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