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

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

Issue 1996243002: Workaround ARM tracing issues for non-component builds. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 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
« no previous file with comments | « base/third_party/symbolize/symbolize.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 386 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 public: 397 public:
398 explicit LineReader(int fd, char *buf, int buf_len) : fd_(fd), 398 explicit LineReader(int fd, char *buf, int buf_len) : fd_(fd),
399 buf_(buf), buf_len_(buf_len), bol_(buf), eol_(buf), eod_(buf) { 399 buf_(buf), buf_len_(buf_len), bol_(buf), eol_(buf), eod_(buf) {
400 } 400 }
401 401
402 // Read '\n'-terminated line from file. On success, modify "bol" 402 // Read '\n'-terminated line from file. On success, modify "bol"
403 // and "eol", then return true. Otherwise, return false. 403 // and "eol", then return true. Otherwise, return false.
404 // 404 //
405 // Note: if the last line doesn't end with '\n', the line will be 405 // Note: if the last line doesn't end with '\n', the line will be
406 // dropped. It's an intentional behavior to make the code simple. 406 // dropped. It's an intentional behavior to make the code simple.
407 bool ReadLine(const char **bol, const char **eol) { 407 bool ReadLine(char **bol, char **eol) {
408 if (BufferIsEmpty()) { // First time. 408 if (BufferIsEmpty()) { // First time.
409 const ssize_t num_bytes = ReadPersistent(fd_, buf_, buf_len_); 409 const ssize_t num_bytes = ReadPersistent(fd_, buf_, buf_len_);
410 if (num_bytes <= 0) { // EOF or error. 410 if (num_bytes <= 0) { // EOF or error.
411 return false; 411 return false;
412 } 412 }
413 eod_ = buf_ + num_bytes; 413 eod_ = buf_ + num_bytes;
414 bol_ = buf_; 414 bol_ = buf_;
415 } else { 415 } else {
416 bol_ = eol_ + 1; // Advance to the next line in the buffer. 416 bol_ = eol_ + 1; // Advance to the next line in the buffer.
417 SAFE_ASSERT(bol_ <= eod_); // "bol_" can point to "eod_". 417 SAFE_ASSERT(bol_ <= eod_); // "bol_" can point to "eod_".
(...skipping 18 matching lines...) Expand all
436 return false; 436 return false;
437 } 437 }
438 *eol_ = '\0'; // Replace '\n' with '\0'. 438 *eol_ = '\0'; // Replace '\n' with '\0'.
439 439
440 *bol = bol_; 440 *bol = bol_;
441 *eol = eol_; 441 *eol = eol_;
442 return true; 442 return true;
443 } 443 }
444 444
445 // Beginning of line. 445 // Beginning of line.
446 const char *bol() { 446 char *bol() {
447 return bol_; 447 return bol_;
448 } 448 }
449 449
450 // End of line. 450 // End of line.
451 const char *eol() { 451 char *eol() {
452 return eol_; 452 return eol_;
453 } 453 }
454 454
455 private: 455 private:
456 explicit LineReader(const LineReader&); 456 explicit LineReader(const LineReader&);
457 void operator=(const LineReader&); 457 void operator=(const LineReader&);
458 458
459 char *FindLineFeed() { 459 char *FindLineFeed() {
460 return reinterpret_cast<char *>(memchr(bol_, '\n', eod_ - bol_)); 460 return reinterpret_cast<char *>(memchr(bol_, '\n', eod_ - bol_));
461 } 461 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
502 // |out_file_name|, and attempts to open the object file. If the object 502 // |out_file_name|, and attempts to open the object file. If the object
503 // file is opened successfully, returns the file descriptor. Otherwise, 503 // file is opened successfully, returns the file descriptor. Otherwise,
504 // returns -1. |out_file_name_size| is the size of the file name buffer 504 // returns -1. |out_file_name_size| is the size of the file name buffer
505 // (including the null-terminator). 505 // (including the null-terminator).
506 static ATTRIBUTE_NOINLINE int 506 static ATTRIBUTE_NOINLINE int
507 OpenObjectFileContainingPcAndGetStartAddress(uint64_t pc, 507 OpenObjectFileContainingPcAndGetStartAddress(uint64_t pc,
508 uint64_t &start_address, 508 uint64_t &start_address,
509 uint64_t &base_address, 509 uint64_t &base_address,
510 char *out_file_name, 510 char *out_file_name,
511 int out_file_name_size) { 511 int out_file_name_size) {
512 int object_fd; 512 struct FindArgs {
513 const uint64_t pc;
514 uint64_t* out_start_address;
515 uint64_t* out_base_address;
516 char* out_file_name;
517 int out_file_name_size;
518 // Fields below are default initialized
519 int num_maps;
520 int out_object_fd;
521 };
513 522
514 // Open /proc/self/maps. 523 auto find_callback = [](void* data, const MappedRegion& region) -> bool {
515 int maps_fd; 524 FindArgs* args = static_cast<FindArgs*>(data);
516 NO_INTR(maps_fd = open("/proc/self/maps", O_RDONLY)); 525 args->num_maps++;
517 FileDescriptor wrapped_maps_fd(maps_fd);
518 if (wrapped_maps_fd.get() < 0) {
519 return -1;
520 }
521
522 // Iterate over maps and look for the map containing the pc. Then
523 // look into the symbol tables inside.
524 char buf[1024]; // Big enough for line of sane /proc/self/maps
525 int num_maps = 0;
526 LineReader reader(wrapped_maps_fd.get(), buf, sizeof(buf));
527 while (true) {
528 num_maps++;
529 const char *cursor;
530 const char *eol;
531 if (!reader.ReadLine(&cursor, &eol)) { // EOF or malformed line.
532 return -1;
533 }
534
535 // Start parsing line in /proc/self/maps. Here is an example:
536 //
537 // 08048000-0804c000 r-xp 00000000 08:01 2142121 /bin/cat
538 //
539 // We want start address (08048000), end address (0804c000), flags
540 // (r-xp) and file name (/bin/cat).
541
542 // Read start address.
543 cursor = GetHex(cursor, eol, &start_address);
544 if (cursor == eol || *cursor != '-') {
545 return -1; // Malformed line.
546 }
547 ++cursor; // Skip '-'.
548
549 // Read end address.
550 uint64_t end_address;
551 cursor = GetHex(cursor, eol, &end_address);
552 if (cursor == eol || *cursor != ' ') {
553 return -1; // Malformed line.
554 }
555 ++cursor; // Skip ' '.
556 526
557 // Check start and end addresses. 527 // Check start and end addresses.
558 if (!(start_address <= pc && pc < end_address)) { 528 if (!(region.start_address <= args->pc && args->pc < region.end_address)) {
559 continue; // We skip this map. PC isn't in this map. 529 return false; // We skip this map. PC isn't in this map.
560 }
561
562 // Read flags. Skip flags until we encounter a space or eol.
563 const char * const flags_start = cursor;
564 while (cursor < eol && *cursor != ' ') {
565 ++cursor;
566 }
567 // We expect at least four letters for flags (ex. "r-xp").
568 if (cursor == eol || cursor < flags_start + 4) {
569 return -1; // Malformed line.
570 } 530 }
571 531
572 // Check flags. We are only interested in "r-x" maps. 532 // Check flags. We are only interested in "r-x" maps.
573 if (memcmp(flags_start, "r-x", 3) != 0) { // Not a "r-x" map. 533 if (memcmp(region.flags, "r-x", 3) != 0) { // Not a "r-x" map.
574 continue; // We skip this map. 534 return false; // We skip this map.
575 } 535 }
576 ++cursor; // Skip ' '.
577 536
578 // Read file offset. 537 *args->out_start_address = region.start_address;
579 uint64_t file_offset;
580 cursor = GetHex(cursor, eol, &file_offset);
581 if (cursor == eol || *cursor != ' ') {
582 return -1; // Malformed line.
583 }
584 ++cursor; // Skip ' '.
585 538
586 // Don't subtract 'start_address' from the first entry: 539 // Don't subtract 'start_address' from the first entry:
587 // * If a binary is compiled w/o -pie, then the first entry in 540 // * If a binary is compiled w/o -pie, then the first entry in
588 // process maps is likely the binary itself (all dynamic libs 541 // process maps is likely the binary itself (all dynamic libs
589 // are mapped higher in address space). For such a binary, 542 // are mapped higher in address space). For such a binary,
590 // instruction offset in binary coincides with the actual 543 // instruction offset in binary coincides with the actual
591 // instruction address in virtual memory (as code section 544 // instruction address in virtual memory (as code section
592 // is mapped to a fixed memory range). 545 // is mapped to a fixed memory range).
593 // * If a binary is compiled with -pie, all the modules are 546 // * If a binary is compiled with -pie, all the modules are
594 // mapped high at address space (in particular, higher than 547 // mapped high at address space (in particular, higher than
595 // shadow memory of the tool), so the module can't be the 548 // shadow memory of the tool), so the module can't be the
596 // first entry. 549 // first entry.
597 base_address = ((num_maps == 1) ? 0U : start_address) - file_offset; 550 *args->out_base_address =
551 ((args->num_maps == 1) ? 0U : region.start_address) -
552 region.file_offset;
553
554 // Open region's file.
555 NO_INTR(args->out_object_fd = open(region.name, O_RDONLY));
556 if (args->out_object_fd < 0) {
557 // Failed to open object file. Copy the object file name to
558 // |out_file_name|.
559 strncpy(args->out_file_name, region.name, args->out_file_name_size);
560 // Making sure |out_file_name| is always null-terminated.
561 args->out_file_name[args->out_file_name_size - 1] = '\0';
562 }
563
564 return true; // We found the entry; stop iterating.
565 };
566
567 FindArgs args = {
568 pc,
569 &start_address,
570 &base_address,
571 out_file_name,
572 out_file_name_size
573 };
574 bool found = FindMappedRegion(&args, find_callback);
575 return found ? args.out_object_fd : -1;
576 }
577
578 bool FindMappedRegion(void* callback_data,
579 bool (*callback)(void*, const MappedRegion&)) {
580 // Open /proc/self/maps.
581 int maps_fd;
582 NO_INTR(maps_fd = open("/proc/self/maps", O_RDONLY));
583 FileDescriptor wrapped_maps_fd(maps_fd);
584 if (wrapped_maps_fd.get() < 0) {
585 return false;
586 }
587
588 char buf[1024]; // Big enough for line of sane /proc/self/maps
589 int num_maps = 0;
590 MappedRegion region;
591 LineReader reader(wrapped_maps_fd.get(), buf, sizeof(buf));
592 while (true) {
593 num_maps++;
594 char *cursor;
595 char *eol;
596 if (!reader.ReadLine(&cursor, &eol)) { // EOF or malformed line.
597 break;
598 }
599
600 // Zero-terminate the line.
601 *eol = 0;
602
603 // Start parsing line in /proc/self/maps. Here is an example:
604 //
605 // 08048000-0804c000 r-xp 00000000 08:01 2142121 /bin/cat
606 //
607 // We want start address (08048000), end address (0804c000), flags
608 // (r-xp), file offset (2142121) and file name (/bin/cat).
609
610 // Read start address.
611 cursor = GetHex(cursor, eol, &region.start_address);
612 if (cursor == eol || *cursor != '-') {
613 break; // Malformed line.
614 }
615 ++cursor; // Skip '-'.
616
617 // Read end address.
618 uint64_t end_address;
619 cursor = GetHex(cursor, eol, &region.end_address);
620 if (cursor == eol || *cursor != ' ') {
621 break; // Malformed line.
622 }
623 ++cursor; // Skip ' '.
624
625 // Read flags. Skip flags until we encounter a space or eol.
626 region.flags = cursor;
627 while (cursor < eol && *cursor != ' ') {
628 ++cursor;
629 }
630 // We expect at least four letters for flags (ex. "r-xp").
631 if (cursor == eol || cursor < region.flags + 4) {
632 break; // Malformed line.
633 }
634 // Replace ' ' with zero and advance.
635 *cursor++ = 0;
636
637 // Read file offset.
638 cursor = GetHex(cursor, eol, &region.file_offset);
639 if (cursor == eol || *cursor != ' ') {
640 break; // Malformed line.
641 }
642 ++cursor; // Skip ' '.
598 643
599 // Skip to file name. "cursor" now points to dev. We need to 644 // Skip to file name. "cursor" now points to dev. We need to
600 // skip at least two spaces for dev and inode. 645 // skip at least two spaces for dev and inode. Note that name can
646 // be empty (cursor == eol).
601 int num_spaces = 0; 647 int num_spaces = 0;
602 while (cursor < eol) { 648 while (cursor < eol) {
603 if (*cursor == ' ') { 649 if (*cursor == ' ') {
604 ++num_spaces; 650 ++num_spaces;
605 } else if (num_spaces >= 2) { 651 } else if (num_spaces >= 2) {
606 // The first non-space character after skipping two spaces 652 // The first non-space character after skipping two spaces
607 // is the beginning of the file name. 653 // is the beginning of the file name.
608 break; 654 break;
609 } 655 }
610 ++cursor; 656 ++cursor;
611 } 657 }
612 if (cursor == eol) { 658
613 return -1; // Malformed line. 659 // Finally, "cursor" now points to file name.
660 region.name = cursor;
661
662 // Report found region to the callback.
663 if (callback(callback_data, region)) {
664 return true; // Callback stopped the iteration.
614 } 665 }
666 }
615 667
616 // Finally, "cursor" now points to file name of our interest. 668 return false;
617 NO_INTR(object_fd = open(cursor, O_RDONLY));
618 if (object_fd < 0) {
619 // Failed to open object file. Copy the object file name to
620 // |out_file_name|.
621 strncpy(out_file_name, cursor, out_file_name_size);
622 // Making sure |out_file_name| is always null-terminated.
623 out_file_name[out_file_name_size - 1] = '\0';
624 return -1;
625 }
626 return object_fd;
627 }
628 } 669 }
629 670
630 // POSIX doesn't define any async-signal safe function for converting 671 // POSIX doesn't define any async-signal safe function for converting
631 // an integer to ASCII. We'll have to define our own version. 672 // an integer to ASCII. We'll have to define our own version.
632 // itoa_r() converts a (signed) integer to ASCII. It returns "buf", if the 673 // itoa_r() converts a (signed) integer to ASCII. It returns "buf", if the
633 // conversion was successful or NULL otherwise. It never writes more than "sz" 674 // conversion was successful or NULL otherwise. It never writes more than "sz"
634 // bytes. Output will be truncated as needed, and a NUL character is always 675 // bytes. Output will be truncated as needed, and a NUL character is always
635 // appended. 676 // appended.
636 // NOTE: code from sandbox/linux/seccomp-bpf/demo.cc. 677 // NOTE: code from sandbox/linux/seccomp-bpf/demo.cc.
637 char *itoa_r(intptr_t i, char *buf, size_t sz, int base, size_t padding) { 678 char *itoa_r(intptr_t i, char *buf, size_t sz, int base, size_t padding) {
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
840 881
841 // TODO: Support other environments. 882 // TODO: Support other environments.
842 bool Symbolize(void *pc, char *out, int out_size) { 883 bool Symbolize(void *pc, char *out, int out_size) {
843 assert(0); 884 assert(0);
844 return false; 885 return false;
845 } 886 }
846 887
847 _END_GOOGLE_NAMESPACE_ 888 _END_GOOGLE_NAMESPACE_
848 889
849 #endif 890 #endif
OLDNEW
« no previous file with comments | « base/third_party/symbolize/symbolize.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698