1 /*	$NetBSD: dwarf_lineno.c,v 1.4 2022/05/01 17:20:47 jkoshy Exp $	*/
2 
3 /*-
4  * Copyright (c) 2009,2011 Kai Wang
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include "_libdwarf.h"
30 
31 __RCSID("$NetBSD: dwarf_lineno.c,v 1.4 2022/05/01 17:20:47 jkoshy Exp $");
32 ELFTC_VCSID("Id: dwarf_lineno.c 2983 2014-02-09 00:24:31Z kaiwang27");
33 
34 int
dwarf_srclines(Dwarf_Die die,Dwarf_Line ** linebuf,Dwarf_Signed * linecount,Dwarf_Error * error)35 dwarf_srclines(Dwarf_Die die, Dwarf_Line **linebuf, Dwarf_Signed *linecount,
36     Dwarf_Error *error)
37 {
38 	Dwarf_LineInfo li;
39 	Dwarf_Debug dbg;
40 	Dwarf_Line ln;
41 	Dwarf_CU cu;
42 	Dwarf_Attribute at;
43 	int i;
44 
45 	dbg = die != NULL ? die->die_dbg : NULL;
46 
47 	if (die == NULL || linebuf == NULL || linecount == NULL) {
48 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
49 		return (DW_DLV_ERROR);
50 	}
51 
52 	if ((at = _dwarf_attr_find(die, DW_AT_stmt_list)) == NULL) {
53 		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
54 		return (DW_DLV_NO_ENTRY);
55 	}
56 
57 	cu = die->die_cu;
58 	if (cu->cu_lineinfo == NULL) {
59 		if (_dwarf_lineno_init(die, at->u[0].u64, error) !=
60 		    DW_DLE_NONE)
61 			return (DW_DLV_ERROR);
62 	}
63 	if (cu->cu_lineinfo == NULL) {
64 		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
65 		return (DW_DLV_NO_ENTRY);
66 	}
67 
68 	li = cu->cu_lineinfo;
69 	*linecount = (Dwarf_Signed) li->li_lnlen;
70 
71 	if (*linecount == 0) {
72 		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
73 		return (DW_DLV_NO_ENTRY);
74 	}
75 
76 	if (li->li_lnarray != NULL) {
77 		*linebuf = li->li_lnarray;
78 		return (DW_DLV_OK);
79 	}
80 
81 	if ((li->li_lnarray = malloc(*linecount * sizeof(Dwarf_Line))) ==
82 	    NULL) {
83 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
84 		return (DW_DLV_ERROR);
85 	}
86 
87 	for (i = 0, ln = STAILQ_FIRST(&li->li_lnlist);
88 	     i < *linecount && ln != NULL; i++, ln = STAILQ_NEXT(ln, ln_next))
89 		li->li_lnarray[i] = ln;
90 
91 	*linebuf = li->li_lnarray;
92 
93 	return (DW_DLV_OK);
94 }
95 
96 int
dwarf_srcfiles(Dwarf_Die die,char *** srcfiles,Dwarf_Signed * srccount,Dwarf_Error * error)97 dwarf_srcfiles(Dwarf_Die die, char ***srcfiles, Dwarf_Signed *srccount,
98     Dwarf_Error *error)
99 {
100 	Dwarf_LineInfo li;
101 	Dwarf_LineFile lf;
102 	Dwarf_Debug dbg;
103 	Dwarf_CU cu;
104 	Dwarf_Attribute at;
105 	int i;
106 
107 	dbg = die != NULL ? die->die_dbg : NULL;
108 
109 	if (die == NULL || srcfiles == NULL || srccount == NULL) {
110 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
111 		return (DW_DLV_ERROR);
112 	}
113 
114 	if ((at = _dwarf_attr_find(die, DW_AT_stmt_list)) == NULL) {
115 		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
116 		return (DW_DLV_NO_ENTRY);
117 	}
118 
119 	cu = die->die_cu;
120 	if (cu->cu_lineinfo == NULL) {
121 		if (_dwarf_lineno_init(die, at->u[0].u64, error) !=
122 		    DW_DLE_NONE)
123 			return (DW_DLV_ERROR);
124 	}
125 	if (cu->cu_lineinfo == NULL) {
126 		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
127 		return (DW_DLV_NO_ENTRY);
128 	}
129 
130 	li = cu->cu_lineinfo;
131 	*srccount = (Dwarf_Signed) li->li_lflen;
132 
133 	if (*srccount == 0) {
134 		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
135 		return (DW_DLV_NO_ENTRY);
136 	}
137 
138 	if (li->li_lfnarray != NULL) {
139 		*srcfiles = li->li_lfnarray;
140 		return (DW_DLV_OK);
141 	}
142 
143 	if ((li->li_lfnarray = malloc(*srccount * sizeof(char *))) == NULL) {
144 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
145 		return (DW_DLV_ERROR);
146 	}
147 
148 	for (i = 0, lf = STAILQ_FIRST(&li->li_lflist);
149 	     i < *srccount && lf != NULL; i++, lf = STAILQ_NEXT(lf, lf_next)) {
150 		if (lf->lf_fullpath)
151 			li->li_lfnarray[i] = lf->lf_fullpath;
152 		else
153 			li->li_lfnarray[i] = lf->lf_fname;
154 	}
155 
156 	*srcfiles = li->li_lfnarray;
157 
158 	return (DW_DLV_OK);
159 }
160 
161 int
dwarf_linebeginstatement(Dwarf_Line ln,Dwarf_Bool * ret_bool,Dwarf_Error * error)162 dwarf_linebeginstatement(Dwarf_Line ln, Dwarf_Bool *ret_bool,
163     Dwarf_Error *error)
164 {
165 
166 	if (ln == NULL || ret_bool == NULL) {
167 		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
168 		return (DW_DLV_ERROR);
169 	}
170 
171 	*ret_bool = ln->ln_stmt;
172 
173 	return (DW_DLV_OK);
174 }
175 
176 int
dwarf_lineendsequence(Dwarf_Line ln,Dwarf_Bool * ret_bool,Dwarf_Error * error)177 dwarf_lineendsequence(Dwarf_Line ln, Dwarf_Bool *ret_bool, Dwarf_Error *error)
178 {
179 
180 	if (ln == NULL || ret_bool == NULL) {
181 		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
182 		return (DW_DLV_ERROR);
183 	}
184 
185 	*ret_bool = ln->ln_endseq;
186 
187 	return (DW_DLV_OK);
188 }
189 
190 int
dwarf_lineno(Dwarf_Line ln,Dwarf_Unsigned * ret_lineno,Dwarf_Error * error)191 dwarf_lineno(Dwarf_Line ln, Dwarf_Unsigned *ret_lineno, Dwarf_Error *error)
192 {
193 
194 	if (ln == NULL || ret_lineno == NULL) {
195 		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
196 		return (DW_DLV_ERROR);
197 	}
198 
199 	*ret_lineno = ln->ln_lineno;
200 
201 	return (DW_DLV_OK);
202 }
203 
204 int
dwarf_line_srcfileno(Dwarf_Line ln,Dwarf_Unsigned * ret_fileno,Dwarf_Error * error)205 dwarf_line_srcfileno(Dwarf_Line ln, Dwarf_Unsigned *ret_fileno,
206     Dwarf_Error *error)
207 {
208 
209 	if (ln == NULL || ret_fileno == NULL) {
210 		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
211 		return (DW_DLV_ERROR);
212 	}
213 
214 	*ret_fileno = ln->ln_fileno;
215 
216 	return (DW_DLV_OK);
217 }
218 
219 int
dwarf_lineaddr(Dwarf_Line ln,Dwarf_Addr * ret_lineaddr,Dwarf_Error * error)220 dwarf_lineaddr(Dwarf_Line ln, Dwarf_Addr *ret_lineaddr, Dwarf_Error *error)
221 {
222 
223 	if (ln == NULL || ret_lineaddr == NULL) {
224 		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
225 		return (DW_DLV_ERROR);
226 	}
227 
228 	*ret_lineaddr = ln->ln_addr;
229 
230 	return (DW_DLV_OK);
231 }
232 
233 int
dwarf_lineoff(Dwarf_Line ln,Dwarf_Signed * ret_lineoff,Dwarf_Error * error)234 dwarf_lineoff(Dwarf_Line ln, Dwarf_Signed *ret_lineoff, Dwarf_Error *error)
235 {
236 
237 	if (ln == NULL || ret_lineoff == NULL) {
238 		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
239 		return (DW_DLV_ERROR);
240 	}
241 
242 	if (ln->ln_column == 0)
243 		*ret_lineoff = -1;
244 	else
245 		*ret_lineoff = (Dwarf_Signed) ln->ln_column;
246 
247 	return (DW_DLV_OK);
248 }
249 
250 int
dwarf_linesrc(Dwarf_Line ln,char ** ret_linesrc,Dwarf_Error * error)251 dwarf_linesrc(Dwarf_Line ln, char **ret_linesrc, Dwarf_Error *error)
252 {
253 	Dwarf_LineInfo li;
254 	Dwarf_LineFile lf;
255 	int i;
256 
257 	if (ln == NULL || ret_linesrc == NULL) {
258 		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
259 		return (DW_DLV_ERROR);
260 	}
261 
262 	li = ln->ln_li;
263 	assert(li != NULL);
264 
265 	for (i = 1, lf = STAILQ_FIRST(&li->li_lflist);
266 	     (Dwarf_Unsigned) i < ln->ln_fileno && lf != NULL;
267 	     i++, lf = STAILQ_NEXT(lf, lf_next))
268 		;
269 
270 	if (lf == NULL) {
271 		DWARF_SET_ERROR(NULL, error, DW_DLE_LINE_FILE_NUM_BAD);
272 		return (DW_DLV_ERROR);
273 	}
274 
275 	if (lf->lf_fullpath) {
276 		*ret_linesrc = (char *) lf->lf_fullpath;
277 		return (DW_DLV_OK);
278 	}
279 
280 	*ret_linesrc = lf->lf_fname;
281 
282 	return (DW_DLV_OK);
283 }
284 
285 int
dwarf_lineblock(Dwarf_Line ln,Dwarf_Bool * ret_bool,Dwarf_Error * error)286 dwarf_lineblock(Dwarf_Line ln, Dwarf_Bool *ret_bool, Dwarf_Error *error)
287 {
288 
289 	if (ln == NULL || ret_bool == NULL) {
290 		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
291 		return (DW_DLV_ERROR);
292 	}
293 
294 	*ret_bool = ln->ln_bblock;
295 
296 	return (DW_DLV_OK);
297 }
298