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