Index: base/third_party/symbolize/symbolize.cc |
diff --git a/base/third_party/symbolize/symbolize.cc b/base/third_party/symbolize/symbolize.cc |
index db82b04d4df254a345107f532c636511cc5e6753..02500c35f5910164d5bf7b783664b42b3329859c 100644 |
--- a/base/third_party/symbolize/symbolize.cc |
+++ b/base/third_party/symbolize/symbolize.cc |
@@ -404,7 +404,7 @@ class LineReader { |
// |
// Note: if the last line doesn't end with '\n', the line will be |
// dropped. It's an intentional behavior to make the code simple. |
- bool ReadLine(const char **bol, const char **eol) { |
+ bool ReadLine(char **bol, char **eol) { |
if (BufferIsEmpty()) { // First time. |
const ssize_t num_bytes = ReadPersistent(fd_, buf_, buf_len_); |
if (num_bytes <= 0) { // EOF or error. |
@@ -443,12 +443,12 @@ class LineReader { |
} |
// Beginning of line. |
- const char *bol() { |
+ char *bol() { |
return bol_; |
} |
// End of line. |
- const char *eol() { |
+ char *eol() { |
return eol_; |
} |
@@ -509,95 +509,141 @@ OpenObjectFileContainingPcAndGetStartAddress(uint64_t pc, |
uint64_t &base_address, |
char *out_file_name, |
int out_file_name_size) { |
- int object_fd; |
+ struct FindArgs { |
+ const uint64_t pc; |
+ uint64_t* out_start_address; |
+ uint64_t* out_base_address; |
+ char* out_file_name; |
+ int out_file_name_size; |
+ // Fields below are default initialized |
+ int num_maps; |
+ int out_object_fd; |
+ }; |
+ |
+ auto find_callback = [](void* data, const MappedRegion& region) -> bool { |
+ FindArgs* args = static_cast<FindArgs*>(data); |
+ args->num_maps++; |
+ // Check start and end addresses. |
+ if (!(region.start_address <= args->pc && args->pc < region.end_address)) { |
+ return false; // We skip this map. PC isn't in this map. |
+ } |
+ |
+ // Check flags. We are only interested in "r-x" maps. |
+ if (memcmp(region.flags, "r-x", 3) != 0) { // Not a "r-x" map. |
+ return false; // We skip this map. |
+ } |
+ |
+ *args->out_start_address = region.start_address; |
+ |
+ // Don't subtract 'start_address' from the first entry: |
+ // * If a binary is compiled w/o -pie, then the first entry in |
+ // process maps is likely the binary itself (all dynamic libs |
+ // are mapped higher in address space). For such a binary, |
+ // instruction offset in binary coincides with the actual |
+ // instruction address in virtual memory (as code section |
+ // is mapped to a fixed memory range). |
+ // * If a binary is compiled with -pie, all the modules are |
+ // mapped high at address space (in particular, higher than |
+ // shadow memory of the tool), so the module can't be the |
+ // first entry. |
+ *args->out_base_address = |
+ ((args->num_maps == 1) ? 0U : region.start_address) - |
+ region.file_offset; |
+ |
+ // Open region's file. |
+ NO_INTR(args->out_object_fd = open(region.name, O_RDONLY)); |
+ if (args->out_object_fd < 0) { |
+ // Failed to open object file. Copy the object file name to |
+ // |out_file_name|. |
+ strncpy(args->out_file_name, region.name, args->out_file_name_size); |
+ // Making sure |out_file_name| is always null-terminated. |
+ args->out_file_name[args->out_file_name_size - 1] = '\0'; |
+ } |
+ |
+ return true; // We found the entry; stop iterating. |
+ }; |
+ |
+ FindArgs args = { |
+ pc, |
+ &start_address, |
+ &base_address, |
+ out_file_name, |
+ out_file_name_size |
+ }; |
+ bool found = FindMappedRegion(&args, find_callback); |
+ return found ? args.out_object_fd : -1; |
+} |
+ |
+bool FindMappedRegion(void* callback_data, |
+ bool (*callback)(void*, const MappedRegion&)) { |
// Open /proc/self/maps. |
int maps_fd; |
NO_INTR(maps_fd = open("/proc/self/maps", O_RDONLY)); |
FileDescriptor wrapped_maps_fd(maps_fd); |
if (wrapped_maps_fd.get() < 0) { |
- return -1; |
+ return false; |
} |
- // Iterate over maps and look for the map containing the pc. Then |
- // look into the symbol tables inside. |
char buf[1024]; // Big enough for line of sane /proc/self/maps |
int num_maps = 0; |
+ MappedRegion region; |
LineReader reader(wrapped_maps_fd.get(), buf, sizeof(buf)); |
while (true) { |
num_maps++; |
- const char *cursor; |
- const char *eol; |
+ char *cursor; |
+ char *eol; |
if (!reader.ReadLine(&cursor, &eol)) { // EOF or malformed line. |
- return -1; |
+ break; |
} |
+ // Zero-terminate the line. |
+ *eol = 0; |
+ |
// Start parsing line in /proc/self/maps. Here is an example: |
// |
// 08048000-0804c000 r-xp 00000000 08:01 2142121 /bin/cat |
// |
// We want start address (08048000), end address (0804c000), flags |
- // (r-xp) and file name (/bin/cat). |
+ // (r-xp), file offset (2142121) and file name (/bin/cat). |
// Read start address. |
- cursor = GetHex(cursor, eol, &start_address); |
+ cursor = GetHex(cursor, eol, ®ion.start_address); |
if (cursor == eol || *cursor != '-') { |
- return -1; // Malformed line. |
+ break; // Malformed line. |
} |
++cursor; // Skip '-'. |
// Read end address. |
uint64_t end_address; |
- cursor = GetHex(cursor, eol, &end_address); |
+ cursor = GetHex(cursor, eol, ®ion.end_address); |
if (cursor == eol || *cursor != ' ') { |
- return -1; // Malformed line. |
+ break; // Malformed line. |
} |
++cursor; // Skip ' '. |
- // Check start and end addresses. |
- if (!(start_address <= pc && pc < end_address)) { |
- continue; // We skip this map. PC isn't in this map. |
- } |
- |
// Read flags. Skip flags until we encounter a space or eol. |
- const char * const flags_start = cursor; |
+ region.flags = cursor; |
while (cursor < eol && *cursor != ' ') { |
++cursor; |
} |
// We expect at least four letters for flags (ex. "r-xp"). |
- if (cursor == eol || cursor < flags_start + 4) { |
- return -1; // Malformed line. |
+ if (cursor == eol || cursor < region.flags + 4) { |
+ break; // Malformed line. |
} |
- |
- // Check flags. We are only interested in "r-x" maps. |
- if (memcmp(flags_start, "r-x", 3) != 0) { // Not a "r-x" map. |
- continue; // We skip this map. |
- } |
- ++cursor; // Skip ' '. |
+ // Replace ' ' with zero and advance. |
+ *cursor++ = 0; |
// Read file offset. |
- uint64_t file_offset; |
- cursor = GetHex(cursor, eol, &file_offset); |
+ cursor = GetHex(cursor, eol, ®ion.file_offset); |
if (cursor == eol || *cursor != ' ') { |
- return -1; // Malformed line. |
+ break; // Malformed line. |
} |
++cursor; // Skip ' '. |
- // Don't subtract 'start_address' from the first entry: |
- // * If a binary is compiled w/o -pie, then the first entry in |
- // process maps is likely the binary itself (all dynamic libs |
- // are mapped higher in address space). For such a binary, |
- // instruction offset in binary coincides with the actual |
- // instruction address in virtual memory (as code section |
- // is mapped to a fixed memory range). |
- // * If a binary is compiled with -pie, all the modules are |
- // mapped high at address space (in particular, higher than |
- // shadow memory of the tool), so the module can't be the |
- // first entry. |
- base_address = ((num_maps == 1) ? 0U : start_address) - file_offset; |
- |
// Skip to file name. "cursor" now points to dev. We need to |
- // skip at least two spaces for dev and inode. |
+ // skip at least two spaces for dev and inode. Note that name can |
+ // be empty (cursor == eol). |
int num_spaces = 0; |
while (cursor < eol) { |
if (*cursor == ' ') { |
@@ -609,22 +655,17 @@ OpenObjectFileContainingPcAndGetStartAddress(uint64_t pc, |
} |
++cursor; |
} |
- if (cursor == eol) { |
- return -1; // Malformed line. |
- } |
- // Finally, "cursor" now points to file name of our interest. |
- NO_INTR(object_fd = open(cursor, O_RDONLY)); |
- if (object_fd < 0) { |
- // Failed to open object file. Copy the object file name to |
- // |out_file_name|. |
- strncpy(out_file_name, cursor, out_file_name_size); |
- // Making sure |out_file_name| is always null-terminated. |
- out_file_name[out_file_name_size - 1] = '\0'; |
- return -1; |
+ // Finally, "cursor" now points to file name. |
+ region.name = cursor; |
+ |
+ // Report found region to the callback. |
+ if (callback(callback_data, region)) { |
+ return true; // Callback stopped the iteration. |
} |
- return object_fd; |
} |
+ |
+ return false; |
} |
// POSIX doesn't define any async-signal safe function for converting |