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