diff options
Diffstat (limited to 'third_party/tcmalloc/chromium/src/symbolize.cc')
-rw-r--r-- | third_party/tcmalloc/chromium/src/symbolize.cc | 78 |
1 files changed, 33 insertions, 45 deletions
diff --git a/third_party/tcmalloc/chromium/src/symbolize.cc b/third_party/tcmalloc/chromium/src/symbolize.cc index 9dd890e..b7cdf0e 100644 --- a/third_party/tcmalloc/chromium/src/symbolize.cc +++ b/third_party/tcmalloc/chromium/src/symbolize.cc @@ -65,37 +65,30 @@ DEFINE_string(symbolize_pprof, // a more-permanent copy that won't ever get destroyed. static string* g_pprof_path = new string(FLAGS_symbolize_pprof); -void SymbolTable::Add(const void* addr) { - symbolization_table_[addr] = ""; -} - -const char* SymbolTable::GetSymbol(const void* addr) { - return symbolization_table_[addr]; -} - // Updates symbolization_table with the pointers to symbol names corresponding // to its keys. The symbol names are stored in out, which is allocated and // freed by the caller of this routine. // Note that the forking/etc is not thread-safe or re-entrant. That's // ok for the purpose we need -- reporting leaks detected by heap-checker // -- but be careful if you decide to use this routine for other purposes. -int SymbolTable::Symbolize() { +extern bool Symbolize(char *out, int out_size, + SymbolMap *symbolization_table) { #if !defined(HAVE_UNISTD_H) || !defined(HAVE_SYS_SOCKET_H) || !defined(HAVE_SYS_WAIT_H) - return 0; + return false; #elif !defined(HAVE_PROGRAM_INVOCATION_NAME) - return 0; // TODO(csilvers): get argv[0] somehow + return false; // TODO(csilvers): get argv[0] somehow #else // All this work is to do two-way communication. ugh. extern char* program_invocation_name; // gcc provides this int child_in[2]; // file descriptors int child_out[2]; // for now, we don't worry about child_err if (socketpair(AF_UNIX, SOCK_STREAM, 0, child_in) == -1) { - return 0; + return false; } if (socketpair(AF_UNIX, SOCK_STREAM, 0, child_out) == -1) { close(child_in[0]); close(child_in[1]); - return 0; + return false; } switch (fork()) { case -1: { // error @@ -103,7 +96,7 @@ int SymbolTable::Symbolize() { close(child_in[1]); close(child_out[0]); close(child_out[1]); - return 0; + return false; } case 0: { // child close(child_in[1]); // child uses the 0's, parent uses the 1's @@ -132,36 +125,30 @@ int SymbolTable::Symbolize() { struct pollfd pfd = { child_in[1], POLLOUT, 0 }; if (!poll(&pfd, 1, 0) || !(pfd.revents & POLLOUT) || (pfd.revents & (POLLHUP|POLLERR))) { - return 0; + return false; } #endif DumpProcSelfMaps(child_in[1]); // what pprof expects on stdin - // Allocate 24 bytes = ("0x" + 8 bytes + "\n" + overhead) for each - // address to feed to pprof. - const int kOutBufSize = 24 * symbolization_table_.size(); - char *pprof_buffer = new char[kOutBufSize]; - int written = 0; - for (SymbolMap::const_iterator iter = symbolization_table_.begin(); - iter != symbolization_table_.end(); ++iter) { - written += snprintf(pprof_buffer + written, kOutBufSize - written, - // pprof expects format to be 0xXXXXXX - "0x%"PRIxPTR"\n", reinterpret_cast<uintptr_t>(iter->first)); + char pcstr[64]; // enough for a single address + for (SymbolMap::const_iterator iter = symbolization_table->begin(); + iter != symbolization_table->end(); ++iter) { + snprintf(pcstr, sizeof(pcstr), // pprof expects format to be 0xXXXXXX + "0x%" PRIxPTR "\n", iter->first); + // TODO(glider): the number of write()s can be reduced by using + // snprintf() here. + write(child_in[1], pcstr, strlen(pcstr)); } - write(child_in[1], pprof_buffer, strlen(pprof_buffer)); close(child_in[1]); // that's all we need to write - const int kSymbolBufferSize = kSymbolSize * symbolization_table_.size(); int total_bytes_read = 0; - delete[] symbol_buffer_; - symbol_buffer_ = new char[kSymbolBufferSize]; - memset(symbol_buffer_, '\0', kSymbolBufferSize); + memset(out, '\0', out_size); while (1) { - int bytes_read = read(child_out[1], symbol_buffer_ + total_bytes_read, - kSymbolBufferSize - total_bytes_read); + int bytes_read = read(child_out[1], out + total_bytes_read, + out_size - total_bytes_read); if (bytes_read < 0) { close(child_out[1]); - return 0; + return false; } else if (bytes_read == 0) { close(child_out[1]); wait(NULL); @@ -172,24 +159,25 @@ int SymbolTable::Symbolize() { } // We have successfully read the output of pprof into out. Make sure // the last symbol is full (we can tell because it ends with a \n). - if (total_bytes_read == 0 || symbol_buffer_[total_bytes_read - 1] != '\n') - return 0; - // make the symbolization_table_ values point to the output vector - SymbolMap::iterator fill = symbolization_table_.begin(); - int num_symbols = 0; - const char *current_name = symbol_buffer_; + // TODO(glider): even when the last symbol is full, the list of symbols + // may be incomplete. We should check for that and return the number of + // symbols we actually get from pprof. + if (total_bytes_read == 0 || out[total_bytes_read - 1] != '\n') + return false; + // make the symbolization_table values point to the output vector + SymbolMap::iterator fill = symbolization_table->begin(); + char *current_name = out; for (int i = 0; i < total_bytes_read; i++) { - if (symbol_buffer_[i] == '\n') { + if (out[i] == '\n') { fill->second = current_name; - symbol_buffer_[i] = '\0'; - current_name = symbol_buffer_ + i + 1; + out[i] = '\0'; + current_name = out + i + 1; fill++; - num_symbols++; } } - return num_symbols; + return true; } } - return 0; // shouldn't be reachable + return false; // shouldn't be reachable #endif } |