Deleted Added
full compact
libdwarf_abbrev.c (276398) libdwarf_abbrev.c (300311)
1/*-
2 * Copyright (c) 2007 John Birrell (jb@freebsd.org)
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
1/*-
2 * Copyright (c) 2007 John Birrell (jb@freebsd.org)
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
30ELFTC_VCSID("$Id: libdwarf_abbrev.c 3136 2014-12-24 16:04:38Z kaiwang27 $");
30ELFTC_VCSID("$Id: libdwarf_abbrev.c 3420 2016-02-27 02:14:05Z emaste $");
31
32int
33_dwarf_abbrev_add(Dwarf_CU cu, uint64_t entry, uint64_t tag, uint8_t children,
34 uint64_t aboff, Dwarf_Abbrev *abp, Dwarf_Error *error)
35{
36 Dwarf_Abbrev ab;
37 Dwarf_Debug dbg;
38
39 dbg = cu != NULL ? cu->cu_dbg : NULL;
40
41 if ((ab = malloc(sizeof(struct _Dwarf_Abbrev))) == NULL) {
42 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
43 return (DW_DLE_MEMORY);
44 }
45
46 /* Initialise the abbrev structure. */
47 ab->ab_entry = entry;
48 ab->ab_tag = tag;
49 ab->ab_children = children;
50 ab->ab_offset = aboff;
51 ab->ab_length = 0; /* fill in later. */
52 ab->ab_atnum = 0; /* fill in later. */
53
54 /* Initialise the list of attribute definitions. */
55 STAILQ_INIT(&ab->ab_attrdef);
56
57 /* Add the abbrev to the hash table of the compilation unit. */
58 if (cu != NULL)
59 HASH_ADD(ab_hh, cu->cu_abbrev_hash, ab_entry,
60 sizeof(ab->ab_entry), ab);
61
62 if (abp != NULL)
63 *abp = ab;
64
65 return (DW_DLE_NONE);
66}
67
68int
69_dwarf_attrdef_add(Dwarf_Debug dbg, Dwarf_Abbrev ab, uint64_t attr,
70 uint64_t form, uint64_t adoff, Dwarf_AttrDef *adp, Dwarf_Error *error)
71{
72 Dwarf_AttrDef ad;
73
74 if (ab == NULL) {
75 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
76 return (DW_DLE_ARGUMENT);
77 }
78
79 if ((ad = malloc(sizeof(struct _Dwarf_AttrDef))) == NULL) {
80 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
81 return (DW_DLE_MEMORY);
82 }
83
84 /* Initialise the attribute definition structure. */
85 ad->ad_attrib = attr;
86 ad->ad_form = form;
87 ad->ad_offset = adoff;
88
89 /* Add the attribute definition to the list in the abbrev. */
90 STAILQ_INSERT_TAIL(&ab->ab_attrdef, ad, ad_next);
91
92 /* Increase number of attribute counter. */
93 ab->ab_atnum++;
94
95 if (adp != NULL)
96 *adp = ad;
97
98 return (DW_DLE_NONE);
99}
100
101int
102_dwarf_abbrev_parse(Dwarf_Debug dbg, Dwarf_CU cu, Dwarf_Unsigned *offset,
103 Dwarf_Abbrev *abp, Dwarf_Error *error)
104{
105 Dwarf_Section *ds;
106 uint64_t attr;
107 uint64_t entry;
108 uint64_t form;
109 uint64_t aboff;
110 uint64_t adoff;
111 uint64_t tag;
112 uint8_t children;
113 int ret;
114
115 assert(abp != NULL);
116
117 ds = _dwarf_find_section(dbg, ".debug_abbrev");
31
32int
33_dwarf_abbrev_add(Dwarf_CU cu, uint64_t entry, uint64_t tag, uint8_t children,
34 uint64_t aboff, Dwarf_Abbrev *abp, Dwarf_Error *error)
35{
36 Dwarf_Abbrev ab;
37 Dwarf_Debug dbg;
38
39 dbg = cu != NULL ? cu->cu_dbg : NULL;
40
41 if ((ab = malloc(sizeof(struct _Dwarf_Abbrev))) == NULL) {
42 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
43 return (DW_DLE_MEMORY);
44 }
45
46 /* Initialise the abbrev structure. */
47 ab->ab_entry = entry;
48 ab->ab_tag = tag;
49 ab->ab_children = children;
50 ab->ab_offset = aboff;
51 ab->ab_length = 0; /* fill in later. */
52 ab->ab_atnum = 0; /* fill in later. */
53
54 /* Initialise the list of attribute definitions. */
55 STAILQ_INIT(&ab->ab_attrdef);
56
57 /* Add the abbrev to the hash table of the compilation unit. */
58 if (cu != NULL)
59 HASH_ADD(ab_hh, cu->cu_abbrev_hash, ab_entry,
60 sizeof(ab->ab_entry), ab);
61
62 if (abp != NULL)
63 *abp = ab;
64
65 return (DW_DLE_NONE);
66}
67
68int
69_dwarf_attrdef_add(Dwarf_Debug dbg, Dwarf_Abbrev ab, uint64_t attr,
70 uint64_t form, uint64_t adoff, Dwarf_AttrDef *adp, Dwarf_Error *error)
71{
72 Dwarf_AttrDef ad;
73
74 if (ab == NULL) {
75 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
76 return (DW_DLE_ARGUMENT);
77 }
78
79 if ((ad = malloc(sizeof(struct _Dwarf_AttrDef))) == NULL) {
80 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
81 return (DW_DLE_MEMORY);
82 }
83
84 /* Initialise the attribute definition structure. */
85 ad->ad_attrib = attr;
86 ad->ad_form = form;
87 ad->ad_offset = adoff;
88
89 /* Add the attribute definition to the list in the abbrev. */
90 STAILQ_INSERT_TAIL(&ab->ab_attrdef, ad, ad_next);
91
92 /* Increase number of attribute counter. */
93 ab->ab_atnum++;
94
95 if (adp != NULL)
96 *adp = ad;
97
98 return (DW_DLE_NONE);
99}
100
101int
102_dwarf_abbrev_parse(Dwarf_Debug dbg, Dwarf_CU cu, Dwarf_Unsigned *offset,
103 Dwarf_Abbrev *abp, Dwarf_Error *error)
104{
105 Dwarf_Section *ds;
106 uint64_t attr;
107 uint64_t entry;
108 uint64_t form;
109 uint64_t aboff;
110 uint64_t adoff;
111 uint64_t tag;
112 uint8_t children;
113 int ret;
114
115 assert(abp != NULL);
116
117 ds = _dwarf_find_section(dbg, ".debug_abbrev");
118 assert(ds != NULL);
119
120 if (*offset >= ds->ds_size)
118 if (ds == NULL || *offset >= ds->ds_size)
121 return (DW_DLE_NO_ENTRY);
122
123 aboff = *offset;
124
125 entry = _dwarf_read_uleb128(ds->ds_data, offset);
126 if (entry == 0) {
127 /* Last entry. */
128 ret = _dwarf_abbrev_add(cu, entry, 0, 0, aboff, abp,
129 error);
130 if (ret == DW_DLE_NONE) {
131 (*abp)->ab_length = 1;
132 return (ret);
133 } else
134 return (ret);
135 }
136 tag = _dwarf_read_uleb128(ds->ds_data, offset);
137 children = dbg->read(ds->ds_data, offset, 1);
138 if ((ret = _dwarf_abbrev_add(cu, entry, tag, children, aboff,
139 abp, error)) != DW_DLE_NONE)
140 return (ret);
141
142 /* Parse attribute definitions. */
143 do {
144 adoff = *offset;
145 attr = _dwarf_read_uleb128(ds->ds_data, offset);
146 form = _dwarf_read_uleb128(ds->ds_data, offset);
147 if (attr != 0)
148 if ((ret = _dwarf_attrdef_add(dbg, *abp, attr,
149 form, adoff, NULL, error)) != DW_DLE_NONE)
150 return (ret);
151 } while (attr != 0);
152
153 (*abp)->ab_length = *offset - aboff;
154
155 return (ret);
156}
157
158int
159_dwarf_abbrev_find(Dwarf_CU cu, uint64_t entry, Dwarf_Abbrev *abp,
160 Dwarf_Error *error)
161{
162 Dwarf_Abbrev ab;
163 Dwarf_Section *ds;
164 Dwarf_Unsigned offset;
165 int ret;
166
167 if (entry == 0)
168 return (DW_DLE_NO_ENTRY);
169
170 /* Check if the desired abbrev entry is already in the hash table. */
171 HASH_FIND(ab_hh, cu->cu_abbrev_hash, &entry, sizeof(entry), ab);
172 if (ab != NULL) {
173 *abp = ab;
174 return (DW_DLE_NONE);
175 }
176
177 if (cu->cu_abbrev_loaded) {
178 return (DW_DLE_NO_ENTRY);
179 }
180
181 /* Load and search the abbrev table. */
182 ds = _dwarf_find_section(cu->cu_dbg, ".debug_abbrev");
183 if (ds == NULL)
184 return (DW_DLE_NO_ENTRY);
185
186 offset = cu->cu_abbrev_offset_cur;
187 while (offset < ds->ds_size) {
188 ret = _dwarf_abbrev_parse(cu->cu_dbg, cu, &offset, &ab, error);
189 if (ret != DW_DLE_NONE)
190 return (ret);
191 if (ab->ab_entry == entry) {
192 cu->cu_abbrev_offset_cur = offset;
193 *abp = ab;
194 return (DW_DLE_NONE);
195 }
196 if (ab->ab_entry == 0) {
197 cu->cu_abbrev_offset_cur = offset;
198 cu->cu_abbrev_loaded = 1;
199 break;
200 }
201 }
202
203 return (DW_DLE_NO_ENTRY);
204}
205
206void
207_dwarf_abbrev_cleanup(Dwarf_CU cu)
208{
209 Dwarf_Abbrev ab, tab;
210 Dwarf_AttrDef ad, tad;
211
212 assert(cu != NULL);
213
214 HASH_ITER(ab_hh, cu->cu_abbrev_hash, ab, tab) {
215 HASH_DELETE(ab_hh, cu->cu_abbrev_hash, ab);
216 STAILQ_FOREACH_SAFE(ad, &ab->ab_attrdef, ad_next, tad) {
217 STAILQ_REMOVE(&ab->ab_attrdef, ad, _Dwarf_AttrDef,
218 ad_next);
219 free(ad);
220 }
221 free(ab);
222 }
223}
224
225int
226_dwarf_abbrev_gen(Dwarf_P_Debug dbg, Dwarf_Error *error)
227{
228 Dwarf_CU cu;
229 Dwarf_Abbrev ab;
230 Dwarf_AttrDef ad;
231 Dwarf_P_Section ds;
232 int ret;
233
234 cu = STAILQ_FIRST(&dbg->dbg_cu);
235 if (cu == NULL)
236 return (DW_DLE_NONE);
237
238 /* Create .debug_abbrev section. */
239 if ((ret = _dwarf_section_init(dbg, &ds, ".debug_abbrev", 0, error)) !=
240 DW_DLE_NONE)
241 return (ret);
242
243 for (ab = cu->cu_abbrev_hash; ab != NULL; ab = ab->ab_hh.next) {
244 RCHECK(WRITE_ULEB128(ab->ab_entry));
245 RCHECK(WRITE_ULEB128(ab->ab_tag));
246 RCHECK(WRITE_VALUE(ab->ab_children, 1));
247 STAILQ_FOREACH(ad, &ab->ab_attrdef, ad_next) {
248 RCHECK(WRITE_ULEB128(ad->ad_attrib));
249 RCHECK(WRITE_ULEB128(ad->ad_form));
250 }
251 /* Signal end of attribute spec list. */
252 RCHECK(WRITE_ULEB128(0));
253 RCHECK(WRITE_ULEB128(0));
254 }
255 /* End of abbreviation for this CU. */
256 RCHECK(WRITE_ULEB128(0));
257
258 /* Notify the creation of .debug_abbrev ELF section. */
259 RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error));
260
261 return (DW_DLE_NONE);
262
263gen_fail:
264
265 _dwarf_section_free(dbg, &ds);
266
267 return (ret);
268}
119 return (DW_DLE_NO_ENTRY);
120
121 aboff = *offset;
122
123 entry = _dwarf_read_uleb128(ds->ds_data, offset);
124 if (entry == 0) {
125 /* Last entry. */
126 ret = _dwarf_abbrev_add(cu, entry, 0, 0, aboff, abp,
127 error);
128 if (ret == DW_DLE_NONE) {
129 (*abp)->ab_length = 1;
130 return (ret);
131 } else
132 return (ret);
133 }
134 tag = _dwarf_read_uleb128(ds->ds_data, offset);
135 children = dbg->read(ds->ds_data, offset, 1);
136 if ((ret = _dwarf_abbrev_add(cu, entry, tag, children, aboff,
137 abp, error)) != DW_DLE_NONE)
138 return (ret);
139
140 /* Parse attribute definitions. */
141 do {
142 adoff = *offset;
143 attr = _dwarf_read_uleb128(ds->ds_data, offset);
144 form = _dwarf_read_uleb128(ds->ds_data, offset);
145 if (attr != 0)
146 if ((ret = _dwarf_attrdef_add(dbg, *abp, attr,
147 form, adoff, NULL, error)) != DW_DLE_NONE)
148 return (ret);
149 } while (attr != 0);
150
151 (*abp)->ab_length = *offset - aboff;
152
153 return (ret);
154}
155
156int
157_dwarf_abbrev_find(Dwarf_CU cu, uint64_t entry, Dwarf_Abbrev *abp,
158 Dwarf_Error *error)
159{
160 Dwarf_Abbrev ab;
161 Dwarf_Section *ds;
162 Dwarf_Unsigned offset;
163 int ret;
164
165 if (entry == 0)
166 return (DW_DLE_NO_ENTRY);
167
168 /* Check if the desired abbrev entry is already in the hash table. */
169 HASH_FIND(ab_hh, cu->cu_abbrev_hash, &entry, sizeof(entry), ab);
170 if (ab != NULL) {
171 *abp = ab;
172 return (DW_DLE_NONE);
173 }
174
175 if (cu->cu_abbrev_loaded) {
176 return (DW_DLE_NO_ENTRY);
177 }
178
179 /* Load and search the abbrev table. */
180 ds = _dwarf_find_section(cu->cu_dbg, ".debug_abbrev");
181 if (ds == NULL)
182 return (DW_DLE_NO_ENTRY);
183
184 offset = cu->cu_abbrev_offset_cur;
185 while (offset < ds->ds_size) {
186 ret = _dwarf_abbrev_parse(cu->cu_dbg, cu, &offset, &ab, error);
187 if (ret != DW_DLE_NONE)
188 return (ret);
189 if (ab->ab_entry == entry) {
190 cu->cu_abbrev_offset_cur = offset;
191 *abp = ab;
192 return (DW_DLE_NONE);
193 }
194 if (ab->ab_entry == 0) {
195 cu->cu_abbrev_offset_cur = offset;
196 cu->cu_abbrev_loaded = 1;
197 break;
198 }
199 }
200
201 return (DW_DLE_NO_ENTRY);
202}
203
204void
205_dwarf_abbrev_cleanup(Dwarf_CU cu)
206{
207 Dwarf_Abbrev ab, tab;
208 Dwarf_AttrDef ad, tad;
209
210 assert(cu != NULL);
211
212 HASH_ITER(ab_hh, cu->cu_abbrev_hash, ab, tab) {
213 HASH_DELETE(ab_hh, cu->cu_abbrev_hash, ab);
214 STAILQ_FOREACH_SAFE(ad, &ab->ab_attrdef, ad_next, tad) {
215 STAILQ_REMOVE(&ab->ab_attrdef, ad, _Dwarf_AttrDef,
216 ad_next);
217 free(ad);
218 }
219 free(ab);
220 }
221}
222
223int
224_dwarf_abbrev_gen(Dwarf_P_Debug dbg, Dwarf_Error *error)
225{
226 Dwarf_CU cu;
227 Dwarf_Abbrev ab;
228 Dwarf_AttrDef ad;
229 Dwarf_P_Section ds;
230 int ret;
231
232 cu = STAILQ_FIRST(&dbg->dbg_cu);
233 if (cu == NULL)
234 return (DW_DLE_NONE);
235
236 /* Create .debug_abbrev section. */
237 if ((ret = _dwarf_section_init(dbg, &ds, ".debug_abbrev", 0, error)) !=
238 DW_DLE_NONE)
239 return (ret);
240
241 for (ab = cu->cu_abbrev_hash; ab != NULL; ab = ab->ab_hh.next) {
242 RCHECK(WRITE_ULEB128(ab->ab_entry));
243 RCHECK(WRITE_ULEB128(ab->ab_tag));
244 RCHECK(WRITE_VALUE(ab->ab_children, 1));
245 STAILQ_FOREACH(ad, &ab->ab_attrdef, ad_next) {
246 RCHECK(WRITE_ULEB128(ad->ad_attrib));
247 RCHECK(WRITE_ULEB128(ad->ad_form));
248 }
249 /* Signal end of attribute spec list. */
250 RCHECK(WRITE_ULEB128(0));
251 RCHECK(WRITE_ULEB128(0));
252 }
253 /* End of abbreviation for this CU. */
254 RCHECK(WRITE_ULEB128(0));
255
256 /* Notify the creation of .debug_abbrev ELF section. */
257 RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error));
258
259 return (DW_DLE_NONE);
260
261gen_fail:
262
263 _dwarf_section_free(dbg, &ds);
264
265 return (ret);
266}