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