]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/elftoolchain/libdwarf/libdwarf_attr.c
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r304460, and update
[FreeBSD/FreeBSD.git] / contrib / elftoolchain / libdwarf / libdwarf_attr.c
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
30 ELFTC_VCSID("$Id: libdwarf_attr.c 3064 2014-06-06 19:35:55Z kaiwang27 $");
31
32 int
33 _dwarf_attr_alloc(Dwarf_Die die, Dwarf_Attribute *atp, Dwarf_Error *error)
34 {
35         Dwarf_Attribute at;
36
37         assert(die != NULL);
38         assert(atp != NULL);
39
40         if ((at = calloc(1, sizeof(struct _Dwarf_Attribute))) == NULL) {
41                 DWARF_SET_ERROR(die->die_dbg, error, DW_DLE_MEMORY);
42                 return (DW_DLE_MEMORY);
43         }
44
45         *atp = at;
46
47         return (DW_DLE_NONE);
48 }
49
50 static int
51 _dwarf_attr_add(Dwarf_Die die, Dwarf_Attribute atref, Dwarf_Attribute *atp,
52     Dwarf_Error *error)
53 {
54         Dwarf_Attribute at;
55         int ret;
56
57         if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
58                 return (ret);
59
60         memcpy(at, atref, sizeof(struct _Dwarf_Attribute));
61
62         STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
63
64         /* Save a pointer to the attribute name if this is one. */
65         if (at->at_attrib == DW_AT_name) {
66                 switch (at->at_form) {
67                 case DW_FORM_strp:
68                         die->die_name = at->u[1].s;
69                         break;
70                 case DW_FORM_string:
71                         die->die_name = at->u[0].s;
72                         break;
73                 default:
74                         break;
75                 }
76         }
77
78         if (atp != NULL)
79                 *atp = at;
80
81         return (DW_DLE_NONE);
82 }
83
84 Dwarf_Attribute
85 _dwarf_attr_find(Dwarf_Die die, Dwarf_Half attr)
86 {
87         Dwarf_Attribute at;
88
89         STAILQ_FOREACH(at, &die->die_attr, at_next) {
90                 if (at->at_attrib == attr)
91                         break;
92         }
93
94         return (at);
95 }
96
97 int
98 _dwarf_attr_init(Dwarf_Debug dbg, Dwarf_Section *ds, uint64_t *offsetp,
99     int dwarf_size, Dwarf_CU cu, Dwarf_Die die, Dwarf_AttrDef ad,
100     uint64_t form, int indirect, Dwarf_Error *error)
101 {
102         struct _Dwarf_Attribute atref;
103         Dwarf_Section *str;
104         int ret;
105
106         ret = DW_DLE_NONE;
107         memset(&atref, 0, sizeof(atref));
108         atref.at_die = die;
109         atref.at_offset = *offsetp;
110         atref.at_attrib = ad->ad_attrib;
111         atref.at_form = indirect ? form : ad->ad_form;
112         atref.at_indirect = indirect;
113         atref.at_ld = NULL;
114
115         switch (form) {
116         case DW_FORM_addr:
117                 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp,
118                     cu->cu_pointer_size);
119                 break;
120         case DW_FORM_block:
121         case DW_FORM_exprloc:
122                 atref.u[0].u64 = _dwarf_read_uleb128(ds->ds_data, offsetp);
123                 atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
124                     atref.u[0].u64);
125                 break;
126         case DW_FORM_block1:
127                 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 1);
128                 atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
129                     atref.u[0].u64);
130                 break;
131         case DW_FORM_block2:
132                 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 2);
133                 atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
134                     atref.u[0].u64);
135                 break;
136         case DW_FORM_block4:
137                 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 4);
138                 atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
139                     atref.u[0].u64);
140                 break;
141         case DW_FORM_data1:
142         case DW_FORM_flag:
143         case DW_FORM_ref1:
144                 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 1);
145                 break;
146         case DW_FORM_data2:
147         case DW_FORM_ref2:
148                 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 2);
149                 break;
150         case DW_FORM_data4:
151         case DW_FORM_ref4:
152                 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 4);
153                 break;
154         case DW_FORM_data8:
155         case DW_FORM_ref8:
156                 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 8);
157                 break;
158         case DW_FORM_indirect:
159                 form = _dwarf_read_uleb128(ds->ds_data, offsetp);
160                 return (_dwarf_attr_init(dbg, ds, offsetp, dwarf_size, cu, die,
161                     ad, form, 1, error));
162         case DW_FORM_ref_addr:
163                 if (cu->cu_version == 2)
164                         atref.u[0].u64 = dbg->read(ds->ds_data, offsetp,
165                             cu->cu_pointer_size);
166                 else
167                         atref.u[0].u64 = dbg->read(ds->ds_data, offsetp,
168                             dwarf_size);
169                 break;
170         case DW_FORM_ref_udata:
171         case DW_FORM_udata:
172                 atref.u[0].u64 = _dwarf_read_uleb128(ds->ds_data, offsetp);
173                 break;
174         case DW_FORM_sdata:
175                 atref.u[0].s64 = _dwarf_read_sleb128(ds->ds_data, offsetp);
176                 break;
177         case DW_FORM_sec_offset:
178                 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size);
179                 break;
180         case DW_FORM_string:
181                 atref.u[0].s = _dwarf_read_string(ds->ds_data, ds->ds_size,
182                     offsetp);
183                 break;
184         case DW_FORM_strp:
185                 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size);
186                 str = _dwarf_find_section(dbg, ".debug_str");
187                 assert(str != NULL);
188                 atref.u[1].s = (char *) str->ds_data + atref.u[0].u64;
189                 break;
190         case DW_FORM_ref_sig8:
191                 atref.u[0].u64 = 8;
192                 atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
193                     atref.u[0].u64);
194                 break;
195         case DW_FORM_flag_present:
196                 /* This form has no value encoded in the DIE. */
197                 atref.u[0].u64 = 1;
198                 break;
199         default:
200                 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
201                 ret = DW_DLE_ATTR_FORM_BAD;
202                 break;
203         }
204
205         if (ret == DW_DLE_NONE) {
206                 if (form == DW_FORM_block || form == DW_FORM_block1 ||
207                     form == DW_FORM_block2 || form == DW_FORM_block4) {
208                         atref.at_block.bl_len = atref.u[0].u64;
209                         atref.at_block.bl_data = atref.u[1].u8p;
210                 }
211                 ret = _dwarf_attr_add(die, &atref, NULL, error);
212         }
213
214         return (ret);
215 }
216
217 static int
218 _dwarf_attr_write(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_Rel_Section drs,
219     Dwarf_CU cu, Dwarf_Attribute at, int pass2, Dwarf_Error *error)
220 {
221         struct _Dwarf_P_Expr_Entry *ee;
222         uint64_t value, offset, bs;
223         int ret;
224
225         assert(dbg != NULL && ds != NULL && cu != NULL && at != NULL);
226
227         /* Fill in reference to other DIE in the second pass. */
228         if (pass2) {
229                 if (at->at_form != DW_FORM_ref4 && at->at_form != DW_FORM_ref8)
230                         return (DW_DLE_NONE);
231                 if (at->at_refdie == NULL || at->at_offset == 0)
232                         return (DW_DLE_NONE);
233                 offset = at->at_offset;
234                 dbg->write(ds->ds_data, &offset, at->at_refdie->die_offset,
235                     at->at_form == DW_FORM_ref4 ? 4 : 8);
236                 return (DW_DLE_NONE);
237         }
238
239         switch (at->at_form) {
240         case DW_FORM_addr:
241                 if (at->at_relsym)
242                         ret = _dwarf_reloc_entry_add(dbg, drs, ds,
243                             dwarf_drt_data_reloc, cu->cu_pointer_size,
244                             ds->ds_size, at->at_relsym, at->u[0].u64, NULL,
245                             error);
246                 else
247                         ret = WRITE_VALUE(at->u[0].u64, cu->cu_pointer_size);
248                 break;
249         case DW_FORM_block:
250         case DW_FORM_block1:
251         case DW_FORM_block2:
252         case DW_FORM_block4:
253                 /* Write block size. */
254                 if (at->at_form == DW_FORM_block) {
255                         ret = _dwarf_write_uleb128_alloc(&ds->ds_data,
256                             &ds->ds_cap, &ds->ds_size, at->u[0].u64, error);
257                         if (ret != DW_DLE_NONE)
258                                 break;
259                 } else {
260                         if (at->at_form == DW_FORM_block1)
261                                 bs = 1;
262                         else if (at->at_form == DW_FORM_block2)
263                                 bs = 2;
264                         else
265                                 bs = 4;
266                         ret = WRITE_VALUE(at->u[0].u64, bs);
267                         if (ret != DW_DLE_NONE)
268                                 break;
269                 }
270
271                 /* Keep block data offset for later use. */
272                 offset = ds->ds_size;
273
274                 /* Write block data. */
275                 ret = WRITE_BLOCK(at->u[1].u8p, at->u[0].u64);
276                 if (ret != DW_DLE_NONE)
277                         break;
278                 if (at->at_expr == NULL)
279                         break;
280
281                 /* Generate relocation entry for DW_OP_addr expressions. */
282                 STAILQ_FOREACH(ee, &at->at_expr->pe_eelist, ee_next) {
283                         if (ee->ee_loc.lr_atom != DW_OP_addr || ee->ee_sym == 0)
284                                 continue;
285                         ret = _dwarf_reloc_entry_add(dbg, drs, ds,
286                             dwarf_drt_data_reloc, dbg->dbg_pointer_size,
287                             offset + ee->ee_loc.lr_offset + 1, ee->ee_sym,
288                             ee->ee_loc.lr_number, NULL, error);
289                         if (ret != DW_DLE_NONE)
290                                 break;
291                 }
292                 break;
293         case DW_FORM_data1:
294         case DW_FORM_flag:
295         case DW_FORM_ref1:
296                 ret = WRITE_VALUE(at->u[0].u64, 1);
297                 break;
298         case DW_FORM_data2:
299         case DW_FORM_ref2:
300                 ret = WRITE_VALUE(at->u[0].u64, 2);
301                 break;
302         case DW_FORM_data4:
303                 if (at->at_relsym || at->at_relsec != NULL)
304                         ret = _dwarf_reloc_entry_add(dbg, drs, ds,
305                             dwarf_drt_data_reloc, 4, ds->ds_size, at->at_relsym,
306                             at->u[0].u64, at->at_relsec, error);
307                 else
308                         ret = WRITE_VALUE(at->u[0].u64, 4);
309                 break;
310         case DW_FORM_data8:
311                 if (at->at_relsym || at->at_relsec != NULL)
312                         ret = _dwarf_reloc_entry_add(dbg, drs, ds,
313                             dwarf_drt_data_reloc, 8, ds->ds_size, at->at_relsym,
314                             at->u[0].u64, at->at_relsec, error);
315                 else
316                         ret = WRITE_VALUE(at->u[0].u64, 8);
317                 break;
318         case DW_FORM_ref4:
319         case DW_FORM_ref8:
320                 /*
321                  * The value of ref4 and ref8 could be a reference to another
322                  * DIE within the CU. And if we don't know the ref DIE's
323                  * offset at the moement, then we remember at_offset and fill
324                  * it in the second pass.
325                  */
326                 if (at->at_refdie) {
327                         value = at->at_refdie->die_offset;
328                         if (value == 0) {
329                                 cu->cu_pass2 = 1;
330                                 at->at_offset = ds->ds_size;
331                         }
332                 } else
333                         value = at->u[0].u64;
334                 ret = WRITE_VALUE(value, at->at_form == DW_FORM_ref4 ? 4 : 8);
335                 break;
336         case DW_FORM_indirect:
337                 /* TODO. */
338                 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
339                 ret = DW_DLE_ATTR_FORM_BAD;
340                 break;
341         case DW_FORM_ref_addr:
342                 /* DWARF2 format. */
343                 if (at->at_relsym)
344                         ret = _dwarf_reloc_entry_add(dbg, drs, ds,
345                             dwarf_drt_data_reloc, cu->cu_pointer_size,
346                             ds->ds_size, at->at_relsym, at->u[0].u64, NULL,
347                             error);
348                 else
349                         ret = WRITE_VALUE(at->u[0].u64, cu->cu_pointer_size);
350                 break;
351         case DW_FORM_ref_udata:
352         case DW_FORM_udata:
353                 ret = WRITE_ULEB128(at->u[0].u64);
354                 break;
355         case DW_FORM_sdata:
356                 ret = WRITE_SLEB128(at->u[0].s64);
357                 break;
358         case DW_FORM_string:
359                 assert(at->u[0].s != NULL);
360                 ret = WRITE_STRING(at->u[0].s);
361                 break;
362         case DW_FORM_strp:
363                 ret = _dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc,
364                     4, ds->ds_size, 0, at->u[0].u64, ".debug_str", error);
365                 break;
366         default:
367                 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
368                 ret = DW_DLE_ATTR_FORM_BAD;
369                 break;
370         }
371
372         return (ret);
373 }
374
375 int
376 _dwarf_add_AT_dataref(Dwarf_P_Debug dbg, Dwarf_P_Die die, Dwarf_Half attr,
377     Dwarf_Unsigned pc_value, Dwarf_Unsigned sym_index, const char *secname,
378     Dwarf_P_Attribute *atp, Dwarf_Error *error)
379 {
380         Dwarf_Attribute at;
381         int ret;
382
383         assert(dbg != NULL && die != NULL);
384
385         if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
386                 return (ret);
387
388         at->at_die = die;
389         at->at_attrib = attr;
390         if (dbg->dbg_pointer_size == 4)
391                 at->at_form = DW_FORM_data4;
392         else
393                 at->at_form = DW_FORM_data8;
394         at->at_relsym = sym_index;
395         at->at_relsec = secname;
396         at->u[0].u64 = pc_value;
397
398         STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
399
400         if (atp)
401                 *atp = at;
402
403         return (DW_DLE_NONE);
404 }
405
406 int
407 _dwarf_add_string_attr(Dwarf_P_Die die, Dwarf_P_Attribute *atp, Dwarf_Half attr,
408     char *string, Dwarf_Error *error)
409 {
410         Dwarf_Attribute at;
411         Dwarf_Debug dbg;
412         int ret;
413
414         dbg = die != NULL ? die->die_dbg : NULL;
415
416         assert(atp != NULL);
417
418         if (die == NULL || string == NULL) {
419                 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
420                 return (DW_DLE_ARGUMENT);
421         }
422
423         if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
424                 return (ret);
425
426         at->at_die = die;
427         at->at_attrib = attr;
428         at->at_form = DW_FORM_strp;
429         if ((ret = _dwarf_strtab_add(dbg, string, &at->u[0].u64,
430             error)) != DW_DLE_NONE) {
431                 free(at);
432                 return (ret);
433         }
434         at->u[1].s = _dwarf_strtab_get_table(dbg) + at->u[0].u64;
435
436         *atp = at;
437
438         STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
439
440         return (DW_DLE_NONE);
441 }
442
443 int
444 _dwarf_attr_gen(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_Rel_Section drs,
445     Dwarf_CU cu, Dwarf_Die die, int pass2, Dwarf_Error *error)
446 {
447         Dwarf_Attribute at;
448         int ret;
449
450         assert(dbg != NULL && ds != NULL && cu != NULL && die != NULL);
451
452         STAILQ_FOREACH(at, &die->die_attr, at_next) {
453                 ret = _dwarf_attr_write(dbg, ds, drs, cu, at, pass2, error);
454                 if (ret != DW_DLE_NONE)
455                         return (ret);
456         }
457
458         return (DW_DLE_NONE);
459 }