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