- Timestamp:
- Aug 29, 2011 1:13:27 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/dbg/dbgmoddwarf.cpp
r38554 r38557 36 36 #include <iprt/ctype.h> 37 37 #include <iprt/mem.h> 38 #include <iprt/path.h> 38 39 #include <iprt/stream.h> 39 40 #include <iprt/string.h> 40 41 #include "internal/dbgmod.h" 42 43 44 /******************************************************************************* 45 * Defined Constants And Macros * 46 *******************************************************************************/ 47 /** @name Standard DWARF Line Number Opcodes 48 * @{ */ 49 #define DW_LNS_extended UINT8_C(0) 50 #define DW_LNS_copy UINT8_C(1) 51 #define DW_LNS_advance_pc UINT8_C(2) 52 #define DW_LNS_advance_line UINT8_C(3) 53 #define DW_LNS_set_file UINT8_C(4) 54 #define DW_LNS_set_column UINT8_C(5) 55 #define DW_LNS_negate_stmt UINT8_C(6) 56 #define DW_LNS_set_basic_block UINT8_C(7) 57 #define DW_LNS_const_add_pc UINT8_C(8) 58 #define DW_LNS_fixed_advance_pc UINT8_C(9) 59 #define DW_LNS_set_prologue_end UINT8_C(10) 60 #define DW_LNS_set_epilogue_begin UINT8_C(11) 61 #define DW_LNS_set_isa UINT8_C(12) 62 /** @} */ 63 64 65 /** @name Extended DWARF Line Number Opcodes 66 * @{ */ 67 #define DW_LNE_end_sequence UINT8_C(1) 68 #define DW_LNE_set_address UINT8_C(2) 69 #define DW_LNE_define_file UINT8_C(3) 70 #define DW_LNE_set_descriminator UINT8_C(4) 71 /** @} */ 41 72 42 73 … … 97 128 typedef struct RTDWARFSECTRDR 98 129 { 99 /** The DWARF debug info reader instance. */100 PRTDBGMODDWARF pDwarfMod;101 /** The section we're reading. */102 krtDbgModDwarfSect enmSect;103 130 /** The current position. */ 104 131 uint8_t const *pb; 105 132 /** The number of bytes left to read. */ 106 133 size_t cbLeft; 134 /** The number of bytes left to read in the current unit. */ 135 size_t cbUnitLeft; 136 /** The DWARF debug info reader instance. */ 137 PRTDBGMODDWARF pDwarfMod; 107 138 /** Set if this is 64-bit DWARF, clear if 32-bit. */ 108 bool f64bit ;139 bool f64bitDwarf; 109 140 /** Set if the format endian is native, clear if endian needs to be 110 141 * inverted. */ 111 142 bool fNativEndian; 112 } RTDWARFSECTRDR; 143 /** The size of a native address. */ 144 uint8_t cbNativeAddr; 145 /** The cursor status code. This is VINF_SUCCESS until some error 146 * occurs. */ 147 int rc; 148 } RTDWARFCURSOR; 113 149 /** Pointer to a DWARF section reader. */ 114 typedef RTDWARFSECTRDR *PRTDWARFSECTRDR; 115 150 typedef RTDWARFCURSOR *PRTDWARFCURSOR; 151 152 153 #define VERR_DWARF_BAD_LINE_NUMBER_HEADER -55555 154 #define VERR_DWARF_UNEXPECTED_END -55554 155 #define VERR_DWARF_LEB_OVERFLOW -55553 156 #define VERR_DWARF_BAD_LNE -55552 116 157 117 158 … … 176 217 177 218 /** 178 * Corrects the endianness of a 32-bit unsigned value. 179 * 180 * @returns The corrected value. 181 * 182 * @param pThis The DWARF instance. 183 * @param pu32 The variable to correct. 184 */ 185 DECLINLINE(uint32_t) rtDbgModDwarfEndianU32(PRTDBGMODDWARF pThis, uint32_t *pu32) 186 { 187 return *pu32; 188 } 189 190 191 /** 192 * Corrects the endianness of a 64-bit unsigned value. 193 * 194 * @returns The corrected value. 195 * 196 * @param pThis The DWARF instance. 197 * @param pu64 The variable to correct. 198 */ 199 DECLINLINE(uint64_t) rtDbgModDwarfEndianU64(PRTDBGMODDWARF pThis, uint64_t *pu64) 200 { 201 return *pu64; 202 } 203 204 205 static uint8_t rtDwarfSectRdrGetU8(PRTDWARFSECTRDR pSectRdr, uint8_t uErrValue) 206 { 207 if (pSectRdr->cbLeft < 1) 208 { 209 pSectRdr->pb += pSectRdr->cbLeft; 210 pSectRdr->cbLeft = 0; 219 * Converts to UTF-8 or otherwise makes sure it's valid UTF-8. 220 * 221 * @returns IPRT status code. 222 * @param pThis The DWARF instance. 223 * @param ppsz Pointer to the string pointer. May be 224 * reallocated (RTStr*). 225 */ 226 static int rtDbgModDwarfStringToUtf8(PRTDBGMODDWARF pThis, char **ppsz) 227 { 228 RTStrPurgeEncoding(*ppsz); 229 return VINF_SUCCESS; 230 } 231 232 233 /** 234 * Convers a link address into a segment+offset or RVA. 235 * 236 * @returns IPRT status code. 237 * @param pThis The DWARF instance. 238 * @param LinkAddress The address to convert.. 239 * @param piSeg The segment index. 240 * @param poffSeg Where to return the segment offset. 241 */ 242 static int rtDbgModDwarfLinkAddressToSegOffset(PRTDBGMODDWARF pThis, uint64_t LinkAddress, 243 PRTDBGSEGIDX piSeg, PRTUINTPTR poffSeg) 244 { 245 /** @todo The image should be doing this conversion, not we. */ 246 *piSeg = RTDBGSEGIDX_RVA; 247 *poffSeg = LinkAddress; 248 return VINF_SUCCESS; 249 } 250 251 252 static uint8_t rtDwarfCursor_GetU8(PRTDWARFCURSOR pCursor, uint8_t uErrValue) 253 { 254 if (pCursor->cbUnitLeft < 1) 255 { 256 pCursor->rc = VERR_DWARF_UNEXPECTED_END; 211 257 return uErrValue; 212 258 } 213 259 214 uint8_t u8 = pSectRdr->pb[0]; 215 pSectRdr->pb += 1; 216 pSectRdr->cbLeft -= 1; 260 uint8_t u8 = pCursor->pb[0]; 261 pCursor->pb += 1; 262 pCursor->cbUnitLeft -= 1; 263 pCursor->cbLeft -= 1; 217 264 return u8; 218 265 } 219 266 220 267 221 static uint16_t rtDwarfSectRdrGetU16(PRTDWARFSECTRDR pSectRdr, uint16_t uErrValue) 222 { 223 if (pSectRdr->cbLeft < 2) 224 { 225 pSectRdr->pb += pSectRdr->cbLeft; 226 pSectRdr->cbLeft = 0; 268 static uint16_t rtDwarfCursor_GetU16(PRTDWARFCURSOR pCursor, uint16_t uErrValue) 269 { 270 if (pCursor->cbUnitLeft < 2) 271 { 272 pCursor->pb += pCursor->cbUnitLeft; 273 pCursor->cbLeft -= pCursor->cbUnitLeft; 274 pCursor->cbUnitLeft = 0; 275 pCursor->rc = VERR_DWARF_UNEXPECTED_END; 227 276 return uErrValue; 228 277 } 229 278 230 uint16_t u16 = RT_MAKE_U16(pSectRdr->pb[0], pSectRdr->pb[1]); 231 pSectRdr->pb += 2; 232 pSectRdr->cbLeft -= 2; 233 if (!pSectRdr->fNativEndian) 279 uint16_t u16 = RT_MAKE_U16(pCursor->pb[0], pCursor->pb[1]); 280 pCursor->pb += 2; 281 pCursor->cbUnitLeft -= 2; 282 pCursor->cbLeft -= 2; 283 if (!pCursor->fNativEndian) 234 284 u16 = RT_BSWAP_U16(u16); 235 285 return u16; … … 237 287 238 288 239 static uint32_t rtDwarfSectRdrGetU32(PRTDWARFSECTRDR pSectRdr, uint32_t uErrValue) 240 { 241 if (pSectRdr->cbLeft < 4) 242 { 243 pSectRdr->pb += pSectRdr->cbLeft; 244 pSectRdr->cbLeft = 0; 289 static uint32_t rtDwarfCursor_GetU32(PRTDWARFCURSOR pCursor, uint32_t uErrValue) 290 { 291 if (pCursor->cbUnitLeft < 4) 292 { 293 pCursor->pb += pCursor->cbUnitLeft; 294 pCursor->cbLeft -= pCursor->cbUnitLeft; 295 pCursor->cbUnitLeft = 0; 296 pCursor->rc = VERR_DWARF_UNEXPECTED_END; 245 297 return uErrValue; 246 298 } 247 299 248 uint32_t u32 = RT_MAKE_U32_FROM_U8(pSectRdr->pb[0], pSectRdr->pb[1], pSectRdr->pb[2], pSectRdr->pb[3]); 249 pSectRdr->pb += 4; 250 pSectRdr->cbLeft -= 4; 251 if (!pSectRdr->fNativEndian) 300 uint32_t u32 = RT_MAKE_U32_FROM_U8(pCursor->pb[0], pCursor->pb[1], pCursor->pb[2], pCursor->pb[3]); 301 pCursor->pb += 4; 302 pCursor->cbUnitLeft -= 4; 303 pCursor->cbLeft -= 4; 304 if (!pCursor->fNativEndian) 252 305 u32 = RT_BSWAP_U32(u32); 253 306 return u32; … … 255 308 256 309 257 static uint64_t rtDwarfSectRdrGetU64(PRTDWARFSECTRDR pSectRdr, uint64_t uErrValue) 258 { 259 if (pSectRdr->cbLeft < 8) 260 { 261 pSectRdr->pb += pSectRdr->cbLeft; 262 pSectRdr->cbLeft = uErrValue; 263 return 0; 264 } 265 266 uint64_t u64 = RT_MAKE_U64_FROM_U8(pSectRdr->pb[0], pSectRdr->pb[1], pSectRdr->pb[2], pSectRdr->pb[3], 267 pSectRdr->pb[4], pSectRdr->pb[5], pSectRdr->pb[6], pSectRdr->pb[7]); 268 pSectRdr->pb += 8; 269 pSectRdr->cbLeft -= 8; 270 if (!pSectRdr->fNativEndian) 310 static uint64_t rtDwarfCursor_GetU64(PRTDWARFCURSOR pCursor, uint64_t uErrValue) 311 { 312 if (pCursor->cbUnitLeft < 8) 313 { 314 pCursor->pb += pCursor->cbUnitLeft; 315 pCursor->cbLeft -= pCursor->cbUnitLeft; 316 pCursor->cbUnitLeft = 0; 317 pCursor->rc = VERR_DWARF_UNEXPECTED_END; 318 return uErrValue; 319 } 320 321 uint64_t u64 = RT_MAKE_U64_FROM_U8(pCursor->pb[0], pCursor->pb[1], pCursor->pb[2], pCursor->pb[3], 322 pCursor->pb[4], pCursor->pb[5], pCursor->pb[6], pCursor->pb[7]); 323 pCursor->pb += 8; 324 pCursor->cbUnitLeft -= 8; 325 pCursor->cbLeft -= 8; 326 if (!pCursor->fNativEndian) 271 327 u64 = RT_BSWAP_U64(u64); 272 328 return u64; … … 274 330 275 331 276 static uint16_t rtDwarfSectRdrGetUHalf(PRTDWARFSECTRDR pSectRdr, uint16_t uErrValue) 277 { 278 return rtDwarfSectRdrGetU16(pSectRdr, uErrValue); 279 } 280 281 282 static uint8_t rtDwarfSectRdrGetUByte(PRTDWARFSECTRDR pSectRdr, uint8_t uErrValue) 283 { 284 return rtDwarfSectRdrGetU8(pSectRdr, uErrValue); 285 } 286 287 288 static int8_t rtDwarfSectRdrGetSByte(PRTDWARFSECTRDR pSectRdr, int8_t iErrValue) 289 { 290 return (int8_t)rtDwarfSectRdrGetU8(pSectRdr, (uint8_t)iErrValue); 291 } 292 293 294 static uint64_t rtDwarfSectRdrGetUOff(PRTDWARFSECTRDR pSectRdr, uint64_t uErrValue) 295 { 296 if (pSectRdr->f64bit) 297 return rtDwarfSectRdrGetU64(pSectRdr, uErrValue); 298 return rtDwarfSectRdrGetU32(pSectRdr, (uint32_t)uErrValue); 332 /** 333 * Gets a unsigned LEB128 encoded number. 334 * 335 * @returns unsigned number. 336 * @param pCursor The cursor. 337 * @param uErrValue The value to return on error. 338 */ 339 static uint64_t rtDwarfCursor_GetULeb128(PRTDWARFCURSOR pCursor, uint64_t uErrValue) 340 { 341 if (pCursor->cbUnitLeft < 1) 342 { 343 pCursor->rc = VERR_DWARF_UNEXPECTED_END; 344 return uErrValue; 345 } 346 347 /* 348 * Special case - single byte. 349 */ 350 uint8_t b = pCursor->pb[0]; 351 if (!(b & 0x80)) 352 { 353 pCursor->pb += 1; 354 pCursor->cbUnitLeft -= 1; 355 pCursor->cbLeft -= 1; 356 return b; 357 } 358 359 /* 360 * Generic case. 361 */ 362 /* Decode. */ 363 uint32_t off = 1; 364 uint64_t u64Ret = b & 0x7f; 365 do 366 { 367 if (off == pCursor->cbUnitLeft) 368 { 369 pCursor->rc = VERR_DWARF_UNEXPECTED_END; 370 u64Ret = uErrValue; 371 break; 372 } 373 b = pCursor->pb[off]; 374 u64Ret |= (b & 0x7f) << off * 7; 375 off++; 376 } while (b & 0x80); 377 378 /* Update the cursor. */ 379 pCursor->pb += off; 380 pCursor->cbUnitLeft -= off; 381 pCursor->cbLeft -= off; 382 383 /* Check the range. */ 384 uint32_t cBits = off * 7; 385 if (cBits > 64) 386 { 387 pCursor->rc = VERR_DWARF_LEB_OVERFLOW; 388 u64Ret = uErrValue; 389 } 390 391 return u64Ret; 392 } 393 394 395 /** 396 * Gets a signed LEB128 encoded number. 397 * 398 * @returns signed number. 399 * @param pCursor The cursor. 400 * @param sErrValue The value to return on error. 401 */ 402 static int64_t rtDwarfCursor_GetSLeb128(PRTDWARFCURSOR pCursor, int64_t sErrValue) 403 { 404 if (pCursor->cbUnitLeft < 1) 405 { 406 pCursor->rc = VERR_DWARF_UNEXPECTED_END; 407 return sErrValue; 408 } 409 410 /* 411 * Special case - single byte. 412 */ 413 uint8_t b = pCursor->pb[0]; 414 if (!(b & 0x80)) 415 { 416 pCursor->pb += 1; 417 pCursor->cbUnitLeft -= 1; 418 pCursor->cbLeft -= 1; 419 if (b & 0x40) 420 b |= 0x80; 421 return (int8_t)b; 422 } 423 424 /* 425 * Generic case. 426 */ 427 /* Decode it. */ 428 uint32_t off = 1; 429 uint64_t u64Ret = b & 0x7f; 430 do 431 { 432 if (off == pCursor->cbUnitLeft) 433 { 434 pCursor->rc = VERR_DWARF_UNEXPECTED_END; 435 u64Ret = (uint64_t)sErrValue; 436 break; 437 } 438 b = pCursor->pb[off]; 439 u64Ret |= (b & 0x7f) << off * 7; 440 off++; 441 } while (b & 0x80); 442 443 /* Update cursor. */ 444 pCursor->pb += off; 445 pCursor->cbUnitLeft -= off; 446 pCursor->cbLeft -= off; 447 448 /* Check the range. */ 449 uint32_t cBits = off * 7; 450 if (cBits > 64) 451 { 452 pCursor->rc = VERR_DWARF_LEB_OVERFLOW; 453 u64Ret = (uint64_t)sErrValue; 454 } 455 /* Sign extend the value. */ 456 else if (u64Ret & RT_BIT_64(cBits - 1)) 457 u64Ret |= ~RT_BIT_64(cBits - 1); 458 459 return (int64_t)u64Ret; 460 } 461 462 463 /** 464 * Gets a unsigned LEB128 encoded number, max 32-bit width. 465 * 466 * @returns unsigned number. 467 * @param pCursor The cursor. 468 * @param uErrValue The value to return on error. 469 */ 470 static uint32_t rtDwarfCursor_GetULeb128AsU32(PRTDWARFCURSOR pCursor, uint32_t uErrValue) 471 { 472 uint64_t u64 = rtDwarfCursor_GetULeb128(pCursor, uErrValue); 473 if (u64 > UINT32_MAX) 474 { 475 pCursor->rc = VERR_DWARF_LEB_OVERFLOW; 476 return uErrValue; 477 } 478 return (uint32_t)u64; 479 } 480 481 482 /** 483 * Gets a signed LEB128 encoded number, max 32-bit width. 484 * 485 * @returns unsigned number. 486 * @param pCursor The cursor. 487 * @param sErrValue The value to return on error. 488 */ 489 static int32_t rtDwarfCursor_GetSLeb128AsS32(PRTDWARFCURSOR pCursor, int32_t sErrValue) 490 { 491 int64_t s64 = rtDwarfCursor_GetSLeb128(pCursor, sErrValue); 492 if (s64 > INT32_MAX || s64 < INT32_MIN) 493 { 494 pCursor->rc = VERR_DWARF_LEB_OVERFLOW; 495 return sErrValue; 496 } 497 return (int32_t)s64; 498 } 499 500 501 static int rtDwarfCursor_SkipLeb128(PRTDWARFCURSOR pCursor) 502 { 503 if (pCursor->cbUnitLeft < 1) 504 return pCursor->rc = VERR_DWARF_UNEXPECTED_END; 505 506 uint32_t offSkip = 1; 507 if (pCursor->pb[0] & 0x80) 508 do 509 { 510 if (offSkip == pCursor->cbUnitLeft) 511 { 512 pCursor->rc = VERR_DWARF_UNEXPECTED_END; 513 break; 514 } 515 } while (pCursor->pb[offSkip++] & 0x80); 516 517 pCursor->pb += offSkip; 518 pCursor->cbUnitLeft -= offSkip; 519 pCursor->cbLeft -= offSkip; 520 return pCursor->rc; 521 } 522 523 524 525 /** 526 * Reads a zero terminated string, advancing the cursor beyond the terminator. 527 * 528 * @returns Pointer to the string. 529 * @param pCursor The cursor. 530 * @param pszErrValue What to return if the string isn't terminated 531 * before the end of the unit. 532 */ 533 static const char *rtDwarfCursor_GetSZ(PRTDWARFCURSOR pCursor, const char *pszErrValue) 534 { 535 const char *pszRet = (const char *)pCursor->pb; 536 for (;;) 537 { 538 if (!pCursor->cbUnitLeft) 539 return pszErrValue; 540 pCursor->cbUnitLeft--; 541 pCursor->cbLeft--; 542 if (!*pCursor->pb++) 543 break; 544 } 545 return pszRet; 546 } 547 548 549 550 static uint16_t rtDwarfCursor_GetUHalf(PRTDWARFCURSOR pCursor, uint16_t uErrValue) 551 { 552 return rtDwarfCursor_GetU16(pCursor, uErrValue); 553 } 554 555 556 static uint8_t rtDwarfCursor_GetUByte(PRTDWARFCURSOR pCursor, uint8_t uErrValue) 557 { 558 return rtDwarfCursor_GetU8(pCursor, uErrValue); 559 } 560 561 562 static int8_t rtDwarfCursor_GetSByte(PRTDWARFCURSOR pCursor, int8_t iErrValue) 563 { 564 return (int8_t)rtDwarfCursor_GetU8(pCursor, (uint8_t)iErrValue); 565 } 566 567 568 static uint64_t rtDwarfCursor_GetUOff(PRTDWARFCURSOR pCursor, uint64_t uErrValue) 569 { 570 if (pCursor->f64bitDwarf) 571 return rtDwarfCursor_GetU64(pCursor, uErrValue); 572 return rtDwarfCursor_GetU32(pCursor, (uint32_t)uErrValue); 573 } 574 575 576 /** 577 * Gets the unit length, updating the unit length member and DWARF bitness 578 * members of the cursor. 579 * 580 * @returns The unit length. 581 * @param pCursor The cursor. 582 */ 583 static uint64_t rtDwarfCursor_GetInitalLength(PRTDWARFCURSOR pCursor) 584 { 585 /* 586 * Read the initial length. 587 */ 588 pCursor->cbUnitLeft = pCursor->cbLeft; 589 uint64_t cbUnit = rtDwarfCursor_GetU32(pCursor, 0); 590 if (cbUnit != UINT32_C(0xffffffff)) 591 pCursor->f64bitDwarf = false; 592 else 593 { 594 pCursor->f64bitDwarf = true; 595 cbUnit = rtDwarfCursor_GetU64(pCursor, 0); 596 } 597 598 599 /* 600 * Set the unit length, quitely fixing bad lengths. 601 */ 602 pCursor->cbUnitLeft = (size_t)cbUnit; 603 if ( pCursor->cbUnitLeft > pCursor->cbLeft 604 || pCursor->cbUnitLeft != cbUnit) 605 pCursor->cbUnitLeft = pCursor->cbLeft; 606 607 return cbUnit; 608 } 609 610 611 static bool rtDwarfCursor_IsAtEndOfUnit(PRTDWARFCURSOR pCursor) 612 { 613 return pCursor->cbUnitLeft > 0; 614 } 615 616 617 static int rtDwarfCursor_SkipUnit(PRTDWARFCURSOR pCursor) 618 { 619 pCursor->pb += pCursor->cbUnitLeft; 620 pCursor->cbLeft -= pCursor->cbUnitLeft; 621 pCursor->cbUnitLeft = 0; 622 return VINF_SUCCESS; 623 } 624 625 626 static bool rtDwarfCursor_IsAtEnd(PRTDWARFCURSOR pCursor) 627 { 628 return pCursor->cbLeft > 0; 299 629 } 300 630 … … 304 634 * 305 635 * @returns IPRT status code. 306 * @param p SectRdr The section reader.636 * @param pCursor The section reader. 307 637 * @param pThis The dwarf module. 308 638 * @param enmSect . 309 639 */ 310 static int rtDwarf SectRdrInit(PRTDWARFSECTRDR pSectRdr, PRTDBGMODDWARF pThis, krtDbgModDwarfSect enmSect)640 static int rtDwarfCursor_Init(PRTDWARFCURSOR pCursor, PRTDBGMODDWARF pThis, krtDbgModDwarfSect enmSect) 311 641 { 312 642 int rc = rtDbgModDwarfLoadSection(pThis, enmSect); … … 314 644 return rc; 315 645 316 pSectRdr->pDwarfMod = pThis; 317 pSectRdr->enmSect = enmSect; 318 pSectRdr->pb = (uint8_t const *)pThis->aSections[krtDbgModDwarfSect_line].pv; 319 pSectRdr->cbLeft = pThis->aSections[krtDbgModDwarfSect_line].cb; 320 pSectRdr->fNativEndian = true; /** @todo endian */ 321 pSectRdr->f64bit = false; 322 323 /* 324 * Read the initial length. 325 */ 326 uint64_t cbUnit = rtDwarfSectRdrGetU32(pSectRdr, 0); 327 if (cbUnit == UINT32_C(0xffffffff)) 328 { 329 pSectRdr->f64bit = true; 330 cbUnit = rtDwarfSectRdrGetU64(pSectRdr, 0); 331 } 332 if (cbUnit < pSectRdr->cbLeft) 333 pSectRdr->cbLeft = (size_t)cbUnit; 646 pCursor->pb = (uint8_t const *)pThis->aSections[enmSect].pv; 647 pCursor->cbLeft = pThis->aSections[enmSect].cb; 648 pCursor->cbUnitLeft = pCursor->cbLeft; 649 pCursor->pDwarfMod = pThis; 650 pCursor->fNativEndian = true; /** @todo endian */ 651 pCursor->f64bitDwarf = false; 652 pCursor->cbNativeAddr = 4; 653 pCursor->rc = VINF_SUCCESS; 654 655 /** @todo ask the image about the endian used as well as the address 656 * width. */ 334 657 335 658 return VINF_SUCCESS; … … 338 661 339 662 /** 340 * Deletes a section reader initialized by rtDwarfSectRdrInit. 341 * 342 * @param pSectRdr The section reader. 343 */ 344 static void rtDwarfSectRdrDelete(PRTDWARFSECTRDR pSectRdr) 345 { 346 rtDbgModDwarfUnloadSection(pSectRdr->pDwarfMod, pSectRdr->enmSect); 347 663 * Deletes a section reader initialized by rtDwarfCursor_Init. 664 * 665 * @param pCursor The section reader. 666 */ 667 static void rtDwarfCursor_Delete(PRTDWARFCURSOR pCursor) 668 { 348 669 /* ... and a drop of poison. */ 349 pSectRdr->pb = NULL; 350 pSectRdr->cbLeft = ~(size_t)0; 351 pSectRdr->enmSect = krtDbgModDwarfSect_End; 670 pCursor->pb = NULL; 671 pCursor->cbLeft = ~(size_t)0; 672 pCursor->cbUnitLeft = ~(size_t)0; 673 pCursor->pDwarfMod = NULL; 674 pCursor->rc = VERR_INTERNAL_ERROR_4; 352 675 } 353 676 … … 492 815 493 816 /** 817 * DWARF line number program state. 818 */ 819 typedef struct RTDWARFLINESTATE 820 { 821 /** Registers */ 822 struct 823 { 824 uint64_t uAddress; 825 uint32_t idxOp; 826 uint32_t iFile; 827 uint32_t uLine; 828 uint32_t uColumn; 829 bool fIsStatement; 830 bool fBasicBlock; 831 bool fEndSequence; 832 bool fPrologueEnd; 833 bool fEpilogueBegin; 834 uint32_t uIsa; 835 uint32_t uDiscriminator; 836 } Regs; 837 /** @} */ 838 839 /** @name Header 840 * @{ */ 841 uint32_t uVer; 842 uint64_t cbSkipAfterHdr; 843 uint8_t cbMinInstr; 844 uint8_t cMaxOpsPerInstr; 845 uint8_t u8DefIsStmt; 846 int8_t s8LineBase; 847 uint8_t u8LineRange; 848 uint8_t u8OpcodeBase; 849 uint8_t const *pacStdOperands; 850 /** @} */ 851 852 /** @name Include Path Table (0-based) 853 * @{ */ 854 const char **papszIncPaths; 855 uint32_t cIncPaths; 856 /** @} */ 857 858 /** @name File Name Table (1-based) 859 * @{ */ 860 char **papszFileNames; 861 uint32_t cFileNames; 862 /** @} */ 863 864 /** The DWARF debug info reader instance. */ 865 PRTDBGMODDWARF pDwarfMod; 866 } RTDWARFLINESTATE; 867 /** Pointer to a DWARF line number program state. */ 868 typedef RTDWARFLINESTATE *PRTDWARFLINESTATE; 869 870 871 static int rtDwarfLine_DefineFileName(PRTDWARFLINESTATE pLnState, const char *pszFilename, uint64_t idxInc) 872 { 873 /* 874 * Resize the array if necessary. 875 */ 876 size_t iFileName = pLnState->cFileNames; 877 if ((iFileName % 2) == 0) 878 { 879 void *pv = RTMemRealloc(pLnState->papszFileNames, sizeof(pLnState->papszFileNames[0]) * (iFileName + 2)); 880 if (!pv) 881 return VERR_NO_MEMORY; 882 pLnState->papszFileNames = (char **)pv; 883 } 884 885 /* 886 * Add the file name. 887 */ 888 if ( pszFilename[0] == '/' 889 || pszFilename[0] == '\\' 890 || (RT_C_IS_ALPHA(pszFilename[0]) && pszFilename[1] == ':') ) 891 pLnState->papszFileNames[iFileName] = RTStrDup(pszFilename); 892 else if (idxInc < pLnState->cIncPaths) 893 pLnState->papszFileNames[iFileName] = RTPathJoinA(pLnState->papszIncPaths[idxInc], pszFilename); 894 else 895 return VERR_DWARF_BAD_LINE_NUMBER_HEADER; 896 if (!pLnState->papszFileNames[iFileName]) 897 return VERR_NO_STR_MEMORY; 898 pLnState->cFileNames = iFileName + 1; 899 900 /* 901 * Sanitize the name. 902 */ 903 return rtDbgModDwarfStringToUtf8(pLnState->pDwarfMod, &pLnState->papszFileNames[iFileName]); 904 } 905 906 907 static int rtDwarfLine_StdOp_Copy(PRTDWARFLINESTATE pLnState) 908 { 909 const char *pszFile = pLnState->Regs.iFile < pLnState->cFileNames 910 ? pLnState->papszFileNames[pLnState->Regs.iFile] 911 : "<bad file name index>"; 912 RTDBGSEGIDX iSeg; 913 RTUINTPTR offSeg; 914 int rc = rtDbgModDwarfLinkAddressToSegOffset(pLnState->pDwarfMod, pLnState->Regs.uAddress, &iSeg, &offSeg); 915 if (RT_SUCCESS(rc)) 916 rc = RTDbgModLineAdd(pLnState->pDwarfMod->hCnt, pszFile, pLnState->Regs.uLine, iSeg, offSeg, NULL); 917 918 pLnState->Regs.fBasicBlock = false; 919 pLnState->Regs.fPrologueEnd = false; 920 pLnState->Regs.fEpilogueBegin = false; 921 pLnState->Regs.uDiscriminator = 0; 922 return rc; 923 } 924 925 926 /** 927 * Reset the program to the start-of-sequence state. 928 * 929 * @param pLnState The line number program state. 930 */ 931 static void rtDwarfLine_ResetState(PRTDWARFLINESTATE pLnState) 932 { 933 pLnState->Regs.uAddress = 0; 934 pLnState->Regs.idxOp = 0; 935 pLnState->Regs.iFile = 1; 936 pLnState->Regs.uLine = 1; 937 pLnState->Regs.uColumn = 0; 938 pLnState->Regs.fIsStatement = RT_BOOL(pLnState->u8DefIsStmt); 939 pLnState->Regs.fBasicBlock = false; 940 pLnState->Regs.fEndSequence = false; 941 pLnState->Regs.fPrologueEnd = false; 942 pLnState->Regs.fEpilogueBegin = false; 943 pLnState->Regs.uIsa = 0; 944 pLnState->Regs.uDiscriminator = 0; 945 } 946 947 948 /** 949 * Runs the line number program. 950 * 951 * @returns IPRT status code. 952 * @param pLnState The line number program state. 953 * @param pCursor The cursor. 954 */ 955 static int rtDwarfLine_RunProgram(PRTDWARFLINESTATE pLnState, PRTDWARFCURSOR pCursor) 956 { 957 int rc = VINF_SUCCESS; 958 rtDwarfLine_ResetState(pLnState); 959 do 960 { 961 uint8_t bOpCode = rtDwarfCursor_GetUByte(pCursor, 0); 962 if (bOpCode > pLnState->u8OpcodeBase) 963 { 964 /* 965 * Special opcode. 966 */ 967 bOpCode -= pLnState->u8OpcodeBase; 968 pLnState->Regs.uLine += bOpCode % pLnState->u8LineRange + (int32_t)pLnState->s8LineBase; 969 bOpCode /= pLnState->u8LineRange; 970 pLnState->Regs.uAddress += (pLnState->Regs.idxOp + bOpCode) / pLnState->cMaxOpsPerInstr 971 * pLnState->cbMinInstr; 972 pLnState->Regs.idxOp += (pLnState->Regs.idxOp + bOpCode) % pLnState->cMaxOpsPerInstr; 973 974 rc = rtDwarfLine_StdOp_Copy(pLnState); 975 } 976 else 977 { 978 switch (bOpCode) 979 { 980 /* 981 * Standard opcode. 982 */ 983 case DW_LNS_copy: 984 rtDwarfLine_StdOp_Copy(pLnState); 985 break; 986 987 case DW_LNS_advance_pc: 988 { 989 uint64_t u64Adv = rtDwarfCursor_GetULeb128(pCursor, 0); 990 pLnState->Regs.uAddress += (pLnState->Regs.idxOp + u64Adv) / pLnState->cMaxOpsPerInstr 991 * pLnState->cbMinInstr; 992 pLnState->Regs.idxOp += (pLnState->Regs.idxOp + u64Adv) % pLnState->cMaxOpsPerInstr; 993 break; 994 } 995 996 case DW_LNS_advance_line: 997 pLnState->Regs.uLine += rtDwarfCursor_GetSLeb128AsS32(pCursor, 0); 998 break; 999 1000 case DW_LNS_set_file: 1001 pLnState->Regs.iFile = rtDwarfCursor_GetULeb128AsU32(pCursor, 0); 1002 break; 1003 1004 case DW_LNS_set_column: 1005 pLnState->Regs.uColumn = rtDwarfCursor_GetULeb128AsU32(pCursor, 0); 1006 break; 1007 1008 case DW_LNS_negate_stmt: 1009 pLnState->Regs.fIsStatement = !pLnState->Regs.fIsStatement; 1010 break; 1011 1012 case DW_LNS_set_basic_block: 1013 pLnState->Regs.fBasicBlock = true; 1014 break; 1015 1016 case DW_LNS_const_add_pc: 1017 pLnState->Regs.uAddress += (pLnState->Regs.idxOp + 255) / pLnState->cMaxOpsPerInstr 1018 * pLnState->cbMinInstr; 1019 pLnState->Regs.idxOp += (pLnState->Regs.idxOp + 255) % pLnState->cMaxOpsPerInstr; 1020 break; 1021 1022 case DW_LNS_fixed_advance_pc: 1023 pLnState->Regs.uAddress += rtDwarfCursor_GetUHalf(pCursor, 0); 1024 pLnState->Regs.idxOp = 0; 1025 break; 1026 1027 case DW_LNS_set_prologue_end: 1028 pLnState->Regs.fPrologueEnd = true; 1029 break; 1030 1031 case DW_LNS_set_epilogue_begin: 1032 pLnState->Regs.fEpilogueBegin = true; 1033 break; 1034 1035 case DW_LNS_set_isa: 1036 pLnState->Regs.uIsa = rtDwarfCursor_GetULeb128AsU32(pCursor, 0); 1037 break; 1038 1039 default: 1040 { 1041 unsigned cOpsToSkip = pLnState->pacStdOperands[bOpCode - 1]; 1042 while (cOpsToSkip-- > 0) 1043 rc = rtDwarfCursor_SkipLeb128(pCursor); 1044 break; 1045 } 1046 1047 /* 1048 * Extended opcode. 1049 */ 1050 case DW_LNS_extended: 1051 { 1052 uint64_t cbInstr = rtDwarfCursor_GetULeb128(pCursor, UINT64_MAX); 1053 if (cbInstr > pCursor->cbUnitLeft) 1054 return VERR_DWARF_BAD_LNE; 1055 /** @todo continue here. */ 1056 bOpCode = rtDwarfCursor_GetUByte(pCursor, 0); 1057 switch (bOpCode) 1058 { 1059 case DW_LNE_end_sequence: 1060 case DW_LNE_set_address: 1061 case DW_LNE_define_file: 1062 case DW_LNE_set_descriminator: 1063 break; 1064 } 1065 break; 1066 } 1067 } 1068 } 1069 } while (RT_SUCCESS(rc)); 1070 return rc; 1071 } 1072 1073 1074 /** 1075 * Reads the include directories for a line number unit. 1076 * 1077 * @returns IPRT status code 1078 * @param pLnState The line number program state. 1079 * @param pCursor The cursor. 1080 */ 1081 static int rtDwarfLine_ReadFileNames(PRTDWARFLINESTATE pLnState, PRTDWARFCURSOR pCursor) 1082 { 1083 for (;;) 1084 { 1085 const char *psz = rtDwarfCursor_GetSZ(pCursor, NULL); 1086 if (!*psz) 1087 break; 1088 1089 uint64_t idxInc = rtDwarfCursor_GetULeb128(pCursor, UINT64_MAX); 1090 rtDwarfCursor_SkipLeb128(pCursor); /* st_mtime */ 1091 rtDwarfCursor_SkipLeb128(pCursor); /* st_size */ 1092 1093 int rc = rtDwarfLine_DefineFileName(pLnState, psz, idxInc); 1094 if (RT_FAILURE(rc)) 1095 return rc; 1096 } 1097 return VINF_SUCCESS; 1098 } 1099 1100 1101 /** 1102 * Reads the include directories for a line number unit. 1103 * 1104 * @returns IPRT status code 1105 * @param pLnState The line number program state. 1106 * @param pCursor The cursor. 1107 */ 1108 static int rtDwarfLine_ReadIncludePaths(PRTDWARFLINESTATE pLnState, PRTDWARFCURSOR pCursor) 1109 { 1110 const char *psz = ""; /* The zeroth is the unit dir. */ 1111 for (;;) 1112 { 1113 if ((pLnState->cIncPaths % 2) == 0) 1114 { 1115 void *pv = RTMemRealloc(pLnState->papszIncPaths, sizeof(pLnState->papszIncPaths[0]) * (pLnState->cIncPaths + 2)); 1116 if (!pv) 1117 return VERR_NO_MEMORY; 1118 pLnState->papszIncPaths = (const char **)pv; 1119 } 1120 pLnState->papszIncPaths[pLnState->cIncPaths] = psz; 1121 pLnState->cIncPaths++; 1122 1123 psz = rtDwarfCursor_GetSZ(pCursor, NULL); 1124 if (!*psz) 1125 break; 1126 } 1127 1128 return VINF_SUCCESS; 1129 } 1130 1131 1132 static int rtDbgModDwarfExplodeLineNumbersForUnit(PRTDBGMODDWARF pThis, PRTDWARFCURSOR pCursor) 1133 { 1134 RTDWARFLINESTATE LnState; 1135 RT_ZERO(LnState); 1136 LnState.pDwarfMod = pThis; 1137 1138 /* 1139 * Parse the header. 1140 */ 1141 LnState.uVer = rtDwarfCursor_GetUHalf(pCursor, 0); 1142 if (LnState.uVer >= 2 && LnState.uVer <= 4) 1143 return rtDwarfCursor_SkipUnit(pCursor); 1144 LnState.cbSkipAfterHdr = rtDwarfCursor_GetUOff(pCursor, 0); 1145 LnState.cbMinInstr = rtDwarfCursor_GetUByte(pCursor, 0); 1146 LnState.cMaxOpsPerInstr= rtDwarfCursor_GetUByte(pCursor, 0); 1147 LnState.u8DefIsStmt = rtDwarfCursor_GetUByte(pCursor, 0); 1148 LnState.s8LineBase = rtDwarfCursor_GetSByte(pCursor, 0); 1149 LnState.u8LineRange = rtDwarfCursor_GetUByte(pCursor, 0); 1150 LnState.u8OpcodeBase = rtDwarfCursor_GetUByte(pCursor, 0); 1151 if (!LnState.u8OpcodeBase) 1152 return VERR_DWARF_BAD_LINE_NUMBER_HEADER; 1153 1154 LnState.pacStdOperands = pCursor->pb; 1155 for (uint8_t iStdOpcode = 1; iStdOpcode < LnState.u8OpcodeBase; iStdOpcode++) 1156 rtDwarfCursor_GetUByte(pCursor, 0); 1157 1158 int rc = rtDwarfLine_ReadIncludePaths(&LnState, pCursor); 1159 if (RT_SUCCESS(rc)) 1160 rc = rtDwarfLine_ReadFileNames(&LnState, pCursor); 1161 1162 /* 1163 * Run the program.... 1164 */ 1165 if (RT_SUCCESS(rc)) 1166 rc = rtDwarfLine_RunProgram(&LnState, pCursor); 1167 1168 /* 1169 * Clean up. 1170 */ 1171 size_t i = LnState.cFileNames; 1172 while (i-- > 0) 1173 RTStrFree(LnState.papszFileNames[i]); 1174 RTMemFree(LnState.papszFileNames); 1175 RTMemFree(LnState.papszIncPaths); 1176 1177 Assert(rtDwarfCursor_IsAtEndOfUnit(pCursor) || RT_FAILURE(rc)); 1178 return rc; 1179 } 1180 1181 1182 /** 494 1183 * Explodes the line number table. 495 1184 * … … 504 1193 return VINF_SUCCESS; 505 1194 506 RTDWARF SECTRDR SectRdr;507 int rc = rtDwarf SectRdrInit(&SectRdr, pThis, krtDbgModDwarfSect_line);1195 RTDWARFCURSOR Cursor; 1196 int rc = rtDwarfCursor_Init(&Cursor, pThis, krtDbgModDwarfSect_line); 508 1197 if (RT_FAILURE(rc)) 509 1198 return rc; 510 1199 511 /* 512 * Parse the header. 513 */ 514 uint32_t const uVer = rtDwarfSectRdrGetUHalf(&SectRdr, 0); 515 uint64_t const cbSkipAfterHdr = rtDwarfSectRdrGetUOff(&SectRdr, 0); 516 uint8_t const cbMinInstr = rtDwarfSectRdrGetUByte(&SectRdr, 0); 517 uint8_t const cbMaxInstr = rtDwarfSectRdrGetUByte(&SectRdr, 0); 518 uint8_t const fDefIsStmt = rtDwarfSectRdrGetUByte(&SectRdr, 0); 519 int8_t const i8LineBase = rtDwarfSectRdrGetSByte(&SectRdr, 0); 520 uint8_t const u8LineRange = rtDwarfSectRdrGetUByte(&SectRdr, 0); 521 uint8_t const u8OpcodeBase = rtDwarfSectRdrGetUByte(&SectRdr, 0); 522 /*...*/ 523 524 if (uVer >= 2 && uVer <= 4) 525 { 526 /* 527 * Run the program.... 528 */ 529 530 } 531 532 rtDwarfSectRdrDelete(&SectRdr); 1200 while ( rtDwarfCursor_IsAtEnd(&Cursor) 1201 && RT_SUCCESS(rc)) 1202 rc = rtDbgModDwarfExplodeLineNumbersForUnit(pThis, &Cursor); 1203 1204 1205 rtDwarfCursor_Delete(&Cursor); 533 1206 return rc; 534 1207 }
Note:
See TracChangeset
for help on using the changeset viewer.