Chromium Code Reviews| 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 |