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

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

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