Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(306)

Side by Side Diff: base/third_party/symbolize/symbolize.cc

Issue 16770006: Implement basic stack traces on Android and reenable unit tests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: refactor symbolize Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
OLDNEW
« base/third_party/symbolize/symbolize.h ('K') | « base/third_party/symbolize/symbolize.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698