1/*-
2 * Copyright (c) 2010 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
29ELFTC_VCSID("$Id: dwarf_pro_lineno.c 2973 2013-12-23 06:46:16Z kaiwang27 $");
30
31Dwarf_Unsigned
32dwarf_add_line_entry(Dwarf_P_Debug dbg, Dwarf_Unsigned file,
33    Dwarf_Addr off, Dwarf_Unsigned lineno, Dwarf_Signed column,
34    Dwarf_Bool is_stmt, Dwarf_Bool basic_block, Dwarf_Error *error)
35{
36	Dwarf_LineInfo li;
37	Dwarf_Line ln;
38
39	if (dbg == NULL) {
40		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
41		return (DW_DLV_NOCOUNT);
42	}
43
44	li = dbg->dbgp_lineinfo;
45
46	ln = STAILQ_LAST(&li->li_lnlist, _Dwarf_Line, ln_next);
47
48	if (ln == NULL || ln->ln_addr > off) {
49		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
50		return (DW_DLV_NOCOUNT);
51	}
52
53	if ((ln = calloc(1, sizeof(struct _Dwarf_Line))) == NULL) {
54		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
55		return (DW_DLV_NOCOUNT);
56	}
57	ln->ln_li     = li;
58	ln->ln_addr   = off;
59	ln->ln_symndx = 0;
60	ln->ln_fileno = file;
61	ln->ln_lineno = lineno;
62	ln->ln_column = column;
63	ln->ln_bblock = basic_block != 0;
64	ln->ln_stmt   = is_stmt != 0;
65	ln->ln_endseq = 0;
66	STAILQ_INSERT_TAIL(&li->li_lnlist, ln, ln_next);
67	li->li_lnlen++;
68
69	return (DW_DLV_OK);
70}
71
72Dwarf_Unsigned
73dwarf_lne_set_address(Dwarf_P_Debug dbg, Dwarf_Addr offs, Dwarf_Unsigned symndx,
74    Dwarf_Error *error)
75{
76	Dwarf_LineInfo li;
77	Dwarf_Line ln;
78
79	if (dbg == NULL || symndx == 0) {
80		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
81		return (DW_DLV_NOCOUNT);
82	}
83
84	li = dbg->dbgp_lineinfo;
85
86	if ((ln = calloc(1, sizeof(struct _Dwarf_Line))) == NULL) {
87		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
88		return (DW_DLV_NOCOUNT);
89	}
90	ln->ln_li = li;
91	ln->ln_addr = offs;
92	ln->ln_symndx = symndx;
93	STAILQ_INSERT_TAIL(&li->li_lnlist, ln, ln_next);
94	li->li_lnlen++;
95
96	return (DW_DLV_OK);
97}
98
99Dwarf_Unsigned
100dwarf_lne_end_sequence(Dwarf_P_Debug dbg, Dwarf_Addr addr, Dwarf_Error *error)
101{
102	Dwarf_LineInfo li;
103	Dwarf_Line ln;
104
105	if (dbg == NULL) {
106		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
107		return (DW_DLV_NOCOUNT);
108	}
109
110	li = dbg->dbgp_lineinfo;
111
112	ln = STAILQ_LAST(&li->li_lnlist, _Dwarf_Line, ln_next);
113	if (ln && ln->ln_addr >= addr) {
114		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
115		return (DW_DLV_NOCOUNT);
116	}
117
118	if ((ln = calloc(1, sizeof(struct _Dwarf_Line))) == NULL) {
119		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
120		return (DW_DLV_NOCOUNT);
121	}
122	ln->ln_li = li;
123	ln->ln_addr = addr;
124	ln->ln_endseq = 1;
125	STAILQ_INSERT_TAIL(&li->li_lnlist, ln, ln_next);
126	li->li_lnlen++;
127
128	return (DW_DLV_OK);
129}
130
131Dwarf_Unsigned
132dwarf_add_directory_decl(Dwarf_P_Debug dbg, char *name, Dwarf_Error *error)
133{
134	Dwarf_LineInfo li;
135
136	if (dbg == NULL || name == NULL || strlen(name) == 0) {
137		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
138		return (DW_DLV_NOCOUNT);
139	}
140
141	li = dbg->dbgp_lineinfo;
142
143	li->li_incdirs = realloc(li->li_incdirs, (li->li_inclen + 1) *
144	    sizeof(char *));
145	if (li->li_incdirs == NULL) {
146		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
147		return (DW_DLV_NOCOUNT);
148	}
149	if ((li->li_incdirs[li->li_inclen] = strdup(name)) == NULL) {
150		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
151		return (DW_DLV_NOCOUNT);
152	}
153
154	return (++li->li_inclen);
155}
156
157Dwarf_Unsigned
158dwarf_add_file_decl(Dwarf_P_Debug dbg, char *name, Dwarf_Unsigned dirndx,
159    Dwarf_Unsigned mtime, Dwarf_Unsigned size, Dwarf_Error *error)
160{
161	Dwarf_LineInfo li;
162	Dwarf_LineFile lf;
163
164	if (dbg == NULL || name == NULL || strlen(name) == 0) {
165		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
166		return (DW_DLV_NOCOUNT);
167	}
168
169	li = dbg->dbgp_lineinfo;
170
171	if ((lf = malloc(sizeof(struct _Dwarf_LineFile))) == NULL) {
172		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
173		return (DW_DLE_MEMORY);
174	}
175
176	if ((lf->lf_fname = strdup(name)) == NULL) {
177		free(lf);
178		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
179		return (DW_DLE_MEMORY);
180	}
181	lf->lf_dirndx = dirndx;
182	lf->lf_mtime = mtime;
183	lf->lf_size = size;
184	STAILQ_INSERT_TAIL(&li->li_lflist, lf, lf_next);
185
186	return (++li->li_lflen);
187}
188