OLD | NEW |
---|---|
1 // Copyright (c) 2006, Google Inc. | 1 // Copyright (c) 2006, Google Inc. |
2 // All rights reserved. | 2 // All rights reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // met: |
7 // | 7 // |
8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
(...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
476 (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')) { | 476 (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')) { |
477 *hex = (*hex << 4) | (ch < 'A' ? ch - '0' : (ch & 0xF) + 9); | 477 *hex = (*hex << 4) | (ch < 'A' ? ch - '0' : (ch & 0xF) + 9); |
478 } else { // Encountered the first non-hex character. | 478 } else { // Encountered the first non-hex character. |
479 break; | 479 break; |
480 } | 480 } |
481 } | 481 } |
482 SAFE_ASSERT(p <= end); | 482 SAFE_ASSERT(p <= end); |
483 return const_cast<char *>(p); | 483 return const_cast<char *>(p); |
484 } | 484 } |
485 | 485 |
486 // Search for the object file (from /proc/self/maps) that contains | 486 bool FindObjectFileNameContainingPcAndGetStartAddress( |
487 // the specified pc. If found, open this file and return the file handle, | 487 void* pc, char *out, int out_size, uint64_t *start_address) { |
488 // and also set start_address to the start address of where this object | 488 uint64_t pc0 = reinterpret_cast<uintptr_t>(pc); |
satorux1
2013/06/13 01:58:10
pc0 looks a bit cryptic. maybe:
void *in_pc, ...)
scherkus (not reviewing)
2013/06/13 02:20:46
I was following SymbolizeAndDemangle() but agree i
| |
489 // file is mapped to in memory. Otherwise, return -1. | |
490 static ATTRIBUTE_NOINLINE int | |
491 OpenObjectFileContainingPcAndGetStartAddress(uint64_t pc, | |
492 uint64_t &start_address) { | |
493 int object_fd; | 489 int object_fd; |
494 | 490 |
495 // Open /proc/self/maps. | 491 // Open /proc/self/maps. |
496 int maps_fd; | 492 int maps_fd; |
497 NO_INTR(maps_fd = open("/proc/self/maps", O_RDONLY)); | 493 NO_INTR(maps_fd = open("/proc/self/maps", O_RDONLY)); |
498 FileDescriptor wrapped_maps_fd(maps_fd); | 494 FileDescriptor wrapped_maps_fd(maps_fd); |
499 if (wrapped_maps_fd.get() < 0) { | 495 if (wrapped_maps_fd.get() < 0) { |
500 return -1; | 496 return false; |
501 } | 497 } |
502 | 498 |
503 // Iterate over maps and look for the map containing the pc. Then | 499 // Iterate over maps and look for the map containing the pc. Then |
504 // look into the symbol tables inside. | 500 // look into the symbol tables inside. |
505 char buf[1024]; // Big enough for line of sane /proc/self/maps | 501 char buf[1024]; // Big enough for line of sane /proc/self/maps |
506 LineReader reader(wrapped_maps_fd.get(), buf, sizeof(buf)); | 502 LineReader reader(wrapped_maps_fd.get(), buf, sizeof(buf)); |
507 while (true) { | 503 while (true) { |
508 const char *cursor; | 504 const char *cursor; |
509 const char *eol; | 505 const char *eol; |
510 if (!reader.ReadLine(&cursor, &eol)) { // EOF or malformed line. | 506 if (!reader.ReadLine(&cursor, &eol)) { // EOF or malformed line. |
511 return -1; | 507 return false; |
512 } | 508 } |
513 | 509 |
514 // Start parsing line in /proc/self/maps. Here is an example: | 510 // Start parsing line in /proc/self/maps. Here is an example: |
515 // | 511 // |
516 // 08048000-0804c000 r-xp 00000000 08:01 2142121 /bin/cat | 512 // 08048000-0804c000 r-xp 00000000 08:01 2142121 /bin/cat |
517 // | 513 // |
518 // We want start address (08048000), end address (0804c000), flags | 514 // We want start address (08048000), end address (0804c000), flags |
519 // (r-xp) and file name (/bin/cat). | 515 // (r-xp) and file name (/bin/cat). |
520 | 516 |
521 // Read start address. | 517 // Read start address. |
522 cursor = GetHex(cursor, eol, &start_address); | 518 cursor = GetHex(cursor, eol, start_address); |
523 if (cursor == eol || *cursor != '-') { | 519 if (cursor == eol || *cursor != '-') { |
524 return -1; // Malformed line. | 520 return false; // Malformed line. |
525 } | 521 } |
526 ++cursor; // Skip '-'. | 522 ++cursor; // Skip '-'. |
527 | 523 |
528 // Read end address. | 524 // Read end address. |
529 uint64_t end_address; | 525 uint64_t end_address; |
530 cursor = GetHex(cursor, eol, &end_address); | 526 cursor = GetHex(cursor, eol, &end_address); |
531 if (cursor == eol || *cursor != ' ') { | 527 if (cursor == eol || *cursor != ' ') { |
532 return -1; // Malformed line. | 528 return false; // Malformed line. |
533 } | 529 } |
534 ++cursor; // Skip ' '. | 530 ++cursor; // Skip ' '. |
535 | 531 |
536 // Check start and end addresses. | 532 // Check start and end addresses. |
537 if (!(start_address <= pc && pc < end_address)) { | 533 if (!(*start_address <= pc0 && pc0 < end_address)) { |
538 continue; // We skip this map. PC isn't in this map. | 534 continue; // We skip this map. PC isn't in this map. |
539 } | 535 } |
540 | 536 |
541 // Read flags. Skip flags until we encounter a space or eol. | 537 // Read flags. Skip flags until we encounter a space or eol. |
542 const char * const flags_start = cursor; | 538 const char * const flags_start = cursor; |
543 while (cursor < eol && *cursor != ' ') { | 539 while (cursor < eol && *cursor != ' ') { |
544 ++cursor; | 540 ++cursor; |
545 } | 541 } |
546 // We expect at least four letters for flags (ex. "r-xp"). | 542 // We expect at least four letters for flags (ex. "r-xp"). |
547 if (cursor == eol || cursor < flags_start + 4) { | 543 if (cursor == eol || cursor < flags_start + 4) { |
548 return -1; // Malformed line. | 544 return false; // Malformed line. |
549 } | 545 } |
550 | 546 |
551 // Check flags. We are only interested in "r-x" maps. | 547 // Check flags. We are only interested in "r-x" maps. |
552 if (memcmp(flags_start, "r-x", 3) != 0) { // Not a "r-x" map. | 548 if (memcmp(flags_start, "r-x", 3) != 0) { // Not a "r-x" map. |
553 continue; // We skip this map. | 549 continue; // We skip this map. |
554 } | 550 } |
555 ++cursor; // Skip ' '. | 551 ++cursor; // Skip ' '. |
556 | 552 |
557 // Skip to file name. "cursor" now points to file offset. We need to | 553 // Skip to file name. "cursor" now points to file offset. We need to |
558 // skip at least three spaces for file offset, dev, and inode. | 554 // skip at least three spaces for file offset, dev, and inode. |
559 int num_spaces = 0; | 555 int num_spaces = 0; |
560 while (cursor < eol) { | 556 while (cursor < eol) { |
561 if (*cursor == ' ') { | 557 if (*cursor == ' ') { |
562 ++num_spaces; | 558 ++num_spaces; |
563 } else if (num_spaces >= 3) { | 559 } else if (num_spaces >= 3) { |
564 // The first non-space character after skipping three spaces | 560 // The first non-space character after skipping three spaces |
565 // is the beginning of the file name. | 561 // is the beginning of the file name. |
566 break; | 562 break; |
567 } | 563 } |
568 ++cursor; | 564 ++cursor; |
569 } | 565 } |
570 if (cursor == eol) { | 566 if (cursor == eol) { |
571 return -1; // Malformed line. | 567 return false; // Malformed line. |
572 } | 568 } |
573 | 569 |
574 // Finally, "cursor" now points to file name of our interest. | 570 // Finally, "cursor" now points to file name of our interest. |
575 NO_INTR(object_fd = open(cursor, O_RDONLY)); | 571 if (strlen(cursor) >= out_size) { |
satorux1
2013/06/13 01:58:10
maybe slightly easier to read:
if (stlren(cursor)
scherkus (not reviewing)
2013/06/13 02:20:46
Done + beefed up comment on next line
| |
576 if (object_fd < 0) { | 572 return false; // Not enough room to write file name. |
577 return -1; | |
578 } | 573 } |
579 return object_fd; | 574 |
575 strcpy(out, cursor); | |
576 return true; | |
580 } | 577 } |
581 } | 578 } |
582 | 579 |
583 // The implementation of our symbolization routine. If it | 580 // The implementation of our symbolization routine. If it |
584 // successfully finds the symbol containing "pc" and obtains the | 581 // successfully finds the symbol containing "pc" and obtains the |
585 // symbol name, returns true and write the symbol name to "out". | 582 // symbol name, returns true and write the symbol name to "out". |
586 // Otherwise, returns false. If Callback function is installed via | 583 // Otherwise, returns false. If Callback function is installed via |
587 // InstallSymbolizeCallback(), the function is also called in this function, | 584 // InstallSymbolizeCallback(), the function is also called in this function, |
588 // and "out" is used as its output. | 585 // and "out" is used as its output. |
589 // To keep stack consumption low, we would like this function to not | 586 // To keep stack consumption low, we would like this function to not |
590 // get inlined. | 587 // get inlined. |
591 static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out, | 588 static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out, |
592 int out_size) { | 589 int out_size) { |
593 uint64_t pc0 = reinterpret_cast<uintptr_t>(pc); | 590 uint64_t pc0 = reinterpret_cast<uintptr_t>(pc); |
594 uint64_t start_address = 0; | 591 uint64_t start_address = 0; |
595 | 592 |
596 int object_fd = OpenObjectFileContainingPcAndGetStartAddress(pc0, | 593 char buf[256]; |
scherkus (not reviewing)
2013/06/13 01:27:44
this additional buffer allocation is a bit crummy
satorux1
2013/06/13 01:58:10
sounds reasonable. buf -> file_name?
| |
597 start_address); | 594 if (!FindObjectFileNameContainingPcAndGetStartAddress( |
598 if (object_fd == -1) { | 595 pc, buf, sizeof(buf), &start_address)) { |
596 return false; | |
597 } | |
598 | |
599 int object_fd; | |
satorux1
2013/06/13 01:58:10
object_fd = - 1;
to be extra defensive.
scherkus (not reviewing)
2013/06/13 02:20:46
Done.
| |
600 NO_INTR(object_fd = open(buf, O_RDONLY)); | |
601 if (object_fd < 0) { | |
599 return false; | 602 return false; |
600 } | 603 } |
601 FileDescriptor wrapped_object_fd(object_fd); | 604 FileDescriptor wrapped_object_fd(object_fd); |
602 int elf_type = FileGetElfType(wrapped_object_fd.get()); | 605 int elf_type = FileGetElfType(wrapped_object_fd.get()); |
603 if (elf_type == -1) { | 606 if (elf_type == -1) { |
604 return false; | 607 return false; |
605 } | 608 } |
606 if (g_symbolize_callback) { | 609 if (g_symbolize_callback) { |
607 // Run the call back if it's installed. | 610 // Run the call back if it's installed. |
608 // Note: relocation (and much of the rest of this code) will be | 611 // Note: relocation (and much of the rest of this code) will be |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
674 | 677 |
675 // TODO: Support other environments. | 678 // TODO: Support other environments. |
676 bool Symbolize(void *pc, char *out, int out_size) { | 679 bool Symbolize(void *pc, char *out, int out_size) { |
677 assert(0); | 680 assert(0); |
678 return false; | 681 return false; |
679 } | 682 } |
680 | 683 |
681 _END_GOOGLE_NAMESPACE_ | 684 _END_GOOGLE_NAMESPACE_ |
682 | 685 |
683 #endif | 686 #endif |
OLD | NEW |