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

Side by Side Diff: third_party/tcmalloc/chromium/src/symbolize.cc

Issue 576001: Merged third_party/tcmalloc/vendor/src(google-perftools r87) into... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Removed the unnecessary printf and ASSERT(0) Created 10 years, 9 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) 2009, Google Inc. 1 // Copyright (c) 2009, 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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 58
59 DEFINE_string(symbolize_pprof, 59 DEFINE_string(symbolize_pprof,
60 EnvToString("PPROF_PATH", "pprof"), 60 EnvToString("PPROF_PATH", "pprof"),
61 "Path to pprof to call for reporting function names."); 61 "Path to pprof to call for reporting function names.");
62 62
63 // heap_profile_table_pprof may be referenced after destructors are 63 // heap_profile_table_pprof may be referenced after destructors are
64 // called (since that's when leak-checking is done), so we make 64 // called (since that's when leak-checking is done), so we make
65 // a more-permanent copy that won't ever get destroyed. 65 // a more-permanent copy that won't ever get destroyed.
66 static string* g_pprof_path = new string(FLAGS_symbolize_pprof); 66 static string* g_pprof_path = new string(FLAGS_symbolize_pprof);
67 67
68 void SymbolTable::Add(const void* addr) {
69 symbolization_table_[addr] = "";
70 }
71
72 const char* SymbolTable::GetSymbol(const void* addr) {
73 return symbolization_table_[addr];
74 }
75
68 // Updates symbolization_table with the pointers to symbol names corresponding 76 // Updates symbolization_table with the pointers to symbol names corresponding
69 // to its keys. The symbol names are stored in out, which is allocated and 77 // to its keys. The symbol names are stored in out, which is allocated and
70 // freed by the caller of this routine. 78 // freed by the caller of this routine.
71 // Note that the forking/etc is not thread-safe or re-entrant. That's 79 // Note that the forking/etc is not thread-safe or re-entrant. That's
72 // ok for the purpose we need -- reporting leaks detected by heap-checker 80 // ok for the purpose we need -- reporting leaks detected by heap-checker
73 // -- but be careful if you decide to use this routine for other purposes. 81 // -- but be careful if you decide to use this routine for other purposes.
74 extern bool Symbolize(char *out, int out_size, 82 int SymbolTable::Symbolize() {
75 SymbolMap *symbolization_table) {
76 #if !defined(HAVE_UNISTD_H) || !defined(HAVE_SYS_SOCKET_H) || !defined(HAVE_SYS _WAIT_H) 83 #if !defined(HAVE_UNISTD_H) || !defined(HAVE_SYS_SOCKET_H) || !defined(HAVE_SYS _WAIT_H)
77 return false; 84 return 0;
78 #elif !defined(HAVE_PROGRAM_INVOCATION_NAME) 85 #elif !defined(HAVE_PROGRAM_INVOCATION_NAME)
79 return false; // TODO(csilvers): get argv[0] somehow 86 return 0; // TODO(csilvers): get argv[0] somehow
80 #else 87 #else
81 // All this work is to do two-way communication. ugh. 88 // All this work is to do two-way communication. ugh.
82 extern char* program_invocation_name; // gcc provides this 89 extern char* program_invocation_name; // gcc provides this
83 int child_in[2]; // file descriptors 90 int child_in[2]; // file descriptors
84 int child_out[2]; // for now, we don't worry about child_err 91 int child_out[2]; // for now, we don't worry about child_err
85 if (socketpair(AF_UNIX, SOCK_STREAM, 0, child_in) == -1) { 92 if (socketpair(AF_UNIX, SOCK_STREAM, 0, child_in) == -1) {
86 return false; 93 return 0;
87 } 94 }
88 if (socketpair(AF_UNIX, SOCK_STREAM, 0, child_out) == -1) { 95 if (socketpair(AF_UNIX, SOCK_STREAM, 0, child_out) == -1) {
89 close(child_in[0]); 96 close(child_in[0]);
90 close(child_in[1]); 97 close(child_in[1]);
91 return false; 98 return 0;
92 } 99 }
93 switch (fork()) { 100 switch (fork()) {
94 case -1: { // error 101 case -1: { // error
95 close(child_in[0]); 102 close(child_in[0]);
96 close(child_in[1]); 103 close(child_in[1]);
97 close(child_out[0]); 104 close(child_out[0]);
98 close(child_out[1]); 105 close(child_out[1]);
99 return false; 106 return 0;
100 } 107 }
101 case 0: { // child 108 case 0: { // child
102 close(child_in[1]); // child uses the 0's, parent uses the 1's 109 close(child_in[1]); // child uses the 0's, parent uses the 1's
103 close(child_out[1]); // child uses the 0's, parent uses the 1's 110 close(child_out[1]); // child uses the 0's, parent uses the 1's
104 close(0); 111 close(0);
105 close(1); 112 close(1);
106 if (dup2(child_in[0], 0) == -1) _exit(1); 113 if (dup2(child_in[0], 0) == -1) _exit(1);
107 if (dup2(child_out[0], 1) == -1) _exit(2); 114 if (dup2(child_out[0], 1) == -1) _exit(2);
108 // Unset vars that might cause trouble when we fork 115 // Unset vars that might cause trouble when we fork
109 unsetenv("CPUPROFILE"); 116 unsetenv("CPUPROFILE");
110 unsetenv("HEAPPROFILE"); 117 unsetenv("HEAPPROFILE");
111 unsetenv("HEAPCHECK"); 118 unsetenv("HEAPCHECK");
112 unsetenv("PERFTOOLS_VERBOSE"); 119 unsetenv("PERFTOOLS_VERBOSE");
113 execlp(g_pprof_path->c_str(), g_pprof_path->c_str(), 120 execlp(g_pprof_path->c_str(), g_pprof_path->c_str(),
114 "--symbols", program_invocation_name, NULL); 121 "--symbols", program_invocation_name, NULL);
115 _exit(3); // if execvp fails, it's bad news for us 122 _exit(3); // if execvp fails, it's bad news for us
116 } 123 }
117 default: { // parent 124 default: { // parent
118 close(child_in[0]); // child uses the 0's, parent uses the 1's 125 close(child_in[0]); // child uses the 0's, parent uses the 1's
119 close(child_out[0]); // child uses the 0's, parent uses the 1's 126 close(child_out[0]); // child uses the 0's, parent uses the 1's
120 #ifdef HAVE_POLL_H 127 #ifdef HAVE_POLL_H
121 // For maximum safety, we check to make sure the execlp 128 // For maximum safety, we check to make sure the execlp
122 // succeeded before trying to write. (Otherwise we'll get a 129 // succeeded before trying to write. (Otherwise we'll get a
123 // SIGPIPE.) For systems without poll.h, we'll just skip this 130 // SIGPIPE.) For systems without poll.h, we'll just skip this
124 // check, and trust that the user set PPROF_PATH correctly! 131 // check, and trust that the user set PPROF_PATH correctly!
125 struct pollfd pfd = { child_in[1], POLLOUT, 0 }; 132 struct pollfd pfd = { child_in[1], POLLOUT, 0 };
126 if (!poll(&pfd, 1, 0) || !(pfd.revents & POLLOUT) || 133 if (!poll(&pfd, 1, 0) || !(pfd.revents & POLLOUT) ||
127 (pfd.revents & (POLLHUP|POLLERR))) { 134 (pfd.revents & (POLLHUP|POLLERR))) {
128 return false; 135 return 0;
129 } 136 }
130 #endif 137 #endif
131 DumpProcSelfMaps(child_in[1]); // what pprof expects on stdin 138 DumpProcSelfMaps(child_in[1]); // what pprof expects on stdin
132 139
133 char pcstr[64]; // enough for a single address 140 // Allocate 24 bytes = ("0x" + 8 bytes + "\n" + overhead) for each
134 for (SymbolMap::const_iterator iter = symbolization_table->begin(); 141 // address to feed to pprof.
135 iter != symbolization_table->end(); ++iter) { 142 const int kOutBufSize = 24 * symbolization_table_.size();
136 snprintf(pcstr, sizeof(pcstr), // pprof expects format to be 0xXXXXXX 143 char *pprof_buffer = new char[kOutBufSize];
137 "0x%" PRIxPTR "\n", iter->first); 144 int written = 0;
138 // TODO(glider): the number of write()s can be reduced by using 145 for (SymbolMap::const_iterator iter = symbolization_table_.begin();
139 // snprintf() here. 146 iter != symbolization_table_.end(); ++iter) {
140 write(child_in[1], pcstr, strlen(pcstr)); 147 written += snprintf(pprof_buffer + written, kOutBufSize - written,
148 // pprof expects format to be 0xXXXXXX
149 "0x%"PRIxPTR"\n", reinterpret_cast<uintptr_t>(iter->first));
141 } 150 }
151 write(child_in[1], pprof_buffer, strlen(pprof_buffer));
142 close(child_in[1]); // that's all we need to write 152 close(child_in[1]); // that's all we need to write
143 153
154 const int kSymbolBufferSize = kSymbolSize * symbolization_table_.size();
144 int total_bytes_read = 0; 155 int total_bytes_read = 0;
145 memset(out, '\0', out_size); 156 delete[] symbol_buffer_;
157 symbol_buffer_ = new char[kSymbolBufferSize];
158 memset(symbol_buffer_, '\0', kSymbolBufferSize);
146 while (1) { 159 while (1) {
147 int bytes_read = read(child_out[1], out + total_bytes_read, 160 int bytes_read = read(child_out[1], symbol_buffer_ + total_bytes_read,
148 out_size - total_bytes_read); 161 kSymbolBufferSize - total_bytes_read);
149 if (bytes_read < 0) { 162 if (bytes_read < 0) {
150 close(child_out[1]); 163 close(child_out[1]);
151 return false; 164 return 0;
152 } else if (bytes_read == 0) { 165 } else if (bytes_read == 0) {
153 close(child_out[1]); 166 close(child_out[1]);
154 wait(NULL); 167 wait(NULL);
155 break; 168 break;
156 } else { 169 } else {
157 total_bytes_read += bytes_read; 170 total_bytes_read += bytes_read;
158 } 171 }
159 } 172 }
160 // We have successfully read the output of pprof into out. Make sure 173 // We have successfully read the output of pprof into out. Make sure
161 // the last symbol is full (we can tell because it ends with a \n). 174 // the last symbol is full (we can tell because it ends with a \n).
162 // TODO(glider): even when the last symbol is full, the list of symbols 175 if (total_bytes_read == 0 || symbol_buffer_[total_bytes_read - 1] != '\n')
163 // may be incomplete. We should check for that and return the number of 176 return 0;
164 // symbols we actually get from pprof. 177 // make the symbolization_table_ values point to the output vector
165 if (total_bytes_read == 0 || out[total_bytes_read - 1] != '\n') 178 SymbolMap::iterator fill = symbolization_table_.begin();
166 return false; 179 int num_symbols = 0;
167 // make the symbolization_table values point to the output vector 180 const char *current_name = symbol_buffer_;
168 SymbolMap::iterator fill = symbolization_table->begin();
169 char *current_name = out;
170 for (int i = 0; i < total_bytes_read; i++) { 181 for (int i = 0; i < total_bytes_read; i++) {
171 if (out[i] == '\n') { 182 if (symbol_buffer_[i] == '\n') {
172 fill->second = current_name; 183 fill->second = current_name;
173 out[i] = '\0'; 184 symbol_buffer_[i] = '\0';
174 current_name = out + i + 1; 185 current_name = symbol_buffer_ + i + 1;
175 fill++; 186 fill++;
187 num_symbols++;
176 } 188 }
177 } 189 }
178 return true; 190 return num_symbols;
179 } 191 }
180 } 192 }
181 return false; // shouldn't be reachable 193 return 0; // shouldn't be reachable
182 #endif 194 #endif
183 } 195 }
OLDNEW
« no previous file with comments | « third_party/tcmalloc/chromium/src/symbolize.h ('k') | third_party/tcmalloc/chromium/src/tcmalloc.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698