Print this page
3265 link-editor builds bogus .eh_frame_hdr on ia32
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/sgs/elfdump/common/dwarf.c
+++ new/usr/src/cmd/sgs/elfdump/common/dwarf.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 #include <_libelf.h>
28 28 #include <dwarf.h>
29 29 #include <stdio.h>
30 30 #include <unistd.h>
31 31 #include <errno.h>
32 32 #include <strings.h>
33 33 #include <debug.h>
34 34 #include <conv.h>
35 35 #include <msg.h>
36 36 #include <_elfdump.h>
37 37
38 38
39 39 /*
40 40 * Data from eh_frame section used by dump_cfi()
41 41 */
↓ open down ↓ |
41 lines elided |
↑ open up ↑ |
42 42 typedef struct {
43 43 Half e_machine; /* ehdr->e_machine */
44 44 uchar_t *e_ident; /* ehdr->e_ident */
45 45 uint64_t sh_addr; /* Address of eh_frame section */
46 46 int do_swap; /* True if object and system byte */
47 47 /* order differs */
48 48 int cieRflag; /* R flag from current CIE */
49 49 uint64_t ciecalign; /* CIE code align factor */
50 50 int64_t ciedalign; /* CIE data align factor */
51 51 uint64_t fdeinitloc; /* FDE initial location */
52 + uint64_t gotaddr; /* Address of the GOT */
52 53 } dump_cfi_state_t;
53 54
54 55
55 56 /*
56 57 * Extract an unsigned integer value from an .eh_frame section, converting it
57 58 * from its native byte order to that of the running machine if necessary.
58 59 *
59 60 * entry:
60 61 * data - Base address from which to extract datum
61 62 * ndx - Address of variable giving index to start byte in data.
62 63 * size - # of bytes in datum. Must be one of: 1, 2, 4, 8
63 64 * do_swap - True if the data is in a different byte order than that
64 65 * of the host system.
65 66 *
66 67 * exit:
67 68 * *ndx is incremented by the size of the extracted datum.
68 69 *
69 70 * The requested datum is extracted, byte swapped if necessary,
70 71 * and returned.
71 72 */
72 73 static uint64_t
73 74 dwarf_extract_uint(uchar_t *data, uint64_t *ndx, int size, int do_swap)
74 75 {
75 76 switch (size) {
76 77 case 1:
77 78 return (data[(*ndx)++]);
78 79 case 2:
79 80 {
80 81 Half r;
81 82 uchar_t *p = (uchar_t *)&r;
82 83
83 84 data += *ndx;
84 85 if (do_swap)
85 86 UL_ASSIGN_BSWAP_HALF(p, data);
86 87 else
87 88 UL_ASSIGN_HALF(p, data);
88 89
89 90 (*ndx) += 2;
90 91 return (r);
91 92 }
92 93 case 4:
93 94 {
94 95 Word r;
95 96 uchar_t *p = (uchar_t *)&r;
96 97
97 98 data += *ndx;
98 99 if (do_swap)
99 100 UL_ASSIGN_BSWAP_WORD(p, data);
100 101 else
101 102 UL_ASSIGN_WORD(p, data);
102 103
103 104 (*ndx) += 4;
104 105 return (r);
105 106 }
106 107
107 108 case 8:
108 109 {
109 110 uint64_t r;
110 111 uchar_t *p = (uchar_t *)&r;
111 112
112 113 data += *ndx;
113 114 if (do_swap)
114 115 UL_ASSIGN_BSWAP_LWORD(p, data);
115 116 else
116 117 UL_ASSIGN_LWORD(p, data);
117 118
118 119 (*ndx) += 8;
119 120 return (r);
120 121 }
121 122 }
122 123
123 124 /* If here, an invalid size was specified */
124 125 assert(0);
125 126 return (0);
126 127 }
127 128
128 129 /*
129 130 * Map a DWARF register constant to the machine register name it
130 131 * corresponds to, formatting the result into buf.
131 132 *
132 133 * The assignment of DWARF register numbers is part of the system
133 134 * specific ABI for each platform.
134 135 *
135 136 * entry:
136 137 * regno - DWARF register number
137 138 * mach - ELF machine code for platform
138 139 * buf, bufsize - Buffer to receive the formatted result string
139 140 *
140 141 * exit:
141 142 * The results are formatted into buf, and buf is returned.
142 143 * If the generated output would exceed the size of the buffer
143 144 * provided, it will be clipped to fit.
144 145 */
145 146 static const char *
146 147 dwarf_regname(Half mach, int regno, char *buf, size_t bufsize)
147 148 {
148 149 Conv_inv_buf_t inv_buf;
149 150 const char *name;
150 151 int good_name;
151 152
152 153 name = conv_dwarf_regname(mach, regno, 0, &good_name, &inv_buf);
153 154
154 155 /*
155 156 * If there is a good mnemonic machine name for the register,
156 157 * format the result as 'r# (mnemonic)'. If there is no good
157 158 * name for it, then simply format the dwarf name as 'r#'.
158 159 */
159 160 if (good_name)
160 161 (void) snprintf(buf, bufsize, MSG_ORIG(MSG_REG_FMT_NAME),
161 162 regno, name);
162 163 else
163 164 (void) snprintf(buf, bufsize, MSG_ORIG(MSG_REG_FMT_BASIC),
164 165 regno);
165 166
166 167 return (buf);
167 168 }
168 169
169 170
170 171 /*
171 172 * Decode eh_frame Call Frame Instructions, printing each one on a
172 173 * separate line.
173 174 *
174 175 * entry:
175 176 * data - Address of base of eh_frame section being processed
176 177 * off - Offset of current FDE within eh_frame
177 178 * ndx - Index of current position within current FDE
178 179 * len - Length of eh_frame section
179 180 * state - Object, CIE, and FDE state for current request
180 181 * msg - Header message to issue before producing output.
181 182 * indent - # of indentation characters issued for each line of output.
182 183 *
183 184 * exit:
184 185 * The Call Frame Instructions have been decoded and printed.
185 186 *
186 187 * *ndx has been incremented to contain the index of the next
187 188 * byte of data to be processed in eh_frame.
188 189 *
189 190 * note:
190 191 * The format of Call Frame Instructions in .eh_frame sections is based
191 192 * on the DWARF specification.
192 193 */
193 194 static void
194 195 dump_cfi(uchar_t *data, uint64_t off, uint64_t *ndx, uint_t len,
195 196 dump_cfi_state_t *state, const char *msg, int indent)
196 197 {
197 198 /*
198 199 * We use %*s%s to insert leading whitespace and the op name.
199 200 * PREFIX supplies these arguments.
200 201 */
201 202 #define PREFIX indent, MSG_ORIG(MSG_STR_EMPTY), opname
202 203
203 204 /* Hide boilerplate clutter in calls to dwarf_regname() */
204 205 #define REGNAME(_rnum, _buf) \
205 206 dwarf_regname(state->e_machine, _rnum, _buf, sizeof (_buf))
206 207
207 208 /* Extract the lower 6 bits from an op code */
208 209 #define LOW_OP(_op) (_op & 0x3f)
209 210
210 211 char rbuf1[32], rbuf2[32];
211 212 Conv_inv_buf_t inv_buf;
212 213 uchar_t op;
213 214 const char *opname;
214 215 uint64_t oper1, oper2, cur_pc;
215 216 int64_t soper;
216 217 const char *loc_str;
217 218 int i;
218 219
219 220 dbg_print(0, msg);
220 221
221 222 /*
222 223 * In a CIE/FDE, the length field does not include it's own
223 224 * size. Hence, the value passed in is 4 less than the index
224 225 * of the actual final location.
225 226 */
226 227 len += 4;
227 228
228 229 /*
229 230 * There is a concept of the 'current location', which is the PC
230 231 * to which the current item applies. It starts out set to the
231 232 * FDE initial location, and can be set or incremented by
232 233 * various OP codes. cur_pc is used to track this.
233 234 *
234 235 * We want to use 'initloc' in the output the first time the location
235 236 * is referenced, and then switch to 'loc' for subsequent references.
236 237 * loc_str is used to manage that.
237 238 */
238 239 cur_pc = state->fdeinitloc;
239 240 loc_str = MSG_ORIG(MSG_STR_INITLOC);
240 241
241 242 while (*ndx < len) {
242 243 /*
243 244 * The first byte contains the primary op code in the top
244 245 * 2 bits, so there are 4 of them. Primary OP code
245 246 * 0 uses the lower 6 bits to specify a sub-opcode, allowing
246 247 * for 64 of them. The other 3 primary op codes use the
247 248 * lower 6 bits to hold an operand (a register #, or value).
248 249 *
249 250 * Check the primary OP code. If it's 1-3, handle it
250 251 * and move to the next loop iteration. For OP code 0,
251 252 * fall through to decode the sub-code.
252 253 */
253 254 op = data[off + (*ndx)++];
254 255 opname = conv_dwarf_cfa(op, 0, &inv_buf);
255 256 switch (op >> 6) {
256 257 case 0x1: /* v2: DW_CFA_advance_loc, delta */
257 258 oper1 = state->ciecalign * LOW_OP(op);
258 259 cur_pc += oper1;
259 260 dbg_print(0, MSG_ORIG(MSG_CFA_ADV_LOC), PREFIX,
260 261 loc_str, EC_XWORD(oper1), EC_XWORD(cur_pc));
261 262 loc_str = MSG_ORIG(MSG_STR_LOC);
262 263 continue;
263 264
264 265 case 0x2: /* v2: DW_CFA_offset, reg, offset */
265 266 soper = uleb_extract(&data[off], ndx) *
266 267 state->ciedalign;
267 268 dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF), PREFIX,
268 269 REGNAME(LOW_OP(op), rbuf1), EC_SXWORD(soper));
269 270 continue;
270 271
271 272 case 0x3: /* v2: DW_CFA_restore, reg */
272 273 dbg_print(0, MSG_ORIG(MSG_CFA_REG), PREFIX,
273 274 REGNAME(LOW_OP(op), rbuf1));
274 275 continue;
275 276 }
276 277
277 278 /*
278 279 * If we're here, the high order 2 bits are 0. The low 6 bits
279 280 * specify a sub-opcode defining the operation.
280 281 */
281 282 switch (op) {
282 283 case 0x00: /* v2: DW_CFA_nop */
283 284 /*
284 285 * No-ops are used to fill unused space required
285 286 * for alignment. It is common for there to be
286 287 * multiple adjacent nops. It saves space to report
287 288 * them all with a single line of output.
288 289 */
289 290 for (i = 1;
290 291 (*ndx < len) && (data[off + *ndx] == 0);
291 292 i++, (*ndx)++)
292 293 ;
293 294 dbg_print(0, MSG_ORIG(MSG_CFA_SIMPLEREP), PREFIX, i);
↓ open down ↓ |
232 lines elided |
↑ open up ↑ |
294 295 break;
295 296
296 297 case 0x0a: /* v2: DW_CFA_remember_state */
297 298 case 0x0b: /* v2: DW_CFA_restore_state */
298 299 case 0x2d: /* GNU: DW_CFA_GNU_window_save */
299 300 dbg_print(0, MSG_ORIG(MSG_CFA_SIMPLE), PREFIX);
300 301 break;
301 302
302 303 case 0x01: /* v2: DW_CFA_set_loc, address */
303 304 cur_pc = dwarf_ehe_extract(&data[off], ndx,
304 - state->cieRflag, state->e_ident,
305 - state->sh_addr, off + *ndx);
305 + state->cieRflag, state->e_ident, B_FALSE,
306 + state->sh_addr, off + *ndx, state->gotaddr);
306 307 dbg_print(0, MSG_ORIG(MSG_CFA_CFASET), PREFIX,
307 308 EC_XWORD(cur_pc));
308 309 break;
309 310
310 311 case 0x02: /* v2: DW_CFA_advance_loc_1, 1-byte delta */
311 312 case 0x03: /* v2: DW_CFA_advance_loc_2, 2-byte delta */
312 313 case 0x04: /* v2: DW_CFA_advance_loc_4, 4-byte delta */
313 314 /*
314 315 * Since the codes are contiguous, and the sizes are
315 316 * powers of 2, we can compute the word width from
316 317 * the code.
317 318 */
318 319 i = 1 << (op - 0x02);
319 320 oper1 = dwarf_extract_uint(data + off, ndx, i,
320 321 state->do_swap) * state->ciecalign;
321 322 cur_pc += oper1;
322 323 dbg_print(0, MSG_ORIG(MSG_CFA_ADV_LOC), PREFIX,
323 324 loc_str, EC_XWORD(oper1), EC_XWORD(cur_pc));
324 325 loc_str = MSG_ORIG(MSG_STR_LOC);
325 326 break;
326 327
327 328 case 0x05: /* v2: DW_CFA_offset_extended,reg,off */
328 329 oper1 = uleb_extract(&data[off], ndx);
329 330 soper = uleb_extract(&data[off], ndx) *
330 331 state->ciedalign;
331 332 dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF), PREFIX,
332 333 REGNAME(oper1, rbuf1), EC_SXWORD(soper));
333 334 break;
334 335
335 336 case 0x06: /* v2: DW_CFA_restore_extended, reg */
336 337 case 0x0d: /* v2: DW_CFA_def_cfa_register, reg */
337 338 case 0x08: /* v2: DW_CFA_same_value, reg */
338 339 case 0x07: /* v2: DW_CFA_undefined, reg */
339 340 oper1 = uleb_extract(&data[off], ndx);
340 341 dbg_print(0, MSG_ORIG(MSG_CFA_REG), PREFIX,
341 342 REGNAME(oper1, rbuf1));
342 343 break;
343 344
344 345
345 346 case 0x09: /* v2: DW_CFA_register, reg, reg */
346 347 oper1 = uleb_extract(&data[off], ndx);
347 348 oper2 = uleb_extract(&data[off], ndx);
348 349 dbg_print(0, MSG_ORIG(MSG_CFA_REG_REG), PREFIX,
349 350 REGNAME(oper1, rbuf1), REGNAME(oper2, rbuf2));
350 351 break;
351 352
352 353 case 0x0c: /* v2: DW_CFA_def_cfa, reg, offset */
353 354 oper1 = uleb_extract(&data[off], ndx);
354 355 oper2 = uleb_extract(&data[off], ndx);
355 356 dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLU), PREFIX,
356 357 REGNAME(oper1, rbuf1), EC_XWORD(oper2));
357 358 break;
358 359
359 360 case 0x0e: /* v2: DW_CFA_def_cfa_offset, offset */
360 361 oper1 = uleb_extract(&data[off], ndx);
361 362 dbg_print(0, MSG_ORIG(MSG_CFA_LLU), PREFIX,
362 363 EC_XWORD(oper1));
363 364 break;
364 365
365 366 case 0x0f: /* v3: DW_CFA_def_cfa_expression, blk */
366 367 oper1 = uleb_extract(&data[off], ndx);
367 368 dbg_print(0, MSG_ORIG(MSG_CFA_EBLK), PREFIX,
368 369 EC_XWORD(oper1));
369 370 /* We currently do not decode the expression block */
370 371 *ndx += oper1;
371 372 break;
372 373
373 374 case 0x10: /* v3: DW_CFA_expression, reg, blk */
374 375 case 0x16: /* v3: DW_CFA_val_expression,reg,blk */
375 376 oper1 = uleb_extract(&data[off], ndx);
376 377 oper2 = uleb_extract(&data[off], ndx);
377 378 dbg_print(0, MSG_ORIG(MSG_CFA_REG_EBLK), PREFIX,
378 379 REGNAME(oper1, rbuf1), EC_XWORD(oper2));
379 380 /* We currently do not decode the expression block */
380 381 *ndx += oper2;
381 382 break;
382 383
383 384 case 0x11: /* v3: DW_CFA_offset_extended_sf, reg, off */
384 385 oper1 = uleb_extract(&data[off], ndx);
385 386 soper = sleb_extract(&data[off], ndx) *
386 387 state->ciedalign;
387 388 dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF), PREFIX,
388 389 REGNAME(oper1, rbuf1), EC_SXWORD(soper));
389 390 break;
390 391
391 392 case 0x12: /* v3: DW_CFA_def_cfa_sf, reg, offset */
392 393 oper1 = uleb_extract(&data[off], ndx);
393 394 soper = sleb_extract(&data[off], ndx) *
394 395 state->ciedalign;
395 396 dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLD), PREFIX,
396 397 REGNAME(oper1, rbuf1), EC_SXWORD(soper));
397 398 break;
398 399
399 400 case 0x13: /* DW_CFA_def_cfa_offset_sf, offset */
400 401 soper = sleb_extract(&data[off], ndx) *
401 402 state->ciedalign;
402 403 dbg_print(0, MSG_ORIG(MSG_CFA_LLD), PREFIX,
403 404 EC_SXWORD(soper));
404 405 break;
405 406
406 407 case 0x14: /* v3: DW_CFA_val_offset, reg, offset */
407 408 oper1 = uleb_extract(&data[off], ndx);
408 409 soper = uleb_extract(&data[off], ndx) *
409 410 state->ciedalign;
410 411 dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLD), PREFIX,
411 412 REGNAME(oper1, rbuf1), EC_SXWORD(soper));
412 413 break;
413 414
414 415 case 0x15: /* v3: DW_CFA_val_offset_sf, reg, offset */
415 416 oper1 = uleb_extract(&data[off], ndx);
416 417 soper = sleb_extract(&data[off], ndx) *
417 418 state->ciedalign;
418 419 dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLD), PREFIX,
419 420 REGNAME(oper1, rbuf1), EC_SXWORD(soper));
420 421 break;
421 422
422 423 case 0x1d: /* GNU: DW_CFA_MIPS_advance_loc8, delta */
423 424 oper1 = dwarf_extract_uint(data + off, ndx, i,
424 425 state->do_swap) * state->ciecalign;
425 426 cur_pc += oper1;
426 427 dbg_print(0, MSG_ORIG(MSG_CFA_ADV_LOC), PREFIX,
427 428 loc_str, EC_XWORD(oper1), EC_XWORD(cur_pc));
428 429 loc_str = MSG_ORIG(MSG_STR_LOC);
429 430 break;
430 431
431 432 case 0x2e: /* GNU: DW_CFA_GNU_args_size, size */
432 433 oper1 = uleb_extract(&data[off], ndx);
433 434 dbg_print(0, MSG_ORIG(MSG_CFA_LLU), PREFIX,
434 435 EC_XWORD(oper1));
435 436
436 437 break;
437 438
438 439 case 0x2f: /* GNU:DW_CFA_GNU_negative_offset_extended,reg,off */
439 440 oper1 = uleb_extract(&data[off], ndx);
440 441 soper = -uleb_extract(&data[off], ndx) *
441 442 state->ciedalign;
442 443 dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF), PREFIX,
443 444 REGNAME(oper1, rbuf1), EC_SXWORD(soper));
444 445 break;
445 446
446 447 default:
447 448 /*
448 449 * Unrecognized OP code: DWARF data is variable length,
449 450 * so we don't know how many bytes to skip in order to
450 451 * advance to the next item. We cannot decode beyond
451 452 * this point, so dump the remainder in hex.
452 453 */
453 454 (*ndx)--; /* Back up to unrecognized opcode */
454 455 dump_hex_bytes(data + off + *ndx, len - *ndx,
455 456 indent, 8, 1);
456 457 (*ndx) = len;
457 458 break;
↓ open down ↓ |
142 lines elided |
↑ open up ↑ |
458 459 }
459 460 }
460 461
461 462 #undef PREFIX
462 463 #undef REGNAME
463 464 #undef LOW_OP
464 465 }
465 466
466 467 void
467 468 dump_eh_frame(uchar_t *data, size_t datasize, uint64_t sh_addr,
468 - Half e_machine, uchar_t *e_ident)
469 + Half e_machine, uchar_t *e_ident, uint64_t gotaddr)
469 470 {
470 471 Conv_dwarf_ehe_buf_t dwarf_ehe_buf;
471 472 dump_cfi_state_t cfi_state;
472 473 uint64_t off, ndx;
473 474 uint_t cieid, cielength, cieversion, cieretaddr;
474 475 int ciePflag, cieZflag, cieLflag, cieLflag_present;
475 476 uint_t cieaugndx, length, id;
476 477 char *cieaugstr;
477 478
478 479 cfi_state.e_machine = e_machine;
479 480 cfi_state.e_ident = e_ident;
480 481 cfi_state.sh_addr = sh_addr;
481 482 cfi_state.do_swap = _elf_sys_encoding() != e_ident[EI_DATA];
483 + cfi_state.gotaddr = gotaddr;
482 484
483 485 off = 0;
484 486 while (off < datasize) {
485 487 ndx = 0;
486 488
487 489 /*
488 490 * Extract length in native format. A zero length indicates
489 491 * that this CIE is a terminator and that processing for this
490 492 * unwind information should end. However, skip this entry and
491 493 * keep processing, just in case there is any other information
492 494 * remaining in this section. Note, ld(1) will terminate the
493 495 * processing of the .eh_frame contents for this file after a
494 496 * zero length CIE, thus any information that does follow is
495 497 * ignored by ld(1), and is therefore questionable.
496 498 */
497 499 length = (uint_t)dwarf_extract_uint(data + off, &ndx,
498 500 4, cfi_state.do_swap);
499 501 if (length == 0) {
500 502 dbg_print(0, MSG_ORIG(MSG_UNW_ZEROTERM));
501 503 off += 4;
502 504 continue;
503 505 }
504 506
505 507 /*
506 508 * extract CIE id in native format
507 509 */
508 510 id = (uint_t)dwarf_extract_uint(data + off, &ndx,
509 511 4, cfi_state.do_swap);
510 512
511 513 /*
512 514 * A CIE record has an id of '0', otherwise this is a
513 515 * FDE entry and the 'id' is the CIE pointer.
514 516 */
515 517 if (id == 0) {
516 518 uint64_t persVal, ndx_save;
517 519 uint_t axsize;
518 520
519 521 cielength = length;
520 522 cieid = id;
521 523 ciePflag = cfi_state.cieRflag = cieZflag = 0;
522 524 cieLflag = cieLflag_present = 0;
523 525
524 526 dbg_print(0, MSG_ORIG(MSG_UNW_CIE),
525 527 EC_XWORD(sh_addr + off));
526 528 dbg_print(0, MSG_ORIG(MSG_UNW_CIELNGTH),
527 529 cielength, cieid);
528 530
529 531 cieversion = data[off + ndx];
530 532 ndx += 1;
531 533 cieaugstr = (char *)(&data[off + ndx]);
532 534 ndx += strlen(cieaugstr) + 1;
533 535
534 536 dbg_print(0, MSG_ORIG(MSG_UNW_CIEVERS),
535 537 cieversion, cieaugstr);
536 538
537 539 cfi_state.ciecalign = uleb_extract(&data[off], &ndx);
538 540 cfi_state.ciedalign = sleb_extract(&data[off], &ndx);
539 541 cieretaddr = data[off + ndx];
540 542 ndx += 1;
541 543
542 544 dbg_print(0, MSG_ORIG(MSG_UNW_CIECALGN),
543 545 EC_XWORD(cfi_state.ciecalign),
544 546 EC_XWORD(cfi_state.ciedalign), cieretaddr);
545 547
546 548 if (cieaugstr[0])
547 549 dbg_print(0, MSG_ORIG(MSG_UNW_CIEAXVAL));
548 550
549 551 for (cieaugndx = 0; cieaugstr[cieaugndx]; cieaugndx++) {
550 552 switch (cieaugstr[cieaugndx]) {
551 553 case 'z':
552 554 axsize = uleb_extract(&data[off], &ndx);
553 555 dbg_print(0, MSG_ORIG(MSG_UNW_CIEAXSIZ),
554 556 axsize);
555 557 cieZflag = 1;
556 558 /*
557 559 * The auxiliary section can contain
558 560 * unused padding bytes at the end, so
559 561 * save the current index. Along with
560 562 * axsize, we will use it to set ndx to
↓ open down ↓ |
69 lines elided |
↑ open up ↑ |
561 563 * the proper continuation index after
562 564 * the aux data has been processed.
563 565 */
564 566 ndx_save = ndx;
565 567 break;
566 568 case 'P':
567 569 ciePflag = data[off + ndx];
568 570 ndx += 1;
569 571
570 572 persVal = dwarf_ehe_extract(&data[off],
571 - &ndx, ciePflag, e_ident,
572 - sh_addr, off + ndx);
573 + &ndx, ciePflag, e_ident, B_FALSE,
574 + sh_addr, off + ndx, gotaddr);
573 575 dbg_print(0,
574 576 MSG_ORIG(MSG_UNW_CIEAXPERS));
575 577 dbg_print(0,
576 578 MSG_ORIG(MSG_UNW_CIEAXPERSENC),
577 579 ciePflag, conv_dwarf_ehe(ciePflag,
578 580 &dwarf_ehe_buf));
579 581 dbg_print(0,
580 582 MSG_ORIG(MSG_UNW_CIEAXPERSRTN),
581 583 EC_XWORD(persVal));
582 584 break;
583 585 case 'R':
584 586 cfi_state.cieRflag = data[off + ndx];
585 587 ndx += 1;
586 588 dbg_print(0,
587 589 MSG_ORIG(MSG_UNW_CIEAXCENC),
588 590 cfi_state.cieRflag,
589 591 conv_dwarf_ehe(cfi_state.cieRflag,
590 592 &dwarf_ehe_buf));
591 593 break;
592 594 case 'L':
593 595 cieLflag_present = 1;
594 596 cieLflag = data[off + ndx];
595 597 ndx += 1;
596 598 dbg_print(0,
597 599 MSG_ORIG(MSG_UNW_CIEAXLSDA),
598 600 cieLflag, conv_dwarf_ehe(
599 601 cieLflag, &dwarf_ehe_buf));
600 602 break;
601 603 default:
602 604 dbg_print(0,
603 605 MSG_ORIG(MSG_UNW_CIEAXUNEC),
604 606 cieaugstr[cieaugndx]);
605 607 break;
606 608 }
607 609 }
608 610
609 611 /*
610 612 * If the z flag was present, reposition ndx using the
611 613 * length given. This will safely move us past any
612 614 * unaccessed padding bytes in the auxiliary section.
613 615 */
614 616 if (cieZflag)
615 617 ndx = ndx_save + axsize;
616 618
617 619 /*
618 620 * Any remaining data are Call Frame Instructions
619 621 */
620 622 if ((cielength + 4) > ndx)
621 623 dump_cfi(data, off, &ndx, cielength, &cfi_state,
622 624 MSG_ORIG(MSG_UNW_CIECFI), 3);
623 625 off += cielength + 4;
624 626
625 627 } else {
↓ open down ↓ |
43 lines elided |
↑ open up ↑ |
626 628 uint_t fdelength = length;
627 629 int fdecieptr = id;
628 630 uint64_t fdeaddrrange;
629 631
630 632 dbg_print(0, MSG_ORIG(MSG_UNW_FDE),
631 633 EC_XWORD(sh_addr + off));
632 634 dbg_print(0, MSG_ORIG(MSG_UNW_FDELNGTH),
633 635 fdelength, fdecieptr);
634 636
635 637 cfi_state.fdeinitloc = dwarf_ehe_extract(&data[off],
636 - &ndx, cfi_state.cieRflag, e_ident,
637 - sh_addr, off + ndx);
638 + &ndx, cfi_state.cieRflag, e_ident, B_FALSE,
639 + sh_addr, off + ndx, gotaddr);
638 640 fdeaddrrange = dwarf_ehe_extract(&data[off], &ndx,
639 641 (cfi_state.cieRflag & ~DW_EH_PE_pcrel),
640 - e_ident, sh_addr, off + ndx);
642 + e_ident, B_FALSE, sh_addr, off + ndx, gotaddr);
641 643
642 644 dbg_print(0, MSG_ORIG(MSG_UNW_FDEINITLOC),
643 645 EC_XWORD(cfi_state.fdeinitloc),
644 646 EC_XWORD(fdeaddrrange),
645 647 EC_XWORD(cfi_state.fdeinitloc + fdeaddrrange - 1));
646 648
647 649 if (cieaugstr[0])
648 650 dbg_print(0, MSG_ORIG(MSG_UNW_FDEAXVAL));
649 651 if (cieZflag) {
650 652 uint64_t val;
651 653 uint64_t lndx;
652 654
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
653 655 val = uleb_extract(&data[off], &ndx);
654 656 lndx = ndx;
655 657 ndx += val;
656 658 dbg_print(0, MSG_ORIG(MSG_UNW_FDEAXSIZE),
657 659 EC_XWORD(val));
658 660 if (val && cieLflag_present) {
659 661 uint64_t lsda;
660 662
661 663 lsda = dwarf_ehe_extract(&data[off],
662 664 &lndx, cieLflag, e_ident,
663 - sh_addr, off + lndx);
665 + B_FALSE, sh_addr, off + lndx,
666 + gotaddr);
664 667 dbg_print(0,
665 668 MSG_ORIG(MSG_UNW_FDEAXLSDA),
666 669 EC_XWORD(lsda));
667 670 }
668 671 }
669 672 if ((fdelength + 4) > ndx)
670 673 dump_cfi(data, off, &ndx, fdelength, &cfi_state,
671 674 MSG_ORIG(MSG_UNW_FDECFI), 6);
672 675 off += fdelength + 4;
673 676 }
674 677 }
675 678 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX