]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/elftoolchain/libdwarf/libdwarf_frame.c
Merge ^/head r296369 through r296409.
[FreeBSD/FreeBSD.git] / contrib / elftoolchain / libdwarf / libdwarf_frame.c
1 /*-
2  * Copyright (c) 2009-2011,2014 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
29 ELFTC_VCSID("$Id: libdwarf_frame.c 3106 2014-12-19 16:00:58Z kaiwang27 $");
30
31 static int
32 _dwarf_frame_find_cie(Dwarf_FrameSec fs, Dwarf_Unsigned offset,
33     Dwarf_Cie *ret_cie)
34 {
35         Dwarf_Cie cie;
36
37         STAILQ_FOREACH(cie, &fs->fs_cielist, cie_next) {
38                 if (cie->cie_offset == offset)
39                         break;
40         }
41
42         if (cie == NULL)
43                 return (DW_DLE_NO_ENTRY);
44
45         if (ret_cie != NULL)
46                 *ret_cie = cie;
47
48         return (DW_DLE_NONE);
49 }
50
51 static int
52 _dwarf_frame_read_lsb_encoded(Dwarf_Debug dbg, Dwarf_Cie cie, uint64_t *val,
53     uint8_t *data, uint64_t *offsetp, uint8_t encode, Dwarf_Addr pc,
54     Dwarf_Error *error)
55 {
56         uint8_t application;
57
58         if (encode == DW_EH_PE_omit)
59                 return (DW_DLE_NONE);
60
61         application = encode & 0xf0;
62         encode &= 0x0f;
63
64         switch (encode) {
65         case DW_EH_PE_absptr:
66                 *val = dbg->read(data, offsetp, cie->cie_addrsize);
67                 break;
68         case DW_EH_PE_uleb128:
69                 *val = _dwarf_read_uleb128(data, offsetp);
70                 break;
71         case DW_EH_PE_udata2:
72                 *val = dbg->read(data, offsetp, 2);
73                 break;
74         case DW_EH_PE_udata4:
75                 *val = dbg->read(data, offsetp, 4);
76                 break;
77         case DW_EH_PE_udata8:
78                 *val = dbg->read(data, offsetp, 8);
79                 break;
80         case DW_EH_PE_sleb128:
81                 *val = _dwarf_read_sleb128(data, offsetp);
82                 break;
83         case DW_EH_PE_sdata2:
84                 *val = (int16_t) dbg->read(data, offsetp, 2);
85                 break;
86         case DW_EH_PE_sdata4:
87                 *val = (int32_t) dbg->read(data, offsetp, 4);
88                 break;
89         case DW_EH_PE_sdata8:
90                 *val = dbg->read(data, offsetp, 8);
91                 break;
92         default:
93                 DWARF_SET_ERROR(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
94                 return (DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
95         }
96
97         if (application == DW_EH_PE_pcrel) {
98                 /*
99                  * Value is relative to .eh_frame section virtual addr.
100                  */
101                 switch (encode) {
102                 case DW_EH_PE_uleb128:
103                 case DW_EH_PE_udata2:
104                 case DW_EH_PE_udata4:
105                 case DW_EH_PE_udata8:
106                         *val += pc;
107                         break;
108                 case DW_EH_PE_sleb128:
109                 case DW_EH_PE_sdata2:
110                 case DW_EH_PE_sdata4:
111                 case DW_EH_PE_sdata8:
112                         *val = pc + (int64_t) *val;
113                         break;
114                 default:
115                         /* DW_EH_PE_absptr is absolute value. */
116                         break;
117                 }
118         }
119
120         /* XXX Applications other than DW_EH_PE_pcrel are not handled. */
121
122         return (DW_DLE_NONE);
123 }
124
125 static int
126 _dwarf_frame_parse_lsb_cie_augment(Dwarf_Debug dbg, Dwarf_Cie cie,
127     Dwarf_Error *error)
128 {
129         uint8_t *aug_p, *augdata_p;
130         uint64_t val, offset;
131         uint8_t encode;
132         int ret;
133
134         assert(cie->cie_augment != NULL && *cie->cie_augment == 'z');
135
136         /*
137          * Here we're only interested in the presence of augment 'R'
138          * and associated CIE augment data, which describes the
139          * encoding scheme of FDE PC begin and range.
140          */
141         aug_p = &cie->cie_augment[1];
142         augdata_p = cie->cie_augdata;
143         while (*aug_p != '\0') {
144                 switch (*aug_p) {
145                 case 'L':
146                         /* Skip one augment in augment data. */
147                         augdata_p++;
148                         break;
149                 case 'P':
150                         /* Skip two augments in augment data. */
151                         encode = *augdata_p++;
152                         offset = 0;
153                         ret = _dwarf_frame_read_lsb_encoded(dbg, cie, &val,
154                             augdata_p, &offset, encode, 0, error);
155                         if (ret != DW_DLE_NONE)
156                                 return (ret);
157                         augdata_p += offset;
158                         break;
159                 case 'R':
160                         cie->cie_fde_encode = *augdata_p++;
161                         break;
162                 default:
163                         DWARF_SET_ERROR(dbg, error,
164                             DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
165                         return (DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
166                 }
167                 aug_p++;
168         }
169
170         return (DW_DLE_NONE);
171 }
172
173 static int
174 _dwarf_frame_add_cie(Dwarf_Debug dbg, Dwarf_FrameSec fs, Dwarf_Section *ds,
175     Dwarf_Unsigned *off, Dwarf_Cie *ret_cie, Dwarf_Error *error)
176 {
177         Dwarf_Cie cie;
178         uint64_t length;
179         int dwarf_size, ret;
180         char *p;
181
182         /* Check if we already added this CIE. */
183         if (_dwarf_frame_find_cie(fs, *off, &cie) != DW_DLE_NO_ENTRY) {
184                 *off += cie->cie_length + 4;
185                 return (DW_DLE_NONE);
186         }
187
188         if ((cie = calloc(1, sizeof(struct _Dwarf_Cie))) == NULL) {
189                 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
190                 return (DW_DLE_MEMORY);
191         }
192         STAILQ_INSERT_TAIL(&fs->fs_cielist, cie, cie_next);
193
194         cie->cie_dbg = dbg;
195         cie->cie_index = fs->fs_cielen;
196         cie->cie_offset = *off;
197
198         length = dbg->read(ds->ds_data, off, 4);
199         if (length == 0xffffffff) {
200                 dwarf_size = 8;
201                 length = dbg->read(ds->ds_data, off, 8);
202         } else
203                 dwarf_size = 4;
204
205         if (length > ds->ds_size - *off) {
206                 DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
207                 return (DW_DLE_DEBUG_FRAME_LENGTH_BAD);
208         }
209
210         (void) dbg->read(ds->ds_data, off, dwarf_size); /* Skip CIE id. */
211         cie->cie_length = length;
212
213         cie->cie_version = dbg->read(ds->ds_data, off, 1);
214         if (cie->cie_version != 1 && cie->cie_version != 3 &&
215             cie->cie_version != 4) {
216                 DWARF_SET_ERROR(dbg, error, DW_DLE_FRAME_VERSION_BAD);
217                 return (DW_DLE_FRAME_VERSION_BAD);
218         }
219
220         cie->cie_augment = ds->ds_data + *off;
221         p = (char *) ds->ds_data;
222         while (p[(*off)++] != '\0')
223                 ;
224
225         /* We only recognize normal .dwarf_frame and GNU .eh_frame sections. */
226         if (*cie->cie_augment != 0 && *cie->cie_augment != 'z') {
227                 *off = cie->cie_offset + ((dwarf_size == 4) ? 4 : 12) +
228                     cie->cie_length;
229                 return (DW_DLE_NONE);
230         }
231
232         /* Optional EH Data field for .eh_frame section. */
233         if (strstr((char *)cie->cie_augment, "eh") != NULL)
234                 cie->cie_ehdata = dbg->read(ds->ds_data, off,
235                     dbg->dbg_pointer_size);
236
237         /* DWARF4 added "address_size" and "segment_size". */
238         if (cie->cie_version == 4) {
239                 cie->cie_addrsize = dbg->read(ds->ds_data, off, 1);
240                 cie->cie_segmentsize = dbg->read(ds->ds_data, off, 1);
241         } else {
242                 /*
243                  * Otherwise (DWARF[23]) we just set CIE addrsize to the
244                  * debug context pointer size.
245                  */
246                 cie->cie_addrsize = dbg->dbg_pointer_size;
247         }
248
249         cie->cie_caf = _dwarf_read_uleb128(ds->ds_data, off);
250         cie->cie_daf = _dwarf_read_sleb128(ds->ds_data, off);
251
252         /* Return address register. */
253         if (cie->cie_version == 1)
254                 cie->cie_ra = dbg->read(ds->ds_data, off, 1);
255         else
256                 cie->cie_ra = _dwarf_read_uleb128(ds->ds_data, off);
257
258         /* Optional CIE augmentation data for .eh_frame section. */
259         if (*cie->cie_augment == 'z') {
260                 cie->cie_auglen = _dwarf_read_uleb128(ds->ds_data, off);
261                 cie->cie_augdata = ds->ds_data + *off;
262                 *off += cie->cie_auglen;
263                 /*
264                  * XXX Use DW_EH_PE_absptr for default FDE PC start/range,
265                  * in case _dwarf_frame_parse_lsb_cie_augment fails to
266                  * find out the real encode.
267                  */
268                 cie->cie_fde_encode = DW_EH_PE_absptr;
269                 ret = _dwarf_frame_parse_lsb_cie_augment(dbg, cie, error);
270                 if (ret != DW_DLE_NONE)
271                         return (ret);
272         }
273
274         /* CIE Initial instructions. */
275         cie->cie_initinst = ds->ds_data + *off;
276         if (dwarf_size == 4)
277                 cie->cie_instlen = cie->cie_offset + 4 + length - *off;
278         else
279                 cie->cie_instlen = cie->cie_offset + 12 + length - *off;
280
281         *off += cie->cie_instlen;
282
283 #ifdef FRAME_DEBUG
284         printf("cie:\n");
285         printf("\tcie_version=%u cie_offset=%ju cie_length=%ju cie_augment=%s"
286             " cie_instlen=%ju cie->cie_caf=%ju cie->cie_daf=%jd off=%ju\n",
287             cie->cie_version, cie->cie_offset, cie->cie_length,
288             (char *)cie->cie_augment, cie->cie_instlen, cie->cie_caf,
289             cie->cie_daf, *off);
290 #endif
291
292         if (ret_cie != NULL)
293                 *ret_cie = cie;
294
295         fs->fs_cielen++;
296
297         return (DW_DLE_NONE);
298 }
299
300 static int
301 _dwarf_frame_add_fde(Dwarf_Debug dbg, Dwarf_FrameSec fs, Dwarf_Section *ds,
302     Dwarf_Unsigned *off, int eh_frame, Dwarf_Error *error)
303 {
304         Dwarf_Cie cie;
305         Dwarf_Fde fde;
306         Dwarf_Unsigned cieoff;
307         uint64_t length, val;
308         int dwarf_size, ret;
309
310         if ((fde = calloc(1, sizeof(struct _Dwarf_Fde))) == NULL) {
311                 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
312                 return (DW_DLE_MEMORY);
313         }
314         STAILQ_INSERT_TAIL(&fs->fs_fdelist, fde, fde_next);
315
316         fde->fde_dbg = dbg;
317         fde->fde_fs = fs;
318         fde->fde_addr = ds->ds_data + *off;
319         fde->fde_offset = *off;
320
321         length = dbg->read(ds->ds_data, off, 4);
322         if (length == 0xffffffff) {
323                 dwarf_size = 8;
324                 length = dbg->read(ds->ds_data, off, 8);
325         } else
326                 dwarf_size = 4;
327
328         if (length > ds->ds_size - *off) {
329                 DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
330                 return (DW_DLE_DEBUG_FRAME_LENGTH_BAD);
331         }
332
333         fde->fde_length = length;
334
335         if (eh_frame) {
336                 fde->fde_cieoff = dbg->read(ds->ds_data, off, 4);
337                 cieoff = *off - (4 + fde->fde_cieoff);
338                 /* This delta should never be 0. */
339                 if (cieoff == fde->fde_offset) {
340                         DWARF_SET_ERROR(dbg, error, DW_DLE_NO_CIE_FOR_FDE);
341                         return (DW_DLE_NO_CIE_FOR_FDE);
342                 }
343         } else {
344                 fde->fde_cieoff = dbg->read(ds->ds_data, off, dwarf_size);
345                 cieoff = fde->fde_cieoff;
346         }
347
348         if (_dwarf_frame_find_cie(fs, cieoff, &cie) ==
349             DW_DLE_NO_ENTRY) {
350                 ret = _dwarf_frame_add_cie(dbg, fs, ds, &cieoff, &cie,
351                     error);
352                 if (ret != DW_DLE_NONE)
353                         return (ret);
354         }
355         fde->fde_cie = cie;
356         if (eh_frame) {
357                 /*
358                  * The FDE PC start/range for .eh_frame is encoded according
359                  * to the LSB spec's extension to DWARF2.
360                  */
361                 ret = _dwarf_frame_read_lsb_encoded(dbg, cie, &val,
362                     ds->ds_data, off, cie->cie_fde_encode, ds->ds_addr + *off,
363                     error);
364                 if (ret != DW_DLE_NONE)
365                         return (ret);
366                 fde->fde_initloc = val;
367                 /*
368                  * FDE PC range should not be relative value to anything.
369                  * So pass 0 for pc value.
370                  */
371                 ret = _dwarf_frame_read_lsb_encoded(dbg, cie, &val,
372                     ds->ds_data, off, cie->cie_fde_encode, 0, error);
373                 if (ret != DW_DLE_NONE)
374                         return (ret);
375                 fde->fde_adrange = val;
376         } else {
377                 fde->fde_initloc = dbg->read(ds->ds_data, off,
378                     cie->cie_addrsize);
379                 fde->fde_adrange = dbg->read(ds->ds_data, off,
380                     cie->cie_addrsize);
381         }
382
383         /* Optional FDE augmentation data for .eh_frame section. (ignored) */
384         if (eh_frame && *cie->cie_augment == 'z') {
385                 fde->fde_auglen = _dwarf_read_uleb128(ds->ds_data, off);
386                 fde->fde_augdata = ds->ds_data + *off;
387                 *off += fde->fde_auglen;
388         }
389
390         fde->fde_inst = ds->ds_data + *off;
391         if (dwarf_size == 4)
392                 fde->fde_instlen = fde->fde_offset + 4 + length - *off;
393         else
394                 fde->fde_instlen = fde->fde_offset + 12 + length - *off;
395
396         *off += fde->fde_instlen;
397
398 #ifdef FRAME_DEBUG
399         printf("fde:");
400         if (eh_frame)
401                 printf("(eh_frame)");
402         putchar('\n');
403         printf("\tfde_offset=%ju fde_length=%ju fde_cieoff=%ju"
404             " fde_instlen=%ju off=%ju\n", fde->fde_offset, fde->fde_length,
405             fde->fde_cieoff, fde->fde_instlen, *off);
406 #endif
407
408         fs->fs_fdelen++;
409
410         return (DW_DLE_NONE);
411 }
412
413 static void
414 _dwarf_frame_section_cleanup(Dwarf_FrameSec fs)
415 {
416         Dwarf_Cie cie, tcie;
417         Dwarf_Fde fde, tfde;
418
419         STAILQ_FOREACH_SAFE(cie, &fs->fs_cielist, cie_next, tcie) {
420                 STAILQ_REMOVE(&fs->fs_cielist, cie, _Dwarf_Cie, cie_next);
421                 free(cie);
422         }
423
424         STAILQ_FOREACH_SAFE(fde, &fs->fs_fdelist, fde_next, tfde) {
425                 STAILQ_REMOVE(&fs->fs_fdelist, fde, _Dwarf_Fde, fde_next);
426                 free(fde);
427         }
428
429         if (fs->fs_ciearray != NULL)
430                 free(fs->fs_ciearray);
431         if (fs->fs_fdearray != NULL)
432                 free(fs->fs_fdearray);
433
434         free(fs);
435 }
436
437 static int
438 _dwarf_frame_section_init(Dwarf_Debug dbg, Dwarf_FrameSec *frame_sec,
439     Dwarf_Section *ds, int eh_frame, Dwarf_Error *error)
440 {
441         Dwarf_FrameSec fs;
442         Dwarf_Cie cie;
443         Dwarf_Fde fde;
444         uint64_t length, offset, cie_id, entry_off;
445         int dwarf_size, i, ret;
446
447         assert(frame_sec != NULL);
448         assert(*frame_sec == NULL);
449
450         if ((fs = calloc(1, sizeof(struct _Dwarf_FrameSec))) == NULL) {
451                 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
452                 return (DW_DLE_MEMORY);
453         }
454         STAILQ_INIT(&fs->fs_cielist);
455         STAILQ_INIT(&fs->fs_fdelist);
456
457         offset = 0;
458         while (offset < ds->ds_size) {
459                 entry_off = offset;
460                 length = dbg->read(ds->ds_data, &offset, 4);
461                 if (length == 0xffffffff) {
462                         dwarf_size = 8;
463                         length = dbg->read(ds->ds_data, &offset, 8);
464                 } else
465                         dwarf_size = 4;
466
467                 if (length > ds->ds_size - offset ||
468                     (length == 0 && !eh_frame)) {
469                         DWARF_SET_ERROR(dbg, error,
470                             DW_DLE_DEBUG_FRAME_LENGTH_BAD);
471                         return (DW_DLE_DEBUG_FRAME_LENGTH_BAD);
472                 }
473
474                 /* Check terminator for .eh_frame */
475                 if (eh_frame && length == 0)
476                         break;
477
478                 cie_id = dbg->read(ds->ds_data, &offset, dwarf_size);
479
480                 if (eh_frame) {
481                         /* GNU .eh_frame use CIE id 0. */
482                         if (cie_id == 0)
483                                 ret = _dwarf_frame_add_cie(dbg, fs, ds,
484                                     &entry_off, NULL, error);
485                         else
486                                 ret = _dwarf_frame_add_fde(dbg, fs, ds,
487                                     &entry_off, 1, error);
488                 } else {
489                         /* .dwarf_frame use CIE id ~0 */
490                         if ((dwarf_size == 4 && cie_id == ~0U) ||
491                             (dwarf_size == 8 && cie_id == ~0ULL))
492                                 ret = _dwarf_frame_add_cie(dbg, fs, ds,
493                                     &entry_off, NULL, error);
494                         else
495                                 ret = _dwarf_frame_add_fde(dbg, fs, ds,
496                                     &entry_off, 0, error);
497                 }
498
499                 if (ret != DW_DLE_NONE)
500                         goto fail_cleanup;
501
502                 offset = entry_off;
503         }
504
505         /* Create CIE array. */
506         if (fs->fs_cielen > 0) {
507                 if ((fs->fs_ciearray = malloc(sizeof(Dwarf_Cie) *
508                     fs->fs_cielen)) == NULL) {
509                         ret = DW_DLE_MEMORY;
510                         DWARF_SET_ERROR(dbg, error, ret);
511                         goto fail_cleanup;
512                 }
513                 i = 0;
514                 STAILQ_FOREACH(cie, &fs->fs_cielist, cie_next) {
515                         fs->fs_ciearray[i++] = cie;
516                 }
517                 assert((Dwarf_Unsigned)i == fs->fs_cielen);
518         }
519
520         /* Create FDE array. */
521         if (fs->fs_fdelen > 0) {
522                 if ((fs->fs_fdearray = malloc(sizeof(Dwarf_Fde) *
523                     fs->fs_fdelen)) == NULL) {
524                         ret = DW_DLE_MEMORY;
525                         DWARF_SET_ERROR(dbg, error, ret);
526                         goto fail_cleanup;
527                 }
528                 i = 0;
529                 STAILQ_FOREACH(fde, &fs->fs_fdelist, fde_next) {
530                         fs->fs_fdearray[i++] = fde;
531                 }
532                 assert((Dwarf_Unsigned)i == fs->fs_fdelen);
533         }
534
535         *frame_sec = fs;
536
537         return (DW_DLE_NONE);
538
539 fail_cleanup:
540
541         _dwarf_frame_section_cleanup(fs);
542
543         return (ret);
544 }
545
546 static int
547 _dwarf_frame_run_inst(Dwarf_Debug dbg, Dwarf_Regtable3 *rt, uint8_t addr_size,
548     uint8_t *insts, Dwarf_Unsigned len, Dwarf_Unsigned caf, Dwarf_Signed daf,
549     Dwarf_Addr pc, Dwarf_Addr pc_req, Dwarf_Addr *row_pc, Dwarf_Error *error)
550 {
551         Dwarf_Regtable3 *init_rt, *saved_rt;
552         uint8_t *p, *pe;
553         uint8_t high2, low6;
554         uint64_t reg, reg2, uoff, soff;
555         int ret;
556
557 #define CFA     rt->rt3_cfa_rule
558 #define INITCFA init_rt->rt3_cfa_rule
559 #define RL      rt->rt3_rules
560 #define INITRL  init_rt->rt3_rules
561
562 #define CHECK_TABLE_SIZE(x)                                             \
563         do {                                                            \
564                 if ((x) >= rt->rt3_reg_table_size) {                    \
565                         DWARF_SET_ERROR(dbg, error,                     \
566                             DW_DLE_DF_REG_NUM_TOO_HIGH);                \
567                         ret = DW_DLE_DF_REG_NUM_TOO_HIGH;               \
568                         goto program_done;                              \
569                 }                                                       \
570         } while(0)
571
572 #ifdef FRAME_DEBUG
573         printf("frame_run_inst: (caf=%ju, daf=%jd)\n", caf, daf);
574 #endif
575
576         ret = DW_DLE_NONE;
577         init_rt = saved_rt = NULL;
578         *row_pc = pc;
579
580         /* Save a copy of the table as initial state. */
581         _dwarf_frame_regtable_copy(dbg, &init_rt, rt, error);
582
583         p = insts;
584         pe = p + len;
585
586         while (p < pe) {
587
588 #ifdef FRAME_DEBUG
589                 printf("p=%p pe=%p pc=%#jx pc_req=%#jx\n", p, pe, pc, pc_req);
590 #endif
591
592                 if (*p == DW_CFA_nop) {
593 #ifdef FRAME_DEBUG
594                         printf("DW_CFA_nop\n");
595 #endif
596                         p++;
597                         continue;
598                 }
599
600                 high2 = *p & 0xc0;
601                 low6 = *p & 0x3f;
602                 p++;
603
604                 if (high2 > 0) {
605                         switch (high2) {
606                         case DW_CFA_advance_loc:
607                                 pc += low6 * caf;
608 #ifdef FRAME_DEBUG
609                                 printf("DW_CFA_advance_loc(%#jx(%u))\n", pc,
610                                     low6);
611 #endif
612                                 if (pc_req < pc)
613                                         goto program_done;
614                                 break;
615                         case DW_CFA_offset:
616                                 *row_pc = pc;
617                                 CHECK_TABLE_SIZE(low6);
618                                 RL[low6].dw_offset_relevant = 1;
619                                 RL[low6].dw_value_type = DW_EXPR_OFFSET;
620                                 RL[low6].dw_regnum = dbg->dbg_frame_cfa_value;
621                                 RL[low6].dw_offset_or_block_len =
622                                     _dwarf_decode_uleb128(&p) * daf;
623 #ifdef FRAME_DEBUG
624                                 printf("DW_CFA_offset(%jd)\n",
625                                     RL[low6].dw_offset_or_block_len);
626 #endif
627                                 break;
628                         case DW_CFA_restore:
629                                 *row_pc = pc;
630                                 CHECK_TABLE_SIZE(low6);
631                                 memcpy(&RL[low6], &INITRL[low6],
632                                     sizeof(Dwarf_Regtable_Entry3));
633 #ifdef FRAME_DEBUG
634                                 printf("DW_CFA_restore(%u)\n", low6);
635 #endif
636                                 break;
637                         default:
638                                 DWARF_SET_ERROR(dbg, error,
639                                     DW_DLE_FRAME_INSTR_EXEC_ERROR);
640                                 ret = DW_DLE_FRAME_INSTR_EXEC_ERROR;
641                                 goto program_done;
642                         }
643
644                         continue;
645                 }
646
647                 switch (low6) {
648                 case DW_CFA_set_loc:
649                         pc = dbg->decode(&p, addr_size);
650 #ifdef FRAME_DEBUG
651                         printf("DW_CFA_set_loc(pc=%#jx)\n", pc);
652 #endif
653                         if (pc_req < pc)
654                                 goto program_done;
655                         break;
656                 case DW_CFA_advance_loc1:
657                         pc += dbg->decode(&p, 1) * caf;
658 #ifdef FRAME_DEBUG
659                         printf("DW_CFA_set_loc1(pc=%#jx)\n", pc);
660 #endif
661                         if (pc_req < pc)
662                                 goto program_done;
663                         break;
664                 case DW_CFA_advance_loc2:
665                         pc += dbg->decode(&p, 2) * caf;
666 #ifdef FRAME_DEBUG
667                         printf("DW_CFA_set_loc2(pc=%#jx)\n", pc);
668 #endif
669                         if (pc_req < pc)
670                                 goto program_done;
671                         break;
672                 case DW_CFA_advance_loc4:
673                         pc += dbg->decode(&p, 4) * caf;
674 #ifdef FRAME_DEBUG
675                         printf("DW_CFA_set_loc4(pc=%#jx)\n", pc);
676 #endif
677                         if (pc_req < pc)
678                                 goto program_done;
679                         break;
680                 case DW_CFA_offset_extended:
681                         *row_pc = pc;
682                         reg = _dwarf_decode_uleb128(&p);
683                         uoff = _dwarf_decode_uleb128(&p);
684                         CHECK_TABLE_SIZE(reg);
685                         RL[reg].dw_offset_relevant = 1;
686                         RL[reg].dw_value_type = DW_EXPR_OFFSET;
687                         RL[reg].dw_regnum = dbg->dbg_frame_cfa_value;
688                         RL[reg].dw_offset_or_block_len = uoff * daf;
689 #ifdef FRAME_DEBUG
690                         printf("DW_CFA_offset_extended(reg=%ju,uoff=%ju)\n",
691                             reg, uoff);
692 #endif
693                         break;
694                 case DW_CFA_restore_extended:
695                         *row_pc = pc;
696                         reg = _dwarf_decode_uleb128(&p);
697                         CHECK_TABLE_SIZE(reg);
698                         memcpy(&RL[reg], &INITRL[reg],
699                             sizeof(Dwarf_Regtable_Entry3));
700 #ifdef FRAME_DEBUG
701                         printf("DW_CFA_restore_extended(%ju)\n", reg);
702 #endif
703                         break;
704                 case DW_CFA_undefined:
705                         *row_pc = pc;
706                         reg = _dwarf_decode_uleb128(&p);
707                         CHECK_TABLE_SIZE(reg);
708                         RL[reg].dw_offset_relevant = 0;
709                         RL[reg].dw_regnum = dbg->dbg_frame_undefined_value;
710 #ifdef FRAME_DEBUG
711                         printf("DW_CFA_undefined(%ju)\n", reg);
712 #endif
713                         break;
714                 case DW_CFA_same_value:
715                         reg = _dwarf_decode_uleb128(&p);
716                         CHECK_TABLE_SIZE(reg);
717                         RL[reg].dw_offset_relevant = 0;
718                         RL[reg].dw_regnum = dbg->dbg_frame_same_value;
719 #ifdef FRAME_DEBUG
720                         printf("DW_CFA_same_value(%ju)\n", reg);
721 #endif
722                         break;
723                 case DW_CFA_register:
724                         *row_pc = pc;
725                         reg = _dwarf_decode_uleb128(&p);
726                         reg2 = _dwarf_decode_uleb128(&p);
727                         CHECK_TABLE_SIZE(reg);
728                         RL[reg].dw_offset_relevant = 0;
729                         RL[reg].dw_regnum = reg2;
730 #ifdef FRAME_DEBUG
731                         printf("DW_CFA_register(reg=%ju,reg2=%ju)\n", reg,
732                             reg2);
733 #endif
734                         break;
735                 case DW_CFA_remember_state:
736                         _dwarf_frame_regtable_copy(dbg, &saved_rt, rt, error);
737 #ifdef FRAME_DEBUG
738                         printf("DW_CFA_remember_state\n");
739 #endif
740                         break;
741                 case DW_CFA_restore_state:
742                         *row_pc = pc;
743                         _dwarf_frame_regtable_copy(dbg, &rt, saved_rt, error);
744 #ifdef FRAME_DEBUG
745                         printf("DW_CFA_restore_state\n");
746 #endif
747                         break;
748                 case DW_CFA_def_cfa:
749                         *row_pc = pc;
750                         reg = _dwarf_decode_uleb128(&p);
751                         uoff = _dwarf_decode_uleb128(&p);
752                         CFA.dw_offset_relevant = 1;
753                         CFA.dw_value_type = DW_EXPR_OFFSET;
754                         CFA.dw_regnum = reg;
755                         CFA.dw_offset_or_block_len = uoff;
756 #ifdef FRAME_DEBUG
757                         printf("DW_CFA_def_cfa(reg=%ju,uoff=%ju)\n", reg, uoff);
758 #endif
759                         break;
760                 case DW_CFA_def_cfa_register:
761                         *row_pc = pc;
762                         reg = _dwarf_decode_uleb128(&p);
763                         CFA.dw_regnum = reg;
764                         /*
765                          * Note that DW_CFA_def_cfa_register change the CFA
766                          * rule register while keep the old offset. So we
767                          * should not touch the CFA.dw_offset_relevant flag
768                          * here.
769                          */
770 #ifdef FRAME_DEBUG
771                         printf("DW_CFA_def_cfa_register(%ju)\n", reg);
772 #endif
773                         break;
774                 case DW_CFA_def_cfa_offset:
775                         *row_pc = pc;
776                         uoff = _dwarf_decode_uleb128(&p);
777                         CFA.dw_offset_relevant = 1;
778                         CFA.dw_value_type = DW_EXPR_OFFSET;
779                         CFA.dw_offset_or_block_len = uoff;
780 #ifdef FRAME_DEBUG
781                         printf("DW_CFA_def_cfa_offset(%ju)\n", uoff);
782 #endif
783                         break;
784                 case DW_CFA_def_cfa_expression:
785                         *row_pc = pc;
786                         CFA.dw_offset_relevant = 0;
787                         CFA.dw_value_type = DW_EXPR_EXPRESSION;
788                         CFA.dw_offset_or_block_len = _dwarf_decode_uleb128(&p);
789                         CFA.dw_block_ptr = p;
790                         p += CFA.dw_offset_or_block_len;
791 #ifdef FRAME_DEBUG
792                         printf("DW_CFA_def_cfa_expression\n");
793 #endif
794                         break;
795                 case DW_CFA_expression:
796                         *row_pc = pc;
797                         reg = _dwarf_decode_uleb128(&p);
798                         CHECK_TABLE_SIZE(reg);
799                         RL[reg].dw_offset_relevant = 0;
800                         RL[reg].dw_value_type = DW_EXPR_EXPRESSION;
801                         RL[reg].dw_offset_or_block_len =
802                             _dwarf_decode_uleb128(&p);
803                         RL[reg].dw_block_ptr = p;
804                         p += RL[reg].dw_offset_or_block_len;
805 #ifdef FRAME_DEBUG
806                         printf("DW_CFA_expression\n");
807 #endif
808                         break;
809                 case DW_CFA_offset_extended_sf:
810                         *row_pc = pc;
811                         reg = _dwarf_decode_uleb128(&p);
812                         soff = _dwarf_decode_sleb128(&p);
813                         CHECK_TABLE_SIZE(reg);
814                         RL[reg].dw_offset_relevant = 1;
815                         RL[reg].dw_value_type = DW_EXPR_OFFSET;
816                         RL[reg].dw_regnum = dbg->dbg_frame_cfa_value;
817                         RL[reg].dw_offset_or_block_len = soff * daf;
818 #ifdef FRAME_DEBUG
819                         printf("DW_CFA_offset_extended_sf(reg=%ju,soff=%jd)\n",
820                             reg, soff);
821 #endif
822                         break;
823                 case DW_CFA_def_cfa_sf:
824                         *row_pc = pc;
825                         reg = _dwarf_decode_uleb128(&p);
826                         soff = _dwarf_decode_sleb128(&p);
827                         CFA.dw_offset_relevant = 1;
828                         CFA.dw_value_type = DW_EXPR_OFFSET;
829                         CFA.dw_regnum = reg;
830                         CFA.dw_offset_or_block_len = soff * daf;
831 #ifdef FRAME_DEBUG
832                         printf("DW_CFA_def_cfa_sf(reg=%ju,soff=%jd)\n", reg,
833                             soff);
834 #endif
835                         break;
836                 case DW_CFA_def_cfa_offset_sf:
837                         *row_pc = pc;
838                         soff = _dwarf_decode_sleb128(&p);
839                         CFA.dw_offset_relevant = 1;
840                         CFA.dw_value_type = DW_EXPR_OFFSET;
841                         CFA.dw_offset_or_block_len = soff * daf;
842 #ifdef FRAME_DEBUG
843                         printf("DW_CFA_def_cfa_offset_sf(soff=%jd)\n", soff);
844 #endif
845                         break;
846                 case DW_CFA_val_offset:
847                         *row_pc = pc;
848                         reg = _dwarf_decode_uleb128(&p);
849                         uoff = _dwarf_decode_uleb128(&p);
850                         CHECK_TABLE_SIZE(reg);
851                         RL[reg].dw_offset_relevant = 1;
852                         RL[reg].dw_value_type = DW_EXPR_VAL_OFFSET;
853                         RL[reg].dw_regnum = dbg->dbg_frame_cfa_value;
854                         RL[reg].dw_offset_or_block_len = uoff * daf;
855 #ifdef FRAME_DEBUG
856                         printf("DW_CFA_val_offset(reg=%ju,uoff=%ju)\n", reg,
857                             uoff);
858 #endif
859                         break;
860                 case DW_CFA_val_offset_sf:
861                         *row_pc = pc;
862                         reg = _dwarf_decode_uleb128(&p);
863                         soff = _dwarf_decode_sleb128(&p);
864                         CHECK_TABLE_SIZE(reg);
865                         RL[reg].dw_offset_relevant = 1;
866                         RL[reg].dw_value_type = DW_EXPR_VAL_OFFSET;
867                         RL[reg].dw_regnum = dbg->dbg_frame_cfa_value;
868                         RL[reg].dw_offset_or_block_len = soff * daf;
869 #ifdef FRAME_DEBUG
870                         printf("DW_CFA_val_offset_sf(reg=%ju,soff=%jd)\n", reg,
871                             soff);
872 #endif
873                         break;
874                 case DW_CFA_val_expression:
875                         *row_pc = pc;
876                         reg = _dwarf_decode_uleb128(&p);
877                         CHECK_TABLE_SIZE(reg);
878                         RL[reg].dw_offset_relevant = 0;
879                         RL[reg].dw_value_type = DW_EXPR_VAL_EXPRESSION;
880                         RL[reg].dw_offset_or_block_len =
881                             _dwarf_decode_uleb128(&p);
882                         RL[reg].dw_block_ptr = p;
883                         p += RL[reg].dw_offset_or_block_len;
884 #ifdef FRAME_DEBUG
885                         printf("DW_CFA_val_expression\n");
886 #endif
887                         break;
888                 default:
889                         DWARF_SET_ERROR(dbg, error,
890                             DW_DLE_FRAME_INSTR_EXEC_ERROR);
891                         ret = DW_DLE_FRAME_INSTR_EXEC_ERROR;
892                         goto program_done;
893                 }
894         }
895
896 program_done:
897
898         free(init_rt->rt3_rules);
899         free(init_rt);
900         if (saved_rt) {
901                 free(saved_rt->rt3_rules);
902                 free(saved_rt);
903         }
904
905         return (ret);
906
907 #undef  CFA
908 #undef  INITCFA
909 #undef  RL
910 #undef  INITRL
911 #undef  CHECK_TABLE_SIZE
912 }
913
914 static int
915 _dwarf_frame_convert_inst(Dwarf_Debug dbg, uint8_t addr_size, uint8_t *insts,
916     Dwarf_Unsigned len, Dwarf_Unsigned *count, Dwarf_Frame_Op *fop,
917     Dwarf_Frame_Op3 *fop3, Dwarf_Error *error)
918 {
919         uint8_t *p, *pe;
920         uint8_t high2, low6;
921         uint64_t reg, reg2, uoff, soff, blen;
922
923 #define SET_BASE_OP(x)                                          \
924         do {                                                    \
925                 if (fop != NULL)                                \
926                         fop[*count].fp_base_op = (x) >> 6;      \
927                 if (fop3 != NULL)                               \
928                         fop3[*count].fp_base_op = (x) >> 6;     \
929         } while(0)
930
931 #define SET_EXTENDED_OP(x)                                      \
932         do {                                                    \
933                 if (fop != NULL)                                \
934                         fop[*count].fp_extended_op = (x);       \
935                 if (fop3 != NULL)                               \
936                         fop3[*count].fp_extended_op = (x);      \
937         } while(0)
938
939 #define SET_REGISTER(x)                                         \
940         do {                                                    \
941                 if (fop != NULL)                                \
942                         fop[*count].fp_register = (x);          \
943                 if (fop3 != NULL)                               \
944                         fop3[*count].fp_register = (x);         \
945         } while(0)
946
947 #define SET_OFFSET(x)                                           \
948         do {                                                    \
949                 if (fop != NULL)                                \
950                         fop[*count].fp_offset = (x);            \
951                 if (fop3 != NULL)                               \
952                         fop3[*count].fp_offset_or_block_len =   \
953                             (x);                                \
954         } while(0)
955
956 #define SET_INSTR_OFFSET(x)                                     \
957         do {                                                    \
958                 if (fop != NULL)                                \
959                         fop[*count].fp_instr_offset = (x);      \
960                 if (fop3 != NULL)                               \
961                         fop3[*count].fp_instr_offset = (x);     \
962         } while(0)
963
964 #define SET_BLOCK_LEN(x)                                        \
965         do {                                                    \
966                 if (fop3 != NULL)                               \
967                         fop3[*count].fp_offset_or_block_len =   \
968                             (x);                                \
969         } while(0)
970
971 #define SET_EXPR_BLOCK(addr, len)                                       \
972         do {                                                            \
973                 if (fop3 != NULL) {                                     \
974                         fop3[*count].fp_expr_block =                    \
975                             malloc((size_t) (len));                     \
976                         if (fop3[*count].fp_expr_block == NULL) {       \
977                                 DWARF_SET_ERROR(dbg, error,             \
978                                     DW_DLE_MEMORY);                     \
979                                 return (DW_DLE_MEMORY);                 \
980                         }                                               \
981                         memcpy(&fop3[*count].fp_expr_block,             \
982                             (addr), (len));                             \
983                 }                                                       \
984         } while(0)
985
986         *count = 0;
987
988         p = insts;
989         pe = p + len;
990
991         while (p < pe) {
992
993                 SET_INSTR_OFFSET(p - insts);
994
995                 if (*p == DW_CFA_nop) {
996                         p++;
997                         (*count)++;
998                         continue;
999                 }
1000
1001                 high2 = *p & 0xc0;
1002                 low6 = *p & 0x3f;
1003                 p++;
1004
1005                 if (high2 > 0) {
1006                         switch (high2) {
1007                         case DW_CFA_advance_loc:
1008                                 SET_BASE_OP(high2);
1009                                 SET_OFFSET(low6);
1010                                 break;
1011                         case DW_CFA_offset:
1012                                 SET_BASE_OP(high2);
1013                                 SET_REGISTER(low6);
1014                                 uoff = _dwarf_decode_uleb128(&p);
1015                                 SET_OFFSET(uoff);
1016                                 break;
1017                         case DW_CFA_restore:
1018                                 SET_BASE_OP(high2);
1019                                 SET_REGISTER(low6);
1020                                 break;
1021                         default:
1022                                 DWARF_SET_ERROR(dbg, error,
1023                                     DW_DLE_FRAME_INSTR_EXEC_ERROR);
1024                                 return (DW_DLE_FRAME_INSTR_EXEC_ERROR);
1025                         }
1026
1027                         (*count)++;
1028                         continue;
1029                 }
1030
1031                 SET_EXTENDED_OP(low6);
1032
1033                 switch (low6) {
1034                 case DW_CFA_set_loc:
1035                         uoff = dbg->decode(&p, addr_size);
1036                         SET_OFFSET(uoff);
1037                         break;
1038                 case DW_CFA_advance_loc1:
1039                         uoff = dbg->decode(&p, 1);
1040                         SET_OFFSET(uoff);
1041                         break;
1042                 case DW_CFA_advance_loc2:
1043                         uoff = dbg->decode(&p, 2);
1044                         SET_OFFSET(uoff);
1045                         break;
1046                 case DW_CFA_advance_loc4:
1047                         uoff = dbg->decode(&p, 4);
1048                         SET_OFFSET(uoff);
1049                         break;
1050                 case DW_CFA_offset_extended:
1051                 case DW_CFA_def_cfa:
1052                 case DW_CFA_val_offset:
1053                         reg = _dwarf_decode_uleb128(&p);
1054                         uoff = _dwarf_decode_uleb128(&p);
1055                         SET_REGISTER(reg);
1056                         SET_OFFSET(uoff);
1057                         break;
1058                 case DW_CFA_restore_extended:
1059                 case DW_CFA_undefined:
1060                 case DW_CFA_same_value:
1061                 case DW_CFA_def_cfa_register:
1062                         reg = _dwarf_decode_uleb128(&p);
1063                         SET_REGISTER(reg);
1064                         break;
1065                 case DW_CFA_register:
1066                         reg = _dwarf_decode_uleb128(&p);
1067                         reg2 = _dwarf_decode_uleb128(&p);
1068                         SET_REGISTER(reg);
1069                         SET_OFFSET(reg2);
1070                         break;
1071                 case DW_CFA_remember_state:
1072                 case DW_CFA_restore_state:
1073                         break;
1074                 case DW_CFA_def_cfa_offset:
1075                         uoff = _dwarf_decode_uleb128(&p);
1076                         SET_OFFSET(uoff);
1077                         break;
1078                 case DW_CFA_def_cfa_expression:
1079                         blen = _dwarf_decode_uleb128(&p);
1080                         SET_BLOCK_LEN(blen);
1081                         SET_EXPR_BLOCK(p, blen);
1082                         p += blen;
1083                         break;
1084                 case DW_CFA_expression:
1085                 case DW_CFA_val_expression:
1086                         reg = _dwarf_decode_uleb128(&p);
1087                         blen = _dwarf_decode_uleb128(&p);
1088                         SET_REGISTER(reg);
1089                         SET_BLOCK_LEN(blen);
1090                         SET_EXPR_BLOCK(p, blen);
1091                         p += blen;
1092                         break;
1093                 case DW_CFA_offset_extended_sf:
1094                 case DW_CFA_def_cfa_sf:
1095                 case DW_CFA_val_offset_sf:
1096                         reg = _dwarf_decode_uleb128(&p);
1097                         soff = _dwarf_decode_sleb128(&p);
1098                         SET_REGISTER(reg);
1099                         SET_OFFSET(soff);
1100                         break;
1101                 case DW_CFA_def_cfa_offset_sf:
1102                         soff = _dwarf_decode_sleb128(&p);
1103                         SET_OFFSET(soff);
1104                         break;
1105                 default:
1106                         DWARF_SET_ERROR(dbg, error,
1107                             DW_DLE_FRAME_INSTR_EXEC_ERROR);
1108                         return (DW_DLE_FRAME_INSTR_EXEC_ERROR);
1109                 }
1110
1111                 (*count)++;
1112         }
1113
1114         return (DW_DLE_NONE);
1115 }
1116
1117 int
1118 _dwarf_frame_get_fop(Dwarf_Debug dbg, uint8_t addr_size, uint8_t *insts,
1119     Dwarf_Unsigned len, Dwarf_Frame_Op **ret_oplist, Dwarf_Signed *ret_opcnt,
1120     Dwarf_Error *error)
1121 {
1122         Dwarf_Frame_Op *oplist;
1123         Dwarf_Unsigned count;
1124         int ret;
1125
1126         ret = _dwarf_frame_convert_inst(dbg, addr_size, insts, len, &count,
1127             NULL, NULL, error);
1128         if (ret != DW_DLE_NONE)
1129                 return (ret);
1130
1131         if ((oplist = calloc(count, sizeof(Dwarf_Frame_Op))) == NULL) {
1132                 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
1133                 return (DW_DLE_MEMORY);
1134         }
1135
1136         ret = _dwarf_frame_convert_inst(dbg, addr_size, insts, len, &count,
1137             oplist, NULL, error);
1138         if (ret != DW_DLE_NONE) {
1139                 free(oplist);
1140                 return (ret);
1141         }
1142
1143         *ret_oplist = oplist;
1144         *ret_opcnt = count;
1145
1146         return (DW_DLE_NONE);
1147 }
1148
1149 int
1150 _dwarf_frame_regtable_copy(Dwarf_Debug dbg, Dwarf_Regtable3 **dest,
1151     Dwarf_Regtable3 *src, Dwarf_Error *error)
1152 {
1153         int i;
1154
1155         assert(dest != NULL);
1156         assert(src != NULL);
1157
1158         if (*dest == NULL) {
1159                 if ((*dest = malloc(sizeof(Dwarf_Regtable3))) == NULL) {
1160                         DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
1161                         return (DW_DLE_MEMORY);
1162                 }
1163                 (*dest)->rt3_reg_table_size = src->rt3_reg_table_size;
1164                 (*dest)->rt3_rules = malloc(src->rt3_reg_table_size *
1165                     sizeof(Dwarf_Regtable_Entry3));
1166                 if ((*dest)->rt3_rules == NULL) {
1167                         free(*dest);
1168                         DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
1169                         return (DW_DLE_MEMORY);
1170                 }
1171         }
1172
1173         memcpy(&(*dest)->rt3_cfa_rule, &src->rt3_cfa_rule,
1174             sizeof(Dwarf_Regtable_Entry3));
1175
1176         for (i = 0; i < (*dest)->rt3_reg_table_size &&
1177              i < src->rt3_reg_table_size; i++)
1178                 memcpy(&(*dest)->rt3_rules[i], &src->rt3_rules[i],
1179                     sizeof(Dwarf_Regtable_Entry3));
1180
1181         for (; i < (*dest)->rt3_reg_table_size; i++)
1182                 (*dest)->rt3_rules[i].dw_regnum =
1183                     dbg->dbg_frame_undefined_value;
1184
1185         return (DW_DLE_NONE);
1186 }
1187
1188 int
1189 _dwarf_frame_get_internal_table(Dwarf_Fde fde, Dwarf_Addr pc_req,
1190     Dwarf_Regtable3 **ret_rt, Dwarf_Addr *ret_row_pc, Dwarf_Error *error)
1191 {
1192         Dwarf_Debug dbg;
1193         Dwarf_Cie cie;
1194         Dwarf_Regtable3 *rt;
1195         Dwarf_Addr row_pc;
1196         int i, ret;
1197
1198         assert(ret_rt != NULL);
1199
1200         dbg = fde->fde_dbg;
1201         assert(dbg != NULL);
1202
1203         rt = dbg->dbg_internal_reg_table;
1204
1205         /* Clear the content of regtable from previous run. */
1206         memset(&rt->rt3_cfa_rule, 0, sizeof(Dwarf_Regtable_Entry3));
1207         memset(rt->rt3_rules, 0, rt->rt3_reg_table_size *
1208             sizeof(Dwarf_Regtable_Entry3));
1209
1210         /* Set rules to initial values. */
1211         for (i = 0; i < rt->rt3_reg_table_size; i++)
1212                 rt->rt3_rules[i].dw_regnum = dbg->dbg_frame_rule_initial_value;
1213
1214         /* Run initial instructions in CIE. */
1215         cie = fde->fde_cie;
1216         assert(cie != NULL);
1217         ret = _dwarf_frame_run_inst(dbg, rt, cie->cie_addrsize,
1218             cie->cie_initinst, cie->cie_instlen, cie->cie_caf, cie->cie_daf, 0,
1219             ~0ULL, &row_pc, error);
1220         if (ret != DW_DLE_NONE)
1221                 return (ret);
1222
1223         /* Run instructions in FDE. */
1224         if (pc_req >= fde->fde_initloc) {
1225                 ret = _dwarf_frame_run_inst(dbg, rt, cie->cie_addrsize,
1226                     fde->fde_inst, fde->fde_instlen, cie->cie_caf,
1227                     cie->cie_daf, fde->fde_initloc, pc_req, &row_pc, error);
1228                 if (ret != DW_DLE_NONE)
1229                         return (ret);
1230         }
1231
1232         *ret_rt = rt;
1233         *ret_row_pc = row_pc;
1234
1235         return (DW_DLE_NONE);
1236 }
1237
1238 void
1239 _dwarf_frame_cleanup(Dwarf_Debug dbg)
1240 {
1241         Dwarf_Regtable3 *rt;
1242
1243         assert(dbg != NULL && dbg->dbg_mode == DW_DLC_READ);
1244
1245         if (dbg->dbg_internal_reg_table) {
1246                 rt = dbg->dbg_internal_reg_table;
1247                 free(rt->rt3_rules);
1248                 free(rt);
1249                 dbg->dbg_internal_reg_table = NULL;
1250         }
1251
1252         if (dbg->dbg_frame) {
1253                 _dwarf_frame_section_cleanup(dbg->dbg_frame);
1254                 dbg->dbg_frame = NULL;
1255         }
1256
1257         if (dbg->dbg_eh_frame) {
1258                 _dwarf_frame_section_cleanup(dbg->dbg_eh_frame);
1259                 dbg->dbg_eh_frame = NULL;
1260         }
1261 }
1262
1263 int
1264 _dwarf_frame_section_load(Dwarf_Debug dbg, Dwarf_Error *error)
1265 {
1266         Dwarf_Section *ds;
1267
1268         if ((ds = _dwarf_find_section(dbg, ".debug_frame")) != NULL) {
1269                 return (_dwarf_frame_section_init(dbg, &dbg->dbg_frame,
1270                     ds, 0, error));
1271         }
1272
1273         return (DW_DLE_NONE);
1274 }
1275
1276 int
1277 _dwarf_frame_section_load_eh(Dwarf_Debug dbg, Dwarf_Error *error)
1278 {
1279         Dwarf_Section *ds;
1280
1281         if ((ds = _dwarf_find_section(dbg, ".eh_frame")) != NULL) {
1282                 return (_dwarf_frame_section_init(dbg, &dbg->dbg_eh_frame,
1283                     ds, 1, error));
1284         }
1285
1286         return (DW_DLE_NONE);
1287 }
1288
1289 void
1290 _dwarf_frame_params_init(Dwarf_Debug dbg)
1291 {
1292
1293         /* Initialise call frame related parameters. */
1294         dbg->dbg_frame_rule_table_size = DW_FRAME_LAST_REG_NUM;
1295         dbg->dbg_frame_rule_initial_value = DW_FRAME_REG_INITIAL_VALUE;
1296         dbg->dbg_frame_cfa_value = DW_FRAME_CFA_COL3;
1297         dbg->dbg_frame_same_value = DW_FRAME_SAME_VAL;
1298         dbg->dbg_frame_undefined_value = DW_FRAME_UNDEFINED_VAL;
1299 }
1300
1301 int
1302 _dwarf_frame_interal_table_init(Dwarf_Debug dbg, Dwarf_Error *error)
1303 {
1304         Dwarf_Regtable3 *rt;
1305
1306         if (dbg->dbg_internal_reg_table != NULL)
1307                 return (DW_DLE_NONE);
1308
1309         /* Initialise internal register table. */
1310         if ((rt = calloc(1, sizeof(Dwarf_Regtable3))) == NULL) {
1311                 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
1312                 return (DW_DLE_MEMORY);
1313         }
1314
1315         rt->rt3_reg_table_size = dbg->dbg_frame_rule_table_size;
1316         if ((rt->rt3_rules = calloc(rt->rt3_reg_table_size,
1317             sizeof(Dwarf_Regtable_Entry3))) == NULL) {
1318                 free(rt);
1319                 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
1320                 return (DW_DLE_MEMORY);
1321         }
1322
1323         dbg->dbg_internal_reg_table = rt;
1324
1325         return (DW_DLE_NONE);
1326 }
1327
1328 #define _FDE_INST_INIT_SIZE     128
1329
1330 int
1331 _dwarf_frame_fde_add_inst(Dwarf_P_Fde fde, Dwarf_Small op, Dwarf_Unsigned val1,
1332     Dwarf_Unsigned val2, Dwarf_Error *error)
1333 {
1334         Dwarf_P_Debug dbg;
1335         uint8_t high2, low6;
1336         int ret;
1337
1338 #define ds      fde
1339 #define ds_data fde_inst
1340 #define ds_cap  fde_instcap
1341 #define ds_size fde_instlen
1342
1343         assert(fde != NULL && fde->fde_dbg != NULL);
1344         dbg = fde->fde_dbg;
1345
1346         if (fde->fde_inst == NULL) {
1347                 fde->fde_instcap = _FDE_INST_INIT_SIZE;
1348                 fde->fde_instlen = 0;
1349                 if ((fde->fde_inst = malloc((size_t) fde->fde_instcap)) ==
1350                     NULL) {
1351                         DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
1352                         return (DW_DLE_MEMORY);
1353                 }
1354         }
1355         assert(fde->fde_instcap != 0);
1356
1357         RCHECK(WRITE_VALUE(op, 1));
1358         if (op == DW_CFA_nop)
1359                 return (DW_DLE_NONE);
1360
1361         high2 = op & 0xc0;
1362         low6 = op & 0x3f;
1363
1364         if (high2 > 0) {
1365                 switch (high2) {
1366                 case DW_CFA_advance_loc:
1367                 case DW_CFA_restore:
1368                         break;
1369                 case DW_CFA_offset:
1370                         RCHECK(WRITE_ULEB128(val1));
1371                         break;
1372                 default:
1373                         DWARF_SET_ERROR(dbg, error,
1374                             DW_DLE_FRAME_INSTR_EXEC_ERROR);
1375                         return (DW_DLE_FRAME_INSTR_EXEC_ERROR);
1376                 }
1377                 return (DW_DLE_NONE);
1378         }
1379
1380         switch (low6) {
1381         case DW_CFA_set_loc:
1382                 RCHECK(WRITE_VALUE(val1, dbg->dbg_pointer_size));
1383                 break;
1384         case DW_CFA_advance_loc1:
1385                 RCHECK(WRITE_VALUE(val1, 1));
1386                 break;
1387         case DW_CFA_advance_loc2:
1388                 RCHECK(WRITE_VALUE(val1, 2));
1389                 break;
1390         case DW_CFA_advance_loc4:
1391                 RCHECK(WRITE_VALUE(val1, 4));
1392                 break;
1393         case DW_CFA_offset_extended:
1394         case DW_CFA_def_cfa:
1395         case DW_CFA_register:
1396                 RCHECK(WRITE_ULEB128(val1));
1397                 RCHECK(WRITE_ULEB128(val2));
1398                 break;
1399         case DW_CFA_restore_extended:
1400         case DW_CFA_undefined:
1401         case DW_CFA_same_value:
1402         case DW_CFA_def_cfa_register:
1403         case DW_CFA_def_cfa_offset:
1404                 RCHECK(WRITE_ULEB128(val1));
1405                 break;
1406         case DW_CFA_remember_state:
1407         case DW_CFA_restore_state:
1408                 break;
1409         default:
1410                 DWARF_SET_ERROR(dbg, error, DW_DLE_FRAME_INSTR_EXEC_ERROR);
1411                 return (DW_DLE_FRAME_INSTR_EXEC_ERROR);
1412         }
1413
1414         return (DW_DLE_NONE);
1415
1416 gen_fail:
1417         return (ret);
1418
1419 #undef  ds
1420 #undef  ds_data
1421 #undef  ds_cap
1422 #undef  ds_size
1423 }
1424
1425 static int
1426 _dwarf_frame_gen_cie(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_P_Cie cie,
1427     Dwarf_Error *error)
1428 {
1429         Dwarf_Unsigned len;
1430         uint64_t offset;
1431         int ret;
1432
1433         assert(dbg != NULL && ds != NULL && cie != NULL);
1434
1435         cie->cie_offset = offset = ds->ds_size;
1436         cie->cie_length = 0;
1437         cie->cie_version = 1;
1438
1439         /* Length placeholder. */
1440         RCHECK(WRITE_VALUE(cie->cie_length, 4));
1441
1442         /* .debug_frame use CIE id ~0. */
1443         RCHECK(WRITE_VALUE(~0U, 4));
1444
1445         /* .debug_frame version is 1. (DWARF2) */
1446         RCHECK(WRITE_VALUE(cie->cie_version, 1));
1447
1448         /* Write augmentation, if present. */
1449         if (cie->cie_augment != NULL)
1450                 RCHECK(WRITE_BLOCK(cie->cie_augment,
1451                     strlen((char *) cie->cie_augment) + 1));
1452         else
1453                 RCHECK(WRITE_VALUE(0, 1));
1454
1455         /* Write caf, daf and ra. */
1456         RCHECK(WRITE_ULEB128(cie->cie_caf));
1457         RCHECK(WRITE_SLEB128(cie->cie_daf));
1458         RCHECK(WRITE_VALUE(cie->cie_ra, 1));
1459
1460         /* Write initial instructions, if present. */
1461         if (cie->cie_initinst != NULL)
1462                 RCHECK(WRITE_BLOCK(cie->cie_initinst, cie->cie_instlen));
1463
1464         /* Add padding. */
1465         len = ds->ds_size - cie->cie_offset - 4;
1466         cie->cie_length = roundup(len, dbg->dbg_pointer_size);
1467         while (len++ < cie->cie_length)
1468                 RCHECK(WRITE_VALUE(DW_CFA_nop, 1));
1469
1470         /* Fill in the length field. */
1471         dbg->write(ds->ds_data, &offset, cie->cie_length, 4);
1472         
1473         return (DW_DLE_NONE);
1474
1475 gen_fail:
1476         return (ret);
1477 }
1478
1479 static int
1480 _dwarf_frame_gen_fde(Dwarf_P_Debug dbg, Dwarf_P_Section ds,
1481     Dwarf_Rel_Section drs, Dwarf_P_Fde fde, Dwarf_Error *error)
1482 {
1483         Dwarf_Unsigned len;
1484         uint64_t offset;
1485         int ret;
1486
1487         assert(dbg != NULL && ds != NULL && drs != NULL);
1488         assert(fde != NULL && fde->fde_cie != NULL);
1489
1490         fde->fde_offset = offset = ds->ds_size;
1491         fde->fde_length = 0;
1492         fde->fde_cieoff = fde->fde_cie->cie_offset;
1493
1494         /* Length placeholder. */
1495         RCHECK(WRITE_VALUE(fde->fde_length, 4));
1496
1497         /* Write CIE pointer. */
1498         RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc, 4,
1499             ds->ds_size, 0, fde->fde_cieoff, ".debug_frame", error));
1500
1501         /* Write FDE initial location. */
1502         RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc,
1503             dbg->dbg_pointer_size, ds->ds_size, fde->fde_symndx,
1504             fde->fde_initloc, NULL, error));
1505
1506         /*
1507          * Write FDE address range. Use a pair of relocation entries if
1508          * application provided end symbol index. Otherwise write the
1509          * length without assoicating any relocation info.
1510          */
1511         if (fde->fde_esymndx > 0)
1512                 RCHECK(_dwarf_reloc_entry_add_pair(dbg, drs, ds,
1513                     dbg->dbg_pointer_size, ds->ds_size, fde->fde_symndx,
1514                     fde->fde_esymndx, fde->fde_initloc, fde->fde_eoff, error));
1515         else
1516                 RCHECK(WRITE_VALUE(fde->fde_adrange, dbg->dbg_pointer_size));
1517
1518         /* Write FDE frame instructions. */
1519         RCHECK(WRITE_BLOCK(fde->fde_inst, fde->fde_instlen));
1520
1521         /* Add padding. */
1522         len = ds->ds_size - fde->fde_offset - 4;
1523         fde->fde_length = roundup(len, dbg->dbg_pointer_size);
1524         while (len++ < fde->fde_length)
1525                 RCHECK(WRITE_VALUE(DW_CFA_nop, 1));
1526
1527         /* Fill in the length field. */
1528         dbg->write(ds->ds_data, &offset, fde->fde_length, 4);
1529
1530         return (DW_DLE_NONE);
1531
1532 gen_fail:
1533         return (ret);
1534 }
1535
1536 int
1537 _dwarf_frame_gen(Dwarf_P_Debug dbg, Dwarf_Error *error)
1538 {
1539         Dwarf_P_Section ds;
1540         Dwarf_Rel_Section drs;
1541         Dwarf_P_Cie cie;
1542         Dwarf_P_Fde fde;
1543         int ret;
1544
1545         if (STAILQ_EMPTY(&dbg->dbgp_cielist))
1546                 return (DW_DLE_NONE);
1547
1548         /* Create .debug_frame section. */
1549         if ((ret = _dwarf_section_init(dbg, &ds, ".debug_frame", 0, error)) !=
1550             DW_DLE_NONE)
1551                 goto gen_fail0;
1552
1553         /* Create relocation section for .debug_frame */
1554         RCHECK(_dwarf_reloc_section_init(dbg, &drs, ds, error));
1555
1556         /* Generate list of CIE. */
1557         STAILQ_FOREACH(cie, &dbg->dbgp_cielist, cie_next)
1558                 RCHECK(_dwarf_frame_gen_cie(dbg, ds, cie, error));
1559
1560         /* Generate list of FDE. */
1561         STAILQ_FOREACH(fde, &dbg->dbgp_fdelist, fde_next)
1562                 RCHECK(_dwarf_frame_gen_fde(dbg, ds, drs, fde, error));
1563
1564         /* Inform application the creation of .debug_frame ELF section. */
1565         RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error));
1566
1567         /* Finalize relocation section for .debug_frame */
1568         RCHECK(_dwarf_reloc_section_finalize(dbg, drs, error));
1569
1570         return (DW_DLE_NONE);
1571
1572 gen_fail:
1573         _dwarf_reloc_section_free(dbg, &drs);
1574
1575 gen_fail0:
1576         _dwarf_section_free(dbg, &ds);
1577
1578         return (ret);
1579 }
1580
1581 void
1582 _dwarf_frame_pro_cleanup(Dwarf_P_Debug dbg)
1583 {
1584         Dwarf_P_Cie cie, tcie;
1585         Dwarf_P_Fde fde, tfde;
1586
1587         assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
1588
1589         STAILQ_FOREACH_SAFE(cie, &dbg->dbgp_cielist, cie_next, tcie) {
1590                 STAILQ_REMOVE(&dbg->dbgp_cielist, cie, _Dwarf_Cie, cie_next);
1591                 if (cie->cie_augment)
1592                         free(cie->cie_augment);
1593                 if (cie->cie_initinst)
1594                         free(cie->cie_initinst);
1595                 free(cie);
1596         }
1597         dbg->dbgp_cielen = 0;
1598
1599         STAILQ_FOREACH_SAFE(fde, &dbg->dbgp_fdelist, fde_next, tfde) {
1600                 STAILQ_REMOVE(&dbg->dbgp_fdelist, fde, _Dwarf_Fde, fde_next);
1601                 if (fde->fde_inst != NULL)
1602                         free(fde->fde_inst);
1603                 free(fde);
1604         }
1605         dbg->dbgp_fdelen = 0;
1606 }