libdwarf_macinfo.c revision 1.1.1.2 1 /* $NetBSD: libdwarf_macinfo.c,v 1.1.1.2 2016/02/20 02:42:00 christos Exp $ */
2 /*-
3 * Copyright (c) 2009-2011 Kai Wang
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include "_libdwarf.h"
29
30 __RCSID("$NetBSD: libdwarf_macinfo.c,v 1.1.1.2 2016/02/20 02:42:00 christos Exp $");
31 ELFTC_VCSID("Id: libdwarf_macinfo.c 2974 2013-12-23 06:46:22Z kaiwang27 ");
32
33 #define _FILEINDEX_STACK_SIZE 16384
34
35 static int
36 _dwarf_macinfo_parse(Dwarf_Debug dbg, Dwarf_Section *ds, uint64_t *off,
37 Dwarf_Macro_Details *dmd, Dwarf_Unsigned *cnt, Dwarf_Error *error)
38 {
39 Dwarf_Unsigned lineno;
40 Dwarf_Signed fileindex[_FILEINDEX_STACK_SIZE];
41 char *p;
42 int i, type, sp;
43
44 i = 0;
45 sp = 0;
46 fileindex[sp] = -1;
47 while (*off < ds->ds_size) {
48
49 if (dmd != NULL)
50 dmd[i].dmd_offset = *off;
51
52 type = dbg->read(ds->ds_data, off, 1);
53
54 if (dmd != NULL) {
55 dmd[i].dmd_type = type;
56 dmd[i].dmd_fileindex = fileindex[sp];
57 }
58
59 switch (type) {
60 case 0:
61 break;
62 case DW_MACINFO_define:
63 case DW_MACINFO_undef:
64 case DW_MACINFO_vendor_ext:
65 lineno = _dwarf_read_uleb128(ds->ds_data, off);
66 p = (char *) ds->ds_data;
67 if (dmd != NULL) {
68 dmd[i].dmd_lineno = lineno;
69 dmd[i].dmd_macro = p + *off;
70
71 }
72 while (p[(*off)++] != '\0')
73 ;
74 break;
75 case DW_MACINFO_start_file:
76 lineno = _dwarf_read_uleb128(ds->ds_data, off);
77 if (sp >= _FILEINDEX_STACK_SIZE - 1) {
78 assert(0);
79 }
80 fileindex[++sp] = _dwarf_read_uleb128(ds->ds_data, off);
81 if (dmd != NULL) {
82 dmd[i].dmd_lineno = lineno;
83 dmd[i].dmd_fileindex = fileindex[sp];
84 }
85 break;
86 case DW_MACINFO_end_file:
87 if (sp > 0) {
88 sp--;
89 break;
90 }
91 /* FALLTHROUGH */
92 default:
93 DWARF_SET_ERROR(dbg, error,
94 DW_DLE_DEBUG_MACRO_INCONSISTENT);
95 return (DW_DLE_DEBUG_MACRO_INCONSISTENT);
96 }
97
98 i++;
99
100 if (type == 0)
101 break;
102 }
103
104 if (cnt != NULL)
105 *cnt = i;
106
107 return (DW_DLE_NONE);
108 }
109
110 void
111 _dwarf_macinfo_cleanup(Dwarf_Debug dbg)
112 {
113 Dwarf_MacroSet ms, tms;
114
115 if (STAILQ_EMPTY(&dbg->dbg_mslist))
116 return;
117
118 STAILQ_FOREACH_SAFE(ms, &dbg->dbg_mslist, ms_next, tms) {
119 STAILQ_REMOVE(&dbg->dbg_mslist, ms, _Dwarf_MacroSet, ms_next);
120 if (ms->ms_mdlist)
121 free(ms->ms_mdlist);
122 free(ms);
123 }
124 }
125
126 int
127 _dwarf_macinfo_init(Dwarf_Debug dbg, Dwarf_Error *error)
128 {
129 Dwarf_MacroSet ms;
130 Dwarf_Unsigned cnt;
131 Dwarf_Section *ds;
132 uint64_t offset, entry_off;
133 int ret;
134
135 if ((ds = _dwarf_find_section(dbg, ".debug_macinfo")) == NULL)
136 return (DW_DLE_NONE);
137
138 offset = 0;
139 while (offset < ds->ds_size) {
140
141 entry_off = offset;
142
143 ret = _dwarf_macinfo_parse(dbg, ds, &offset, NULL, &cnt, error);
144 if (ret != DW_DLE_NONE)
145 return (ret);
146
147 if (cnt == 0)
148 break;
149
150 if ((ms = calloc(1, sizeof(struct _Dwarf_MacroSet))) == NULL) {
151 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
152 ret = DW_DLE_MEMORY;
153 goto fail_cleanup;
154 }
155 STAILQ_INSERT_TAIL(&dbg->dbg_mslist, ms, ms_next);
156
157 if ((ms->ms_mdlist = calloc(cnt, sizeof(Dwarf_Macro_Details)))
158 == NULL) {
159 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
160 ret = DW_DLE_MEMORY;
161 goto fail_cleanup;
162 }
163
164 ms->ms_cnt = cnt;
165
166 offset = entry_off;
167
168 ret = _dwarf_macinfo_parse(dbg, ds, &offset, ms->ms_mdlist,
169 NULL, error);
170
171 if (ret != DW_DLE_NONE) {
172 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
173 ret = DW_DLE_MEMORY;
174 goto fail_cleanup;
175 }
176 }
177
178 return (DW_DLE_NONE);
179
180 fail_cleanup:
181
182 _dwarf_macinfo_cleanup(dbg);
183
184 return (ret);
185 }
186
187 int
188 _dwarf_macinfo_gen(Dwarf_P_Debug dbg, Dwarf_Error *error)
189 {
190 Dwarf_P_Section ds;
191 Dwarf_Macro_Details *md;
192 int i, ret;
193
194 if (dbg->dbgp_mdcnt == 0)
195 return (DW_DLE_NONE);
196
197 /* Create .debug_frame section. */
198 RCHECK(_dwarf_section_init(dbg, &ds, ".debug_macinfo", 0, error));
199
200 /* Write the list of Dwarf_Macro_Details. */
201 for (i = 0; (Dwarf_Unsigned) i < dbg->dbgp_mdcnt; i++) {
202 md = &dbg->dbgp_mdlist[i];
203 md->dmd_offset = ds->ds_size;
204 RCHECK(WRITE_VALUE(md->dmd_type, 1));
205 switch (md->dmd_type) {
206 case DW_MACINFO_define:
207 case DW_MACINFO_undef:
208 case DW_MACINFO_vendor_ext:
209 RCHECK(WRITE_ULEB128(md->dmd_lineno));
210 assert(md->dmd_macro != NULL);
211 RCHECK(WRITE_STRING(md->dmd_macro));
212 break;
213 case DW_MACINFO_start_file:
214 RCHECK(WRITE_ULEB128(md->dmd_lineno));
215 RCHECK(WRITE_ULEB128(md->dmd_fileindex));
216 break;
217 case DW_MACINFO_end_file:
218 break;
219 default:
220 assert(0);
221 break;
222 }
223 }
224 RCHECK(WRITE_VALUE(0, 1));
225
226 /* Inform application the creation of .debug_macinfo ELF section. */
227 RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error));
228
229 return (DW_DLE_NONE);
230
231 gen_fail:
232 _dwarf_section_free(dbg, &ds);
233
234 return (ret);
235 }
236
237 void
238 _dwarf_macinfo_pro_cleanup(Dwarf_P_Debug dbg)
239 {
240 Dwarf_Macro_Details *md;
241 int i;
242
243 assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
244 if (dbg->dbgp_mdlist == NULL)
245 return;
246
247 assert(dbg->dbgp_mdcnt > 0);
248 for (i = 0; (Dwarf_Unsigned) i < dbg->dbgp_mdcnt; i++) {
249 md = &dbg->dbgp_mdlist[i];
250 if (md->dmd_macro)
251 free(md->dmd_macro);
252 }
253 free(dbg->dbgp_mdlist);
254 dbg->dbgp_mdlist = NULL;
255 dbg->dbgp_mdcnt = 0;
256 }
257