Remove building with NOCRYPTO option
[minix.git] / external / bsd / elftoolchain / dist / libdwarf / libdwarf_frame.c
blob81922dda71a7f30ebd0c2fd2d1f55ed576b9adcb
1 /* $NetBSD: libdwarf_frame.c,v 1.2 2014/03/09 16:58:04 christos Exp $ */
3 /*-
4 * Copyright (c) 2009-2011 Kai Wang
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
29 #include "_libdwarf.h"
31 __RCSID("$NetBSD: libdwarf_frame.c,v 1.2 2014/03/09 16:58:04 christos Exp $");
32 ELFTC_VCSID("Id: libdwarf_frame.c 2529 2012-07-29 23:31:12Z kaiwang27 ");
34 static int
35 _dwarf_frame_find_cie(Dwarf_FrameSec fs, Dwarf_Unsigned offset,
36 Dwarf_Cie *ret_cie)
38 Dwarf_Cie cie;
40 STAILQ_FOREACH(cie, &fs->fs_cielist, cie_next) {
41 if (cie->cie_offset == offset)
42 break;
45 if (cie == NULL)
46 return (DW_DLE_NO_ENTRY);
48 if (ret_cie != NULL)
49 *ret_cie = cie;
51 return (DW_DLE_NONE);
54 static int
55 _dwarf_frame_read_lsb_encoded(Dwarf_Debug dbg, uint64_t *val, uint8_t *data,
56 uint64_t *offsetp, uint8_t encode, Dwarf_Addr pc, Dwarf_Error *error)
58 uint8_t application;
60 if (encode == DW_EH_PE_omit)
61 return (DW_DLE_NONE);
63 application = encode & 0xf0;
64 encode &= 0x0f;
66 switch (encode) {
67 case DW_EH_PE_absptr:
68 *val = dbg->read(data, offsetp, dbg->dbg_pointer_size);
69 break;
70 case DW_EH_PE_uleb128:
71 *val = _dwarf_read_uleb128(data, offsetp);
72 break;
73 case DW_EH_PE_udata2:
74 *val = dbg->read(data, offsetp, 2);
75 break;
76 case DW_EH_PE_udata4:
77 *val = dbg->read(data, offsetp, 4);
78 break;
79 case DW_EH_PE_udata8:
80 *val = dbg->read(data, offsetp, 8);
81 break;
82 case DW_EH_PE_sleb128:
83 *val = _dwarf_read_sleb128(data, offsetp);
84 break;
85 case DW_EH_PE_sdata2:
86 *val = (int16_t) dbg->read(data, offsetp, 2);
87 break;
88 case DW_EH_PE_sdata4:
89 *val = (int32_t) dbg->read(data, offsetp, 4);
90 break;
91 case DW_EH_PE_sdata8:
92 *val = dbg->read(data, offsetp, 8);
93 break;
94 default:
95 DWARF_SET_ERROR(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
96 return (DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
99 if (application == DW_EH_PE_pcrel) {
101 * Value is relative to .eh_frame section virtual addr.
103 switch (encode) {
104 case DW_EH_PE_uleb128:
105 case DW_EH_PE_udata2:
106 case DW_EH_PE_udata4:
107 case DW_EH_PE_udata8:
108 *val += pc;
109 break;
110 case DW_EH_PE_sleb128:
111 case DW_EH_PE_sdata2:
112 case DW_EH_PE_sdata4:
113 case DW_EH_PE_sdata8:
114 *val = pc + (int64_t) *val;
115 break;
116 default:
117 /* DW_EH_PE_absptr is absolute value. */
118 break;
122 /* XXX Applications other than DW_EH_PE_pcrel are not handled. */
124 return (DW_DLE_NONE);
127 static int
128 _dwarf_frame_parse_lsb_cie_augment(Dwarf_Debug dbg, Dwarf_Cie cie,
129 Dwarf_Error *error)
131 uint8_t *aug_p, *augdata_p;
132 uint64_t val, offset;
133 uint8_t encode;
134 int ret;
136 assert(cie->cie_augment != NULL && *cie->cie_augment == 'z');
139 * Here we're only interested in the presence of augment 'R'
140 * and associated CIE augment data, which describes the
141 * encoding scheme of FDE PC begin and range.
143 aug_p = &cie->cie_augment[1];
144 augdata_p = cie->cie_augdata;
145 while (*aug_p != '\0') {
146 switch (*aug_p) {
147 case 'L':
148 /* Skip one augment in augment data. */
149 augdata_p++;
150 break;
151 case 'P':
152 /* Skip two augments in augment data. */
153 encode = *augdata_p++;
154 offset = 0;
155 ret = _dwarf_frame_read_lsb_encoded(dbg, &val,
156 augdata_p, &offset, encode, 0, error);
157 if (ret != DW_DLE_NONE)
158 return (ret);
159 augdata_p += offset;
160 break;
161 case 'R':
162 cie->cie_fde_encode = *augdata_p++;
163 break;
164 default:
165 DWARF_SET_ERROR(dbg, error,
166 DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
167 return (DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
169 aug_p++;
172 return (DW_DLE_NONE);
175 static int
176 _dwarf_frame_add_cie(Dwarf_Debug dbg, Dwarf_FrameSec fs, Dwarf_Section *ds,
177 Dwarf_Unsigned *off, Dwarf_Cie *ret_cie, Dwarf_Error *error)
179 Dwarf_Cie cie;
180 uint64_t length;
181 int dwarf_size, ret;
182 char *p;
184 /* Check if we already added this CIE. */
185 if (_dwarf_frame_find_cie(fs, *off, &cie) != DW_DLE_NO_ENTRY) {
186 *off += cie->cie_length + 4;
187 return (DW_DLE_NONE);
190 if ((cie = calloc(1, sizeof(struct _Dwarf_Cie))) == NULL) {
191 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
192 return (DW_DLE_MEMORY);
194 STAILQ_INSERT_TAIL(&fs->fs_cielist, cie, cie_next);
196 cie->cie_dbg = dbg;
197 cie->cie_index = fs->fs_cielen;
198 cie->cie_offset = *off;
200 length = dbg->read(ds->ds_data, off, 4);
201 if (length == 0xffffffff) {
202 dwarf_size = 8;
203 length = dbg->read(ds->ds_data, off, 8);
204 } else
205 dwarf_size = 4;
207 if (length > ds->ds_size - *off) {
208 DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
209 return (DW_DLE_DEBUG_FRAME_LENGTH_BAD);
212 (void) dbg->read(ds->ds_data, off, dwarf_size); /* Skip CIE id. */
213 cie->cie_length = length;
215 cie->cie_version = dbg->read(ds->ds_data, off, 1);
216 if (cie->cie_version != 1 && cie->cie_version != 3 &&
217 cie->cie_version != 4) {
218 DWARF_SET_ERROR(dbg, error, DW_DLE_FRAME_VERSION_BAD);
219 return (DW_DLE_FRAME_VERSION_BAD);
222 cie->cie_augment = ds->ds_data + *off;
223 p = (char *) ds->ds_data;
224 while (p[(*off)++] != '\0')
227 /* We only recognize normal .dwarf_frame and GNU .eh_frame sections. */
228 if (*cie->cie_augment != 0 && *cie->cie_augment != 'z') {
229 *off = cie->cie_offset + ((dwarf_size == 4) ? 4 : 12) +
230 cie->cie_length;
231 return (DW_DLE_NONE);
234 /* Optional EH Data field for .eh_frame section. */
235 if (strstr((char *)cie->cie_augment, "eh") != NULL)
236 cie->cie_ehdata = dbg->read(ds->ds_data, off,
237 dbg->dbg_pointer_size);
239 cie->cie_caf = _dwarf_read_uleb128(ds->ds_data, off);
240 cie->cie_daf = _dwarf_read_sleb128(ds->ds_data, off);
242 /* Return address register. */
243 if (cie->cie_version == 1)
244 cie->cie_ra = dbg->read(ds->ds_data, off, 1);
245 else
246 cie->cie_ra = _dwarf_read_uleb128(ds->ds_data, off);
248 /* Optional CIE augmentation data for .eh_frame section. */
249 if (*cie->cie_augment == 'z') {
250 cie->cie_auglen = _dwarf_read_uleb128(ds->ds_data, off);
251 cie->cie_augdata = ds->ds_data + *off;
252 *off += cie->cie_auglen;
254 * XXX Use DW_EH_PE_absptr for default FDE PC start/range,
255 * in case _dwarf_frame_parse_lsb_cie_augment fails to
256 * find out the real encode.
258 cie->cie_fde_encode = DW_EH_PE_absptr;
259 ret = _dwarf_frame_parse_lsb_cie_augment(dbg, cie, error);
260 if (ret != DW_DLE_NONE)
261 return (ret);
264 /* CIE Initial instructions. */
265 cie->cie_initinst = ds->ds_data + *off;
266 if (dwarf_size == 4)
267 cie->cie_instlen = cie->cie_offset + 4 + length - *off;
268 else
269 cie->cie_instlen = cie->cie_offset + 12 + length - *off;
271 *off += cie->cie_instlen;
273 #ifdef FRAME_DEBUG
274 printf("cie:\n");
275 printf("\tcie_version=%u cie_offset=%ju cie_length=%ju cie_augment=%s"
276 " cie_instlen=%ju cie->cie_caf=%ju cie->cie_daf=%jd off=%ju\n",
277 cie->cie_version, cie->cie_offset, cie->cie_length,
278 (char *)cie->cie_augment, cie->cie_instlen, cie->cie_caf,
279 cie->cie_daf, *off);
280 #endif
282 if (ret_cie != NULL)
283 *ret_cie = cie;
285 fs->fs_cielen++;
287 return (DW_DLE_NONE);
290 static int
291 _dwarf_frame_add_fde(Dwarf_Debug dbg, Dwarf_FrameSec fs, Dwarf_Section *ds,
292 Dwarf_Unsigned *off, int eh_frame, Dwarf_Error *error)
294 Dwarf_Cie cie;
295 Dwarf_Fde fde;
296 Dwarf_Unsigned cieoff;
297 uint64_t length, val;
298 int dwarf_size, ret;
300 if ((fde = calloc(1, sizeof(struct _Dwarf_Fde))) == NULL) {
301 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
302 return (DW_DLE_MEMORY);
304 STAILQ_INSERT_TAIL(&fs->fs_fdelist, fde, fde_next);
306 fde->fde_dbg = dbg;
307 fde->fde_fs = fs;
308 fde->fde_addr = ds->ds_data + *off;
309 fde->fde_offset = *off;
311 length = dbg->read(ds->ds_data, off, 4);
312 if (length == 0xffffffff) {
313 dwarf_size = 8;
314 length = dbg->read(ds->ds_data, off, 8);
315 } else
316 dwarf_size = 4;
318 if (length > ds->ds_size - *off) {
319 DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
320 return (DW_DLE_DEBUG_FRAME_LENGTH_BAD);
323 fde->fde_length = length;
325 if (eh_frame) {
326 fde->fde_cieoff = dbg->read(ds->ds_data, off, 4);
327 cieoff = *off - (4 + fde->fde_cieoff);
328 /* This delta should never be 0. */
329 if (cieoff == fde->fde_offset) {
330 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_CIE_FOR_FDE);
331 return (DW_DLE_NO_CIE_FOR_FDE);
333 } else {
334 fde->fde_cieoff = dbg->read(ds->ds_data, off, dwarf_size);
335 cieoff = fde->fde_cieoff;
338 if (_dwarf_frame_find_cie(fs, cieoff, &cie) ==
339 DW_DLE_NO_ENTRY) {
340 ret = _dwarf_frame_add_cie(dbg, fs, ds, &cieoff, &cie,
341 error);
342 if (ret != DW_DLE_NONE)
343 return (ret);
345 fde->fde_cie = cie;
346 if (eh_frame) {
348 * The FDE PC start/range for .eh_frame is encoded according
349 * to the LSB spec's extension to DWARF2.
351 ret = _dwarf_frame_read_lsb_encoded(dbg, &val, ds->ds_data,
352 off, cie->cie_fde_encode, ds->ds_addr + *off, error);
353 if (ret != DW_DLE_NONE)
354 return (ret);
355 fde->fde_initloc = val;
357 * FDE PC range should not be relative value to anything.
358 * So pass 0 for pc value.
360 ret = _dwarf_frame_read_lsb_encoded(dbg, &val, ds->ds_data,
361 off, cie->cie_fde_encode, 0, error);
362 if (ret != DW_DLE_NONE)
363 return (ret);
364 fde->fde_adrange = val;
365 } else {
366 fde->fde_initloc = dbg->read(ds->ds_data, off,
367 dbg->dbg_pointer_size);
368 fde->fde_adrange = dbg->read(ds->ds_data, off,
369 dbg->dbg_pointer_size);
372 /* Optional FDE augmentation data for .eh_frame section. (ignored) */
373 if (eh_frame && *cie->cie_augment == 'z') {
374 fde->fde_auglen = _dwarf_read_uleb128(ds->ds_data, off);
375 fde->fde_augdata = ds->ds_data + *off;
376 *off += fde->fde_auglen;
379 fde->fde_inst = ds->ds_data + *off;
380 if (dwarf_size == 4)
381 fde->fde_instlen = fde->fde_offset + 4 + length - *off;
382 else
383 fde->fde_instlen = fde->fde_offset + 12 + length - *off;
385 *off += fde->fde_instlen;
387 #ifdef FRAME_DEBUG
388 printf("fde:");
389 if (eh_frame)
390 printf("(eh_frame)");
391 putchar('\n');
392 printf("\tfde_offset=%ju fde_length=%ju fde_cieoff=%ju"
393 " fde_instlen=%ju off=%ju\n", fde->fde_offset, fde->fde_length,
394 fde->fde_cieoff, fde->fde_instlen, *off);
395 #endif
397 fs->fs_fdelen++;
399 return (DW_DLE_NONE);
402 static void
403 _dwarf_frame_section_cleanup(Dwarf_FrameSec fs)
405 Dwarf_Cie cie, tcie;
406 Dwarf_Fde fde, tfde;
408 STAILQ_FOREACH_SAFE(cie, &fs->fs_cielist, cie_next, tcie) {
409 STAILQ_REMOVE(&fs->fs_cielist, cie, _Dwarf_Cie, cie_next);
410 free(cie);
413 STAILQ_FOREACH_SAFE(fde, &fs->fs_fdelist, fde_next, tfde) {
414 STAILQ_REMOVE(&fs->fs_fdelist, fde, _Dwarf_Fde, fde_next);
415 free(fde);
418 if (fs->fs_ciearray != NULL)
419 free(fs->fs_ciearray);
420 if (fs->fs_fdearray != NULL)
421 free(fs->fs_fdearray);
423 free(fs);
426 static int
427 _dwarf_frame_section_init(Dwarf_Debug dbg, Dwarf_FrameSec *frame_sec,
428 Dwarf_Section *ds, int eh_frame, Dwarf_Error *error)
430 Dwarf_FrameSec fs;
431 Dwarf_Cie cie;
432 Dwarf_Fde fde;
433 uint64_t length, offset, cie_id, entry_off;
434 int dwarf_size, i, ret;
436 assert(frame_sec != NULL);
437 assert(*frame_sec == NULL);
439 if ((fs = calloc(1, sizeof(struct _Dwarf_FrameSec))) == NULL) {
440 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
441 return (DW_DLE_MEMORY);
443 STAILQ_INIT(&fs->fs_cielist);
444 STAILQ_INIT(&fs->fs_fdelist);
446 offset = 0;
447 while (offset < ds->ds_size) {
448 entry_off = offset;
449 length = dbg->read(ds->ds_data, &offset, 4);
450 if (length == 0xffffffff) {
451 dwarf_size = 8;
452 length = dbg->read(ds->ds_data, &offset, 8);
453 } else
454 dwarf_size = 4;
456 if (length > ds->ds_size - offset ||
457 (length == 0 && !eh_frame)) {
458 DWARF_SET_ERROR(dbg, error,
459 DW_DLE_DEBUG_FRAME_LENGTH_BAD);
460 return (DW_DLE_DEBUG_FRAME_LENGTH_BAD);
463 /* Check terminator for .eh_frame */
464 if (eh_frame && length == 0)
465 break;
467 cie_id = dbg->read(ds->ds_data, &offset, dwarf_size);
469 if (eh_frame) {
470 /* GNU .eh_frame use CIE id 0. */
471 if (cie_id == 0)
472 ret = _dwarf_frame_add_cie(dbg, fs, ds,
473 &entry_off, NULL, error);
474 else
475 ret = _dwarf_frame_add_fde(dbg, fs, ds,
476 &entry_off, 1, error);
477 } else {
478 /* .dwarf_frame use CIE id ~0 */
479 if ((dwarf_size == 4 && cie_id == ~0U) ||
480 (dwarf_size == 8 && cie_id == ~0ULL))
481 ret = _dwarf_frame_add_cie(dbg, fs, ds,
482 &entry_off, NULL, error);
483 else
484 ret = _dwarf_frame_add_fde(dbg, fs, ds,
485 &entry_off, 0, error);
488 if (ret != DW_DLE_NONE)
489 goto fail_cleanup;
491 offset = entry_off;
494 /* Create CIE array. */
495 if (fs->fs_cielen > 0) {
496 if ((fs->fs_ciearray = malloc(sizeof(Dwarf_Cie) *
497 fs->fs_cielen)) == NULL) {
498 ret = DW_DLE_MEMORY;
499 DWARF_SET_ERROR(dbg, error, ret);
500 goto fail_cleanup;
502 i = 0;
503 STAILQ_FOREACH(cie, &fs->fs_cielist, cie_next) {
504 fs->fs_ciearray[i++] = cie;
506 assert((Dwarf_Unsigned)i == fs->fs_cielen);
509 /* Create FDE array. */
510 if (fs->fs_fdelen > 0) {
511 if ((fs->fs_fdearray = malloc(sizeof(Dwarf_Fde) *
512 fs->fs_fdelen)) == NULL) {
513 ret = DW_DLE_MEMORY;
514 DWARF_SET_ERROR(dbg, error, ret);
515 goto fail_cleanup;
517 i = 0;
518 STAILQ_FOREACH(fde, &fs->fs_fdelist, fde_next) {
519 fs->fs_fdearray[i++] = fde;
521 assert((Dwarf_Unsigned)i == fs->fs_fdelen);
524 *frame_sec = fs;
526 return (DW_DLE_NONE);
528 fail_cleanup:
530 _dwarf_frame_section_cleanup(fs);
532 return (ret);
535 static int
536 _dwarf_frame_run_inst(Dwarf_Debug dbg, Dwarf_Regtable3 *rt, uint8_t *insts,
537 Dwarf_Unsigned len, Dwarf_Unsigned caf, Dwarf_Signed daf, Dwarf_Addr pc,
538 Dwarf_Addr pc_req, Dwarf_Addr *row_pc, Dwarf_Error *error)
540 Dwarf_Regtable3 *init_rt, *saved_rt;
541 uint8_t *p, *pe;
542 uint8_t high2, low6;
543 uint64_t reg, reg2, uoff, soff;
544 int ret;
546 #define CFA rt->rt3_cfa_rule
547 #define INITCFA init_rt->rt3_cfa_rule
548 #define RL rt->rt3_rules
549 #define INITRL init_rt->rt3_rules
551 #define CHECK_TABLE_SIZE(x) \
552 do { \
553 if ((x) >= rt->rt3_reg_table_size) { \
554 DWARF_SET_ERROR(dbg, error, \
555 DW_DLE_DF_REG_NUM_TOO_HIGH); \
556 ret = DW_DLE_DF_REG_NUM_TOO_HIGH; \
557 goto program_done; \
559 } while(0)
561 #ifdef FRAME_DEBUG
562 printf("frame_run_inst: (caf=%ju, daf=%jd)\n", caf, daf);
563 #endif
565 ret = DW_DLE_NONE;
566 init_rt = saved_rt = NULL;
567 *row_pc = pc;
569 /* Save a copy of the table as initial state. */
570 _dwarf_frame_regtable_copy(dbg, &init_rt, rt, error);
572 p = insts;
573 pe = p + len;
575 while (p < pe) {
577 #ifdef FRAME_DEBUG
578 printf("p=%p pe=%p pc=%#jx pc_req=%#jx\n", p, pe, pc, pc_req);
579 #endif
581 if (*p == DW_CFA_nop) {
582 #ifdef FRAME_DEBUG
583 printf("DW_CFA_nop\n");
584 #endif
585 p++;
586 continue;
589 high2 = *p & 0xc0;
590 low6 = *p & 0x3f;
591 p++;
593 if (high2 > 0) {
594 switch (high2) {
595 case DW_CFA_advance_loc:
596 pc += low6 * caf;
597 #ifdef FRAME_DEBUG
598 printf("DW_CFA_advance_loc(%#jx(%u))\n", pc,
599 low6);
600 #endif
601 if (pc_req < pc)
602 goto program_done;
603 break;
604 case DW_CFA_offset:
605 *row_pc = pc;
606 CHECK_TABLE_SIZE(low6);
607 RL[low6].dw_offset_relevant = 1;
608 RL[low6].dw_value_type = DW_EXPR_OFFSET;
609 RL[low6].dw_regnum = dbg->dbg_frame_cfa_value;
610 RL[low6].dw_offset_or_block_len =
611 _dwarf_decode_uleb128(&p) * daf;
612 #ifdef FRAME_DEBUG
613 printf("DW_CFA_offset(%jd)\n",
614 RL[low6].dw_offset_or_block_len);
615 #endif
616 break;
617 case DW_CFA_restore:
618 *row_pc = pc;
619 CHECK_TABLE_SIZE(low6);
620 memcpy(&RL[low6], &INITRL[low6],
621 sizeof(Dwarf_Regtable_Entry3));
622 #ifdef FRAME_DEBUG
623 printf("DW_CFA_restore(%u)\n", low6);
624 #endif
625 break;
626 default:
627 DWARF_SET_ERROR(dbg, error,
628 DW_DLE_FRAME_INSTR_EXEC_ERROR);
629 ret = DW_DLE_FRAME_INSTR_EXEC_ERROR;
630 goto program_done;
633 continue;
636 switch (low6) {
637 case DW_CFA_set_loc:
638 pc = dbg->decode(&p, dbg->dbg_pointer_size);
639 #ifdef FRAME_DEBUG
640 printf("DW_CFA_set_loc(pc=%#jx)\n", pc);
641 #endif
642 if (pc_req < pc)
643 goto program_done;
644 break;
645 case DW_CFA_advance_loc1:
646 pc += dbg->decode(&p, 1) * caf;
647 #ifdef FRAME_DEBUG
648 printf("DW_CFA_set_loc1(pc=%#jx)\n", pc);
649 #endif
650 if (pc_req < pc)
651 goto program_done;
652 break;
653 case DW_CFA_advance_loc2:
654 pc += dbg->decode(&p, 2) * caf;
655 #ifdef FRAME_DEBUG
656 printf("DW_CFA_set_loc2(pc=%#jx)\n", pc);
657 #endif
658 if (pc_req < pc)
659 goto program_done;
660 break;
661 case DW_CFA_advance_loc4:
662 pc += dbg->decode(&p, 4) * caf;
663 #ifdef FRAME_DEBUG
664 printf("DW_CFA_set_loc4(pc=%#jx)\n", pc);
665 #endif
666 if (pc_req < pc)
667 goto program_done;
668 break;
669 case DW_CFA_offset_extended:
670 *row_pc = pc;
671 reg = _dwarf_decode_uleb128(&p);
672 uoff = _dwarf_decode_uleb128(&p);
673 CHECK_TABLE_SIZE(reg);
674 RL[reg].dw_offset_relevant = 1;
675 RL[reg].dw_value_type = DW_EXPR_OFFSET;
676 RL[reg].dw_regnum = dbg->dbg_frame_cfa_value;
677 RL[reg].dw_offset_or_block_len = uoff * daf;
678 #ifdef FRAME_DEBUG
679 printf("DW_CFA_offset_extended(reg=%ju,uoff=%ju)\n",
680 reg, uoff);
681 #endif
682 break;
683 case DW_CFA_restore_extended:
684 *row_pc = pc;
685 reg = _dwarf_decode_uleb128(&p);
686 CHECK_TABLE_SIZE(reg);
687 memcpy(&RL[reg], &INITRL[reg],
688 sizeof(Dwarf_Regtable_Entry3));
689 #ifdef FRAME_DEBUG
690 printf("DW_CFA_restore_extended(%ju)\n", reg);
691 #endif
692 break;
693 case DW_CFA_undefined:
694 *row_pc = pc;
695 reg = _dwarf_decode_uleb128(&p);
696 CHECK_TABLE_SIZE(reg);
697 RL[reg].dw_offset_relevant = 0;
698 RL[reg].dw_regnum = dbg->dbg_frame_undefined_value;
699 #ifdef FRAME_DEBUG
700 printf("DW_CFA_undefined(%ju)\n", reg);
701 #endif
702 break;
703 case DW_CFA_same_value:
704 reg = _dwarf_decode_uleb128(&p);
705 CHECK_TABLE_SIZE(reg);
706 RL[reg].dw_offset_relevant = 0;
707 RL[reg].dw_regnum = dbg->dbg_frame_same_value;
708 #ifdef FRAME_DEBUG
709 printf("DW_CFA_same_value(%ju)\n", reg);
710 #endif
711 break;
712 case DW_CFA_register:
713 *row_pc = pc;
714 reg = _dwarf_decode_uleb128(&p);
715 reg2 = _dwarf_decode_uleb128(&p);
716 CHECK_TABLE_SIZE(reg);
717 RL[reg].dw_offset_relevant = 0;
718 RL[reg].dw_regnum = reg2;
719 #ifdef FRAME_DEBUG
720 printf("DW_CFA_register(reg=%ju,reg2=%ju)\n", reg,
721 reg2);
722 #endif
723 break;
724 case DW_CFA_remember_state:
725 _dwarf_frame_regtable_copy(dbg, &saved_rt, rt, error);
726 #ifdef FRAME_DEBUG
727 printf("DW_CFA_remember_state\n");
728 #endif
729 break;
730 case DW_CFA_restore_state:
731 *row_pc = pc;
732 _dwarf_frame_regtable_copy(dbg, &rt, saved_rt, error);
733 #ifdef FRAME_DEBUG
734 printf("DW_CFA_restore_state\n");
735 #endif
736 break;
737 case DW_CFA_def_cfa:
738 *row_pc = pc;
739 reg = _dwarf_decode_uleb128(&p);
740 uoff = _dwarf_decode_uleb128(&p);
741 CFA.dw_offset_relevant = 1;
742 CFA.dw_value_type = DW_EXPR_OFFSET;
743 CFA.dw_regnum = reg;
744 CFA.dw_offset_or_block_len = uoff;
745 #ifdef FRAME_DEBUG
746 printf("DW_CFA_def_cfa(reg=%ju,uoff=%ju)\n", reg, uoff);
747 #endif
748 break;
749 case DW_CFA_def_cfa_register:
750 *row_pc = pc;
751 reg = _dwarf_decode_uleb128(&p);
752 CFA.dw_regnum = reg;
754 * Note that DW_CFA_def_cfa_register change the CFA
755 * rule register while keep the old offset. So we
756 * should not touch the CFA.dw_offset_relevant flag
757 * here.
759 #ifdef FRAME_DEBUG
760 printf("DW_CFA_def_cfa_register(%ju)\n", reg);
761 #endif
762 break;
763 case DW_CFA_def_cfa_offset:
764 *row_pc = pc;
765 uoff = _dwarf_decode_uleb128(&p);
766 CFA.dw_offset_relevant = 1;
767 CFA.dw_value_type = DW_EXPR_OFFSET;
768 CFA.dw_offset_or_block_len = uoff;
769 #ifdef FRAME_DEBUG
770 printf("DW_CFA_def_cfa_offset(%ju)\n", uoff);
771 #endif
772 break;
773 case DW_CFA_def_cfa_expression:
774 *row_pc = pc;
775 CFA.dw_offset_relevant = 0;
776 CFA.dw_value_type = DW_EXPR_EXPRESSION;
777 CFA.dw_offset_or_block_len = _dwarf_decode_uleb128(&p);
778 CFA.dw_block_ptr = p;
779 p += CFA.dw_offset_or_block_len;
780 #ifdef FRAME_DEBUG
781 printf("DW_CFA_def_cfa_expression\n");
782 #endif
783 break;
784 case DW_CFA_expression:
785 *row_pc = pc;
786 reg = _dwarf_decode_uleb128(&p);
787 CHECK_TABLE_SIZE(reg);
788 RL[reg].dw_offset_relevant = 0;
789 RL[reg].dw_value_type = DW_EXPR_EXPRESSION;
790 RL[reg].dw_offset_or_block_len =
791 _dwarf_decode_uleb128(&p);
792 RL[reg].dw_block_ptr = p;
793 p += RL[reg].dw_offset_or_block_len;
794 #ifdef FRAME_DEBUG
795 printf("DW_CFA_expression\n");
796 #endif
797 break;
798 case DW_CFA_offset_extended_sf:
799 *row_pc = pc;
800 reg = _dwarf_decode_uleb128(&p);
801 soff = _dwarf_decode_sleb128(&p);
802 CHECK_TABLE_SIZE(reg);
803 RL[reg].dw_offset_relevant = 1;
804 RL[reg].dw_value_type = DW_EXPR_OFFSET;
805 RL[reg].dw_regnum = dbg->dbg_frame_cfa_value;
806 RL[reg].dw_offset_or_block_len = soff * daf;
807 #ifdef FRAME_DEBUG
808 printf("DW_CFA_offset_extended_sf(reg=%ju,soff=%jd)\n",
809 reg, soff);
810 #endif
811 break;
812 case DW_CFA_def_cfa_sf:
813 *row_pc = pc;
814 reg = _dwarf_decode_uleb128(&p);
815 soff = _dwarf_decode_sleb128(&p);
816 CFA.dw_offset_relevant = 1;
817 CFA.dw_value_type = DW_EXPR_OFFSET;
818 CFA.dw_regnum = reg;
819 CFA.dw_offset_or_block_len = soff * daf;
820 #ifdef FRAME_DEBUG
821 printf("DW_CFA_def_cfa_sf(reg=%ju,soff=%jd)\n", reg,
822 soff);
823 #endif
824 break;
825 case DW_CFA_def_cfa_offset_sf:
826 *row_pc = pc;
827 soff = _dwarf_decode_sleb128(&p);
828 CFA.dw_offset_relevant = 1;
829 CFA.dw_value_type = DW_EXPR_OFFSET;
830 CFA.dw_offset_or_block_len = soff * daf;
831 #ifdef FRAME_DEBUG
832 printf("DW_CFA_def_cfa_offset_sf(soff=%jd)\n", soff);
833 #endif
834 break;
835 case DW_CFA_val_offset:
836 *row_pc = pc;
837 reg = _dwarf_decode_uleb128(&p);
838 uoff = _dwarf_decode_uleb128(&p);
839 CHECK_TABLE_SIZE(reg);
840 RL[reg].dw_offset_relevant = 1;
841 RL[reg].dw_value_type = DW_EXPR_VAL_OFFSET;
842 RL[reg].dw_regnum = dbg->dbg_frame_cfa_value;
843 RL[reg].dw_offset_or_block_len = uoff * daf;
844 #ifdef FRAME_DEBUG
845 printf("DW_CFA_val_offset(reg=%ju,uoff=%ju)\n", reg,
846 uoff);
847 #endif
848 break;
849 case DW_CFA_val_offset_sf:
850 *row_pc = pc;
851 reg = _dwarf_decode_uleb128(&p);
852 soff = _dwarf_decode_sleb128(&p);
853 CHECK_TABLE_SIZE(reg);
854 RL[reg].dw_offset_relevant = 1;
855 RL[reg].dw_value_type = DW_EXPR_VAL_OFFSET;
856 RL[reg].dw_regnum = dbg->dbg_frame_cfa_value;
857 RL[reg].dw_offset_or_block_len = soff * daf;
858 #ifdef FRAME_DEBUG
859 printf("DW_CFA_val_offset_sf(reg=%ju,soff=%jd)\n", reg,
860 soff);
861 #endif
862 break;
863 case DW_CFA_val_expression:
864 *row_pc = pc;
865 reg = _dwarf_decode_uleb128(&p);
866 CHECK_TABLE_SIZE(reg);
867 RL[reg].dw_offset_relevant = 0;
868 RL[reg].dw_value_type = DW_EXPR_VAL_EXPRESSION;
869 RL[reg].dw_offset_or_block_len =
870 _dwarf_decode_uleb128(&p);
871 RL[reg].dw_block_ptr = p;
872 p += RL[reg].dw_offset_or_block_len;
873 #ifdef FRAME_DEBUG
874 printf("DW_CFA_val_expression\n");
875 #endif
876 break;
877 default:
878 DWARF_SET_ERROR(dbg, error,
879 DW_DLE_FRAME_INSTR_EXEC_ERROR);
880 ret = DW_DLE_FRAME_INSTR_EXEC_ERROR;
881 goto program_done;
885 program_done:
887 free(init_rt->rt3_rules);
888 free(init_rt);
889 if (saved_rt) {
890 free(saved_rt->rt3_rules);
891 free(saved_rt);
894 return (ret);
896 #undef CFA
897 #undef INITCFA
898 #undef RL
899 #undef INITRL
900 #undef CHECK_TABLE_SIZE
903 static int
904 _dwarf_frame_convert_inst(Dwarf_Debug dbg, uint8_t *insts, Dwarf_Unsigned len,
905 Dwarf_Unsigned *count, Dwarf_Frame_Op *fop, Dwarf_Frame_Op3 *fop3,
906 Dwarf_Error *error)
908 uint8_t *p, *pe;
909 uint8_t high2, low6;
910 uint64_t reg, reg2, uoff, soff, blen;
911 int ret;
913 #define SET_BASE_OP(x) \
914 do { \
915 if (fop != NULL) \
916 fop[*count].fp_base_op = (x) >> 6; \
917 if (fop3 != NULL) \
918 fop3[*count].fp_base_op = (x) >> 6; \
919 } while(0)
921 #define SET_EXTENDED_OP(x) \
922 do { \
923 if (fop != NULL) \
924 fop[*count].fp_extended_op = (x); \
925 if (fop3 != NULL) \
926 fop3[*count].fp_extended_op = (x); \
927 } while(0)
929 #define SET_REGISTER(x) \
930 do { \
931 if (fop != NULL) \
932 fop[*count].fp_register = (x); \
933 if (fop3 != NULL) \
934 fop3[*count].fp_register = (x); \
935 } while(0)
937 #define SET_OFFSET(x) \
938 do { \
939 if (fop != NULL) \
940 fop[*count].fp_offset = (x); \
941 if (fop3 != NULL) \
942 fop3[*count].fp_offset_or_block_len = \
943 (x); \
944 } while(0)
946 #define SET_INSTR_OFFSET(x) \
947 do { \
948 if (fop != NULL) \
949 fop[*count].fp_instr_offset = (x); \
950 if (fop3 != NULL) \
951 fop3[*count].fp_instr_offset = (x); \
952 } while(0)
954 #define SET_BLOCK_LEN(x) \
955 do { \
956 if (fop3 != NULL) \
957 fop3[*count].fp_offset_or_block_len = \
958 (x); \
959 } while(0)
961 #define SET_EXPR_BLOCK(addr, len) \
962 do { \
963 if (fop3 != NULL) { \
964 fop3[*count].fp_expr_block = \
965 malloc((size_t) (len)); \
966 if (fop3[*count].fp_expr_block == NULL) { \
967 DWARF_SET_ERROR(dbg, error, \
968 DW_DLE_MEMORY); \
969 return (DW_DLE_MEMORY); \
971 memcpy(&fop3[*count].fp_expr_block, \
972 (addr), (len)); \
974 } while(0)
976 ret = DW_DLE_NONE;
977 *count = 0;
979 p = insts;
980 pe = p + len;
982 while (p < pe) {
984 SET_INSTR_OFFSET(p - insts);
986 if (*p == DW_CFA_nop) {
987 p++;
988 (*count)++;
989 continue;
992 high2 = *p & 0xc0;
993 low6 = *p & 0x3f;
994 p++;
996 if (high2 > 0) {
997 switch (high2) {
998 case DW_CFA_advance_loc:
999 SET_BASE_OP(high2);
1000 SET_OFFSET(low6);
1001 break;
1002 case DW_CFA_offset:
1003 SET_BASE_OP(high2);
1004 SET_REGISTER(low6);
1005 uoff = _dwarf_decode_uleb128(&p);
1006 SET_OFFSET(uoff);
1007 break;
1008 case DW_CFA_restore:
1009 SET_BASE_OP(high2);
1010 SET_REGISTER(low6);
1011 break;
1012 default:
1013 DWARF_SET_ERROR(dbg, error,
1014 DW_DLE_FRAME_INSTR_EXEC_ERROR);
1015 return (DW_DLE_FRAME_INSTR_EXEC_ERROR);
1018 (*count)++;
1019 continue;
1022 SET_EXTENDED_OP(low6);
1024 switch (low6) {
1025 case DW_CFA_set_loc:
1026 uoff = dbg->decode(&p, dbg->dbg_pointer_size);
1027 SET_OFFSET(uoff);
1028 break;
1029 case DW_CFA_advance_loc1:
1030 uoff = dbg->decode(&p, 1);
1031 SET_OFFSET(uoff);
1032 break;
1033 case DW_CFA_advance_loc2:
1034 uoff = dbg->decode(&p, 2);
1035 SET_OFFSET(uoff);
1036 break;
1037 case DW_CFA_advance_loc4:
1038 uoff = dbg->decode(&p, 4);
1039 SET_OFFSET(uoff);
1040 break;
1041 case DW_CFA_offset_extended:
1042 case DW_CFA_def_cfa:
1043 case DW_CFA_val_offset:
1044 reg = _dwarf_decode_uleb128(&p);
1045 uoff = _dwarf_decode_uleb128(&p);
1046 SET_REGISTER(reg);
1047 SET_OFFSET(uoff);
1048 break;
1049 case DW_CFA_restore_extended:
1050 case DW_CFA_undefined:
1051 case DW_CFA_same_value:
1052 case DW_CFA_def_cfa_register:
1053 reg = _dwarf_decode_uleb128(&p);
1054 SET_REGISTER(reg);
1055 break;
1056 case DW_CFA_register:
1057 reg = _dwarf_decode_uleb128(&p);
1058 reg2 = _dwarf_decode_uleb128(&p);
1059 SET_REGISTER(reg);
1060 SET_OFFSET(reg2);
1061 break;
1062 case DW_CFA_remember_state:
1063 case DW_CFA_restore_state:
1064 break;
1065 case DW_CFA_def_cfa_offset:
1066 uoff = _dwarf_decode_uleb128(&p);
1067 SET_OFFSET(uoff);
1068 break;
1069 case DW_CFA_def_cfa_expression:
1070 blen = _dwarf_decode_uleb128(&p);
1071 SET_BLOCK_LEN(blen);
1072 SET_EXPR_BLOCK(p, blen);
1073 p += blen;
1074 break;
1075 case DW_CFA_expression:
1076 case DW_CFA_val_expression:
1077 reg = _dwarf_decode_uleb128(&p);
1078 blen = _dwarf_decode_uleb128(&p);
1079 SET_REGISTER(reg);
1080 SET_BLOCK_LEN(blen);
1081 SET_EXPR_BLOCK(p, blen);
1082 p += blen;
1083 break;
1084 case DW_CFA_offset_extended_sf:
1085 case DW_CFA_def_cfa_sf:
1086 case DW_CFA_val_offset_sf:
1087 reg = _dwarf_decode_uleb128(&p);
1088 soff = _dwarf_decode_sleb128(&p);
1089 SET_REGISTER(reg);
1090 SET_OFFSET(soff);
1091 break;
1092 case DW_CFA_def_cfa_offset_sf:
1093 soff = _dwarf_decode_sleb128(&p);
1094 SET_OFFSET(soff);
1095 break;
1096 default:
1097 DWARF_SET_ERROR(dbg, error,
1098 DW_DLE_FRAME_INSTR_EXEC_ERROR);
1099 return (DW_DLE_FRAME_INSTR_EXEC_ERROR);
1102 (*count)++;
1105 return (DW_DLE_NONE);
1109 _dwarf_frame_get_fop(Dwarf_Debug dbg, uint8_t *insts, Dwarf_Unsigned len,
1110 Dwarf_Frame_Op **ret_oplist, Dwarf_Signed *ret_opcnt, Dwarf_Error *error)
1112 Dwarf_Frame_Op *oplist;
1113 Dwarf_Unsigned count;
1114 int ret;
1116 ret = _dwarf_frame_convert_inst(dbg, insts, len, &count, NULL, NULL,
1117 error);
1118 if (ret != DW_DLE_NONE)
1119 return (ret);
1121 if ((oplist = calloc(count, sizeof(Dwarf_Frame_Op))) == NULL) {
1122 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
1123 return (DW_DLE_MEMORY);
1126 ret = _dwarf_frame_convert_inst(dbg, insts, len, &count, oplist, NULL,
1127 error);
1128 if (ret != DW_DLE_NONE) {
1129 free(oplist);
1130 return (ret);
1133 *ret_oplist = oplist;
1134 *ret_opcnt = count;
1136 return (DW_DLE_NONE);
1140 _dwarf_frame_regtable_copy(Dwarf_Debug dbg, Dwarf_Regtable3 **dest,
1141 Dwarf_Regtable3 *src, Dwarf_Error *error)
1143 int i;
1145 assert(dest != NULL);
1146 assert(src != NULL);
1148 if (*dest == NULL) {
1149 if ((*dest = malloc(sizeof(Dwarf_Regtable3))) == NULL) {
1150 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
1151 return (DW_DLE_MEMORY);
1153 (*dest)->rt3_reg_table_size = src->rt3_reg_table_size;
1154 (*dest)->rt3_rules = malloc(src->rt3_reg_table_size *
1155 sizeof(Dwarf_Regtable_Entry3));
1156 if ((*dest)->rt3_rules == NULL) {
1157 free(*dest);
1158 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
1159 return (DW_DLE_MEMORY);
1163 memcpy(&(*dest)->rt3_cfa_rule, &src->rt3_cfa_rule,
1164 sizeof(Dwarf_Regtable_Entry3));
1166 for (i = 0; i < (*dest)->rt3_reg_table_size &&
1167 i < src->rt3_reg_table_size; i++)
1168 memcpy(&(*dest)->rt3_rules[i], &src->rt3_rules[i],
1169 sizeof(Dwarf_Regtable_Entry3));
1171 for (; i < (*dest)->rt3_reg_table_size; i++)
1172 (*dest)->rt3_rules[i].dw_regnum =
1173 dbg->dbg_frame_undefined_value;
1175 return (DW_DLE_NONE);
1179 _dwarf_frame_get_internal_table(Dwarf_Fde fde, Dwarf_Addr pc_req,
1180 Dwarf_Regtable3 **ret_rt, Dwarf_Addr *ret_row_pc, Dwarf_Error *error)
1182 Dwarf_Debug dbg;
1183 Dwarf_Cie cie;
1184 Dwarf_Regtable3 *rt;
1185 Dwarf_Addr row_pc;
1186 int i, ret;
1188 assert(ret_rt != NULL);
1190 dbg = fde->fde_dbg;
1191 assert(dbg != NULL);
1193 rt = dbg->dbg_internal_reg_table;
1195 /* Clear the content of regtable from previous run. */
1196 memset(&rt->rt3_cfa_rule, 0, sizeof(Dwarf_Regtable_Entry3));
1197 memset(rt->rt3_rules, 0, rt->rt3_reg_table_size *
1198 sizeof(Dwarf_Regtable_Entry3));
1200 /* Set rules to initial values. */
1201 for (i = 0; i < rt->rt3_reg_table_size; i++)
1202 rt->rt3_rules[i].dw_regnum = dbg->dbg_frame_rule_initial_value;
1204 /* Run initial instructions in CIE. */
1205 cie = fde->fde_cie;
1206 assert(cie != NULL);
1207 ret = _dwarf_frame_run_inst(dbg, rt, cie->cie_initinst,
1208 cie->cie_instlen, cie->cie_caf, cie->cie_daf, 0, ~0ULL,
1209 &row_pc, error);
1210 if (ret != DW_DLE_NONE)
1211 return (ret);
1213 /* Run instructions in FDE. */
1214 if (pc_req >= fde->fde_initloc) {
1215 ret = _dwarf_frame_run_inst(dbg, rt, fde->fde_inst,
1216 fde->fde_instlen, cie->cie_caf, cie->cie_daf,
1217 fde->fde_initloc, pc_req, &row_pc, error);
1218 if (ret != DW_DLE_NONE)
1219 return (ret);
1222 *ret_rt = rt;
1223 *ret_row_pc = row_pc;
1225 return (DW_DLE_NONE);
1228 void
1229 _dwarf_frame_cleanup(Dwarf_Debug dbg)
1231 Dwarf_Regtable3 *rt;
1233 assert(dbg != NULL && dbg->dbg_mode == DW_DLC_READ);
1235 if (dbg->dbg_internal_reg_table) {
1236 rt = dbg->dbg_internal_reg_table;
1237 free(rt->rt3_rules);
1238 free(rt);
1239 dbg->dbg_internal_reg_table = NULL;
1242 if (dbg->dbg_frame) {
1243 _dwarf_frame_section_cleanup(dbg->dbg_frame);
1244 dbg->dbg_frame = NULL;
1247 if (dbg->dbg_eh_frame) {
1248 _dwarf_frame_section_cleanup(dbg->dbg_eh_frame);
1249 dbg->dbg_eh_frame = NULL;
1254 _dwarf_frame_section_load(Dwarf_Debug dbg, Dwarf_Error *error)
1256 Dwarf_Section *ds;
1258 if ((ds = _dwarf_find_section(dbg, ".debug_frame")) != NULL) {
1259 return (_dwarf_frame_section_init(dbg, &dbg->dbg_frame,
1260 ds, 0, error));
1263 return (DW_DLE_NONE);
1267 _dwarf_frame_section_load_eh(Dwarf_Debug dbg, Dwarf_Error *error)
1269 Dwarf_Section *ds;
1271 if ((ds = _dwarf_find_section(dbg, ".eh_frame")) != NULL) {
1272 return (_dwarf_frame_section_init(dbg, &dbg->dbg_eh_frame,
1273 ds, 1, error));
1276 return (DW_DLE_NONE);
1279 void
1280 _dwarf_frame_params_init(Dwarf_Debug dbg)
1283 /* Initialise call frame related parameters. */
1284 dbg->dbg_frame_rule_table_size = DW_FRAME_LAST_REG_NUM;
1285 dbg->dbg_frame_rule_initial_value = DW_FRAME_REG_INITIAL_VALUE;
1286 dbg->dbg_frame_cfa_value = DW_FRAME_CFA_COL3;
1287 dbg->dbg_frame_same_value = DW_FRAME_SAME_VAL;
1288 dbg->dbg_frame_undefined_value = DW_FRAME_UNDEFINED_VAL;
1292 _dwarf_frame_interal_table_init(Dwarf_Debug dbg, Dwarf_Error *error)
1294 Dwarf_Regtable3 *rt;
1296 if (dbg->dbg_internal_reg_table != NULL)
1297 return (DW_DLE_NONE);
1299 /* Initialise internal register table. */
1300 if ((rt = calloc(1, sizeof(Dwarf_Regtable3))) == NULL) {
1301 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
1302 return (DW_DLE_MEMORY);
1305 rt->rt3_reg_table_size = dbg->dbg_frame_rule_table_size;
1306 if ((rt->rt3_rules = calloc(rt->rt3_reg_table_size,
1307 sizeof(Dwarf_Regtable_Entry3))) == NULL) {
1308 free(rt);
1309 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
1310 return (DW_DLE_MEMORY);
1313 dbg->dbg_internal_reg_table = rt;
1315 return (DW_DLE_NONE);
1318 #define _FDE_INST_INIT_SIZE 128
1321 _dwarf_frame_fde_add_inst(Dwarf_P_Fde fde, Dwarf_Small op, Dwarf_Unsigned val1,
1322 Dwarf_Unsigned val2, Dwarf_Error *error)
1324 Dwarf_P_Debug dbg;
1325 uint8_t high2, low6;
1326 int ret;
1328 #define ds fde
1329 #define ds_data fde_inst
1330 #define ds_cap fde_instcap
1331 #define ds_size fde_instlen
1333 assert(fde != NULL && fde->fde_dbg != NULL);
1334 dbg = fde->fde_dbg;
1336 if (fde->fde_inst == NULL) {
1337 fde->fde_instcap = _FDE_INST_INIT_SIZE;
1338 fde->fde_instlen = 0;
1339 if ((fde->fde_inst = malloc((size_t) fde->fde_instcap)) ==
1340 NULL) {
1341 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
1342 return (DW_DLE_MEMORY);
1345 assert(fde->fde_instcap != 0);
1347 RCHECK(WRITE_VALUE(op, 1));
1348 if (op == DW_CFA_nop)
1349 return (DW_DLE_NONE);
1351 high2 = op & 0xc0;
1352 low6 = op & 0x3f;
1354 if (high2 > 0) {
1355 switch (high2) {
1356 case DW_CFA_advance_loc:
1357 case DW_CFA_restore:
1358 break;
1359 case DW_CFA_offset:
1360 RCHECK(WRITE_ULEB128(val1));
1361 break;
1362 default:
1363 DWARF_SET_ERROR(dbg, error,
1364 DW_DLE_FRAME_INSTR_EXEC_ERROR);
1365 return (DW_DLE_FRAME_INSTR_EXEC_ERROR);
1367 return (DW_DLE_NONE);
1370 switch (low6) {
1371 case DW_CFA_set_loc:
1372 RCHECK(WRITE_VALUE(val1, dbg->dbg_pointer_size));
1373 break;
1374 case DW_CFA_advance_loc1:
1375 RCHECK(WRITE_VALUE(val1, 1));
1376 break;
1377 case DW_CFA_advance_loc2:
1378 RCHECK(WRITE_VALUE(val1, 2));
1379 break;
1380 case DW_CFA_advance_loc4:
1381 RCHECK(WRITE_VALUE(val1, 4));
1382 break;
1383 case DW_CFA_offset_extended:
1384 case DW_CFA_def_cfa:
1385 case DW_CFA_register:
1386 RCHECK(WRITE_ULEB128(val1));
1387 RCHECK(WRITE_ULEB128(val2));
1388 break;
1389 case DW_CFA_restore_extended:
1390 case DW_CFA_undefined:
1391 case DW_CFA_same_value:
1392 case DW_CFA_def_cfa_register:
1393 case DW_CFA_def_cfa_offset:
1394 RCHECK(WRITE_ULEB128(val1));
1395 break;
1396 case DW_CFA_remember_state:
1397 case DW_CFA_restore_state:
1398 break;
1399 default:
1400 DWARF_SET_ERROR(dbg, error, DW_DLE_FRAME_INSTR_EXEC_ERROR);
1401 return (DW_DLE_FRAME_INSTR_EXEC_ERROR);
1404 return (DW_DLE_NONE);
1406 gen_fail:
1407 return (ret);
1409 #undef ds
1410 #undef ds_data
1411 #undef ds_cap
1412 #undef ds_size
1415 static int
1416 _dwarf_frame_gen_cie(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_P_Cie cie,
1417 Dwarf_Error *error)
1419 Dwarf_Unsigned len;
1420 uint64_t offset;
1421 int ret;
1423 assert(dbg != NULL && ds != NULL && cie != NULL);
1425 cie->cie_offset = offset = ds->ds_size;
1426 cie->cie_length = 0;
1427 cie->cie_version = 1;
1429 /* Length placeholder. */
1430 RCHECK(WRITE_VALUE(cie->cie_length, 4));
1432 /* .debug_frame use CIE id ~0. */
1433 RCHECK(WRITE_VALUE(~0U, 4));
1435 /* .debug_frame version is 1. (DWARF2) */
1436 RCHECK(WRITE_VALUE(cie->cie_version, 1));
1438 /* Write augmentation, if present. */
1439 if (cie->cie_augment != NULL)
1440 RCHECK(WRITE_BLOCK(cie->cie_augment,
1441 strlen((char *) cie->cie_augment) + 1));
1442 else
1443 RCHECK(WRITE_VALUE(0, 1));
1445 /* Write caf, daf and ra. */
1446 RCHECK(WRITE_ULEB128(cie->cie_caf));
1447 RCHECK(WRITE_SLEB128(cie->cie_daf));
1448 RCHECK(WRITE_VALUE(cie->cie_ra, 1));
1450 /* Write initial instructions, if present. */
1451 if (cie->cie_initinst != NULL)
1452 RCHECK(WRITE_BLOCK(cie->cie_initinst, cie->cie_instlen));
1454 /* Add padding. */
1455 len = ds->ds_size - cie->cie_offset - 4;
1456 cie->cie_length = roundup(len, dbg->dbg_pointer_size);
1457 while (len++ < cie->cie_length)
1458 RCHECK(WRITE_VALUE(DW_CFA_nop, 1));
1460 /* Fill in the length field. */
1461 dbg->write(ds->ds_data, &offset, cie->cie_length, 4);
1463 return (DW_DLE_NONE);
1465 gen_fail:
1466 return (ret);
1469 static int
1470 _dwarf_frame_gen_fde(Dwarf_P_Debug dbg, Dwarf_P_Section ds,
1471 Dwarf_Rel_Section drs, Dwarf_P_Fde fde, Dwarf_Error *error)
1473 Dwarf_Unsigned len;
1474 uint64_t offset;
1475 int ret;
1477 assert(dbg != NULL && ds != NULL && drs != NULL);
1478 assert(fde != NULL && fde->fde_cie != NULL);
1480 fde->fde_offset = offset = ds->ds_size;
1481 fde->fde_length = 0;
1482 fde->fde_cieoff = fde->fde_cie->cie_offset;
1484 /* Length placeholder. */
1485 RCHECK(WRITE_VALUE(fde->fde_length, 4));
1487 /* Write CIE pointer. */
1488 RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc, 4,
1489 ds->ds_size, 0, fde->fde_cieoff, ".debug_frame", error));
1491 /* Write FDE initial location. */
1492 RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc,
1493 dbg->dbg_pointer_size, ds->ds_size, fde->fde_symndx,
1494 fde->fde_initloc, NULL, error));
1497 * Write FDE address range. Use a pair of relocation entries if
1498 * application provided end symbol index. Otherwise write the
1499 * length without assoicating any relocation info.
1501 if (fde->fde_esymndx > 0)
1502 RCHECK(_dwarf_reloc_entry_add_pair(dbg, drs, ds,
1503 dbg->dbg_pointer_size, ds->ds_size, fde->fde_symndx,
1504 fde->fde_esymndx, fde->fde_initloc, fde->fde_eoff, error));
1505 else
1506 RCHECK(WRITE_VALUE(fde->fde_adrange, dbg->dbg_pointer_size));
1508 /* Write FDE frame instructions. */
1509 RCHECK(WRITE_BLOCK(fde->fde_inst, fde->fde_instlen));
1511 /* Add padding. */
1512 len = ds->ds_size - fde->fde_offset - 4;
1513 fde->fde_length = roundup(len, dbg->dbg_pointer_size);
1514 while (len++ < fde->fde_length)
1515 RCHECK(WRITE_VALUE(DW_CFA_nop, 1));
1517 /* Fill in the length field. */
1518 dbg->write(ds->ds_data, &offset, fde->fde_length, 4);
1520 return (DW_DLE_NONE);
1522 gen_fail:
1523 return (ret);
1527 _dwarf_frame_gen(Dwarf_P_Debug dbg, Dwarf_Error *error)
1529 Dwarf_P_Section ds;
1530 Dwarf_Rel_Section drs;
1531 Dwarf_P_Cie cie;
1532 Dwarf_P_Fde fde;
1533 int ret;
1535 if (STAILQ_EMPTY(&dbg->dbgp_cielist))
1536 return (DW_DLE_NONE);
1538 /* Create .debug_frame section. */
1539 if ((ret = _dwarf_section_init(dbg, &ds, ".debug_frame", 0, error)) !=
1540 DW_DLE_NONE)
1541 goto gen_fail0;
1543 /* Create relocation section for .debug_frame */
1544 RCHECK(_dwarf_reloc_section_init(dbg, &drs, ds, error));
1546 /* Generate list of CIE. */
1547 STAILQ_FOREACH(cie, &dbg->dbgp_cielist, cie_next)
1548 RCHECK(_dwarf_frame_gen_cie(dbg, ds, cie, error));
1550 /* Generate list of FDE. */
1551 STAILQ_FOREACH(fde, &dbg->dbgp_fdelist, fde_next)
1552 RCHECK(_dwarf_frame_gen_fde(dbg, ds, drs, fde, error));
1554 /* Inform application the creation of .debug_frame ELF section. */
1555 RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error));
1557 /* Finalize relocation section for .debug_frame */
1558 RCHECK(_dwarf_reloc_section_finalize(dbg, drs, error));
1560 return (DW_DLE_NONE);
1562 gen_fail:
1563 _dwarf_reloc_section_free(dbg, &drs);
1565 gen_fail0:
1566 _dwarf_section_free(dbg, &ds);
1568 return (ret);
1571 void
1572 _dwarf_frame_pro_cleanup(Dwarf_P_Debug dbg)
1574 Dwarf_P_Cie cie, tcie;
1575 Dwarf_P_Fde fde, tfde;
1577 assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
1579 STAILQ_FOREACH_SAFE(cie, &dbg->dbgp_cielist, cie_next, tcie) {
1580 STAILQ_REMOVE(&dbg->dbgp_cielist, cie, _Dwarf_Cie, cie_next);
1581 if (cie->cie_augment)
1582 free(cie->cie_augment);
1583 if (cie->cie_initinst)
1584 free(cie->cie_initinst);
1585 free(cie);
1587 dbg->dbgp_cielen = 0;
1589 STAILQ_FOREACH_SAFE(fde, &dbg->dbgp_fdelist, fde_next, tfde) {
1590 STAILQ_REMOVE(&dbg->dbgp_fdelist, fde, _Dwarf_Fde, fde_next);
1591 if (fde->fde_inst != NULL)
1592 free(fde->fde_inst);
1593 free(fde);
1595 dbg->dbgp_fdelen = 0;