diff --git a/tools/DEPS b/tools/DEPS deleted file mode 100644 index dc04e3dfc6..0000000000 --- a/tools/DEPS +++ /dev/null @@ -1,6 +0,0 @@ -# checkdeps.py shouldn't check include paths for files in these dirs: -skip_child_includes = [ - "clang", - "gyp", - "traceline", -] diff --git a/tools/OWNERS b/tools/OWNERS deleted file mode 100644 index 4cd808f040..0000000000 --- a/tools/OWNERS +++ /dev/null @@ -1,3 +0,0 @@ -* - -per-file bisect-builds.py=rsesek@chromium.org diff --git a/tools/PRESUBMIT.py b/tools/PRESUBMIT.py deleted file mode 100644 index 01572314c0..0000000000 --- a/tools/PRESUBMIT.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (c) 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Top-level presubmit script for bisect trybot. - -See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for -details on the presubmit API built into gcl. -""" - -import imp - -def _ExamineBisectConfigFile(input_api, output_api): - for f in input_api.AffectedFiles(): - if not f.LocalPath().endswith('run-bisect-perf-regression.cfg'): - continue - - try: - cfg_file = imp.load_source('config', 'run-bisect-perf-regression.cfg') - - for k, v in cfg_file.config.iteritems(): - if v: - return f.LocalPath() - except (IOError, AttributeError, TypeError): - return f.LocalPath() - - return None - -def _CheckNoChangesToBisectConfigFile(input_api, output_api): - results = _ExamineBisectConfigFile(input_api, output_api) - if results: - return [output_api.PresubmitError( - 'The bisection config file should only contain a config dict with ' - 'empty fields. Changes to this file should never be submitted.', - items=[results])] - - return [] - -def CommonChecks(input_api, output_api): - results = [] - results.extend(_CheckNoChangesToBisectConfigFile(input_api, output_api)) - return results - -def CheckChangeOnUpload(input_api, output_api): - return CommonChecks(input_api, output_api) - -def CheckChangeOnCommit(input_api, output_api): - return CommonChecks(input_api, output_api) diff --git a/tools/android/OWNERS b/tools/android/OWNERS deleted file mode 100644 index e911c595c5..0000000000 --- a/tools/android/OWNERS +++ /dev/null @@ -1,6 +0,0 @@ -bulach@chromium.org -digit@chromium.org -michaelbai@chromium.org -pliard@chromium.org -wangxianzhu@chromium.org -yfriedman@chromium.org diff --git a/tools/android/adb_reboot/adb_reboot.c b/tools/android/adb_reboot/adb_reboot.c deleted file mode 100644 index 48c5cbe58f..0000000000 --- a/tools/android/adb_reboot/adb_reboot.c +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include -#include -#include -#include -#include -#include - -int main(int argc, char ** argv) { - int i = fork(); - struct stat ft; - time_t ct; - - if (i < 0) { - printf("fork error"); - return 1; - } - if (i > 0) - return 0; - - /* child (daemon) continues */ - int j; - for (j = 0; j < getdtablesize(); j++) - close(j); - - setsid(); /* obtain a new process group */ - - while (1) { - sleep(120); - - stat("/sdcard/host_heartbeat", &ft); - time(&ct); - if (ct - ft.st_mtime > 120) { - /* File was not touched for some time. */ - system("su -c reboot"); - } - } - - return 0; -} diff --git a/tools/android/adb_reboot/adb_reboot.gyp b/tools/android/adb_reboot/adb_reboot.gyp deleted file mode 100644 index 85134b9906..0000000000 --- a/tools/android/adb_reboot/adb_reboot.gyp +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -{ - 'targets': [ - { - 'target_name': 'adb_reboot', - 'type': 'executable', - 'sources': [ - 'adb_reboot.c', - ], - }, - ], -} diff --git a/tools/android/android_tools.gyp b/tools/android/android_tools.gyp deleted file mode 100644 index c38cd70d58..0000000000 --- a/tools/android/android_tools.gyp +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -{ - 'targets': [ - # Intermediate target grouping the android tools needed to run native - # unittests and instrumentation test apks. - { - 'target_name': 'android_tools', - 'type': 'none', - 'dependencies': [ - 'fake_dns/fake_dns.gyp:fake_dns', - 'forwarder2/forwarder.gyp:forwarder2', - 'md5sum/md5sum.gyp:md5sum', - 'adb_reboot/adb_reboot.gyp:adb_reboot', - ], - }, - { - 'target_name': 'memdump', - 'type': 'none', - 'dependencies': [ - 'memdump/memdump.gyp:memdump', - ], - } - ], -} diff --git a/tools/android/asan/asanwrapper.sh b/tools/android/asan/asanwrapper.sh deleted file mode 100755 index 2392d2ca44..0000000000 --- a/tools/android/asan/asanwrapper.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/system/bin/sh -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -ASAN_OPTIONS=debug=1,verbosity=1,strict_memcmp=0 \ -LD_LIBRARY_PATH=/data/local/tmp/asan:$LD_LIBRARY_PATH \ -LD_PRELOAD=libclang_rt.asan-arm-android.so \ -exec $@ diff --git a/tools/android/common/adb_connection.cc b/tools/android/common/adb_connection.cc deleted file mode 100644 index 91c25fed20..0000000000 --- a/tools/android/common/adb_connection.cc +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/android/common/adb_connection.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "base/logging.h" -#include "base/posix/eintr_wrapper.h" -#include "tools/android/common/net.h" - -namespace tools { -namespace { - -void CloseSocket(int fd) { - if (fd >= 0) { - int old_errno = errno; - (void) HANDLE_EINTR(close(fd)); - errno = old_errno; - } -} - -} // namespace - -int ConnectAdbHostSocket(const char* forward_to) { - // ADB port forward request format: HHHHtcp:port:address. - // HHHH is the hexidecimal length of the "tcp:port:address" part. - const size_t kBufferMaxLength = 30; - const size_t kLengthOfLength = 4; - const size_t kAddressMaxLength = kBufferMaxLength - kLengthOfLength; - - const char kAddressPrefix[] = { 't', 'c', 'p', ':' }; - size_t address_length = arraysize(kAddressPrefix) + strlen(forward_to); - if (address_length > kBufferMaxLength - kLengthOfLength) { - LOG(ERROR) << "Forward to address is too long: " << forward_to; - return -1; - } - - char request[kBufferMaxLength]; - memcpy(request + kLengthOfLength, kAddressPrefix, arraysize(kAddressPrefix)); - memcpy(request + kLengthOfLength + arraysize(kAddressPrefix), - forward_to, strlen(forward_to)); - - char length_buffer[kLengthOfLength + 1]; - snprintf(length_buffer, arraysize(length_buffer), "%04X", - static_cast(address_length)); - memcpy(request, length_buffer, kLengthOfLength); - - int host_socket = socket(AF_INET, SOCK_STREAM, 0); - if (host_socket < 0) { - LOG(ERROR) << "Failed to create adb socket: " << strerror(errno); - return -1; - } - - DisableNagle(host_socket); - - const int kAdbPort = 5037; - sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr.sin_port = htons(kAdbPort); - if (HANDLE_EINTR(connect(host_socket, reinterpret_cast(&addr), - sizeof(addr))) < 0) { - LOG(ERROR) << "Failed to connect adb socket: " << strerror(errno); - CloseSocket(host_socket); - return -1; - } - - size_t bytes_remaining = address_length + kLengthOfLength; - size_t bytes_sent = 0; - while (bytes_remaining > 0) { - int ret = HANDLE_EINTR(send(host_socket, request + bytes_sent, - bytes_remaining, 0)); - if (ret < 0) { - LOG(ERROR) << "Failed to send request: " << strerror(errno); - CloseSocket(host_socket); - return -1; - } - - bytes_sent += ret; - bytes_remaining -= ret; - } - - const size_t kAdbStatusLength = 4; - char response[kBufferMaxLength]; - int response_length = HANDLE_EINTR(recv(host_socket, response, - kBufferMaxLength, 0)); - if (response_length < kAdbStatusLength || - strncmp("OKAY", response, kAdbStatusLength) != 0) { - LOG(ERROR) << "Bad response from ADB: length: " << response_length - << " data: " << DumpBinary(response, response_length); - CloseSocket(host_socket); - return -1; - } - - return host_socket; -} - -} // namespace tools diff --git a/tools/android/common/adb_connection.h b/tools/android/common/adb_connection.h deleted file mode 100644 index 3fa0fb396f..0000000000 --- a/tools/android/common/adb_connection.h +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef TOOLS_ANDROID_COMMON_ADB_CONNECTION_H_ -#define TOOLS_ANDROID_COMMON_ADB_CONNECTION_H_ - -namespace tools { - -// Creates a socket that can forward to a host socket through ADB. -// The format of forward_to is :. -// Returns the socket handle, or -1 on any error. -int ConnectAdbHostSocket(const char* forward_to); - -} // namespace tools - -#endif // TOOLS_ANDROID_COMMON_ADB_CONNECTION_H_ - diff --git a/tools/android/common/common.gyp b/tools/android/common/common.gyp deleted file mode 100644 index 8622625844..0000000000 --- a/tools/android/common/common.gyp +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -{ - 'targets': [ - { - 'target_name': 'android_tools_common', - 'type': 'static_library', - 'toolsets': ['host', 'target'], - 'include_dirs': [ - '..', - '../../..', - ], - 'sources': [ - 'adb_connection.cc', - 'adb_connection.h', - 'daemon.cc', - 'daemon.h', - 'net.cc', - 'net.h', - ], - }, - ], -} - diff --git a/tools/android/common/daemon.cc b/tools/android/common/daemon.cc deleted file mode 100644 index 9eafdbce05..0000000000 --- a/tools/android/common/daemon.cc +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/android/common/daemon.h" - -#include -#include -#include -#include - -#include "base/command_line.h" -#include "base/logging.h" -#include "base/posix/eintr_wrapper.h" - -namespace { - -const char kNoSpawnDaemon[] = "D"; - -int g_exit_status = 0; - -void Exit(int unused) { - _exit(g_exit_status); -} - -void CloseFileDescriptor(int fd) { - int old_errno = errno; - (void) HANDLE_EINTR(close(fd)); - errno = old_errno; -} - -} // namespace - -namespace tools { - -bool HasHelpSwitch(const CommandLine& command_line) { - return command_line.HasSwitch("h") || command_line.HasSwitch("help"); -} - -bool HasNoSpawnDaemonSwitch(const CommandLine& command_line) { - return command_line.HasSwitch(kNoSpawnDaemon); -} - -void ShowHelp(const char* program, - const char* extra_title, - const char* extra_descriptions) { - printf("Usage: %s [-%s] %s\n" - " -%s stops from spawning a daemon process\n%s", - program, kNoSpawnDaemon, extra_title, kNoSpawnDaemon, - extra_descriptions); -} - -void SpawnDaemon(int exit_status) { - g_exit_status = exit_status; - signal(SIGUSR1, Exit); - - if (fork()) { - // In parent process. - sleep(10); // Wait for the child process to finish setsid(). - NOTREACHED(); - } - - // In child process. - setsid(); // Detach the child process from its parent. - kill(getppid(), SIGUSR1); // Inform the parent process to exit. - - // Close the standard input and outputs, otherwise the process may block - // adbd when the shell exits. - // Comment out these lines if you want to see outputs for debugging. - CloseFileDescriptor(0); - CloseFileDescriptor(1); - CloseFileDescriptor(2); -} - -} // namespace tools diff --git a/tools/android/common/daemon.h b/tools/android/common/daemon.h deleted file mode 100644 index 0c1640107d..0000000000 --- a/tools/android/common/daemon.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef TOOLS_ANDROID_COMMON_DAEMON_H_ -#define TOOLS_ANDROID_COMMON_DAEMON_H_ - -class CommandLine; - -namespace tools { - -bool HasHelpSwitch(const CommandLine& command_line); - -bool HasNoSpawnDaemonSwitch(const CommandLine& command_line); - -void ShowHelp(const char* program, - const char* extra_title, - const char* extra_descriptions); - -// Spawns a daemon process and exits the current process with exit_status. -// Any code executed after this function returns will be executed in the -// spawned daemon process. -void SpawnDaemon(int exit_status); - -} // namespace tools - -#endif // TOOLS_ANDROID_COMMON_DAEMON_H_ - diff --git a/tools/android/common/net.cc b/tools/android/common/net.cc deleted file mode 100644 index 3b9ef15bc3..0000000000 --- a/tools/android/common/net.cc +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/android/common/net.h" - -#include -#include -#include -#include - -#include "base/strings/stringprintf.h" - -namespace tools { - -int DisableNagle(int socket) { - int on = 1; - return setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)); -} - -int DeferAccept(int socket) { - int on = 1; - return setsockopt(socket, IPPROTO_TCP, TCP_DEFER_ACCEPT, &on, sizeof(on)); -} - -std::string DumpBinary(const char* buffer, size_t length) { - std::string result = "["; - for (int i = 0; i < length; ++i) { - base::StringAppendF(&result, "%02x,", - static_cast(buffer[i])); - } - - if (length) - result.erase(result.length() - 1); - - return result + "]"; -} - -} // namespace tools - diff --git a/tools/android/common/net.h b/tools/android/common/net.h deleted file mode 100644 index e3619548ab..0000000000 --- a/tools/android/common/net.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef TOOLS_ANDROID_COMMON_NET_H_ -#define TOOLS_ANDROID_COMMON_NET_H_ - -#include - -namespace tools { - -// DisableNagle can improve TCP transmission performance. Both Chrome net stack -// and adb tool use it. -int DisableNagle(int socket); - -// Wake up listener only when data arrive. -int DeferAccept(int socket); - -// Dumps a binary buffer into a string in a human-readable format. -std::string DumpBinary(const char* buffer, size_t length); - -} // namespace tools - -#endif // TOOLS_ANDROID_COMMON_NET_H_ - diff --git a/tools/android/device_stats_monitor/device_stats_monitor.cc b/tools/android/device_stats_monitor/device_stats_monitor.cc deleted file mode 100644 index 6388cdaf43..0000000000 --- a/tools/android/device_stats_monitor/device_stats_monitor.cc +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Dumps CPU and IO stats to a file at a regular interval. -// -// Output may be post processed by host to get top/iotop style information. - -#include -#include - -#include -#include -#include - -#include "base/command_line.h" -#include "base/file_util.h" -#include "base/strings/string_split.h" - -namespace { - -const char kIOStatsPath[] = "/proc/diskstats"; -const char kCPUStatsPath[] = "/proc/stat"; - -class DeviceStatsMonitor { - public: - explicit DeviceStatsMonitor(const std::string& out_path) - : out_path_(out_path), - record_(true) { - CHECK(!out_path_.empty()); - samples_.reserve(1024 * 1024); - } - - // Records stats continuously at |hz| cycles per second util - // StopRecordingAndDumpStats() is called. - // - // Yes, this buffers everything in memory, so it cannot be used for extended - // durations without OOM. But that beats writing during the trace which - // would affect the results. - void Start(int hz) { - const int sample_interval = 1000000 / hz; - const base::FilePath io_stats_path(kIOStatsPath); - const base::FilePath cpu_stats_path(kCPUStatsPath); - std::string out; - while (record_) { - out.clear(); - CHECK(file_util::ReadFileToString(io_stats_path, &out)); - CHECK(file_util::ReadFileToString(cpu_stats_path, &out)); - samples_.push_back(out); - usleep(sample_interval); - } - } - - // Stops recording and saves samples to file. - void StopAndDumpStats() { - record_ = false; - usleep(250 * 1000); - std::ofstream out_stream; - out_stream.open(out_path_.value().c_str(), std::ios::out); - for (std::vector::const_iterator i = samples_.begin(); - i != samples_.end(); ++i) { - out_stream << i->c_str() << std::endl; - } - out_stream.close(); - } - - private: - const base::FilePath out_path_; - std::vector samples_; - bool record_; - - DISALLOW_COPY_AND_ASSIGN(DeviceStatsMonitor); -}; - -DeviceStatsMonitor* g_device_stats_monitor = NULL; - -void SigTermHandler(int unused) { - printf("Stopping device stats monitor\n"); - g_device_stats_monitor->StopAndDumpStats(); -} - -} // namespace - -int main(int argc, char** argv) { - const int kDefaultHz = 20; - - CommandLine command_line(argc, argv); - CommandLine::StringVector args = command_line.GetArgs(); - if (command_line.HasSwitch("h") || command_line.HasSwitch("help") || - args.size() != 1) { - printf("Usage: %s OUTPUT_FILE\n" - " --hz=HZ Number of samples/second. default=%d\n", - argv[0], kDefaultHz); - return 1; - } - - int hz = command_line.HasSwitch("hz") ? - atoi(command_line.GetSwitchValueNative("hz").c_str()) : - kDefaultHz; - - printf("Starting device stats monitor\n"); - g_device_stats_monitor = new DeviceStatsMonitor(args[0]); - signal(SIGTERM, SigTermHandler); - g_device_stats_monitor->Start(hz); - delete g_device_stats_monitor; - - return 0; -} diff --git a/tools/android/device_stats_monitor/device_stats_monitor.gyp b/tools/android/device_stats_monitor/device_stats_monitor.gyp deleted file mode 100644 index f9bd9e8e4b..0000000000 --- a/tools/android/device_stats_monitor/device_stats_monitor.gyp +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -{ - 'targets': [ - { - 'target_name': 'device_stats_monitor', - 'type': 'none', - 'dependencies': [ - 'device_stats_monitor_symbols', - ], - 'actions': [ - { - 'action_name': 'strip_device_stats_monitor', - 'inputs': ['<(PRODUCT_DIR)/device_stats_monitor_symbols'], - 'outputs': ['<(PRODUCT_DIR)/device_stats_monitor'], - 'action': [ - '<(android_strip)', - '--strip-unneeded', - '<@(_inputs)', - '-o', - '<@(_outputs)', - ], - }, - ], - }, { - 'target_name': 'device_stats_monitor_symbols', - 'type': 'executable', - 'dependencies': [ - '../../../base/base.gyp:base', - ], - 'include_dirs': [ - '../../..', - ], - 'sources': [ - 'device_stats_monitor.cc', - ], - }, - ], -} diff --git a/tools/android/fake_dns/DEPS b/tools/android/fake_dns/DEPS deleted file mode 100644 index 8fa9d48d88..0000000000 --- a/tools/android/fake_dns/DEPS +++ /dev/null @@ -1,3 +0,0 @@ -include_rules = [ - "+net", -] diff --git a/tools/android/fake_dns/fake_dns.cc b/tools/android/fake_dns/fake_dns.cc deleted file mode 100644 index 9a055bfd37..0000000000 --- a/tools/android/fake_dns/fake_dns.cc +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "base/basictypes.h" -#include "base/command_line.h" -#include "base/logging.h" -#include "base/posix/eintr_wrapper.h" -#include "base/safe_strerror_posix.h" -#include "net/base/big_endian.h" -#include "net/base/net_util.h" -#include "net/dns/dns_protocol.h" -#include "tools/android/common/daemon.h" -#include "tools/android/common/net.h" - -namespace { - -// Mininum request size: 1 question containing 1 QNAME, 1 TYPE and 1 CLASS. -const size_t kMinRequestSize = sizeof(net::dns_protocol::Header) + 6; - -// The name reference in the answer pointing to the name in the query. -// Its format is: highest two bits set to 1, then the offset of the name -// which just follows the header. -const uint16 kPointerToQueryName = - static_cast(0xc000 | sizeof(net::dns_protocol::Header)); - -const uint32 kTTL = 86400; // One day. - -void PError(const char* msg) { - int current_errno = errno; - LOG(ERROR) << "ERROR: " << msg << ": " << safe_strerror(current_errno); -} - -void SendTo(int sockfd, const void* buf, size_t len, int flags, - const sockaddr* dest_addr, socklen_t addrlen) { - if (HANDLE_EINTR(sendto(sockfd, buf, len, flags, dest_addr, addrlen)) == -1) - PError("sendto()"); -} - -void CloseFileDescriptor(int fd) { - int old_errno = errno; - (void) HANDLE_EINTR(close(fd)); - errno = old_errno; -} - -void SendRefusedResponse(int sock, const sockaddr_in& client_addr, uint16 id) { - net::dns_protocol::Header response; - response.id = htons(id); - response.flags = htons(net::dns_protocol::kFlagResponse | - net::dns_protocol::kFlagAA | - net::dns_protocol::kFlagRD | - net::dns_protocol::kFlagRA | - net::dns_protocol::kRcodeREFUSED); - response.qdcount = 0; - response.ancount = 0; - response.nscount = 0; - response.arcount = 0; - SendTo(sock, &response, sizeof(response), 0, - reinterpret_cast(&client_addr), sizeof(client_addr)); -} - -void SendResponse(int sock, const sockaddr_in& client_addr, uint16 id, - uint16 qtype, const char* question, size_t question_length) { - net::dns_protocol::Header header; - header.id = htons(id); - header.flags = htons(net::dns_protocol::kFlagResponse | - net::dns_protocol::kFlagAA | - net::dns_protocol::kFlagRD | - net::dns_protocol::kFlagRA | - net::dns_protocol::kRcodeNOERROR); - header.qdcount = htons(1); - header.ancount = htons(1); - header.nscount = 0; - header.arcount = 0; - - // Size of RDATA which is a IPv4 or IPv6 address. - size_t rdata_size = qtype == net::dns_protocol::kTypeA ? - net::kIPv4AddressSize : net::kIPv6AddressSize; - - // Size of the whole response which contains the header, the question and - // the answer. 12 is the sum of sizes of the compressed name reference, TYPE, - // CLASS, TTL and RDLENGTH. - size_t response_size = sizeof(header) + question_length + 12 + rdata_size; - - if (response_size > net::dns_protocol::kMaxUDPSize) { - LOG(ERROR) << "Response is too large: " << response_size; - SendRefusedResponse(sock, client_addr, id); - return; - } - - char response[net::dns_protocol::kMaxUDPSize]; - net::BigEndianWriter writer(response, arraysize(response)); - writer.WriteBytes(&header, sizeof(header)); - - // Repeat the question in the response. Some clients (e.g. ping) needs this. - writer.WriteBytes(question, question_length); - - // Construct the answer. - writer.WriteU16(kPointerToQueryName); - writer.WriteU16(qtype); - writer.WriteU16(net::dns_protocol::kClassIN); - writer.WriteU32(kTTL); - writer.WriteU16(rdata_size); - if (qtype == net::dns_protocol::kTypeA) - writer.WriteU32(INADDR_LOOPBACK); - else - writer.WriteBytes(&in6addr_loopback, sizeof(in6_addr)); - DCHECK(writer.ptr() - response == response_size); - - SendTo(sock, response, response_size, 0, - reinterpret_cast(&client_addr), sizeof(client_addr)); -} - -void HandleRequest(int sock, const char* request, size_t size, - const sockaddr_in& client_addr) { - if (size < kMinRequestSize) { - LOG(ERROR) << "Request is too small " << size - << "\n" << tools::DumpBinary(request, size); - return; - } - - net::BigEndianReader reader(request, size); - net::dns_protocol::Header header; - reader.ReadBytes(&header, sizeof(header)); - uint16 id = ntohs(header.id); - uint16 flags = ntohs(header.flags); - uint16 qdcount = ntohs(header.qdcount); - uint16 ancount = ntohs(header.ancount); - uint16 nscount = ntohs(header.nscount); - uint16 arcount = ntohs(header.arcount); - - const uint16 kAllowedFlags = 0x07ff; - if ((flags & ~kAllowedFlags) || - qdcount != 1 || ancount || nscount || arcount) { - LOG(ERROR) << "Unsupported request: FLAGS=" << flags - << " QDCOUNT=" << qdcount - << " ANCOUNT=" << ancount - << " NSCOUNT=" << nscount - << " ARCOUNT=" << arcount - << "\n" << tools::DumpBinary(request, size); - SendRefusedResponse(sock, client_addr, id); - return; - } - - // request[size - 5] should be the end of the QNAME (a zero byte). - // We don't care about the validity of QNAME because we don't parse it. - const char* qname_end = &request[size - 5]; - if (*qname_end) { - LOG(ERROR) << "Error parsing QNAME\n" << tools::DumpBinary(request, size); - SendRefusedResponse(sock, client_addr, id); - return; - } - - reader.Skip(qname_end - reader.ptr() + 1); - - uint16 qtype; - uint16 qclass; - reader.ReadU16(&qtype); - reader.ReadU16(&qclass); - if ((qtype != net::dns_protocol::kTypeA && - qtype != net::dns_protocol::kTypeAAAA) || - qclass != net::dns_protocol::kClassIN) { - LOG(ERROR) << "Unsupported query: QTYPE=" << qtype << " QCLASS=" << qclass - << "\n" << tools::DumpBinary(request, size); - SendRefusedResponse(sock, client_addr, id); - return; - } - - SendResponse(sock, client_addr, id, qtype, - request + sizeof(header), size - sizeof(header)); -} - -} // namespace - -int main(int argc, char** argv) { - printf("Fake DNS server\n"); - - CommandLine command_line(argc, argv); - if (tools::HasHelpSwitch(command_line) || command_line.GetArgs().size()) { - tools::ShowHelp(argv[0], "", ""); - return 0; - } - - int sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock < 0) { - PError("create socket"); - return 1; - } - - sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr.sin_port = htons(53); - int reuse_addr = 1; - if (HANDLE_EINTR(bind(sock, reinterpret_cast(&addr), - sizeof(addr))) < 0) { - PError("server bind"); - CloseFileDescriptor(sock); - return 1; - } - - if (!tools::HasNoSpawnDaemonSwitch(command_line)) - tools::SpawnDaemon(0); - - while (true) { - sockaddr_in client_addr; - socklen_t client_addr_len = sizeof(client_addr); - char request[net::dns_protocol::kMaxUDPSize]; - int size = HANDLE_EINTR(recvfrom(sock, request, sizeof(request), - MSG_WAITALL, - reinterpret_cast(&client_addr), - &client_addr_len)); - if (size < 0) { - // Unrecoverable error, can only exit. - LOG(ERROR) << "Failed to receive a request: " << strerror(errno); - CloseFileDescriptor(sock); - return 1; - } - - if (size > 0) - HandleRequest(sock, request, size, client_addr); - } -} - diff --git a/tools/android/fake_dns/fake_dns.gyp b/tools/android/fake_dns/fake_dns.gyp deleted file mode 100644 index 0edacfadf0..0000000000 --- a/tools/android/fake_dns/fake_dns.gyp +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -{ - 'targets': [ - { - 'target_name': 'fake_dns', - 'type': 'none', - 'dependencies': [ - 'fake_dns_symbols', - ], - 'actions': [ - { - 'action_name': 'strip_fake_dns', - 'inputs': ['<(PRODUCT_DIR)/fake_dns_symbols'], - 'outputs': ['<(PRODUCT_DIR)/fake_dns'], - 'action': [ - '<(android_strip)', - '--strip-unneeded', - '<@(_inputs)', - '-o', - '<@(_outputs)', - ], - }, - ], - }, { - 'target_name': 'fake_dns_symbols', - 'type': 'executable', - 'dependencies': [ - '../../../base/base.gyp:base', - '../../../net/net.gyp:net', - '../common/common.gyp:android_tools_common', - ], - 'include_dirs': [ - '../../..', - ], - 'sources': [ - 'fake_dns.cc', - ], - }, - ], -} - diff --git a/tools/android/find_unused_resources.py b/tools/android/find_unused_resources.py deleted file mode 100755 index da86e73415..0000000000 --- a/tools/android/find_unused_resources.py +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/python -# Copyright (c) 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Lists unused Java strings and other resources.""" - -import optparse -import re -import subprocess -import sys - - -def GetApkResources(apk_path): - """Returns the types and names of resources packaged in an APK. - - Args: - apk_path: path to the APK. - - Returns: - The resources in the APK as a list of tuples (type, name). Example: - [('drawable', 'arrow'), ('layout', 'month_picker'), ...] - """ - p = subprocess.Popen( - ['aapt', 'dump', 'resources', apk_path], - stdout=subprocess.PIPE) - dump_out, _ = p.communicate() - assert p.returncode == 0, 'aapt dump failed' - matches = re.finditer( - r'^\s+spec resource 0x[0-9a-fA-F]+ [\w.]+:(?P\w+)/(?P\w+)', - dump_out, re.MULTILINE) - return [m.group('type', 'name') for m in matches] - - -def GetUsedResources(source_paths, resource_types): - """Returns the types and names of resources used in Java or resource files. - - Args: - source_paths: a list of files or folders collectively containing all the - Java files, resource files, and the AndroidManifest.xml. - resource_types: a list of resource types to look for. Example: - ['string', 'drawable'] - - Returns: - The resources referenced by the Java and resource files as a list of tuples - (type, name). Example: - [('drawable', 'app_icon'), ('layout', 'month_picker'), ...] - """ - type_regex = '|'.join(map(re.escape, resource_types)) - patterns = [r'@(())(%s)/(\w+)' % type_regex, - r'\b((\w+\.)*)R\.(%s)\.(\w+)' % type_regex] - resources = [] - for pattern in patterns: - p = subprocess.Popen( - ['grep', '-REIhoe', pattern] + source_paths, - stdout=subprocess.PIPE) - grep_out, grep_err = p.communicate() - # Check stderr instead of return code, since return code is 1 when no - # matches are found. - assert not grep_err, 'grep failed' - matches = re.finditer(pattern, grep_out) - for match in matches: - package = match.group(1) - if package == 'android.': - continue - type_ = match.group(3) - name = match.group(4) - resources.append((type_, name)) - return resources - - -def FormatResources(resources): - """Formats a list of resources for printing. - - Args: - resources: a list of resources, given as (type, name) tuples. - """ - return '\n'.join(['%-12s %s' % (t, n) for t, n in sorted(resources)]) - - -def ParseArgs(args): - usage = 'usage: %prog [-v] APK_PATH SOURCE_PATH...' - parser = optparse.OptionParser(usage=usage) - parser.add_option('-v', help='Show verbose output', action='store_true') - options, args = parser.parse_args(args=args) - if len(args) < 2: - parser.error('must provide APK_PATH and SOURCE_PATH arguments') - return options.v, args[0], args[1:] - - -def main(args=None): - verbose, apk_path, source_paths = ParseArgs(args) - apk_resources = GetApkResources(apk_path) - resource_types = list(set([r[0] for r in apk_resources])) - used_resources = GetUsedResources(source_paths, resource_types) - unused_resources = set(apk_resources) - set(used_resources) - undefined_resources = set(used_resources) - set(apk_resources) - - # aapt dump fails silently. Notify the user if things look wrong. - if not apk_resources: - print >> sys.stderr, ( - 'Warning: No resources found in the APK. Did you provide the correct ' - 'APK path?') - if not used_resources: - print >> sys.stderr, ( - 'Warning: No resources references from Java or resource files. Did you ' - 'provide the correct source paths?') - if undefined_resources: - print >> sys.stderr, ( - 'Warning: found %d "undefined" resources that are referenced by Java ' - 'files or by other resources, but are not in the APK. Run with -v to ' - 'see them.' % len(undefined_resources)) - - if verbose: - print '%d undefined resources:' % len(undefined_resources) - print FormatResources(undefined_resources), '\n' - print '%d resources packaged into the APK:' % len(apk_resources) - print FormatResources(apk_resources), '\n' - print '%d used resources:' % len(used_resources) - print FormatResources(used_resources), '\n' - print '%d unused resources:' % len(unused_resources) - print FormatResources(unused_resources) - - -if __name__ == '__main__': - main() diff --git a/tools/android/findbugs_plugin/README b/tools/android/findbugs_plugin/README deleted file mode 100644 index 3ba3f53085..0000000000 --- a/tools/android/findbugs_plugin/README +++ /dev/null @@ -1,15 +0,0 @@ -This is the FindBugs plugin for chrome on android. - -Currently it detects: -- synchronized method -- synchronized 'this' - -We don't want the synchronized method and synchronized 'this' to be -used, the exception is the synchronized method defined in Android -API. - -The plugin jar file was prebuilt and checked in, to rebuild the -plugin, you need ant, and run below command, the new jar file will -be in lib directory. - -ant install diff --git a/tools/android/findbugs_plugin/build.xml b/tools/android/findbugs_plugin/build.xml deleted file mode 100644 index 09ee13c41f..0000000000 --- a/tools/android/findbugs_plugin/build.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - Build findbugs_plugin for Chromium Android - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/android/findbugs_plugin/findbugs.xml b/tools/android/findbugs_plugin/findbugs.xml deleted file mode 100644 index 43b1f3417d..0000000000 --- a/tools/android/findbugs_plugin/findbugs.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - diff --git a/tools/android/findbugs_plugin/findbugs_plugin.gyp b/tools/android/findbugs_plugin/findbugs_plugin.gyp deleted file mode 100644 index 16d06e6c25..0000000000 --- a/tools/android/findbugs_plugin/findbugs_plugin.gyp +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -{ - 'targets': [ - { - 'target_name': 'findbugs_plugin_test', - 'type': 'none', - 'variables': { - 'java_in_dir': 'test/java/', - }, - 'includes': [ '../../../build/java.gypi' ], - } - ] -} diff --git a/tools/android/findbugs_plugin/lib/chromiumPlugin.jar b/tools/android/findbugs_plugin/lib/chromiumPlugin.jar deleted file mode 100644 index 6ccf61b430..0000000000 Binary files a/tools/android/findbugs_plugin/lib/chromiumPlugin.jar and /dev/null differ diff --git a/tools/android/findbugs_plugin/messages.xml b/tools/android/findbugs_plugin/messages.xml deleted file mode 100644 index aea983bc24..0000000000 --- a/tools/android/findbugs_plugin/messages.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - Chromium FindBugs Plugin -
Adds style checks enforced in the chromium project.
-
- - -
- -
- -
- - - Shouldn't use synchronized(this) - Shouldn't use synchronized(this), please narrow down the synchronization scope. -
-Shouldn't use synchronized(this), please narrow down the synchronization scope.

-]]> -
-
- - -
- -
- -
- - - Shouldn't use synchronized method - Shouldn't use synchronized method, please narrow down the synchronization scope. -
-Shouldn't use synchronized method, please narrow down the synchronization scope.

-]]> -
-
- - CHROMIUM -
diff --git a/tools/android/findbugs_plugin/src/org/chromium/tools/findbugs/plugin/SynchronizedMethodDetector.java b/tools/android/findbugs_plugin/src/org/chromium/tools/findbugs/plugin/SynchronizedMethodDetector.java deleted file mode 100644 index 7a879f6644..0000000000 --- a/tools/android/findbugs_plugin/src/org/chromium/tools/findbugs/plugin/SynchronizedMethodDetector.java +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.tools.findbugs.plugin; - -import edu.umd.cs.findbugs.BugInstance; -import edu.umd.cs.findbugs.BugReporter; -import edu.umd.cs.findbugs.bcel.OpcodeStackDetector; - -import org.apache.bcel.classfile.Code; - -/** - * This class detects the synchronized method. - */ -public class SynchronizedMethodDetector extends OpcodeStackDetector { - - private BugReporter mBugReporter; - - public SynchronizedMethodDetector(BugReporter bugReporter) { - this.mBugReporter = bugReporter; - } - - @Override - public void visit(Code code) { - if (getMethod().isSynchronized()) { - mBugReporter.reportBug(new BugInstance(this, "CHROMIUM_SYNCHRONIZED_METHOD", - NORMAL_PRIORITY) - .addClassAndMethod(this) - .addSourceLine(this)); - } - super.visit(code); - } - - @Override - public void sawOpcode(int arg0) { - } -} diff --git a/tools/android/findbugs_plugin/src/org/chromium/tools/findbugs/plugin/SynchronizedThisDetector.java b/tools/android/findbugs_plugin/src/org/chromium/tools/findbugs/plugin/SynchronizedThisDetector.java deleted file mode 100644 index 330431ba7c..0000000000 --- a/tools/android/findbugs_plugin/src/org/chromium/tools/findbugs/plugin/SynchronizedThisDetector.java +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.tools.findbugs.plugin; - -import org.apache.bcel.classfile.Code; - -import edu.umd.cs.findbugs.BugInstance; -import edu.umd.cs.findbugs.BugReporter; -import edu.umd.cs.findbugs.bcel.OpcodeStackDetector; - -/** - * This class detects the synchronized(this). - * - * The pattern of byte code of synchronized(this) is - * aload_0 # Load the 'this' pointer on top of stack - * dup # Duplicate the 'this' pointer - * astore_x # Store this for late use, it might be astore. - * monitorenter - */ -public class SynchronizedThisDetector extends OpcodeStackDetector { - private final int PATTERN[] = {ALOAD_0, DUP, 0xff, 0xff, MONITORENTER}; - - private int mStep = 0; - private BugReporter mBugReporter; - - public SynchronizedThisDetector(BugReporter bugReporter) { - mBugReporter = bugReporter; - } - - @Override - public void visit(Code code) { - mStep = 0; - super.visit(code); - } - - @Override - public void sawOpcode(int seen) { - if (PATTERN[mStep] == seen) { - mStep++; - if (mStep == PATTERN.length) { - mBugReporter.reportBug(new BugInstance(this, "CHROMIUM_SYNCHRONIZED_THIS", - NORMAL_PRIORITY) - .addClassAndMethod(this) - .addSourceLine(this)); - mStep = 0; - return; - } - } else if (mStep == 2) { - // This could be astore_x - switch (seen) { - case ASTORE_0: - case ASTORE_1: - case ASTORE_2: - case ASTORE_3: - mStep += 2; - break; - case ASTORE: - mStep++; - break; - default: - mStep = 0; - break; - } - } else if (mStep == 3) { - // Could be any byte following the ASTORE. - mStep++; - } else { - mStep = 0; - } - } -} diff --git a/tools/android/findbugs_plugin/test/expected_result.txt b/tools/android/findbugs_plugin/test/expected_result.txt deleted file mode 100644 index 076b00703c..0000000000 --- a/tools/android/findbugs_plugin/test/expected_result.txt +++ /dev/null @@ -1,3 +0,0 @@ -M C CSM: Shouldn't use synchronized method, please narrow down the synchronization scope. At SimpleSynchronizedMethod.java -M C CSM: Shouldn't use synchronized method, please narrow down the synchronization scope. At SimpleSynchronizedStaticMethod.java -M C CST: Shouldn't use synchronized(this), please narrow down the synchronization scope. At SimpleSynchronizedThis.java diff --git a/tools/android/findbugs_plugin/test/java/src/org/chromium/tools/findbugs/plugin/SimpleSynchronizedMethod.java b/tools/android/findbugs_plugin/test/java/src/org/chromium/tools/findbugs/plugin/SimpleSynchronizedMethod.java deleted file mode 100644 index c04a35cb02..0000000000 --- a/tools/android/findbugs_plugin/test/java/src/org/chromium/tools/findbugs/plugin/SimpleSynchronizedMethod.java +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.tools.findbugs.plugin; - -/** - * This class has synchronized method and is used to test - * SynchronizedMethodDetector. - */ -class SimpleSynchronizedMethod { - private int i = 0; - synchronized void synchronizedMethod() { - i++; - } -} diff --git a/tools/android/findbugs_plugin/test/java/src/org/chromium/tools/findbugs/plugin/SimpleSynchronizedStaticMethod.java b/tools/android/findbugs_plugin/test/java/src/org/chromium/tools/findbugs/plugin/SimpleSynchronizedStaticMethod.java deleted file mode 100644 index 0af6582fa0..0000000000 --- a/tools/android/findbugs_plugin/test/java/src/org/chromium/tools/findbugs/plugin/SimpleSynchronizedStaticMethod.java +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.tools.findbugs.plugin; - -/** - * This class is used to test SynchronizedMethodDetector - */ -class SimpleSynchronizedStaticMethod { - private static int i = 0; - synchronized static void synchronizedStaticMethod() { - i++; - } -} diff --git a/tools/android/findbugs_plugin/test/java/src/org/chromium/tools/findbugs/plugin/SimpleSynchronizedThis.java b/tools/android/findbugs_plugin/test/java/src/org/chromium/tools/findbugs/plugin/SimpleSynchronizedThis.java deleted file mode 100644 index 2c7e6fdfb4..0000000000 --- a/tools/android/findbugs_plugin/test/java/src/org/chromium/tools/findbugs/plugin/SimpleSynchronizedThis.java +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.tools.findbugs.plugin; - -/** - * This class has synchronized(this) statement and is used to test - * SynchronizedThisDetector. - */ -class SimpleSynchronizedThis { - private int i = 0; - - void synchronizedThis() { - synchronized(this) { - i++; - } - } -} diff --git a/tools/android/findbugs_plugin/test/run_findbugs_plugin_tests.py b/tools/android/findbugs_plugin/test/run_findbugs_plugin_tests.py deleted file mode 100755 index c2e1531484..0000000000 --- a/tools/android/findbugs_plugin/test/run_findbugs_plugin_tests.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# This is used to test the findbugs plugin, it calls -# build/android/pylib/utils/findbugs.py to analyze the classes in -# org.chromium.tools.findbugs.plugin package, and expects to get the same -# issue with those in expected_result.txt. -# -# Useful command line: -# --rebaseline to generate the expected_result.txt, please make sure don't -# remove the expected result of exsting tests. - - -import optparse -import os -import sys - -sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), - '..', '..', '..', '..', - 'build', 'android'))) - -from pylib import constants -from pylib.utils import findbugs - - -def main(argv): - parser = findbugs.GetCommonParser() - - options, _ = parser.parse_args() - - if not options.known_bugs: - options.known_bugs = os.path.join(constants.DIR_SOURCE_ROOT, 'tools', - 'android', 'findbugs_plugin', 'test', - 'expected_result.txt') - if not options.only_analyze: - options.only_analyze = 'org.chromium.tools.findbugs.plugin.*' - - return findbugs.Run(options) - -if __name__ == '__main__': - sys.exit(main(sys.argv)) diff --git a/tools/android/forwarder/forwarder.cc b/tools/android/forwarder/forwarder.cc deleted file mode 100644 index e77c8065ff..0000000000 --- a/tools/android/forwarder/forwarder.cc +++ /dev/null @@ -1,426 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "base/command_line.h" -#include "base/logging.h" -#include "base/posix/eintr_wrapper.h" -#include "tools/android/common/adb_connection.h" -#include "tools/android/common/daemon.h" -#include "tools/android/common/net.h" - -namespace { - -const pthread_t kInvalidThread = static_cast(-1); -volatile bool g_killed = false; - -void CloseSocket(int fd) { - if (fd >= 0) { - int old_errno = errno; - (void) HANDLE_EINTR(close(fd)); - errno = old_errno; - } -} - -class Buffer { - public: - Buffer() - : bytes_read_(0), - write_offset_(0) { - } - - bool CanRead() { - return bytes_read_ == 0; - } - - bool CanWrite() { - return write_offset_ < bytes_read_; - } - - int Read(int fd) { - int ret = -1; - if (CanRead()) { - ret = HANDLE_EINTR(read(fd, buffer_, kBufferSize)); - if (ret > 0) - bytes_read_ = ret; - } - return ret; - } - - int Write(int fd) { - int ret = -1; - if (CanWrite()) { - ret = HANDLE_EINTR(write(fd, buffer_ + write_offset_, - bytes_read_ - write_offset_)); - if (ret > 0) { - write_offset_ += ret; - if (write_offset_ == bytes_read_) { - write_offset_ = 0; - bytes_read_ = 0; - } - } - } - return ret; - } - - private: - // A big buffer to let our file-over-http bridge work more like real file. - static const int kBufferSize = 1024 * 128; - int bytes_read_; - int write_offset_; - char buffer_[kBufferSize]; - - DISALLOW_COPY_AND_ASSIGN(Buffer); -}; - -class Server; - -struct ForwarderThreadInfo { - ForwarderThreadInfo(Server* a_server, int a_forwarder_index) - : server(a_server), - forwarder_index(a_forwarder_index) { - } - Server* server; - int forwarder_index; -}; - -struct ForwarderInfo { - time_t start_time; - int socket1; - time_t socket1_last_byte_time; - size_t socket1_bytes; - int socket2; - time_t socket2_last_byte_time; - size_t socket2_bytes; -}; - -class Server { - public: - Server() - : thread_(kInvalidThread), - socket_(-1) { - memset(forward_to_, 0, sizeof(forward_to_)); - memset(&forwarders_, 0, sizeof(forwarders_)); - } - - int GetFreeForwarderIndex() { - for (int i = 0; i < kMaxForwarders; i++) { - if (forwarders_[i].start_time == 0) - return i; - } - return -1; - } - - void DisposeForwarderInfo(int index) { - forwarders_[index].start_time = 0; - } - - ForwarderInfo* GetForwarderInfo(int index) { - return &forwarders_[index]; - } - - void DumpInformation() { - LOG(INFO) << "Server information: " << forward_to_; - LOG(INFO) << "No.: age up(bytes,idle) down(bytes,idle)"; - int count = 0; - time_t now = time(NULL); - for (int i = 0; i < kMaxForwarders; i++) { - const ForwarderInfo& info = forwarders_[i]; - if (info.start_time) { - count++; - LOG(INFO) << count << ": " << now - info.start_time << " up(" - << info.socket1_bytes << "," - << now - info.socket1_last_byte_time << " down(" - << info.socket2_bytes << "," - << now - info.socket2_last_byte_time << ")"; - } - } - } - - void Shutdown() { - if (socket_ >= 0) - shutdown(socket_, SHUT_RDWR); - } - - bool InitSocket(const char* arg); - - void StartThread() { - pthread_create(&thread_, NULL, ServerThread, this); - } - - void JoinThread() { - if (thread_ != kInvalidThread) - pthread_join(thread_, NULL); - } - - private: - static void* ServerThread(void* arg); - - // There are 3 kinds of threads that will access the array: - // 1. Server thread will get a free ForwarderInfo and initialize it; - // 2. Forwarder threads will dispose the ForwarderInfo when it finishes; - // 3. Main thread will iterate and print the forwarders. - // Using an array is not optimal, but can avoid locks or other complex - // inter-thread communication. - static const int kMaxForwarders = 512; - ForwarderInfo forwarders_[kMaxForwarders]; - - pthread_t thread_; - int socket_; - char forward_to_[40]; - - DISALLOW_COPY_AND_ASSIGN(Server); -}; - -// Forwards all outputs from one socket to another socket. -void* ForwarderThread(void* arg) { - ForwarderThreadInfo* thread_info = - reinterpret_cast(arg); - Server* server = thread_info->server; - int index = thread_info->forwarder_index; - delete thread_info; - ForwarderInfo* info = server->GetForwarderInfo(index); - int socket1 = info->socket1; - int socket2 = info->socket2; - int nfds = socket1 > socket2 ? socket1 + 1 : socket2 + 1; - fd_set read_fds; - fd_set write_fds; - Buffer buffer1; - Buffer buffer2; - - while (!g_killed) { - FD_ZERO(&read_fds); - if (buffer1.CanRead()) - FD_SET(socket1, &read_fds); - if (buffer2.CanRead()) - FD_SET(socket2, &read_fds); - - FD_ZERO(&write_fds); - if (buffer1.CanWrite()) - FD_SET(socket2, &write_fds); - if (buffer2.CanWrite()) - FD_SET(socket1, &write_fds); - - if (HANDLE_EINTR(select(nfds, &read_fds, &write_fds, NULL, NULL)) <= 0) { - LOG(ERROR) << "Select error: " << strerror(errno); - break; - } - - int now = time(NULL); - if (FD_ISSET(socket1, &read_fds)) { - info->socket1_last_byte_time = now; - int bytes = buffer1.Read(socket1); - if (bytes <= 0) - break; - info->socket1_bytes += bytes; - } - if (FD_ISSET(socket2, &read_fds)) { - info->socket2_last_byte_time = now; - int bytes = buffer2.Read(socket2); - if (bytes <= 0) - break; - info->socket2_bytes += bytes; - } - if (FD_ISSET(socket1, &write_fds)) { - if (buffer2.Write(socket1) <= 0) - break; - } - if (FD_ISSET(socket2, &write_fds)) { - if (buffer1.Write(socket2) <= 0) - break; - } - } - - CloseSocket(socket1); - CloseSocket(socket2); - server->DisposeForwarderInfo(index); - return NULL; -} - -// Listens to a server socket. On incoming request, forward it to the host. -// static -void* Server::ServerThread(void* arg) { - Server* server = reinterpret_cast(arg); - while (!g_killed) { - int forwarder_index = server->GetFreeForwarderIndex(); - if (forwarder_index < 0) { - LOG(ERROR) << "Too many forwarders"; - continue; - } - - struct sockaddr_in addr; - socklen_t addr_len = sizeof(addr); - int socket = HANDLE_EINTR(accept(server->socket_, - reinterpret_cast(&addr), - &addr_len)); - if (socket < 0) { - LOG(ERROR) << "Failed to accept: " << strerror(errno); - break; - } - tools::DisableNagle(socket); - - int host_socket = tools::ConnectAdbHostSocket(server->forward_to_); - if (host_socket >= 0) { - // Set NONBLOCK flag because we use select(). - fcntl(socket, F_SETFL, fcntl(socket, F_GETFL) | O_NONBLOCK); - fcntl(host_socket, F_SETFL, fcntl(host_socket, F_GETFL) | O_NONBLOCK); - - ForwarderInfo* forwarder_info = server->GetForwarderInfo(forwarder_index); - time_t now = time(NULL); - forwarder_info->start_time = now; - forwarder_info->socket1 = socket; - forwarder_info->socket1_last_byte_time = now; - forwarder_info->socket1_bytes = 0; - forwarder_info->socket2 = host_socket; - forwarder_info->socket2_last_byte_time = now; - forwarder_info->socket2_bytes = 0; - - pthread_t thread; - pthread_create(&thread, NULL, ForwarderThread, - new ForwarderThreadInfo(server, forwarder_index)); - } else { - // Close the unused client socket which is failed to connect to host. - CloseSocket(socket); - } - } - - CloseSocket(server->socket_); - server->socket_ = -1; - return NULL; -} - -// Format of arg: [::] -bool Server::InitSocket(const char* arg) { - char* endptr; - int local_port = static_cast(strtol(arg, &endptr, 10)); - if (local_port < 0) - return false; - - if (*endptr != ':') { - snprintf(forward_to_, sizeof(forward_to_), "%d:127.0.0.1", local_port); - } else { - strncpy(forward_to_, endptr + 1, sizeof(forward_to_) - 1); - } - - socket_ = socket(AF_INET, SOCK_STREAM, 0); - if (socket_ < 0) { - perror("server socket"); - return false; - } - tools::DisableNagle(socket_); - - sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr.sin_port = htons(local_port); - int reuse_addr = 1; - setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, - &reuse_addr, sizeof(reuse_addr)); - tools::DeferAccept(socket_); - if (HANDLE_EINTR(bind(socket_, reinterpret_cast(&addr), - sizeof(addr))) < 0 || - HANDLE_EINTR(listen(socket_, 5)) < 0) { - perror("server bind"); - CloseSocket(socket_); - socket_ = -1; - return false; - } - - if (local_port == 0) { - socklen_t addrlen = sizeof(addr); - if (getsockname(socket_, reinterpret_cast(&addr), &addrlen) - != 0) { - perror("get listen address"); - CloseSocket(socket_); - socket_ = -1; - return false; - } - local_port = ntohs(addr.sin_port); - } - - printf("Forwarding device port %d to host %s\n", local_port, forward_to_); - return true; -} - -int g_server_count = 0; -Server* g_servers = NULL; - -void KillHandler(int unused) { - g_killed = true; - for (int i = 0; i < g_server_count; i++) - g_servers[i].Shutdown(); -} - -void DumpInformation(int unused) { - for (int i = 0; i < g_server_count; i++) - g_servers[i].DumpInformation(); -} - -} // namespace - -int main(int argc, char** argv) { - printf("Android device to host TCP forwarder\n"); - printf("Like 'adb forward' but in the reverse direction\n"); - - CommandLine command_line(argc, argv); - CommandLine::StringVector server_args = command_line.GetArgs(); - if (tools::HasHelpSwitch(command_line) || server_args.empty()) { - tools::ShowHelp( - argv[0], - "[::] ...", - " default is \n" - " default is 127.0.0.1\n" - "If is 0, a port will by dynamically allocated.\n"); - return 0; - } - - g_servers = new Server[server_args.size()]; - g_server_count = 0; - int failed_count = 0; - for (size_t i = 0; i < server_args.size(); i++) { - if (!g_servers[g_server_count].InitSocket(server_args[i].c_str())) { - printf("Couldn't start forwarder server for port spec: %s\n", - server_args[i].c_str()); - ++failed_count; - } else { - ++g_server_count; - } - } - - if (g_server_count == 0) { - printf("No forwarder servers could be started. Exiting.\n"); - delete [] g_servers; - return failed_count; - } - - if (!tools::HasNoSpawnDaemonSwitch(command_line)) - tools::SpawnDaemon(failed_count); - - signal(SIGTERM, KillHandler); - signal(SIGUSR2, DumpInformation); - - for (int i = 0; i < g_server_count; i++) - g_servers[i].StartThread(); - for (int i = 0; i < g_server_count; i++) - g_servers[i].JoinThread(); - g_server_count = 0; - delete [] g_servers; - - return 0; -} - diff --git a/tools/android/forwarder/forwarder.gyp b/tools/android/forwarder/forwarder.gyp deleted file mode 100644 index 1df518b1bb..0000000000 --- a/tools/android/forwarder/forwarder.gyp +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -{ - 'targets': [ - { - 'target_name': 'forwarder', - 'type': 'none', - 'dependencies': [ - 'forwarder_symbols', - ], - 'actions': [ - { - 'action_name': 'strip_forwarder', - 'inputs': ['<(PRODUCT_DIR)/forwarder_symbols'], - 'outputs': ['<(PRODUCT_DIR)/forwarder'], - 'action': [ - '<(android_strip)', - '--strip-unneeded', - '<@(_inputs)', - '-o', - '<@(_outputs)', - ], - }, - ], - }, { - 'target_name': 'forwarder_symbols', - 'type': 'executable', - 'dependencies': [ - '../../../base/base.gyp:base', - '../common/common.gyp:android_tools_common', - ], - 'include_dirs': [ - '../../..', - ], - 'sources': [ - 'forwarder.cc', - ], - }, - ], -} - diff --git a/tools/android/forwarder2/command.cc b/tools/android/forwarder2/command.cc deleted file mode 100644 index 9b0aa24cfb..0000000000 --- a/tools/android/forwarder2/command.cc +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/android/forwarder2/command.h" - -#include -#include -#include -#include - -#include "base/logging.h" -#include "base/safe_strerror_posix.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" -#include "tools/android/forwarder2/socket.h" - -using base::StringPiece; - -namespace { - - -// Command format: -// : -// -// Where: -// is a 5-chars zero-padded ASCII decimal integer -// matching the target port for the command (e.g. -// '08080' for port 8080) -// is a 3-char zero-padded ASCII decimal integer -// matching a command::Type value (e.g. 002 for -// ACK). -// The column (:) is used as a separator for easier reading. -const int kPortStringSize = 5; -const int kCommandTypeStringSize = 2; -// Command string size also includes the ':' separator char. -const int kCommandStringSize = kPortStringSize + kCommandTypeStringSize + 1; - -} // namespace - -namespace forwarder2 { - -bool ReadCommand(Socket* socket, - int* port_out, - command::Type* command_type_out) { - char command_buffer[kCommandStringSize + 1]; - // To make logging easier. - command_buffer[kCommandStringSize] = '\0'; - - int bytes_read = socket->ReadNumBytes(command_buffer, kCommandStringSize); - if (bytes_read != kCommandStringSize) { - if (bytes_read < 0) - LOG(ERROR) << "Read() error: " << safe_strerror(errno); - else if (!bytes_read) - LOG(ERROR) << "Read() error, endpoint was unexpectedly closed."; - else - LOG(ERROR) << "Read() error, not enough data received from the socket."; - return false; - } - - StringPiece port_str(command_buffer, kPortStringSize); - if (!StringToInt(port_str, port_out)) { - LOG(ERROR) << "Could not parse the command port string: " - << port_str; - return false; - } - - StringPiece command_type_str( - &command_buffer[kPortStringSize + 1], kCommandTypeStringSize); - int command_type; - if (!StringToInt(command_type_str, &command_type)) { - LOG(ERROR) << "Could not parse the command type string: " - << command_type_str; - return false; - } - *command_type_out = static_cast(command_type); - return true; -} - -bool SendCommand(command::Type command, int port, Socket* socket) { - char buffer[kCommandStringSize + 1]; - int len = snprintf(buffer, sizeof(buffer), "%05d:%02d", port, command); - CHECK_EQ(len, kCommandStringSize); - // Write the full command minus the leading \0 char. - return socket->WriteNumBytes(buffer, len) == len; -} - -bool ReceivedCommand(command::Type command, Socket* socket) { - int port; - command::Type received_command; - if (!ReadCommand(socket, &port, &received_command)) - return false; - return received_command == command; -} - -} // namespace forwarder diff --git a/tools/android/forwarder2/command.h b/tools/android/forwarder2/command.h deleted file mode 100644 index 8e222ef7bb..0000000000 --- a/tools/android/forwarder2/command.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef TOOLS_ANDROID_FORWARDER2_COMMAND_H_ -#define TOOLS_ANDROID_FORWARDER2_COMMAND_H_ - -#include "base/basictypes.h" - -namespace forwarder2 { - -class Socket; - -namespace command { - -enum Type { - ACCEPT_ERROR = 0, - ACCEPT_SUCCESS, - ACK, - ADB_DATA_SOCKET_ERROR, - ADB_DATA_SOCKET_SUCCESS, - BIND_ERROR, - BIND_SUCCESS, - DATA_CONNECTION, - HOST_SERVER_ERROR, - HOST_SERVER_SUCCESS, - KILL_ALL_LISTENERS, - LISTEN, - UNLISTEN, - UNLISTEN_ERROR, - UNLISTEN_SUCCESS, -}; - -} // namespace command - -bool ReadCommand(Socket* socket, - int* port_out, - command::Type* command_type_out); - -// Helper function to read the command from the |socket| and return true if the -// |command| is equal to the given command parameter. -bool ReceivedCommand(command::Type command, Socket* socket); - -bool SendCommand(command::Type command, int port, Socket* socket); - -} // namespace forwarder - -#endif // TOOLS_ANDROID_FORWARDER2_COMMAND_H_ diff --git a/tools/android/forwarder2/common.cc b/tools/android/forwarder2/common.cc deleted file mode 100644 index c97ed8056b..0000000000 --- a/tools/android/forwarder2/common.cc +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/android/forwarder2/common.h" - -#include -#include - -#include "base/logging.h" -#include "base/posix/eintr_wrapper.h" -#include "base/safe_strerror_posix.h" - -namespace forwarder2 { - -void PError(const char* msg) { - LOG(ERROR) << msg << ": " << safe_strerror(errno); -} - -void CloseFD(int fd) { - const int errno_copy = errno; - if (HANDLE_EINTR(close(fd)) < 0) { - PError("close"); - errno = errno_copy; - } -} - -} // namespace forwarder2 diff --git a/tools/android/forwarder2/common.h b/tools/android/forwarder2/common.h deleted file mode 100644 index 43de57b160..0000000000 --- a/tools/android/forwarder2/common.h +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Common helper functions/classes used both in the host and device forwarder. - -#ifndef TOOLS_ANDROID_FORWARDER2_COMMON_H_ -#define TOOLS_ANDROID_FORWARDER2_COMMON_H_ - -#include -#include -#include - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "base/posix/eintr_wrapper.h" - -// Preserving errno for Close() is important because the function is very often -// used in cleanup code, after an error occurred, and it is very easy to pass an -// invalid file descriptor to close() in this context, or more rarely, a -// spurious signal might make close() return -1 + setting errno to EINTR, -// masking the real reason for the original error. This leads to very unpleasant -// debugging sessions. -#define PRESERVE_ERRNO_HANDLE_EINTR(Func) \ - do { \ - int local_errno = errno; \ - (void) HANDLE_EINTR(Func); \ - errno = local_errno; \ - } while (false); - -// Wrapper around RAW_LOG() which is signal-safe. The only purpose of this macro -// is to avoid documenting uses of RawLog(). -#define SIGNAL_SAFE_LOG(Level, Msg) \ - RAW_LOG(Level, Msg); - -namespace forwarder2 { - -// Note that the two following functions are not signal-safe. - -// Chromium logging-aware implementation of libc's perror(). -void PError(const char* msg); - -// Closes the provided file descriptor and logs an error if it failed. -void CloseFD(int fd); - -// Helps build a formatted C-string allocated in a fixed-size array. This is -// useful in signal handlers where base::StringPrintf() can't be used safely -// (due to its use of LOG()). -template -class FixedSizeStringBuilder { - public: - FixedSizeStringBuilder() { - Reset(); - } - - const char* buffer() const { return buffer_; } - - void Reset() { - buffer_[0] = 0; - write_ptr_ = buffer_; - } - - // Returns the number of bytes appended to the underlying buffer or -1 if it - // failed. - int Append(const char* format, ...) PRINTF_FORMAT(/* + 1 for 'this' */ 2, 3) { - if (write_ptr_ >= buffer_ + BufferSize) - return -1; - va_list ap; - va_start(ap, format); - const int bytes_written = vsnprintf( - write_ptr_, BufferSize - (write_ptr_ - buffer_), format, ap); - va_end(ap); - if (bytes_written > 0) - write_ptr_ += bytes_written; - return bytes_written; - } - - private: - char* write_ptr_; - char buffer_[BufferSize]; - - COMPILE_ASSERT(BufferSize >= 1, Size_of_buffer_must_be_at_least_one); - DISALLOW_COPY_AND_ASSIGN(FixedSizeStringBuilder); -}; - -} // namespace forwarder2 - -#endif // TOOLS_ANDROID_FORWARDER2_COMMON_H_ diff --git a/tools/android/forwarder2/daemon.cc b/tools/android/forwarder2/daemon.cc deleted file mode 100644 index 0ca89d1a5f..0000000000 --- a/tools/android/forwarder2/daemon.cc +++ /dev/null @@ -1,288 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/android/forwarder2/daemon.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "base/basictypes.h" -#include "base/file_util.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/posix/eintr_wrapper.h" -#include "base/safe_strerror_posix.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" -#include "tools/android/forwarder2/common.h" -#include "tools/android/forwarder2/socket.h" - -namespace forwarder2 { -namespace { - -const int kBufferSize = 256; - -// Timeout constant used for polling when connecting to the daemon's Unix Domain -// Socket and also when waiting for its death when it is killed. -const int kNumTries = 100; -const int kIdleTimeMSec = 20; - -void InitLoggingForDaemon(const std::string& log_file) { - logging::LoggingSettings settings; - settings.logging_dest = - log_file.empty() ? - logging::LOG_TO_SYSTEM_DEBUG_LOG : logging::LOG_TO_FILE; - settings.log_file = log_file.c_str(); - settings.lock_log = logging::DONT_LOCK_LOG_FILE; - settings.dcheck_state = - logging::ENABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS; - CHECK(logging::InitLogging(settings)); -} - -bool RunServerAcceptLoop(const std::string& welcome_message, - Socket* server_socket, - Daemon::ServerDelegate* server_delegate) { - bool failed = false; - for (;;) { - scoped_ptr client_socket(new Socket()); - if (!server_socket->Accept(client_socket.get())) { - if (server_socket->DidReceiveEvent()) - break; - PError("Accept()"); - failed = true; - break; - } - if (!client_socket->Write(welcome_message.c_str(), - welcome_message.length() + 1)) { - PError("Write()"); - failed = true; - continue; - } - server_delegate->OnClientConnected(client_socket.Pass()); - } - return !failed; -} - -void SigChildHandler(int signal_number) { - DCHECK_EQ(signal_number, SIGCHLD); - int status; - pid_t child_pid = waitpid(-1 /* any child */, &status, WNOHANG); - if (child_pid < 0) { - PError("waitpid"); - return; - } - if (child_pid == 0) - return; - if (WIFEXITED(status) && WEXITSTATUS(status) == 0) - return; - // Avoid using StringAppendF() since it's unsafe in a signal handler due to - // its use of LOG(). - FixedSizeStringBuilder<256> string_builder; - string_builder.Append("Daemon (pid=%d) died unexpectedly with ", child_pid); - if (WIFEXITED(status)) - string_builder.Append("status %d.", WEXITSTATUS(status)); - else if (WIFSIGNALED(status)) - string_builder.Append("signal %d.", WTERMSIG(status)); - else - string_builder.Append("unknown reason."); - SIGNAL_SAFE_LOG(ERROR, string_builder.buffer()); -} - -// Note that 0 is written to |lock_owner_pid| in case the file is not locked. -bool GetFileLockOwnerPid(int fd, pid_t* lock_owner_pid) { - struct flock lock_info = {}; - lock_info.l_type = F_WRLCK; - lock_info.l_whence = SEEK_CUR; - const int ret = HANDLE_EINTR(fcntl(fd, F_GETLK, &lock_info)); - if (ret < 0) { - if (errno == EBADF) { - // Assume that the provided file descriptor corresponding to the PID file - // was valid until the daemon removed this file. - *lock_owner_pid = 0; - return true; - } - PError("fcntl"); - return false; - } - if (lock_info.l_type == F_UNLCK) { - *lock_owner_pid = 0; - return true; - } - CHECK_EQ(F_WRLCK /* exclusive lock */, lock_info.l_type); - *lock_owner_pid = lock_info.l_pid; - return true; -} - -scoped_ptr ConnectToUnixDomainSocket( - const std::string& socket_name, - int tries_count, - int idle_time_msec, - const std::string& expected_welcome_message) { - for (int i = 0; i < tries_count; ++i) { - scoped_ptr socket(new Socket()); - if (!socket->ConnectUnix(socket_name)) { - if (idle_time_msec) - usleep(idle_time_msec * 1000); - continue; - } - char buf[kBufferSize]; - DCHECK(expected_welcome_message.length() + 1 <= sizeof(buf)); - memset(buf, 0, sizeof(buf)); - if (socket->Read(buf, expected_welcome_message.length() + 1) < 0) { - perror("read"); - continue; - } - if (expected_welcome_message != buf) { - LOG(ERROR) << "Unexpected message read from daemon: " << buf; - break; - } - return socket.Pass(); - } - return scoped_ptr(); -} - -} // namespace - -Daemon::Daemon(const std::string& log_file_path, - const std::string& identifier, - ClientDelegate* client_delegate, - ServerDelegate* server_delegate, - GetExitNotifierFDCallback get_exit_fd_callback) - : log_file_path_(log_file_path), - identifier_(identifier), - client_delegate_(client_delegate), - server_delegate_(server_delegate), - get_exit_fd_callback_(get_exit_fd_callback) { - DCHECK(client_delegate_); - DCHECK(server_delegate_); - DCHECK(get_exit_fd_callback_); -} - -Daemon::~Daemon() {} - -bool Daemon::SpawnIfNeeded() { - const int kSingleTry = 1; - const int kNoIdleTime = 0; - scoped_ptr client_socket = ConnectToUnixDomainSocket( - identifier_, kSingleTry, kNoIdleTime, identifier_); - if (!client_socket) { - switch (fork()) { - case -1: - PError("fork()"); - return false; - // Child. - case 0: { - if (setsid() < 0) { // Detach the child process from its parent. - PError("setsid()"); - exit(1); - } - InitLoggingForDaemon(log_file_path_); - CloseFD(STDIN_FILENO); - CloseFD(STDOUT_FILENO); - CloseFD(STDERR_FILENO); - const int null_fd = open("/dev/null", O_RDWR); - CHECK_EQ(null_fd, STDIN_FILENO); - CHECK_EQ(dup(null_fd), STDOUT_FILENO); - CHECK_EQ(dup(null_fd), STDERR_FILENO); - Socket command_socket; - if (!command_socket.BindUnix(identifier_)) { - scoped_ptr client_socket = ConnectToUnixDomainSocket( - identifier_, kSingleTry, kNoIdleTime, identifier_); - if (client_socket.get()) { - // The daemon was spawned by a concurrent process. - exit(0); - } - PError("bind()"); - exit(1); - } - server_delegate_->Init(); - command_socket.AddEventFd(get_exit_fd_callback_()); - return RunServerAcceptLoop( - identifier_, &command_socket, server_delegate_); - } - default: - break; - } - } - // Parent. - // Install the custom SIGCHLD handler. - sigset_t blocked_signals_set; - if (sigprocmask(0 /* first arg ignored */, NULL, &blocked_signals_set) < 0) { - PError("sigprocmask()"); - return false; - } - struct sigaction old_action; - struct sigaction new_action; - memset(&new_action, 0, sizeof(new_action)); - new_action.sa_handler = SigChildHandler; - new_action.sa_flags = SA_NOCLDSTOP; - sigemptyset(&new_action.sa_mask); - if (sigaction(SIGCHLD, &new_action, &old_action) < 0) { - PError("sigaction()"); - return false; - } - // Connect to the daemon's Unix Domain Socket. - bool failed = false; - if (!client_socket) { - client_socket = ConnectToUnixDomainSocket( - identifier_, kNumTries, kIdleTimeMSec, identifier_); - if (!client_socket) { - LOG(ERROR) << "Could not connect to daemon's Unix Daemon socket"; - failed = true; - } - } - if (!failed) - client_delegate_->OnDaemonReady(client_socket.get()); - // Restore the previous signal action for SIGCHLD. - if (sigaction(SIGCHLD, &old_action, NULL) < 0) { - PError("sigaction"); - failed = true; - } - return !failed; -} - -bool Daemon::Kill() { - pid_t daemon_pid = Socket::GetUnixDomainSocketProcessOwner(identifier_); - if (daemon_pid < 0) - return true; // No daemon running. - if (kill(daemon_pid, SIGTERM) < 0) { - if (errno == ESRCH /* invalid PID */) - // The daemon exited for some reason (e.g. kill by a process other than - // us) right before the call to kill() above. - return true; - PError("kill"); - return false; - } - for (int i = 0; i < kNumTries; ++i) { - const pid_t previous_pid = daemon_pid; - daemon_pid = Socket::GetUnixDomainSocketProcessOwner(identifier_); - if (daemon_pid < 0) - return true; - // Since we are polling we might not see the 'daemon exited' event if - // another daemon was spawned during our idle period. - if (daemon_pid != previous_pid) { - LOG(WARNING) << "Daemon (pid=" << previous_pid - << ") was successfully killed but a new daemon (pid=" - << daemon_pid << ") seems to be running now."; - return true; - } - usleep(kIdleTimeMSec * 1000); - } - LOG(ERROR) << "Timed out while killing daemon. " - "It might still be tearing down."; - return false; -} - -} // namespace forwarder2 diff --git a/tools/android/forwarder2/daemon.h b/tools/android/forwarder2/daemon.h deleted file mode 100644 index 4b05ea423c..0000000000 --- a/tools/android/forwarder2/daemon.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef TOOLS_ANDROID_FORWARDER2_DAEMON_H_ -#define TOOLS_ANDROID_FORWARDER2_DAEMON_H_ - -#include - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" - -namespace forwarder2 { - -class Socket; - -// Provides a way to spawn a daemon and communicate with it. -class Daemon { - public: - // Callback used by the daemon to shutdown properly. See pipe_notifier.h for - // more details. - typedef int (*GetExitNotifierFDCallback)(); - - class ClientDelegate { - public: - virtual ~ClientDelegate() {} - - // Called after the daemon is ready to receive commands. - virtual void OnDaemonReady(Socket* daemon_socket) = 0; - }; - - class ServerDelegate { - public: - virtual ~ServerDelegate() {} - - // Called after the daemon bound its Unix Domain Socket. This can be used to - // setup signal handlers or perform global initialization. - virtual void Init() = 0; - - virtual void OnClientConnected(scoped_ptr client_socket) = 0; - }; - - // |identifier| should be a unique string identifier. It is used to - // bind/connect the underlying Unix Domain Socket. - // Note that this class does not take ownership of |client_delegate| and - // |server_delegate|. - Daemon(const std::string& log_file_path, - const std::string& identifier, - ClientDelegate* client_delegate, - ServerDelegate* server_delegate, - GetExitNotifierFDCallback get_exit_fd_callback); - - ~Daemon(); - - // Returns whether the daemon was successfully spawned. Note that this does - // not necessarily mean that the current process was forked in case the daemon - // is already running. - bool SpawnIfNeeded(); - - // Kills the daemon and blocks until it exited. Returns whether it succeeded. - bool Kill(); - - private: - const std::string log_file_path_; - const std::string identifier_; - ClientDelegate* const client_delegate_; - ServerDelegate* const server_delegate_; - const GetExitNotifierFDCallback get_exit_fd_callback_; - - DISALLOW_COPY_AND_ASSIGN(Daemon); -}; - -} // namespace forwarder2 - -#endif // TOOLS_ANDROID_FORWARDER2_DAEMON_H_ diff --git a/tools/android/forwarder2/device_controller.cc b/tools/android/forwarder2/device_controller.cc deleted file mode 100644 index 87d0e17143..0000000000 --- a/tools/android/forwarder2/device_controller.cc +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/android/forwarder2/device_controller.h" - -#include - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop_proxy.h" -#include "base/single_thread_task_runner.h" -#include "tools/android/forwarder2/command.h" -#include "tools/android/forwarder2/device_listener.h" -#include "tools/android/forwarder2/socket.h" - -namespace forwarder2 { - -// static -scoped_ptr DeviceController::Create( - const std::string& adb_unix_socket, - int exit_notifier_fd) { - scoped_ptr device_controller; - scoped_ptr host_socket(new Socket()); - if (!host_socket->BindUnix(adb_unix_socket)) { - PLOG(ERROR) << "Could not BindAndListen DeviceController socket on port " - << adb_unix_socket << ": "; - return device_controller.Pass(); - } - LOG(INFO) << "Listening on Unix Domain Socket " << adb_unix_socket; - device_controller.reset( - new DeviceController(host_socket.Pass(), exit_notifier_fd)); - return device_controller.Pass(); -} - -DeviceController::~DeviceController() { - DCHECK(construction_task_runner_->RunsTasksOnCurrentThread()); -} - -void DeviceController::Start() { - AcceptHostCommandSoon(); -} - -DeviceController::DeviceController(scoped_ptr host_socket, - int exit_notifier_fd) - : host_socket_(host_socket.Pass()), - exit_notifier_fd_(exit_notifier_fd), - construction_task_runner_(base::MessageLoopProxy::current()), - weak_ptr_factory_(this) { - host_socket_->AddEventFd(exit_notifier_fd); -} - -void DeviceController::AcceptHostCommandSoon() { - base::MessageLoopProxy::current()->PostTask( - FROM_HERE, - base::Bind(&DeviceController::AcceptHostCommandInternal, - base::Unretained(this))); -} - -void DeviceController::AcceptHostCommandInternal() { - scoped_ptr socket(new Socket); - if (!host_socket_->Accept(socket.get())) { - if (!host_socket_->DidReceiveEvent()) - PLOG(ERROR) << "Could not Accept DeviceController socket"; - else - LOG(INFO) << "Received exit notification"; - return; - } - base::ScopedClosureRunner accept_next_client( - base::Bind(&DeviceController::AcceptHostCommandSoon, - base::Unretained(this))); - // So that |socket| doesn't block on read if it has notifications. - socket->AddEventFd(exit_notifier_fd_); - int port; - command::Type command; - if (!ReadCommand(socket.get(), &port, &command)) { - LOG(ERROR) << "Invalid command received."; - return; - } - const ListenersMap::iterator listener_it = listeners_.find(port); - DeviceListener* const listener = listener_it == listeners_.end() - ? static_cast(NULL) : listener_it->second.get(); - switch (command) { - case command::LISTEN: { - if (listener != NULL) { - LOG(WARNING) << "Already forwarding port " << port - << ". Attempting to restart the listener.\n"; - // Note that this deletes the listener object. - listeners_.erase(listener_it); - } - scoped_ptr new_listener( - DeviceListener::Create( - socket.Pass(), port, base::Bind(&DeviceController::DeleteListener, - weak_ptr_factory_.GetWeakPtr()))); - if (!new_listener) - return; - new_listener->Start(); - // |port| can be zero, to allow dynamically allocated port, so instead, we - // call DeviceListener::listener_port() to retrieve the currently - // allocated port to this new listener. - const int listener_port = new_listener->listener_port(); - listeners_.insert( - std::make_pair(listener_port, - linked_ptr(new_listener.release()))); - LOG(INFO) << "Forwarding device port " << listener_port << " to host."; - break; - } - case command::DATA_CONNECTION: - if (listener == NULL) { - LOG(ERROR) << "Data Connection command received, but " - << "listener has not been set up yet for port " << port; - // After this point it is assumed that, once we close our Adb Data - // socket, the Adb forwarder command will propagate the closing of - // sockets all the way to the host side. - break; - } - listener->SetAdbDataSocket(socket.Pass()); - break; - case command::UNLISTEN: - if (!listener) { - SendCommand(command::UNLISTEN_ERROR, port, socket.get()); - break; - } - listeners_.erase(listener_it); - SendCommand(command::UNLISTEN_SUCCESS, port, socket.get()); - break; - default: - // TODO(felipeg): add a KillAllListeners command. - LOG(ERROR) << "Invalid command received. Port: " << port - << " Command: " << command; - } -} - -// static -void DeviceController::DeleteListener( - const base::WeakPtr& device_controller_ptr, - int listener_port) { - DeviceController* const controller = device_controller_ptr.get(); - if (!controller) - return; - DCHECK(controller->construction_task_runner_->RunsTasksOnCurrentThread()); - const ListenersMap::iterator listener_it = controller->listeners_.find( - listener_port); - if (listener_it == controller->listeners_.end()) - return; - const linked_ptr listener = listener_it->second; - // Note that the listener is removed from the map before it gets destroyed in - // case its destructor would access the map. - controller->listeners_.erase(listener_it); -} - -} // namespace forwarder diff --git a/tools/android/forwarder2/device_controller.h b/tools/android/forwarder2/device_controller.h deleted file mode 100644 index 3daedb3688..0000000000 --- a/tools/android/forwarder2/device_controller.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef TOOLS_ANDROID_FORWARDER2_DEVICE_CONTROLLER_H_ -#define TOOLS_ANDROID_FORWARDER2_DEVICE_CONTROLLER_H_ - -#include - -#include "base/basictypes.h" -#include "base/containers/hash_tables.h" -#include "base/memory/linked_ptr.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "tools/android/forwarder2/socket.h" - -namespace base { -class SingleThreadTaskRunner; -} // namespace base - -namespace forwarder2 { - -class DeviceListener; - -// There is a single DeviceController per device_forwarder process, and it is in -// charge of managing all active redirections on the device side (one -// DeviceListener each). -class DeviceController { - public: - static scoped_ptr Create(const std::string& adb_unix_socket, - int exit_notifier_fd); - ~DeviceController(); - - void Start(); - - private: - typedef base::hash_map< - int /* port */, linked_ptr > ListenersMap; - - DeviceController(scoped_ptr host_socket, int exit_notifier_fd); - - void AcceptHostCommandSoon(); - void AcceptHostCommandInternal(); - - // Note that this can end up being called after the DeviceController is - // destroyed which is why a weak pointer is used. - static void DeleteListener( - const base::WeakPtr& device_controller_ptr, - int listener_port); - - const scoped_ptr host_socket_; - // Used to notify the controller to exit. - const int exit_notifier_fd_; - // Lets ensure DeviceListener instances are deleted on the thread they were - // created on. - const scoped_refptr construction_task_runner_; - base::WeakPtrFactory weak_ptr_factory_; - ListenersMap listeners_; - - DISALLOW_COPY_AND_ASSIGN(DeviceController); -}; - -} // namespace forwarder - -#endif // TOOLS_ANDROID_FORWARDER2_DEVICE_CONTROLLER_H_ diff --git a/tools/android/forwarder2/device_forwarder_main.cc b/tools/android/forwarder2/device_forwarder_main.cc deleted file mode 100644 index cad46f465a..0000000000 --- a/tools/android/forwarder2/device_forwarder_main.cc +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include -#include - -#include -#include - -#include "base/at_exit.h" -#include "base/bind.h" -#include "base/command_line.h" -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "base/strings/string_piece.h" -#include "base/strings/stringprintf.h" -#include "base/threading/thread.h" -#include "tools/android/forwarder2/common.h" -#include "tools/android/forwarder2/daemon.h" -#include "tools/android/forwarder2/device_controller.h" -#include "tools/android/forwarder2/pipe_notifier.h" - -namespace forwarder2 { -namespace { - -// Leaky global instance, accessed from the signal handler. -forwarder2::PipeNotifier* g_notifier = NULL; - -const int kBufSize = 256; - -const char kUnixDomainSocketPath[] = "chrome_device_forwarder"; -const char kDaemonIdentifier[] = "chrome_device_forwarder_daemon"; - -void KillHandler(int /* unused */) { - CHECK(g_notifier); - if (!g_notifier->Notify()) - exit(1); -} - -// Lets the daemon fetch the exit notifier file descriptor. -int GetExitNotifierFD() { - DCHECK(g_notifier); - return g_notifier->receiver_fd(); -} - -class ServerDelegate : public Daemon::ServerDelegate { - public: - ServerDelegate() : initialized_(false) {} - - virtual ~ServerDelegate() { - if (!controller_thread_.get()) - return; - // The DeviceController instance, if any, is constructed on the controller - // thread. Make sure that it gets deleted on that same thread. Note that - // DeleteSoon() is not used here since it would imply reading |controller_| - // from the main thread while it's set on the internal thread. - controller_thread_->message_loop_proxy()->PostTask( - FROM_HERE, - base::Bind(&ServerDelegate::DeleteControllerOnInternalThread, - base::Unretained(this))); - } - - void DeleteControllerOnInternalThread() { - DCHECK( - controller_thread_->message_loop_proxy()->RunsTasksOnCurrentThread()); - controller_.reset(); - } - - // Daemon::ServerDelegate: - virtual void Init() OVERRIDE { - DCHECK(!g_notifier); - g_notifier = new forwarder2::PipeNotifier(); - signal(SIGTERM, KillHandler); - signal(SIGINT, KillHandler); - controller_thread_.reset(new base::Thread("controller_thread")); - controller_thread_->Start(); - } - - virtual void OnClientConnected(scoped_ptr client_socket) OVERRIDE { - if (initialized_) { - client_socket->WriteString("OK"); - return; - } - controller_thread_->message_loop()->PostTask( - FROM_HERE, - base::Bind(&ServerDelegate::StartController, base::Unretained(this), - GetExitNotifierFD(), base::Passed(&client_socket))); - initialized_ = true; - } - - private: - void StartController(int exit_notifier_fd, scoped_ptr client_socket) { - DCHECK(!controller_.get()); - scoped_ptr controller( - DeviceController::Create(kUnixDomainSocketPath, exit_notifier_fd)); - if (!controller.get()) { - client_socket->WriteString( - base::StringPrintf("ERROR: Could not initialize device controller " - "with ADB socket path: %s", - kUnixDomainSocketPath)); - return; - } - controller_.swap(controller); - controller_->Start(); - client_socket->WriteString("OK"); - client_socket->Close(); - } - - scoped_ptr controller_; - scoped_ptr controller_thread_; - bool initialized_; -}; - -class ClientDelegate : public Daemon::ClientDelegate { - public: - ClientDelegate() : has_failed_(false) {} - - bool has_failed() const { return has_failed_; } - - // Daemon::ClientDelegate: - virtual void OnDaemonReady(Socket* daemon_socket) OVERRIDE { - char buf[kBufSize]; - const int bytes_read = daemon_socket->Read( - buf, sizeof(buf) - 1 /* leave space for null terminator */); - CHECK_GT(bytes_read, 0); - DCHECK(bytes_read < sizeof(buf)); - buf[bytes_read] = 0; - base::StringPiece msg(buf, bytes_read); - if (msg.starts_with("ERROR")) { - LOG(ERROR) << msg; - has_failed_ = true; - return; - } - } - - private: - bool has_failed_; -}; - -int RunDeviceForwarder(int argc, char** argv) { - CommandLine::Init(argc, argv); // Needed by logging. - const bool kill_server = CommandLine::ForCurrentProcess()->HasSwitch( - "kill-server"); - if ((kill_server && argc != 2) || (!kill_server && argc != 1)) { - std::cerr << "Usage: device_forwarder [--kill-server]" << std::endl; - return 1; - } - base::AtExitManager at_exit_manager; // Used by base::Thread. - ClientDelegate client_delegate; - ServerDelegate daemon_delegate; - const char kLogFilePath[] = ""; // Log to logcat. - Daemon daemon(kLogFilePath, kDaemonIdentifier, &client_delegate, - &daemon_delegate, &GetExitNotifierFD); - - if (kill_server) - return !daemon.Kill(); - - if (!daemon.SpawnIfNeeded()) - return 1; - return client_delegate.has_failed(); -} - -} // namespace -} // namespace forwarder2 - -int main(int argc, char** argv) { - return forwarder2::RunDeviceForwarder(argc, argv); -} diff --git a/tools/android/forwarder2/device_listener.cc b/tools/android/forwarder2/device_listener.cc deleted file mode 100644 index 1819a8a6ed..0000000000 --- a/tools/android/forwarder2/device_listener.cc +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/android/forwarder2/device_listener.h" - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/callback.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop_proxy.h" -#include "base/single_thread_task_runner.h" -#include "tools/android/forwarder2/command.h" -#include "tools/android/forwarder2/forwarder.h" -#include "tools/android/forwarder2/socket.h" - -namespace forwarder2 { - -// static -scoped_ptr DeviceListener::Create( - scoped_ptr host_socket, - int listener_port, - const DeleteCallback& delete_callback) { - scoped_ptr listener_socket(new Socket()); - scoped_ptr device_listener; - if (!listener_socket->BindTcp("", listener_port)) { - LOG(ERROR) << "Device could not bind and listen to local port " - << listener_port; - SendCommand(command::BIND_ERROR, listener_port, host_socket.get()); - return device_listener.Pass(); - } - // In case the |listener_port_| was zero, GetPort() will return the - // currently (non-zero) allocated port for this socket. - listener_port = listener_socket->GetPort(); - SendCommand(command::BIND_SUCCESS, listener_port, host_socket.get()); - device_listener.reset( - new DeviceListener( - scoped_ptr(new PipeNotifier()), listener_socket.Pass(), - host_socket.Pass(), listener_port, delete_callback)); - return device_listener.Pass(); -} - -DeviceListener::~DeviceListener() { - DCHECK(deletion_task_runner_->RunsTasksOnCurrentThread()); - exit_notifier_->Notify(); -} - -void DeviceListener::Start() { - thread_.Start(); - AcceptNextClientSoon(); -} - -void DeviceListener::SetAdbDataSocket(scoped_ptr adb_data_socket) { - thread_.message_loop_proxy()->PostTask( - FROM_HERE, - base::Bind(&DeviceListener::OnAdbDataSocketReceivedOnInternalThread, - base::Unretained(this), base::Passed(&adb_data_socket))); -} - -DeviceListener::DeviceListener(scoped_ptr pipe_notifier, - scoped_ptr listener_socket, - scoped_ptr host_socket, - int port, - const DeleteCallback& delete_callback) - : exit_notifier_(pipe_notifier.Pass()), - listener_socket_(listener_socket.Pass()), - host_socket_(host_socket.Pass()), - listener_port_(port), - delete_callback_(delete_callback), - deletion_task_runner_(base::MessageLoopProxy::current()), - thread_("DeviceListener") { - CHECK(host_socket_.get()); - DCHECK(deletion_task_runner_.get()); - DCHECK(exit_notifier_.get()); - host_socket_->AddEventFd(exit_notifier_->receiver_fd()); - listener_socket_->AddEventFd(exit_notifier_->receiver_fd()); -} - -void DeviceListener::AcceptNextClientSoon() { - thread_.message_loop_proxy()->PostTask( - FROM_HERE, - base::Bind(&DeviceListener::AcceptClientOnInternalThread, - base::Unretained(this))); -} - -void DeviceListener::AcceptClientOnInternalThread() { - device_data_socket_.reset(new Socket()); - if (!listener_socket_->Accept(device_data_socket_.get())) { - if (listener_socket_->DidReceiveEvent()) { - LOG(INFO) << "Received exit notification, stopped accepting clients."; - SelfDelete(); - return; - } - LOG(WARNING) << "Could not Accept in ListenerSocket."; - SendCommand(command::ACCEPT_ERROR, listener_port_, host_socket_.get()); - SelfDelete(); - return; - } - SendCommand(command::ACCEPT_SUCCESS, listener_port_, host_socket_.get()); - if (!ReceivedCommand(command::HOST_SERVER_SUCCESS, - host_socket_.get())) { - SendCommand(command::ACK, listener_port_, host_socket_.get()); - LOG(ERROR) << "Host could not connect to server."; - device_data_socket_->Close(); - if (host_socket_->has_error()) { - LOG(ERROR) << "Adb Control connection lost. " - << "Listener port: " << listener_port_; - SelfDelete(); - return; - } - // It can continue if the host forwarder could not connect to the host - // server but the control connection is still alive (no errors). The device - // acknowledged that (above), and it can re-try later. - AcceptNextClientSoon(); - return; - } -} - -void DeviceListener::OnAdbDataSocketReceivedOnInternalThread( - scoped_ptr adb_data_socket) { - adb_data_socket_.swap(adb_data_socket); - SendCommand(command::ADB_DATA_SOCKET_SUCCESS, listener_port_, - host_socket_.get()); - CHECK(adb_data_socket_.get()); - StartForwarder(device_data_socket_.Pass(), adb_data_socket_.Pass()); - AcceptNextClientSoon(); -} - -void DeviceListener::SelfDelete() { - if (!deletion_task_runner_->RunsTasksOnCurrentThread()) { - deletion_task_runner_->PostTask( - FROM_HERE, - base::Bind(&DeviceListener::SelfDeleteOnDeletionTaskRunner, - delete_callback_, listener_port_)); - return; - } - SelfDeleteOnDeletionTaskRunner(delete_callback_, listener_port_); -} - -// static -void DeviceListener::SelfDeleteOnDeletionTaskRunner( - const DeleteCallback& delete_callback, - int listener_port) { - delete_callback.Run(listener_port); -} - -} // namespace forwarder diff --git a/tools/android/forwarder2/device_listener.h b/tools/android/forwarder2/device_listener.h deleted file mode 100644 index 2a69823196..0000000000 --- a/tools/android/forwarder2/device_listener.h +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef TOOLS_ANDROID_FORWARDER2_DEVICE_LISTENER_H_ -#define TOOLS_ANDROID_FORWARDER2_DEVICE_LISTENER_H_ - -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/threading/thread.h" -#include "tools/android/forwarder2/pipe_notifier.h" -#include "tools/android/forwarder2/socket.h" - -namespace base { -class SingleThreadTaskRunner; -} // namespace base - -namespace forwarder2 { - -class Forwarder; - -// A DeviceListener instance is used in the device_forwarder program to bind to -// a specific device-side |port| and wait for client connections. When a -// connection happens, it informs the corresponding HostController instance -// running on the host, through |host_socket|. Then the class expects a call to -// its SetAdbDataSocket() method (performed by the device controller) once the -// host opened a new connection to the device. When this happens, a new internal -// Forwarder instance is started. -// Note that instances of this class are owned by the device controller which -// creates and destroys them on the same thread. In case an internal error -// happens on the DeviceListener's internal thread, the DeviceListener -// can also self-delete by executing the user-provided callback on the thread -// the DeviceListener was created on. -// Note that the DeviceListener's destructor joins its internal thread (i.e. -// waits for its completion) which means that the internal thread is guaranteed -// not to be running anymore once the object is deleted. -class DeviceListener { - public: - // Callback that is used for self-deletion as a way to let the device - // controller perform some additional cleanup work (e.g. removing the device - // listener instance from its internal map before deleting it). - typedef base::Callback DeleteCallback; - - static scoped_ptr Create( - scoped_ptr host_socket, - int port, - const DeleteCallback& delete_callback); - - ~DeviceListener(); - - void Start(); - - void SetAdbDataSocket(scoped_ptr adb_data_socket); - - int listener_port() const { return listener_port_; } - - private: - DeviceListener(scoped_ptr pipe_notifier, - scoped_ptr listener_socket, - scoped_ptr host_socket, - int port, - const DeleteCallback& delete_callback); - - // Pushes an AcceptClientOnInternalThread() task to the internal thread's - // message queue in order to wait for a new client soon. - void AcceptNextClientSoon(); - - void AcceptClientOnInternalThread(); - - void OnAdbDataSocketReceivedOnInternalThread( - scoped_ptr adb_data_socket); - - void SelfDelete(); - - // Note that this can be called after the DeviceListener instance gets deleted - // which is why this method is static. - static void SelfDeleteOnDeletionTaskRunner( - const DeleteCallback& delete_callback, - int listener_port); - - // Used for the listener thread to be notified on destruction. We have one - // notifier per Listener thread since each Listener thread may be requested to - // exit for different reasons independently from each other and independent - // from the main program, ex. when the host requests to forward/listen the - // same port again. Both the |host_socket_| and |listener_socket_| - // must share the same receiver file descriptor from |exit_notifier_| and it - // is set in the constructor. - const scoped_ptr exit_notifier_; - // The local device listener socket for accepting connections from the local - // port (listener_port_). - const scoped_ptr listener_socket_; - // The listener socket for sending control commands. - const scoped_ptr host_socket_; - scoped_ptr device_data_socket_; - // This is the adb connection to transport the actual data, used for creating - // the forwarder. Ownership transferred to the Forwarder. - scoped_ptr adb_data_socket_; - const int listener_port_; - const DeleteCallback delete_callback_; - // Task runner used for deletion set at construction time (i.e. the object is - // deleted on the same thread it is created on). - scoped_refptr deletion_task_runner_; - base::Thread thread_; - - DISALLOW_COPY_AND_ASSIGN(DeviceListener); -}; - -} // namespace forwarder - -#endif // TOOLS_ANDROID_FORWARDER2_DEVICE_LISTENER_H_ diff --git a/tools/android/forwarder2/forwarder.cc b/tools/android/forwarder2/forwarder.cc deleted file mode 100644 index df4c29cf9f..0000000000 --- a/tools/android/forwarder2/forwarder.cc +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/android/forwarder2/forwarder.h" - -#include "base/basictypes.h" -#include "base/bind.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/posix/eintr_wrapper.h" -#include "base/single_thread_task_runner.h" -#include "tools/android/forwarder2/socket.h" - -namespace forwarder2 { -namespace { - -// Helper class to buffer reads and writes from one socket to another. -class BufferedCopier { - public: - // Does NOT own the pointers. - BufferedCopier(Socket* socket_from, - Socket* socket_to) - : socket_from_(socket_from), - socket_to_(socket_to), - bytes_read_(0), - write_offset_(0) { - } - - bool AddToReadSet(fd_set* read_fds) { - if (bytes_read_ == 0) - return socket_from_->AddFdToSet(read_fds); - return false; - } - - bool AddToWriteSet(fd_set* write_fds) { - if (write_offset_ < bytes_read_) - return socket_to_->AddFdToSet(write_fds); - return false; - } - - bool TryRead(const fd_set& read_fds) { - if (!socket_from_->IsFdInSet(read_fds)) - return false; - if (bytes_read_ != 0) // Can't read. - return false; - int ret = socket_from_->Read(buffer_, kBufferSize); - if (ret > 0) { - bytes_read_ = ret; - return true; - } - return false; - } - - bool TryWrite(const fd_set& write_fds) { - if (!socket_to_->IsFdInSet(write_fds)) - return false; - if (write_offset_ >= bytes_read_) // Nothing to write. - return false; - int ret = socket_to_->Write(buffer_ + write_offset_, - bytes_read_ - write_offset_); - if (ret > 0) { - write_offset_ += ret; - if (write_offset_ == bytes_read_) { - write_offset_ = 0; - bytes_read_ = 0; - } - return true; - } - return false; - } - - private: - // Not owned. - Socket* socket_from_; - Socket* socket_to_; - - // A big buffer to let our file-over-http bridge work more like real file. - static const int kBufferSize = 1024 * 128; - int bytes_read_; - int write_offset_; - char buffer_[kBufferSize]; - - DISALLOW_COPY_AND_ASSIGN(BufferedCopier); -}; - -// Internal class that wraps a helper thread to forward traffic between -// |socket1| and |socket2|. After creating a new instance, call its Start() -// method to launch operations. Thread stops automatically if one of the socket -// disconnects, but ensures that all buffered writes to the other, still alive, -// socket, are written first. When this happens, the instance will delete itself -// automatically. -// Note that the instance will always be destroyed on the same thread that -// created it. -class Forwarder { - public: - Forwarder(scoped_ptr socket1, scoped_ptr socket2) - : socket1_(socket1.Pass()), - socket2_(socket2.Pass()), - destructor_runner_(base::MessageLoopProxy::current()), - thread_("ForwarderThread") { - } - - void Start() { - thread_.Start(); - thread_.message_loop_proxy()->PostTask( - FROM_HERE, - base::Bind(&Forwarder::ThreadHandler, base::Unretained(this))); - } - - private: - void ThreadHandler() { - const int nfds = Socket::GetHighestFileDescriptor(*socket1_, *socket2_) + 1; - fd_set read_fds; - fd_set write_fds; - - // Copy from socket1 to socket2 - BufferedCopier buffer1(socket1_.get(), socket2_.get()); - // Copy from socket2 to socket1 - BufferedCopier buffer2(socket2_.get(), socket1_.get()); - - bool run = true; - while (run) { - FD_ZERO(&read_fds); - FD_ZERO(&write_fds); - - buffer1.AddToReadSet(&read_fds); - buffer2.AddToReadSet(&read_fds); - buffer1.AddToWriteSet(&write_fds); - buffer2.AddToWriteSet(&write_fds); - - if (HANDLE_EINTR(select(nfds, &read_fds, &write_fds, NULL, NULL)) <= 0) { - PLOG(ERROR) << "select"; - break; - } - // When a socket in the read set closes the connection, select() returns - // with that socket descriptor set as "ready to read". When we call - // TryRead() below, it will return false, but the while loop will continue - // to run until all the write operations are finished, to make sure the - // buffers are completely flushed out. - - // Keep running while we have some operation to do. - run = buffer1.TryRead(read_fds); - run = run || buffer2.TryRead(read_fds); - run = run || buffer1.TryWrite(write_fds); - run = run || buffer2.TryWrite(write_fds); - } - - // Note that the thread that |destruction_runner_| runs tasks on could be - // temporarily blocked on I/O (e.g. select()) therefore it is safer to close - // the sockets now rather than relying on the destructor. - socket1_.reset(); - socket2_.reset(); - - // Note that base::Thread must be destroyed on the thread it was created on. - destructor_runner_->DeleteSoon(FROM_HERE, this); - } - - scoped_ptr socket1_; - scoped_ptr socket2_; - scoped_refptr destructor_runner_; - base::Thread thread_; -}; - -} // namespace - -void StartForwarder(scoped_ptr socket1, scoped_ptr socket2) { - (new Forwarder(socket1.Pass(), socket2.Pass()))->Start(); -} - -} // namespace forwarder2 diff --git a/tools/android/forwarder2/forwarder.gyp b/tools/android/forwarder2/forwarder.gyp deleted file mode 100644 index fdc19aa4ce..0000000000 --- a/tools/android/forwarder2/forwarder.gyp +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -{ - 'targets': [ - { - 'target_name': 'forwarder2', - 'type': 'none', - 'dependencies': [ - 'device_forwarder', - 'host_forwarder#host', - ], - # For the component build, ensure dependent shared libraries are stripped - # and put alongside forwarder to simplify pushing to the device. - 'variables': { - 'output_dir': '<(PRODUCT_DIR)/forwarder_dist/', - 'native_binary': '<(PRODUCT_DIR)/device_forwarder', - }, - 'includes': ['../../../build/android/native_app_dependencies.gypi'], - }, - { - 'target_name': 'device_forwarder', - 'type': 'executable', - 'toolsets': ['target'], - 'dependencies': [ - '../../../base/base.gyp:base', - '../common/common.gyp:android_tools_common', - ], - 'include_dirs': [ - '../../..', - ], - 'conditions': [ - # Warning: A PIE tool cannot run on ICS 4.0.4, so only - # build it as position-independent when ASAN - # is activated. See b/6587214 for details. - [ 'asan==1', { - 'cflags': [ - '-fPIE', - ], - 'ldflags': [ - '-pie', - ], - }], - ], - 'sources': [ - 'command.cc', - 'common.cc', - 'daemon.cc', - 'device_controller.cc', - 'device_forwarder_main.cc', - 'device_listener.cc', - 'forwarder.cc', - 'pipe_notifier.cc', - 'socket.cc', - ], - }, - { - 'target_name': 'host_forwarder', - 'type': 'executable', - 'toolsets': ['host'], - 'dependencies': [ - '../../../base/base.gyp:base', - '../common/common.gyp:android_tools_common', - ], - 'include_dirs': [ - '../../..', - ], - 'sources': [ - 'command.cc', - 'common.cc', - 'daemon.cc', - 'forwarder.cc', - 'host_controller.cc', - 'host_forwarder_main.cc', - 'pipe_notifier.cc', - 'socket.cc', - # TODO(pliard): Remove this. This is needed to avoid undefined - # references at link time. - '../../../base/message_loop/message_pump_glib.cc', - '../../../base/message_loop/message_pump_gtk.cc', - ], - }, - ], -} diff --git a/tools/android/forwarder2/forwarder.h b/tools/android/forwarder2/forwarder.h deleted file mode 100644 index 651b5e80f7..0000000000 --- a/tools/android/forwarder2/forwarder.h +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef TOOLS_ANDROID_FORWARDER2_FORWARDER_H_ -#define TOOLS_ANDROID_FORWARDER2_FORWARDER_H_ - -#include "base/memory/scoped_ptr.h" -#include "base/threading/thread.h" - -namespace forwarder2 { - -class Socket; - -void StartForwarder(scoped_ptr socket1, scoped_ptr socket2); - -} // namespace forwarder2 - -#endif // TOOLS_ANDROID_FORWARDER2_FORWARDER_H_ diff --git a/tools/android/forwarder2/host_controller.cc b/tools/android/forwarder2/host_controller.cc deleted file mode 100644 index 1588e7291b..0000000000 --- a/tools/android/forwarder2/host_controller.cc +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/android/forwarder2/host_controller.h" - -#include - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "tools/android/forwarder2/command.h" -#include "tools/android/forwarder2/forwarder.h" -#include "tools/android/forwarder2/socket.h" - -namespace forwarder2 { - -// static -scoped_ptr HostController::Create( - int device_port, - int host_port, - int adb_port, - int exit_notifier_fd, - const DeletionCallback& deletion_callback) { - scoped_ptr host_controller; - scoped_ptr delete_controller_notifier(new PipeNotifier()); - scoped_ptr adb_control_socket(new Socket()); - adb_control_socket->AddEventFd(exit_notifier_fd); - adb_control_socket->AddEventFd(delete_controller_notifier->receiver_fd()); - if (!adb_control_socket->ConnectTcp(std::string(), adb_port)) { - LOG(ERROR) << "Could not connect HostController socket on port: " - << adb_port; - return host_controller.Pass(); - } - // Send the command to the device start listening to the "device_forward_port" - bool send_command_success = SendCommand( - command::LISTEN, device_port, adb_control_socket.get()); - CHECK(send_command_success); - int device_port_allocated; - command::Type command; - if (!ReadCommand( - adb_control_socket.get(), &device_port_allocated, &command) || - command != command::BIND_SUCCESS) { - LOG(ERROR) << "Device binding error using port " << device_port; - return host_controller.Pass(); - } - host_controller.reset( - new HostController( - device_port_allocated, host_port, adb_port, exit_notifier_fd, - deletion_callback, adb_control_socket.Pass(), - delete_controller_notifier.Pass())); - return host_controller.Pass(); -} - -HostController::~HostController() { - DCHECK(deletion_task_runner_->RunsTasksOnCurrentThread()); - delete_controller_notifier_->Notify(); - // Note that the Forwarder instance (that also received a delete notification) - // might still be running on its own thread at this point. This is not a - // problem since it will self-delete once the socket that it is operating on - // is closed. -} - -void HostController::Start() { - thread_.Start(); - ReadNextCommandSoon(); -} - -HostController::HostController( - int device_port, - int host_port, - int adb_port, - int exit_notifier_fd, - const DeletionCallback& deletion_callback, - scoped_ptr adb_control_socket, - scoped_ptr delete_controller_notifier) - : device_port_(device_port), - host_port_(host_port), - adb_port_(adb_port), - global_exit_notifier_fd_(exit_notifier_fd), - deletion_callback_(deletion_callback), - adb_control_socket_(adb_control_socket.Pass()), - delete_controller_notifier_(delete_controller_notifier.Pass()), - deletion_task_runner_(base::MessageLoopProxy::current()), - thread_("HostControllerThread") { -} - -void HostController::ReadNextCommandSoon() { - thread_.message_loop_proxy()->PostTask( - FROM_HERE, - base::Bind(&HostController::ReadCommandOnInternalThread, - base::Unretained(this))); -} - -void HostController::ReadCommandOnInternalThread() { - if (!ReceivedCommand(command::ACCEPT_SUCCESS, adb_control_socket_.get())) { - SelfDelete(); - return; - } - // Try to connect to host server. - scoped_ptr host_server_data_socket(CreateSocket()); - if (!host_server_data_socket->ConnectTcp(std::string(), host_port_)) { - LOG(ERROR) << "Could not Connect HostServerData socket on port: " - << host_port_; - SendCommand( - command::HOST_SERVER_ERROR, device_port_, adb_control_socket_.get()); - if (ReceivedCommand(command::ACK, adb_control_socket_.get())) { - // It can continue if the host forwarder could not connect to the host - // server but the device acknowledged that, so that the device could - // re-try later. - ReadNextCommandSoon(); - return; - } - SelfDelete(); - return; - } - SendCommand( - command::HOST_SERVER_SUCCESS, device_port_, adb_control_socket_.get()); - StartForwarder(host_server_data_socket.Pass()); - ReadNextCommandSoon(); -} - -void HostController::StartForwarder( - scoped_ptr host_server_data_socket) { - scoped_ptr adb_data_socket(CreateSocket()); - if (!adb_data_socket->ConnectTcp("", adb_port_)) { - LOG(ERROR) << "Could not connect AdbDataSocket on port: " << adb_port_; - SelfDelete(); - return; - } - // Open the Adb data connection, and send a command with the - // |device_forward_port| as a way for the device to identify the connection. - SendCommand(command::DATA_CONNECTION, device_port_, adb_data_socket.get()); - - // Check that the device received the new Adb Data Connection. Note that this - // check is done through the |adb_control_socket_| that is handled in the - // DeviceListener thread just after the call to WaitForAdbDataSocket(). - if (!ReceivedCommand(command::ADB_DATA_SOCKET_SUCCESS, - adb_control_socket_.get())) { - LOG(ERROR) << "Device could not handle the new Adb Data Connection."; - SelfDelete(); - return; - } - forwarder2::StartForwarder( - host_server_data_socket.Pass(), adb_data_socket.Pass()); -} - -scoped_ptr HostController::CreateSocket() { - scoped_ptr socket(new Socket()); - socket->AddEventFd(global_exit_notifier_fd_); - socket->AddEventFd(delete_controller_notifier_->receiver_fd()); - return socket.Pass(); -} - -void HostController::SelfDelete() { - scoped_ptr self_deleter(this); - deletion_task_runner_->PostTask( - FROM_HERE, - base::Bind(&HostController::SelfDeleteOnDeletionTaskRunner, - deletion_callback_, base::Passed(&self_deleter))); - // Tell the device to delete its corresponding controller instance before we - // self-delete. - Socket socket; - if (!socket.ConnectTcp("", adb_port_)) { - LOG(ERROR) << "Could not connect to device on port " << adb_port_; - return; - } - if (!SendCommand(command::UNLISTEN, device_port_, &socket)) { - LOG(ERROR) << "Could not send unmap command for port " << device_port_; - return; - } - if (!ReceivedCommand(command::UNLISTEN_SUCCESS, &socket)) { - LOG(ERROR) << "Unamp command failed for port " << device_port_; - return; - } -} - -// static -void HostController::SelfDeleteOnDeletionTaskRunner( - const DeletionCallback& deletion_callback, - scoped_ptr controller) { - deletion_callback.Run(controller.Pass()); -} - -} // namespace forwarder2 diff --git a/tools/android/forwarder2/host_controller.h b/tools/android/forwarder2/host_controller.h deleted file mode 100644 index aaedb945e8..0000000000 --- a/tools/android/forwarder2/host_controller.h +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef TOOLS_ANDROID_FORWARDER2_HOST_CONTROLLER_H_ -#define TOOLS_ANDROID_FORWARDER2_HOST_CONTROLLER_H_ - -#include - -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "base/threading/thread.h" -#include "tools/android/forwarder2/pipe_notifier.h" -#include "tools/android/forwarder2/socket.h" - -namespace forwarder2 { - -// This class partners with DeviceController and has the same lifetime and -// threading characteristics as DeviceListener. In a nutshell, this class -// operates on its own thread and is destroyed on the thread it was constructed -// on. The class' deletion can happen in two different ways: -// - Its destructor was called by its owner (HostControllersManager). -// - Its internal thread requested self-deletion after an error happened. In -// this case the owner (HostControllersManager) is notified on the -// construction thread through the provided DeletionCallback invoked with the -// HostController instance. When this callback is invoked, it's up to the -// owner to delete the instance. -class HostController { - public: - // Callback used for self-deletion that lets the client perform some cleanup - // work before deleting the HostController instance. - typedef base::Callback)> DeletionCallback; - - // If |device_port| is zero then a dynamic port is allocated (and retrievable - // through device_port() below). - static scoped_ptr Create( - int device_port, - int host_port, - int adb_port, - int exit_notifier_fd, - const DeletionCallback& deletion_callback); - - ~HostController(); - - // Starts the internal controller thread. - void Start(); - - int adb_port() const { return adb_port_; } - - int device_port() const { return device_port_; } - - private: - HostController(int device_port, - int host_port, - int adb_port, - int exit_notifier_fd, - const DeletionCallback& deletion_callback, - scoped_ptr adb_control_socket, - scoped_ptr delete_controller_notifier); - - void ReadNextCommandSoon(); - void ReadCommandOnInternalThread(); - - void StartForwarder(scoped_ptr host_server_data_socket); - - // Helper method that creates a socket and adds the appropriate event file - // descriptors. - scoped_ptr CreateSocket(); - - void SelfDelete(); - - static void SelfDeleteOnDeletionTaskRunner( - const DeletionCallback& deletion_callback, - scoped_ptr controller); - - const int device_port_; - const int host_port_; - const int adb_port_; - // Used to notify the controller when the process is killed. - const int global_exit_notifier_fd_; - // Used to let the client delete the instance in case an error happened. - const DeletionCallback deletion_callback_; - scoped_ptr adb_control_socket_; - scoped_ptr delete_controller_notifier_; - // Used to cancel the pending blocking IO operations when the host controller - // instance is deleted. - // Task runner used for deletion set at construction time (i.e. the object is - // deleted on the same thread it is created on). - const scoped_refptr deletion_task_runner_; - base::Thread thread_; - - DISALLOW_COPY_AND_ASSIGN(HostController); -}; - -} // namespace forwarder2 - -#endif // TOOLS_ANDROID_FORWARDER2_HOST_CONTROLLER_H_ diff --git a/tools/android/forwarder2/host_forwarder_main.cc b/tools/android/forwarder2/host_forwarder_main.cc deleted file mode 100644 index 1071aa7dd4..0000000000 --- a/tools/android/forwarder2/host_forwarder_main.cc +++ /dev/null @@ -1,414 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "base/at_exit.h" -#include "base/basictypes.h" -#include "base/bind.h" -#include "base/command_line.h" -#include "base/compiler_specific.h" -#include "base/containers/hash_tables.h" -#include "base/file_util.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/memory/linked_ptr.h" -#include "base/memory/scoped_vector.h" -#include "base/memory/weak_ptr.h" -#include "base/pickle.h" -#include "base/posix/eintr_wrapper.h" -#include "base/safe_strerror_posix.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" -#include "base/strings/string_split.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "base/task_runner.h" -#include "base/threading/thread.h" -#include "tools/android/forwarder2/common.h" -#include "tools/android/forwarder2/daemon.h" -#include "tools/android/forwarder2/host_controller.h" -#include "tools/android/forwarder2/pipe_notifier.h" -#include "tools/android/forwarder2/socket.h" - -namespace forwarder2 { -namespace { - -const char kLogFilePath[] = "/tmp/host_forwarder_log"; -const char kDaemonIdentifier[] = "chrome_host_forwarder_daemon"; - -const char kKillServerCommand[] = "kill-server"; -const char kForwardCommand[] = "forward"; - -const int kBufSize = 256; - -// Needs to be global to be able to be accessed from the signal handler. -PipeNotifier* g_notifier = NULL; - -// Lets the daemon fetch the exit notifier file descriptor. -int GetExitNotifierFD() { - DCHECK(g_notifier); - return g_notifier->receiver_fd(); -} - -void KillHandler(int signal_number) { - char buf[kBufSize]; - if (signal_number != SIGTERM && signal_number != SIGINT) { - snprintf(buf, sizeof(buf), "Ignoring unexpected signal %d.", signal_number); - SIGNAL_SAFE_LOG(WARNING, buf); - return; - } - snprintf(buf, sizeof(buf), "Received signal %d.", signal_number); - SIGNAL_SAFE_LOG(WARNING, buf); - static int s_kill_handler_count = 0; - CHECK(g_notifier); - // If for some reason the forwarder get stuck in any socket waiting forever, - // we can send a SIGKILL or SIGINT three times to force it die - // (non-nicely). This is useful when debugging. - ++s_kill_handler_count; - if (!g_notifier->Notify() || s_kill_handler_count > 2) - exit(1); -} - -// Manages HostController instances. There is one HostController instance for -// each connection being forwarded. Note that forwarding can happen with many -// devices (identified with a serial id). -class HostControllersManager { - public: - HostControllersManager() - : weak_ptr_factory_(this), - controllers_(new HostControllerMap()), - has_failed_(false) { - } - - ~HostControllersManager() { - if (!thread_.get()) - return; - // Delete the controllers on the thread they were created on. - thread_->message_loop_proxy()->DeleteSoon( - FROM_HERE, controllers_.release()); - } - - void HandleRequest(const std::string& device_serial, - int device_port, - int host_port, - scoped_ptr client_socket) { - // Lazy initialize so that the CLI process doesn't get this thread created. - InitOnce(); - thread_->message_loop_proxy()->PostTask( - FROM_HERE, - base::Bind( - &HostControllersManager::HandleRequestOnInternalThread, - base::Unretained(this), device_serial, device_port, host_port, - base::Passed(&client_socket))); - } - - bool has_failed() const { return has_failed_; } - - private: - typedef base::hash_map< - std::string, linked_ptr > HostControllerMap; - - static std::string MakeHostControllerMapKey(int adb_port, int device_port) { - return base::StringPrintf("%d:%d", adb_port, device_port); - } - - void InitOnce() { - if (thread_.get()) - return; - at_exit_manager_.reset(new base::AtExitManager()); - thread_.reset(new base::Thread("HostControllersManagerThread")); - thread_->Start(); - } - - // Invoked when a HostController instance reports an error (e.g. due to a - // device connectivity issue). Note that this could be called after the - // controller manager was destroyed which is why a weak pointer is used. - static void DeleteHostController( - const base::WeakPtr& manager_ptr, - scoped_ptr host_controller) { - HostController* const controller = host_controller.release(); - HostControllersManager* const manager = manager_ptr.get(); - if (!manager) { - // Note that |controller| is not leaked in this case since the host - // controllers manager owns the controllers. If the manager was deleted - // then all the controllers (including |controller|) were also deleted. - return; - } - DCHECK(manager->thread_->message_loop_proxy()->RunsTasksOnCurrentThread()); - // Note that this will delete |controller| which is owned by the map. - manager->controllers_->erase( - MakeHostControllerMapKey(controller->adb_port(), - controller->device_port())); - } - - void HandleRequestOnInternalThread(const std::string& device_serial, - int device_port, - int host_port, - scoped_ptr client_socket) { - const int adb_port = GetAdbPortForDevice(device_serial); - if (adb_port < 0) { - SendMessage( - "ERROR: could not get adb port for device. You might need to add " - "'adb' to your PATH or provide the device serial id.", - client_socket.get()); - return; - } - if (device_port < 0) { - // Remove the previously created host controller. - const std::string controller_key = MakeHostControllerMapKey( - adb_port, -device_port); - const HostControllerMap::size_type removed_elements = controllers_->erase( - controller_key); - SendMessage( - !removed_elements ? "ERROR: could not unmap port" : "OK", - client_socket.get()); - return; - } - if (host_port < 0) { - SendMessage("ERROR: missing host port", client_socket.get()); - return; - } - const bool use_dynamic_port_allocation = device_port == 0; - if (!use_dynamic_port_allocation) { - const std::string controller_key = MakeHostControllerMapKey( - adb_port, device_port); - if (controllers_->find(controller_key) != controllers_->end()) { - LOG(INFO) << "Already forwarding device port " << device_port - << " to host port " << host_port; - SendMessage(base::StringPrintf("%d:%d", device_port, host_port), - client_socket.get()); - return; - } - } - // Create a new host controller. - scoped_ptr host_controller( - HostController::Create( - device_port, host_port, adb_port, GetExitNotifierFD(), - base::Bind(&HostControllersManager::DeleteHostController, - weak_ptr_factory_.GetWeakPtr()))); - if (!host_controller.get()) { - has_failed_ = true; - SendMessage("ERROR: Connection to device failed.", client_socket.get()); - return; - } - // Get the current allocated port. - device_port = host_controller->device_port(); - LOG(INFO) << "Forwarding device port " << device_port << " to host port " - << host_port; - const std::string msg = base::StringPrintf("%d:%d", device_port, host_port); - if (!SendMessage(msg, client_socket.get())) - return; - host_controller->Start(); - controllers_->insert( - std::make_pair(MakeHostControllerMapKey(adb_port, device_port), - linked_ptr(host_controller.release()))); - } - - int GetAdbPortForDevice(const std::string& device_serial) { - base::hash_map::const_iterator it = - device_serial_to_adb_port_map_.find(device_serial); - if (it != device_serial_to_adb_port_map_.end()) - return it->second; - Socket bind_socket; - CHECK(bind_socket.BindTcp("127.0.0.1", 0)); - const int port = bind_socket.GetPort(); - bind_socket.Close(); - const std::string serial_part = device_serial.empty() ? - std::string() : std::string("-s ") + device_serial; - const std::string command = base::StringPrintf( - "adb %s forward tcp:%d localabstract:chrome_device_forwarder", - device_serial.empty() ? "" : serial_part.c_str(), - port); - LOG(INFO) << command; - const int ret = system(command.c_str()); - if (ret < 0 || !WIFEXITED(ret) || WEXITSTATUS(ret) != 0) - return -1; - device_serial_to_adb_port_map_[device_serial] = port; - return port; - } - - bool SendMessage(const std::string& msg, Socket* client_socket) { - bool result = client_socket->WriteString(msg); - DCHECK(result); - if (!result) - has_failed_ = true; - return result; - } - - base::WeakPtrFactory weak_ptr_factory_; - base::hash_map device_serial_to_adb_port_map_; - scoped_ptr controllers_; - bool has_failed_; - scoped_ptr at_exit_manager_; // Needed by base::Thread. - scoped_ptr thread_; -}; - -class ServerDelegate : public Daemon::ServerDelegate { - public: - ServerDelegate() : has_failed_(false) {} - - bool has_failed() const { - return has_failed_ || controllers_manager_.has_failed(); - } - - // Daemon::ServerDelegate: - virtual void Init() OVERRIDE { - LOG(INFO) << "Starting host process daemon (pid=" << getpid() << ")"; - DCHECK(!g_notifier); - g_notifier = new PipeNotifier(); - signal(SIGTERM, KillHandler); - signal(SIGINT, KillHandler); - } - - virtual void OnClientConnected(scoped_ptr client_socket) OVERRIDE { - char buf[kBufSize]; - const int bytes_read = client_socket->Read(buf, sizeof(buf)); - if (bytes_read <= 0) { - if (client_socket->DidReceiveEvent()) - return; - PError("Read()"); - has_failed_ = true; - return; - } - const Pickle command_pickle(buf, bytes_read); - PickleIterator pickle_it(command_pickle); - std::string device_serial; - CHECK(pickle_it.ReadString(&device_serial)); - int device_port; - if (!pickle_it.ReadInt(&device_port)) { - client_socket->WriteString("ERROR: missing device port"); - return; - } - int host_port; - if (!pickle_it.ReadInt(&host_port)) - host_port = -1; - controllers_manager_.HandleRequest( - device_serial, device_port, host_port, client_socket.Pass()); - } - - private: - bool has_failed_; - HostControllersManager controllers_manager_; - - DISALLOW_COPY_AND_ASSIGN(ServerDelegate); -}; - -class ClientDelegate : public Daemon::ClientDelegate { - public: - ClientDelegate(const Pickle& command_pickle) - : command_pickle_(command_pickle), - has_failed_(false) { - } - - bool has_failed() const { return has_failed_; } - - // Daemon::ClientDelegate: - virtual void OnDaemonReady(Socket* daemon_socket) OVERRIDE { - // Send the forward command to the daemon. - CHECK_EQ(command_pickle_.size(), - daemon_socket->WriteNumBytes(command_pickle_.data(), - command_pickle_.size())); - char buf[kBufSize]; - const int bytes_read = daemon_socket->Read( - buf, sizeof(buf) - 1 /* leave space for null terminator */); - CHECK_GT(bytes_read, 0); - DCHECK(bytes_read < sizeof(buf)); - buf[bytes_read] = 0; - base::StringPiece msg(buf, bytes_read); - if (msg.starts_with("ERROR")) { - LOG(ERROR) << msg; - has_failed_ = true; - return; - } - printf("%s\n", buf); - } - - private: - const Pickle command_pickle_; - bool has_failed_; -}; - -void ExitWithUsage() { - std::cerr << "Usage: host_forwarder [options]\n\n" - "Options:\n" - " --serial-id=[0-9A-Z]{16}]\n" - " --map DEVICE_PORT HOST_PORT\n" - " --unmap DEVICE_PORT\n" - " --kill-server\n"; - exit(1); -} - -int PortToInt(const std::string& s) { - int value; - // Note that 0 is a valid port (used for dynamic port allocation). - if (!base::StringToInt(s, &value) || value < 0 || - value > std::numeric_limits::max()) { - LOG(ERROR) << "Could not convert string " << s << " to port"; - ExitWithUsage(); - } - return value; -} - -int RunHostForwarder(int argc, char** argv) { - CommandLine::Init(argc, argv); - const CommandLine& cmd_line = *CommandLine::ForCurrentProcess(); - bool kill_server = false; - - Pickle pickle; - pickle.WriteString( - cmd_line.HasSwitch("serial-id") ? - cmd_line.GetSwitchValueASCII("serial-id") : std::string()); - - const std::vector args = cmd_line.GetArgs(); - if (cmd_line.HasSwitch("kill-server")) { - kill_server = true; - } else if (cmd_line.HasSwitch("unmap")) { - if (args.size() != 1) - ExitWithUsage(); - // Note the minus sign below. - pickle.WriteInt(-PortToInt(args[0])); - } else if (cmd_line.HasSwitch("map")) { - if (args.size() != 2) - ExitWithUsage(); - pickle.WriteInt(PortToInt(args[0])); - pickle.WriteInt(PortToInt(args[1])); - } else { - ExitWithUsage(); - } - - if (kill_server && args.size() > 0) - ExitWithUsage(); - - ClientDelegate client_delegate(pickle); - ServerDelegate daemon_delegate; - Daemon daemon( - kLogFilePath, kDaemonIdentifier, &client_delegate, &daemon_delegate, - &GetExitNotifierFD); - - if (kill_server) - return !daemon.Kill(); - if (!daemon.SpawnIfNeeded()) - return 1; - - return client_delegate.has_failed() || daemon_delegate.has_failed(); -} - -} // namespace -} // namespace forwarder2 - -int main(int argc, char** argv) { - return forwarder2::RunHostForwarder(argc, argv); -} diff --git a/tools/android/forwarder2/pipe_notifier.cc b/tools/android/forwarder2/pipe_notifier.cc deleted file mode 100644 index 3aba18b0d0..0000000000 --- a/tools/android/forwarder2/pipe_notifier.cc +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/android/forwarder2/pipe_notifier.h" - -#include -#include -#include -#include - -#include "base/logging.h" -#include "base/posix/eintr_wrapper.h" -#include "base/safe_strerror_posix.h" - -namespace forwarder2 { - -PipeNotifier::PipeNotifier() { - int pipe_fd[2]; - int ret = pipe(pipe_fd); - CHECK_EQ(0, ret); - receiver_fd_ = pipe_fd[0]; - sender_fd_ = pipe_fd[1]; - fcntl(sender_fd_, F_SETFL, O_NONBLOCK); -} - -PipeNotifier::~PipeNotifier() { - (void) HANDLE_EINTR(close(receiver_fd_)); - (void) HANDLE_EINTR(close(sender_fd_)); -} - -bool PipeNotifier::Notify() { - CHECK_NE(-1, sender_fd_); - errno = 0; - int ret = HANDLE_EINTR(write(sender_fd_, "1", 1)); - if (ret < 0) { - LOG(WARNING) << "Error while notifying pipe. " << safe_strerror(errno); - return false; - } - return true; -} - -} // namespace forwarder diff --git a/tools/android/forwarder2/pipe_notifier.h b/tools/android/forwarder2/pipe_notifier.h deleted file mode 100644 index efe303b2c1..0000000000 --- a/tools/android/forwarder2/pipe_notifier.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef TOOLS_ANDROID_FORWARDER2_PIPE_NOTIFIER_H_ -#define TOOLS_ANDROID_FORWARDER2_PIPE_NOTIFIER_H_ - -#include "base/basictypes.h" - -namespace forwarder2 { - -// Helper class used to create a unix pipe that sends notifications to the -// |receiver_fd_| file descriptor when called |Notify()|. This should be used -// by the main thread to notify other threads that it must exit. -// The |receiver_fd_| can be put into a fd_set and used in a select together -// with a socket waiting to accept or read. -class PipeNotifier { - public: - PipeNotifier(); - ~PipeNotifier(); - - bool Notify(); - - int receiver_fd() const { return receiver_fd_; } - - private: - int sender_fd_; - int receiver_fd_; - - DISALLOW_COPY_AND_ASSIGN(PipeNotifier); -}; - -} // namespace forwarder - -#endif // TOOLS_ANDROID_FORWARDER2_PIPE_NOTIFIER_H_ diff --git a/tools/android/forwarder2/socket.cc b/tools/android/forwarder2/socket.cc deleted file mode 100644 index 9564e98634..0000000000 --- a/tools/android/forwarder2/socket.cc +++ /dev/null @@ -1,422 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/android/forwarder2/socket.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "base/logging.h" -#include "base/posix/eintr_wrapper.h" -#include "base/safe_strerror_posix.h" -#include "tools/android/common/net.h" -#include "tools/android/forwarder2/common.h" - -namespace { -const int kNoTimeout = -1; -const int kConnectTimeOut = 10; // Seconds. - -bool FamilyIsTCP(int family) { - return family == AF_INET || family == AF_INET6; -} -} // namespace - -namespace forwarder2 { - -bool Socket::BindUnix(const std::string& path) { - errno = 0; - if (!InitUnixSocket(path) || !BindAndListen()) { - Close(); - return false; - } - return true; -} - -bool Socket::BindTcp(const std::string& host, int port) { - errno = 0; - if (!InitTcpSocket(host, port) || !BindAndListen()) { - Close(); - return false; - } - return true; -} - -bool Socket::ConnectUnix(const std::string& path) { - errno = 0; - if (!InitUnixSocket(path) || !Connect()) { - Close(); - return false; - } - return true; -} - -bool Socket::ConnectTcp(const std::string& host, int port) { - errno = 0; - if (!InitTcpSocket(host, port) || !Connect()) { - Close(); - return false; - } - return true; -} - -Socket::Socket() - : socket_(-1), - port_(0), - socket_error_(false), - family_(AF_INET), - addr_ptr_(reinterpret_cast(&addr_.addr4)), - addr_len_(sizeof(sockaddr)) { - memset(&addr_, 0, sizeof(addr_)); -} - -Socket::~Socket() { - Close(); -} - -void Socket::Shutdown() { - if (!IsClosed()) { - PRESERVE_ERRNO_HANDLE_EINTR(shutdown(socket_, SHUT_RDWR)); - } -} - -void Socket::Close() { - if (!IsClosed()) { - CloseFD(socket_); - socket_ = -1; - } -} - -bool Socket::InitSocketInternal() { - socket_ = socket(family_, SOCK_STREAM, 0); - if (socket_ < 0) - return false; - tools::DisableNagle(socket_); - int reuse_addr = 1; - setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, - &reuse_addr, sizeof(reuse_addr)); - return true; -} - -bool Socket::InitUnixSocket(const std::string& path) { - static const size_t kPathMax = sizeof(addr_.addr_un.sun_path); - // For abstract sockets we need one extra byte for the leading zero. - if (path.size() + 2 /* '\0' */ > kPathMax) { - LOG(ERROR) << "The provided path is too big to create a unix " - << "domain socket: " << path; - return false; - } - family_ = PF_UNIX; - addr_.addr_un.sun_family = family_; - // Copied from net/socket/unix_domain_socket_posix.cc - // Convert the path given into abstract socket name. It must start with - // the '\0' character, so we are adding it. |addr_len| must specify the - // length of the structure exactly, as potentially the socket name may - // have '\0' characters embedded (although we don't support this). - // Note that addr_.addr_un.sun_path is already zero initialized. - memcpy(addr_.addr_un.sun_path + 1, path.c_str(), path.size()); - addr_len_ = path.size() + offsetof(struct sockaddr_un, sun_path) + 1; - addr_ptr_ = reinterpret_cast(&addr_.addr_un); - return InitSocketInternal(); -} - -bool Socket::InitTcpSocket(const std::string& host, int port) { - port_ = port; - if (host.empty()) { - // Use localhost: INADDR_LOOPBACK - family_ = AF_INET; - addr_.addr4.sin_family = family_; - addr_.addr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - } else if (!Resolve(host)) { - return false; - } - CHECK(FamilyIsTCP(family_)) << "Invalid socket family."; - if (family_ == AF_INET) { - addr_.addr4.sin_port = htons(port_); - addr_ptr_ = reinterpret_cast(&addr_.addr4); - addr_len_ = sizeof(addr_.addr4); - } else if (family_ == AF_INET6) { - addr_.addr6.sin6_port = htons(port_); - addr_ptr_ = reinterpret_cast(&addr_.addr6); - addr_len_ = sizeof(addr_.addr6); - } - return InitSocketInternal(); -} - -bool Socket::BindAndListen() { - errno = 0; - if (HANDLE_EINTR(bind(socket_, addr_ptr_, addr_len_)) < 0 || - HANDLE_EINTR(listen(socket_, SOMAXCONN)) < 0) { - SetSocketError(); - return false; - } - if (port_ == 0 && FamilyIsTCP(family_)) { - SockAddr addr; - memset(&addr, 0, sizeof(addr)); - socklen_t addrlen = 0; - sockaddr* addr_ptr = NULL; - uint16* port_ptr = NULL; - if (family_ == AF_INET) { - addr_ptr = reinterpret_cast(&addr.addr4); - port_ptr = &addr.addr4.sin_port; - addrlen = sizeof(addr.addr4); - } else if (family_ == AF_INET6) { - addr_ptr = reinterpret_cast(&addr.addr6); - port_ptr = &addr.addr6.sin6_port; - addrlen = sizeof(addr.addr6); - } - errno = 0; - if (getsockname(socket_, addr_ptr, &addrlen) != 0) { - LOG(ERROR) << "getsockname error: " << safe_strerror(errno);; - SetSocketError(); - return false; - } - port_ = ntohs(*port_ptr); - } - return true; -} - -bool Socket::Accept(Socket* new_socket) { - DCHECK(new_socket != NULL); - if (!WaitForEvent(READ, kNoTimeout)) { - SetSocketError(); - return false; - } - errno = 0; - int new_socket_fd = HANDLE_EINTR(accept(socket_, NULL, NULL)); - if (new_socket_fd < 0) { - SetSocketError(); - return false; - } - - tools::DisableNagle(new_socket_fd); - new_socket->socket_ = new_socket_fd; - return true; -} - -bool Socket::Connect() { - // Set non-block because we use select for connect. - const int kFlags = fcntl(socket_, F_GETFL); - DCHECK(!(kFlags & O_NONBLOCK)); - fcntl(socket_, F_SETFL, kFlags | O_NONBLOCK); - errno = 0; - if (HANDLE_EINTR(connect(socket_, addr_ptr_, addr_len_)) < 0 && - errno != EINPROGRESS) { - SetSocketError(); - PRESERVE_ERRNO_HANDLE_EINTR(fcntl(socket_, F_SETFL, kFlags)); - return false; - } - // Wait for connection to complete, or receive a notification. - if (!WaitForEvent(WRITE, kConnectTimeOut)) { - SetSocketError(); - PRESERVE_ERRNO_HANDLE_EINTR(fcntl(socket_, F_SETFL, kFlags)); - return false; - } - int socket_errno; - socklen_t opt_len = sizeof(socket_errno); - if (getsockopt(socket_, SOL_SOCKET, SO_ERROR, &socket_errno, &opt_len) < 0) { - LOG(ERROR) << "getsockopt(): " << safe_strerror(errno); - SetSocketError(); - PRESERVE_ERRNO_HANDLE_EINTR(fcntl(socket_, F_SETFL, kFlags)); - return false; - } - if (socket_errno != 0) { - LOG(ERROR) << "Could not connect to host: " << safe_strerror(socket_errno); - SetSocketError(); - PRESERVE_ERRNO_HANDLE_EINTR(fcntl(socket_, F_SETFL, kFlags)); - return false; - } - fcntl(socket_, F_SETFL, kFlags); - return true; -} - -bool Socket::Resolve(const std::string& host) { - struct addrinfo hints; - struct addrinfo* res; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags |= AI_CANONNAME; - - int errcode = getaddrinfo(host.c_str(), NULL, &hints, &res); - if (errcode != 0) { - SetSocketError(); - freeaddrinfo(res); - return false; - } - family_ = res->ai_family; - switch (res->ai_family) { - case AF_INET: - memcpy(&addr_.addr4, - reinterpret_cast(res->ai_addr), - sizeof(sockaddr_in)); - break; - case AF_INET6: - memcpy(&addr_.addr6, - reinterpret_cast(res->ai_addr), - sizeof(sockaddr_in6)); - break; - } - freeaddrinfo(res); - return true; -} - -int Socket::GetPort() { - if (!FamilyIsTCP(family_)) { - LOG(ERROR) << "Can't call GetPort() on an unix domain socket."; - return 0; - } - return port_; -} - -bool Socket::IsFdInSet(const fd_set& fds) const { - if (IsClosed()) - return false; - return FD_ISSET(socket_, &fds); -} - -bool Socket::AddFdToSet(fd_set* fds) const { - if (IsClosed()) - return false; - FD_SET(socket_, fds); - return true; -} - -int Socket::ReadNumBytes(void* buffer, size_t num_bytes) { - int bytes_read = 0; - int ret = 1; - while (bytes_read < num_bytes && ret > 0) { - ret = Read(static_cast(buffer) + bytes_read, num_bytes - bytes_read); - if (ret >= 0) - bytes_read += ret; - } - return bytes_read; -} - -void Socket::SetSocketError() { - socket_error_ = true; - // We never use non-blocking socket. - DCHECK(errno != EAGAIN && errno != EWOULDBLOCK); - Close(); -} - -int Socket::Read(void* buffer, size_t buffer_size) { - if (!WaitForEvent(READ, kNoTimeout)) { - SetSocketError(); - return 0; - } - int ret = HANDLE_EINTR(read(socket_, buffer, buffer_size)); - if (ret < 0) - SetSocketError(); - return ret; -} - -int Socket::Write(const void* buffer, size_t count) { - int ret = HANDLE_EINTR(send(socket_, buffer, count, MSG_NOSIGNAL)); - if (ret < 0) - SetSocketError(); - return ret; -} - -int Socket::WriteString(const std::string& buffer) { - return WriteNumBytes(buffer.c_str(), buffer.size()); -} - -void Socket::AddEventFd(int event_fd) { - Event event; - event.fd = event_fd; - event.was_fired = false; - events_.push_back(event); -} - -bool Socket::DidReceiveEventOnFd(int fd) const { - for (size_t i = 0; i < events_.size(); ++i) - if (events_[i].fd == fd) - return events_[i].was_fired; - return false; -} - -bool Socket::DidReceiveEvent() const { - for (size_t i = 0; i < events_.size(); ++i) - if (events_[i].was_fired) - return true; - return false; -} - -int Socket::WriteNumBytes(const void* buffer, size_t num_bytes) { - int bytes_written = 0; - int ret = 1; - while (bytes_written < num_bytes && ret > 0) { - ret = Write(static_cast(buffer) + bytes_written, - num_bytes - bytes_written); - if (ret >= 0) - bytes_written += ret; - } - return bytes_written; -} - -bool Socket::WaitForEvent(EventType type, int timeout_secs) { - if (events_.empty() || socket_ == -1) - return true; - fd_set read_fds; - fd_set write_fds; - FD_ZERO(&read_fds); - FD_ZERO(&write_fds); - if (type == READ) - FD_SET(socket_, &read_fds); - else - FD_SET(socket_, &write_fds); - for (size_t i = 0; i < events_.size(); ++i) - FD_SET(events_[i].fd, &read_fds); - timeval tv = {}; - timeval* tv_ptr = NULL; - if (timeout_secs > 0) { - tv.tv_sec = timeout_secs; - tv.tv_usec = 0; - tv_ptr = &tv; - } - int max_fd = socket_; - for (size_t i = 0; i < events_.size(); ++i) - if (events_[i].fd > max_fd) - max_fd = events_[i].fd; - if (HANDLE_EINTR( - select(max_fd + 1, &read_fds, &write_fds, NULL, tv_ptr)) <= 0) { - return false; - } - bool event_was_fired = false; - for (size_t i = 0; i < events_.size(); ++i) { - if (FD_ISSET(events_[i].fd, &read_fds)) { - events_[i].was_fired = true; - event_was_fired = true; - } - } - return !event_was_fired; -} - -// static -int Socket::GetHighestFileDescriptor(const Socket& s1, const Socket& s2) { - return std::max(s1.socket_, s2.socket_); -} - -// static -pid_t Socket::GetUnixDomainSocketProcessOwner(const std::string& path) { - Socket socket; - if (!socket.ConnectUnix(path)) - return -1; - ucred ucred; - socklen_t len = sizeof(ucred); - if (getsockopt(socket.socket_, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1) { - CHECK_NE(ENOPROTOOPT, errno); - return -1; - } - return ucred.pid; -} - -} // namespace forwarder2 diff --git a/tools/android/forwarder2/socket.h b/tools/android/forwarder2/socket.h deleted file mode 100644 index b86fd9e7aa..0000000000 --- a/tools/android/forwarder2/socket.h +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef TOOLS_ANDROID_FORWARDER2_SOCKET_H_ -#define TOOLS_ANDROID_FORWARDER2_SOCKET_H_ - -#include -#include -#include -#include - -#include -#include - -#include "base/basictypes.h" - -namespace forwarder2 { - -// Wrapper class around unix socket api. Can be used to create, bind or -// connect to both Unix domain sockets and TCP sockets. -// TODO(pliard): Split this class into TCPSocket and UnixDomainSocket. -class Socket { - public: - Socket(); - ~Socket(); - - bool BindUnix(const std::string& path); - bool BindTcp(const std::string& host, int port); - bool ConnectUnix(const std::string& path); - bool ConnectTcp(const std::string& host, int port); - - // Just a wrapper around unix socket shutdown(), see man 2 shutdown. - void Shutdown(); - - // Just a wrapper around unix socket close(), see man 2 close. - void Close(); - bool IsClosed() const { return socket_ < 0; } - - bool Accept(Socket* new_socket); - - // Returns the port allocated to this socket or zero on error. - int GetPort(); - - bool IsFdInSet(const fd_set& fds) const; - bool AddFdToSet(fd_set* fds) const; - - // Just a wrapper around unix read() function. - // Reads up to buffer_size, but may read less then buffer_size. - // Returns the number of bytes read. - int Read(void* buffer, size_t buffer_size); - - // Same as Read(), just a wrapper around write(). - int Write(const void* buffer, size_t count); - - // Calls Read() multiple times until num_bytes is written to the provided - // buffer. No bounds checking is performed. - // Returns number of bytes read, which can be different from num_bytes in case - // of errror. - int ReadNumBytes(void* buffer, size_t num_bytes); - - // Calls Write() multiple times until num_bytes is written. No bounds checking - // is performed. Returns number of bytes written, which can be different from - // num_bytes in case of errror. - int WriteNumBytes(const void* buffer, size_t num_bytes); - - // Calls WriteNumBytes for the given std::string. Note that the null - // terminator is not written to the socket. - int WriteString(const std::string& buffer); - - bool has_error() const { return socket_error_; } - - // |event_fd| must be a valid pipe file descriptor created from the - // PipeNotifier and must live (not be closed) at least as long as this socket - // is alive. - void AddEventFd(int event_fd); - - // Returns whether Accept() or Connect() was interrupted because the socket - // received an external event fired through the provided fd. - bool DidReceiveEventOnFd(int fd) const; - - bool DidReceiveEvent() const; - - static int GetHighestFileDescriptor(const Socket& s1, const Socket& s2); - - static pid_t GetUnixDomainSocketProcessOwner(const std::string& path); - - private: - enum EventType { - READ, - WRITE - }; - - union SockAddr { - // IPv4 sockaddr - sockaddr_in addr4; - // IPv6 sockaddr - sockaddr_in6 addr6; - // Unix Domain sockaddr - sockaddr_un addr_un; - }; - - struct Event { - int fd; - bool was_fired; - }; - - // If |host| is empty, use localhost. - bool InitTcpSocket(const std::string& host, int port); - bool InitUnixSocket(const std::string& path); - bool BindAndListen(); - bool Connect(); - - bool Resolve(const std::string& host); - bool InitSocketInternal(); - void SetSocketError(); - - // Waits until either the Socket or the |exit_notifier_fd_| has received an - // event. - bool WaitForEvent(EventType type, int timeout_secs); - - int socket_; - int port_; - bool socket_error_; - - // Family of the socket (PF_INET, PF_INET6 or PF_UNIX). - int family_; - - SockAddr addr_; - - // Points to one of the members of the above union depending on the family. - sockaddr* addr_ptr_; - // Length of one of the members of the above union depending on the family. - socklen_t addr_len_; - - // Used to listen for external events (e.g. process received a SIGTERM) while - // blocking on I/O operations. - std::vector events_; - - DISALLOW_COPY_AND_ASSIGN(Socket); -}; - -} // namespace forwarder - -#endif // TOOLS_ANDROID_FORWARDER2_SOCKET_H_ diff --git a/tools/android/md5sum/md5sum.cc b/tools/android/md5sum/md5sum.cc deleted file mode 100644 index bc4ca071b8..0000000000 --- a/tools/android/md5sum/md5sum.cc +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Md5sum implementation for Android. This version handles files as well as -// directories. Its output is sorted by file path. - -#include -#include -#include -#include - -#include "base/file_util.h" -#include "base/files/file_enumerator.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/md5.h" - -namespace { - -const int kBufferSize = 1024; - -// Returns whether |path|'s MD5 was successfully written to |digest_string|. -bool MD5Sum(const char* path, std::string* digest_string) { - std::ifstream stream(path); - if (!stream.good()) { - LOG(ERROR) << "Could not open file " << path; - return false; - } - base::MD5Context ctx; - base::MD5Init(&ctx); - char buf[kBufferSize]; - while (stream.good()) { - std::streamsize bytes_read = stream.readsome(buf, sizeof(buf)); - if (bytes_read == 0) - break; - base::MD5Update(&ctx, base::StringPiece(buf, bytes_read)); - } - if (stream.fail()) { - LOG(ERROR) << "Error reading file " << path; - return false; - } - base::MD5Digest digest; - base::MD5Final(&digest, &ctx); - *digest_string = base::MD5DigestToBase16(digest); - return true; -} - -// Returns the set of all files contained in |files|. This handles directories -// by walking them recursively. Excludes, .svn directories and file under them. -std::set MakeFileSet(const char** files) { - const std::string svn_dir_component = FILE_PATH_LITERAL("/.svn/"); - std::set file_set; - for (const char** file = files; *file; ++file) { - base::FilePath file_path(*file); - if (base::DirectoryExists(file_path)) { - base::FileEnumerator file_enumerator( - file_path, true /* recurse */, base::FileEnumerator::FILES); - for (base::FilePath child, empty; - (child = file_enumerator.Next()) != empty; ) { - // If the path contains /.svn/, ignore it. - if (child.value().find(svn_dir_component) == std::string::npos) { - child = base::MakeAbsoluteFilePath(child); - file_set.insert(child.value()); - } - } - } else { - file_set.insert(*file); - } - } - return file_set; -} - -} // namespace - -int main(int argc, const char* argv[]) { - if (argc < 2) { - LOG(ERROR) << "Usage: md5sum ..."; - return 1; - } - const std::set files = MakeFileSet(argv + 1); - bool failed = false; - std::string digest; - for (std::set::const_iterator it = files.begin(); - it != files.end(); ++it) { - if (!MD5Sum(it->c_str(), &digest)) - failed = true; - base::FilePath file_path(*it); - std::cout << digest << " " - << base::MakeAbsoluteFilePath(file_path).value() << std::endl; - } - return failed; -} diff --git a/tools/android/md5sum/md5sum.gyp b/tools/android/md5sum/md5sum.gyp deleted file mode 100644 index 2c4ccc84dd..0000000000 --- a/tools/android/md5sum/md5sum.gyp +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -{ - 'targets': [ - { - 'target_name': 'md5sum', - 'type': 'none', - 'dependencies': [ - 'md5sum_stripped_device_bin', - 'md5sum_bin_host#host', - ], - # For the component build, ensure dependent shared libraries are stripped - # and put alongside md5sum to simplify pushing to the device. - 'variables': { - 'output_dir': '<(PRODUCT_DIR)/md5sum_dist/', - 'native_binary': '<(PRODUCT_DIR)/md5sum_bin', - }, - 'includes': ['../../../build/android/native_app_dependencies.gypi'], - }, - { - 'target_name': 'md5sum_device_bin', - 'type': 'executable', - 'dependencies': [ - '../../../base/base.gyp:base', - ], - 'include_dirs': [ - '../../..', - ], - 'sources': [ - 'md5sum.cc', - ], - 'conditions': [ - [ 'order_profiling!=0 and OS=="android"', { - 'dependencies': [ '../../../tools/cygprofile/cygprofile.gyp:cygprofile', ], - }], - ], - }, - { - 'target_name': 'md5sum_stripped_device_bin', - 'type': 'none', - 'dependencies': [ - 'md5sum_device_bin', - ], - 'actions': [ - { - 'action_name': 'strip_md5sum_device_bin', - 'inputs': ['<(PRODUCT_DIR)/md5sum_device_bin'], - 'outputs': ['<(PRODUCT_DIR)/md5sum_bin'], - 'action': [ - '<(android_strip)', - '--strip-unneeded', - '<@(_inputs)', - '-o', - '<@(_outputs)', - ], - }, - ], - }, - # Same binary but for the host rather than the device. - { - 'target_name': 'md5sum_bin_host', - 'toolsets': ['host'], - 'type': 'executable', - 'dependencies': [ - '../../../base/base.gyp:base', - ], - 'include_dirs': [ - '../../..', - ], - 'sources': [ - 'md5sum.cc', - ], - }, - ], -} diff --git a/tools/android/memdump/memdump.cc b/tools/android/memdump/memdump.cc deleted file mode 100644 index 26035b29b0..0000000000 --- a/tools/android/memdump/memdump.cc +++ /dev/null @@ -1,555 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "base/base64.h" -#include "base/basictypes.h" -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/containers/hash_tables.h" -#include "base/file_util.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" -#include "base/strings/string_split.h" -#include "base/strings/stringprintf.h" - -namespace { - -class BitSet { - public: - void resize(size_t nbits) { - data_.resize((nbits + 7) / 8); - } - - void set(uint32 bit) { - const uint32 byte_idx = bit / 8; - CHECK(byte_idx < data_.size()); - data_[byte_idx] |= (1 << (bit & 7)); - } - - std::string AsB64String() const { - std::string bits(&data_[0], data_.size()); - std::string b64_string; - base::Base64Encode(bits, &b64_string); - return b64_string; - } - - private: - std::vector data_; -}; - -// An entry in /proc//pagemap. -struct PageMapEntry { - uint64 page_frame_number : 55; - uint unused : 8; - uint present : 1; -}; - -// Describes a memory page. -struct PageInfo { - int64 page_frame_number; // Physical page id, also known as PFN. - int64 flags; - int32 times_mapped; -}; - -struct MemoryMap { - std::string name; - std::string flags; - uint start_address; - uint end_address; - uint offset; - int private_count; - int unevictable_private_count; - int other_shared_count; - int unevictable_other_shared_count; - // app_shared_counts[i] contains the number of pages mapped in i+2 processes - // (only among the processes that are being analyzed). - std::vector app_shared_counts; - std::vector committed_pages; - // committed_pages_bits is a bitset reflecting the present bit for all the - // virtual pages of the mapping. - BitSet committed_pages_bits; -}; - -struct ProcessMemory { - pid_t pid; - std::vector memory_maps; -}; - -bool PageIsUnevictable(const PageInfo& page_info) { - // These constants are taken from kernel-page-flags.h. - const int KPF_DIRTY = 4; // Note that only file-mapped pages can be DIRTY. - const int KPF_ANON = 12; // Anonymous pages are dirty per definition. - const int KPF_UNEVICTABLE = 18; - const int KPF_MLOCKED = 33; - - return (page_info.flags & ((1ll << KPF_DIRTY) | - (1ll << KPF_ANON) | - (1ll << KPF_UNEVICTABLE) | - (1ll << KPF_MLOCKED))) ? - true : false; -} - -// Number of times a physical page is mapped in a process. -typedef base::hash_map PFNMap; - -// Parses lines from /proc//maps, e.g.: -// 401e7000-401f5000 r-xp 00000000 103:02 158 /system/bin/linker -bool ParseMemoryMapLine(const std::string& line, - std::vector* tokens, - MemoryMap* memory_map) { - tokens->clear(); - base::SplitString(line, ' ', tokens); - if (tokens->size() < 2) - return false; - const int addr_len = 8; - const std::string& addr_range = tokens->at(0); - if (addr_range.length() != addr_len + 1 + addr_len) - return false; - uint64 tmp = 0; - if (!base::HexStringToUInt64( - base::StringPiece( - addr_range.begin(), addr_range.begin() + addr_len), - &tmp)) { - return false; - } - memory_map->start_address = static_cast(tmp); - const int end_addr_start_pos = addr_len + 1; - if (!base::HexStringToUInt64( - base::StringPiece( - addr_range.begin() + end_addr_start_pos, - addr_range.begin() + end_addr_start_pos + addr_len), - &tmp)) { - return false; - } - memory_map->end_address = static_cast(tmp); - if (tokens->at(1).size() != strlen("rwxp")) - return false; - memory_map->flags.swap(tokens->at(1)); - if (!base::HexStringToUInt64(tokens->at(2), &tmp)) - return false; - memory_map->offset = static_cast(tmp); - memory_map->committed_pages_bits.resize( - (memory_map->end_address - memory_map->start_address) / PAGE_SIZE); - const int map_name_index = 5; - if (tokens->size() >= map_name_index + 1) { - for (std::vector::const_iterator it = - tokens->begin() + map_name_index; it != tokens->end(); ++it) { - if (!it->empty()) { - if (!memory_map->name.empty()) - memory_map->name.append(" "); - memory_map->name.append(*it); - } - } - } - return true; -} - -// Reads sizeof(T) bytes from file |fd| at |offset|. -template -bool ReadFromFileAtOffset(int fd, off_t offset, T* value) { - if (lseek64(fd, offset * sizeof(*value), SEEK_SET) < 0) { - PLOG(ERROR) << "lseek"; - return false; - } - ssize_t bytes = read(fd, value, sizeof(*value)); - if (bytes != sizeof(*value) && bytes != 0) { - PLOG(ERROR) << "read"; - return false; - } - return true; -} - -// Fills |process_maps| in with the process memory maps identified by |pid|. -bool GetProcessMaps(pid_t pid, std::vector* process_maps) { - std::ifstream maps_file(base::StringPrintf("/proc/%d/maps", pid).c_str()); - if (!maps_file.good()) { - PLOG(ERROR) << "open"; - return false; - } - std::string line; - std::vector tokens; - while (std::getline(maps_file, line) && !line.empty()) { - MemoryMap memory_map = {}; - if (!ParseMemoryMapLine(line, &tokens, &memory_map)) { - LOG(ERROR) << "Could not parse line: " << line; - return false; - } - process_maps->push_back(memory_map); - } - return true; -} - -// Fills |committed_pages| in with the set of committed pages contained in the -// provided memory map. -bool GetPagesForMemoryMap(int pagemap_fd, - const MemoryMap& memory_map, - std::vector* committed_pages, - BitSet* committed_pages_bits) { - for (uint addr = memory_map.start_address, page_index = 0; - addr < memory_map.end_address; - addr += PAGE_SIZE, ++page_index) { - DCHECK_EQ(0, addr % PAGE_SIZE); - PageMapEntry page_map_entry = {}; - COMPILE_ASSERT(sizeof(PageMapEntry) == sizeof(uint64), unexpected_size); - const off64_t offset = addr / PAGE_SIZE; - if (!ReadFromFileAtOffset(pagemap_fd, offset, &page_map_entry)) - return false; - if (page_map_entry.present) { // Ignore non-committed pages. - if (page_map_entry.page_frame_number == 0) - continue; - PageInfo page_info = {}; - page_info.page_frame_number = page_map_entry.page_frame_number; - committed_pages->push_back(page_info); - committed_pages_bits->set(page_index); - } - } - return true; -} - -// Fills |committed_pages| with mapping count and flags information gathered -// looking-up /proc/kpagecount and /proc/kpageflags. -bool SetPagesInfo(int pagecount_fd, - int pageflags_fd, - std::vector* pages) { - for (std::vector::iterator it = pages->begin(); - it != pages->end(); ++it) { - PageInfo* const page_info = &*it; - - int64 times_mapped; - if (!ReadFromFileAtOffset( - pagecount_fd, page_info->page_frame_number, ×_mapped)) { - return false; - } - DCHECK(times_mapped <= std::numeric_limits::max()); - page_info->times_mapped = static_cast(times_mapped); - - int64 page_flags; - if (!ReadFromFileAtOffset( - pageflags_fd, page_info->page_frame_number, &page_flags)) { - return false; - } - page_info->flags = page_flags; - } - return true; -} - -// Fills in the provided vector of Page Frame Number maps. This lets -// ClassifyPages() know how many times each page is mapped in the processes. -void FillPFNMaps(const std::vector& processes_memory, - std::vector* pfn_maps) { - int current_process_index = 0; - for (std::vector::const_iterator it = processes_memory.begin(); - it != processes_memory.end(); ++it, ++current_process_index) { - const std::vector& memory_maps = it->memory_maps; - for (std::vector::const_iterator it = memory_maps.begin(); - it != memory_maps.end(); ++it) { - const std::vector& pages = it->committed_pages; - for (std::vector::const_iterator it = pages.begin(); - it != pages.end(); ++it) { - const PageInfo& page_info = *it; - PFNMap* const pfn_map = &(*pfn_maps)[current_process_index]; - const std::pair result = pfn_map->insert( - std::make_pair(page_info.page_frame_number, 0)); - ++result.first->second; - } - } - } -} - -// Sets the private_count/app_shared_counts/other_shared_count fields of the -// provided memory maps for each process. -void ClassifyPages(std::vector* processes_memory) { - std::vector pfn_maps(processes_memory->size()); - FillPFNMaps(*processes_memory, &pfn_maps); - // Hash set keeping track of the physical pages mapped in a single process so - // that they can be counted only once. - std::hash_set physical_pages_mapped_in_process; - - for (std::vector::iterator it = processes_memory->begin(); - it != processes_memory->end(); ++it) { - std::vector* const memory_maps = &it->memory_maps; - physical_pages_mapped_in_process.clear(); - for (std::vector::iterator it = memory_maps->begin(); - it != memory_maps->end(); ++it) { - MemoryMap* const memory_map = &*it; - const size_t processes_count = processes_memory->size(); - memory_map->app_shared_counts.resize(processes_count - 1, 0); - const std::vector& pages = memory_map->committed_pages; - for (std::vector::const_iterator it = pages.begin(); - it != pages.end(); ++it) { - const PageInfo& page_info = *it; - if (page_info.times_mapped == 1) { - ++memory_map->private_count; - if (PageIsUnevictable(page_info)) - ++memory_map->unevictable_private_count; - continue; - } - const uint64 page_frame_number = page_info.page_frame_number; - const std::pair::iterator, bool> result = - physical_pages_mapped_in_process.insert(page_frame_number); - const bool did_insert = result.second; - if (!did_insert) { - // This physical page (mapped multiple times in the same process) was - // already counted. - continue; - } - // See if the current physical page is also mapped in the other - // processes that are being analyzed. - int times_mapped = 0; - int mapped_in_processes_count = 0; - for (std::vector::const_iterator it = pfn_maps.begin(); - it != pfn_maps.end(); ++it) { - const PFNMap& pfn_map = *it; - const PFNMap::const_iterator found_it = pfn_map.find( - page_frame_number); - if (found_it == pfn_map.end()) - continue; - ++mapped_in_processes_count; - times_mapped += found_it->second; - } - if (times_mapped == page_info.times_mapped) { - // The physical page is only mapped in the processes that are being - // analyzed. - if (mapped_in_processes_count > 1) { - // The physical page is mapped in multiple processes. - ++memory_map->app_shared_counts[mapped_in_processes_count - 2]; - } else { - // The physical page is mapped multiple times in the same process. - ++memory_map->private_count; - if (PageIsUnevictable(page_info)) - ++memory_map->unevictable_private_count; - } - } else { - ++memory_map->other_shared_count; - if (PageIsUnevictable(page_info)) - ++memory_map->unevictable_other_shared_count; - - } - } - } - } -} - -void AppendAppSharedField(const std::vector& app_shared_counts, - std::string* out) { - out->append("["); - for (std::vector::const_iterator it = app_shared_counts.begin(); - it != app_shared_counts.end(); ++it) { - out->append(base::IntToString(*it * PAGE_SIZE)); - if (it + 1 != app_shared_counts.end()) - out->append(","); - } - out->append("]"); -} - -void DumpProcessesMemoryMaps( - const std::vector& processes_memory) { - std::string buf; - std::string app_shared_buf; - for (std::vector::const_iterator it = processes_memory.begin(); - it != processes_memory.end(); ++it) { - const ProcessMemory& process_memory = *it; - std::cout << "[ PID=" << process_memory.pid << "]" << '\n'; - const std::vector& memory_maps = process_memory.memory_maps; - for (std::vector::const_iterator it = memory_maps.begin(); - it != memory_maps.end(); ++it) { - const MemoryMap& memory_map = *it; - app_shared_buf.clear(); - AppendAppSharedField(memory_map.app_shared_counts, &app_shared_buf); - base::SStringPrintf( - &buf, - "%x-%x %s private_unevictable=%d private=%d shared_app=%s " - "shared_other_unevictable=%d shared_other=%d %s\n", - memory_map.start_address, - memory_map.end_address, memory_map.flags.c_str(), - memory_map.unevictable_private_count * PAGE_SIZE, - memory_map.private_count * PAGE_SIZE, - app_shared_buf.c_str(), - memory_map.unevictable_other_shared_count * PAGE_SIZE, - memory_map.other_shared_count * PAGE_SIZE, - memory_map.name.c_str()); - std::cout << buf; - } - } -} - -void DumpProcessesMemoryMapsInShortFormat( - const std::vector& processes_memory) { - const int KB_PER_PAGE = PAGE_SIZE >> 10; - std::vector totals_app_shared(processes_memory.size()); - std::string buf; - std::cout << "pid\tprivate\t\tshared_app\tshared_other (KB)\n"; - for (std::vector::const_iterator it = processes_memory.begin(); - it != processes_memory.end(); ++it) { - const ProcessMemory& process_memory = *it; - std::fill(totals_app_shared.begin(), totals_app_shared.end(), 0); - int total_private = 0, total_other_shared = 0; - const std::vector& memory_maps = process_memory.memory_maps; - for (std::vector::const_iterator it = memory_maps.begin(); - it != memory_maps.end(); ++it) { - const MemoryMap& memory_map = *it; - total_private += memory_map.private_count; - for (size_t i = 0; i < memory_map.app_shared_counts.size(); ++i) - totals_app_shared[i] += memory_map.app_shared_counts[i]; - total_other_shared += memory_map.other_shared_count; - } - double total_app_shared = 0; - for (size_t i = 0; i < totals_app_shared.size(); ++i) - total_app_shared += static_cast(totals_app_shared[i]) / (i + 2); - base::SStringPrintf( - &buf, "%d\t%d\t\t%d\t\t%d\n", - process_memory.pid, - total_private * KB_PER_PAGE, - static_cast(total_app_shared) * KB_PER_PAGE, - total_other_shared * KB_PER_PAGE); - std::cout << buf; - } -} - -void DumpProcessesMemoryMapsInExtendedFormat( - const std::vector& processes_memory) { - std::string buf; - std::string app_shared_buf; - for (std::vector::const_iterator it = processes_memory.begin(); - it != processes_memory.end(); ++it) { - const ProcessMemory& process_memory = *it; - std::cout << "[ PID=" << process_memory.pid << "]" << '\n'; - const std::vector& memory_maps = process_memory.memory_maps; - for (std::vector::const_iterator it = memory_maps.begin(); - it != memory_maps.end(); ++it) { - const MemoryMap& memory_map = *it; - app_shared_buf.clear(); - AppendAppSharedField(memory_map.app_shared_counts, &app_shared_buf); - base::SStringPrintf( - &buf, - "%x-%x %s %x private_unevictable=%d private=%d shared_app=%s " - "shared_other_unevictable=%d shared_other=%d \"%s\" [%s]\n", - memory_map.start_address, - memory_map.end_address, - memory_map.flags.c_str(), - memory_map.offset, - memory_map.unevictable_private_count * PAGE_SIZE, - memory_map.private_count * PAGE_SIZE, - app_shared_buf.c_str(), - memory_map.unevictable_other_shared_count * PAGE_SIZE, - memory_map.other_shared_count * PAGE_SIZE, - memory_map.name.c_str(), - memory_map.committed_pages_bits.AsB64String().c_str()); - std::cout << buf; - } - } -} - -bool CollectProcessMemoryInformation(int page_count_fd, - int page_flags_fd, - ProcessMemory* process_memory) { - const pid_t pid = process_memory->pid; - int pagemap_fd = open( - base::StringPrintf("/proc/%d/pagemap", pid).c_str(), O_RDONLY); - if (pagemap_fd < 0) { - PLOG(ERROR) << "open"; - return false; - } - file_util::ScopedFD auto_closer(&pagemap_fd); - std::vector* const process_maps = &process_memory->memory_maps; - if (!GetProcessMaps(pid, process_maps)) - return false; - for (std::vector::iterator it = process_maps->begin(); - it != process_maps->end(); ++it) { - std::vector* const committed_pages = &it->committed_pages; - BitSet* const pages_bits = &it->committed_pages_bits; - GetPagesForMemoryMap(pagemap_fd, *it, committed_pages, pages_bits); - SetPagesInfo(page_count_fd, page_flags_fd, committed_pages); - } - return true; -} - -void KillAll(const std::vector& pids, int signal_number) { - for (std::vector::const_iterator it = pids.begin(); it != pids.end(); - ++it) { - kill(*it, signal_number); - } -} - -} // namespace - -int main(int argc, char** argv) { - if (argc == 1) { - LOG(ERROR) << "Usage: " << argv[0] << " [-a|-x] ... "; - return EXIT_FAILURE; - } - const bool short_output = !strncmp(argv[1], "-a", 2); - const bool extended_output = !strncmp(argv[1], "-x", 2); - if (short_output || extended_output) { - if (argc == 2) { - LOG(ERROR) << "Usage: " << argv[0] << " [-a|-x] ... "; - return EXIT_FAILURE; - } - ++argv; - } - std::vector pids; - for (const char* const* ptr = argv + 1; *ptr; ++ptr) { - pid_t pid; - if (!base::StringToInt(*ptr, &pid)) - return EXIT_FAILURE; - pids.push_back(pid); - } - - std::vector processes_memory(pids.size()); - { - int page_count_fd = open("/proc/kpagecount", O_RDONLY); - if (page_count_fd < 0) { - PLOG(ERROR) << "open /proc/kpagecount"; - return EXIT_FAILURE; - } - - int page_flags_fd = open("/proc/kpageflags", O_RDONLY); - if (page_flags_fd < 0) { - PLOG(ERROR) << "open /proc/kpageflags"; - return EXIT_FAILURE; - } - - file_util::ScopedFD page_count_fd_closer(&page_count_fd); - file_util::ScopedFD page_flags_fd_closer(&page_flags_fd); - - base::ScopedClosureRunner auto_resume_processes( - base::Bind(&KillAll, pids, SIGCONT)); - KillAll(pids, SIGSTOP); - for (std::vector::const_iterator it = pids.begin(); it != pids.end(); - ++it) { - ProcessMemory* const process_memory = - &processes_memory[it - pids.begin()]; - process_memory->pid = *it; - if (!CollectProcessMemoryInformation(page_count_fd, - page_flags_fd, - process_memory)) - return EXIT_FAILURE; - } - } - - ClassifyPages(&processes_memory); - if (short_output) - DumpProcessesMemoryMapsInShortFormat(processes_memory); - else if (extended_output) - DumpProcessesMemoryMapsInExtendedFormat(processes_memory); - else - DumpProcessesMemoryMaps(processes_memory); - return EXIT_SUCCESS; -} diff --git a/tools/android/memdump/memdump.gyp b/tools/android/memdump/memdump.gyp deleted file mode 100644 index faa24d0737..0000000000 --- a/tools/android/memdump/memdump.gyp +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -{ - 'targets': [ - { - 'target_name': 'memdump', - 'type': 'executable', - 'dependencies': [ - '../../../base/base.gyp:base', - ], - 'conditions': [ - # Warning: A PIE tool cannot run on ICS 4.0.4, so only - # build it as position-independent when ASAN - # is activated. See b/6587214 for details. - [ 'asan==1', { - 'cflags': [ - '-fPIE', - ], - 'ldflags': [ - '-pie', - ], - }], - ], - 'sources': [ - 'memdump.cc', - ], - }, - ], -} diff --git a/tools/android/memdump/memreport.py b/tools/android/memdump/memreport.py deleted file mode 100755 index 1db1cb6b5e..0000000000 --- a/tools/android/memdump/memreport.py +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (c) 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import re -import sys - -from sets import Set - - -_ENTRIES = [ - ('Total', '.* r... .*'), - ('Read-only', '.* r--. .*'), - ('Read-write', '.* rw.. .*'), - ('Executable', '.* ..x. .*'), - ('Anonymous total', '.* .... .* .*other=[0-9]+ ($|.*chromium:.*)'), - ('Anonymous read-write', '.* rw.. .* .*other=[0-9]+ ($|.*chromium:.*)'), - ('Anonymous executable (JIT\'ed code)', '.* ..x. .* shared_other=[0-9]+ $'), - ('File total', '.* .... .* /.*'), - ('File read-write', '.* rw.. .* /.*'), - ('File executable', '.* ..x. .* /.*'), - ('chromium mmap', '.* r... .*chromium:.*'), - ('chromium TransferBuffer', '.* r... .*chromium:.*CreateTransferBuffer.*'), - ('Galaxy Nexus GL driver', '.* r... .*pvrsrvkm.*'), - ('Dalvik', '.* rw.. .* /.*dalvik.*'), - ('Dalvik heap', '.* rw.. .* /.*dalvik-heap.*'), - ('Native heap (jemalloc)', '.* r... .* /.*jemalloc.*'), - ('System heap', '.* r... .* \\[heap\\]'), - ('Ashmem', '.* rw.. .* /dev/ashmem .*'), - ('libchromeview.so total', '.* r... .* /.*libchromeview.so'), - ('libchromeview.so read-only', '.* r--. .* /.*libchromeview.so'), - ('libchromeview.so read-write', '.* rw-. .* /.*libchromeview.so'), - ('libchromeview.so executable', '.* r.x. .* /.*libchromeview.so'), -] - - -def _CollectMemoryStats(memdump, region_filters): - processes = [] - mem_usage_for_regions = None - regexps = {} - for region_filter in region_filters: - regexps[region_filter] = re.compile(region_filter) - for line in memdump: - if 'PID=' in line: - mem_usage_for_regions = {} - processes.append(mem_usage_for_regions) - continue - matched_regions = Set([]) - for region_filter in region_filters: - if regexps[region_filter].match(line.rstrip('\r\n')): - matched_regions.add(region_filter) - if not region_filter in mem_usage_for_regions: - mem_usage_for_regions[region_filter] = { - 'private_unevictable': 0, - 'private': 0, - 'shared_app': 0.0, - 'shared_other_unevictable': 0, - 'shared_other': 0, - } - for matched_region in matched_regions: - mem_usage = mem_usage_for_regions[matched_region] - for key in mem_usage: - for token in line.split(' '): - if (key + '=') in token: - field = token.split('=')[1] - if key != 'shared_app': - mem_usage[key] += int(field) - else: # shared_app=[\d,\d...] - array = eval(field) - for i in xrange(len(array)): - mem_usage[key] += float(array[i]) / (i + 2) - break - return processes - - -def _ConvertMemoryField(field): - return str(field / (1024.0 * 1024)) - - -def _DumpCSV(processes_stats): - total_map = {} - i = 0 - for process in processes_stats: - i += 1 - print (',Process ' + str(i) + ',private,private_unevictable,shared_app,' + - 'shared_other,shared_other_unevictable,') - for (k, v) in _ENTRIES: - if not v in process: - print ',' + k + ',0,0,0,0,' - continue - if not v in total_map: - total_map[v] = {'resident':0, 'unevictable':0} - total_map[v]['resident'] += (process[v]['private'] + - process[v]['shared_app']) - total_map[v]['unevictable'] += process[v]['private_unevictable'] - print ( - ',' + k + ',' + - _ConvertMemoryField(process[v]['private']) + ',' + - _ConvertMemoryField(process[v]['private_unevictable']) + ',' + - _ConvertMemoryField(process[v]['shared_app']) + ',' + - _ConvertMemoryField(process[v]['shared_other']) + ',' + - _ConvertMemoryField(process[v]['shared_other_unevictable']) + ',' - ) - print '' - - for (k, v) in _ENTRIES: - if not v in total_map: - print ',' + k + ',0,0,' - continue - print (',' + k + ',' + _ConvertMemoryField(total_map[v]['resident']) + ',' + - _ConvertMemoryField(total_map[v]['unevictable']) + ',') - print '' - - -def main(argv): - _DumpCSV(_CollectMemoryStats(sys.stdin, [value for (key, value) in _ENTRIES])) - - -if __name__ == '__main__': - main(sys.argv) diff --git a/tools/android/memdump/memsymbols.py b/tools/android/memdump/memsymbols.py deleted file mode 100755 index 372196303b..0000000000 --- a/tools/android/memdump/memsymbols.py +++ /dev/null @@ -1,152 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import base64 -import os -import sys -import re - -from optparse import OptionParser - -"""Extracts the list of resident symbols of a library loaded in a process. - -This scripts combines the extended output of memdump for a given process -(obtained through memdump -x PID) and the symbol table of a .so loaded in that -process (obtained through nm -C lib-with-symbols.so), filtering out only those -symbols that, at the time of the snapshot, were resident in memory (that are, -the symbols which start address belongs to a mapped page of the .so which was -resident at the time of the snapshot). -The aim is to perform a "code coverage"-like profiling of a binary, intersecting -run-time information (list of resident pages) and debug symbols. -""" - -_PAGE_SIZE = 4096 - - -def _TestBit(word, bit): - assert(bit >= 0 and bit < 8) - return not not ((word >> bit) & 1) - - -def _HexAddr(addr): - return hex(addr)[2:].zfill(8) - - -def _GetResidentPagesSet(memdump_contents, lib_name, verbose): - """Parses the memdump output and extracts the resident page set for lib_name. - Args: - memdump_contents: Array of strings (lines) of a memdump output. - lib_name: A string containing the name of the library.so to be matched. - verbose: Print a verbose header for each mapping matched. - - Returns: - A set of resident pages (the key is the page index) for all the - mappings matching .*lib_name. - """ - resident_pages = set() - MAP_RX = re.compile( - r'^([0-9a-f]+)-([0-9a-f]+) ([\w-]+) ([0-9a-f]+) .* "(.*)" \[(.*)\]$') - for line in memdump_contents: - line = line.rstrip('\r\n') - if line.startswith('[ PID'): - continue - - r = MAP_RX.match(line) - if not r: - sys.stderr.write('Skipping %s from %s\n' % (line, memdump_file)) - continue - - map_start = int(r.group(1), 16) - map_end = int(r.group(2), 16) - prot = r.group(3) - offset = int(r.group(4), 16) - assert(offset % _PAGE_SIZE == 0) - lib = r.group(5) - enc_bitmap = r.group(6) - - if not lib.endswith(lib_name): - continue - - bitmap = base64.b64decode(enc_bitmap) - map_pages_count = (map_end - map_start + 1) / _PAGE_SIZE - bitmap_pages_count = len(bitmap) * 8 - - if verbose: - print 'Found %s: mapped %d pages in mode %s @ offset %s.' % ( - lib, map_pages_count, prot, _HexAddr(offset)) - print ' Map range in the process VA: [%s - %s]. Len: %s' % ( - _HexAddr(map_start), - _HexAddr(map_end), - _HexAddr(map_pages_count * _PAGE_SIZE)) - print ' Corresponding addresses in the binary: [%s - %s]. Len: %s' % ( - _HexAddr(offset), - _HexAddr(offset + map_end - map_start), - _HexAddr(map_pages_count * _PAGE_SIZE)) - print ' Bitmap: %d pages' % bitmap_pages_count - print '' - - assert(bitmap_pages_count >= map_pages_count) - for i in xrange(map_pages_count): - bitmap_idx = i / 8 - bitmap_off = i % 8 - if (bitmap_idx < len(bitmap) and - _TestBit(ord(bitmap[bitmap_idx]), bitmap_off)): - resident_pages.add(offset / _PAGE_SIZE + i) - return resident_pages - - -def main(argv): - NM_RX = re.compile(r'^([0-9a-f]+)\s+.*$') - - parser = OptionParser() - parser.add_option("-r", "--reverse", - action="store_true", dest="reverse", default=False, - help="Print out non present symbols") - parser.add_option("-v", "--verbose", - action="store_true", dest="verbose", default=False, - help="Print out verbose debug information.") - - (options, args) = parser.parse_args() - - if len(args) != 3: - print 'Usage: %s [-v] memdump.file nm.file library.so' % ( - os.path.basename(argv[0])) - return 1 - - memdump_file = args[0] - nm_file = args[1] - lib_name = args[2] - - if memdump_file == '-': - memdump_contents = sys.stdin.readlines() - else: - memdump_contents = open(memdump_file, 'r').readlines() - resident_pages = _GetResidentPagesSet(memdump_contents, - lib_name, - options.verbose) - - # Process the nm symbol table, filtering out the resident symbols. - nm_fh = open(nm_file, 'r') - for line in nm_fh: - line = line.rstrip('\r\n') - # Skip undefined symbols (lines with no address). - if line.startswith(' '): - continue - - r = NM_RX.match(line) - if not r: - sys.stderr.write('Skipping %s from %s\n' % (line, nm_file)) - continue - - sym_addr = int(r.group(1), 16) - sym_page = sym_addr / _PAGE_SIZE - last_sym_matched = (sym_page in resident_pages) - if (sym_page in resident_pages) != options.reverse: - print line - return 0 - -if __name__ == '__main__': - sys.exit(main(sys.argv)) diff --git a/tools/android/remove_strings.py b/tools/android/remove_strings.py deleted file mode 100755 index b8c4807d88..0000000000 --- a/tools/android/remove_strings.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/python -# Copyright (c) 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Remove strings by name from a GRD file.""" - -import optparse -import re -import sys - - -def RemoveStrings(grd_path, string_names): - """Removes strings with the given names from a GRD file. Overwrites the file. - - Args: - grd_path: path to the GRD file. - string_names: a list of string names to be removed. - """ - with open(grd_path, 'r') as f: - grd = f.read() - names_pattern = '|'.join(map(re.escape, string_names)) - pattern = r']*name="(%s)".*?\s*' % names_pattern - grd = re.sub(pattern, '', grd, flags=re.DOTALL) - with open(grd_path, 'w') as f: - f.write(grd) - - -def ParseArgs(args): - usage = 'usage: %prog GRD_PATH...' - parser = optparse.OptionParser( - usage=usage, description='Remove strings from GRD files. Reads string ' - 'names from stdin, and removes strings with those names from the listed ' - 'GRD files.') - options, args = parser.parse_args(args=args) - if not args: - parser.error('must provide GRD_PATH argument(s)') - return args - - -def main(args=None): - grd_paths = ParseArgs(args) - strings_to_remove = filter(None, map(str.strip, sys.stdin.readlines())) - for grd_path in grd_paths: - RemoveStrings(grd_path, strings_to_remove) - - -if __name__ == '__main__': - main() diff --git a/tools/bash-completion b/tools/bash-completion deleted file mode 100644 index 19172dab14..0000000000 --- a/tools/bash-completion +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# Flag completion rule for bash. -# To load in your shell, "source path/to/this/file". - -chrome_source=$(cd $(dirname $BASH_SOURCE)/.. && pwd) - -_chrome_flag() { - local cur targets - cur="${COMP_WORDS[COMP_CWORD]}" - targets=$(cd $chrome_source; \ - git ls-files '*switches*' | \ - xargs sed -ne 's/^[^/]*"\([^" /]\{1,\}\)".*/--\1/p') - COMPREPLY=($(compgen -W "$targets" -- "$cur")) - return 0 -} - -complete -F _chrome_flag google-chrome -complete -F _chrome_flag chrome -if [ $(uname) = "Darwin" ] -then - complete -F _chrome_flag Chromium -fi diff --git a/tools/bisect-builds.py b/tools/bisect-builds.py deleted file mode 100755 index d9f394736b..0000000000 --- a/tools/bisect-builds.py +++ /dev/null @@ -1,718 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Snapshot Build Bisect Tool - -This script bisects a snapshot archive using binary search. It starts at -a bad revision (it will try to guess HEAD) and asks for a last known-good -revision. It will then binary search across this revision range by downloading, -unzipping, and opening Chromium for you. After testing the specific revision, -it will ask you whether it is good or bad before continuing the search. -""" - -# The root URL for storage. -BASE_URL = 'http://commondatastorage.googleapis.com/chromium-browser-snapshots' - -# The root URL for official builds. -OFFICIAL_BASE_URL = 'http://master.chrome.corp.google.com/official_builds' - -# Changelogs URL. -CHANGELOG_URL = 'http://build.chromium.org/f/chromium/' \ - 'perf/dashboard/ui/changelog.html?' \ - 'url=/trunk/src&range=%d%%3A%d' - -# Official Changelogs URL. -OFFICIAL_CHANGELOG_URL = 'http://omahaproxy.appspot.com/'\ - 'changelog?old_version=%s&new_version=%s' - -# DEPS file URL. -DEPS_FILE= 'http://src.chromium.org/viewvc/chrome/trunk/src/DEPS?revision=%d' -# Blink Changelogs URL. -BLINK_CHANGELOG_URL = 'http://build.chromium.org/f/chromium/' \ - 'perf/dashboard/ui/changelog_blink.html?' \ - 'url=/trunk&range=%d%%3A%d' - -DONE_MESSAGE_GOOD_MIN = 'You are probably looking for a change made after %s ' \ - '(known good), but no later than %s (first known bad).' -DONE_MESSAGE_GOOD_MAX = 'You are probably looking for a change made after %s ' \ - '(known bad), but no later than %s (first known good).' - -############################################################################### - -import math -import optparse -import os -import pipes -import re -import shutil -import subprocess -import sys -import tempfile -import threading -import urllib -from distutils.version import LooseVersion -from xml.etree import ElementTree -import zipfile - - -class PathContext(object): - """A PathContext is used to carry the information used to construct URLs and - paths when dealing with the storage server and archives.""" - def __init__(self, platform, good_revision, bad_revision, is_official): - super(PathContext, self).__init__() - # Store off the input parameters. - self.platform = platform # What's passed in to the '-a/--archive' option. - self.good_revision = good_revision - self.bad_revision = bad_revision - self.is_official = is_official - - # The name of the ZIP file in a revision directory on the server. - self.archive_name = None - - # Set some internal members: - # _listing_platform_dir = Directory that holds revisions. Ends with a '/'. - # _archive_extract_dir = Uncompressed directory in the archive_name file. - # _binary_name = The name of the executable to run. - if self.platform in ('linux', 'linux64', 'linux-arm'): - self._binary_name = 'chrome' - elif self.platform == 'mac': - self.archive_name = 'chrome-mac.zip' - self._archive_extract_dir = 'chrome-mac' - elif self.platform == 'win': - self.archive_name = 'chrome-win32.zip' - self._archive_extract_dir = 'chrome-win32' - self._binary_name = 'chrome.exe' - else: - raise Exception('Invalid platform: %s' % self.platform) - - if is_official: - if self.platform == 'linux': - self._listing_platform_dir = 'lucid32bit/' - self.archive_name = 'chrome-lucid32bit.zip' - self._archive_extract_dir = 'chrome-lucid32bit' - elif self.platform == 'linux64': - self._listing_platform_dir = 'lucid64bit/' - self.archive_name = 'chrome-lucid64bit.zip' - self._archive_extract_dir = 'chrome-lucid64bit' - elif self.platform == 'mac': - self._listing_platform_dir = 'mac/' - self._binary_name = 'Google Chrome.app/Contents/MacOS/Google Chrome' - elif self.platform == 'win': - self._listing_platform_dir = 'win/' - else: - if self.platform in ('linux', 'linux64', 'linux-arm'): - self.archive_name = 'chrome-linux.zip' - self._archive_extract_dir = 'chrome-linux' - if self.platform == 'linux': - self._listing_platform_dir = 'Linux/' - elif self.platform == 'linux64': - self._listing_platform_dir = 'Linux_x64/' - elif self.platform == 'linux-arm': - self._listing_platform_dir = 'Linux_ARM_Cross-Compile/' - elif self.platform == 'mac': - self._listing_platform_dir = 'Mac/' - self._binary_name = 'Chromium.app/Contents/MacOS/Chromium' - elif self.platform == 'win': - self._listing_platform_dir = 'Win/' - - def GetListingURL(self, marker=None): - """Returns the URL for a directory listing, with an optional marker.""" - marker_param = '' - if marker: - marker_param = '&marker=' + str(marker) - return BASE_URL + '/?delimiter=/&prefix=' + self._listing_platform_dir + \ - marker_param - - def GetDownloadURL(self, revision): - """Gets the download URL for a build archive of a specific revision.""" - if self.is_official: - return "%s/%s/%s%s" % ( - OFFICIAL_BASE_URL, revision, self._listing_platform_dir, - self.archive_name) - else: - return "%s/%s%s/%s" % ( - BASE_URL, self._listing_platform_dir, revision, self.archive_name) - - def GetLastChangeURL(self): - """Returns a URL to the LAST_CHANGE file.""" - return BASE_URL + '/' + self._listing_platform_dir + 'LAST_CHANGE' - - def GetLaunchPath(self): - """Returns a relative path (presumably from the archive extraction location) - that is used to run the executable.""" - return os.path.join(self._archive_extract_dir, self._binary_name) - - def ParseDirectoryIndex(self): - """Parses the Google Storage directory listing into a list of revision - numbers.""" - - def _FetchAndParse(url): - """Fetches a URL and returns a 2-Tuple of ([revisions], next-marker). If - next-marker is not None, then the listing is a partial listing and another - fetch should be performed with next-marker being the marker= GET - parameter.""" - handle = urllib.urlopen(url) - document = ElementTree.parse(handle) - - # All nodes in the tree are namespaced. Get the root's tag name to extract - # the namespace. Etree does namespaces as |{namespace}tag|. - root_tag = document.getroot().tag - end_ns_pos = root_tag.find('}') - if end_ns_pos == -1: - raise Exception("Could not locate end namespace for directory index") - namespace = root_tag[:end_ns_pos + 1] - - # Find the prefix (_listing_platform_dir) and whether or not the list is - # truncated. - prefix_len = len(document.find(namespace + 'Prefix').text) - next_marker = None - is_truncated = document.find(namespace + 'IsTruncated') - if is_truncated is not None and is_truncated.text.lower() == 'true': - next_marker = document.find(namespace + 'NextMarker').text - - # Get a list of all the revisions. - all_prefixes = document.findall(namespace + 'CommonPrefixes/' + - namespace + 'Prefix') - # The nodes have content of the form of - # |_listing_platform_dir/revision/|. Strip off the platform dir and the - # trailing slash to just have a number. - revisions = [] - for prefix in all_prefixes: - revnum = prefix.text[prefix_len:-1] - try: - revnum = int(revnum) - revisions.append(revnum) - except ValueError: - pass - return (revisions, next_marker) - - # Fetch the first list of revisions. - (revisions, next_marker) = _FetchAndParse(self.GetListingURL()) - - # If the result list was truncated, refetch with the next marker. Do this - # until an entire directory listing is done. - while next_marker: - next_url = self.GetListingURL(next_marker) - (new_revisions, next_marker) = _FetchAndParse(next_url) - revisions.extend(new_revisions) - return revisions - - def GetRevList(self): - """Gets the list of revision numbers between self.good_revision and - self.bad_revision.""" - # Download the revlist and filter for just the range between good and bad. - minrev = min(self.good_revision, self.bad_revision) - maxrev = max(self.good_revision, self.bad_revision) - revlist = map(int, self.ParseDirectoryIndex()) - revlist = [x for x in revlist if x >= int(minrev) and x <= int(maxrev)] - revlist.sort() - return revlist - - def GetOfficialBuildsList(self): - """Gets the list of official build numbers between self.good_revision and - self.bad_revision.""" - # Download the revlist and filter for just the range between good and bad. - minrev = min(self.good_revision, self.bad_revision) - maxrev = max(self.good_revision, self.bad_revision) - handle = urllib.urlopen(OFFICIAL_BASE_URL) - dirindex = handle.read() - handle.close() - build_numbers = re.findall(r'', dirindex) - final_list = [] - i = 0 - parsed_build_numbers = [LooseVersion(x) for x in build_numbers] - for build_number in sorted(parsed_build_numbers): - path = OFFICIAL_BASE_URL + '/' + str(build_number) + '/' + \ - self._listing_platform_dir + self.archive_name - i = i + 1 - try: - connection = urllib.urlopen(path) - connection.close() - if build_number > maxrev: - break - if build_number >= minrev: - final_list.append(str(build_number)) - except urllib.HTTPError, e: - pass - return final_list - -def UnzipFilenameToDir(filename, dir): - """Unzip |filename| to directory |dir|.""" - cwd = os.getcwd() - if not os.path.isabs(filename): - filename = os.path.join(cwd, filename) - zf = zipfile.ZipFile(filename) - # Make base. - if not os.path.isdir(dir): - os.mkdir(dir) - os.chdir(dir) - # Extract files. - for info in zf.infolist(): - name = info.filename - if name.endswith('/'): # dir - if not os.path.isdir(name): - os.makedirs(name) - else: # file - dir = os.path.dirname(name) - if not os.path.isdir(dir): - os.makedirs(dir) - out = open(name, 'wb') - out.write(zf.read(name)) - out.close() - # Set permissions. Permission info in external_attr is shifted 16 bits. - os.chmod(name, info.external_attr >> 16L) - os.chdir(cwd) - - -def FetchRevision(context, rev, filename, quit_event=None, progress_event=None): - """Downloads and unzips revision |rev|. - @param context A PathContext instance. - @param rev The Chromium revision number/tag to download. - @param filename The destination for the downloaded file. - @param quit_event A threading.Event which will be set by the master thread to - indicate that the download should be aborted. - @param progress_event A threading.Event which will be set by the master thread - to indicate that the progress of the download should be - displayed. - """ - def ReportHook(blocknum, blocksize, totalsize): - if quit_event and quit_event.isSet(): - raise RuntimeError("Aborting download of revision %s" % str(rev)) - if progress_event and progress_event.isSet(): - size = blocknum * blocksize - if totalsize == -1: # Total size not known. - progress = "Received %d bytes" % size - else: - size = min(totalsize, size) - progress = "Received %d of %d bytes, %.2f%%" % ( - size, totalsize, 100.0 * size / totalsize) - # Send a \r to let all progress messages use just one line of output. - sys.stdout.write("\r" + progress) - sys.stdout.flush() - - download_url = context.GetDownloadURL(rev) - try: - urllib.urlretrieve(download_url, filename, ReportHook) - if progress_event and progress_event.isSet(): - print - except RuntimeError, e: - pass - - -def RunRevision(context, revision, zipfile, profile, num_runs, command, args): - """Given a zipped revision, unzip it and run the test.""" - print "Trying revision %s..." % str(revision) - - # Create a temp directory and unzip the revision into it. - cwd = os.getcwd() - tempdir = tempfile.mkdtemp(prefix='bisect_tmp') - UnzipFilenameToDir(zipfile, tempdir) - os.chdir(tempdir) - - # Run the build as many times as specified. - testargs = ['--user-data-dir=%s' % profile] + args - # The sandbox must be run as root on Official Chrome, so bypass it. - if context.is_official and context.platform.startswith('linux'): - testargs.append('--no-sandbox') - - runcommand = [] - for token in command.split(): - if token == "%a": - runcommand.extend(testargs) - else: - runcommand.append( \ - token.replace('%p', context.GetLaunchPath()) \ - .replace('%s', ' '.join(testargs))) - - for i in range(0, num_runs): - subproc = subprocess.Popen(runcommand, - bufsize=-1, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - (stdout, stderr) = subproc.communicate() - - os.chdir(cwd) - try: - shutil.rmtree(tempdir, True) - except Exception, e: - pass - - return (subproc.returncode, stdout, stderr) - - -def AskIsGoodBuild(rev, official_builds, status, stdout, stderr): - """Ask the user whether build |rev| is good or bad.""" - # Loop until we get a response that we can parse. - while True: - response = raw_input('Revision %s is [(g)ood/(b)ad/(u)nknown/(q)uit]: ' % - str(rev)) - if response and response in ('g', 'b', 'u'): - return response - if response and response == 'q': - raise SystemExit() - - -class DownloadJob(object): - """DownloadJob represents a task to download a given Chromium revision.""" - def __init__(self, context, name, rev, zipfile): - super(DownloadJob, self).__init__() - # Store off the input parameters. - self.context = context - self.name = name - self.rev = rev - self.zipfile = zipfile - self.quit_event = threading.Event() - self.progress_event = threading.Event() - - def Start(self): - """Starts the download.""" - fetchargs = (self.context, - self.rev, - self.zipfile, - self.quit_event, - self.progress_event) - self.thread = threading.Thread(target=FetchRevision, - name=self.name, - args=fetchargs) - self.thread.start() - - def Stop(self): - """Stops the download which must have been started previously.""" - self.quit_event.set() - self.thread.join() - os.unlink(self.zipfile) - - def WaitFor(self): - """Prints a message and waits for the download to complete. The download - must have been started previously.""" - print "Downloading revision %s..." % str(self.rev) - self.progress_event.set() # Display progress of download. - self.thread.join() - - -def Bisect(platform, - official_builds, - good_rev=0, - bad_rev=0, - num_runs=1, - command="%p %a", - try_args=(), - profile=None, - evaluate=AskIsGoodBuild): - """Given known good and known bad revisions, run a binary search on all - archived revisions to determine the last known good revision. - - @param platform Which build to download/run ('mac', 'win', 'linux64', etc.). - @param official_builds Specify build type (Chromium or Official build). - @param good_rev Number/tag of the known good revision. - @param bad_rev Number/tag of the known bad revision. - @param num_runs Number of times to run each build for asking good/bad. - @param try_args A tuple of arguments to pass to the test application. - @param profile The name of the user profile to run with. - @param evaluate A function which returns 'g' if the argument build is good, - 'b' if it's bad or 'u' if unknown. - - Threading is used to fetch Chromium revisions in the background, speeding up - the user's experience. For example, suppose the bounds of the search are - good_rev=0, bad_rev=100. The first revision to be checked is 50. Depending on - whether revision 50 is good or bad, the next revision to check will be either - 25 or 75. So, while revision 50 is being checked, the script will download - revisions 25 and 75 in the background. Once the good/bad verdict on rev 50 is - known: - - - If rev 50 is good, the download of rev 25 is cancelled, and the next test - is run on rev 75. - - - If rev 50 is bad, the download of rev 75 is cancelled, and the next test - is run on rev 25. - """ - - if not profile: - profile = 'profile' - - context = PathContext(platform, good_rev, bad_rev, official_builds) - cwd = os.getcwd() - - - - print "Downloading list of known revisions..." - _GetDownloadPath = lambda rev: os.path.join(cwd, - '%s-%s' % (str(rev), context.archive_name)) - if official_builds: - revlist = context.GetOfficialBuildsList() - else: - revlist = context.GetRevList() - - # Get a list of revisions to bisect across. - if len(revlist) < 2: # Don't have enough builds to bisect. - msg = 'We don\'t have enough builds to bisect. revlist: %s' % revlist - raise RuntimeError(msg) - - # Figure out our bookends and first pivot point; fetch the pivot revision. - minrev = 0 - maxrev = len(revlist) - 1 - pivot = maxrev / 2 - rev = revlist[pivot] - zipfile = _GetDownloadPath(rev) - fetch = DownloadJob(context, 'initial_fetch', rev, zipfile) - fetch.Start() - fetch.WaitFor() - - # Binary search time! - while fetch and fetch.zipfile and maxrev - minrev > 1: - if bad_rev < good_rev: - min_str, max_str = "bad", "good" - else: - min_str, max_str = "good", "bad" - print 'Bisecting range [%s (%s), %s (%s)].' % (revlist[minrev], min_str, \ - revlist[maxrev], max_str) - - # Pre-fetch next two possible pivots - # - down_pivot is the next revision to check if the current revision turns - # out to be bad. - # - up_pivot is the next revision to check if the current revision turns - # out to be good. - down_pivot = int((pivot - minrev) / 2) + minrev - down_fetch = None - if down_pivot != pivot and down_pivot != minrev: - down_rev = revlist[down_pivot] - down_fetch = DownloadJob(context, 'down_fetch', down_rev, - _GetDownloadPath(down_rev)) - down_fetch.Start() - - up_pivot = int((maxrev - pivot) / 2) + pivot - up_fetch = None - if up_pivot != pivot and up_pivot != maxrev: - up_rev = revlist[up_pivot] - up_fetch = DownloadJob(context, 'up_fetch', up_rev, - _GetDownloadPath(up_rev)) - up_fetch.Start() - - # Run test on the pivot revision. - status = None - stdout = None - stderr = None - try: - (status, stdout, stderr) = RunRevision(context, - rev, - fetch.zipfile, - profile, - num_runs, - command, - try_args) - except Exception, e: - print >>sys.stderr, e - fetch.Stop() - fetch = None - - # Call the evaluate function to see if the current revision is good or bad. - # On that basis, kill one of the background downloads and complete the - # other, as described in the comments above. - try: - answer = evaluate(rev, official_builds, status, stdout, stderr) - if answer == 'g' and good_rev < bad_rev or \ - answer == 'b' and bad_rev < good_rev: - minrev = pivot - if down_fetch: - down_fetch.Stop() # Kill the download of the older revision. - if up_fetch: - up_fetch.WaitFor() - pivot = up_pivot - fetch = up_fetch - elif answer == 'b' and good_rev < bad_rev or \ - answer == 'g' and bad_rev < good_rev: - maxrev = pivot - if up_fetch: - up_fetch.Stop() # Kill the download of the newer revision. - if down_fetch: - down_fetch.WaitFor() - pivot = down_pivot - fetch = down_fetch - elif answer == 'u': - # Nuke the revision from the revlist and choose a new pivot. - revlist.pop(pivot) - maxrev -= 1 # Assumes maxrev >= pivot. - - if maxrev - minrev > 1: - # Alternate between using down_pivot or up_pivot for the new pivot - # point, without affecting the range. Do this instead of setting the - # pivot to the midpoint of the new range because adjacent revisions - # are likely affected by the same issue that caused the (u)nknown - # response. - if up_fetch and down_fetch: - fetch = [up_fetch, down_fetch][len(revlist) % 2] - elif up_fetch: - fetch = up_fetch - else: - fetch = down_fetch - fetch.WaitFor() - if fetch == up_fetch: - pivot = up_pivot - 1 # Subtracts 1 because revlist was resized. - else: - pivot = down_pivot - zipfile = fetch.zipfile - - if down_fetch and fetch != down_fetch: - down_fetch.Stop() - if up_fetch and fetch != up_fetch: - up_fetch.Stop() - else: - assert False, "Unexpected return value from evaluate(): " + answer - except SystemExit: - print "Cleaning up..." - for f in [_GetDownloadPath(revlist[down_pivot]), - _GetDownloadPath(revlist[up_pivot])]: - try: - os.unlink(f) - except OSError: - pass - sys.exit(0) - - rev = revlist[pivot] - - return (revlist[minrev], revlist[maxrev]) - - -def GetBlinkRevisionForChromiumRevision(rev): - """Returns the blink revision that was in chromium's DEPS file at - chromium revision |rev|.""" - # . doesn't match newlines without re.DOTALL, so this is safe. - blink_re = re.compile(r'webkit_revision.:\D*(\d+)') - url = urllib.urlopen(DEPS_FILE % rev) - m = blink_re.search(url.read()) - url.close() - if m: - return int(m.group(1)) - else: - raise Exception('Could not get blink revision for cr rev %d' % rev) - - -def GetChromiumRevision(url): - """Returns the chromium revision read from given URL.""" - try: - # Location of the latest build revision number - return int(urllib.urlopen(url).read()) - except Exception, e: - print('Could not determine latest revision. This could be bad...') - return 999999999 - - -def main(): - usage = ('%prog [options] [-- chromium-options]\n' - 'Perform binary search on the snapshot builds to find a minimal\n' - 'range of revisions where a behavior change happened. The\n' - 'behaviors are described as "good" and "bad".\n' - 'It is NOT assumed that the behavior of the later revision is\n' - 'the bad one.\n' - '\n' - 'Revision numbers should use\n' - ' Official versions (e.g. 1.0.1000.0) for official builds. (-o)\n' - ' SVN revisions (e.g. 123456) for chromium builds, from trunk.\n' - ' Use base_trunk_revision from http://omahaproxy.appspot.com/\n' - ' for earlier revs.\n' - ' Chrome\'s about: build number and omahaproxy branch_revision\n' - ' are incorrect, they are from branches.\n' - '\n' - 'Tip: add "-- --no-first-run" to bypass the first run prompts.') - parser = optparse.OptionParser(usage=usage) - # Strangely, the default help output doesn't include the choice list. - choices = ['mac', 'win', 'linux', 'linux64', 'linux-arm'] - # linux-chromiumos lacks a continuous archive http://crbug.com/78158 - parser.add_option('-a', '--archive', - choices = choices, - help = 'The buildbot archive to bisect [%s].' % - '|'.join(choices)) - parser.add_option('-o', action="store_true", dest='official_builds', - help = 'Bisect across official ' + - 'Chrome builds (internal only) instead of ' + - 'Chromium archives.') - parser.add_option('-b', '--bad', type = 'str', - help = 'A bad revision to start bisection. ' + - 'May be earlier or later than the good revision. ' + - 'Default is HEAD.') - parser.add_option('-g', '--good', type = 'str', - help = 'A good revision to start bisection. ' + - 'May be earlier or later than the bad revision. ' + - 'Default is 0.') - parser.add_option('-p', '--profile', '--user-data-dir', type = 'str', - help = 'Profile to use; this will not reset every run. ' + - 'Defaults to a clean profile.', default = 'profile') - parser.add_option('-t', '--times', type = 'int', - help = 'Number of times to run each build before asking ' + - 'if it\'s good or bad. Temporary profiles are reused.', - default = 1) - parser.add_option('-c', '--command', type = 'str', - help = 'Command to execute. %p and %a refer to Chrome ' + - 'executable and specified extra arguments respectively. ' + - 'Use %s to specify all extra arguments as one string. ' + - 'Defaults to "%p %a". Note that any extra paths ' + - 'specified should be absolute.', - default = '%p %a'); - (opts, args) = parser.parse_args() - - if opts.archive is None: - print 'Error: missing required parameter: --archive' - print - parser.print_help() - return 1 - - # Create the context. Initialize 0 for the revisions as they are set below. - context = PathContext(opts.archive, 0, 0, opts.official_builds) - # Pick a starting point, try to get HEAD for this. - if opts.bad: - bad_rev = opts.bad - else: - bad_rev = '999.0.0.0' - if not opts.official_builds: - bad_rev = GetChromiumRevision(context.GetLastChangeURL()) - - # Find out when we were good. - if opts.good: - good_rev = opts.good - else: - good_rev = '0.0.0.0' if opts.official_builds else 0 - - if opts.official_builds: - good_rev = LooseVersion(good_rev) - bad_rev = LooseVersion(bad_rev) - else: - good_rev = int(good_rev) - bad_rev = int(bad_rev) - - if opts.times < 1: - print('Number of times to run (%d) must be greater than or equal to 1.' % - opts.times) - parser.print_help() - return 1 - - (min_chromium_rev, max_chromium_rev) = Bisect( - opts.archive, opts.official_builds, good_rev, bad_rev, opts.times, - opts.command, args, opts.profile) - - # Get corresponding blink revisions. - try: - min_blink_rev = GetBlinkRevisionForChromiumRevision(min_chromium_rev) - max_blink_rev = GetBlinkRevisionForChromiumRevision(max_chromium_rev) - except Exception, e: - # Silently ignore the failure. - min_blink_rev, max_blink_rev = 0, 0 - - # We're done. Let the user know the results in an official manner. - if good_rev > bad_rev: - print DONE_MESSAGE_GOOD_MAX % (str(min_chromium_rev), str(max_chromium_rev)) - else: - print DONE_MESSAGE_GOOD_MIN % (str(min_chromium_rev), str(max_chromium_rev)) - - if min_blink_rev != max_blink_rev: - print 'BLINK CHANGELOG URL:' - print ' ' + BLINK_CHANGELOG_URL % (max_blink_rev, min_blink_rev) - print 'CHANGELOG URL:' - if opts.official_builds: - print OFFICIAL_CHANGELOG_URL % (min_chromium_rev, max_chromium_rev) - else: - print ' ' + CHANGELOG_URL % (min_chromium_rev, max_chromium_rev) - -if __name__ == '__main__': - sys.exit(main()) diff --git a/tools/bisect-manual-test.py b/tools/bisect-manual-test.py deleted file mode 100755 index 62aa072c03..0000000000 --- a/tools/bisect-manual-test.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python -# Copyright 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Simple script which asks user to manually check result of bisection. - -Typically used as by the run-bisect-manual-test.py script. -""" - -import os -import sys - -sys.path.append(os.path.join(os.path.dirname(__file__), 'telemetry')) -from telemetry.core import browser_finder -from telemetry.core import browser_options - - -def _StartManualTest(options): - """Start browser then ask the user whether build is good or bad.""" - browser_to_create = browser_finder.FindBrowser(options) - print 'Starting browser: %s.' % options.browser_type - with browser_to_create.Create() as browser: - - # Loop until we get a response that we can parse. - while True: - sys.stderr.write('Revision is [(g)ood/(b)ad]: ') - response = raw_input() - if response and response in ('g', 'b'): - if response in ('g'): - print "RESULT manual_test: manual_test= 1" - else: - print "RESULT manual_test: manual_test= 0" - break - - browser.Close() - - -def main(): - usage = ('%prog [options]\n' - 'Starts browser with an optional url and asks user whether ' - 'revision is good or bad.\n') - - options = browser_options.BrowserOptions() - parser = options.CreateParser(usage) - options, args = parser.parse_args() - - _StartManualTest(options) - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/tools/bisect-perf-regression.py b/tools/bisect-perf-regression.py deleted file mode 100755 index 4947ece657..0000000000 --- a/tools/bisect-perf-regression.py +++ /dev/null @@ -1,2456 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Performance Test Bisect Tool - -This script bisects a series of changelists using binary search. It starts at -a bad revision where a performance metric has regressed, and asks for a last -known-good revision. It will then binary search across this revision range by -syncing, building, and running a performance test. If the change is -suspected to occur as a result of WebKit/V8 changes, the script will -further bisect changes to those depots and attempt to narrow down the revision -range. - - -An example usage (using svn cl's): - -./tools/bisect-perf-regression.py -c\ -"out/Release/performance_ui_tests --gtest_filter=ShutdownTest.SimpleUserQuit"\ --g 168222 -b 168232 -m shutdown/simple-user-quit - -Be aware that if you're using the git workflow and specify an svn revision, -the script will attempt to find the git SHA1 where svn changes up to that -revision were merged in. - - -An example usage (using git hashes): - -./tools/bisect-perf-regression.py -c\ -"out/Release/performance_ui_tests --gtest_filter=ShutdownTest.SimpleUserQuit"\ --g 1f6e67861535121c5c819c16a666f2436c207e7b\ --b b732f23b4f81c382db0b23b9035f3dadc7d925bb\ --m shutdown/simple-user-quit - -""" - -import errno -import imp -import math -import optparse -import os -import re -import shlex -import shutil -import subprocess -import sys -import threading -import time - -import bisect_utils - - -# The additional repositories that might need to be bisected. -# If the repository has any dependant repositories (such as skia/src needs -# skia/include and skia/gyp to be updated), specify them in the 'depends' -# so that they're synced appropriately. -# Format is: -# src: path to the working directory. -# recurse: True if this repositry will get bisected. -# depends: A list of other repositories that are actually part of the same -# repository in svn. -# svn: Needed for git workflow to resolve hashes to svn revisions. -# from: Parent depot that must be bisected before this is bisected. -DEPOT_DEPS_NAME = { - 'chromium' : { - "src" : "src/", - "recurse" : True, - "depends" : None, - "from" : 'cros' - }, - 'webkit' : { - "src" : "src/third_party/WebKit", - "recurse" : True, - "depends" : None, - "from" : 'chromium' - }, - 'v8' : { - "src" : "src/v8", - "recurse" : True, - "depends" : None, - "build_with": 'v8_bleeding_edge', - "from" : 'chromium', - "custom_deps": bisect_utils.GCLIENT_CUSTOM_DEPS_V8 - }, - 'v8_bleeding_edge' : { - "src" : "src/v8_bleeding_edge", - "recurse" : False, - "depends" : None, - "svn": "https://v8.googlecode.com/svn/branches/bleeding_edge", - "from" : 'chromium' - }, - 'skia/src' : { - "src" : "src/third_party/skia/src", - "recurse" : True, - "svn" : "http://skia.googlecode.com/svn/trunk/src", - "depends" : ['skia/include', 'skia/gyp'], - "from" : 'chromium' - }, - 'skia/include' : { - "src" : "src/third_party/skia/include", - "recurse" : False, - "svn" : "http://skia.googlecode.com/svn/trunk/include", - "depends" : None, - "from" : 'chromium' - }, - 'skia/gyp' : { - "src" : "src/third_party/skia/gyp", - "recurse" : False, - "svn" : "http://skia.googlecode.com/svn/trunk/gyp", - "depends" : None, - "from" : 'chromium' - } -} - -DEPOT_NAMES = DEPOT_DEPS_NAME.keys() -CROS_SDK_PATH = os.path.join('..', 'cros', 'chromite', 'bin', 'cros_sdk') -CROS_VERSION_PATTERN = 'new version number from %s' -CROS_CHROMEOS_PATTERN = 'chromeos-base/chromeos-chrome' -CROS_TEST_KEY_PATH = os.path.join('..', 'cros', 'chromite', 'ssh_keys', - 'testing_rsa') -CROS_SCRIPT_KEY_PATH = os.path.join('..', 'cros', 'src', 'scripts', - 'mod_for_test_scripts', 'ssh_keys', - 'testing_rsa') - -BUILD_RESULT_SUCCEED = 0 -BUILD_RESULT_FAIL = 1 -BUILD_RESULT_SKIPPED = 2 - -def CalculateTruncatedMean(data_set, truncate_percent): - """Calculates the truncated mean of a set of values. - - Args: - data_set: Set of values to use in calculation. - truncate_percent: The % from the upper/lower portions of the data set to - discard, expressed as a value in [0, 1]. - - Returns: - The truncated mean as a float. - """ - if len(data_set) > 2: - data_set = sorted(data_set) - - discard_num_float = len(data_set) * truncate_percent - discard_num_int = int(math.floor(discard_num_float)) - kept_weight = len(data_set) - discard_num_float * 2 - - data_set = data_set[discard_num_int:len(data_set)-discard_num_int] - - weight_left = 1.0 - (discard_num_float - discard_num_int) - - if weight_left < 1: - # If the % to discard leaves a fractional portion, need to weight those - # values. - unweighted_vals = data_set[1:len(data_set)-1] - weighted_vals = [data_set[0], data_set[len(data_set)-1]] - weighted_vals = [w * weight_left for w in weighted_vals] - data_set = weighted_vals + unweighted_vals - else: - kept_weight = len(data_set) - - truncated_mean = reduce(lambda x, y: float(x) + float(y), - data_set) / kept_weight - - return truncated_mean - - -def CalculateStandardDeviation(v): - if len(v) == 1: - return 0.0 - - mean = CalculateTruncatedMean(v, 0.0) - variances = [float(x) - mean for x in v] - variances = [x * x for x in variances] - variance = reduce(lambda x, y: float(x) + float(y), variances) / (len(v) - 1) - std_dev = math.sqrt(variance) - - return std_dev - - -def IsStringFloat(string_to_check): - """Checks whether or not the given string can be converted to a floating - point number. - - Args: - string_to_check: Input string to check if it can be converted to a float. - - Returns: - True if the string can be converted to a float. - """ - try: - float(string_to_check) - - return True - except ValueError: - return False - - -def IsStringInt(string_to_check): - """Checks whether or not the given string can be converted to a integer. - - Args: - string_to_check: Input string to check if it can be converted to an int. - - Returns: - True if the string can be converted to an int. - """ - try: - int(string_to_check) - - return True - except ValueError: - return False - - -def IsWindows(): - """Checks whether or not the script is running on Windows. - - Returns: - True if running on Windows. - """ - return os.name == 'nt' - - -def RunProcess(command): - """Run an arbitrary command. If output from the call is needed, use - RunProcessAndRetrieveOutput instead. - - Args: - command: A list containing the command and args to execute. - - Returns: - The return code of the call. - """ - # On Windows, use shell=True to get PATH interpretation. - shell = IsWindows() - return subprocess.call(command, shell=shell) - - -def RunProcessAndRetrieveOutput(command): - """Run an arbitrary command, returning its output and return code. Since - output is collected via communicate(), there will be no output until the - call terminates. If you need output while the program runs (ie. so - that the buildbot doesn't terminate the script), consider RunProcess(). - - Args: - command: A list containing the command and args to execute. - print_output: Optional parameter to write output to stdout as it's - being collected. - - Returns: - A tuple of the output and return code. - """ - # On Windows, use shell=True to get PATH interpretation. - shell = IsWindows() - proc = subprocess.Popen(command, - shell=shell, - stdout=subprocess.PIPE) - - (output, _) = proc.communicate() - - return (output, proc.returncode) - - -def RunGit(command): - """Run a git subcommand, returning its output and return code. - - Args: - command: A list containing the args to git. - - Returns: - A tuple of the output and return code. - """ - command = ['git'] + command - - return RunProcessAndRetrieveOutput(command) - - -def CheckRunGit(command): - """Run a git subcommand, returning its output and return code. Asserts if - the return code of the call is non-zero. - - Args: - command: A list containing the args to git. - - Returns: - A tuple of the output and return code. - """ - (output, return_code) = RunGit(command) - - assert not return_code, 'An error occurred while running'\ - ' "git %s"' % ' '.join(command) - return output - - -def BuildWithMake(threads, targets): - cmd = ['make', 'BUILDTYPE=Release'] - - if threads: - cmd.append('-j%d' % threads) - - cmd += targets - - return_code = RunProcess(cmd) - - return not return_code - - -def BuildWithNinja(threads, targets): - cmd = ['ninja', '-C', os.path.join('out', 'Release')] - - if threads: - cmd.append('-j%d' % threads) - - cmd += targets - - return_code = RunProcess(cmd) - - return not return_code - - -def BuildWithVisualStudio(targets): - path_to_devenv = os.path.abspath( - os.path.join(os.environ['VS100COMNTOOLS'], '..', 'IDE', 'devenv.com')) - path_to_sln = os.path.join(os.getcwd(), 'chrome', 'chrome.sln') - cmd = [path_to_devenv, '/build', 'Release', path_to_sln] - - for t in targets: - cmd.extend(['/Project', t]) - - return_code = RunProcess(cmd) - - return not return_code - - -class Builder(object): - """Builder is used by the bisect script to build relevant targets and deploy. - """ - def Build(self, depot, opts): - raise NotImplementedError() - - -class DesktopBuilder(Builder): - """DesktopBuilder is used to build Chromium on linux/mac/windows.""" - def Build(self, depot, opts): - """Builds chrome and performance_ui_tests using options passed into - the script. - - Args: - depot: Current depot being bisected. - opts: The options parsed from the command line. - - Returns: - True if build was successful. - """ - targets = ['chrome', 'performance_ui_tests'] - - threads = None - if opts.use_goma: - threads = 64 - - build_success = False - if opts.build_preference == 'make': - build_success = BuildWithMake(threads, targets) - elif opts.build_preference == 'ninja': - if IsWindows(): - targets = [t + '.exe' for t in targets] - build_success = BuildWithNinja(threads, targets) - elif opts.build_preference == 'msvs': - assert IsWindows(), 'msvs is only supported on Windows.' - build_success = BuildWithVisualStudio(targets) - else: - assert False, 'No build system defined.' - return build_success - - -class AndroidBuilder(Builder): - """AndroidBuilder is used to build on android.""" - def InstallAPK(self, opts): - """Installs apk to device. - - Args: - opts: The options parsed from the command line. - - Returns: - True if successful. - """ - path_to_tool = os.path.join('build', 'android', 'adb_install_apk.py') - cmd = [path_to_tool, '--apk', 'ChromiumTestShell.apk', '--apk_package', - 'org.chromium.chrome.testshell', '--release'] - return_code = RunProcess(cmd) - - return not return_code - - def Build(self, depot, opts): - """Builds the android content shell and other necessary tools using options - passed into the script. - - Args: - depot: Current depot being bisected. - opts: The options parsed from the command line. - - Returns: - True if build was successful. - """ - targets = ['chromium_testshell', 'forwarder2', 'md5sum'] - threads = None - if opts.use_goma: - threads = 64 - - build_success = False - if opts.build_preference == 'ninja': - build_success = BuildWithNinja(threads, targets) - else: - assert False, 'No build system defined.' - - if build_success: - build_success = self.InstallAPK(opts) - - return build_success - - -class CrosBuilder(Builder): - """CrosBuilder is used to build and image ChromeOS/Chromium when cros is the - target platform.""" - def ImageToTarget(self, opts): - """Installs latest image to target specified by opts.cros_remote_ip. - - Args: - opts: Program options containing cros_board and cros_remote_ip. - - Returns: - True if successful. - """ - try: - # Keys will most likely be set to 0640 after wiping the chroot. - os.chmod(CROS_SCRIPT_KEY_PATH, 0600) - os.chmod(CROS_TEST_KEY_PATH, 0600) - cmd = [CROS_SDK_PATH, '--', './bin/cros_image_to_target.py', - '--remote=%s' % opts.cros_remote_ip, - '--board=%s' % opts.cros_board, '--test', '--verbose'] - - return_code = RunProcess(cmd) - return not return_code - except OSError, e: - return False - - def BuildPackages(self, opts, depot): - """Builds packages for cros. - - Args: - opts: Program options containing cros_board. - depot: The depot being bisected. - - Returns: - True if successful. - """ - cmd = [CROS_SDK_PATH] - - if depot != 'cros': - path_to_chrome = os.path.join(os.getcwd(), '..') - cmd += ['--chrome_root=%s' % path_to_chrome] - - cmd += ['--'] - - if depot != 'cros': - cmd += ['CHROME_ORIGIN=LOCAL_SOURCE'] - - cmd += ['BUILDTYPE=Release', './build_packages', - '--board=%s' % opts.cros_board] - return_code = RunProcess(cmd) - - return not return_code - - def BuildImage(self, opts, depot): - """Builds test image for cros. - - Args: - opts: Program options containing cros_board. - depot: The depot being bisected. - - Returns: - True if successful. - """ - cmd = [CROS_SDK_PATH] - - if depot != 'cros': - path_to_chrome = os.path.join(os.getcwd(), '..') - cmd += ['--chrome_root=%s' % path_to_chrome] - - cmd += ['--'] - - if depot != 'cros': - cmd += ['CHROME_ORIGIN=LOCAL_SOURCE'] - - cmd += ['BUILDTYPE=Release', '--', './build_image', - '--board=%s' % opts.cros_board, 'test'] - - return_code = RunProcess(cmd) - - return not return_code - - def Build(self, depot, opts): - """Builds targets using options passed into the script. - - Args: - depot: Current depot being bisected. - opts: The options parsed from the command line. - - Returns: - True if build was successful. - """ - if self.BuildPackages(opts, depot): - if self.BuildImage(opts, depot): - return self.ImageToTarget(opts) - return False - - -class SourceControl(object): - """SourceControl is an abstraction over the underlying source control - system used for chromium. For now only git is supported, but in the - future, the svn workflow could be added as well.""" - def __init__(self): - super(SourceControl, self).__init__() - - def SyncToRevisionWithGClient(self, revision): - """Uses gclient to sync to the specified revision. - - ie. gclient sync --revision - - Args: - revision: The git SHA1 or svn CL (depending on workflow). - - Returns: - The return code of the call. - """ - return bisect_utils.RunGClient(['sync', '--revision', - revision, '--verbose', '--nohooks', '--reset', '--force']) - - def SyncToRevisionWithRepo(self, timestamp): - """Uses repo to sync all the underlying git depots to the specified - time. - - Args: - timestamp: The unix timestamp to sync to. - - Returns: - The return code of the call. - """ - return bisect_utils.RunRepoSyncAtTimestamp(timestamp) - - -class GitSourceControl(SourceControl): - """GitSourceControl is used to query the underlying source control. """ - def __init__(self, opts): - super(GitSourceControl, self).__init__() - self.opts = opts - - def IsGit(self): - return True - - def GetRevisionList(self, revision_range_end, revision_range_start): - """Retrieves a list of revisions between |revision_range_start| and - |revision_range_end|. - - Args: - revision_range_end: The SHA1 for the end of the range. - revision_range_start: The SHA1 for the beginning of the range. - - Returns: - A list of the revisions between |revision_range_start| and - |revision_range_end| (inclusive). - """ - revision_range = '%s..%s' % (revision_range_start, revision_range_end) - cmd = ['log', '--format=%H', '-10000', '--first-parent', revision_range] - log_output = CheckRunGit(cmd) - - revision_hash_list = log_output.split() - revision_hash_list.append(revision_range_start) - - return revision_hash_list - - def SyncToRevision(self, revision, sync_client=None): - """Syncs to the specified revision. - - Args: - revision: The revision to sync to. - use_gclient: Specifies whether or not we should sync using gclient or - just use source control directly. - - Returns: - True if successful. - """ - - if not sync_client: - results = RunGit(['checkout', revision])[1] - elif sync_client == 'gclient': - results = self.SyncToRevisionWithGClient(revision) - elif sync_client == 'repo': - results = self.SyncToRevisionWithRepo(revision) - - return not results - - def ResolveToRevision(self, revision_to_check, depot, search): - """If an SVN revision is supplied, try to resolve it to a git SHA1. - - Args: - revision_to_check: The user supplied revision string that may need to be - resolved to a git SHA1. - depot: The depot the revision_to_check is from. - search: The number of changelists to try if the first fails to resolve - to a git hash. If the value is negative, the function will search - backwards chronologically, otherwise it will search forward. - - Returns: - A string containing a git SHA1 hash, otherwise None. - """ - if depot != 'cros': - if not IsStringInt(revision_to_check): - return revision_to_check - - depot_svn = 'svn://svn.chromium.org/chrome/trunk/src' - - if depot != 'chromium': - depot_svn = DEPOT_DEPS_NAME[depot]['svn'] - - svn_revision = int(revision_to_check) - git_revision = None - - if search > 0: - search_range = xrange(svn_revision, svn_revision + search, 1) - else: - search_range = xrange(svn_revision, svn_revision + search, -1) - - for i in search_range: - svn_pattern = 'git-svn-id: %s@%d' % (depot_svn, i) - cmd = ['log', '--format=%H', '-1', '--grep', svn_pattern, - 'origin/master'] - - (log_output, return_code) = RunGit(cmd) - - assert not return_code, 'An error occurred while running'\ - ' "git %s"' % ' '.join(cmd) - - if not return_code: - log_output = log_output.strip() - - if log_output: - git_revision = log_output - - break - - return git_revision - else: - if IsStringInt(revision_to_check): - return int(revision_to_check) - else: - cwd = os.getcwd() - os.chdir(os.path.join(os.getcwd(), 'src', 'third_party', - 'chromiumos-overlay')) - pattern = CROS_VERSION_PATTERN % revision_to_check - cmd = ['log', '--format=%ct', '-1', '--grep', pattern] - - git_revision = None - - log_output = CheckRunGit(cmd) - if log_output: - git_revision = log_output - git_revision = int(log_output.strip()) - os.chdir(cwd) - - return git_revision - - def IsInProperBranch(self): - """Confirms they're in the master branch for performing the bisection. - This is needed or gclient will fail to sync properly. - - Returns: - True if the current branch on src is 'master' - """ - cmd = ['rev-parse', '--abbrev-ref', 'HEAD'] - log_output = CheckRunGit(cmd) - log_output = log_output.strip() - - return log_output == "master" - - def SVNFindRev(self, revision): - """Maps directly to the 'git svn find-rev' command. - - Args: - revision: The git SHA1 to use. - - Returns: - An integer changelist #, otherwise None. - """ - - cmd = ['svn', 'find-rev', revision] - - output = CheckRunGit(cmd) - svn_revision = output.strip() - - if IsStringInt(svn_revision): - return int(svn_revision) - - return None - - def QueryRevisionInfo(self, revision): - """Gathers information on a particular revision, such as author's name, - email, subject, and date. - - Args: - revision: Revision you want to gather information on. - Returns: - A dict in the following format: - { - 'author': %s, - 'email': %s, - 'date': %s, - 'subject': %s, - } - """ - commit_info = {} - - formats = ['%cN', '%cE', '%s', '%cD'] - targets = ['author', 'email', 'subject', 'date'] - - for i in xrange(len(formats)): - cmd = ['log', '--format=%s' % formats[i], '-1', revision] - output = CheckRunGit(cmd) - commit_info[targets[i]] = output.rstrip() - - return commit_info - - def CheckoutFileAtRevision(self, file_name, revision): - """Performs a checkout on a file at the given revision. - - Returns: - True if successful. - """ - return not RunGit(['checkout', revision, file_name])[1] - - def RevertFileToHead(self, file_name): - """Unstages a file and returns it to HEAD. - - Returns: - True if successful. - """ - # Reset doesn't seem to return 0 on success. - RunGit(['reset', 'HEAD', bisect_utils.FILE_DEPS_GIT]) - - return not RunGit(['checkout', bisect_utils.FILE_DEPS_GIT])[1] - - def QueryFileRevisionHistory(self, filename, revision_start, revision_end): - """Returns a list of commits that modified this file. - - Args: - filename: Name of file. - revision_start: Start of revision range. - revision_end: End of revision range. - - Returns: - Returns a list of commits that touched this file. - """ - cmd = ['log', '--format=%H', '%s~1..%s' % (revision_start, revision_end), - filename] - output = CheckRunGit(cmd) - - return [o for o in output.split('\n') if o] - -class BisectPerformanceMetrics(object): - """BisectPerformanceMetrics performs a bisection against a list of range - of revisions to narrow down where performance regressions may have - occurred.""" - - def __init__(self, source_control, opts): - super(BisectPerformanceMetrics, self).__init__() - - self.opts = opts - self.source_control = source_control - self.src_cwd = os.getcwd() - self.cros_cwd = os.path.join(os.getcwd(), '..', 'cros') - self.depot_cwd = {} - self.cleanup_commands = [] - self.warnings = [] - self.builder = None - - if opts.target_platform == 'cros': - self.builder = CrosBuilder() - elif opts.target_platform == 'android': - self.builder = AndroidBuilder() - else: - self.builder = DesktopBuilder() - - # This always starts true since the script grabs latest first. - self.was_blink = True - - for d in DEPOT_NAMES: - # The working directory of each depot is just the path to the depot, but - # since we're already in 'src', we can skip that part. - - self.depot_cwd[d] = self.src_cwd + DEPOT_DEPS_NAME[d]['src'][3:] - - def PerformCleanup(self): - """Performs cleanup when script is finished.""" - os.chdir(self.src_cwd) - for c in self.cleanup_commands: - if c[0] == 'mv': - shutil.move(c[1], c[2]) - else: - assert False, 'Invalid cleanup command.' - - def GetRevisionList(self, depot, bad_revision, good_revision): - """Retrieves a list of all the commits between the bad revision and - last known good revision.""" - - revision_work_list = [] - - if depot == 'cros': - revision_range_start = good_revision - revision_range_end = bad_revision - - cwd = os.getcwd() - self.ChangeToDepotWorkingDirectory('cros') - - # Print the commit timestamps for every commit in the revision time - # range. We'll sort them and bisect by that. There is a remote chance that - # 2 (or more) commits will share the exact same timestamp, but it's - # probably safe to ignore that case. - cmd = ['repo', 'forall', '-c', - 'git log --format=%%ct --before=%d --after=%d' % ( - revision_range_end, revision_range_start)] - (output, return_code) = RunProcessAndRetrieveOutput(cmd) - - assert not return_code, 'An error occurred while running'\ - ' "%s"' % ' '.join(cmd) - - os.chdir(cwd) - - revision_work_list = list(set( - [int(o) for o in output.split('\n') if IsStringInt(o)])) - revision_work_list = sorted(revision_work_list, reverse=True) - else: - revision_work_list = self.source_control.GetRevisionList(bad_revision, - good_revision) - - return revision_work_list - - def Get3rdPartyRevisionsFromCurrentRevision(self, depot): - """Parses the DEPS file to determine WebKit/v8/etc... versions. - - Returns: - A dict in the format {depot:revision} if successful, otherwise None. - """ - - cwd = os.getcwd() - self.ChangeToDepotWorkingDirectory(depot) - - results = {} - - if depot == 'chromium': - locals = {'Var': lambda _: locals["vars"][_], - 'From': lambda *args: None} - execfile(bisect_utils.FILE_DEPS_GIT, {}, locals) - - os.chdir(cwd) - - rxp = re.compile(".git@(?P[a-fA-F0-9]+)") - - for d in DEPOT_NAMES: - if DEPOT_DEPS_NAME[d]['recurse'] and\ - DEPOT_DEPS_NAME[d]['from'] == depot: - if locals['deps'].has_key(DEPOT_DEPS_NAME[d]['src']): - re_results = rxp.search(locals['deps'][DEPOT_DEPS_NAME[d]['src']]) - - if re_results: - results[d] = re_results.group('revision') - else: - return None - else: - return None - elif depot == 'cros': - cmd = [CROS_SDK_PATH, '--', 'portageq-%s' % self.opts.cros_board, - 'best_visible', '/build/%s' % self.opts.cros_board, 'ebuild', - CROS_CHROMEOS_PATTERN] - (output, return_code) = RunProcessAndRetrieveOutput(cmd) - - assert not return_code, 'An error occurred while running'\ - ' "%s"' % ' '.join(cmd) - - if len(output) > CROS_CHROMEOS_PATTERN: - output = output[len(CROS_CHROMEOS_PATTERN):] - - if len(output) > 1: - output = output.split('_')[0] - - if len(output) > 3: - contents = output.split('.') - - version = contents[2] - - if contents[3] != '0': - warningText = 'Chrome version: %s.%s but using %s.0 to bisect.' %\ - (version, contents[3], version) - if not warningText in self.warnings: - self.warnings.append(warningText) - - cwd = os.getcwd() - self.ChangeToDepotWorkingDirectory('chromium') - return_code = CheckRunGit(['log', '-1', '--format=%H', - '--author=chrome-release@google.com', '--grep=to %s' % version, - 'origin/master']) - os.chdir(cwd) - - results['chromium'] = output.strip() - - return results - - def BuildCurrentRevision(self, depot): - """Builds chrome and performance_ui_tests on the current revision. - - Returns: - True if the build was successful. - """ - if self.opts.debug_ignore_build: - return True - - cwd = os.getcwd() - os.chdir(self.src_cwd) - - build_success = self.builder.Build(depot, self.opts) - - os.chdir(cwd) - - return build_success - - def RunGClientHooks(self): - """Runs gclient with runhooks command. - - Returns: - True if gclient reports no errors. - """ - - if self.opts.debug_ignore_build: - return True - - return not bisect_utils.RunGClient(['runhooks']) - - def TryParseHistogramValuesFromOutput(self, metric, text): - """Attempts to parse a metric in the format HISTOGRAM . - - Args: - metric: The metric as a list of [, ] strings. - text: The text to parse the metric values from. - - Returns: - A list of floating point numbers found. - """ - metric_formatted = 'HISTOGRAM %s: %s= ' % (metric[0], metric[1]) - - text_lines = text.split('\n') - values_list = [] - - for current_line in text_lines: - if metric_formatted in current_line: - current_line = current_line[len(metric_formatted):] - - try: - histogram_values = eval(current_line) - - for b in histogram_values['buckets']: - average_for_bucket = float(b['high'] + b['low']) * 0.5 - # Extends the list with N-elements with the average for that bucket. - values_list.extend([average_for_bucket] * b['count']) - except: - pass - - return values_list - - def TryParseResultValuesFromOutput(self, metric, text): - """Attempts to parse a metric in the format RESULT . - - Args: - metric: The metric as a list of [, ] strings. - text: The text to parse the metric values from. - - Returns: - A list of floating point numbers found. - """ - # Format is: RESULT : = - metric_formatted = re.escape('RESULT %s: %s=' % (metric[0], metric[1])) - - text_lines = text.split('\n') - values_list = [] - - for current_line in text_lines: - # Parse the output from the performance test for the metric we're - # interested in. - metric_re = metric_formatted +\ - "(\s)*(?P[0-9]+(\.[0-9]*)?)" - metric_re = re.compile(metric_re) - regex_results = metric_re.search(current_line) - - if not regex_results is None: - values_list += [regex_results.group('values')] - else: - metric_re = metric_formatted +\ - "(\s)*\[(\s)*(?P[0-9,.]+)\]" - metric_re = re.compile(metric_re) - regex_results = metric_re.search(current_line) - - if not regex_results is None: - metric_values = regex_results.group('values') - - values_list += metric_values.split(',') - - values_list = [float(v) for v in values_list if IsStringFloat(v)] - - # If the metric is times/t, we need to sum the timings in order to get - # similar regression results as the try-bots. - - if metric == ['times', 't']: - if values_list: - values_list = [reduce(lambda x, y: float(x) + float(y), values_list)] - - return values_list - - def ParseMetricValuesFromOutput(self, metric, text): - """Parses output from performance_ui_tests and retrieves the results for - a given metric. - - Args: - metric: The metric as a list of [, ] strings. - text: The text to parse the metric values from. - - Returns: - A list of floating point numbers found. - """ - metric_values = self.TryParseResultValuesFromOutput(metric, text) - - if not metric_values: - metric_values = self.TryParseHistogramValuesFromOutput(metric, text) - - return metric_values - - def RunPerformanceTestAndParseResults(self, command_to_run, metric): - """Runs a performance test on the current revision by executing the - 'command_to_run' and parses the results. - - Args: - command_to_run: The command to be run to execute the performance test. - metric: The metric to parse out from the results of the performance test. - - Returns: - On success, it will return a tuple of the average value of the metric, - and a success code of 0. - """ - - if self.opts.debug_ignore_perf_test: - return ({'mean': 0.0, 'std_dev': 0.0}, 0) - - if IsWindows(): - command_to_run = command_to_run.replace('/', r'\\') - - args = shlex.split(command_to_run) - - # If running a telemetry test for cros, insert the remote ip, and - # identity parameters. - if self.opts.target_platform == 'cros': - if 'tools/perf/run_' in args[0]: - args.append('--remote=%s' % self.opts.cros_remote_ip) - args.append('--identity=%s' % CROS_TEST_KEY_PATH) - - cwd = os.getcwd() - os.chdir(self.src_cwd) - - start_time = time.time() - - metric_values = [] - for i in xrange(self.opts.repeat_test_count): - # Can ignore the return code since if the tests fail, it won't return 0. - try: - (output, return_code) = RunProcessAndRetrieveOutput(args) - except OSError, e: - if e.errno == errno.ENOENT: - err_text = ("Something went wrong running the performance test. " - "Please review the command line:\n\n") - if 'src/' in ' '.join(args): - err_text += ("Check that you haven't accidentally specified a path " - "with src/ in the command.\n\n") - err_text += ' '.join(args) - err_text += '\n' - - return (err_text, -1) - raise - - if self.opts.output_buildbot_annotations: - print output - - metric_values += self.ParseMetricValuesFromOutput(metric, output) - - elapsed_minutes = (time.time() - start_time) / 60.0 - - if elapsed_minutes >= self.opts.repeat_test_max_time or not metric_values: - break - - os.chdir(cwd) - - # Need to get the average value if there were multiple values. - if metric_values: - truncated_mean = CalculateTruncatedMean(metric_values, - self.opts.truncate_percent) - standard_dev = CalculateStandardDeviation(metric_values) - - values = { - 'mean': truncated_mean, - 'std_dev': standard_dev, - } - - print 'Results of performance test: %12f %12f' % ( - truncated_mean, standard_dev) - print - return (values, 0) - else: - return ('Invalid metric specified, or no values returned from ' - 'performance test.', -1) - - def FindAllRevisionsToSync(self, revision, depot): - """Finds all dependant revisions and depots that need to be synced for a - given revision. This is only useful in the git workflow, as an svn depot - may be split into multiple mirrors. - - ie. skia is broken up into 3 git mirrors over skia/src, skia/gyp, and - skia/include. To sync skia/src properly, one has to find the proper - revisions in skia/gyp and skia/include. - - Args: - revision: The revision to sync to. - depot: The depot in use at the moment (probably skia). - - Returns: - A list of [depot, revision] pairs that need to be synced. - """ - revisions_to_sync = [[depot, revision]] - - is_base = (depot == 'chromium') or (depot == 'cros') - - # Some SVN depots were split into multiple git depots, so we need to - # figure out for each mirror which git revision to grab. There's no - # guarantee that the SVN revision will exist for each of the dependant - # depots, so we have to grep the git logs and grab the next earlier one. - if not is_base and\ - DEPOT_DEPS_NAME[depot]['depends'] and\ - self.source_control.IsGit(): - svn_rev = self.source_control.SVNFindRev(revision) - - for d in DEPOT_DEPS_NAME[depot]['depends']: - self.ChangeToDepotWorkingDirectory(d) - - dependant_rev = self.source_control.ResolveToRevision(svn_rev, d, -1000) - - if dependant_rev: - revisions_to_sync.append([d, dependant_rev]) - - num_resolved = len(revisions_to_sync) - num_needed = len(DEPOT_DEPS_NAME[depot]['depends']) - - self.ChangeToDepotWorkingDirectory(depot) - - if not ((num_resolved - 1) == num_needed): - return None - - return revisions_to_sync - - def PerformPreBuildCleanup(self): - """Performs necessary cleanup between runs.""" - print 'Cleaning up between runs.' - print - - # Having these pyc files around between runs can confuse the - # perf tests and cause them to crash. - for (path, dir, files) in os.walk(self.src_cwd): - for cur_file in files: - if cur_file.endswith('.pyc'): - path_to_file = os.path.join(path, cur_file) - os.remove(path_to_file) - - def PerformWebkitDirectoryCleanup(self, revision): - """If the script is switching between Blink and WebKit during bisect, - its faster to just delete the directory rather than leave it up to git - to sync. - - Returns: - True if successful. - """ - if not self.source_control.CheckoutFileAtRevision( - bisect_utils.FILE_DEPS_GIT, revision): - return False - - cwd = os.getcwd() - os.chdir(self.src_cwd) - - is_blink = bisect_utils.IsDepsFileBlink() - - os.chdir(cwd) - - if not self.source_control.RevertFileToHead( - bisect_utils.FILE_DEPS_GIT): - return False - - if self.was_blink != is_blink: - self.was_blink = is_blink - return bisect_utils.RemoveThirdPartyWebkitDirectory() - return True - - def PerformCrosChrootCleanup(self): - """Deletes the chroot. - - Returns: - True if successful. - """ - cwd = os.getcwd() - self.ChangeToDepotWorkingDirectory('cros') - cmd = [CROS_SDK_PATH, '--delete'] - return_code = RunProcess(cmd) - os.chdir(cwd) - return not return_code - - def CreateCrosChroot(self): - """Creates a new chroot. - - Returns: - True if successful. - """ - cwd = os.getcwd() - self.ChangeToDepotWorkingDirectory('cros') - cmd = [CROS_SDK_PATH, '--create'] - return_code = RunProcess(cmd) - os.chdir(cwd) - return not return_code - - def PerformPreSyncCleanup(self, revision, depot): - """Performs any necessary cleanup before syncing. - - Returns: - True if successful. - """ - if depot == 'chromium': - return self.PerformWebkitDirectoryCleanup(revision) - elif depot == 'cros': - return self.PerformCrosChrootCleanup() - return True - - def RunPostSync(self, depot): - """Performs any work after syncing. - - Returns: - True if successful. - """ - if self.opts.target_platform == 'android': - cwd = os.getcwd() - os.chdir(os.path.join(self.src_cwd, '..')) - if not bisect_utils.SetupAndroidBuildEnvironment(self.opts): - return False - os.chdir(cwd) - - if depot == 'cros': - return self.CreateCrosChroot() - else: - return self.RunGClientHooks() - return True - - def ShouldSkipRevision(self, depot, revision): - """Some commits can be safely skipped (such as a DEPS roll), since the tool - is git based those changes would have no effect. - - Args: - depot: The depot being bisected. - revision: Current revision we're synced to. - - Returns: - True if we should skip building/testing this revision. - """ - if depot == 'chromium': - if self.source_control.IsGit(): - cmd = ['diff-tree', '--no-commit-id', '--name-only', '-r', revision] - output = CheckRunGit(cmd) - - files = output.splitlines() - - if len(files) == 1 and files[0] == 'DEPS': - return True - - return False - - def SyncBuildAndRunRevision(self, revision, depot, command_to_run, metric, - skippable=False): - """Performs a full sync/build/run of the specified revision. - - Args: - revision: The revision to sync to. - depot: The depot that's being used at the moment (src, webkit, etc.) - command_to_run: The command to execute the performance test. - metric: The performance metric being tested. - - Returns: - On success, a tuple containing the results of the performance test. - Otherwise, a tuple with the error message. - """ - sync_client = None - if depot == 'chromium': - sync_client = 'gclient' - elif depot == 'cros': - sync_client = 'repo' - - revisions_to_sync = self.FindAllRevisionsToSync(revision, depot) - - if not revisions_to_sync: - return ('Failed to resolve dependant depots.', BUILD_RESULT_FAIL) - - if not self.PerformPreSyncCleanup(revision, depot): - return ('Failed to perform pre-sync cleanup.', BUILD_RESULT_FAIL) - - success = True - - if not self.opts.debug_ignore_sync: - for r in revisions_to_sync: - self.ChangeToDepotWorkingDirectory(r[0]) - - if sync_client: - self.PerformPreBuildCleanup() - - if not self.source_control.SyncToRevision(r[1], sync_client): - success = False - - break - - if success: - success = self.RunPostSync(depot) - - if success: - if skippable and self.ShouldSkipRevision(depot, revision): - return ('Skipped revision: [%s]' % str(revision), - BUILD_RESULT_SKIPPED) - - if self.BuildCurrentRevision(depot): - results = self.RunPerformanceTestAndParseResults(command_to_run, - metric) - - if results[1] == 0 and sync_client: - external_revisions = self.Get3rdPartyRevisionsFromCurrentRevision( - depot) - - if external_revisions: - return (results[0], results[1], external_revisions) - else: - return ('Failed to parse DEPS file for external revisions.', - BUILD_RESULT_FAIL) - else: - return results - else: - return ('Failed to build revision: [%s]' % (str(revision, )), - BUILD_RESULT_FAIL) - else: - return ('Failed to run [gclient runhooks].', BUILD_RESULT_FAIL) - else: - return ('Failed to sync revision: [%s]' % (str(revision, )), - BUILD_RESULT_FAIL) - - def CheckIfRunPassed(self, current_value, known_good_value, known_bad_value): - """Given known good and bad values, decide if the current_value passed - or failed. - - Args: - current_value: The value of the metric being checked. - known_bad_value: The reference value for a "failed" run. - known_good_value: The reference value for a "passed" run. - - Returns: - True if the current_value is closer to the known_good_value than the - known_bad_value. - """ - dist_to_good_value = abs(current_value['mean'] - known_good_value['mean']) - dist_to_bad_value = abs(current_value['mean'] - known_bad_value['mean']) - - return dist_to_good_value < dist_to_bad_value - - def ChangeToDepotWorkingDirectory(self, depot_name): - """Given a depot, changes to the appropriate working directory. - - Args: - depot_name: The name of the depot (see DEPOT_NAMES). - """ - if depot_name == 'chromium': - os.chdir(self.src_cwd) - elif depot_name == 'cros': - os.chdir(self.cros_cwd) - elif depot_name in DEPOT_NAMES: - os.chdir(self.depot_cwd[depot_name]) - else: - assert False, 'Unknown depot [ %s ] encountered. Possibly a new one'\ - ' was added without proper support?' %\ - (depot_name,) - - def PrepareToBisectOnDepot(self, - current_depot, - end_revision, - start_revision, - previous_depot, - previous_revision): - """Changes to the appropriate directory and gathers a list of revisions - to bisect between |start_revision| and |end_revision|. - - Args: - current_depot: The depot we want to bisect. - end_revision: End of the revision range. - start_revision: Start of the revision range. - previous_depot: The depot we were previously bisecting. - previous_revision: The last revision we synced to on |previous_depot|. - - Returns: - A list containing the revisions between |start_revision| and - |end_revision| inclusive. - """ - # Change into working directory of external library to run - # subsequent commands. - old_cwd = os.getcwd() - os.chdir(self.depot_cwd[current_depot]) - - # V8 (and possibly others) is merged in periodically. Bisecting - # this directory directly won't give much good info. - if DEPOT_DEPS_NAME[current_depot].has_key('build_with'): - if (DEPOT_DEPS_NAME[current_depot].has_key('custom_deps') and - previous_depot == 'chromium'): - config_path = os.path.join(self.src_cwd, '..') - if bisect_utils.RunGClientAndCreateConfig(self.opts, - DEPOT_DEPS_NAME[current_depot]['custom_deps'], cwd=config_path): - return [] - if bisect_utils.RunGClient( - ['sync', '--revision', previous_revision], cwd=self.src_cwd): - return [] - - new_depot = DEPOT_DEPS_NAME[current_depot]['build_with'] - - svn_start_revision = self.source_control.SVNFindRev(start_revision) - svn_end_revision = self.source_control.SVNFindRev(end_revision) - os.chdir(self.depot_cwd[new_depot]) - - start_revision = self.source_control.ResolveToRevision( - svn_start_revision, new_depot, -1000) - end_revision = self.source_control.ResolveToRevision( - svn_end_revision, new_depot, -1000) - - old_name = DEPOT_DEPS_NAME[current_depot]['src'][4:] - new_name = DEPOT_DEPS_NAME[new_depot]['src'][4:] - - os.chdir(self.src_cwd) - - shutil.move(old_name, old_name + '.bak') - shutil.move(new_name, old_name) - os.chdir(self.depot_cwd[current_depot]) - - self.cleanup_commands.append(['mv', old_name, new_name]) - self.cleanup_commands.append(['mv', old_name + '.bak', old_name]) - - os.chdir(self.depot_cwd[current_depot]) - - depot_revision_list = self.GetRevisionList(current_depot, - end_revision, - start_revision) - - os.chdir(old_cwd) - - return depot_revision_list - - def GatherReferenceValues(self, good_rev, bad_rev, cmd, metric, target_depot): - """Gathers reference values by running the performance tests on the - known good and bad revisions. - - Args: - good_rev: The last known good revision where the performance regression - has not occurred yet. - bad_rev: A revision where the performance regression has already occurred. - cmd: The command to execute the performance test. - metric: The metric being tested for regression. - - Returns: - A tuple with the results of building and running each revision. - """ - bad_run_results = self.SyncBuildAndRunRevision(bad_rev, - target_depot, - cmd, - metric) - - good_run_results = None - - if not bad_run_results[1]: - good_run_results = self.SyncBuildAndRunRevision(good_rev, - target_depot, - cmd, - metric) - - return (bad_run_results, good_run_results) - - def AddRevisionsIntoRevisionData(self, revisions, depot, sort, revision_data): - """Adds new revisions to the revision_data dict and initializes them. - - Args: - revisions: List of revisions to add. - depot: Depot that's currently in use (src, webkit, etc...) - sort: Sorting key for displaying revisions. - revision_data: A dict to add the new revisions into. Existing revisions - will have their sort keys offset. - """ - - num_depot_revisions = len(revisions) - - for k, v in revision_data.iteritems(): - if v['sort'] > sort: - v['sort'] += num_depot_revisions - - for i in xrange(num_depot_revisions): - r = revisions[i] - - revision_data[r] = {'revision' : r, - 'depot' : depot, - 'value' : None, - 'passed' : '?', - 'sort' : i + sort + 1} - - def PrintRevisionsToBisectMessage(self, revision_list, depot): - if self.opts.output_buildbot_annotations: - step_name = 'Bisection Range: [%s - %s]' % ( - revision_list[len(revision_list)-1], revision_list[0]) - bisect_utils.OutputAnnotationStepStart(step_name) - - print - print 'Revisions to bisect on [%s]:' % depot - for revision_id in revision_list: - print ' -> %s' % (revision_id, ) - print - - if self.opts.output_buildbot_annotations: - bisect_utils.OutputAnnotationStepClosed() - - def NudgeRevisionsIfDEPSChange(self, bad_revision, good_revision): - """Checks to see if changes to DEPS file occurred, and that the revision - range also includes the change to .DEPS.git. If it doesn't, attempts to - expand the revision range to include it. - - Args: - bad_rev: First known bad revision. - good_revision: Last known good revision. - - Returns: - A tuple with the new bad and good revisions. - """ - if self.source_control.IsGit() and self.opts.target_platform == 'chromium': - changes_to_deps = self.source_control.QueryFileRevisionHistory( - 'DEPS', good_revision, bad_revision) - - if changes_to_deps: - # DEPS file was changed, search from the oldest change to DEPS file to - # bad_revision to see if there are matching .DEPS.git changes. - oldest_deps_change = changes_to_deps[-1] - changes_to_gitdeps = self.source_control.QueryFileRevisionHistory( - bisect_utils.FILE_DEPS_GIT, oldest_deps_change, bad_revision) - - if len(changes_to_deps) != len(changes_to_gitdeps): - # Grab the timestamp of the last DEPS change - cmd = ['log', '--format=%ct', '-1', changes_to_deps[0]] - output = CheckRunGit(cmd) - commit_time = int(output) - - # Try looking for a commit that touches the .DEPS.git file in the - # next 15 minutes after the DEPS file change. - cmd = ['log', '--format=%H', '-1', - '--before=%d' % (commit_time + 900), '--after=%d' % commit_time, - 'origin/master', bisect_utils.FILE_DEPS_GIT] - output = CheckRunGit(cmd) - output = output.strip() - if output: - self.warnings.append('Detected change to DEPS and modified ' - 'revision range to include change to .DEPS.git') - return (output, good_revision) - else: - self.warnings.append('Detected change to DEPS but couldn\'t find ' - 'matching change to .DEPS.git') - return (bad_revision, good_revision) - - def CheckIfRevisionsInProperOrder(self, - target_depot, - good_revision, - bad_revision): - """Checks that |good_revision| is an earlier revision than |bad_revision|. - - Args: - good_revision: Number/tag of the known good revision. - bad_revision: Number/tag of the known bad revision. - - Returns: - True if the revisions are in the proper order (good earlier than bad). - """ - if self.source_control.IsGit() and target_depot != 'cros': - cmd = ['log', '--format=%ct', '-1', good_revision] - output = CheckRunGit(cmd) - good_commit_time = int(output) - - cmd = ['log', '--format=%ct', '-1', bad_revision] - output = CheckRunGit(cmd) - bad_commit_time = int(output) - - return good_commit_time <= bad_commit_time - else: - # Cros/svn use integers - return int(good_revision) <= int(bad_revision) - - def Run(self, command_to_run, bad_revision_in, good_revision_in, metric): - """Given known good and bad revisions, run a binary search on all - intermediate revisions to determine the CL where the performance regression - occurred. - - Args: - command_to_run: Specify the command to execute the performance test. - good_revision: Number/tag of the known good revision. - bad_revision: Number/tag of the known bad revision. - metric: The performance metric to monitor. - - Returns: - A dict with 2 members, 'revision_data' and 'error'. On success, - 'revision_data' will contain a dict mapping revision ids to - data about that revision. Each piece of revision data consists of a - dict with the following keys: - - 'passed': Represents whether the performance test was successful at - that revision. Possible values include: 1 (passed), 0 (failed), - '?' (skipped), 'F' (build failed). - 'depot': The depot that this revision is from (ie. WebKit) - 'external': If the revision is a 'src' revision, 'external' contains - the revisions of each of the external libraries. - 'sort': A sort value for sorting the dict in order of commits. - - For example: - { - 'error':None, - 'revision_data': - { - 'CL #1': - { - 'passed':False, - 'depot':'chromium', - 'external':None, - 'sort':0 - } - } - } - - If an error occurred, the 'error' field will contain the message and - 'revision_data' will be empty. - """ - - results = {'revision_data' : {}, - 'error' : None} - - # Choose depot to bisect first - target_depot = 'chromium' - if self.opts.target_platform == 'cros': - target_depot = 'cros' - - cwd = os.getcwd() - self.ChangeToDepotWorkingDirectory(target_depot) - - # If they passed SVN CL's, etc... we can try match them to git SHA1's. - bad_revision = self.source_control.ResolveToRevision(bad_revision_in, - target_depot, 100) - good_revision = self.source_control.ResolveToRevision(good_revision_in, - target_depot, -100) - - os.chdir(cwd) - - - if bad_revision is None: - results['error'] = 'Could\'t resolve [%s] to SHA1.' % (bad_revision_in,) - return results - - if good_revision is None: - results['error'] = 'Could\'t resolve [%s] to SHA1.' % (good_revision_in,) - return results - - # Check that they didn't accidentally swap good and bad revisions. - if not self.CheckIfRevisionsInProperOrder( - target_depot, good_revision, bad_revision): - results['error'] = 'bad_revision < good_revision, did you swap these '\ - 'by mistake?' - return results - - (bad_revision, good_revision) = self.NudgeRevisionsIfDEPSChange( - bad_revision, good_revision) - - if self.opts.output_buildbot_annotations: - bisect_utils.OutputAnnotationStepStart('Gathering Revisions') - - print 'Gathering revision range for bisection.' - - # Retrieve a list of revisions to do bisection on. - src_revision_list = self.GetRevisionList(target_depot, - bad_revision, - good_revision) - - if self.opts.output_buildbot_annotations: - bisect_utils.OutputAnnotationStepClosed() - - if src_revision_list: - # revision_data will store information about a revision such as the - # depot it came from, the webkit/V8 revision at that time, - # performance timing, build state, etc... - revision_data = results['revision_data'] - - # revision_list is the list we're binary searching through at the moment. - revision_list = [] - - sort_key_ids = 0 - - for current_revision_id in src_revision_list: - sort_key_ids += 1 - - revision_data[current_revision_id] = {'value' : None, - 'passed' : '?', - 'depot' : target_depot, - 'external' : None, - 'sort' : sort_key_ids} - revision_list.append(current_revision_id) - - min_revision = 0 - max_revision = len(revision_list) - 1 - - self.PrintRevisionsToBisectMessage(revision_list, target_depot) - - if self.opts.output_buildbot_annotations: - bisect_utils.OutputAnnotationStepStart('Gathering Reference Values') - - print 'Gathering reference values for bisection.' - - # Perform the performance tests on the good and bad revisions, to get - # reference values. - (bad_results, good_results) = self.GatherReferenceValues(good_revision, - bad_revision, - command_to_run, - metric, - target_depot) - - if self.opts.output_buildbot_annotations: - bisect_utils.OutputAnnotationStepClosed() - - if bad_results[1]: - results['error'] = bad_results[0] - return results - - if good_results[1]: - results['error'] = good_results[0] - return results - - - # We need these reference values to determine if later runs should be - # classified as pass or fail. - known_bad_value = bad_results[0] - known_good_value = good_results[0] - - # Can just mark the good and bad revisions explicitly here since we - # already know the results. - bad_revision_data = revision_data[revision_list[0]] - bad_revision_data['external'] = bad_results[2] - bad_revision_data['passed'] = 0 - bad_revision_data['value'] = known_bad_value - - good_revision_data = revision_data[revision_list[max_revision]] - good_revision_data['external'] = good_results[2] - good_revision_data['passed'] = 1 - good_revision_data['value'] = known_good_value - - next_revision_depot = target_depot - - while True: - if not revision_list: - break - - min_revision_data = revision_data[revision_list[min_revision]] - max_revision_data = revision_data[revision_list[max_revision]] - - if max_revision - min_revision <= 1: - if min_revision_data['passed'] == '?': - next_revision_index = min_revision - elif max_revision_data['passed'] == '?': - next_revision_index = max_revision - elif min_revision_data['depot'] == 'chromium' or\ - min_revision_data['depot'] == 'cros': - # If there were changes to any of the external libraries we track, - # should bisect the changes there as well. - external_depot = None - - for current_depot in DEPOT_NAMES: - if DEPOT_DEPS_NAME[current_depot]["recurse"] and\ - DEPOT_DEPS_NAME[current_depot]['from'] ==\ - min_revision_data['depot']: - if min_revision_data['external'][current_depot] !=\ - max_revision_data['external'][current_depot]: - external_depot = current_depot - break - - # If there was no change in any of the external depots, the search - # is over. - if not external_depot: - break - - previous_revision = revision_list[min_revision] - - earliest_revision = max_revision_data['external'][external_depot] - latest_revision = min_revision_data['external'][external_depot] - - new_revision_list = self.PrepareToBisectOnDepot(external_depot, - latest_revision, - earliest_revision, - next_revision_depot, - previous_revision) - - if not new_revision_list: - results['error'] = 'An error occurred attempting to retrieve'\ - ' revision range: [%s..%s]' %\ - (depot_rev_range[1], depot_rev_range[0]) - return results - - self.AddRevisionsIntoRevisionData(new_revision_list, - external_depot, - min_revision_data['sort'], - revision_data) - - # Reset the bisection and perform it on the newly inserted - # changelists. - revision_list = new_revision_list - min_revision = 0 - max_revision = len(revision_list) - 1 - sort_key_ids += len(revision_list) - - print 'Regression in metric:%s appears to be the result of changes'\ - ' in [%s].' % (metric, external_depot) - - self.PrintRevisionsToBisectMessage(revision_list, external_depot) - - continue - else: - break - else: - next_revision_index = int((max_revision - min_revision) / 2) +\ - min_revision - - next_revision_id = revision_list[next_revision_index] - next_revision_data = revision_data[next_revision_id] - next_revision_depot = next_revision_data['depot'] - - self.ChangeToDepotWorkingDirectory(next_revision_depot) - - if self.opts.output_buildbot_annotations: - step_name = 'Working on [%s]' % next_revision_id - bisect_utils.OutputAnnotationStepStart(step_name) - - print 'Working on revision: [%s]' % next_revision_id - - run_results = self.SyncBuildAndRunRevision(next_revision_id, - next_revision_depot, - command_to_run, - metric, skippable=True) - - # If the build is successful, check whether or not the metric - # had regressed. - if not run_results[1]: - if len(run_results) > 2: - next_revision_data['external'] = run_results[2] - - passed_regression = self.CheckIfRunPassed(run_results[0], - known_good_value, - known_bad_value) - - next_revision_data['passed'] = passed_regression - next_revision_data['value'] = run_results[0] - - if passed_regression: - max_revision = next_revision_index - else: - min_revision = next_revision_index - else: - if run_results[1] == BUILD_RESULT_SKIPPED: - next_revision_data['passed'] = 'Skipped' - elif run_results[1] == BUILD_RESULT_FAIL: - next_revision_data['passed'] = 'Failed' - - print run_results[0] - - # If the build is broken, remove it and redo search. - revision_list.pop(next_revision_index) - - max_revision -= 1 - - if self.opts.output_buildbot_annotations: - bisect_utils.OutputAnnotationStepClosed() - else: - # Weren't able to sync and retrieve the revision range. - results['error'] = 'An error occurred attempting to retrieve revision '\ - 'range: [%s..%s]' % (good_revision, bad_revision) - - return results - - def FormatAndPrintResults(self, bisect_results): - """Prints the results from a bisection run in a readable format. - - Args - bisect_results: The results from a bisection test run. - """ - revision_data = bisect_results['revision_data'] - revision_data_sorted = sorted(revision_data.iteritems(), - key = lambda x: x[1]['sort']) - - if self.opts.output_buildbot_annotations: - bisect_utils.OutputAnnotationStepStart('Results') - - print - print 'Full results of bisection:' - for current_id, current_data in revision_data_sorted: - build_status = current_data['passed'] - - if type(build_status) is bool: - build_status = int(build_status) - - print ' %8s %40s %s' % (current_data['depot'], - current_id, build_status) - print - - print - print 'Tested commits:' - for current_id, current_data in revision_data_sorted: - if current_data['value']: - print ' %8s %40s %12f %12f' % ( - current_data['depot'], current_id, - current_data['value']['mean'], current_data['value']['std_dev']) - print - - # Find range where it possibly broke. - first_working_revision = None - last_broken_revision = None - last_broken_revision_index = -1 - - for i in xrange(len(revision_data_sorted)): - k, v = revision_data_sorted[i] - if v['passed'] == 1: - if not first_working_revision: - first_working_revision = k - - if not v['passed']: - last_broken_revision = k - last_broken_revision_index = i - - if last_broken_revision != None and first_working_revision != None: - print 'Results: Regression may have occurred in range:' - print ' -> First Bad Revision: [%40s] [%s]' %\ - (last_broken_revision, - revision_data[last_broken_revision]['depot']) - print ' -> Last Good Revision: [%40s] [%s]' %\ - (first_working_revision, - revision_data[first_working_revision]['depot']) - - cwd = os.getcwd() - self.ChangeToDepotWorkingDirectory( - revision_data[last_broken_revision]['depot']) - - if revision_data[last_broken_revision]['depot'] == 'cros': - # Want to get a list of all the commits and what depots they belong - # to so that we can grab info about each. - cmd = ['repo', 'forall', '-c', - 'pwd ; git log --pretty=oneline --before=%d --after=%d' % ( - last_broken_revision, first_working_revision + 1)] - (output, return_code) = RunProcessAndRetrieveOutput(cmd) - - changes = [] - - assert not return_code, 'An error occurred while running'\ - ' "%s"' % ' '.join(cmd) - - last_depot = None - cwd = os.getcwd() - for l in output.split('\n'): - if l: - # Output will be in form: - # /path_to_depot - # /path_to_other_depot - # - # /path_again - # - # etc. - if l[0] == '/': - last_depot = l - else: - contents = l.split(' ') - if len(contents) > 1: - changes.append([last_depot, contents[0]]) - - print - for c in changes: - os.chdir(c[0]) - info = self.source_control.QueryRevisionInfo(c[1]) - - print - print 'Commit : %s' % c[1] - print 'Author : %s' % info['author'] - print 'Email : %s' % info['email'] - print 'Date : %s' % info['date'] - print 'Subject : %s' % info['subject'] - print - else: - multiple_commits = 0 - for i in xrange(last_broken_revision_index, len(revision_data_sorted)): - k, v = revision_data_sorted[i] - if k == first_working_revision: - break - - self.ChangeToDepotWorkingDirectory(v['depot']) - - info = self.source_control.QueryRevisionInfo(k) - - print - print 'Commit : %s' % k - print 'Author : %s' % info['author'] - print 'Email : %s' % info['email'] - print 'Date : %s' % info['date'] - print 'Subject : %s' % info['subject'] - - multiple_commits += 1 - if multiple_commits > 1: - self.warnings.append('Due to build errors, regression range could' - ' not be narrowed down to a single commit.') - print - os.chdir(cwd) - - # Give a warning if the values were very close together - good_std_dev = revision_data[first_working_revision]['value']['std_dev'] - good_mean = revision_data[first_working_revision]['value']['mean'] - bad_mean = revision_data[last_broken_revision]['value']['mean'] - - # A standard deviation of 0 could indicate either insufficient runs - # or a test that consistently returns the same value. - if good_std_dev > 0: - deviations = math.fabs(bad_mean - good_mean) / good_std_dev - - if deviations < 1.5: - self.warnings.append('Regression was less than 1.5 standard ' - 'deviations from "good" value. Results may not be accurate.') - elif self.opts.repeat_test_count == 1: - self.warnings.append('Tests were only set to run once. This ' - 'may be insufficient to get meaningful results.') - - # Check for any other possible regression ranges - prev_revision_data = revision_data_sorted[0][1] - prev_revision_id = revision_data_sorted[0][0] - possible_regressions = [] - for current_id, current_data in revision_data_sorted: - if current_data['value']: - prev_mean = prev_revision_data['value']['mean'] - cur_mean = current_data['value']['mean'] - - if good_std_dev: - deviations = math.fabs(prev_mean - cur_mean) / good_std_dev - else: - deviations = None - - if good_mean: - percent_change = (prev_mean - cur_mean) / good_mean - - # If the "good" valuse are supposed to be higher than the "bad" - # values (ie. scores), flip the sign of the percent change so that - # a positive value always represents a regression. - if bad_mean < good_mean: - percent_change *= -1.0 - else: - percent_change = None - - if deviations >= 1.5 or percent_change > 0.01: - if current_id != first_working_revision: - possible_regressions.append( - [current_id, prev_revision_id, percent_change, deviations]) - prev_revision_data = current_data - prev_revision_id = current_id - - if possible_regressions: - print - print 'Other regressions may have occurred:' - print - for p in possible_regressions: - current_id = p[0] - percent_change = p[2] - deviations = p[3] - current_data = revision_data[current_id] - previous_id = p[1] - previous_data = revision_data[previous_id] - - if deviations is None: - deviations = 'N/A' - else: - deviations = '%.2f' % deviations - - if percent_change is None: - percent_change = 0 - - print ' %8s %s [%.2f%%, %s x std.dev]' % ( - previous_data['depot'], previous_id, 100 * percent_change, - deviations) - print ' %8s %s' % ( - current_data['depot'], current_id) - print - - if self.warnings: - print - print 'The following warnings were generated:' - print - for w in self.warnings: - print ' - %s' % w - print - - if self.opts.output_buildbot_annotations: - bisect_utils.OutputAnnotationStepClosed() - - -def DetermineAndCreateSourceControl(opts): - """Attempts to determine the underlying source control workflow and returns - a SourceControl object. - - Returns: - An instance of a SourceControl object, or None if the current workflow - is unsupported. - """ - - (output, return_code) = RunGit(['rev-parse', '--is-inside-work-tree']) - - if output.strip() == 'true': - return GitSourceControl(opts) - - return None - - -def SetNinjaBuildSystemDefault(): - """Makes ninja the default build system to be used by - the bisection script.""" - gyp_var = os.getenv('GYP_GENERATORS') - - if not gyp_var or not 'ninja' in gyp_var: - if gyp_var: - os.environ['GYP_GENERATORS'] = gyp_var + ',ninja' - else: - os.environ['GYP_GENERATORS'] = 'ninja' - - if IsWindows(): - os.environ['GYP_DEFINES'] = 'component=shared_library '\ - 'incremental_chrome_dll=1 disable_nacl=1 fastbuild=1 '\ - 'chromium_win_pch=0' - - -def SetMakeBuildSystemDefault(): - """Makes make the default build system to be used by - the bisection script.""" - os.environ['GYP_GENERATORS'] = 'make' - - -def CheckPlatformSupported(opts): - """Checks that this platform and build system are supported. - - Args: - opts: The options parsed from the command line. - - Returns: - True if the platform and build system are supported. - """ - # Haven't tested the script out on any other platforms yet. - supported = ['posix', 'nt'] - if not os.name in supported: - print "Sorry, this platform isn't supported yet." - print - return False - - if IsWindows(): - if not opts.build_preference: - opts.build_preference = 'msvs' - - if opts.build_preference == 'msvs': - if not os.getenv('VS100COMNTOOLS'): - print 'Error: Path to visual studio could not be determined.' - print - return False - elif opts.build_preference == 'ninja': - SetNinjaBuildSystemDefault() - else: - assert False, 'Error: %s build not supported' % opts.build_preference - else: - if not opts.build_preference: - if 'ninja' in os.getenv('GYP_GENERATORS'): - opts.build_preference = 'ninja' - else: - opts.build_preference = 'make' - - if opts.build_preference == 'ninja': - SetNinjaBuildSystemDefault() - elif opts.build_preference == 'make': - SetMakeBuildSystemDefault() - elif opts.build_preference != 'make': - assert False, 'Error: %s build not supported' % opts.build_preference - - bisect_utils.RunGClient(['runhooks']) - - return True - - -def RmTreeAndMkDir(path_to_dir): - """Removes the directory tree specified, and then creates an empty - directory in the same location. - - Args: - path_to_dir: Path to the directory tree. - - Returns: - True if successful, False if an error occurred. - """ - try: - if os.path.exists(path_to_dir): - shutil.rmtree(path_to_dir) - except OSError, e: - if e.errno != errno.ENOENT: - return False - - try: - os.makedirs(path_to_dir) - except OSError, e: - if e.errno != errno.EEXIST: - return False - - return True - - -def RemoveBuildFiles(): - """Removes build files from previous runs.""" - if RmTreeAndMkDir(os.path.join('out', 'Release')): - if RmTreeAndMkDir(os.path.join('build', 'Release')): - return True - return False - - -def main(): - - usage = ('%prog [options] [-- chromium-options]\n' - 'Perform binary search on revision history to find a minimal ' - 'range of revisions where a peformance metric regressed.\n') - - parser = optparse.OptionParser(usage=usage) - - parser.add_option('-c', '--command', - type='str', - help='A command to execute your performance test at' + - ' each point in the bisection.') - parser.add_option('-b', '--bad_revision', - type='str', - help='A bad revision to start bisection. ' + - 'Must be later than good revision. May be either a git' + - ' or svn revision.') - parser.add_option('-g', '--good_revision', - type='str', - help='A revision to start bisection where performance' + - ' test is known to pass. Must be earlier than the ' + - 'bad revision. May be either a git or svn revision.') - parser.add_option('-m', '--metric', - type='str', - help='The desired metric to bisect on. For example ' + - '"vm_rss_final_b/vm_rss_f_b"') - parser.add_option('-w', '--working_directory', - type='str', - help='Path to the working directory where the script will ' - 'do an initial checkout of the chromium depot. The ' - 'files will be placed in a subdirectory "bisect" under ' - 'working_directory and that will be used to perform the ' - 'bisection. This parameter is optional, if it is not ' - 'supplied, the script will work from the current depot.') - parser.add_option('-r', '--repeat_test_count', - type='int', - default=20, - help='The number of times to repeat the performance test. ' - 'Values will be clamped to range [1, 100]. ' - 'Default value is 20.') - parser.add_option('--repeat_test_max_time', - type='int', - default=20, - help='The maximum time (in minutes) to take running the ' - 'performance tests. The script will run the performance ' - 'tests according to --repeat_test_count, so long as it ' - 'doesn\'t exceed --repeat_test_max_time. Values will be ' - 'clamped to range [1, 60].' - 'Default value is 20.') - parser.add_option('-t', '--truncate_percent', - type='int', - default=25, - help='The highest/lowest % are discarded to form a ' - 'truncated mean. Values will be clamped to range [0, 25]. ' - 'Default value is 25 (highest/lowest 25% will be ' - 'discarded).') - parser.add_option('--build_preference', - type='choice', - choices=['msvs', 'ninja', 'make'], - help='The preferred build system to use. On linux/mac ' - 'the options are make/ninja. On Windows, the options ' - 'are msvs/ninja.') - parser.add_option('--target_platform', - type='choice', - choices=['chromium', 'cros', 'android'], - default='chromium', - help='The target platform. Choices are "chromium" (current ' - 'platform), "cros", or "android". If you specify something ' - 'other than "chromium", you must be properly set up to ' - 'build that platform.') - parser.add_option('--cros_board', - type='str', - help='The cros board type to build.') - parser.add_option('--cros_remote_ip', - type='str', - help='The remote machine to image to.') - parser.add_option('--use_goma', - action="store_true", - help='Add a bunch of extra threads for goma.') - parser.add_option('--output_buildbot_annotations', - action="store_true", - help='Add extra annotation output for buildbot.') - parser.add_option('--debug_ignore_build', - action="store_true", - help='DEBUG: Don\'t perform builds.') - parser.add_option('--debug_ignore_sync', - action="store_true", - help='DEBUG: Don\'t perform syncs.') - parser.add_option('--debug_ignore_perf_test', - action="store_true", - help='DEBUG: Don\'t perform performance tests.') - (opts, args) = parser.parse_args() - - if not opts.command: - print 'Error: missing required parameter: --command' - print - parser.print_help() - return 1 - - if not opts.good_revision: - print 'Error: missing required parameter: --good_revision' - print - parser.print_help() - return 1 - - if not opts.bad_revision: - print 'Error: missing required parameter: --bad_revision' - print - parser.print_help() - return 1 - - if not opts.metric: - print 'Error: missing required parameter: --metric' - print - parser.print_help() - return 1 - - if opts.target_platform == 'cros': - # Run sudo up front to make sure credentials are cached for later. - print 'Sudo is required to build cros:' - print - RunProcess(['sudo', 'true']) - - if not opts.cros_board: - print 'Error: missing required parameter: --cros_board' - print - parser.print_help() - return 1 - - if not opts.cros_remote_ip: - print 'Error: missing required parameter: --cros_remote_ip' - print - parser.print_help() - return 1 - - if not opts.working_directory: - print 'Error: missing required parameter: --working_directory' - print - parser.print_help() - return 1 - - opts.repeat_test_count = min(max(opts.repeat_test_count, 1), 100) - opts.repeat_test_max_time = min(max(opts.repeat_test_max_time, 1), 60) - opts.truncate_percent = min(max(opts.truncate_percent, 0), 25) - opts.truncate_percent = opts.truncate_percent / 100.0 - - metric_values = opts.metric.split('/') - if len(metric_values) != 2: - print "Invalid metric specified: [%s]" % (opts.metric,) - print - return 1 - - if opts.working_directory: - if bisect_utils.CreateBisectDirectoryAndSetupDepot(opts): - return 1 - - if not bisect_utils.SetupPlatformBuildEnvironment(opts): - print 'Error: Failed to set platform environment.' - print - return 1 - - os.chdir(os.path.join(os.getcwd(), 'src')) - - if not RemoveBuildFiles(): - print "Something went wrong removing the build files." - print - return 1 - - if not CheckPlatformSupported(opts): - return 1 - - # Check what source control method they're using. Only support git workflow - # at the moment. - source_control = DetermineAndCreateSourceControl(opts) - - if not source_control: - print "Sorry, only the git workflow is supported at the moment." - print - return 1 - - # gClient sync seems to fail if you're not in master branch. - if not source_control.IsInProperBranch() and not opts.debug_ignore_sync: - print "You must switch to master branch to run bisection." - print - return 1 - - bisect_test = BisectPerformanceMetrics(source_control, opts) - try: - bisect_results = bisect_test.Run(opts.command, - opts.bad_revision, - opts.good_revision, - metric_values) - if not(bisect_results['error']): - bisect_test.FormatAndPrintResults(bisect_results) - finally: - bisect_test.PerformCleanup() - - if not(bisect_results['error']): - return 0 - else: - print 'Error: ' + bisect_results['error'] - print - return 1 - -if __name__ == '__main__': - sys.exit(main()) diff --git a/tools/bisect_test.py b/tools/bisect_test.py deleted file mode 100644 index b970f84e36..0000000000 --- a/tools/bisect_test.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import unittest - -bisect_builds = __import__('bisect-builds') - - -class BisectTest(unittest.TestCase): - - patched = [] - max_rev = 10000 - - def monkey_patch(self, obj, name, new): - self.patched.append((obj, name, getattr(obj, name))) - setattr(obj, name, new) - - def clear_patching(self): - for obj, name, old in self.patched: - setattr(obj, name, old) - self.patched = [] - - def setUp(self): - self.monkey_patch(bisect_builds.DownloadJob, 'Start', lambda *args: None) - self.monkey_patch(bisect_builds.DownloadJob, 'Stop', lambda *args: None) - self.monkey_patch(bisect_builds.DownloadJob, 'WaitFor', lambda *args: None) - self.monkey_patch(bisect_builds, 'RunRevision', lambda *args: (0, "", "")) - self.monkey_patch(bisect_builds.PathContext, 'ParseDirectoryIndex', - lambda *args: range(self.max_rev)) - - def tearDown(self): - self.clear_patching() - - def bisect(self, good_rev, bad_rev, evaluate): - return bisect_builds.Bisect(good_rev=good_rev, - bad_rev=bad_rev, - evaluate=evaluate, - num_runs=1, - official_builds=False, - platform='linux', - profile=None, - try_args=()) - - def testBisectConsistentAnswer(self): - self.assertEqual(self.bisect(1000, 100, lambda *args: 'g'), (100, 101)) - self.assertEqual(self.bisect(100, 1000, lambda *args: 'b'), (100, 101)) - self.assertEqual(self.bisect(2000, 200, lambda *args: 'b'), (1999, 2000)) - self.assertEqual(self.bisect(200, 2000, lambda *args: 'g'), (1999, 2000)) - - -if __name__ == '__main__': - unittest.main() diff --git a/tools/bisect_utils.py b/tools/bisect_utils.py deleted file mode 100644 index 37869df791..0000000000 --- a/tools/bisect_utils.py +++ /dev/null @@ -1,402 +0,0 @@ -# Copyright (c) 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Set of operations/utilities related to checking out the depot, and -outputting annotations on the buildbot waterfall. These are intended to be -used by the bisection scripts.""" - -import errno -import os -import shutil -import subprocess -import sys - -GCLIENT_SPEC_DATA = [ - { "name" : "src", - "url" : "https://chromium.googlesource.com/chromium/src.git", - "deps_file" : ".DEPS.git", - "managed" : True, - "custom_deps" : { - "src/data/page_cycler": "https://chrome-internal.googlesource.com/" - "chrome/data/page_cycler/.git", - "src/data/dom_perf": "https://chrome-internal.googlesource.com/" - "chrome/data/dom_perf/.git", - "src/data/mach_ports": "https://chrome-internal.googlesource.com/" - "chrome/data/mach_ports/.git", - "src/tools/perf/data": "https://chrome-internal.googlesource.com/" - "chrome/tools/perf/data/.git", - "src/third_party/adobe/flash/binaries/ppapi/linux": - "https://chrome-internal.googlesource.com/" - "chrome/deps/adobe/flash/binaries/ppapi/linux/.git", - "src/third_party/adobe/flash/binaries/ppapi/linux_x64": - "https://chrome-internal.googlesource.com/" - "chrome/deps/adobe/flash/binaries/ppapi/linux_x64/.git", - "src/third_party/adobe/flash/binaries/ppapi/mac": - "https://chrome-internal.googlesource.com/" - "chrome/deps/adobe/flash/binaries/ppapi/mac/.git", - "src/third_party/adobe/flash/binaries/ppapi/mac_64": - "https://chrome-internal.googlesource.com/" - "chrome/deps/adobe/flash/binaries/ppapi/mac_64/.git", - "src/third_party/adobe/flash/binaries/ppapi/win": - "https://chrome-internal.googlesource.com/" - "chrome/deps/adobe/flash/binaries/ppapi/win/.git", - "src/third_party/adobe/flash/binaries/ppapi/win_x64": - "https://chrome-internal.googlesource.com/" - "chrome/deps/adobe/flash/binaries/ppapi/win_x64/.git", - }, - "safesync_url": "", - }, -] -GCLIENT_SPEC_ANDROID = "\ntarget_os = ['android']" -GCLIENT_CUSTOM_DEPS_V8 = {"src/v8_bleeding_edge": "git://github.com/v8/v8.git"} -FILE_DEPS_GIT = '.DEPS.git' - -REPO_PARAMS = [ - 'https://chrome-internal.googlesource.com/chromeos/manifest-internal/', - '--repo-url', - 'https://git.chromium.org/external/repo.git' -] - -REPO_SYNC_COMMAND = 'git checkout -f $(git rev-list --max-count=1 '\ - '--before=%d remotes/m/master)' - -ORIGINAL_ENV = {} - -def OutputAnnotationStepStart(name): - """Outputs appropriate annotation to signal the start of a step to - a trybot. - - Args: - name: The name of the step. - """ - print - print '@@@SEED_STEP %s@@@' % name - print '@@@STEP_CURSOR %s@@@' % name - print '@@@STEP_STARTED@@@' - print - sys.stdout.flush() - - -def OutputAnnotationStepClosed(): - """Outputs appropriate annotation to signal the closing of a step to - a trybot.""" - print - print '@@@STEP_CLOSED@@@' - print - sys.stdout.flush() - - -def CreateAndChangeToSourceDirectory(working_directory): - """Creates a directory 'bisect' as a subdirectory of 'working_directory'. If - the function is successful, the current working directory will change to that - of the new 'bisect' directory. - - Returns: - True if the directory was successfully created (or already existed). - """ - cwd = os.getcwd() - os.chdir(working_directory) - try: - os.mkdir('bisect') - except OSError, e: - if e.errno != errno.EEXIST: - return False - os.chdir('bisect') - return True - - -def SubprocessCall(cmd, cwd=None): - """Runs a subprocess with specified parameters. - - Args: - params: A list of parameters to pass to gclient. - cwd: Working directory to run from. - - Returns: - The return code of the call. - """ - if os.name == 'nt': - # "HOME" isn't normally defined on windows, but is needed - # for git to find the user's .netrc file. - if not os.getenv('HOME'): - os.environ['HOME'] = os.environ['USERPROFILE'] - shell = os.name == 'nt' - return subprocess.call(cmd, shell=shell, cwd=cwd) - - -def RunGClient(params, cwd=None): - """Runs gclient with the specified parameters. - - Args: - params: A list of parameters to pass to gclient. - cwd: Working directory to run from. - - Returns: - The return code of the call. - """ - cmd = ['gclient'] + params - - return SubprocessCall(cmd, cwd=cwd) - - -def RunRepo(params): - """Runs cros repo command with specified parameters. - - Args: - params: A list of parameters to pass to gclient. - - Returns: - The return code of the call. - """ - cmd = ['repo'] + params - - return SubprocessCall(cmd) - - -def RunRepoSyncAtTimestamp(timestamp): - """Syncs all git depots to the timestamp specified using repo forall. - - Args: - params: Unix timestamp to sync to. - - Returns: - The return code of the call. - """ - repo_sync = REPO_SYNC_COMMAND % timestamp - cmd = ['forall', '-c', REPO_SYNC_COMMAND % timestamp] - return RunRepo(cmd) - - -def RunGClientAndCreateConfig(opts, custom_deps=None, cwd=None): - """Runs gclient and creates a config containing both src and src-internal. - - Args: - opts: The options parsed from the command line through parse_args(). - custom_deps: A dictionary of additional dependencies to add to .gclient. - cwd: Working directory to run from. - - Returns: - The return code of the call. - """ - spec = GCLIENT_SPEC_DATA - - if custom_deps: - for k, v in custom_deps.iteritems(): - spec[0]['custom_deps'][k] = v - - # Cannot have newlines in string on windows - spec = 'solutions =' + str(spec) - spec = ''.join([l for l in spec.splitlines()]) - - if opts.target_platform == 'android': - spec += GCLIENT_SPEC_ANDROID - - return_code = RunGClient( - ['config', '--spec=%s' % spec, '--git-deps'], cwd=cwd) - return return_code - - -def IsDepsFileBlink(): - """Reads .DEPS.git and returns whether or not we're using blink. - - Returns: - True if blink, false if webkit. - """ - locals = {'Var': lambda _: locals["vars"][_], - 'From': lambda *args: None} - execfile(FILE_DEPS_GIT, {}, locals) - return 'blink.git' in locals['vars']['webkit_url'] - - -def RemoveThirdPartyWebkitDirectory(): - """Removes third_party/WebKit. - - Returns: - True on success. - """ - try: - path_to_dir = os.path.join(os.getcwd(), 'third_party', 'WebKit') - if os.path.exists(path_to_dir): - shutil.rmtree(path_to_dir) - except OSError, e: - if e.errno != errno.ENOENT: - return False - return True - - -def RunGClientAndSync(cwd=None): - """Runs gclient and does a normal sync. - - Args: - cwd: Working directory to run from. - - Returns: - The return code of the call. - """ - params = ['sync', '--verbose', '--nohooks', '--reset', '--force'] - return RunGClient(params, cwd=cwd) - - -def SetupGitDepot(opts): - """Sets up the depot for the bisection. The depot will be located in a - subdirectory called 'bisect'. - - Args: - opts: The options parsed from the command line through parse_args(). - - Returns: - True if gclient successfully created the config file and did a sync, False - otherwise. - """ - name = 'Setting up Bisection Depot' - - if opts.output_buildbot_annotations: - OutputAnnotationStepStart(name) - - passed = False - - if not RunGClientAndCreateConfig(opts): - passed_deps_check = True - if os.path.isfile(os.path.join('src', FILE_DEPS_GIT)): - cwd = os.getcwd() - os.chdir('src') - if not IsDepsFileBlink(): - passed_deps_check = RemoveThirdPartyWebkitDirectory() - else: - passed_deps_check = True - os.chdir(cwd) - - if passed_deps_check: - RunGClient(['revert']) - if not RunGClientAndSync(): - passed = True - - if opts.output_buildbot_annotations: - print - OutputAnnotationStepClosed() - - return passed - - -def SetupCrosRepo(): - """Sets up cros repo for bisecting chromeos. - - Returns: - Returns 0 on success. - """ - cwd = os.getcwd() - try: - os.mkdir('cros') - except OSError, e: - if e.errno != errno.EEXIST: - return False - os.chdir('cros') - - cmd = ['init', '-u'] + REPO_PARAMS - - passed = False - - if not RunRepo(cmd): - if not RunRepo(['sync']): - passed = True - os.chdir(cwd) - - return passed - - -def CopyAndSaveOriginalEnvironmentVars(): - """Makes a copy of the current environment variables.""" - # TODO: Waiting on crbug.com/255689, will remove this after. - vars_to_remove = [] - for k, v in os.environ.iteritems(): - if 'ANDROID' in k: - vars_to_remove.append(k) - vars_to_remove.append('CHROME_SRC') - vars_to_remove.append('CHROMIUM_GYP_FILE') - vars_to_remove.append('GYP_CROSSCOMPILE') - vars_to_remove.append('GYP_DEFINES') - vars_to_remove.append('GYP_GENERATORS') - vars_to_remove.append('GYP_GENERATOR_FLAGS') - vars_to_remove.append('OBJCOPY') - for k in vars_to_remove: - if os.environ.has_key(k): - del os.environ[k] - - global ORIGINAL_ENV - ORIGINAL_ENV = os.environ.copy() - - -def SetupAndroidBuildEnvironment(opts): - """Sets up the android build environment. - - Args: - opts: The options parsed from the command line through parse_args(). - path_to_file: Path to the bisect script's directory. - - Returns: - True if successful. - """ - - # Revert the environment variables back to default before setting them up - # with envsetup.sh. - env_vars = os.environ.copy() - for k, _ in env_vars.iteritems(): - del os.environ[k] - for k, v in ORIGINAL_ENV.iteritems(): - os.environ[k] = v - - path_to_file = os.path.join('build', 'android', 'envsetup.sh') - proc = subprocess.Popen(['bash', '-c', 'source %s && env' % path_to_file], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - cwd='src') - (out, _) = proc.communicate() - - for line in out.splitlines(): - (k, _, v) = line.partition('=') - os.environ[k] = v - return not proc.returncode - - -def SetupPlatformBuildEnvironment(opts): - """Performs any platform specific setup. - - Args: - opts: The options parsed from the command line through parse_args(). - path_to_file: Path to the bisect script's directory. - - Returns: - True if successful. - """ - if opts.target_platform == 'android': - CopyAndSaveOriginalEnvironmentVars() - return SetupAndroidBuildEnvironment(opts) - elif opts.target_platform == 'cros': - return SetupCrosRepo() - - return True - - -def CreateBisectDirectoryAndSetupDepot(opts): - """Sets up a subdirectory 'bisect' and then retrieves a copy of the depot - there using gclient. - - Args: - opts: The options parsed from the command line through parse_args(). - reset: Whether to reset any changes to the depot. - - Returns: - Returns 0 on success, otherwise 1. - """ - if not CreateAndChangeToSourceDirectory(opts.working_directory): - print 'Error: Could not create bisect directory.' - print - return 1 - - if not SetupGitDepot(opts): - print 'Error: Failed to grab source.' - print - return 1 - - return 0 diff --git a/tools/checkbins/checkbins.py b/tools/checkbins/checkbins.py deleted file mode 100755 index e166eec551..0000000000 --- a/tools/checkbins/checkbins.py +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2011 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Makes sure that all EXE and DLL files in the provided directory were built -correctly. - -In essense it runs a subset of BinScope tests ensuring that binaries have -/NXCOMPAT, /DYNAMICBASE and /SAFESEH. -""" - -import os -import optparse -import sys - -# Find /third_party/pefile based on current directory and script path. -sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', - 'third_party', 'pefile')) -import pefile - -PE_FILE_EXTENSIONS = ['.exe', '.dll'] -DYNAMICBASE_FLAG = 0x0040 -NXCOMPAT_FLAG = 0x0100 -NO_SEH_FLAG = 0x0400 -MACHINE_TYPE_AMD64 = 0x8664 - -# Please do not add your file here without confirming that it indeed doesn't -# require /NXCOMPAT and /DYNAMICBASE. Contact cpu@chromium.org or your local -# Windows guru for advice. -EXCLUDED_FILES = ['chrome_frame_mini_installer.exe', - 'mini_installer.exe', - 'wow_helper.exe', - 'xinput1_3.dll' # Microsoft DirectX redistributable. - ] - -def IsPEFile(path): - return (os.path.isfile(path) and - os.path.splitext(path)[1].lower() in PE_FILE_EXTENSIONS and - os.path.basename(path) not in EXCLUDED_FILES) - -def main(options, args): - directory = args[0] - pe_total = 0 - pe_passed = 0 - - for file in os.listdir(directory): - path = os.path.abspath(os.path.join(directory, file)) - if not IsPEFile(path): - continue - pe = pefile.PE(path, fast_load=True) - pe.parse_data_directories(directories=[ - pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG']]) - pe_total = pe_total + 1 - success = True - - # Check for /DYNAMICBASE. - if pe.OPTIONAL_HEADER.DllCharacteristics & DYNAMICBASE_FLAG: - if options.verbose: - print "Checking %s for /DYNAMICBASE... PASS" % path - else: - success = False - print "Checking %s for /DYNAMICBASE... FAIL" % path - - # Check for /NXCOMPAT. - if pe.OPTIONAL_HEADER.DllCharacteristics & NXCOMPAT_FLAG: - if options.verbose: - print "Checking %s for /NXCOMPAT... PASS" % path - else: - success = False - print "Checking %s for /NXCOMPAT... FAIL" % path - - # Check for /SAFESEH. Binaries should meet one of the following - # criteria: - # 1) Have no SEH table as indicated by the DLL characteristics - # 2) Have a LOAD_CONFIG section containing a valid SEH table - # 3) Be a 64-bit binary, in which case /SAFESEH isn't required - # - # Refer to the following MSDN article for more information: - # http://msdn.microsoft.com/en-us/library/9a89h429.aspx - if (pe.OPTIONAL_HEADER.DllCharacteristics & NO_SEH_FLAG or - (hasattr(pe, "DIRECTORY_ENTRY_LOAD_CONFIG") and - pe.DIRECTORY_ENTRY_LOAD_CONFIG.struct.SEHandlerCount > 0 and - pe.DIRECTORY_ENTRY_LOAD_CONFIG.struct.SEHandlerTable != 0) or - pe.FILE_HEADER.Machine == MACHINE_TYPE_AMD64): - if options.verbose: - print "Checking %s for /SAFESEH... PASS" % path - else: - success = False - print "Checking %s for /SAFESEH... FAIL" % path - - # Update tally. - if success: - pe_passed = pe_passed + 1 - - print "Result: %d files found, %d files passed" % (pe_total, pe_passed) - if pe_passed != pe_total: - sys.exit(1) - -if __name__ == '__main__': - usage = "Usage: %prog [options] DIRECTORY" - option_parser = optparse.OptionParser(usage=usage) - option_parser.add_option("-v", "--verbose", action="store_true", - default=False, help="Print debug logging") - options, args = option_parser.parse_args() - if not args: - option_parser.print_help() - sys.exit(0) - main(options, args) diff --git a/tools/checkdeps/DEPS b/tools/checkdeps/DEPS deleted file mode 100644 index 7a57b0bcc8..0000000000 --- a/tools/checkdeps/DEPS +++ /dev/null @@ -1,3 +0,0 @@ -skip_child_includes = [ - "testdata", -] diff --git a/tools/checkdeps/PRESUBMIT.py b/tools/checkdeps/PRESUBMIT.py deleted file mode 100644 index 10ef63212f..0000000000 --- a/tools/checkdeps/PRESUBMIT.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Presubmit script for checkdeps tool. -""" - - -def CheckChange(input_api, output_api): - results = [] - results.extend(input_api.canned_checks.RunUnitTests( - input_api, output_api, - [input_api.os_path.join(input_api.PresubmitLocalPath(), - 'checkdeps_test.py')])) - return results - - -# Mandatory entrypoint. -def CheckChangeOnUpload(input_api, output_api): - return CheckChange(input_api, output_api) - - -# Mandatory entrypoint. -def CheckChangeOnCommit(input_api, output_api): - return CheckChange(input_api, output_api) diff --git a/tools/checkdeps/checkdeps.py b/tools/checkdeps/checkdeps.py deleted file mode 100755 index 5bfde13b4d..0000000000 --- a/tools/checkdeps/checkdeps.py +++ /dev/null @@ -1,526 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Makes sure that files include headers from allowed directories. - -Checks DEPS files in the source tree for rules, and applies those rules to -"#include" commands in source files. Any source file including something not -permitted by the DEPS files will fail. - -The format of the deps file: - -First you have the normal module-level deps. These are the ones used by -gclient. An example would be: - - deps = { - "base":"http://foo.bar/trunk/base" - } - -DEPS files not in the top-level of a module won't need this. Then you -have any additional include rules. You can add (using "+") or subtract -(using "-") from the previously specified rules (including -module-level deps). You can also specify a path that is allowed for -now but that we intend to remove, using "!"; this is treated the same -as "+" when check_deps is run by our bots, but a presubmit step will -show a warning if you add a new include of a file that is only allowed -by "!". - -Note that for .java files, there is currently no difference between -"+" and "!", even in the presubmit step. - - include_rules = { - # Code should be able to use base (it's specified in the module-level - # deps above), but nothing in "base/evil" because it's evil. - "-base/evil", - - # But this one subdirectory of evil is OK. - "+base/evil/not", - - # And it can include files from this other directory even though there is - # no deps rule for it. - "+tools/crime_fighter", - - # This dependency is allowed for now but work is ongoing to remove it, - # so you shouldn't add further dependencies on it. - "!base/evil/ok_for_now.h", - } - -If you have certain include rules that should only be applied for some -files within this directory and subdirectories, you can write a -section named specific_include_rules that is a hash map of regular -expressions to the list of rules that should apply to files matching -them. Note that such rules will always be applied before the rules -from 'include_rules' have been applied, but the order in which rules -associated with different regular expressions is applied is arbitrary. - - specific_include_rules = { - ".*_(unit|browser|api)test\.cc": [ - "+libraries/testsupport", - ], - } - -DEPS files may be placed anywhere in the tree. Each one applies to all -subdirectories, where there may be more DEPS files that provide additions or -subtractions for their own sub-trees. - -There is an implicit rule for the current directory (where the DEPS file lives) -and all of its subdirectories. This prevents you from having to explicitly -allow the current directory everywhere. This implicit rule is applied first, -so you can modify or remove it using the normal include rules. - -The rules are processed in order. This means you can explicitly allow a higher -directory and then take away permissions from sub-parts, or the reverse. - -Note that all directory separators must be slashes (Unix-style) and not -backslashes. All directories should be relative to the source root and use -only lowercase. -""" - -import os -import optparse -import re -import subprocess -import sys -import copy - -import cpp_checker -import java_checker -import results -from rules import Rule, Rules - - -# Variable name used in the DEPS file to add or subtract include files from -# the module-level deps. -INCLUDE_RULES_VAR_NAME = 'include_rules' - -# Variable name used in the DEPS file to add or subtract include files -# from module-level deps specific to files whose basename (last -# component of path) matches a given regular expression. -SPECIFIC_INCLUDE_RULES_VAR_NAME = 'specific_include_rules' - -# Optionally present in the DEPS file to list subdirectories which should not -# be checked. This allows us to skip third party code, for example. -SKIP_SUBDIRS_VAR_NAME = 'skip_child_includes' - - -def NormalizePath(path): - """Returns a path normalized to how we write DEPS rules and compare paths. - """ - return path.lower().replace('\\', '/') - - -def _IsTestFile(filename): - """Does a rudimentary check to try to skip test files; this could be - improved but is good enough for now. - """ - return re.match('(test|mock|dummy)_.*|.*_[a-z]*test\.(cc|mm|java)', filename) - - -class DepsChecker(object): - """Parses include_rules from DEPS files and can verify files in the - source tree against them. - """ - - def __init__(self, - base_directory=None, - verbose=False, - being_tested=False, - ignore_temp_rules=False, - skip_tests=False): - """Creates a new DepsChecker. - - Args: - base_directory: OS-compatible path to root of checkout, e.g. C:\chr\src. - verbose: Set to true for debug output. - being_tested: Set to true to ignore the DEPS file at tools/checkdeps/DEPS. - """ - self.base_directory = base_directory - self.verbose = verbose - self._under_test = being_tested - self._ignore_temp_rules = ignore_temp_rules - self._skip_tests = skip_tests - - if not base_directory: - self.base_directory = os.path.abspath( - os.path.join(os.path.abspath(os.path.dirname(__file__)), '..', '..')) - - self.results_formatter = results.NormalResultsFormatter(verbose) - - self.git_source_directories = set() - self._AddGitSourceDirectories() - - # Map of normalized directory paths to rules to use for those - # directories, or None for directories that should be skipped. - self.directory_rules = {} - self._ApplyDirectoryRulesAndSkipSubdirs(Rules(), self.base_directory) - - def Report(self): - """Prints a report of results, and returns an exit code for the process.""" - if self.results_formatter.GetResults(): - self.results_formatter.PrintResults() - return 1 - print '\nSUCCESS\n' - return 0 - - def _ApplyRules(self, existing_rules, includes, specific_includes, cur_dir): - """Applies the given include rules, returning the new rules. - - Args: - existing_rules: A set of existing rules that will be combined. - include: The list of rules from the "include_rules" section of DEPS. - specific_includes: E.g. {'.*_unittest\.cc': ['+foo', '-blat']} rules - from the "specific_include_rules" section of DEPS. - cur_dir: The current directory, normalized path. We will create an - implicit rule that allows inclusion from this directory. - - Returns: A new set of rules combining the existing_rules with the other - arguments. - """ - rules = copy.deepcopy(existing_rules) - - # First apply the implicit "allow" rule for the current directory. - if cur_dir.startswith( - NormalizePath(os.path.normpath(self.base_directory))): - relative_dir = cur_dir[len(self.base_directory) + 1:] - - source = relative_dir - if len(source) == 0: - source = 'top level' # Make the help string a little more meaningful. - rules.AddRule('+' + relative_dir, 'Default rule for ' + source) - else: - raise Exception('Internal error: base directory is not at the beginning' + - ' for\n %s and base dir\n %s' % - (cur_dir, self.base_directory)) - - def ApplyOneRule(rule_str, dependee_regexp=None): - """Deduces a sensible description for the rule being added, and - adds the rule with its description to |rules|. - - If we are ignoring temporary rules, this function does nothing - for rules beginning with the Rule.TEMP_ALLOW character. - """ - if self._ignore_temp_rules and rule_str.startswith(Rule.TEMP_ALLOW): - return - - rule_block_name = 'include_rules' - if dependee_regexp: - rule_block_name = 'specific_include_rules' - if not relative_dir: - rule_description = 'the top level %s' % rule_block_name - else: - rule_description = relative_dir + "'s %s" % rule_block_name - rules.AddRule(rule_str, rule_description, dependee_regexp) - - # Apply the additional explicit rules. - for (_, rule_str) in enumerate(includes): - ApplyOneRule(rule_str) - - # Finally, apply the specific rules. - for regexp, specific_rules in specific_includes.iteritems(): - for rule_str in specific_rules: - ApplyOneRule(rule_str, regexp) - - return rules - - def _ApplyDirectoryRules(self, existing_rules, dir_name): - """Combines rules from the existing rules and the new directory. - - Any directory can contain a DEPS file. Toplevel DEPS files can contain - module dependencies which are used by gclient. We use these, along with - additional include rules and implicit rules for the given directory, to - come up with a combined set of rules to apply for the directory. - - Args: - existing_rules: The rules for the parent directory. We'll add-on to these. - dir_name: The directory name that the deps file may live in (if - it exists). This will also be used to generate the - implicit rules. This is a non-normalized path. - - Returns: A tuple containing: (1) the combined set of rules to apply to the - sub-tree, and (2) a list of all subdirectories that should NOT be - checked, as specified in the DEPS file (if any). - """ - norm_dir_name = NormalizePath(dir_name) - - # Check for a .svn directory in this directory or check this directory is - # contained in git source direcotries. This will tell us if it's a source - # directory and should be checked. - if not (os.path.exists(os.path.join(dir_name, ".svn")) or - (norm_dir_name in self.git_source_directories)): - return (None, []) - - # Check the DEPS file in this directory. - if self.verbose: - print 'Applying rules from', dir_name - def FromImpl(_unused, _unused2): - pass # NOP function so "From" doesn't fail. - - def FileImpl(_unused): - pass # NOP function so "File" doesn't fail. - - class _VarImpl: - def __init__(self, local_scope): - self._local_scope = local_scope - - def Lookup(self, var_name): - """Implements the Var syntax.""" - if var_name in self._local_scope.get('vars', {}): - return self._local_scope['vars'][var_name] - raise Exception('Var is not defined: %s' % var_name) - - local_scope = {} - global_scope = { - 'File': FileImpl, - 'From': FromImpl, - 'Var': _VarImpl(local_scope).Lookup, - } - deps_file = os.path.join(dir_name, 'DEPS') - - # The second conditional here is to disregard the - # tools/checkdeps/DEPS file while running tests. This DEPS file - # has a skip_child_includes for 'testdata' which is necessary for - # running production tests, since there are intentional DEPS - # violations under the testdata directory. On the other hand when - # running tests, we absolutely need to verify the contents of that - # directory to trigger those intended violations and see that they - # are handled correctly. - if os.path.isfile(deps_file) and ( - not self._under_test or not os.path.split(dir_name)[1] == 'checkdeps'): - execfile(deps_file, global_scope, local_scope) - elif self.verbose: - print ' No deps file found in', dir_name - - # Even if a DEPS file does not exist we still invoke ApplyRules - # to apply the implicit "allow" rule for the current directory - include_rules = local_scope.get(INCLUDE_RULES_VAR_NAME, []) - specific_include_rules = local_scope.get(SPECIFIC_INCLUDE_RULES_VAR_NAME, - {}) - skip_subdirs = local_scope.get(SKIP_SUBDIRS_VAR_NAME, []) - - return (self._ApplyRules(existing_rules, include_rules, - specific_include_rules, norm_dir_name), - skip_subdirs) - - def _ApplyDirectoryRulesAndSkipSubdirs(self, parent_rules, dir_path): - """Given |parent_rules| and a subdirectory |dir_path| from the - directory that owns the |parent_rules|, add |dir_path|'s rules to - |self.directory_rules|, and add None entries for any of its - subdirectories that should be skipped. - """ - directory_rules, excluded_subdirs = self._ApplyDirectoryRules(parent_rules, - dir_path) - self.directory_rules[NormalizePath(dir_path)] = directory_rules - for subdir in excluded_subdirs: - self.directory_rules[NormalizePath( - os.path.normpath(os.path.join(dir_path, subdir)))] = None - - def GetDirectoryRules(self, dir_path): - """Returns a Rules object to use for the given directory, or None - if the given directory should be skipped. This takes care of - first building rules for parent directories (up to - self.base_directory) if needed. - - Args: - dir_path: A real (non-normalized) path to the directory you want - rules for. - """ - norm_dir_path = NormalizePath(dir_path) - - if not norm_dir_path.startswith( - NormalizePath(os.path.normpath(self.base_directory))): - dir_path = os.path.join(self.base_directory, dir_path) - norm_dir_path = NormalizePath(dir_path) - - parent_dir = os.path.dirname(dir_path) - parent_rules = None - if not norm_dir_path in self.directory_rules: - parent_rules = self.GetDirectoryRules(parent_dir) - - # We need to check for an entry for our dir_path again, in case we - # are at a path e.g. A/B/C where A/B/DEPS specifies the C - # subdirectory to be skipped; in this case, the invocation to - # GetDirectoryRules(parent_dir) has already filled in an entry for - # A/B/C. - if not norm_dir_path in self.directory_rules: - if not parent_rules: - # If the parent directory should be skipped, then the current - # directory should also be skipped. - self.directory_rules[norm_dir_path] = None - else: - self._ApplyDirectoryRulesAndSkipSubdirs(parent_rules, dir_path) - return self.directory_rules[norm_dir_path] - - def CheckDirectory(self, start_dir): - """Checks all relevant source files in the specified directory and - its subdirectories for compliance with DEPS rules throughout the - tree (starting at |self.base_directory|). |start_dir| must be a - subdirectory of |self.base_directory|. - - On completion, self.results_formatter has the results of - processing, and calling Report() will print a report of results. - """ - java = java_checker.JavaChecker(self.base_directory, self.verbose) - cpp = cpp_checker.CppChecker(self.verbose) - checkers = dict( - (extension, checker) - for checker in [java, cpp] for extension in checker.EXTENSIONS) - self._CheckDirectoryImpl(checkers, start_dir) - - def _CheckDirectoryImpl(self, checkers, dir_name): - rules = self.GetDirectoryRules(dir_name) - if rules == None: - return - - # Collect a list of all files and directories to check. - files_to_check = [] - dirs_to_check = [] - contents = os.listdir(dir_name) - for cur in contents: - full_name = os.path.join(dir_name, cur) - if os.path.isdir(full_name): - dirs_to_check.append(full_name) - elif os.path.splitext(full_name)[1] in checkers: - if not self._skip_tests or not _IsTestFile(cur): - files_to_check.append(full_name) - - # First check all files in this directory. - for cur in files_to_check: - checker = checkers[os.path.splitext(cur)[1]] - file_status = checker.CheckFile(rules, cur) - if file_status.HasViolations(): - self.results_formatter.AddError(file_status) - - # Next recurse into the subdirectories. - for cur in dirs_to_check: - self._CheckDirectoryImpl(checkers, cur) - - def CheckAddedCppIncludes(self, added_includes): - """This is used from PRESUBMIT.py to check new #include statements added in - the change being presubmit checked. - - Args: - added_includes: ((file_path, (include_line, include_line, ...), ...) - - Return: - A list of tuples, (bad_file_path, rule_type, rule_description) - where rule_type is one of Rule.DISALLOW or Rule.TEMP_ALLOW and - rule_description is human-readable. Empty if no problems. - """ - cpp = cpp_checker.CppChecker(self.verbose) - problems = [] - for file_path, include_lines in added_includes: - if not cpp.IsCppFile(file_path): - pass - rules_for_file = self.GetDirectoryRules(os.path.dirname(file_path)) - if rules_for_file: - for line in include_lines: - is_include, violation = cpp.CheckLine( - rules_for_file, line, file_path, True) - if violation: - rule_type = violation.violated_rule.allow - if rule_type != Rule.ALLOW: - violation_text = results.NormalResultsFormatter.FormatViolation( - violation, self.verbose) - problems.append((file_path, rule_type, violation_text)) - return problems - - def _AddGitSourceDirectories(self): - """Adds any directories containing sources managed by git to - self.git_source_directories. - """ - if not os.path.exists(os.path.join(self.base_directory, '.git')): - return - - popen_out = os.popen('cd %s && git ls-files --full-name .' % - subprocess.list2cmdline([self.base_directory])) - for line in popen_out.readlines(): - dir_name = os.path.join(self.base_directory, os.path.dirname(line)) - # Add the directory as well as all the parent directories. Use - # forward slashes and lower case to normalize paths. - while dir_name != self.base_directory: - self.git_source_directories.add(NormalizePath(dir_name)) - dir_name = os.path.dirname(dir_name) - self.git_source_directories.add(NormalizePath(self.base_directory)) - - -def PrintUsage(): - print """Usage: python checkdeps.py [--root ] [tocheck] - - --root ROOT Specifies the repository root. This defaults to "../../.." - relative to the script file. This will be correct given the - normal location of the script in "/tools/checkdeps". - - --(others) There are a few lesser-used options; run with --help to show them. - - tocheck Specifies the directory, relative to root, to check. This defaults - to "." so it checks everything. - -Examples: - python checkdeps.py - python checkdeps.py --root c:\\source chrome""" - - -def main(): - option_parser = optparse.OptionParser() - option_parser.add_option( - '', '--root', - default='', dest='base_directory', - help='Specifies the repository root. This defaults ' - 'to "../../.." relative to the script file, which ' - 'will normally be the repository root.') - option_parser.add_option( - '', '--ignore-temp-rules', - action='store_true', dest='ignore_temp_rules', default=False, - help='Ignore !-prefixed (temporary) rules.') - option_parser.add_option( - '', '--generate-temp-rules', - action='store_true', dest='generate_temp_rules', default=False, - help='Print rules to temporarily allow files that fail ' - 'dependency checking.') - option_parser.add_option( - '', '--count-violations', - action='store_true', dest='count_violations', default=False, - help='Count #includes in violation of intended rules.') - option_parser.add_option( - '', '--skip-tests', - action='store_true', dest='skip_tests', default=False, - help='Skip checking test files (best effort).') - option_parser.add_option( - '-v', '--verbose', - action='store_true', default=False, - help='Print debug logging') - options, args = option_parser.parse_args() - - deps_checker = DepsChecker(options.base_directory, - verbose=options.verbose, - ignore_temp_rules=options.ignore_temp_rules, - skip_tests=options.skip_tests) - - # Figure out which directory we have to check. - start_dir = deps_checker.base_directory - if len(args) == 1: - # Directory specified. Start here. It's supposed to be relative to the - # base directory. - start_dir = os.path.abspath( - os.path.join(deps_checker.base_directory, args[0])) - elif len(args) >= 2 or (options.generate_temp_rules and - options.count_violations): - # More than one argument, or incompatible flags, we don't handle this. - PrintUsage() - return 1 - - print 'Using base directory:', deps_checker.base_directory - print 'Checking:', start_dir - - if options.generate_temp_rules: - deps_checker.results_formatter = results.TemporaryRulesFormatter() - elif options.count_violations: - deps_checker.results_formatter = results.CountViolationsFormatter() - deps_checker.CheckDirectory(start_dir) - return deps_checker.Report() - - -if '__main__' == __name__: - sys.exit(main()) diff --git a/tools/checkdeps/checkdeps_test.py b/tools/checkdeps/checkdeps_test.py deleted file mode 100755 index e8835a5ca8..0000000000 --- a/tools/checkdeps/checkdeps_test.py +++ /dev/null @@ -1,177 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Tests for checkdeps. -""" - -import os -import unittest - - -import checkdeps -import results - - -class CheckDepsTest(unittest.TestCase): - - def setUp(self): - self.deps_checker = checkdeps.DepsChecker(being_tested=True) - - def ImplTestRegularCheckDepsRun(self, ignore_temp_rules, skip_tests): - self.deps_checker._ignore_temp_rules = ignore_temp_rules - self.deps_checker._skip_tests = skip_tests - self.deps_checker.CheckDirectory( - os.path.join(self.deps_checker.base_directory, - 'tools/checkdeps/testdata')) - - problems = self.deps_checker.results_formatter.GetResults() - if skip_tests: - self.failUnlessEqual(3, len(problems)) - else: - self.failUnlessEqual(4, len(problems)) - - def VerifySubstringsInProblems(key_path, substrings_in_sequence): - """Finds the problem in |problems| that contains |key_path|, - then verifies that each of |substrings_in_sequence| occurs in - that problem, in the order they appear in - |substrings_in_sequence|. - """ - found = False - key_path = os.path.normpath(key_path) - for problem in problems: - index = problem.find(key_path) - if index != -1: - for substring in substrings_in_sequence: - index = problem.find(substring, index + 1) - self.failUnless(index != -1, '%s in %s' % (substring, problem)) - found = True - break - if not found: - self.fail('Found no problem for file %s' % key_path) - - if ignore_temp_rules: - VerifySubstringsInProblems('testdata/allowed/test.h', - ['-tools/checkdeps/testdata/disallowed', - 'temporarily_allowed.h', - '-third_party/explicitly_disallowed', - 'Because of no rule applying']) - else: - VerifySubstringsInProblems('testdata/allowed/test.h', - ['-tools/checkdeps/testdata/disallowed', - '-third_party/explicitly_disallowed', - 'Because of no rule applying']) - - VerifySubstringsInProblems('testdata/disallowed/test.h', - ['-third_party/explicitly_disallowed', - 'Because of no rule applying', - 'Because of no rule applying']) - VerifySubstringsInProblems('disallowed/allowed/test.h', - ['-third_party/explicitly_disallowed', - 'Because of no rule applying', - 'Because of no rule applying']) - - if not skip_tests: - VerifySubstringsInProblems('allowed/not_a_test.cc', - ['-tools/checkdeps/testdata/disallowed']) - - def testRegularCheckDepsRun(self): - self.ImplTestRegularCheckDepsRun(False, False) - - def testRegularCheckDepsRunIgnoringTempRules(self): - self.ImplTestRegularCheckDepsRun(True, False) - - def testRegularCheckDepsRunSkipTests(self): - self.ImplTestRegularCheckDepsRun(False, True) - - def testRegularCheckDepsRunIgnoringTempRulesSkipTests(self): - self.ImplTestRegularCheckDepsRun(True, True) - - def CountViolations(self, ignore_temp_rules): - self.deps_checker._ignore_temp_rules = ignore_temp_rules - self.deps_checker.results_formatter = results.CountViolationsFormatter() - self.deps_checker.CheckDirectory( - os.path.join(self.deps_checker.base_directory, - 'tools/checkdeps/testdata')) - return self.deps_checker.results_formatter.GetResults() - - def testCountViolations(self): - self.failUnlessEqual('10', self.CountViolations(False)) - - def testCountViolationsIgnoringTempRules(self): - self.failUnlessEqual('11', self.CountViolations(True)) - - def testTempRulesGenerator(self): - self.deps_checker.results_formatter = results.TemporaryRulesFormatter() - self.deps_checker.CheckDirectory( - os.path.join(self.deps_checker.base_directory, - 'tools/checkdeps/testdata/allowed')) - temp_rules = self.deps_checker.results_formatter.GetResults() - expected = [u' "!third_party/explicitly_disallowed/bad.h",', - u' "!third_party/no_rule/bad.h",', - u' "!tools/checkdeps/testdata/disallowed/bad.h",', - u' "!tools/checkdeps/testdata/disallowed/teststuff/bad.h",'] - self.failUnlessEqual(expected, temp_rules) - - def testCheckAddedIncludesAllGood(self): - problems = self.deps_checker.CheckAddedCppIncludes( - [['tools/checkdeps/testdata/allowed/test.cc', - ['#include "tools/checkdeps/testdata/allowed/good.h"', - '#include "tools/checkdeps/testdata/disallowed/allowed/good.h"'] - ]]) - self.failIf(problems) - - def testCheckAddedIncludesManyGarbageLines(self): - garbage_lines = ["My name is Sam%d\n" % num for num in range(50)] - problems = self.deps_checker.CheckAddedCppIncludes( - [['tools/checkdeps/testdata/allowed/test.cc', garbage_lines]]) - self.failIf(problems) - - def testCheckAddedIncludesNoRule(self): - problems = self.deps_checker.CheckAddedCppIncludes( - [['tools/checkdeps/testdata/allowed/test.cc', - ['#include "no_rule_for_this/nogood.h"'] - ]]) - self.failUnless(problems) - - def testCheckAddedIncludesSkippedDirectory(self): - problems = self.deps_checker.CheckAddedCppIncludes( - [['tools/checkdeps/testdata/disallowed/allowed/skipped/test.cc', - ['#include "whatever/whocares.h"'] - ]]) - self.failIf(problems) - - def testCheckAddedIncludesTempAllowed(self): - problems = self.deps_checker.CheckAddedCppIncludes( - [['tools/checkdeps/testdata/allowed/test.cc', - ['#include "tools/checkdeps/testdata/disallowed/temporarily_allowed.h"'] - ]]) - self.failUnless(problems) - - def testCopyIsDeep(self): - # Regression test for a bug where we were making shallow copies of - # Rules objects and therefore all Rules objects shared the same - # dictionary for specific rules. - # - # The first pair should bring in a rule from testdata/allowed/DEPS - # into that global dictionary that allows the - # temp_allowed_for_tests.h file to be included in files ending - # with _unittest.cc, and the second pair should completely fail - # once the bug is fixed, but succeed (with a temporary allowance) - # if the bug is in place. - problems = self.deps_checker.CheckAddedCppIncludes( - [['tools/checkdeps/testdata/allowed/test.cc', - ['#include "tools/checkdeps/testdata/disallowed/temporarily_allowed.h"'] - ], - ['tools/checkdeps/testdata/disallowed/foo_unittest.cc', - ['#include "tools/checkdeps/testdata/bongo/temp_allowed_for_tests.h"'] - ]]) - # With the bug in place, there would be two problems reported, and - # the second would be for foo_unittest.cc. - self.failUnless(len(problems) == 1) - self.failUnless(problems[0][0].endswith('/test.cc')) - - -if __name__ == '__main__': - unittest.main() diff --git a/tools/checkdeps/cpp_checker.py b/tools/checkdeps/cpp_checker.py deleted file mode 100644 index 9bcd14d75c..0000000000 --- a/tools/checkdeps/cpp_checker.py +++ /dev/null @@ -1,113 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Checks C++ and Objective-C files for illegal includes.""" - -import codecs -import os -import re - -import results -from rules import Rule, MessageRule - - -class CppChecker(object): - - EXTENSIONS = [ - '.h', - '.cc', - '.cpp', - '.m', - '.mm', - ] - - # The maximum number of non-include lines we can see before giving up. - _MAX_UNINTERESTING_LINES = 50 - - # The maximum line length, this is to be efficient in the case of very long - # lines (which can't be #includes). - _MAX_LINE_LENGTH = 128 - - # This regular expression will be used to extract filenames from include - # statements. - _EXTRACT_INCLUDE_PATH = re.compile( - '[ \t]*#[ \t]*(?:include|import)[ \t]+"(.*)"') - - def __init__(self, verbose): - self._verbose = verbose - - def CheckLine(self, rules, line, dependee_path, fail_on_temp_allow=False): - """Checks the given line with the given rule set. - - Returns a tuple (is_include, dependency_violation) where - is_include is True only if the line is an #include or #import - statement, and dependency_violation is an instance of - results.DependencyViolation if the line violates a rule, or None - if it does not. - """ - found_item = self._EXTRACT_INCLUDE_PATH.match(line) - if not found_item: - return False, None # Not a match - - include_path = found_item.group(1) - - if '\\' in include_path: - return True, results.DependencyViolation( - include_path, - MessageRule('Include paths may not include backslashes.'), - rules) - - if '/' not in include_path: - # Don't fail when no directory is specified. We may want to be more - # strict about this in the future. - if self._verbose: - print ' WARNING: directory specified with no path: ' + include_path - return True, None - - rule = rules.RuleApplyingTo(include_path, dependee_path) - if (rule.allow == Rule.DISALLOW or - (fail_on_temp_allow and rule.allow == Rule.TEMP_ALLOW)): - return True, results.DependencyViolation(include_path, rule, rules) - return True, None - - def CheckFile(self, rules, filepath): - if self._verbose: - print 'Checking: ' + filepath - - dependee_status = results.DependeeStatus(filepath) - ret_val = '' # We'll collect the error messages in here - last_include = 0 - with codecs.open(filepath, encoding='utf-8') as f: - in_if0 = 0 - for line_num, line in enumerate(f): - if line_num - last_include > self._MAX_UNINTERESTING_LINES: - break - - line = line.strip() - - # Check to see if we're at / inside a #if 0 block - if line.startswith('#if 0'): - in_if0 += 1 - continue - if in_if0 > 0: - if line.startswith('#if'): - in_if0 += 1 - elif line.startswith('#endif'): - in_if0 -= 1 - continue - - is_include, violation = self.CheckLine(rules, line, filepath) - if is_include: - last_include = line_num - if violation: - dependee_status.AddViolation(violation) - - return dependee_status - - @staticmethod - def IsCppFile(file_path): - """Returns True iff the given path ends in one of the extensions - handled by this checker. - """ - return os.path.splitext(file_path)[1] in CppChecker.EXTENSIONS diff --git a/tools/checkdeps/java_checker.py b/tools/checkdeps/java_checker.py deleted file mode 100644 index 670eac2164..0000000000 --- a/tools/checkdeps/java_checker.py +++ /dev/null @@ -1,107 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Checks Java files for illegal imports.""" - -import codecs -import os -import re - -import results -from rules import Rule - - -class JavaChecker(object): - """Import checker for Java files. - - The CheckFile method uses real filesystem paths, but Java imports work in - terms of package names. To deal with this, we have an extra "prescan" pass - that reads all the .java files and builds a mapping of class name -> filepath. - In CheckFile, we convert each import statement into a real filepath, and check - that against the rules in the DEPS files. - - Note that in Java you can always use classes in the same directory without an - explicit import statement, so these imports can't be blocked with DEPS files. - But that shouldn't be a problem, because same-package imports are pretty much - always correct by definition. (If we find a case where this is *not* correct, - it probably means the package is too big and needs to be split up.) - - Properties: - _classmap: dict of fully-qualified Java class name -> filepath - """ - - EXTENSIONS = ['.java'] - - def __init__(self, base_directory, verbose): - self._base_directory = base_directory - self._verbose = verbose - self._classmap = {} - self._PrescanFiles() - - def _PrescanFiles(self): - for root, dirs, files in os.walk(self._base_directory): - # Skip unwanted subdirectories. TODO(husky): it would be better to do - # this via the skip_child_includes flag in DEPS files. Maybe hoist this - # prescan logic into checkdeps.py itself? - for d in dirs: - # Skip hidden directories. - if d.startswith('.'): - dirs.remove(d) - # Skip the "out" directory, as dealing with generated files is awkward. - # We don't want paths like "out/Release/lib.java" in our DEPS files. - # TODO(husky): We need some way of determining the "real" path to - # a generated file -- i.e., where it would be in source control if - # it weren't generated. - if d == 'out': - dirs.remove(d) - # Skip third-party directories. - if d == 'third_party': - dirs.remove(d) - for f in files: - if f.endswith('.java'): - self._PrescanFile(os.path.join(root, f)) - - def _PrescanFile(self, filepath): - if self._verbose: - print 'Prescanning: ' + filepath - with codecs.open(filepath, encoding='utf-8') as f: - short_class_name, _ = os.path.splitext(os.path.basename(filepath)) - for line in f: - for package in re.findall('^package ([\w\.]+);', line): - full_class_name = package + '.' + short_class_name - if full_class_name in self._classmap: - print 'WARNING: multiple definitions of %s:' % full_class_name - print ' ' + filepath - print ' ' + self._classmap[full_class_name] - print - else: - self._classmap[full_class_name] = filepath - return - print 'WARNING: no package definition found in %s' % filepath - - def CheckFile(self, rules, filepath): - if self._verbose: - print 'Checking: ' + filepath - - dependee_status = results.DependeeStatus(filepath) - with codecs.open(filepath, encoding='utf-8') as f: - for line in f: - for clazz in re.findall('^import\s+(?:static\s+)?([\w\.]+)\s*;', line): - if clazz not in self._classmap: - # Importing a class from outside the Chromium tree. That's fine -- - # it's probably a Java or Android system class. - continue - include_path = os.path.relpath( - self._classmap[clazz], self._base_directory) - # Convert Windows paths to Unix style, as used in DEPS files. - include_path = include_path.replace(os.path.sep, '/') - rule = rules.RuleApplyingTo(include_path, filepath) - if rule.allow == Rule.DISALLOW: - dependee_status.AddViolation( - results.DependencyViolation(include_path, rule, rules)) - if '{' in line: - # This is code, so we're finished reading imports for this file. - break - - return dependee_status diff --git a/tools/checkdeps/results.py b/tools/checkdeps/results.py deleted file mode 100644 index 8f9c189854..0000000000 --- a/tools/checkdeps/results.py +++ /dev/null @@ -1,140 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - - -"""Results object and results formatters for checkdeps tool.""" - - -class DependencyViolation(object): - """A single dependency violation.""" - - def __init__(self, include_path, violated_rule, rules): - # The include or import path that is in violation of a rule. - self.include_path = include_path - - # The violated rule. - self.violated_rule = violated_rule - - # The set of rules containing self.violated_rule. - self.rules = rules - - -class DependeeStatus(object): - """Results object for a dependee file.""" - - def __init__(self, dependee_path): - # Path of the file whose nonconforming dependencies are listed in - # self.violations. - self.dependee_path = dependee_path - - # List of DependencyViolation objects that apply to the dependee - # file. May be empty. - self.violations = [] - - def AddViolation(self, violation): - """Adds a violation.""" - self.violations.append(violation) - - def HasViolations(self): - """Returns True if this dependee is violating one or more rules.""" - return not not self.violations - - -class ResultsFormatter(object): - """Base class for results formatters.""" - - def AddError(self, dependee_status): - """Add a formatted result to |self.results| for |dependee_status|, - which is guaranteed to return True for - |dependee_status.HasViolations|. - """ - raise NotImplementedError() - - def GetResults(self): - """Returns the results. May be overridden e.g. to process the - results that have been accumulated. - """ - raise NotImplementedError() - - def PrintResults(self): - """Prints the results to stdout.""" - raise NotImplementedError() - - -class NormalResultsFormatter(ResultsFormatter): - """A results formatting object that produces the classical, - detailed, human-readable output of the checkdeps tool. - """ - - def __init__(self, verbose): - self.results = [] - self.verbose = verbose - - def AddError(self, dependee_status): - lines = [] - lines.append('\nERROR in %s' % dependee_status.dependee_path) - for violation in dependee_status.violations: - lines.append(self.FormatViolation(violation, self.verbose)) - self.results.append('\n'.join(lines)) - - @staticmethod - def FormatViolation(violation, verbose=False): - lines = [] - if verbose: - lines.append(' For %s' % violation.rules) - lines.append( - ' Illegal include: "%s"\n Because of %s' % - (violation.include_path, str(violation.violated_rule))) - return '\n'.join(lines) - - def GetResults(self): - return self.results - - def PrintResults(self): - for result in self.results: - print result - if self.results: - print '\nFAILED\n' - - -class TemporaryRulesFormatter(ResultsFormatter): - """A results formatter that produces a single line per nonconforming - include. The combined output is suitable for directly pasting into a - DEPS file as a list of temporary-allow rules. - """ - - def __init__(self): - self.violations = set() - - def AddError(self, dependee_status): - for violation in dependee_status.violations: - self.violations.add(violation.include_path) - - def GetResults(self): - return [' "!%s",' % path for path in sorted(self.violations)] - - def PrintResults(self): - for result in self.GetResults(): - print result - - -class CountViolationsFormatter(ResultsFormatter): - """A results formatter that produces a number, the count of #include - statements that are in violation of the dependency rules. - - Note that you normally want to instantiate DepsChecker with - ignore_temp_rules=True when you use this formatter. - """ - - def __init__(self): - self.count = 0 - - def AddError(self, dependee_status): - self.count += len(dependee_status.violations) - - def GetResults(self): - return '%d' % self.count - - def PrintResults(self): - print self.count diff --git a/tools/checkdeps/rules.py b/tools/checkdeps/rules.py deleted file mode 100644 index 09d718c723..0000000000 --- a/tools/checkdeps/rules.py +++ /dev/null @@ -1,151 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Base classes to represent dependency rules, used by checkdeps.py""" - - -import os -import re - - -class Rule(object): - """Specifies a single rule for an include, which can be one of - ALLOW, DISALLOW and TEMP_ALLOW. - """ - - # These are the prefixes used to indicate each type of rule. These - # are also used as values for self.allow to indicate which type of - # rule this is. - ALLOW = '+' - DISALLOW = '-' - TEMP_ALLOW = '!' - - def __init__(self, allow, directory, source): - self.allow = allow - self._dir = directory - self._source = source - - def __str__(self): - return '"%s%s" from %s.' % (self.allow, self._dir, self._source) - - def ParentOrMatch(self, other): - """Returns true if the input string is an exact match or is a parent - of the current rule. For example, the input "foo" would match "foo/bar".""" - return self._dir == other or self._dir.startswith(other + '/') - - def ChildOrMatch(self, other): - """Returns true if the input string would be covered by this rule. For - example, the input "foo/bar" would match the rule "foo".""" - return self._dir == other or other.startswith(self._dir + '/') - - -class MessageRule(Rule): - """A rule that has a simple message as the reason for failing, - unrelated to directory or source. - """ - - def __init__(self, reason): - super(MessageRule, self).__init__(Rule.DISALLOW, '', '') - self._reason = reason - - def __str__(self): - return self._reason - - -def ParseRuleString(rule_string, source): - """Returns a tuple of a character indicating what type of rule this - is, and a string holding the path the rule applies to. - """ - if not rule_string: - raise Exception('The rule string "%s" is empty\nin %s' % - (rule_string, source)) - - if not rule_string[0] in [Rule.ALLOW, Rule.DISALLOW, Rule.TEMP_ALLOW]: - raise Exception( - 'The rule string "%s" does not begin with a "+", "-" or "!".' % - rule_string) - - return (rule_string[0], rule_string[1:]) - - -class Rules(object): - """Sets of rules for files in a directory. - - By default, rules are added to the set of rules applicable to all - dependee files in the directory. Rules may also be added that apply - only to dependee files whose filename (last component of their path) - matches a given regular expression; hence there is one additional - set of rules per unique regular expression. - """ - - def __init__(self): - """Initializes the current rules with an empty rule list for all - files. - """ - # We keep the general rules out of the specific rules dictionary, - # as we need to always process them last. - self._general_rules = [] - - # Keys are regular expression strings, values are arrays of rules - # that apply to dependee files whose basename matches the regular - # expression. These are applied before the general rules, but - # their internal order is arbitrary. - self._specific_rules = {} - - def __str__(self): - result = ['Rules = {\n (apply to all files): [\n%s\n ],' % '\n'.join( - ' %s' % x for x in self._general_rules)] - for regexp, rules in self._specific_rules.iteritems(): - result.append(' (limited to files matching %s): [\n%s\n ]' % ( - regexp, '\n'.join(' %s' % x for x in rules))) - result.append(' }') - return '\n'.join(result) - - def AddRule(self, rule_string, source, dependee_regexp=None): - """Adds a rule for the given rule string. - - Args: - rule_string: The include_rule string read from the DEPS file to apply. - source: A string representing the location of that string (filename, etc.) - so that we can give meaningful errors. - dependee_regexp: The rule will only be applied to dependee files - whose filename (last component of their path) - matches the expression. None to match all - dependee files. - """ - (rule_type, rule_dir) = ParseRuleString(rule_string, source) - - if not dependee_regexp: - rules_to_update = self._general_rules - else: - if dependee_regexp in self._specific_rules: - rules_to_update = self._specific_rules[dependee_regexp] - else: - rules_to_update = [] - - # Remove any existing rules or sub-rules that apply. For example, if we're - # passed "foo", we should remove "foo", "foo/bar", but not "foobar". - rules_to_update = [x for x in rules_to_update - if not x.ParentOrMatch(rule_dir)] - rules_to_update.insert(0, Rule(rule_type, rule_dir, source)) - - if not dependee_regexp: - self._general_rules = rules_to_update - else: - self._specific_rules[dependee_regexp] = rules_to_update - - def RuleApplyingTo(self, include_path, dependee_path): - """Returns the rule that applies to |include_path| for a dependee - file located at |dependee_path|. - """ - dependee_filename = os.path.basename(dependee_path) - for regexp, specific_rules in self._specific_rules.iteritems(): - if re.match(regexp, dependee_filename): - for rule in specific_rules: - if rule.ChildOrMatch(include_path): - return rule - for rule in self._general_rules: - if rule.ChildOrMatch(include_path): - return rule - return MessageRule('no rule applying.') diff --git a/tools/checkdeps/testdata/DEPS b/tools/checkdeps/testdata/DEPS deleted file mode 100644 index f0657f5bc3..0000000000 --- a/tools/checkdeps/testdata/DEPS +++ /dev/null @@ -1,8 +0,0 @@ -include_rules = [ - "-tools/checkdeps/testdata/disallowed", - "+tools/checkdeps/testdata/allowed", - "-third_party/explicitly_disallowed", -] -skip_child_includes = [ - "checkdeps_test", -] diff --git a/tools/checkdeps/testdata/allowed/DEPS b/tools/checkdeps/testdata/allowed/DEPS deleted file mode 100644 index 8fb09053c1..0000000000 --- a/tools/checkdeps/testdata/allowed/DEPS +++ /dev/null @@ -1,12 +0,0 @@ -include_rules = [ - "+tools/checkdeps/testdata/disallowed/allowed", - "!tools/checkdeps/testdata/disallowed/temporarily_allowed.h", - "+third_party/allowed_may_use", -] - -specific_include_rules = { - ".*_unittest\.cc": [ - "+tools/checkdeps/testdata/disallowed/teststuff", - "!tools/checkdeps/testdata/bongo/temp_allowed_for_tests.h", - ] -} diff --git a/tools/checkdeps/testdata/allowed/foo_unittest.cc b/tools/checkdeps/testdata/allowed/foo_unittest.cc deleted file mode 100644 index 754f295eb5..0000000000 --- a/tools/checkdeps/testdata/allowed/foo_unittest.cc +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/checkdeps/testdata/disallowed/teststuff/good.h" diff --git a/tools/checkdeps/testdata/allowed/not_a_test.cc b/tools/checkdeps/testdata/allowed/not_a_test.cc deleted file mode 100644 index 7b2a105d53..0000000000 --- a/tools/checkdeps/testdata/allowed/not_a_test.cc +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/checkdeps/testdata/disallowed/teststuff/bad.h" diff --git a/tools/checkdeps/testdata/allowed/test.h b/tools/checkdeps/testdata/allowed/test.h deleted file mode 100644 index ea33090050..0000000000 --- a/tools/checkdeps/testdata/allowed/test.h +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/checkdeps/testdata/allowed/good.h" -#include "tools/checkdeps/testdata/disallowed/bad.h" -#include "tools/checkdeps/testdata/disallowed/allowed/good.h" -#include "tools/checkdeps/testdata/disallowed/temporarily_allowed.h" -#include "third_party/explicitly_disallowed/bad.h" -#include "third_party/allowed_may_use/good.h" -#include "third_party/no_rule/bad.h" diff --git a/tools/checkdeps/testdata/checkdeps_test/DEPS b/tools/checkdeps/testdata/checkdeps_test/DEPS deleted file mode 100644 index 91a9b990c3..0000000000 --- a/tools/checkdeps/testdata/checkdeps_test/DEPS +++ /dev/null @@ -1,5 +0,0 @@ -include_rules = [ - "-disallowed", - "+allowed", - "-third_party/explicitly_disallowed", -] diff --git a/tools/checkdeps/testdata/checkdeps_test/allowed/DEPS b/tools/checkdeps/testdata/checkdeps_test/allowed/DEPS deleted file mode 100644 index 14aa4d4516..0000000000 --- a/tools/checkdeps/testdata/checkdeps_test/allowed/DEPS +++ /dev/null @@ -1,11 +0,0 @@ -include_rules = [ - "+disallowed/allowed", - "!disallowed/temporarily_allowed.h", - "+third_party/allowed_may_use", -] - -specific_include_rules = { - ".*_unittest\.cc": [ - "+disallowed/teststuff", - ] -} diff --git a/tools/checkdeps/testdata/checkdeps_test/allowed/foo_unittest.cc b/tools/checkdeps/testdata/checkdeps_test/allowed/foo_unittest.cc deleted file mode 100644 index 1a507eca4e..0000000000 --- a/tools/checkdeps/testdata/checkdeps_test/allowed/foo_unittest.cc +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "disallowed/teststuff/good.h" diff --git a/tools/checkdeps/testdata/checkdeps_test/allowed/not_a_test.cc b/tools/checkdeps/testdata/checkdeps_test/allowed/not_a_test.cc deleted file mode 100644 index 4278d64763..0000000000 --- a/tools/checkdeps/testdata/checkdeps_test/allowed/not_a_test.cc +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "disallowed/teststuff/bad.h" diff --git a/tools/checkdeps/testdata/checkdeps_test/allowed/test.h b/tools/checkdeps/testdata/checkdeps_test/allowed/test.h deleted file mode 100644 index 2dbd7a38b4..0000000000 --- a/tools/checkdeps/testdata/checkdeps_test/allowed/test.h +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "allowed/good.h" -#include "disallowed/bad.h" -#include "disallowed/allowed/good.h" -#include "disallowed/temporarily_allowed.h" -#include "third_party/explicitly_disallowed/bad.h" -#include "third_party/allowed_may_use/good.h" -#include "third_party/no_rule/bad.h" diff --git a/tools/checkdeps/testdata/checkdeps_test/disallowed/allowed/DEPS b/tools/checkdeps/testdata/checkdeps_test/disallowed/allowed/DEPS deleted file mode 100644 index 2be72b8018..0000000000 --- a/tools/checkdeps/testdata/checkdeps_test/disallowed/allowed/DEPS +++ /dev/null @@ -1,3 +0,0 @@ -skip_child_includes = [ - "skipped", -] diff --git a/tools/checkdeps/testdata/checkdeps_test/disallowed/allowed/skipped/test.h b/tools/checkdeps/testdata/checkdeps_test/disallowed/allowed/skipped/test.h deleted file mode 100644 index 80105968e2..0000000000 --- a/tools/checkdeps/testdata/checkdeps_test/disallowed/allowed/skipped/test.h +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "whatever/whocares/ok.h" diff --git a/tools/checkdeps/testdata/checkdeps_test/disallowed/allowed/test.h b/tools/checkdeps/testdata/checkdeps_test/disallowed/allowed/test.h deleted file mode 100644 index aa5013d25d..0000000000 --- a/tools/checkdeps/testdata/checkdeps_test/disallowed/allowed/test.h +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "allowed/good.h" -// Always allowed to include self and parents. -#include "disallowed/good.h" -#include "disallowed/allowed/good.h" -#include "third_party/explicitly_disallowed/bad.h" -#include "third_party/allowed_may_use/bad.h" -#include "third_party/no_rule/bad.h" diff --git a/tools/checkdeps/testdata/checkdeps_test/disallowed/test.h b/tools/checkdeps/testdata/checkdeps_test/disallowed/test.h deleted file mode 100644 index 5520a68c8f..0000000000 --- a/tools/checkdeps/testdata/checkdeps_test/disallowed/test.h +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "allowed/good.h" -// Always allowed to include self. -#include "disallowed/good.h" -#include "disallowed/allowed/good.h" -#include "third_party/explicitly_disallowed/bad.h" -// Only allowed for code under allowed/. -#include "third_party/allowed_may_use/bad.h" -#include "third_party/no_rule/bad.h" diff --git a/tools/checkdeps/testdata/disallowed/allowed/DEPS b/tools/checkdeps/testdata/disallowed/allowed/DEPS deleted file mode 100644 index 2be72b8018..0000000000 --- a/tools/checkdeps/testdata/disallowed/allowed/DEPS +++ /dev/null @@ -1,3 +0,0 @@ -skip_child_includes = [ - "skipped", -] diff --git a/tools/checkdeps/testdata/disallowed/allowed/skipped/test.h b/tools/checkdeps/testdata/disallowed/allowed/skipped/test.h deleted file mode 100644 index 80105968e2..0000000000 --- a/tools/checkdeps/testdata/disallowed/allowed/skipped/test.h +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "whatever/whocares/ok.h" diff --git a/tools/checkdeps/testdata/disallowed/allowed/test.h b/tools/checkdeps/testdata/disallowed/allowed/test.h deleted file mode 100644 index f7dc822c4b..0000000000 --- a/tools/checkdeps/testdata/disallowed/allowed/test.h +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/checkdeps/testdata/allowed/good.h" -// Always allowed to include self and parents. -#include "tools/checkdeps/testdata/disallowed/good.h" -#include "tools/checkdeps/testdata/disallowed/allowed/good.h" -#include "third_party/explicitly_disallowed/bad.h" -#include "third_party/allowed_may_use/bad.h" -#include "third_party/no_rule/bad.h" diff --git a/tools/checkdeps/testdata/disallowed/foo_unittest.cc b/tools/checkdeps/testdata/disallowed/foo_unittest.cc deleted file mode 100644 index 144c05eb36..0000000000 --- a/tools/checkdeps/testdata/disallowed/foo_unittest.cc +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Not allowed for code under disallowed/ but temporarily allowed -// specifically for test code under allowed/. This regression tests a -// bug where we were taking shallow copies of rules when generating -// rules for subdirectories, so all rule objects were getting the same -// dictionary for specific rules. -#include "tools/checkdeps/testdata/disallowed/temp_allowed_for_tests.h" diff --git a/tools/checkdeps/testdata/disallowed/test.h b/tools/checkdeps/testdata/disallowed/test.h deleted file mode 100644 index d0128e3a96..0000000000 --- a/tools/checkdeps/testdata/disallowed/test.h +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/checkdeps/testdata/allowed/good.h" -// Always allowed to include self. -#include "tools/checkdeps/testdata/disallowed/good.h" -#include "tools/checkdeps/testdata/disallowed/allowed/good.h" -#include "third_party/explicitly_disallowed/bad.h" -// Only allowed for code under allowed/. -#include "third_party/allowed_may_use/bad.h" -#include "third_party/no_rule/bad.h" diff --git a/tools/checklicenses/OWNERS b/tools/checklicenses/OWNERS deleted file mode 100644 index 2abfa66e8a..0000000000 --- a/tools/checklicenses/OWNERS +++ /dev/null @@ -1,3 +0,0 @@ -set noparent -phajdan.jr@chromium.org -thestig@chromium.org diff --git a/tools/checklicenses/checklicenses.py b/tools/checklicenses/checklicenses.py deleted file mode 100755 index 25dedc2974..0000000000 --- a/tools/checklicenses/checklicenses.py +++ /dev/null @@ -1,548 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Makes sure that all files contain proper licensing information.""" - - -import optparse -import os.path -import subprocess -import sys - - -def PrintUsage(): - print """Usage: python checklicenses.py [--root ] [tocheck] - --root Specifies the repository root. This defaults to "../.." relative - to the script file. This will be correct given the normal location - of the script in "/tools/checklicenses". - - --ignore-suppressions Ignores path-specific license whitelist. Useful when - trying to remove a suppression/whitelist entry. - - tocheck Specifies the directory, relative to root, to check. This defaults - to "." so it checks everything. - -Examples: - python checklicenses.py - python checklicenses.py --root ~/chromium/src third_party""" - - -WHITELISTED_LICENSES = [ - 'Apache (v2.0)', - 'Apache (v2.0) BSD (2 clause)', - 'Apache (v2.0) GPL (v2)', - 'Apple MIT', # https://fedoraproject.org/wiki/Licensing/Apple_MIT_License - 'APSL (v2)', - 'APSL (v2) BSD (4 clause)', - 'BSD', - 'BSD (2 clause)', - 'BSD (2 clause) ISC', - 'BSD (2 clause) MIT/X11 (BSD like)', - 'BSD (3 clause)', - 'BSD (3 clause) GPL (v2)', - 'BSD (3 clause) ISC', - 'BSD (3 clause) LGPL (v2 or later)', - 'BSD (3 clause) LGPL (v2.1 or later)', - 'BSD (3 clause) MIT/X11 (BSD like)', - 'BSD (4 clause)', - 'BSD-like', - - # TODO(phajdan.jr): Make licensecheck not print BSD-like twice. - 'BSD-like MIT/X11 (BSD like)', - - 'BSL (v1.0)', - 'GPL (v2) LGPL (v2.1 or later)', - 'GPL (v2 or later) with Bison parser exception', - 'GPL (v2 or later) with libtool exception', - 'GPL (v3 or later) with Bison parser exception', - 'GPL with Bison parser exception', - 'ISC', - 'LGPL (unversioned/unknown version)', - 'LGPL (v2)', - 'LGPL (v2 or later)', - 'LGPL (v2.1)', - 'LGPL (v2.1 or later)', - 'LGPL (v3 or later)', - 'MIT/X11 (BSD like)', - 'MPL (v1.0) LGPL (v2 or later)', - 'MPL (v1.1)', - 'MPL (v1.1) BSD (3 clause) GPL (v2) LGPL (v2.1 or later)', - 'MPL (v1.1) BSD (3 clause) LGPL (v2.1 or later)', - 'MPL (v1.1) BSD-like', - 'MPL (v1.1) BSD-like GPL (unversioned/unknown version)', - 'MPL (v1.1) BSD-like GPL (v2) LGPL (v2.1 or later)', - 'MPL (v1.1) GPL (v2)', - 'MPL (v1.1) GPL (v2) LGPL (v2 or later)', - 'MPL (v1.1) GPL (v2) LGPL (v2.1 or later)', - 'MPL (v1.1) GPL (unversioned/unknown version)', - 'MPL (v1.1) LGPL (v2 or later)', - 'MPL (v1.1) LGPL (v2.1 or later)', - 'MPL (v2.0)', - 'Ms-PL', - 'Public domain', - 'Public domain BSD', - 'Public domain BSD (3 clause)', - 'Public domain BSD-like', - 'Public domain LGPL (v2.1 or later)', - 'libpng', - 'zlib/libpng', - 'SGI Free Software License B', - 'University of Illinois/NCSA Open Source License (BSD like)', -] - - -PATH_SPECIFIC_WHITELISTED_LICENSES = { - 'base/hash.cc': [ # http://crbug.com/98100 - 'UNKNOWN', - ], - 'base/third_party/icu': [ # http://crbug.com/98087 - 'UNKNOWN', - ], - - # http://code.google.com/p/google-breakpad/issues/detail?id=450 - 'breakpad/src': [ - 'UNKNOWN', - ], - - 'chrome/common/extensions/docs/examples': [ # http://crbug.com/98092 - 'UNKNOWN', - ], - 'chrome/test/data/gpu/vt': [ - 'UNKNOWN', - ], - 'chrome/test/data/layout_tests/LayoutTests': [ - 'UNKNOWN', - ], - 'courgette/third_party/bsdiff_create.cc': [ # http://crbug.com/98095 - 'UNKNOWN', - ], - 'data/mozilla_js_tests': [ - 'UNKNOWN', - ], - 'data/page_cycler': [ - 'UNKNOWN', - 'GPL (v2 or later)', - ], - 'data/tab_switching': [ - 'UNKNOWN', - ], - 'native_client': [ # http://crbug.com/98099 - 'UNKNOWN', - ], - 'native_client/toolchain': [ - 'BSD GPL (v2 or later)', - 'BSD (2 clause) GPL (v2 or later)', - 'BSD (3 clause) GPL (v2 or later)', - 'BSL (v1.0) GPL', - 'BSL (v1.0) GPL (v3.1)', - 'GPL', - 'GPL (unversioned/unknown version)', - 'GPL (v2)', - 'GPL (v2 or later)', - 'GPL (v3.1)', - 'GPL (v3 or later)', - ], - 'net/tools/spdyshark': [ - 'GPL (v2 or later)', - 'UNKNOWN', - ], - 'third_party/WebKit': [ - 'UNKNOWN', - ], - 'third_party/WebKit/Websites/webkit.org/blog/wp-content/plugins/' - 'akismet/akismet.php': [ - 'GPL (v2 or later)' - ], - 'third_party/WebKit/Source/JavaScriptCore/tests/mozilla': [ - 'GPL', - 'GPL (v2 or later)', - 'GPL (unversioned/unknown version)', - ], - 'third_party/active_doc': [ # http://crbug.com/98113 - 'UNKNOWN', - ], - - # http://code.google.com/p/angleproject/issues/detail?id=217 - 'third_party/angle': [ - 'UNKNOWN', - ], - - 'third_party/bsdiff/mbsdiff.cc': [ - 'UNKNOWN', - ], - 'third_party/bzip2': [ - 'UNKNOWN', - ], - - # http://crbug.com/222828 - # http://bugs.python.org/issue17514 - 'third_party/chromite/third_party/argparse.py': [ - 'UNKNOWN', - ], - - # Not used. http://crbug.com/156020 - # Using third_party/cros_dbus_cplusplus/cros_dbus_cplusplus.gyp instead. - 'third_party/cros_dbus_cplusplus/source/autogen.sh': [ - 'UNKNOWN', - ], - # Included in the source tree but not built. http://crbug.com/156020 - 'third_party/cros_dbus_cplusplus/source/examples': [ - 'UNKNOWN', - ], - 'third_party/devscripts': [ - 'GPL (v2 or later)', - ], - 'third_party/expat/files/lib': [ # http://crbug.com/98121 - 'UNKNOWN', - ], - 'third_party/ffmpeg': [ - 'GPL', - 'GPL (v2)', - 'GPL (v2 or later)', - 'UNKNOWN', # http://crbug.com/98123 - ], - 'third_party/findbugs/doc': [ # http://crbug.com/157206 - 'UNKNOWN', - ], - 'third_party/freetype2': [ # http://crbug.com/177319 - 'UNKNOWN', - ], - 'third_party/gles2_book': [ # http://crbug.com/98130 - 'UNKNOWN', - ], - 'third_party/gles2_conform/GTF_ES': [ # http://crbug.com/98131 - 'UNKNOWN', - ], - 'third_party/harfbuzz': [ # http://crbug.com/98133 - 'UNKNOWN', - ], - 'third_party/hunspell': [ # http://crbug.com/98134 - 'UNKNOWN', - ], - 'third_party/hyphen/hyphen.tex': [ # http://crbug.com/157375 - 'UNKNOWN', - ], - 'third_party/iccjpeg': [ # http://crbug.com/98137 - 'UNKNOWN', - ], - 'third_party/icu': [ # http://crbug.com/98301 - 'UNKNOWN', - ], - 'third_party/jemalloc': [ # http://crbug.com/98302 - 'UNKNOWN', - ], - 'third_party/JSON': [ - 'Perl', # Build-only. - # License missing upstream on 3 minor files. - 'UNKNOWN', # https://rt.cpan.org/Public/Bug/Display.html?id=85915 - ], - 'third_party/lcov': [ # http://crbug.com/98304 - 'UNKNOWN', - ], - 'third_party/lcov/contrib/galaxy/genflat.pl': [ - 'GPL (v2 or later)', - ], - 'third_party/lcov-1.9/contrib/galaxy/genflat.pl': [ - 'GPL (v2 or later)', - ], - 'third_party/libevent': [ # http://crbug.com/98309 - 'UNKNOWN', - ], - 'third_party/libjingle/source/talk': [ # http://crbug.com/98310 - 'UNKNOWN', - ], - 'third_party/libjingle/source_internal/talk': [ # http://crbug.com/98310 - 'UNKNOWN', - ], - 'third_party/libjpeg': [ # http://crbug.com/98313 - 'UNKNOWN', - ], - 'third_party/libjpeg_turbo': [ # http://crbug.com/98314 - 'UNKNOWN', - ], - 'third_party/libpng': [ # http://crbug.com/98318 - 'UNKNOWN', - ], - - # The following files lack license headers, but are trivial. - 'third_party/libusb/src/libusb/os/poll_posix.h': [ - 'UNKNOWN', - ], - 'third_party/libusb/src/libusb/version.h': [ - 'UNKNOWN', - ], - 'third_party/libusb/src/autogen.sh': [ - 'UNKNOWN', - ], - 'third_party/libusb/src/config.h': [ - 'UNKNOWN', - ], - 'third_party/libusb/src/msvc/config.h': [ - 'UNKNOWN', - ], - - 'third_party/libvpx/source': [ # http://crbug.com/98319 - 'UNKNOWN', - ], - 'third_party/libvpx/source/libvpx/examples/includes': [ - 'GPL (v2 or later)', - ], - 'third_party/libxml': [ - 'UNKNOWN', - ], - 'third_party/libxslt': [ - 'UNKNOWN', - ], - 'third_party/lzma_sdk': [ - 'UNKNOWN', - ], - 'third_party/mesa/src': [ - 'GPL (v2)', - 'GPL (v3 or later)', - 'MIT/X11 (BSD like) GPL (v3 or later) with Bison parser exception', - 'UNKNOWN', # http://crbug.com/98450 - ], - 'third_party/modp_b64': [ - 'UNKNOWN', - ], - 'third_party/npapi/npspy/extern/java': [ - 'GPL (unversioned/unknown version)', - ], - 'third_party/openmax_dl/dl' : [ - 'Khronos Group', - ], - 'third_party/openssl': [ # http://crbug.com/98451 - 'UNKNOWN', - ], - 'third_party/ots/tools/ttf-checksum.py': [ # http://code.google.com/p/ots/issues/detail?id=2 - 'UNKNOWN', - ], - 'third_party/molokocacao': [ # http://crbug.com/98453 - 'UNKNOWN', - ], - 'third_party/npapi/npspy': [ - 'UNKNOWN', - ], - 'third_party/ocmock/OCMock': [ # http://crbug.com/98454 - 'UNKNOWN', - ], - 'third_party/ply/__init__.py': [ - 'UNKNOWN', - ], - 'third_party/protobuf': [ # http://crbug.com/98455 - 'UNKNOWN', - ], - - # http://crbug.com/222831 - # https://bitbucket.org/eliben/pyelftools/issue/12 - 'third_party/pyelftools': [ - 'UNKNOWN', - ], - - 'third_party/pylib': [ - 'UNKNOWN', - ], - 'third_party/scons-2.0.1/engine/SCons': [ # http://crbug.com/98462 - 'UNKNOWN', - ], - 'third_party/simplejson': [ - 'UNKNOWN', - ], - 'third_party/skia': [ # http://crbug.com/98463 - 'UNKNOWN', - ], - 'third_party/snappy/src': [ # http://crbug.com/98464 - 'UNKNOWN', - ], - 'third_party/smhasher/src': [ # http://crbug.com/98465 - 'UNKNOWN', - ], - 'third_party/speech-dispatcher/libspeechd.h': [ - 'GPL (v2 or later)', - ], - 'third_party/sqlite': [ - 'UNKNOWN', - ], - 'third_party/swig/Lib/linkruntime.c': [ # http://crbug.com/98585 - 'UNKNOWN', - ], - 'third_party/talloc': [ - 'GPL (v3 or later)', - 'UNKNOWN', # http://crbug.com/98588 - ], - 'third_party/tcmalloc': [ - 'UNKNOWN', # http://crbug.com/98589 - ], - 'third_party/tlslite': [ - 'UNKNOWN', - ], - 'third_party/webdriver': [ # http://crbug.com/98590 - 'UNKNOWN', - ], - 'third_party/webrtc': [ # http://crbug.com/98592 - 'UNKNOWN', - ], - 'third_party/xdg-utils': [ # http://crbug.com/98593 - 'UNKNOWN', - ], - 'third_party/yasm/source': [ # http://crbug.com/98594 - 'UNKNOWN', - ], - 'third_party/zlib/contrib/minizip': [ - 'UNKNOWN', - ], - 'third_party/zlib/trees.h': [ - 'UNKNOWN', - ], - 'tools/dromaeo_benchmark_runner/dromaeo_benchmark_runner.py': [ - 'UNKNOWN', - ], - 'tools/emacs': [ # http://crbug.com/98595 - 'UNKNOWN', - ], - 'tools/grit/grit/node/custom/__init__.py': [ - 'UNKNOWN', - ], - 'tools/gyp/test': [ - 'UNKNOWN', - ], - 'tools/histograms': [ - 'UNKNOWN', - ], - 'tools/memory_watcher': [ - 'UNKNOWN', - ], - 'tools/playback_benchmark': [ - 'UNKNOWN', - ], - 'tools/python/google/__init__.py': [ - 'UNKNOWN', - ], - 'tools/site_compare': [ - 'UNKNOWN', - ], - 'tools/stats_viewer/Properties/AssemblyInfo.cs': [ - 'UNKNOWN', - ], - 'tools/symsrc/pefile.py': [ - 'UNKNOWN', - ], - 'v8/test/cctest': [ # http://crbug.com/98597 - 'UNKNOWN', - ], - 'webkit/data/ico_decoder': [ - 'UNKNOWN', - ], -} - - -def check_licenses(options, args): - # Figure out which directory we have to check. - if len(args) == 0: - # No directory to check specified, use the repository root. - start_dir = options.base_directory - elif len(args) == 1: - # Directory specified. Start here. It's supposed to be relative to the - # base directory. - start_dir = os.path.abspath(os.path.join(options.base_directory, args[0])) - else: - # More than one argument, we don't handle this. - PrintUsage() - return 1 - - print "Using base directory:", options.base_directory - print "Checking:", start_dir - print - - licensecheck_path = os.path.abspath(os.path.join(options.base_directory, - 'third_party', - 'devscripts', - 'licensecheck.pl')) - - licensecheck = subprocess.Popen([licensecheck_path, - '-l', '100', - '-r', start_dir], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - stdout, stderr = licensecheck.communicate() - if options.verbose: - print '----------- licensecheck stdout -----------' - print stdout - print '--------- end licensecheck stdout ---------' - if licensecheck.returncode != 0 or stderr: - print '----------- licensecheck stderr -----------' - print stderr - print '--------- end licensecheck stderr ---------' - print "\nFAILED\n" - return 1 - - success = True - for line in stdout.splitlines(): - filename, license = line.split(':', 1) - filename = os.path.relpath(filename.strip(), options.base_directory) - - # All files in the build output directory are generated one way or another. - # There's no need to check them. - if filename.startswith('out/') or filename.startswith('sconsbuild/'): - continue - - # For now we're just interested in the license. - license = license.replace('*No copyright*', '').strip() - - # Skip generated files. - if 'GENERATED FILE' in license: - continue - - if license in WHITELISTED_LICENSES: - continue - - if not options.ignore_suppressions: - found_path_specific = False - for prefix in PATH_SPECIFIC_WHITELISTED_LICENSES: - if (filename.startswith(prefix) and - license in PATH_SPECIFIC_WHITELISTED_LICENSES[prefix]): - found_path_specific = True - break - if found_path_specific: - continue - - print "'%s' has non-whitelisted license '%s'" % (filename, license) - success = False - - if success: - print "\nSUCCESS\n" - return 0 - else: - print "\nFAILED\n" - print "Please read", - print "http://www.chromium.org/developers/adding-3rd-party-libraries" - print "for more info how to handle the failure." - print - print "Please respect OWNERS of checklicenses.py. Changes violating" - print "this requirement may be reverted." - return 1 - - -def main(): - default_root = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..', '..')) - option_parser = optparse.OptionParser() - option_parser.add_option('--root', default=default_root, - dest='base_directory', - help='Specifies the repository root. This defaults ' - 'to "../.." relative to the script file, which ' - 'will normally be the repository root.') - option_parser.add_option('-v', '--verbose', action='store_true', - default=False, help='Print debug logging') - option_parser.add_option('--ignore-suppressions', - action='store_true', - default=False, - help='Ignore path-specific license whitelist.') - options, args = option_parser.parse_args() - return check_licenses(options, args) - - -if '__main__' == __name__: - sys.exit(main()) diff --git a/tools/checkperms/OWNERS b/tools/checkperms/OWNERS deleted file mode 100644 index 1967bf567e..0000000000 --- a/tools/checkperms/OWNERS +++ /dev/null @@ -1 +0,0 @@ -thestig@chromium.org diff --git a/tools/checkperms/PRESUBMIT.py b/tools/checkperms/PRESUBMIT.py deleted file mode 100644 index c2f93567da..0000000000 --- a/tools/checkperms/PRESUBMIT.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Top-level presubmit script for checkperms. - -See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for -details on the presubmit API built into gcl. -""" - - -def CommonChecks(input_api, output_api): - output = [] - output.extend(input_api.canned_checks.RunPylint(input_api, output_api)) - # Run it like if it were a unit test. - output.extend( - input_api.canned_checks.RunUnitTests( - input_api, output_api, ['./checkperms.py'])) - return output - - -def CheckChangeOnUpload(input_api, output_api): - return CommonChecks(input_api, output_api) - - -def CheckChangeOnCommit(input_api, output_api): - return CommonChecks(input_api, output_api) diff --git a/tools/checkperms/checkperms.py b/tools/checkperms/checkperms.py deleted file mode 100755 index f07103e379..0000000000 --- a/tools/checkperms/checkperms.py +++ /dev/null @@ -1,508 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Makes sure files have the right permissions. - -Some developers have broken SCM configurations that flip the svn:executable -permission on for no good reason. Unix developers who run ls --color will then -see .cc files in green and get confused. - -- For file extensions that must be executable, add it to EXECUTABLE_EXTENSIONS. -- For file extensions that must not be executable, add it to - NOT_EXECUTABLE_EXTENSIONS. -- To ignore all the files inside a directory, add it to IGNORED_PATHS. -- For file base name with ambiguous state and that should not be checked for - shebang, add it to IGNORED_FILENAMES. - -Any file not matching the above will be opened and looked if it has a shebang. -It this doesn't match the executable bit on the file, the file will be flagged. - -Note that all directory separators must be slashes (Unix-style) and not -backslashes. All directories should be relative to the source root and all -file paths should be only lowercase. -""" - -import logging -import optparse -import os -import stat -import subprocess -import sys - -#### USER EDITABLE SECTION STARTS HERE #### - -# Files with these extensions must have executable bit set. -EXECUTABLE_EXTENSIONS = ( - 'bat', - 'dll', - 'dylib', - 'exe', -) - -# These files must have executable bit set. -EXECUTABLE_PATHS = ( - # TODO(maruel): Detect ELF files. - 'chrome/installer/mac/sign_app.sh.in', - 'chrome/installer/mac/sign_versioned_dir.sh.in', -) - -# These files must not have the executable bit set. This is mainly a performance -# optimization as these files are not checked for shebang. The list was -# partially generated from: -# git ls-files | grep "\\." | sed 's/.*\.//' | sort | uniq -c | sort -b -g -NON_EXECUTABLE_EXTENSIONS = ( - '1', - '3ds', - 'S', - 'am', - 'applescript', - 'asm', - 'c', - 'cc', - 'cfg', - 'chromium', - 'cpp', - 'crx', - 'cs', - 'css', - 'cur', - 'def', - 'der', - 'expected', - 'gif', - 'grd', - 'gyp', - 'gypi', - 'h', - 'hh', - 'htm', - 'html', - 'hyph', - 'ico', - 'idl', - 'java', - 'jpg', - 'js', - 'json', - 'm', - 'm4', - 'mm', - 'mms', - 'mock-http-headers', - 'nmf', - 'onc', - 'pat', - 'patch', - 'pdf', - 'pem', - 'plist', - 'png', - 'proto', - 'rc', - 'rfx', - 'rgs', - 'rules', - 'spec', - 'sql', - 'srpc', - 'svg', - 'tcl', - 'test', - 'tga', - 'txt', - 'vcproj', - 'vsprops', - 'webm', - 'word', - 'xib', - 'xml', - 'xtb', - 'zip', -) - -# File names that are always whitelisted. (These are all autoconf spew.) -IGNORED_FILENAMES = ( - 'config.guess', - 'config.sub', - 'configure', - 'depcomp', - 'install-sh', - 'missing', - 'mkinstalldirs', - 'naclsdk', - 'scons', -) - -# File paths starting with one of these will be ignored as well. -# Please consider fixing your file permissions, rather than adding to this list. -IGNORED_PATHS = ( - # TODO(maruel): Detect ELF files. - 'chrome/test/data/extensions/uitest/plugins/plugin.plugin/contents/' - 'macos/testnetscapeplugin', - 'chrome/test/data/extensions/uitest/plugins_private/plugin.plugin/contents/' - 'macos/testnetscapeplugin', - 'chrome/installer/mac/sign_app.sh.in', - 'chrome/installer/mac/sign_versioned_dir.sh.in', - 'native_client_sdk/src/build_tools/sdk_tools/third_party/', - 'out/', - # TODO(maruel): Fix these. - 'third_party/android_testrunner/', - 'third_party/bintrees/', - 'third_party/closure_linter/', - 'third_party/devscripts/licensecheck.pl.vanilla', - 'third_party/hyphen/', - 'third_party/jemalloc/', - 'third_party/lcov-1.9/contrib/galaxy/conglomerate_functions.pl', - 'third_party/lcov-1.9/contrib/galaxy/gen_makefile.sh', - 'third_party/lcov/contrib/galaxy/conglomerate_functions.pl', - 'third_party/lcov/contrib/galaxy/gen_makefile.sh', - 'third_party/libevent/autogen.sh', - 'third_party/libevent/test/test.sh', - 'third_party/libxml/linux/xml2-config', - 'third_party/libxml/src/ltmain.sh', - 'third_party/mesa/', - 'third_party/protobuf/', - 'third_party/python_gflags/gflags.py', - 'third_party/sqlite/', - 'third_party/talloc/script/mksyms.sh', - 'third_party/tcmalloc/', - 'third_party/tlslite/setup.py', -) - -#### USER EDITABLE SECTION ENDS HERE #### - -assert set(EXECUTABLE_EXTENSIONS) & set(NON_EXECUTABLE_EXTENSIONS) == set() - - -def capture(cmd, cwd): - """Returns the output of a command. - - Ignores the error code or stderr. - """ - logging.debug('%s; cwd=%s' % (' '.join(cmd), cwd)) - env = os.environ.copy() - env['LANGUAGE'] = 'en_US.UTF-8' - p = subprocess.Popen( - cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd, env=env) - return p.communicate()[0] - - -def get_svn_info(dir_path): - """Returns svn meta-data for a svn checkout.""" - if not os.path.isdir(dir_path): - return {} - out = capture(['svn', 'info', '.', '--non-interactive'], dir_path) - return dict(l.split(': ', 1) for l in out.splitlines() if l) - - -def get_svn_url(dir_path): - return get_svn_info(dir_path).get('URL') - - -def get_svn_root(dir_path): - """Returns the svn checkout root or None.""" - svn_url = get_svn_url(dir_path) - if not svn_url: - return None - logging.info('svn url: %s' % svn_url) - while True: - parent = os.path.dirname(dir_path) - if parent == dir_path: - return None - svn_url = svn_url.rsplit('/', 1)[0] - if svn_url != get_svn_url(parent): - return dir_path - dir_path = parent - - -def get_git_root(dir_path): - """Returns the git checkout root or None.""" - root = capture(['git', 'rev-parse', '--show-toplevel'], dir_path).strip() - if root: - return root - - -def is_ignored(rel_path): - """Returns True if rel_path is in our whitelist of files to ignore.""" - rel_path = rel_path.lower() - return ( - os.path.basename(rel_path) in IGNORED_FILENAMES or - rel_path.startswith(IGNORED_PATHS)) - - -def must_be_executable(rel_path): - """The file name represents a file type that must have the executable bit - set. - """ - return ( - os.path.splitext(rel_path)[1][1:].lower() in EXECUTABLE_EXTENSIONS or - rel_path in EXECUTABLE_PATHS) - - -def must_not_be_executable(rel_path): - """The file name represents a file type that must not have the executable - bit set. - """ - return os.path.splitext(rel_path)[1][1:].lower() in NON_EXECUTABLE_EXTENSIONS - - -def has_executable_bit(full_path): - """Returns if any executable bit is set.""" - permission = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH - return bool(permission & os.stat(full_path).st_mode) - - -def has_shebang(full_path): - """Returns if the file starts with #!/. - - file_path is the absolute path to the file. - """ - with open(full_path, 'rb') as f: - return f.read(3) == '#!/' - -def check_file(full_path, bare_output): - """Checks file_path's permissions and returns an error if it is - inconsistent. - - It is assumed that the file is not ignored by is_ignored(). - - If the file name is matched with must_be_executable() or - must_not_be_executable(), only its executable bit is checked. - Otherwise, the 3 first bytes of the file are read to verify if it has a - shebang and compares this with the executable bit on the file. - """ - try: - bit = has_executable_bit(full_path) - except OSError: - # It's faster to catch exception than call os.path.islink(). Chromium - # tree happens to have invalid symlinks under - # third_party/openssl/openssl/test/. - return None - - if must_be_executable(full_path): - if not bit: - if bare_output: - return full_path - return '%s: Must have executable bit set' % full_path - return - if must_not_be_executable(full_path): - if bit: - if bare_output: - return full_path - return '%s: Must not have executable bit set' % full_path - return - - # For the others, it depends on the shebang. - shebang = has_shebang(full_path) - if bit != shebang: - if bare_output: - return full_path - if bit: - return '%s: Has executable bit but not shebang' % full_path - else: - return '%s: Has shebang but not executable bit' % full_path - - -def check_files(root, files, bare_output): - errors = [] - for file_path in files: - if is_ignored(file_path): - continue - - full_file_path = os.path.join(root, file_path) - - error = check_file(full_file_path, bare_output) - if error: - errors.append(error) - - return errors - -class ApiBase(object): - def __init__(self, root_dir, bare_output): - self.root_dir = root_dir - self.bare_output = bare_output - self.count = 0 - self.count_shebang = 0 - - def check_file(self, rel_path): - logging.debug('check_file(%s)' % rel_path) - self.count += 1 - - if (not must_be_executable(rel_path) and - not must_not_be_executable(rel_path)): - self.count_shebang += 1 - - full_path = os.path.join(self.root_dir, rel_path) - return check_file(full_path, self.bare_output) - - def check_dir(self, rel_path): - return self.check(rel_path) - - def check(self, start_dir): - """Check the files in start_dir, recursively check its subdirectories.""" - errors = [] - items = self.list_dir(start_dir) - logging.info('check(%s) -> %d' % (start_dir, len(items))) - for item in items: - full_path = os.path.join(self.root_dir, start_dir, item) - rel_path = full_path[len(self.root_dir) + 1:] - if is_ignored(rel_path): - continue - if os.path.isdir(full_path): - # Depth first. - errors.extend(self.check_dir(rel_path)) - else: - error = self.check_file(rel_path) - if error: - errors.append(error) - return errors - - def list_dir(self, start_dir): - """Lists all the files and directory inside start_dir.""" - return sorted( - x for x in os.listdir(os.path.join(self.root_dir, start_dir)) - if not x.startswith('.') - ) - - -class ApiSvnQuick(ApiBase): - """Returns all files in svn-versioned directories, independent of the fact if - they are versionned. - - Uses svn info in each directory to determine which directories should be - crawled. - """ - def __init__(self, *args): - super(ApiSvnQuick, self).__init__(*args) - self.url = get_svn_url(self.root_dir) - - def check_dir(self, rel_path): - url = self.url + '/' + rel_path - if get_svn_url(os.path.join(self.root_dir, rel_path)) != url: - return [] - return super(ApiSvnQuick, self).check_dir(rel_path) - - -class ApiAllFilesAtOnceBase(ApiBase): - _files = None - - def list_dir(self, start_dir): - """Lists all the files and directory inside start_dir.""" - if self._files is None: - self._files = sorted(self._get_all_files()) - if not self.bare_output: - print 'Found %s files' % len(self._files) - start_dir = start_dir[len(self.root_dir) + 1:] - return [ - x[len(start_dir):] for x in self._files if x.startswith(start_dir) - ] - - def _get_all_files(self): - """Lists all the files and directory inside self._root_dir.""" - raise NotImplementedError() - - -class ApiSvn(ApiAllFilesAtOnceBase): - """Returns all the subversion controlled files. - - Warning: svn ls is abnormally slow. - """ - def _get_all_files(self): - cmd = ['svn', 'ls', '--non-interactive', '--recursive'] - return ( - x for x in capture(cmd, self.root_dir).splitlines() - if not x.endswith(os.path.sep)) - - -class ApiGit(ApiAllFilesAtOnceBase): - def _get_all_files(self): - return capture(['git', 'ls-files'], cwd=self.root_dir).splitlines() - - -def get_scm(dir_path, bare): - """Returns a properly configured ApiBase instance.""" - cwd = os.getcwd() - root = get_svn_root(dir_path or cwd) - if root: - if not bare: - print('Found subversion checkout at %s' % root) - return ApiSvnQuick(dir_path or root, bare) - root = get_git_root(dir_path or cwd) - if root: - if not bare: - print('Found git repository at %s' % root) - return ApiGit(dir_path or root, bare) - - # Returns a non-scm aware checker. - if not bare: - print('Failed to determine the SCM for %s' % dir_path) - return ApiBase(dir_path or cwd, bare) - - -def main(): - usage = """Usage: python %prog [--root ] [tocheck] - tocheck Specifies the directory, relative to root, to check. This defaults - to "." so it checks everything. - -Examples: - python %prog - python %prog --root /path/to/source chrome""" - - parser = optparse.OptionParser(usage=usage) - parser.add_option( - '--root', - help='Specifies the repository root. This defaults ' - 'to the checkout repository root') - parser.add_option( - '-v', '--verbose', action='count', default=0, help='Print debug logging') - parser.add_option( - '--bare', - action='store_true', - default=False, - help='Prints the bare filename triggering the checks') - parser.add_option( - '--file', action='append', dest='files', - help='Specifics a list of files to check the permissions of. Only these ' - 'files will be checked') - options, args = parser.parse_args() - - levels = [logging.ERROR, logging.INFO, logging.DEBUG] - logging.basicConfig(level=levels[min(len(levels) - 1, options.verbose)]) - - if len(args) > 1: - parser.error('Too many arguments used') - - if options.root: - options.root = os.path.abspath(options.root) - - if options.files: - errors = check_files(options.root, options.files, options.bare) - print '\n'.join(errors) - return bool(errors) - - api = get_scm(options.root, options.bare) - if args: - start_dir = args[0] - else: - start_dir = api.root_dir - - errors = api.check(start_dir) - - if not options.bare: - print 'Processed %s files, %d files where tested for shebang' % ( - api.count, api.count_shebang) - - if errors: - if not options.bare: - print '\nFAILED\n' - print '\n'.join(errors) - return 1 - if not options.bare: - print '\nSUCCESS\n' - return 0 - - -if '__main__' == __name__: - sys.exit(main()) diff --git a/tools/code_coverage/coverage.py b/tools/code_coverage/coverage.py deleted file mode 100755 index a1496d7418..0000000000 --- a/tools/code_coverage/coverage.py +++ /dev/null @@ -1,359 +0,0 @@ -#!/bin/env python -# Copyright (c) 2011 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - - -"""Module to setup and generate code coverage data - -This module first sets up the environment for code coverage, instruments the -binaries, runs the tests and collects the code coverage data. - - -Usage: - coverage.py --upload= - --revision= - --src_root= - [--tools_path=] -""" - -import logging -import optparse -import os -import shutil -import subprocess -import sys -import tempfile - -import google.logging_utils -import google.process_utils as proc - - -# The list of binaries that will be instrumented for code coverage -# TODO(niranjan): Re-enable instrumentation of chrome.exe and chrome.dll once we -# resolve the issue where vsinstr.exe is confused while reading symbols. -windows_binaries = [#'chrome.exe', - #'chrome.dll', - 'unit_tests.exe', - 'automated_ui_tests.exe', - 'installer_util_unittests.exe', - 'ipc_tests.exe', - 'memory_test.exe', - 'page_cycler_tests.exe', - 'perf_tests.exe', - 'reliability_tests.exe', - 'security_tests.dll', - 'startup_tests.exe', - 'tab_switching_test.exe', - 'test_shell.exe'] - -# The list of [tests, args] that will be run. -# Failing tests have been commented out. -# TODO(niranjan): Need to add layout tests that excercise the test shell. -windows_tests = [ - ['unit_tests.exe', ''], -# ['automated_ui_tests.exe', ''], - ['installer_util_unittests.exe', ''], - ['ipc_tests.exe', ''], - ['page_cycler_tests.exe', '--gtest_filter=*File --no-sandbox'], - ['reliability_tests.exe', '--no-sandbox'], - ['startup_tests.exe', '--no-sandbox'], - ['tab_switching_test.exe', '--no-sandbox'], - ] - - -def IsWindows(): - """Checks if the current platform is Windows. - """ - return sys.platform[:3] == 'win' - - -class Coverage(object): - """Class to set up and generate code coverage. - - This class contains methods that are useful to set up the environment for - code coverage. - - Attributes: - instrumented: A boolean indicating if all the binaries have been - instrumented. - """ - - def __init__(self, - revision, - src_path = None, - tools_path = None, - archive=None): - """Init method for the Coverage class. - - Args: - revision: Revision number of the Chromium source tree. - src_path: Location of the Chromium source base. - tools_path: Location of the Visual Studio Team Tools. (Win32 only) - archive: Archive location for the intermediate .coverage results. - """ - google.logging_utils.config_root() - self.revision = revision - self.instrumented = False - self.tools_path = tools_path - self.src_path = src_path - self._dir = tempfile.mkdtemp() - self._archive = archive - - def SetUp(self, binaries): - """Set up the platform specific environment and instrument the binaries for - coverage. - - This method sets up the environment, instruments all the compiled binaries - and sets up the code coverage counters. - - Args: - binaries: List of binaries that need to be instrumented. - - Returns: - True on success. - False on error. - """ - if self.instrumented: - logging.error('Binaries already instrumented') - return False - if IsWindows(): - # Stop all previous instance of VSPerfMon counters - counters_command = ('%s -shutdown' % - (os.path.join(self.tools_path, 'vsperfcmd.exe'))) - (retcode, output) = proc.RunCommandFull(counters_command, - collect_output=True) - # TODO(niranjan): Add a check that to verify that the binaries were built - # using the /PROFILE linker flag. - if self.tools_path == None: - logging.error('Could not locate Visual Studio Team Server tools') - return False - # Remove trailing slashes - self.tools_path = self.tools_path.rstrip('\\') - # Add this to the env PATH. - os.environ['PATH'] = os.environ['PATH'] + ';' + self.tools_path - instrument_command = '%s /COVERAGE ' % (os.path.join(self.tools_path, - 'vsinstr.exe')) - for binary in binaries: - logging.info('binary = %s' % (binary)) - logging.info('instrument_command = %s' % (instrument_command)) - # Instrument each binary in the list - binary = os.path.join(self.src_path, 'chrome', 'Release', binary) - (retcode, output) = proc.RunCommandFull(instrument_command + binary, - collect_output=True) - # Check if the file has been instrumented correctly. - if output.pop().rfind('Successfully instrumented') == -1: - logging.error('Error instrumenting %s' % (binary)) - return False - # We are now ready to run tests and measure code coverage. - self.instrumented = True - return True - - def TearDown(self): - """Tear down method. - - This method shuts down the counters, and cleans up all the intermediate - artifacts. - """ - if self.instrumented == False: - return - - if IsWindows(): - # Stop counters - counters_command = ('%s -shutdown' % - (os.path.join(self.tools_path, 'vsperfcmd.exe'))) - (retcode, output) = proc.RunCommandFull(counters_command, - collect_output=True) - logging.info('Counters shut down: %s' % (output)) - # TODO(niranjan): Revert the instrumented binaries to their original - # versions. - else: - return - if self._archive: - shutil.copytree(self._dir, os.path.join(self._archive, self.revision)) - logging.info('Archived the .coverage files') - # Delete all the temp files and folders - if self._dir != None: - shutil.rmtree(self._dir, ignore_errors=True) - logging.info('Cleaned up temporary files and folders') - # Reset the instrumented flag. - self.instrumented = False - - def RunTest(self, src_root, test): - """Run tests and collect the .coverage file - - Args: - src_root: Path to the root of the source. - test: Path to the test to be run. - - Returns: - Path of the intermediate .coverage file on success. - None on error. - """ - # Generate the intermediate file name for the coverage results - test_name = os.path.split(test[0])[1].strip('.exe') - # test_command = binary + args - test_command = '%s %s' % (os.path.join(src_root, - 'chrome', - 'Release', - test[0]), - test[1]) - - coverage_file = os.path.join(self._dir, '%s_win32_%s.coverage' % - (test_name, self.revision)) - logging.info('.coverage file for test %s: %s' % (test_name, coverage_file)) - - # After all the binaries have been instrumented, we start the counters. - counters_command = ('%s -start:coverage -output:%s' % - (os.path.join(self.tools_path, 'vsperfcmd.exe'), - coverage_file)) - # Here we use subprocess.call() instead of the RunCommandFull because the - # VSPerfCmd spawns another process before terminating and this confuses - # the subprocess.Popen() used by RunCommandFull. - retcode = subprocess.call(counters_command) - - # Run the test binary - logging.info('Executing test %s: ' % test_command) - (retcode, output) = proc.RunCommandFull(test_command, collect_output=True) - if retcode != 0: # Return error if the tests fail - logging.error('One or more tests failed in %s.' % test_command) - return None - - # Stop the counters - counters_command = ('%s -shutdown' % - (os.path.join(self.tools_path, 'vsperfcmd.exe'))) - (retcode, output) = proc.RunCommandFull(counters_command, - collect_output=True) - logging.info('Counters shut down: %s' % (output)) - # Return the intermediate .coverage file - return coverage_file - - def Upload(self, list_coverage, upload_path, sym_path=None, src_root=None): - """Upload the results to the dashboard. - - This method uploads the coverage data to a dashboard where it will be - processed. On Windows, this method will first convert the .coverage file to - the lcov format. This method needs to be called before the TearDown method. - - Args: - list_coverage: The list of coverage data files to consoliate and upload. - upload_path: Destination where the coverage data will be processed. - sym_path: Symbol path for the build (Win32 only) - src_root: Root folder of the source tree (Win32 only) - - Returns: - True on success. - False on failure. - """ - if upload_path == None: - logging.info('Upload path not specified. Will not convert to LCOV') - return True - - if IsWindows(): - # Stop counters - counters_command = ('%s -shutdown' % - (os.path.join(self.tools_path, 'vsperfcmd.exe'))) - (retcode, output) = proc.RunCommandFull(counters_command, - collect_output=True) - logging.info('Counters shut down: %s' % (output)) - lcov_file = os.path.join(upload_path, 'chrome_win32_%s.lcov' % - (self.revision)) - lcov = open(lcov_file, 'w') - for coverage_file in list_coverage: - # Convert the intermediate .coverage file to lcov format - if self.tools_path == None: - logging.error('Lcov converter tool not found') - return False - self.tools_path = self.tools_path.rstrip('\\') - convert_command = ('%s -sym_path=%s -src_root=%s %s' % - (os.path.join(self.tools_path, - 'coverage_analyzer.exe'), - sym_path, - src_root, - coverage_file)) - (retcode, output) = proc.RunCommandFull(convert_command, - collect_output=True) - # TODO(niranjan): Fix this to check for the correct return code. -# if output != 0: -# logging.error('Conversion to LCOV failed. Exiting.') - tmp_lcov_file = coverage_file + '.lcov' - logging.info('Conversion to lcov complete for %s' % (coverage_file)) - # Now append this .lcov file to the cumulative lcov file - logging.info('Consolidating LCOV file: %s' % (tmp_lcov_file)) - tmp_lcov = open(tmp_lcov_file, 'r') - lcov.write(tmp_lcov.read()) - tmp_lcov.close() - lcov.close() - logging.info('LCOV file uploaded to %s' % (upload_path)) - - -def main(): - # Command line parsing - parser = optparse.OptionParser() - # Path where the .coverage to .lcov converter tools are stored. - parser.add_option('-t', - '--tools_path', - dest='tools_path', - default=None, - help='Location of the coverage tools (windows only)') - parser.add_option('-u', - '--upload', - dest='upload_path', - default=None, - help='Location where the results should be uploaded') - # We need the revision number so that we can generate the output file of the - # format chrome__.lcov - parser.add_option('-r', - '--revision', - dest='revision', - default=None, - help='Revision number of the Chromium source repo') - # Root of the source tree. Needed for converting the generated .coverage file - # on Windows to the open source lcov format. - parser.add_option('-s', - '--src_root', - dest='src_root', - default=None, - help='Root of the source repository') - parser.add_option('-a', - '--archive', - dest='archive', - default=None, - help='Archive location of the intermediate .coverage data') - - (options, args) = parser.parse_args() - - if options.revision == None: - parser.error('Revision number not specified') - if options.src_root == None: - parser.error('Source root not specified') - - if IsWindows(): - # Initialize coverage - cov = Coverage(options.revision, - options.src_root, - options.tools_path, - options.archive) - list_coverage = [] - # Instrument the binaries - if cov.SetUp(windows_binaries): - # Run all the tests - for test in windows_tests: - coverage = cov.RunTest(options.src_root, test) - if coverage == None: # Indicate failure to the buildbots. - return 1 - # Collect the intermediate file - list_coverage.append(coverage) - else: - logging.error('Error during instrumentation.') - sys.exit(1) - - cov.Upload(list_coverage, - options.upload_path, - os.path.join(options.src_root, 'chrome', 'Release'), - options.src_root) - cov.TearDown() - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/tools/code_coverage/coverage_posix.py b/tools/code_coverage/coverage_posix.py deleted file mode 100755 index f4fa56caa1..0000000000 --- a/tools/code_coverage/coverage_posix.py +++ /dev/null @@ -1,1266 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Generate and process code coverage. - -TODO(jrg): rename this from coverage_posix.py to coverage_all.py! - -Written for and tested on Mac, Linux, and Windows. To use this script -to generate coverage numbers, please run from within a gyp-generated -project. - -All platforms, to set up coverage: - cd ...../chromium ; src/tools/gyp/gyp_dogfood -Dcoverage=1 src/build/all.gyp - -Run coverage on... -Mac: - ( cd src/chrome ; xcodebuild -configuration Debug -target coverage ) -Linux: - ( cd src/chrome ; hammer coverage ) - # In particular, don't try and run 'coverage' from src/build - - ---directory=DIR: specify directory that contains gcda files, and where - a "coverage" directory will be created containing the output html. - Example name: ..../chromium/src/xcodebuild/Debug. - If not specified (e.g. buildbot) we will try and figure it out based on - other options (e.g. --target and --build-dir; see below). - ---genhtml: generate html output. If not specified only lcov is generated. - ---all_unittests: if present, run all files named *_unittests that we - can find. - ---fast_test: make the tests run real fast (just for testing) - ---strict: if a test fails, we continue happily. --strict will cause - us to die immediately. - ---trim=False: by default we trim away tests known to be problematic on - specific platforms. If set to false we do NOT trim out tests. - ---xvfb=True: By default we use Xvfb to make sure DISPLAY is valid - (Linux only). if set to False, do not use Xvfb. TODO(jrg): convert - this script from the compile stage of a builder to a - RunPythonCommandInBuildDir() command to avoid the need for this - step. - ---timeout=SECS: if a subprocess doesn't have output within SECS, - assume it's a hang. Kill it and give up. - ---bundles=BUNDLEFILE: a file containing a python list of coverage - bundles to be eval'd. Example contents of the bundlefile: - ['../base/base.gyp:base_unittests'] - This is used as part of the coverage bot. - If no other bundlefile-finding args are used (--target, - --build-dir), this is assumed to be an absolute path. - If those args are used, find BUNDLEFILE in a way consistent with - other scripts launched by buildbot. Example of another script - launched by buildbot: - http://src.chromium.org/viewvc/chrome/trunk/tools/buildbot/scripts/slave/runtest.py - ---target=NAME: specify the build target (e.g. 'Debug' or 'Release'). - This is used by buildbot scripts to help us find the output directory. - Must be used with --build-dir. - ---build-dir=DIR: According to buildbot comments, this is the name of - the directory within the buildbot working directory in which the - solution, Debug, and Release directories are found. - It's usually "src/build", but on mac it's $DIR/../xcodebuild and on - Linux it's $DIR/out. - This is used by buildbot scripts to help us find the output directory. - Must be used with --target. - ---no_exclusions: Do NOT use the exclusion list. This script keeps a - list of tests known to be problematic under coverage. For example, - ProcessUtilTest.SpawnChild will crash inside __gcov_fork() when - using the MacOS 10.6 SDK. Use of --no_exclusions prevents the use - of this exclusion list. - ---dont-clear-coverage-data: Normally we clear coverage data from - previous runs. If this arg is used we do NOT clear the coverage - data. - -Strings after all options are considered tests to run. Test names -have all text before a ':' stripped to help with gyp compatibility. -For example, ../base/base.gyp:base_unittests is interpreted as a test -named "base_unittests". -""" - -import glob -import logging -import optparse -import os -import Queue -import re -import shutil -import signal -import subprocess -import sys -import tempfile -import threading -import time -import traceback - -"""Global list of child PIDs to kill when we die.""" -gChildPIDs = [] - -"""Exclusion list. Format is - { platform: { testname: (exclusion1, exclusion2, ... ), ... } } - - Platform is a match for sys.platform and can be a list. - Matching code does an 'if sys.platform in (the key):'. - Similarly, matching does an 'if testname in thefulltestname:' - - The Chromium convention has traditionally been to place the - exclusion list in a distinct file. Unlike valgrind (which has - frequent changes when things break and are fixed), the expectation - here is that exclusions remain relatively constant (e.g. OS bugs). - If that changes, revisit the decision to place inclusions in this - script. - - Details: - ProcessUtilTest.SpawnChild: chokes in __gcov_fork on 10.6 - IPCFuzzingTest.MsgBadPayloadArgs: ditto - PanelBrowserNavigatorTest.NavigateFromCrashedPanel: Fails on coverage bot. - WebGLConformanceTests.conformance_attribs_gl_enable_vertex_attrib: Fails - with timeout (45000 ms) exceeded error. crbug.com/143248 - WebGLConformanceTests.conformance_attribs_gl_disabled_vertex_attrib: - ditto. - WebGLConformanceTests.conformance_attribs_gl_vertex_attrib_zero_issues: - ditto. - WebGLConformanceTests.conformance_attribs_gl_vertex_attrib: ditto. - WebGLConformanceTests.conformance_attribs_gl_vertexattribpointer_offsets: - ditto. - WebGLConformanceTests.conformance_attribs_gl_vertexattribpointer: ditto. - WebGLConformanceTests.conformance_buffers_buffer_bind_test: After - disabling WebGLConformanceTests specified above, this test fails when run - on local machine. - WebGLConformanceTests.conformance_buffers_buffer_data_array_buffer: ditto. - WebGLConformanceTests.conformance_buffers_index_validation_copies_indices: - ditto. - WebGLConformanceTests. - conformance_buffers_index_validation_crash_with_buffer_sub_data: ditto. - WebGLConformanceTests. - conformance_buffers_index_validation_verifies_too_many_indices: ditto. - WebGLConformanceTests. - conformance_buffers_index_validation_with_resized_buffer: ditto. - WebGLConformanceTests.conformance_canvas_buffer_offscreen_test: ditto. - WebGLConformanceTests.conformance_canvas_buffer_preserve_test: ditto. - WebGLConformanceTests.conformance_canvas_canvas_test: ditto. - WebGLConformanceTests.conformance_canvas_canvas_zero_size: ditto. - WebGLConformanceTests. - conformance_canvas_drawingbuffer_static_canvas_test: ditto. - WebGLConformanceTests.conformance_canvas_drawingbuffer_test: ditto. - PageCycler*.*: Fails on coverage bot with "Missing test directory - /....../slave/coverage-dbg-linux/build/src/data/page_cycler/moz" error. - *FrameRateCompositingTest.*: Fails with - "FATAL:chrome_content_browser_client.cc(893)] Check failed: - command_line->HasSwitch(switches::kEnableStatsTable)." - *FrameRateNoVsyncCanvasInternalTest.*: ditto. - *FrameRateGpuCanvasInternalTest.*: ditto. - IndexedDBTest.Perf: Fails with 'Timeout reached in WaitUntilCookieValue' - error. - TwoClientPasswordsSyncTest.DeleteAll: Fails on coverage bot. - MigrationTwoClientTest.MigrationHellWithoutNigori: Fails with timeout - (45000 ms) exceeded error. - TwoClientSessionsSyncTest.DeleteActiveSession: ditto. - MultipleClientSessionsSyncTest.EncryptedAndChanged: ditto. - MigrationSingleClientTest.AllTypesIndividuallyTriggerNotification: ditto. - *OldPanelResizeBrowserTest.*: crbug.com/143247 - *OldPanelDragBrowserTest.*: ditto. - *OldPanelBrowserTest.*: ditto. - *OldPanelAndDesktopNotificationTest.*: ditto. - *OldDockedPanelBrowserTest.*: ditto. - *OldDetachedPanelBrowserTest.*: ditto. - PanelDragBrowserTest.AttachWithSqueeze: ditto. - *PanelBrowserTest.*: ditto. - *DockedPanelBrowserTest.*: ditto. - *DetachedPanelBrowserTest.*: ditto. - AutomatedUITest.TheOneAndOnlyTest: crbug.com/143419 - AutomatedUITestBase.DragOut: ditto - -""" -gTestExclusions = { - 'darwin2': { 'base_unittests': ('ProcessUtilTest.SpawnChild',), - 'ipc_tests': ('IPCFuzzingTest.MsgBadPayloadArgs',), }, - 'linux2': { - 'gpu_tests': - ('WebGLConformanceTests.conformance_attribs_gl_enable_vertex_attrib', - 'WebGLConformanceTests.' - 'conformance_attribs_gl_disabled_vertex_attrib', - 'WebGLConformanceTests.' - 'conformance_attribs_gl_vertex_attrib_zero_issues', - 'WebGLConformanceTests.conformance_attribs_gl_vertex_attrib', - 'WebGLConformanceTests.' - 'conformance_attribs_gl_vertexattribpointer_offsets', - 'WebGLConformanceTests.conformance_attribs_gl_vertexattribpointer', - 'WebGLConformanceTests.conformance_buffers_buffer_bind_test', - 'WebGLConformanceTests.' - 'conformance_buffers_buffer_data_array_buffer', - 'WebGLConformanceTests.' - 'conformance_buffers_index_validation_copies_indices', - 'WebGLConformanceTests.' - 'conformance_buffers_index_validation_crash_with_buffer_sub_data', - 'WebGLConformanceTests.' - 'conformance_buffers_index_validation_verifies_too_many_indices', - 'WebGLConformanceTests.' - 'conformance_buffers_index_validation_with_resized_buffer', - 'WebGLConformanceTests.conformance_canvas_buffer_offscreen_test', - 'WebGLConformanceTests.conformance_canvas_buffer_preserve_test', - 'WebGLConformanceTests.conformance_canvas_canvas_test', - 'WebGLConformanceTests.conformance_canvas_canvas_zero_size', - 'WebGLConformanceTests.' - 'conformance_canvas_drawingbuffer_static_canvas_test', - 'WebGLConformanceTests.conformance_canvas_drawingbuffer_test',), - 'performance_ui_tests': - ('*PageCycler*.*', - '*FrameRateCompositingTest.*', - '*FrameRateNoVsyncCanvasInternalTest.*', - '*FrameRateGpuCanvasInternalTest.*', - 'IndexedDBTest.Perf',), - 'sync_integration_tests': - ('TwoClientPasswordsSyncTest.DeleteAll', - 'MigrationTwoClientTest.MigrationHellWithoutNigori', - 'TwoClientSessionsSyncTest.DeleteActiveSession', - 'MultipleClientSessionsSyncTest.EncryptedAndChanged', - 'MigrationSingleClientTest.' - 'AllTypesIndividuallyTriggerNotification',), - 'interactive_ui_tests': - ('*OldPanelResizeBrowserTest.*', - '*OldPanelDragBrowserTest.*', - '*OldPanelBrowserTest.*', - '*OldPanelAndDesktopNotificationTest.*', - '*OldDockedPanelBrowserTest.*', - '*OldDetachedPanelBrowserTest.*', - 'PanelDragBrowserTest.AttachWithSqueeze', - '*PanelBrowserTest.*', - '*DockedPanelBrowserTest.*', - '*DetachedPanelBrowserTest.*',), - 'automated_ui_tests': - ('AutomatedUITest.TheOneAndOnlyTest', - 'AutomatedUITestBase.DragOut',), }, -} - -"""Since random tests are failing/hanging on coverage bot, we are enabling - tests feature by feature. crbug.com/159748 -""" -gTestInclusions = { - 'linux2': { - 'browser_tests': - (# 'src/chrome/browser/downloads' - 'SavePageBrowserTest.*', - 'SavePageAsMHTMLBrowserTest.*', - 'DownloadQueryTest.*', - 'DownloadDangerPromptTest.*', - 'DownloadTest.*', - # 'src/chrome/browser/net' - 'CookiePolicyBrowserTest.*', - 'FtpBrowserTest.*', - 'LoadTimingObserverTest.*', - 'PredictorBrowserTest.*', - 'ProxyBrowserTest.*', - # 'src/chrome/browser/extensions' - 'Extension*.*', - 'WindowOpenPanelDisabledTest.*', - 'WindowOpenPanelTest.*', - 'WebstoreStandalone*.*', - 'CommandLineWebstoreInstall.*', - 'WebViewTest.*', - 'RequirementsCheckerBrowserTest.*', - 'ProcessManagementTest.*', - 'PlatformAppBrowserTest.*', - 'PlatformAppDevToolsBrowserTest.*', - 'LazyBackgroundPageApiTest.*', - 'IsolatedAppTest.*', - 'PanelMessagingTest.*', - 'GeolocationApiTest.*', - 'ClipboardApiTest.*', - 'ExecuteScriptApiTest.*', - 'CalculatorBrowserTest.*', - 'ChromeAppAPITest.*', - 'AppApiTest.*', - 'BlockedAppApiTest.*', - 'AppBackgroundPageApiTest.*', - 'WebNavigationApiTest.*', - 'UsbApiTest.*', - 'TabCaptureApiTest.*', - 'SystemInfo*.*', - 'SyncFileSystemApiTest.*', - 'SocketApiTest.*', - 'SerialApiTest.*', - 'RecordApiTest.*', - 'PushMessagingApiTest.*', - 'ProxySettingsApiTest.*', - 'ExperimentalApiTest.*', - 'OmniboxApiTest.*', - 'OffscreenTabsApiTest.*', - 'NotificationApiTest.*', - 'MediaGalleriesPrivateApiTest.*', - 'PlatformAppMediaGalleriesBrowserTest.*', - 'GetAuthTokenFunctionTest.*', - 'LaunchWebAuthFlowFunctionTest.*', - 'FileSystemApiTest.*', - 'ScriptBadgeApiTest.*', - 'PageAsBrowserActionApiTest.*', - 'PageActionApiTest.*', - 'BrowserActionApiTest.*', - 'DownloadExtensionTest.*', - 'DnsApiTest.*', - 'DeclarativeApiTest.*', - 'BluetoothApiTest.*', - 'AllUrlsApiTest.*', - # 'src/chrome/browser/nacl_host' - 'nacl_host.*', - # 'src/chrome/browser/automation' - 'AutomationMiscBrowserTest.*', - # 'src/chrome/browser/autofill' - 'FormStructureBrowserTest.*', - 'AutofillPopupViewBrowserTest.*', - 'AutofillTest.*', - # 'src/chrome/browser/autocomplete' - 'AutocompleteBrowserTest.*', - # 'src/chrome/browser/captive_portal' - 'CaptivePortalBrowserTest.*', - # 'src/chrome/browser/geolocation' - 'GeolocationAccessTokenStoreTest.*', - 'GeolocationBrowserTest.*', - # 'src/chrome/browser/nacl_host' - 'NaClGdbTest.*', - # 'src/chrome/browser/devtools' - 'DevToolsSanityTest.*', - 'DevToolsExtensionTest.*', - 'DevToolsExperimentalExtensionTest.*', - 'WorkerDevToolsSanityTest.*', - # 'src/chrome/browser/first_run' - 'FirstRunBrowserTest.*', - # 'src/chrome/browser/importer' - 'ToolbarImporterUtilsTest.*', - # 'src/chrome/browser/page_cycler' - 'PageCyclerBrowserTest.*', - 'PageCyclerCachedBrowserTest.*', - # 'src/chrome/browser/performance_monitor' - 'PerformanceMonitorBrowserTest.*', - 'PerformanceMonitorUncleanExitBrowserTest.*', - 'PerformanceMonitorSessionRestoreBrowserTest.*', - # 'src/chrome/browser/prerender' - 'PrerenderBrowserTest.*', - 'PrerenderBrowserTestWithNaCl.*', - 'PrerenderBrowserTestWithExtensions.*', - 'PrefetchBrowserTest.*', - 'PrefetchBrowserTestNoPrefetching.*', ), - }, -} - - -def TerminateSignalHandler(sig, stack): - """When killed, try and kill our child processes.""" - signal.signal(sig, signal.SIG_DFL) - for pid in gChildPIDs: - if 'kill' in os.__all__: # POSIX - os.kill(pid, sig) - else: - subprocess.call(['taskkill.exe', '/PID', str(pid)]) - sys.exit(0) - - -class RunTooLongException(Exception): - """Thrown when a command runs too long without output.""" - pass - -class BadUserInput(Exception): - """Thrown when arguments from the user are incorrectly formatted.""" - pass - - -class RunProgramThread(threading.Thread): - """A thread to run a subprocess. - - We want to print the output of our subprocess in real time, but also - want a timeout if there has been no output for a certain amount of - time. Normal techniques (e.g. loop in select()) aren't cross - platform enough. the function seems simple: "print output of child, kill it - if there is no output by timeout. But it was tricky to get this right - in a x-platform way (see warnings about deadlock on the python - subprocess doc page). - - """ - # Constants in our queue - PROGRESS = 0 - DONE = 1 - - def __init__(self, cmd): - super(RunProgramThread, self).__init__() - self._cmd = cmd - self._process = None - self._queue = Queue.Queue() - self._retcode = None - - def run(self): - if sys.platform in ('win32', 'cygwin'): - return self._run_windows() - else: - self._run_posix() - - def _run_windows(self): - # We need to save stdout to a temporary file because of a bug on the - # windows implementation of python which can deadlock while waiting - # for the IO to complete while writing to the PIPE and the pipe waiting - # on us and us waiting on the child process. - stdout_file = tempfile.TemporaryFile() - try: - self._process = subprocess.Popen(self._cmd, - stdin=subprocess.PIPE, - stdout=stdout_file, - stderr=subprocess.STDOUT) - gChildPIDs.append(self._process.pid) - try: - # To make sure that the buildbot don't kill us if we run too long - # without any activity on the console output, we look for progress in - # the length of the temporary file and we print what was accumulated so - # far to the output console to make the buildbot know we are making some - # progress. - previous_tell = 0 - # We will poll the process until we get a non-None return code. - self._retcode = None - while self._retcode is None: - self._retcode = self._process.poll() - current_tell = stdout_file.tell() - if current_tell > previous_tell: - # Report progress to our main thread so we don't timeout. - self._queue.put(RunProgramThread.PROGRESS) - # And print what was accumulated to far. - stdout_file.seek(previous_tell) - print stdout_file.read(current_tell - previous_tell), - previous_tell = current_tell - # Don't be selfish, let other threads do stuff while we wait for - # the process to complete. - time.sleep(0.5) - # OK, the child process has exited, let's print its output to our - # console to create debugging logs in case they get to be needed. - stdout_file.flush() - stdout_file.seek(previous_tell) - print stdout_file.read(stdout_file.tell() - previous_tell) - except IOError, e: - logging.exception('%s', e) - pass - finally: - stdout_file.close() - - # If we get here the process is done. - gChildPIDs.remove(self._process.pid) - self._queue.put(RunProgramThread.DONE) - - def _run_posix(self): - """No deadlock problem so use the simple answer. The windows solution - appears to add extra buffering which we don't want on other platforms.""" - self._process = subprocess.Popen(self._cmd, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - gChildPIDs.append(self._process.pid) - try: - while True: - line = self._process.stdout.readline() - if not line: # EOF - break - print line, - self._queue.put(RunProgramThread.PROGRESS, True) - except IOError: - pass - # If we get here the process is done. - gChildPIDs.remove(self._process.pid) - self._queue.put(RunProgramThread.DONE) - - def stop(self): - self.kill() - - def kill(self): - """Kill our running process if needed. Wait for kill to complete. - - Should be called in the PARENT thread; we do not self-kill. - Returns the return code of the process. - Safe to call even if the process is dead. - """ - if not self._process: - return self.retcode() - if 'kill' in os.__all__: # POSIX - os.kill(self._process.pid, signal.SIGKILL) - else: - subprocess.call(['taskkill.exe', '/PID', str(self._process.pid)]) - return self.retcode() - - def retcode(self): - """Return the return value of the subprocess. - - Waits for process to die but does NOT kill it explicitly. - """ - if self._retcode == None: # must be none, not 0/False - self._retcode = self._process.wait() - return self._retcode - - def RunUntilCompletion(self, timeout): - """Run thread until completion or timeout (in seconds). - - Start the thread. Let it run until completion, or until we've - spent TIMEOUT without seeing output. On timeout throw - RunTooLongException. - """ - self.start() - while True: - try: - x = self._queue.get(True, timeout) - if x == RunProgramThread.DONE: - return self.retcode() - except Queue.Empty, e: # timed out - logging.info('TIMEOUT (%d seconds exceeded with no output): killing' % - timeout) - self.kill() - raise RunTooLongException() - - -class Coverage(object): - """Doitall class for code coverage.""" - - def __init__(self, options, args): - super(Coverage, self).__init__() - logging.basicConfig(level=logging.DEBUG) - self.directory = options.directory - self.options = options - self.args = args - self.ConfirmDirectory() - self.directory_parent = os.path.dirname(self.directory) - self.output_directory = os.path.join(self.directory, 'coverage') - if not os.path.exists(self.output_directory): - os.mkdir(self.output_directory) - # The "final" lcov-format file - self.coverage_info_file = os.path.join(self.directory, 'coverage.info') - # If needed, an intermediate VSTS-format file - self.vsts_output = os.path.join(self.directory, 'coverage.vsts') - # Needed for Windows. - self.src_root = options.src_root - self.FindPrograms() - self.ConfirmPlatformAndPaths() - self.tests = [] # This can be a list of strings, lists or both. - self.xvfb_pid = 0 - self.test_files = [] # List of files with test specifications. - self.test_filters = {} # Mapping from testname->--gtest_filter arg. - logging.info('self.directory: ' + self.directory) - logging.info('self.directory_parent: ' + self.directory_parent) - - def FindInPath(self, program): - """Find program in our path. Return abs path to it, or None.""" - if not 'PATH' in os.environ: - logging.fatal('No PATH environment variable?') - sys.exit(1) - paths = os.environ['PATH'].split(os.pathsep) - for path in paths: - fullpath = os.path.join(path, program) - if os.path.exists(fullpath): - return fullpath - return None - - def FindPrograms(self): - """Find programs we may want to run.""" - if self.IsPosix(): - self.lcov_directory = os.path.join(sys.path[0], - '../../third_party/lcov/bin') - self.lcov = os.path.join(self.lcov_directory, 'lcov') - self.mcov = os.path.join(self.lcov_directory, 'mcov') - self.genhtml = os.path.join(self.lcov_directory, 'genhtml') - self.programs = [self.lcov, self.mcov, self.genhtml] - else: - # Hack to get the buildbot working. - os.environ['PATH'] += r';c:\coverage\coverage_analyzer' - os.environ['PATH'] += r';c:\coverage\performance_tools' - # (end hack) - commands = ['vsperfcmd.exe', 'vsinstr.exe', 'coverage_analyzer.exe'] - self.perf = self.FindInPath('vsperfcmd.exe') - self.instrument = self.FindInPath('vsinstr.exe') - self.analyzer = self.FindInPath('coverage_analyzer.exe') - if not self.perf or not self.instrument or not self.analyzer: - logging.fatal('Could not find Win performance commands.') - logging.fatal('Commands needed in PATH: ' + str(commands)) - sys.exit(1) - self.programs = [self.perf, self.instrument, self.analyzer] - - def PlatformBuildPrefix(self): - """Return a platform specific build directory prefix. - - This prefix is prepended to the build target (Debug, Release) to - identify output as relative to the build directory. - These values are specific to Chromium's use of gyp. - """ - if self.IsMac(): - return '../xcodebuild' - if self.IsWindows(): - return '' - else: # Linux - return '../out' # assumes make, unlike runtest.py - - def ConfirmDirectory(self): - """Confirm correctness of self.directory. - - If it exists, happiness. If not, try and figure it out in a - manner similar to FindBundlesFile(). The 'figure it out' case - happens with buildbot where the directory isn't specified - explicitly. - """ - if (not self.directory and - not (self.options.target and self.options.build_dir)): - logging.fatal('Must use --directory or (--target and --build-dir)') - sys.exit(1) - - if not self.directory: - self.directory = os.path.join(self.options.build_dir, - self.PlatformBuildPrefix(), - self.options.target) - - if os.path.exists(self.directory): - logging.info('Directory: ' + self.directory) - return - else: - logging.fatal('Directory ' + - self.directory + ' doesn\'t exist') - sys.exit(1) - - - def FindBundlesFile(self): - """Find the bundlesfile. - - The 'bundles' file can be either absolute path, or (if we are run - from buildbot) we need to find it based on other hints (--target, - --build-dir, etc). - """ - # If no bundle file, no problem! - if not self.options.bundles: - return - # If true, we're buildbot. Form a path. - # Else assume absolute. - if self.options.target and self.options.build_dir: - fullpath = os.path.join(self.options.build_dir, - self.PlatformBuildPrefix(), - self.options.target, - self.options.bundles) - self.options.bundles = fullpath - - if os.path.exists(self.options.bundles): - logging.info('BundlesFile: ' + self.options.bundles) - return - else: - logging.fatal('bundlefile ' + - self.options.bundles + ' doesn\'t exist') - sys.exit(1) - - - def FindTests(self): - """Find unit tests to run; set self.tests to this list. - - Assume all non-option items in the arg list are tests to be run. - """ - # Before we begin, find the bundles file if not an absolute path. - self.FindBundlesFile() - - # Small tests: can be run in the "chromium" directory. - # If asked, run all we can find. - if self.options.all_unittests: - self.tests += glob.glob(os.path.join(self.directory, '*_unittests')) - self.tests += glob.glob(os.path.join(self.directory, '*unit_tests')) - elif self.options.all_browsertests: - # Run all tests in browser_tests and content_browsertests. - self.tests += glob.glob(os.path.join(self.directory, 'browser_tests')) - self.tests += glob.glob(os.path.join(self.directory, - 'content_browsertests')) - - # Tests can come in as args directly, indirectly (through a file - # of test lists) or as a file of bundles. - all_testnames = self.args[:] # Copy since we might modify - - for test_file in self.options.test_files: - f = open(test_file) - for line in f: - line = re.sub(r"#.*$", "", line) - line = re.sub(r"\s*", "", line) - if re.match("\s*$"): - continue - all_testnames.append(line) - f.close() - - tests_from_bundles = None - if self.options.bundles: - try: - tests_from_bundles = eval(open(self.options.bundles).read()) - except IOError: - logging.fatal('IO error in bundle file ' + - self.options.bundles + ' (doesn\'t exist?)') - except (NameError, SyntaxError): - logging.fatal('Parse or syntax error in bundle file ' + - self.options.bundles) - if hasattr(tests_from_bundles, '__iter__'): - all_testnames += tests_from_bundles - else: - logging.fatal('Fatal error with bundle file; could not get list from' + - self.options.bundles) - sys.exit(1) - - # If told explicit tests, run those (after stripping the name as - # appropriate) - for testname in all_testnames: - mo = re.search(r"(.*)\[(.*)\]$", testname) - gtest_filter = None - if mo: - gtest_filter = mo.group(2) - testname = mo.group(1) - if ':' in testname: - testname = testname.split(':')[1] - # We need 'pyautolib' to run pyauto tests and 'pyautolib' itself is not an - # executable. So skip this test from adding into coverage_bundles.py. - if testname == 'pyautolib': - continue - self.tests += [os.path.join(self.directory, testname)] - if gtest_filter: - self.test_filters[testname] = gtest_filter - - # Add 'src/test/functional/pyauto_functional.py' to self.tests. - # This file with '-v --suite=CODE_COVERAGE' arguments runs all pyauto tests. - # Pyauto tests are failing randomly on coverage bots. So excluding them. - # self.tests += [['src/chrome/test/functional/pyauto_functional.py', - # '-v', - # '--suite=CODE_COVERAGE']] - - # Medium tests? - # Not sure all of these work yet (e.g. page_cycler_tests) - # self.tests += glob.glob(os.path.join(self.directory, '*_tests')) - - # If needed, append .exe to tests since vsinstr.exe likes it that - # way. - if self.IsWindows(): - for ind in range(len(self.tests)): - test = self.tests[ind] - test_exe = test + '.exe' - if not test.endswith('.exe') and os.path.exists(test_exe): - self.tests[ind] = test_exe - - def TrimTests(self): - """Trim specific tests for each platform.""" - if self.IsWindows(): - return - # TODO(jrg): remove when not needed - inclusion = ['unit_tests'] - keep = [] - for test in self.tests: - for i in inclusion: - if i in test: - keep.append(test) - self.tests = keep - logging.info('After trimming tests we have ' + ' '.join(self.tests)) - return - if self.IsLinux(): - # self.tests = filter(lambda t: t.endswith('base_unittests'), self.tests) - return - if self.IsMac(): - exclusion = ['automated_ui_tests'] - punted = [] - for test in self.tests: - for e in exclusion: - if test.endswith(e): - punted.append(test) - self.tests = filter(lambda t: t not in punted, self.tests) - if punted: - logging.info('Tests trimmed out: ' + str(punted)) - - def ConfirmPlatformAndPaths(self): - """Confirm OS and paths (e.g. lcov).""" - for program in self.programs: - if not os.path.exists(program): - logging.fatal('Program missing: ' + program) - sys.exit(1) - - def Run(self, cmdlist, ignore_error=False, ignore_retcode=None, - explanation=None): - """Run the command list; exit fatally on error. - - Args: - cmdlist: a list of commands (e.g. to pass to subprocess.call) - ignore_error: if True log an error; if False then exit. - ignore_retcode: if retcode is non-zero, exit unless we ignore. - - Returns: process return code. - Throws: RunTooLongException if the process does not produce output - within TIMEOUT seconds; timeout is specified as a command line - option to the Coverage class and is set on init. - """ - logging.info('Running ' + str(cmdlist)) - t = RunProgramThread(cmdlist) - retcode = t.RunUntilCompletion(self.options.timeout) - - if retcode: - if ignore_error or retcode == ignore_retcode: - logging.warning('COVERAGE: %s unhappy but errors ignored %s' % - (str(cmdlist), explanation or '')) - else: - logging.fatal('COVERAGE: %s failed; return code: %d' % - (str(cmdlist), retcode)) - sys.exit(retcode) - return retcode - - def IsPosix(self): - """Return True if we are POSIX.""" - return self.IsMac() or self.IsLinux() - - def IsMac(self): - return sys.platform == 'darwin' - - def IsLinux(self): - return sys.platform.startswith('linux') - - def IsWindows(self): - """Return True if we are Windows.""" - return sys.platform in ('win32', 'cygwin') - - def ClearData(self): - """Clear old gcda files and old coverage info files.""" - if self.options.dont_clear_coverage_data: - print 'Clearing of coverage data NOT performed.' - return - print 'Clearing coverage data from previous runs.' - if os.path.exists(self.coverage_info_file): - os.remove(self.coverage_info_file) - if self.IsPosix(): - subprocess.call([self.lcov, - '--directory', self.directory_parent, - '--zerocounters']) - shutil.rmtree(os.path.join(self.directory, 'coverage')) - if self.options.all_unittests: - if os.path.exists(os.path.join(self.directory, 'unittests_coverage')): - shutil.rmtree(os.path.join(self.directory, 'unittests_coverage')) - elif self.options.all_browsertests: - if os.path.exists(os.path.join(self.directory, - 'browsertests_coverage')): - shutil.rmtree(os.path.join(self.directory, 'browsertests_coverage')) - else: - if os.path.exists(os.path.join(self.directory, 'total_coverage')): - shutil.rmtree(os.path.join(self.directory, 'total_coverage')) - - def BeforeRunOneTest(self, testname): - """Do things before running each test.""" - if not self.IsWindows(): - return - # Stop old counters if needed - cmdlist = [self.perf, '-shutdown'] - self.Run(cmdlist, ignore_error=True) - # Instrument binaries - for fulltest in self.tests: - if os.path.exists(fulltest): - # See http://support.microsoft.com/kb/939818 for details on args - cmdlist = [self.instrument, '/d:ignorecverr', '/COVERAGE', fulltest] - self.Run(cmdlist, ignore_retcode=4, - explanation='OK with a multiple-instrument') - # Start new counters - cmdlist = [self.perf, '-start:coverage', '-output:' + self.vsts_output] - self.Run(cmdlist) - - def BeforeRunAllTests(self): - """Called right before we run all tests.""" - if self.IsLinux() and self.options.xvfb: - self.StartXvfb() - - def GtestFilter(self, fulltest, excl=None): - """Return a --gtest_filter=BLAH for this test. - - Args: - fulltest: full name of test executable - exclusions: the exclusions list. Only set in a unit test; - else uses gTestExclusions. - Returns: - String of the form '--gtest_filter=BLAH', or None. - """ - positive_gfilter_list = [] - negative_gfilter_list = [] - - # Exclude all flaky, failing, disabled and maybe tests; - # they don't count for code coverage. - negative_gfilter_list += ('*.FLAKY_*', '*.FAILS_*', - '*.DISABLED_*', '*.MAYBE_*') - - if not self.options.no_exclusions: - exclusions = excl or gTestExclusions - excldict = exclusions.get(sys.platform) - if excldict: - for test in excldict.keys(): - # example: if base_unittests in ../blah/blah/base_unittests.exe - if test in fulltest: - negative_gfilter_list += excldict[test] - - inclusions = gTestInclusions - include_dict = inclusions.get(sys.platform) - if include_dict: - for test in include_dict.keys(): - if test in fulltest: - positive_gfilter_list += include_dict[test] - - fulltest_basename = os.path.basename(fulltest) - if fulltest_basename in self.test_filters: - specific_test_filters = self.test_filters[fulltest_basename].split('-') - if len(specific_test_filters) > 2: - logging.error('Multiple "-" symbols in filter list: %s' % - self.test_filters[fulltest_basename]) - raise BadUserInput() - if len(specific_test_filters) == 2: - # Remove trailing ':' - specific_test_filters[0] = specific_test_filters[0][:-1] - - if specific_test_filters[0]: # Test for no positive filters. - positive_gfilter_list += specific_test_filters[0].split(':') - if len(specific_test_filters) > 1: - negative_gfilter_list += specific_test_filters[1].split(':') - - if not positive_gfilter_list and not negative_gfilter_list: - return None - - result = '--gtest_filter=' - if positive_gfilter_list: - result += ':'.join(positive_gfilter_list) - if negative_gfilter_list: - if positive_gfilter_list: result += ':' - result += '-' + ':'.join(negative_gfilter_list) - return result - - def RunTests(self): - """Run all unit tests and generate appropriate lcov files.""" - self.BeforeRunAllTests() - for fulltest in self.tests: - if type(fulltest) is str: - if not os.path.exists(fulltest): - logging.info(fulltest + ' does not exist') - if self.options.strict: - sys.exit(2) - else: - logging.info('%s path exists' % fulltest) - cmdlist = [fulltest, '--gtest_print_time'] - - # If asked, make this REAL fast for testing. - if self.options.fast_test: - logging.info('Running as a FAST test for testing') - # cmdlist.append('--gtest_filter=RenderWidgetHost*') - # cmdlist.append('--gtest_filter=CommandLine*') - cmdlist.append('--gtest_filter=C*') - - # Possibly add a test-specific --gtest_filter - filter = self.GtestFilter(fulltest) - if filter: - cmdlist.append(filter) - elif type(fulltest) is list: - cmdlist = fulltest - - self.BeforeRunOneTest(fulltest) - logging.info('Running test ' + str(cmdlist)) - try: - retcode = self.Run(cmdlist, ignore_retcode=True) - except SystemExit: # e.g. sys.exit() was called somewhere in here - raise - except: # can't "except WindowsError" since script runs on non-Windows - logging.info('EXCEPTION while running a unit test') - logging.info(traceback.format_exc()) - retcode = 999 - self.AfterRunOneTest(fulltest) - - if retcode: - logging.info('COVERAGE: test %s failed; return code: %d.' % - (fulltest, retcode)) - if self.options.strict: - logging.fatal('Test failure is fatal.') - sys.exit(retcode) - self.AfterRunAllTests() - - def AfterRunOneTest(self, testname): - """Do things right after running each test.""" - if not self.IsWindows(): - return - # Stop counters - cmdlist = [self.perf, '-shutdown'] - self.Run(cmdlist) - full_output = self.vsts_output + '.coverage' - shutil.move(full_output, self.vsts_output) - # generate lcov! - self.GenerateLcovWindows(testname) - - def AfterRunAllTests(self): - """Do things right after running ALL tests.""" - # On POSIX we can do it all at once without running out of memory. - # This contrasts with Windows where we must do it after each test. - if self.IsPosix(): - self.GenerateLcovPosix() - # Only on Linux do we have the Xvfb step. - if self.IsLinux() and self.options.xvfb: - self.StopXvfb() - - def StartXvfb(self): - """Start Xvfb and set an appropriate DISPLAY environment. Linux only. - - Copied from http://src.chromium.org/viewvc/chrome/trunk/tools/buildbot/ - scripts/slave/slave_utils.py?view=markup - with some simplifications (e.g. no need to use xdisplaycheck, save - pid in var not file, etc) - """ - logging.info('Xvfb: starting') - proc = subprocess.Popen(["Xvfb", ":9", "-screen", "0", "1024x768x24", - "-ac"], - stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - self.xvfb_pid = proc.pid - if not self.xvfb_pid: - logging.info('Could not start Xvfb') - return - os.environ['DISPLAY'] = ":9" - # Now confirm, giving a chance for it to start if needed. - logging.info('Xvfb: confirming') - for test in range(10): - proc = subprocess.Popen('xdpyinfo >/dev/null', shell=True) - pid, retcode = os.waitpid(proc.pid, 0) - if retcode == 0: - break - time.sleep(0.5) - if retcode != 0: - logging.info('Warning: could not confirm Xvfb happiness') - else: - logging.info('Xvfb: OK') - - def StopXvfb(self): - """Stop Xvfb if needed. Linux only.""" - if self.xvfb_pid: - logging.info('Xvfb: killing') - try: - os.kill(self.xvfb_pid, signal.SIGKILL) - except: - pass - del os.environ['DISPLAY'] - self.xvfb_pid = 0 - - def CopyCoverageFileToDestination(self, coverage_folder): - coverage_dir = os.path.join(self.directory, coverage_folder) - if not os.path.exists(coverage_dir): - os.makedirs(coverage_dir) - shutil.copyfile(self.coverage_info_file, os.path.join(coverage_dir, - 'coverage.info')) - - def GenerateLcovPosix(self): - """Convert profile data to lcov on Mac or Linux.""" - start_dir = os.getcwd() - logging.info('GenerateLcovPosix: start_dir=' + start_dir) - if self.IsLinux(): - # With Linux/make (e.g. the coverage_run target), the current - # directory for this command is .../build/src/chrome but we need - # to be in .../build/src for the relative path of source files - # to be correct. However, when run from buildbot, the current - # directory is .../build. Accommodate. - # On Mac source files are compiled with abs paths so this isn't - # a problem. - # This is a bit of a hack. The best answer is to require this - # script be run in a specific directory for all cases (from - # Makefile or from buildbot). - if start_dir.endswith('chrome'): - logging.info('coverage_posix.py: doing a "cd .." ' - 'to accomodate Linux/make PWD') - os.chdir('..') - elif start_dir.endswith('build'): - logging.info('coverage_posix.py: doing a "cd src" ' - 'to accomodate buildbot PWD') - os.chdir('src') - else: - logging.info('coverage_posix.py: NOT changing directory.') - elif self.IsMac(): - pass - - command = [self.mcov, - '--directory', - os.path.join(start_dir, self.directory_parent), - '--output', - os.path.join(start_dir, self.coverage_info_file)] - logging.info('Assembly command: ' + ' '.join(command)) - retcode = subprocess.call(command) - if retcode: - logging.fatal('COVERAGE: %s failed; return code: %d' % - (command[0], retcode)) - if self.options.strict: - sys.exit(retcode) - if self.IsLinux(): - os.chdir(start_dir) - - # Copy the unittests coverage information to a different folder. - if self.options.all_unittests: - self.CopyCoverageFileToDestination('unittests_coverage') - elif self.options.all_browsertests: - # Save browsertests only coverage information. - self.CopyCoverageFileToDestination('browsertests_coverage') - else: - # Save the overall coverage information. - self.CopyCoverageFileToDestination('total_coverage') - - if not os.path.exists(self.coverage_info_file): - logging.fatal('%s was not created. Coverage run failed.' % - self.coverage_info_file) - sys.exit(1) - - def GenerateLcovWindows(self, testname=None): - """Convert VSTS format to lcov. Appends coverage data to sum file.""" - lcov_file = self.vsts_output + '.lcov' - if os.path.exists(lcov_file): - os.remove(lcov_file) - # generates the file (self.vsts_output + ".lcov") - - cmdlist = [self.analyzer, - '-sym_path=' + self.directory, - '-src_root=' + self.src_root, - '-noxml', - self.vsts_output] - self.Run(cmdlist) - if not os.path.exists(lcov_file): - logging.fatal('Output file %s not created' % lcov_file) - sys.exit(1) - logging.info('Appending lcov for test %s to %s' % - (testname, self.coverage_info_file)) - size_before = 0 - if os.path.exists(self.coverage_info_file): - size_before = os.stat(self.coverage_info_file).st_size - src = open(lcov_file, 'r') - dst = open(self.coverage_info_file, 'a') - dst.write(src.read()) - src.close() - dst.close() - size_after = os.stat(self.coverage_info_file).st_size - logging.info('Lcov file growth for %s: %d --> %d' % - (self.coverage_info_file, size_before, size_after)) - - def GenerateHtml(self): - """Convert lcov to html.""" - # TODO(jrg): This isn't happy when run with unit_tests since V8 has a - # different "base" so V8 includes can't be found in ".". Fix. - command = [self.genhtml, - self.coverage_info_file, - '--output-directory', - self.output_directory] - print >>sys.stderr, 'html generation command: ' + ' '.join(command) - retcode = subprocess.call(command) - if retcode: - logging.fatal('COVERAGE: %s failed; return code: %d' % - (command[0], retcode)) - if self.options.strict: - sys.exit(retcode) - -def CoverageOptionParser(): - """Return an optparse.OptionParser() suitable for Coverage object creation.""" - parser = optparse.OptionParser() - parser.add_option('-d', - '--directory', - dest='directory', - default=None, - help='Directory of unit test files') - parser.add_option('-a', - '--all_unittests', - dest='all_unittests', - default=False, - help='Run all tests we can find (*_unittests)') - parser.add_option('-b', - '--all_browsertests', - dest='all_browsertests', - default=False, - help='Run all tests in browser_tests ' - 'and content_browsertests') - parser.add_option('-g', - '--genhtml', - dest='genhtml', - default=False, - help='Generate html from lcov output') - parser.add_option('-f', - '--fast_test', - dest='fast_test', - default=False, - help='Make the tests run REAL fast by doing little.') - parser.add_option('-s', - '--strict', - dest='strict', - default=False, - help='Be strict and die on test failure.') - parser.add_option('-S', - '--src_root', - dest='src_root', - default='.', - help='Source root (only used on Windows)') - parser.add_option('-t', - '--trim', - dest='trim', - default=True, - help='Trim out tests? Default True.') - parser.add_option('-x', - '--xvfb', - dest='xvfb', - default=True, - help='Use Xvfb for tests? Default True.') - parser.add_option('-T', - '--timeout', - dest='timeout', - default=5.0 * 60.0, - type="int", - help='Timeout before bailing if a subprocess has no output.' - ' Default is 5min (Buildbot is 10min.)') - parser.add_option('-B', - '--bundles', - dest='bundles', - default=None, - help='Filename of bundles for coverage.') - parser.add_option('--build-dir', - dest='build_dir', - default=None, - help=('Working directory for buildbot build.' - 'used for finding bundlefile.')) - parser.add_option('--target', - dest='target', - default=None, - help=('Buildbot build target; ' - 'used for finding bundlefile (e.g. Debug)')) - parser.add_option('--no_exclusions', - dest='no_exclusions', - default=None, - help=('Disable the exclusion list.')) - parser.add_option('--dont-clear-coverage-data', - dest='dont_clear_coverage_data', - default=False, - action='store_true', - help=('Turn off clearing of cov data from a prev run')) - parser.add_option('-F', - '--test-file', - dest="test_files", - default=[], - action='append', - help=('Specify a file from which tests to be run will ' + - 'be extracted')) - return parser - - -def main(): - # Print out the args to help someone do it by hand if needed - print >>sys.stderr, sys.argv - - # Try and clean up nice if we're killed by buildbot, Ctrl-C, ... - signal.signal(signal.SIGINT, TerminateSignalHandler) - signal.signal(signal.SIGTERM, TerminateSignalHandler) - - parser = CoverageOptionParser() - (options, args) = parser.parse_args() - if options.all_unittests and options.all_browsertests: - print 'Error! Can not have all_unittests and all_browsertests together!' - sys.exit(1) - coverage = Coverage(options, args) - coverage.ClearData() - coverage.FindTests() - if options.trim: - coverage.TrimTests() - coverage.RunTests() - if options.genhtml: - coverage.GenerateHtml() - return 0 - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/tools/code_coverage/coverage_posix_unittest.py b/tools/code_coverage/coverage_posix_unittest.py deleted file mode 100755 index 3164cd3359..0000000000 --- a/tools/code_coverage/coverage_posix_unittest.py +++ /dev/null @@ -1,142 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2010 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Unit tests for coverage_posix.py. - -Run a single test with a command such as: - ./coverage_posix_unittest.py CoveragePosixTest.testFindTestsAsArgs - -Waring that running a single test like that may interfere with the arg -parsing tests, since coverage_posix.py uses optparse.OptionParser() -which references globals. -""" - -import coverage_posix as coverage -import os -import sys -import tempfile -import unittest - -class CoveragePosixTest(unittest.TestCase): - - - def setUp(self): - self.parseArgs() - self.sample_test_names = ['zippy_tests', '../base/base.gyp:base_unittests'] - - def confirmSampleTestsArePresent(self, tests): - """Confirm the tests in self.sample_test_names are in some form in 'tests'. - - The Coverage object can munge them (e.g. add .exe to the end as needed. - Helper function for arg parsing, bundle file tests. - - Args: - tests: the parsed tests from a Coverage object. - """ - for simple_test_name in ('zippy_tests', 'base_unittests'): - found = False - for item in tests: - if simple_test_name in item: - found = True - break - self.assertTrue(found) - for not_test_name in ('kablammo', 'not_a_unittest'): - found = False - for item in tests: - if not_test_name in item: - found = True - break - self.assertFalse(found) - - def parseArgs(self): - """Setup and process arg parsing.""" - self.parser = coverage.CoverageOptionParser() - (self.options, self.args) = self.parser.parse_args() - self.options.directory = '.' - - def testSanity(self): - """Sanity check we're able to actually run the tests. - - Simply creating a Coverage instance checks a few things (e.g. on - Windows that the coverage tools can be found).""" - c = coverage.Coverage(self.options, self.args) - - def testRunBasicProcess(self): - """Test a simple run of a subprocess.""" - c = coverage.Coverage(self.options, self.args) - for code in range(2): - retcode = c.Run([sys.executable, '-u', '-c', - 'import sys; sys.exit(%d)' % code], - ignore_error=True) - self.assertEqual(code, retcode) - - def testRunSlowProcess(self): - """Test program which prints slowly but doesn't hit our timeout. - - Overall runtime is longer than the timeout but output lines - trickle in keeping things alive. - """ - self.options.timeout = 2.5 - c = coverage.Coverage(self.options, self.args) - slowscript = ('import sys, time\n' - 'for x in range(10):\n' - ' time.sleep(0.5)\n' - ' print "hi mom"\n' - 'sys.exit(0)\n') - retcode = c.Run([sys.executable, '-u', '-c', slowscript]) - self.assertEqual(0, retcode) - - def testRunExcessivelySlowProcess(self): - """Test program which DOES hit our timeout. - - Initial lines should print but quickly it takes too long and - should be killed. - """ - self.options.timeout = 2.5 - c = coverage.Coverage(self.options, self.args) - slowscript = ('import time\n' - 'for x in range(1,10):\n' - ' print "sleeping for %d" % x\n' - ' time.sleep(x)\n') - self.assertRaises(Exception, - c.Run, - [sys.executable, '-u', '-c', slowscript]) - - def testFindTestsAsArgs(self): - """Test finding of tests passed as args.""" - self.args += '--' - self.args += self.sample_test_names - c = coverage.Coverage(self.options, self.args) - c.FindTests() - self.confirmSampleTestsArePresent(c.tests) - - def testFindTestsFromBundleFile(self): - """Test finding of tests from a bundlefile.""" - (fd, filename) = tempfile.mkstemp() - f = os.fdopen(fd, 'w') - f.write(str(self.sample_test_names)) - f.close() - self.options.bundles = filename - c = coverage.Coverage(self.options, self.args) - c.FindTests() - self.confirmSampleTestsArePresent(c.tests) - os.unlink(filename) - - def testExclusionList(self): - """Test the gtest_filter exclusion list.""" - c = coverage.Coverage(self.options, self.args) - self.assertFalse(c.GtestFilter('doesnotexist_test')) - fake_exclusions = { sys.platform: { 'foobar': - ('a','b'), - 'doesnotexist_test': - ('Evil.Crash','Naughty.Test') } } - self.assertFalse(c.GtestFilter('barfoo')) - filter = c.GtestFilter('doesnotexist_test', fake_exclusions) - self.assertEquals('--gtest_filter=-Evil.Crash:-Naughty.Test', filter) - - - -if __name__ == '__main__': - unittest.main() diff --git a/tools/code_coverage/croc.css b/tools/code_coverage/croc.css deleted file mode 100644 index 071822dafa..0000000000 --- a/tools/code_coverage/croc.css +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2012 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* - * croc.css - styles for croc HTML output - */ - -body { - font-family:arial; -} - -table { - border-collapse:collapse; - border-width:0px; - border-style:solid; -} - -thead { - background-color:#C0C0E0; - text-align:center; -} - -td { - padding-right:10px; - padding-left:10px; - font-size:small; - border-width:1px; - border-style:solid; - border-color:black; -} - -td.secdesc { - text-align:center; - font-size:medium; - font-weight:bold; - border-width:0px; - border-style:none; - padding-top:10px; - padding-bottom:5px; -} - -td.section { - background-color:#D0D0F0; - text-align:center; -} - -td.stat { - text-align:center; -} - -td.number { - text-align:right; -} - -td.graph { - /* Hide the dummy character */ - color:#FFFFFF; - padding-left:6px; -} - -td.high_pct { - text-align:right; - background-color:#B0FFB0; -} -td.mid_pct { - text-align:right; - background-color:#FFFF90; -} -td.low_pct { - text-align:right; - background-color:#FFB0B0; -} - - -span.missing { - background-color:#FFB0B0; -} -span.instr { - background-color:#FFFF90; -} -span.covered { - background-color:#B0FFB0; -} - -span.g_missing { - background-color:#FF4040; -} -span.g_instr { - background-color:#FFFF00; -} -span.g_covered { - background-color:#40FF40; -} - -p.time { - padding-top:10px; - font-size:small; - font-style:italic; -} diff --git a/tools/code_coverage/croc.py b/tools/code_coverage/croc.py deleted file mode 100755 index 1b9908a5f8..0000000000 --- a/tools/code_coverage/croc.py +++ /dev/null @@ -1,722 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Crocodile - compute coverage numbers for Chrome coverage dashboard.""" - -import optparse -import os -import platform -import re -import sys -import croc_html -import croc_scan - - -class CrocError(Exception): - """Coverage error.""" - - -class CrocStatError(CrocError): - """Error evaluating coverage stat.""" - -#------------------------------------------------------------------------------ - - -class CoverageStats(dict): - """Coverage statistics.""" - - # Default dictionary values for this stat. - DEFAULTS = { 'files_covered': 0, - 'files_instrumented': 0, - 'files_executable': 0, - 'lines_covered': 0, - 'lines_instrumented': 0, - 'lines_executable': 0 } - - def Add(self, coverage_stats): - """Adds a contribution from another coverage stats dict. - - Args: - coverage_stats: Statistics to add to this one. - """ - for k, v in coverage_stats.iteritems(): - if k in self: - self[k] += v - else: - self[k] = v - - def AddDefaults(self): - """Add some default stats which might be assumed present. - - Do not clobber if already present. Adds resilience when evaling a - croc file which expects certain stats to exist.""" - for k, v in self.DEFAULTS.iteritems(): - if not k in self: - self[k] = v - -#------------------------------------------------------------------------------ - - -class CoveredFile(object): - """Information about a single covered file.""" - - def __init__(self, filename, **kwargs): - """Constructor. - - Args: - filename: Full path to file, '/'-delimited. - kwargs: Keyword args are attributes for file. - """ - self.filename = filename - self.attrs = dict(kwargs) - - # Move these to attrs? - self.local_path = None # Local path to file - self.in_lcov = False # Is file instrumented? - - # No coverage data for file yet - self.lines = {} # line_no -> None=executable, 0=instrumented, 1=covered - self.stats = CoverageStats() - - def UpdateCoverage(self): - """Updates the coverage summary based on covered lines.""" - exe = instr = cov = 0 - for l in self.lines.itervalues(): - exe += 1 - if l is not None: - instr += 1 - if l == 1: - cov += 1 - - # Add stats that always exist - self.stats = CoverageStats(lines_executable=exe, - lines_instrumented=instr, - lines_covered=cov, - files_executable=1) - - # Add conditional stats - if cov: - self.stats['files_covered'] = 1 - if instr or self.in_lcov: - self.stats['files_instrumented'] = 1 - -#------------------------------------------------------------------------------ - - -class CoveredDir(object): - """Information about a directory containing covered files.""" - - def __init__(self, dirpath): - """Constructor. - - Args: - dirpath: Full path of directory, '/'-delimited. - """ - self.dirpath = dirpath - - # List of covered files directly in this dir, indexed by filename (not - # full path) - self.files = {} - - # List of subdirs, indexed by filename (not full path) - self.subdirs = {} - - # Dict of CoverageStats objects summarizing all children, indexed by group - self.stats_by_group = {'all': CoverageStats()} - # TODO: by language - - def GetTree(self, indent=''): - """Recursively gets stats for the directory and its children. - - Args: - indent: indent prefix string. - - Returns: - The tree as a string. - """ - dest = [] - - # Compile all groupstats - groupstats = [] - for group in sorted(self.stats_by_group): - s = self.stats_by_group[group] - if not s.get('lines_executable'): - continue # Skip groups with no executable lines - groupstats.append('%s:%d/%d/%d' % ( - group, s.get('lines_covered', 0), - s.get('lines_instrumented', 0), - s.get('lines_executable', 0))) - - outline = '%s%-30s %s' % (indent, - os.path.split(self.dirpath)[1] + '/', - ' '.join(groupstats)) - dest.append(outline.rstrip()) - - for d in sorted(self.subdirs): - dest.append(self.subdirs[d].GetTree(indent=indent + ' ')) - - return '\n'.join(dest) - -#------------------------------------------------------------------------------ - - -class Coverage(object): - """Code coverage for a group of files.""" - - def __init__(self): - """Constructor.""" - self.files = {} # Map filename --> CoverageFile - self.root_dirs = [] # (root, altname) - self.rules = [] # (regexp, dict of RHS attrs) - self.tree = CoveredDir('') - self.print_stats = [] # Dicts of args to PrintStat() - - # Functions which need to be replaced for unit testing - self.add_files_walk = os.walk # Walk function for AddFiles() - self.scan_file = croc_scan.ScanFile # Source scanner for AddFiles() - - def CleanupFilename(self, filename): - """Cleans up a filename. - - Args: - filename: Input filename. - - Returns: - The cleaned up filename. - - Changes all path separators to '/'. - Makes relative paths (those starting with '../' or './' absolute. - Replaces all instances of root dirs with alternate names. - """ - # Change path separators - filename = filename.replace('\\', '/') - - # Windows doesn't care about case sensitivity. - if platform.system() in ['Windows', 'Microsoft']: - filename = filename.lower() - - # If path is relative, make it absolute - # TODO: Perhaps we should default to relative instead, and only understand - # absolute to be files starting with '\', '/', or '[A-Za-z]:'? - if filename.split('/')[0] in ('.', '..'): - filename = os.path.abspath(filename).replace('\\', '/') - - # Replace alternate roots - for root, alt_name in self.root_dirs: - # Windows doesn't care about case sensitivity. - if platform.system() in ['Windows', 'Microsoft']: - root = root.lower() - filename = re.sub('^' + re.escape(root) + '(?=(/|$))', - alt_name, filename) - return filename - - def ClassifyFile(self, filename): - """Applies rules to a filename, to see if we care about it. - - Args: - filename: Input filename. - - Returns: - A dict of attributes for the file, accumulated from the right hand sides - of rules which fired. - """ - attrs = {} - - # Process all rules - for regexp, rhs_dict in self.rules: - if regexp.match(filename): - attrs.update(rhs_dict) - - return attrs - # TODO: Files can belong to multiple groups? - # (test/source) - # (mac/pc/win) - # (media_test/all_tests) - # (small/med/large) - # How to handle that? - - def AddRoot(self, root_path, alt_name='_'): - """Adds a root directory. - - Args: - root_path: Root directory to add. - alt_name: If specified, name of root dir. Otherwise, defaults to '_'. - - Raises: - ValueError: alt_name was blank. - """ - # Alt name must not be blank. If it were, there wouldn't be a way to - # reverse-resolve from a root-replaced path back to the local path, since - # '' would always match the beginning of the candidate filename, resulting - # in an infinite loop. - if not alt_name: - raise ValueError('AddRoot alt_name must not be blank.') - - # Clean up root path based on existing rules - self.root_dirs.append([self.CleanupFilename(root_path), alt_name]) - - def AddRule(self, path_regexp, **kwargs): - """Adds a rule. - - Args: - path_regexp: Regular expression to match for filenames. These are - matched after root directory replacement. - kwargs: Keyword arguments are attributes to set if the rule applies. - - Keyword arguments currently supported: - include: If True, includes matches; if False, excludes matches. Ignored - if None. - group: If not None, sets group to apply to matches. - language: If not None, sets file language to apply to matches. - """ - - # Compile regexp ahead of time - self.rules.append([re.compile(path_regexp), dict(kwargs)]) - - def GetCoveredFile(self, filename, add=False): - """Gets the CoveredFile object for the filename. - - Args: - filename: Name of file to find. - add: If True, will add the file if it's not present. This applies the - transformations from AddRoot() and AddRule(), and only adds the file - if a rule includes it, and it has a group and language. - - Returns: - The matching CoveredFile object, or None if not present. - """ - # Clean filename - filename = self.CleanupFilename(filename) - - # Check for existing match - if filename in self.files: - return self.files[filename] - - # File isn't one we know about. If we can't add it, give up. - if not add: - return None - - # Check rules to see if file can be added. Files must be included and - # have a group and language. - attrs = self.ClassifyFile(filename) - if not (attrs.get('include') - and attrs.get('group') - and attrs.get('language')): - return None - - # Add the file - f = CoveredFile(filename, **attrs) - self.files[filename] = f - - # Return the newly covered file - return f - - def RemoveCoveredFile(self, cov_file): - """Removes the file from the covered file list. - - Args: - cov_file: A file object returned by GetCoveredFile(). - """ - self.files.pop(cov_file.filename) - - def ParseLcovData(self, lcov_data): - """Adds coverage from LCOV-formatted data. - - Args: - lcov_data: An iterable returning lines of data in LCOV format. For - example, a file or list of strings. - """ - cov_file = None - cov_lines = None - for line in lcov_data: - line = line.strip() - if line.startswith('SF:'): - # Start of data for a new file; payload is filename - cov_file = self.GetCoveredFile(line[3:], add=True) - if cov_file: - cov_lines = cov_file.lines - cov_file.in_lcov = True # File was instrumented - elif not cov_file: - # Inside data for a file we don't care about - so skip it - pass - elif line.startswith('DA:'): - # Data point - that is, an executable line in current file - line_no, is_covered = map(int, line[3:].split(',')) - if is_covered: - # Line is covered - cov_lines[line_no] = 1 - elif cov_lines.get(line_no) != 1: - # Line is not covered, so track it as uncovered - cov_lines[line_no] = 0 - elif line == 'end_of_record': - cov_file.UpdateCoverage() - cov_file = None - # (else ignore other line types) - - def ParseLcovFile(self, input_filename): - """Adds coverage data from a .lcov file. - - Args: - input_filename: Input filename. - """ - # TODO: All manner of error checking - lcov_file = None - try: - lcov_file = open(input_filename, 'rt') - self.ParseLcovData(lcov_file) - finally: - if lcov_file: - lcov_file.close() - - def GetStat(self, stat, group='all', default=None): - """Gets a statistic from the coverage object. - - Args: - stat: Statistic to get. May also be an evaluatable python expression, - using the stats. For example, 'stat1 - stat2'. - group: File group to match; if 'all', matches all groups. - default: Value to return if there was an error evaluating the stat. For - example, if the stat does not exist. If None, raises - CrocStatError. - - Returns: - The evaluated stat, or None if error. - - Raises: - CrocStatError: Error evaluating stat. - """ - # TODO: specify a subdir to get the stat from, then walk the tree to - # print the stats from just that subdir - - # Make sure the group exists - if group not in self.tree.stats_by_group: - if default is None: - raise CrocStatError('Group %r not found.' % group) - else: - return default - - stats = self.tree.stats_by_group[group] - # Unit tests use real dicts, not CoverageStats objects, - # so we can't AddDefaults() on them. - if group == 'all' and hasattr(stats, 'AddDefaults'): - stats.AddDefaults() - try: - return eval(stat, {'__builtins__': {'S': self.GetStat}}, stats) - except Exception, e: - if default is None: - raise CrocStatError('Error evaluating stat %r: %s' % (stat, e)) - else: - return default - - def PrintStat(self, stat, format=None, outfile=sys.stdout, **kwargs): - """Prints a statistic from the coverage object. - - Args: - stat: Statistic to get. May also be an evaluatable python expression, - using the stats. For example, 'stat1 - stat2'. - format: Format string to use when printing stat. If None, prints the - stat and its evaluation. - outfile: File stream to output stat to; defaults to stdout. - kwargs: Additional args to pass to GetStat(). - """ - s = self.GetStat(stat, **kwargs) - if format is None: - outfile.write('GetStat(%r) = %s\n' % (stat, s)) - else: - outfile.write(format % s + '\n') - - def AddFiles(self, src_dir): - """Adds files to coverage information. - - LCOV files only contains files which are compiled and instrumented as part - of running coverage. This function finds missing files and adds them. - - Args: - src_dir: Directory on disk at which to start search. May be a relative - path on disk starting with '.' or '..', or an absolute path, or a - path relative to an alt_name for one of the roots - (for example, '_/src'). If the alt_name matches more than one root, - all matches will be attempted. - - Note that dirs not underneath one of the root dirs and covered by an - inclusion rule will be ignored. - """ - # Check for root dir alt_names in the path and replace with the actual - # root dirs, then recurse. - found_root = False - for root, alt_name in self.root_dirs: - replaced_root = re.sub('^' + re.escape(alt_name) + '(?=(/|$))', root, - src_dir) - if replaced_root != src_dir: - found_root = True - self.AddFiles(replaced_root) - if found_root: - return # Replaced an alt_name with a root_dir, so already recursed. - - for (dirpath, dirnames, filenames) in self.add_files_walk(src_dir): - # Make a copy of the dirnames list so we can modify the original to - # prune subdirs we don't need to walk. - for d in list(dirnames): - # Add trailing '/' to directory names so dir-based regexps can match - # '/' instead of needing to specify '(/|$)'. - dpath = self.CleanupFilename(dirpath + '/' + d) + '/' - attrs = self.ClassifyFile(dpath) - if not attrs.get('include'): - # Directory has been excluded, so don't traverse it - # TODO: Document the slight weirdness caused by this: If you - # AddFiles('./A'), and the rules include 'A/B/C/D' but not 'A/B', - # then it won't recurse into './A/B' so won't find './A/B/C/D'. - # Workarounds are to AddFiles('./A/B/C/D') or AddFiles('./A/B/C'). - # The latter works because it explicitly walks the contents of the - # path passed to AddFiles(), so it finds './A/B/C/D'. - dirnames.remove(d) - - for f in filenames: - local_path = dirpath + '/' + f - - covf = self.GetCoveredFile(local_path, add=True) - if not covf: - continue - - # Save where we found the file, for generating line-by-line HTML output - covf.local_path = local_path - - if covf.in_lcov: - # File already instrumented and doesn't need to be scanned - continue - - if not covf.attrs.get('add_if_missing', 1): - # Not allowed to add the file - self.RemoveCoveredFile(covf) - continue - - # Scan file to find potentially-executable lines - lines = self.scan_file(covf.local_path, covf.attrs.get('language')) - if lines: - for l in lines: - covf.lines[l] = None - covf.UpdateCoverage() - else: - # File has no executable lines, so don't count it - self.RemoveCoveredFile(covf) - - def AddConfig(self, config_data, lcov_queue=None, addfiles_queue=None): - """Adds JSON-ish config data. - - Args: - config_data: Config data string. - lcov_queue: If not None, object to append lcov_files to instead of - parsing them immediately. - addfiles_queue: If not None, object to append add_files to instead of - processing them immediately. - """ - # TODO: All manner of error checking - cfg = eval(config_data, {'__builtins__': {}}, {}) - - for rootdict in cfg.get('roots', []): - self.AddRoot(rootdict['root'], alt_name=rootdict.get('altname', '_')) - - for ruledict in cfg.get('rules', []): - regexp = ruledict.pop('regexp') - self.AddRule(regexp, **ruledict) - - for add_lcov in cfg.get('lcov_files', []): - if lcov_queue is not None: - lcov_queue.append(add_lcov) - else: - self.ParseLcovFile(add_lcov) - - for add_path in cfg.get('add_files', []): - if addfiles_queue is not None: - addfiles_queue.append(add_path) - else: - self.AddFiles(add_path) - - self.print_stats += cfg.get('print_stats', []) - - def ParseConfig(self, filename, **kwargs): - """Parses a configuration file. - - Args: - filename: Config filename. - kwargs: Additional parameters to pass to AddConfig(). - """ - # TODO: All manner of error checking - f = None - try: - f = open(filename, 'rt') - # Need to strip CR's from CRLF-terminated lines or posix systems can't - # eval the data. - config_data = f.read().replace('\r\n', '\n') - # TODO: some sort of include syntax. - # - # Needs to be done at string-time rather than at eval()-time, so that - # it's possible to include parts of dicts. Path from a file to its - # include should be relative to the dir containing the file. - # - # Or perhaps it could be done after eval. In that case, there'd be an - # 'include' section with a list of files to include. Those would be - # eval()'d and recursively pre- or post-merged with the including file. - # - # Or maybe just don't worry about it, since multiple configs can be - # specified on the command line. - self.AddConfig(config_data, **kwargs) - finally: - if f: - f.close() - - def UpdateTreeStats(self): - """Recalculates the tree stats from the currently covered files. - - Also calculates coverage summary for files. - """ - self.tree = CoveredDir('') - for cov_file in self.files.itervalues(): - # Add the file to the tree - fdirs = cov_file.filename.split('/') - parent = self.tree - ancestors = [parent] - for d in fdirs[:-1]: - if d not in parent.subdirs: - if parent.dirpath: - parent.subdirs[d] = CoveredDir(parent.dirpath + '/' + d) - else: - parent.subdirs[d] = CoveredDir(d) - parent = parent.subdirs[d] - ancestors.append(parent) - # Final subdir actually contains the file - parent.files[fdirs[-1]] = cov_file - - # Now add file's contribution to coverage by dir - for a in ancestors: - # Add to 'all' group - a.stats_by_group['all'].Add(cov_file.stats) - - # Add to group file belongs to - group = cov_file.attrs.get('group') - if group not in a.stats_by_group: - a.stats_by_group[group] = CoverageStats() - cbyg = a.stats_by_group[group] - cbyg.Add(cov_file.stats) - - def PrintTree(self): - """Prints the tree stats.""" - # Print the tree - print 'Lines of code coverage by directory:' - print self.tree.GetTree() - -#------------------------------------------------------------------------------ - - -def Main(argv): - """Main routine. - - Args: - argv: list of arguments - - Returns: - exit code, 0 for normal exit. - """ - # Parse args - parser = optparse.OptionParser() - parser.add_option( - '-i', '--input', dest='inputs', type='string', action='append', - metavar='FILE', - help='read LCOV input from FILE') - parser.add_option( - '-r', '--root', dest='roots', type='string', action='append', - metavar='ROOT[=ALTNAME]', - help='add ROOT directory, optionally map in coverage results as ALTNAME') - parser.add_option( - '-c', '--config', dest='configs', type='string', action='append', - metavar='FILE', - help='read settings from configuration FILE') - parser.add_option( - '-a', '--addfiles', dest='addfiles', type='string', action='append', - metavar='PATH', - help='add files from PATH to coverage data') - parser.add_option( - '-t', '--tree', dest='tree', action='store_true', - help='print tree of code coverage by group') - parser.add_option( - '-u', '--uninstrumented', dest='uninstrumented', action='store_true', - help='list uninstrumented files') - parser.add_option( - '-m', '--html', dest='html_out', type='string', metavar='PATH', - help='write HTML output to PATH') - parser.add_option( - '-b', '--base_url', dest='base_url', type='string', metavar='URL', - help='include URL in base tag of HTML output') - - parser.set_defaults( - inputs=[], - roots=[], - configs=[], - addfiles=[], - tree=False, - html_out=None, - ) - - options = parser.parse_args(args=argv)[0] - - cov = Coverage() - - # Set root directories for coverage - for root_opt in options.roots: - if '=' in root_opt: - cov.AddRoot(*root_opt.split('=')) - else: - cov.AddRoot(root_opt) - - # Read config files - for config_file in options.configs: - cov.ParseConfig(config_file, lcov_queue=options.inputs, - addfiles_queue=options.addfiles) - - # Parse lcov files - for input_filename in options.inputs: - cov.ParseLcovFile(input_filename) - - # Add missing files - for add_path in options.addfiles: - cov.AddFiles(add_path) - - # Print help if no files specified - if not cov.files: - print 'No covered files found.' - parser.print_help() - return 1 - - # Update tree stats - cov.UpdateTreeStats() - - # Print uninstrumented filenames - if options.uninstrumented: - print 'Uninstrumented files:' - for f in sorted(cov.files): - covf = cov.files[f] - if not covf.in_lcov: - print ' %-6s %-6s %s' % (covf.attrs.get('group'), - covf.attrs.get('language'), f) - - # Print tree stats - if options.tree: - cov.PrintTree() - - # Print stats - for ps_args in cov.print_stats: - cov.PrintStat(**ps_args) - - # Generate HTML - if options.html_out: - html = croc_html.CrocHtml(cov, options.html_out, options.base_url) - html.Write() - - # Normal exit - return 0 - - -if __name__ == '__main__': - sys.exit(Main(sys.argv)) diff --git a/tools/code_coverage/croc_html.py b/tools/code_coverage/croc_html.py deleted file mode 100644 index 7866f472f7..0000000000 --- a/tools/code_coverage/croc_html.py +++ /dev/null @@ -1,451 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Crocodile HTML output.""" - -import os -import shutil -import time -import xml.dom - - -class CrocHtmlError(Exception): - """Coverage HTML error.""" - - -class HtmlElement(object): - """Node in a HTML file.""" - - def __init__(self, doc, element): - """Constructor. - - Args: - doc: XML document object. - element: XML element. - """ - self.doc = doc - self.element = element - - def E(self, name, **kwargs): - """Adds a child element. - - Args: - name: Name of element. - kwargs: Attributes for element. To use an attribute which is a python - reserved word (i.e. 'class'), prefix the attribute name with 'e_'. - - Returns: - The child element. - """ - he = HtmlElement(self.doc, self.doc.createElement(name)) - element = he.element - self.element.appendChild(element) - - for k, v in kwargs.iteritems(): - if k.startswith('e_'): - # Remove prefix - element.setAttribute(k[2:], str(v)) - else: - element.setAttribute(k, str(v)) - - return he - - def Text(self, text): - """Adds a text node. - - Args: - text: Text to add. - - Returns: - self. - """ - t = self.doc.createTextNode(str(text)) - self.element.appendChild(t) - return self - - -class HtmlFile(object): - """HTML file.""" - - def __init__(self, xml_impl, filename): - """Constructor. - - Args: - xml_impl: DOMImplementation to use to create document. - filename: Path to file. - """ - self.xml_impl = xml_impl - doctype = xml_impl.createDocumentType( - 'HTML', '-//W3C//DTD HTML 4.01//EN', - 'http://www.w3.org/TR/html4/strict.dtd') - self.doc = xml_impl.createDocument(None, 'html', doctype) - self.filename = filename - - # Create head and body elements - root = HtmlElement(self.doc, self.doc.documentElement) - self.head = root.E('head') - self.body = root.E('body') - - def Write(self, cleanup=True): - """Writes the file. - - Args: - cleanup: If True, calls unlink() on the internal xml document. This - frees up memory, but means that you can't use this file for anything - else. - """ - f = open(self.filename, 'wt') - self.doc.writexml(f, encoding='UTF-8') - f.close() - - if cleanup: - self.doc.unlink() - # Prevent future uses of the doc now that we've unlinked it - self.doc = None - -#------------------------------------------------------------------------------ - -COV_TYPE_STRING = {None: 'm', 0: 'i', 1: 'E', 2: ' '} -COV_TYPE_CLASS = {None: 'missing', 0: 'instr', 1: 'covered', 2: ''} - - -class CrocHtml(object): - """Crocodile HTML output class.""" - - def __init__(self, cov, output_root, base_url=None): - """Constructor.""" - self.cov = cov - self.output_root = output_root - self.base_url = base_url - self.xml_impl = xml.dom.getDOMImplementation() - self.time_string = 'Coverage information generated %s.' % time.asctime() - - def CreateHtmlDoc(self, filename, title): - """Creates a new HTML document. - - Args: - filename: Filename to write to, relative to self.output_root. - title: Title of page - - Returns: - The document. - """ - f = HtmlFile(self.xml_impl, self.output_root + '/' + filename) - - f.head.E('title').Text(title) - - if self.base_url: - css_href = self.base_url + 'croc.css' - base_href = self.base_url + os.path.dirname(filename) - if not base_href.endswith('/'): - base_href += '/' - f.head.E('base', href=base_href) - else: - css_href = '../' * (len(filename.split('/')) - 1) + 'croc.css' - - f.head.E('link', rel='stylesheet', type='text/css', href=css_href) - - return f - - def AddCaptionForFile(self, body, path): - """Adds a caption for the file, with links to each parent dir. - - Args: - body: Body elemement. - path: Path to file. - """ - # This is slightly different that for subdir, because it needs to have a - # link to the current directory's index.html. - hdr = body.E('h2') - hdr.Text('Coverage for ') - dirs = [''] + path.split('/') - num_dirs = len(dirs) - for i in range(num_dirs - 1): - hdr.E('a', href=( - '../' * (num_dirs - i - 2) + 'index.html')).Text(dirs[i] + '/') - hdr.Text(dirs[-1]) - - def AddCaptionForSubdir(self, body, path): - """Adds a caption for the subdir, with links to each parent dir. - - Args: - body: Body elemement. - path: Path to subdir. - """ - # Link to parent dirs - hdr = body.E('h2') - hdr.Text('Coverage for ') - dirs = [''] + path.split('/') - num_dirs = len(dirs) - for i in range(num_dirs - 1): - hdr.E('a', href=( - '../' * (num_dirs - i - 1) + 'index.html')).Text(dirs[i] + '/') - hdr.Text(dirs[-1] + '/') - - def AddSectionHeader(self, table, caption, itemtype, is_file=False): - """Adds a section header to the coverage table. - - Args: - table: Table to add rows to. - caption: Caption for section, if not None. - itemtype: Type of items in this section, if not None. - is_file: Are items in this section files? - """ - - if caption is not None: - table.E('tr').E('th', e_class='secdesc', colspan=8).Text(caption) - - sec_hdr = table.E('tr') - - if itemtype is not None: - sec_hdr.E('th', e_class='section').Text(itemtype) - - sec_hdr.E('th', e_class='section').Text('Coverage') - sec_hdr.E('th', e_class='section', colspan=3).Text( - 'Lines executed / instrumented / missing') - - graph = sec_hdr.E('th', e_class='section') - graph.E('span', style='color:#00FF00').Text('exe') - graph.Text(' / ') - graph.E('span', style='color:#FFFF00').Text('inst') - graph.Text(' / ') - graph.E('span', style='color:#FF0000').Text('miss') - - if is_file: - sec_hdr.E('th', e_class='section').Text('Language') - sec_hdr.E('th', e_class='section').Text('Group') - else: - sec_hdr.E('th', e_class='section', colspan=2) - - def AddItem(self, table, itemname, stats, attrs, link=None): - """Adds a bar graph to the element. This is a series of elements. - - Args: - table: Table to add item to. - itemname: Name of item. - stats: Stats object. - attrs: Attributes dictionary; if None, no attributes will be printed. - link: Destination for itemname hyperlink, if not None. - """ - row = table.E('tr') - - # Add item name - if itemname is not None: - item_elem = row.E('td') - if link is not None: - item_elem = item_elem.E('a', href=link) - item_elem.Text(itemname) - - # Get stats - stat_exe = stats.get('lines_executable', 0) - stat_ins = stats.get('lines_instrumented', 0) - stat_cov = stats.get('lines_covered', 0) - - percent = row.E('td') - - # Add text - row.E('td', e_class='number').Text(stat_cov) - row.E('td', e_class='number').Text(stat_ins) - row.E('td', e_class='number').Text(stat_exe - stat_ins) - - # Add percent and graph; only fill in if there's something in there - graph = row.E('td', e_class='graph', width=100) - if stat_exe: - percent_cov = 100.0 * stat_cov / stat_exe - percent_ins = 100.0 * stat_ins / stat_exe - - # Color percent based on thresholds - percent.Text('%.1f%%' % percent_cov) - if percent_cov >= 80: - percent.element.setAttribute('class', 'high_pct') - elif percent_cov >= 60: - percent.element.setAttribute('class', 'mid_pct') - else: - percent.element.setAttribute('class', 'low_pct') - - # Graphs use integer values - percent_cov = int(percent_cov) - percent_ins = int(percent_ins) - - graph.Text('.') - graph.E('span', style='padding-left:%dpx' % percent_cov, - e_class='g_covered') - graph.E('span', style='padding-left:%dpx' % (percent_ins - percent_cov), - e_class='g_instr') - graph.E('span', style='padding-left:%dpx' % (100 - percent_ins), - e_class='g_missing') - - if attrs: - row.E('td', e_class='stat').Text(attrs.get('language')) - row.E('td', e_class='stat').Text(attrs.get('group')) - else: - row.E('td', colspan=2) - - def WriteFile(self, cov_file): - """Writes the HTML for a file. - - Args: - cov_file: croc.CoveredFile to write. - """ - print ' ' + cov_file.filename - title = 'Coverage for ' + cov_file.filename - - f = self.CreateHtmlDoc(cov_file.filename + '.html', title) - body = f.body - - # Write header section - self.AddCaptionForFile(body, cov_file.filename) - - # Summary for this file - table = body.E('table') - self.AddSectionHeader(table, None, None, is_file=True) - self.AddItem(table, None, cov_file.stats, cov_file.attrs) - - body.E('h2').Text('Line-by-line coverage:') - - # Print line-by-line coverage - if cov_file.local_path: - code_table = body.E('table').E('tr').E('td').E('pre') - - flines = open(cov_file.local_path, 'rt') - lineno = 0 - - for line in flines: - lineno += 1 - line_cov = cov_file.lines.get(lineno, 2) - e_class = COV_TYPE_CLASS.get(line_cov) - - code_table.E('span', e_class=e_class).Text('%4d %s : %s\n' % ( - lineno, - COV_TYPE_STRING.get(line_cov), - line.rstrip() - )) - - else: - body.Text('Line-by-line coverage not available. Make sure the directory' - ' containing this file has been scanned via ') - body.E('B').Text('add_files') - body.Text(' in a configuration file, or the ') - body.E('B').Text('--addfiles') - body.Text(' command line option.') - - # TODO: if file doesn't have a local path, try to find it by - # reverse-mapping roots and searching for the file. - - body.E('p', e_class='time').Text(self.time_string) - f.Write() - - def WriteSubdir(self, cov_dir): - """Writes the index.html for a subdirectory. - - Args: - cov_dir: croc.CoveredDir to write. - """ - print ' ' + cov_dir.dirpath + '/' - - # Create the subdir if it doesn't already exist - subdir = self.output_root + '/' + cov_dir.dirpath - if not os.path.exists(subdir): - os.mkdir(subdir) - - if cov_dir.dirpath: - title = 'Coverage for ' + cov_dir.dirpath + '/' - f = self.CreateHtmlDoc(cov_dir.dirpath + '/index.html', title) - else: - title = 'Coverage summary' - f = self.CreateHtmlDoc('index.html', title) - - body = f.body - - dirs = [''] + cov_dir.dirpath.split('/') - num_dirs = len(dirs) - sort_jsfile = '../' * (num_dirs - 1) + 'sorttable.js' - script = body.E('script', src=sort_jsfile) - body.E('/script') - - # Write header section - if cov_dir.dirpath: - self.AddCaptionForSubdir(body, cov_dir.dirpath) - else: - body.E('h2').Text(title) - - table = body.E('table', e_class='sortable') - table.E('h3').Text('Coverage by Group') - # Coverage by group - self.AddSectionHeader(table, None, 'Group') - - for group in sorted(cov_dir.stats_by_group): - self.AddItem(table, group, cov_dir.stats_by_group[group], None) - - # List subdirs - if cov_dir.subdirs: - table = body.E('table', e_class='sortable') - table.E('h3').Text('Subdirectories') - self.AddSectionHeader(table, None, 'Subdirectory') - - for d in sorted(cov_dir.subdirs): - self.AddItem(table, d + '/', cov_dir.subdirs[d].stats_by_group['all'], - None, link=d + '/index.html') - - # List files - if cov_dir.files: - table = body.E('table', e_class='sortable') - table.E('h3').Text('Files in This Directory') - self.AddSectionHeader(table, None, 'Filename', - is_file=True) - - for filename in sorted(cov_dir.files): - cov_file = cov_dir.files[filename] - self.AddItem(table, filename, cov_file.stats, cov_file.attrs, - link=filename + '.html') - - body.E('p', e_class='time').Text(self.time_string) - f.Write() - - def WriteRoot(self): - """Writes the files in the output root.""" - # Find ourselves - src_dir = os.path.split(self.WriteRoot.func_code.co_filename)[0] - - # Files to copy into output root - copy_files = ['croc.css'] - # Third_party files to copy into output root - third_party_files = ['sorttable.js'] - - # Copy files from our directory into the output directory - for copy_file in copy_files: - print ' Copying %s' % copy_file - shutil.copyfile(os.path.join(src_dir, copy_file), - os.path.join(self.output_root, copy_file)) - # Copy third party files from third_party directory into - # the output directory - src_dir = os.path.join(src_dir, 'third_party') - for third_party_file in third_party_files: - print ' Copying %s' % third_party_file - shutil.copyfile(os.path.join(src_dir, third_party_file), - os.path.join(self.output_root, third_party_file)) - - def Write(self): - """Writes HTML output.""" - - print 'Writing HTML to %s...' % self.output_root - - # Loop through the tree and write subdirs, breadth-first - # TODO: switch to depth-first and sort values - makes nicer output? - todo = [self.cov.tree] - while todo: - cov_dir = todo.pop(0) - - # Append subdirs to todo list - todo += cov_dir.subdirs.values() - - # Write this subdir - self.WriteSubdir(cov_dir) - - # Write files in this subdir - for cov_file in cov_dir.files.itervalues(): - self.WriteFile(cov_file) - - # Write files in root directory - self.WriteRoot() diff --git a/tools/code_coverage/croc_scan.py b/tools/code_coverage/croc_scan.py deleted file mode 100644 index 8d0e2e8df2..0000000000 --- a/tools/code_coverage/croc_scan.py +++ /dev/null @@ -1,164 +0,0 @@ -# Copyright (c) 2011 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Crocodile source scanners.""" - - -import re - - -class Scanner(object): - """Generic source scanner.""" - - def __init__(self): - """Constructor.""" - - self.re_token = re.compile('#') - self.comment_to_eol = ['#'] - self.comment_start = None - self.comment_end = None - - def ScanLines(self, lines): - """Scans the lines for executable statements. - - Args: - lines: Iterator returning source lines. - - Returns: - An array of line numbers which are executable. - """ - exe_lines = [] - lineno = 0 - - in_string = None - in_comment = None - comment_index = None - - for line in lines: - lineno += 1 - in_string_at_start = in_string - - for t in self.re_token.finditer(line): - tokenstr = t.groups()[0] - - if in_comment: - # Inside a multi-line comment, so look for end token - if tokenstr == in_comment: - in_comment = None - # Replace comment with spaces - line = (line[:comment_index] - + ' ' * (t.end(0) - comment_index) - + line[t.end(0):]) - - elif in_string: - # Inside a string, so look for end token - if tokenstr == in_string: - in_string = None - - elif tokenstr in self.comment_to_eol: - # Single-line comment, so truncate line at start of token - line = line[:t.start(0)] - break - - elif tokenstr == self.comment_start: - # Multi-line comment start - end token is comment_end - in_comment = self.comment_end - comment_index = t.start(0) - - else: - # Starting a string - end token is same as start - in_string = tokenstr - - # If still in comment at end of line, remove comment - if in_comment: - line = line[:comment_index] - # Next line, delete from the beginnine - comment_index = 0 - - # If line-sans-comments is not empty, claim it may be executable - if line.strip() or in_string_at_start: - exe_lines.append(lineno) - - # Return executable lines - return exe_lines - - def Scan(self, filename): - """Reads the file and scans its lines. - - Args: - filename: Path to file to scan. - - Returns: - An array of line numbers which are executable. - """ - - # TODO: All manner of error checking - f = None - try: - f = open(filename, 'rt') - return self.ScanLines(f) - finally: - if f: - f.close() - - -class PythonScanner(Scanner): - """Python source scanner.""" - - def __init__(self): - """Constructor.""" - Scanner.__init__(self) - - # TODO: This breaks for strings ending in more than 2 backslashes. Need - # a pattern which counts only an odd number of backslashes, so the last - # one thus escapes the quote. - self.re_token = re.compile(r'(#|\'\'\'|"""|(?_.lcov. - This method parses the file name and then sets up the correct folder - hierarchy for the coverage data and then runs genhtml to get the actual HTML - formatted coverage data. - - Args: - lcov_path: Path of the lcov data file. - dash_root: Root location of the dashboard. - - Returns: - Code coverage percentage on sucess. - None on failure. - """ - # Parse the LCOV file name. - filename = os.path.basename(lcov_path).split('.')[0] - buffer = filename.split('_') - dash_root = dash_root.rstrip('/') # Remove trailing '/' - - # Set up correct folder hierarchy in the dashboard root - # TODO(niranjan): Check the formatting using a regexp - if len(buffer) >= 3: # Check if filename has right formatting - platform = buffer[len(buffer) - 2] - revision = buffer[len(buffer) - 1] - if os.path.exists(os.path.join(dash_root, platform)) == False: - os.mkdir(os.path.join(dash_root, platform)) - output_dir = os.path.join(dash_root, platform, revision) - os.mkdir(output_dir) - else: - # TODO(niranjan): Add failure logging here. - return None # File not formatted correctly - - # Run genhtml - os.system('/usr/bin/genhtml -o %s %s' % (output_dir, lcov_path)) - # TODO(niranjan): Check the exit status of the genhtml command. - # TODO(niranjan): Parse the stdout and return coverage percentage. - CleanPathNames(output_dir) - return 'dummy' # TODO(niranjan): Return actual percentage. - - -def CleanWin32Lcov(lcov_path, src_root): - """Cleanup the lcov data generated on Windows. - - This method fixes up the paths inside the lcov file from the Win32 specific - paths to the actual paths of the mounted CIFS share. The lcov files generated - on Windows have the following format: - - SF:c:\chrome_src\src\skia\sgl\skscan_antihair.cpp - DA:97,0 - DA:106,0 - DA:107,0 - DA:109,0 - ... - end_of_record - - This method changes the source-file (SF) lines to a format compatible with - genhtml on Linux by fixing paths. This method also removes references to - certain dynamically generated files to be excluded from the code ceverage. - - Args: - lcov_path: Path of the Win32 lcov file to be cleaned. - src_root: Location of the source and symbols dir. - Returns: - None - """ - strip_flag = False - lcov = open(lcov_path, 'r') - loc_csv_file = open(lcov_path + '.csv', 'w') - (tmpfile_id, tmpfile_name) = tempfile.mkstemp() - tmpfile = open(tmpfile_name, 'w') - src_root = src_root.rstrip('/') # Remove trailing '/' - for line in lcov: - if line.startswith('SF'): - # We want to exclude certain auto-generated files otherwise genhtml will - # fail to convert lcov to HTML. - for exp in win32_srcs_exclude: - if line.rfind(exp) != -1: - strip_flag = True # Indicates that we want to remove this section - - # Now we normalize the paths - # e.g. Change SF:c:\foo\src\... to SF:/chrome_src/... - parse_buffer = line.split(':') - buffer = '%s:%s%s' % (parse_buffer[0], - src_root, - parse_buffer[2]) - buffer = buffer.replace('\\', '/') - line = buffer.replace('\r', '') - - # We want an accurate count of the lines of code in a given file so that - # we can estimate the code coverage perscentage accurately. We use a - # third party script cloc.pl which gives that count and then just parse - # its command line output to filter out the other unnecessary data. - # TODO(niranjan): Find out a better way of doing this. - buffer = buffer.lstrip('SF:') - file_for_loc = buffer.replace('\r\n', '') - # TODO(niranjan): Add a check to see if cloc is present on the machine. - command = ["perl", - "cloc.pl", - file_for_loc] - output = subprocess.Popen(command, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT).communicate()[0] - if output.rfind('error:'): - return None - - tmp_buf1 = output.split('=') - tmp_buf2 = tmp_buf1[len(tmp_buf1) - 2].split('x')[0].split(' ') - loc = tmp_buf2[len(tmp_buf2) - 2] - loc_csv_file.write('%s,%s\r\n' % (file_for_loc, loc)) - - # Write to the temp file if the section to write is valid - if strip_flag == False: - # Also write this to the 'clean' LCOV file - tmpfile.write('%s' % (line)) - - # Reset the strip flag - if line.endswith('end_of_record'): - strip_flag = False - - # Close the files and replace the lcov file by the 'clean' tmpfile - tmpfile.close() - lcov.close() - loc_csv_file.close() - shutil.move(tmpfile_name, lcov_path) - - -def ParseCoverageDataForDashboard(lcov_path): - """Parse code coverage data into coverage results per source node. - - Use lcov and linecount data to create a map of source nodes to - corresponding total and tested line counts. - - Args: - lcov_path: File path to lcov coverage data. - - Returns: - List of strings with comma separated source node and coverage. - """ - results = {} - linecount_path = lcov_path + '.csv' - assert(os.path.exists(linecount_path), - 'linecount csv does not exist at: %s' % linecount_path) - csv_file = open(linecount_path, 'r') - linecounts = csv_file.readlines() - csv_file.close() - lcov_file = open(lcov_path, 'r') - srcfile_index = 0 - for line in lcov_file: - line = line.strip() - - # Set the current srcfile name for a new src file declaration. - if line[:len('SF:')] == 'SF:': - instrumented_set = {} - executed_set = {} - srcfile_name = line[len('SF:'):] - - # Mark coverage data points hashlist style for the current src file. - if line[:len('DA:')] == 'DA:': - line_info = line[len('DA:'):].split(',') - assert(len(line_info) == 2, 'DA: line format unexpected - %s' % line) - (line_num, line_was_executed) = line_info - instrumented_set[line_num] = True - # line_was_executed is '0' or '1' - if int(line_was_executed): - executed_set[line_num] = True - - # Update results for the current src file at record end. - if line == 'end_of_record': - instrumented = len(instrumented_set.keys()) - executed = len(executed_set.keys()) - parent_directory = srcfile_name[:srcfile_name.rfind('/') + 1] - linecount_point = linecounts[srcfile_index].strip().split(',') - assert(len(linecount_point) == 2, - 'lintcount format unexpected - %s' % linecounts[srcfile_index]) - (linecount_path, linecount_count) = linecount_point - srcfile_index += 1 - - # Sanity check that path names in the lcov and linecount are lined up. - if linecount_path[-10:] != srcfile_name[-10:]: - print 'NAME MISMATCH: %s :: %s' % (srcfile_name, linecount_path) - if instrumented > int(linecount_count): - linecount_count = instrumented - - # Keep counts the same way that it is done in the genhtml utility. - # Count the coverage of a file towards the file, - # the parent directory, and the source root. - AddResults(results, srcfile_name, int(linecount_count), executed) - AddResults(results, parent_directory, int(linecount_count), executed) - AddResults(results, '/', instrumented, executed) - - lcov_file.close() - keys = results.keys() - keys.sort() - # The first key (sorted) will be the base directory '/' - # but its full path may be '/mnt/chrome_src/src/' - # using this offset will ignore the part '/mnt/chrome_src/src'. - # Offset is the last '/' that isn't the last character for the - # first directory name in results (position 1 in keys). - offset = len(keys[1][:keys[1][:-1].rfind('/')]) - lines = [] - for key in keys: - if len(key) > offset: - node_path = key[offset:] - else: - node_path = key - (total, covered) = results[key] - percent = float(covered) * 100 / total - lines.append('%s,%.2f' % (node_path, percent)) - return lines - - -def AddResults(results, location, lines_total, lines_executed): - """Add resulting line tallies to a location's total. - - Args: - results: Map of node location to corresponding coverage data. - location: Source node string. - lines_total: Number of lines to add to the total count for this node. - lines_executed: Number of lines to add to the executed count for this node. - """ - if results.has_key(location): - (i, e) = results[location] - results[location] = (i + lines_total, e + lines_executed) - else: - results[location] = (lines_total, lines_executed) - - -def PostResultsToDashboard(lcov_path, results, post_url): - """Post coverage results to coverage dashboard. - - Args: - lcov_path: File path for lcov data in the expected format: - __.coverage.lcov - results: string list in the appropriate posting format. - """ - project_platform_cl = lcov_path.split('.')[0].split('_') - assert(len(project_platform_cl) == 3, - 'lcov_path not in expected format: %s' % lcov_path) - (project, platform, cl_string) = project_platform_cl - project_name = '%s-%s' % (project, platform) - url = '%s/newdata.do?project=%s&cl=%s' % (post_url, project_name, cl_string) - - # Send POSTs of POST_CHUNK_SIZE lines of the result set until - # there is no more data and last_loop is set to True. - last_loop = False - cur_line = 0 - while not last_loop: - body = '\n'.join(results[cur_line:cur_line + POST_CHUNK_SIZE]) - cur_line += POST_CHUNK_SIZE - last_loop = (cur_line >= len(results)) - req = urllib2.Request('%s&last=%s' % (url, str(last_loop)), body) - req.add_header('Content-Type', 'text/plain') - SendPost(req) - - -# Global counter for the current number of request failures. -num_fails = 0 - -def SendPost(req): - """Execute a post request and retry for up to MAX_FAILURES. - - Args: - req: A urllib2 request object. - - Raises: - URLError: If urlopen throws after too many retries. - HTTPError: If urlopen throws after too many retries. - """ - global num_fails - try: - urllib2.urlopen(req) - # Reset failure count. - num_fails = 0 - except (urllib2.URLError, urllib2.HTTPError): - num_fails += 1 - if num_fails < MAX_FAILURES: - print 'fail, retrying (%d)' % num_fails - time.sleep(5) - SendPost(req) - else: - print 'POST request exceeded allowed retries.' - raise - - -def main(): - if not sys.platform.startswith('linux'): - print 'This script is supported only on Linux' - return 0 - - # Command line parsing - parser = optparse.OptionParser() - parser.add_option('-p', - '--platform', - dest='platform', - default=None, - help=('Platform that the locv file was generated on. Must' - 'be one of {win32, linux2, linux3, macosx}')) - parser.add_option('-s', - '--source', - dest='src_dir', - default=None, - help='Path to the source code and symbols') - parser.add_option('-d', - '--dash_root', - dest='dash_root', - default=None, - help='Root directory for the dashboard') - parser.add_option('-l', - '--lcov', - dest='lcov_path', - default=None, - help='Location of the LCOV file to process') - parser.add_option('-u', - '--post_url', - dest='post_url', - default=None, - help='Base URL of the coverage dashboard') - (options, args) = parser.parse_args() - - if options.platform == None: - parser.error('Platform not specified') - if options.lcov_path == None: - parser.error('lcov file path not specified') - if options.src_dir == None: - parser.error('Source directory not specified') - if options.dash_root == None: - parser.error('Dashboard root not specified') - if options.post_url == None: - parser.error('Post URL not specified') - if options.platform == 'win32': - CleanWin32Lcov(options.lcov_path, options.src_dir) - percent = GenerateHtml(options.lcov_path, options.dash_root) - if percent == None: - # TODO(niranjan): Add logging. - print 'Failed to generate code coverage' - return 1 - else: - # TODO(niranjan): Do something with the code coverage numbers - pass - else: - print 'Unsupported platform' - return 1 - - # Prep coverage results for dashboard and post new set. - parsed_data = ParseCoverageDataForDashboard(options.lcov_path) - PostResultsToDashboard(options.lcov_path, parsed_data, options.post_url) - return 0 - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/tools/code_coverage/third_party/README.chromium b/tools/code_coverage/third_party/README.chromium deleted file mode 100644 index a4925525c8..0000000000 --- a/tools/code_coverage/third_party/README.chromium +++ /dev/null @@ -1,11 +0,0 @@ -Name: SortTable -Short Name: sorttable.js -URL: http://www.kryogenix.org/code/browser/sorttable/ -Version: 2 -Date: 7th April 2007 -License: Licenced as X11: http://www.kryogenix.org/code/browser/licence.html - -Description: -Add to your HTML -Add class="sortable" to any table you'd like to make sortable -Click on the headers to sort diff --git a/tools/code_coverage/third_party/sorttable.js b/tools/code_coverage/third_party/sorttable.js deleted file mode 100644 index 16ef551497..0000000000 --- a/tools/code_coverage/third_party/sorttable.js +++ /dev/null @@ -1,494 +0,0 @@ -/* - SortTable - version 2 - 7th April 2007 - Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ - - Instructions: - Download this file - Add to your HTML - Add class="sortable" to any table you'd like to make sortable - Click on the headers to sort - - Thanks to many, many people for contributions and suggestions. - Licenced as X11: http://www.kryogenix.org/code/browser/licence.html - This basically means: do what you want with it. -*/ - - -var stIsIE = /*@cc_on!@*/false; - -sorttable = { - init: function() { - // quit if this function has already been called - if (arguments.callee.done) return; - // flag this function so we don't do the same thing twice - arguments.callee.done = true; - // kill the timer - if (_timer) clearInterval(_timer); - - if (!document.createElement || !document.getElementsByTagName) return; - - sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; - - forEach(document.getElementsByTagName('table'), function(table) { - if (table.className.search(/\bsortable\b/) != -1) { - sorttable.makeSortable(table); - } - }); - - }, - - makeSortable: function(table) { - if (table.getElementsByTagName('thead').length == 0) { - // table doesn't have a tHead. Since it should have, create one and - // put the first table row in it. - the = document.createElement('thead'); - the.appendChild(table.rows[0]); - table.insertBefore(the,table.firstChild); - } - // Safari doesn't support table.tHead, sigh - if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; - - if (table.tHead.rows.length != 1) return; // can't cope with two header rows - - // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as - // "total" rows, for example). This is B&R, since what you're supposed - // to do is put them in a tfoot. So, if there are sortbottom rows, - // for backwards compatibility, move them to tfoot (creating it if needed). - sortbottomrows = []; - for (var i=0; i5' : ' ▴'; - this.appendChild(sortrevind); - return; - } - if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { - // if we're already sorted by this column in reverse, just - // re-reverse the table, which is quicker - sorttable.reverse(this.sorttable_tbody); - this.className = this.className.replace('sorttable_sorted_reverse', - 'sorttable_sorted'); - this.removeChild(document.getElementById('sorttable_sortrevind')); - sortfwdind = document.createElement('span'); - sortfwdind.id = "sorttable_sortfwdind"; - sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; - this.appendChild(sortfwdind); - return; - } - - // remove sorttable_sorted classes - theadrow = this.parentNode; - forEach(theadrow.childNodes, function(cell) { - if (cell.nodeType == 1) { // an element - cell.className = cell.className.replace('sorttable_sorted_reverse',''); - cell.className = cell.className.replace('sorttable_sorted',''); - } - }); - sortfwdind = document.getElementById('sorttable_sortfwdind'); - if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } - sortrevind = document.getElementById('sorttable_sortrevind'); - if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } - - this.className += ' sorttable_sorted'; - sortfwdind = document.createElement('span'); - sortfwdind.id = "sorttable_sortfwdind"; - sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; - this.appendChild(sortfwdind); - - // build an array to sort. This is a Schwartzian transform thing, - // i.e., we "decorate" each row with the actual sort key, - // sort based on the sort keys, and then put the rows back in order - // which is a lot faster because you only do getInnerText once per row - row_array = []; - col = this.sorttable_columnindex; - rows = this.sorttable_tbody.rows; - for (var j=0; j 12) { - // definitely dd/mm - return sorttable.sort_ddmm; - } else if (second > 12) { - return sorttable.sort_mmdd; - } else { - // looks like a date, but we can't tell which, so assume - // that it's dd/mm (English imperialism!) and keep looking - sortfn = sorttable.sort_ddmm; - } - } - } - } - return sortfn; - }, - - getInnerText: function(node) { - // gets the text we want to use for sorting for a cell. - // strips leading and trailing whitespace. - // this is *not* a generic getInnerText function; it's special to sorttable. - // for example, you can override the cell text with a customkey attribute. - // it also gets .value for fields. - - if (!node) return ""; - - hasInputs = (typeof node.getElementsByTagName == 'function') && - node.getElementsByTagName('input').length; - - if (node.getAttribute("sorttable_customkey") != null) { - return node.getAttribute("sorttable_customkey"); - } - else if (typeof node.textContent != 'undefined' && !hasInputs) { - return node.textContent.replace(/^\s+|\s+$/g, ''); - } - else if (typeof node.innerText != 'undefined' && !hasInputs) { - return node.innerText.replace(/^\s+|\s+$/g, ''); - } - else if (typeof node.text != 'undefined' && !hasInputs) { - return node.text.replace(/^\s+|\s+$/g, ''); - } - else { - switch (node.nodeType) { - case 3: - if (node.nodeName.toLowerCase() == 'input') { - return node.value.replace(/^\s+|\s+$/g, ''); - } - case 4: - return node.nodeValue.replace(/^\s+|\s+$/g, ''); - break; - case 1: - case 11: - var innerText = ''; - for (var i = 0; i < node.childNodes.length; i++) { - innerText += sorttable.getInnerText(node.childNodes[i]); - } - return innerText.replace(/^\s+|\s+$/g, ''); - break; - default: - return ''; - } - } - }, - - reverse: function(tbody) { - // reverse the rows in a tbody - newrows = []; - for (var i=0; i=0; i--) { - tbody.appendChild(newrows[i]); - } - delete newrows; - }, - - /* sort functions - each sort function takes two parameters, a and b - you are comparing a[0] and b[0] */ - sort_numeric: function(a,b) { - aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); - if (isNaN(aa)) aa = 0; - bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); - if (isNaN(bb)) bb = 0; - return aa-bb; - }, - sort_alpha: function(a,b) { - if (a[0]==b[0]) return 0; - if (a[0] 0 ) { - var q = list[i]; list[i] = list[i+1]; list[i+1] = q; - swap = true; - } - } // for - t--; - - if (!swap) break; - - for(var i = t; i > b; --i) { - if ( comp_func(list[i], list[i-1]) < 0 ) { - var q = list[i]; list[i] = list[i-1]; list[i-1] = q; - swap = true; - } - } // for - b++; - - } // while(swap) - } -} - -/* ****************************************************************** - Supporting functions: bundled here to avoid depending on a library - ****************************************************************** */ - -// Dean Edwards/Matthias Miller/John Resig - -/* for Mozilla/Opera9 */ -if (document.addEventListener) { - document.addEventListener("DOMContentLoaded", sorttable.init, false); -} - -/* for Internet Explorer */ -/*@cc_on @*/ -/*@if (@_win32) - document.write(" - - - -
-
- - -""" - -def _GenerateGraph(json_data, policy): - legends = list(json_data['policies'][policy]['legends']) - legends = ['second'] + legends[legends.index('FROM_HERE_FOR_TOTAL') + 1: - legends.index('UNTIL_HERE_FOR_TOTAL')] - data = [] - for snapshot in json_data['policies'][policy]['snapshots']: - data.append([0] * len(legends)) - for k, v in snapshot.iteritems(): - if k in legends: - data[-1][legends.index(k)] = v - print Template(_HTML_TEMPLATE).safe_substitute( - {'JSON_ARRAY': json.dumps([legends] + data)}) - - -def main(argv): - _GenerateGraph(json.load(file(argv[1], 'r')), argv[2]) - - -if __name__ == '__main__': - sys.exit(main(sys.argv)) - - diff --git a/tools/deep_memory_profiler/lib/__init__.py b/tools/deep_memory_profiler/lib/__init__.py deleted file mode 100644 index 9228df89b0..0000000000 --- a/tools/deep_memory_profiler/lib/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# Copyright 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. diff --git a/tools/deep_memory_profiler/lib/bucket.py b/tools/deep_memory_profiler/lib/bucket.py deleted file mode 100644 index 51af5b2ddd..0000000000 --- a/tools/deep_memory_profiler/lib/bucket.py +++ /dev/null @@ -1,191 +0,0 @@ -# Copyright 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import logging -import os - -from lib.symbol import FUNCTION_SYMBOLS, SOURCEFILE_SYMBOLS, TYPEINFO_SYMBOLS - - -LOGGER = logging.getLogger('dmprof') - -# Indexes in dumped heap profile dumps. -VIRTUAL, COMMITTED, ALLOC_COUNT, FREE_COUNT, _, BUCKET_ID = range(6) - - -class Bucket(object): - """Represents a bucket, which is a unit of memory block classification.""" - - def __init__(self, stacktrace, allocator_type, typeinfo, typeinfo_name): - self._stacktrace = stacktrace - self._allocator_type = allocator_type - self._typeinfo = typeinfo - self._typeinfo_name = typeinfo_name - - self._symbolized_stackfunction = stacktrace - self._symbolized_joined_stackfunction = '' - self._symbolized_stacksourcefile = stacktrace - self._symbolized_joined_stacksourcefile = '' - self._symbolized_typeinfo = typeinfo_name - - self.component_cache = '' - - def __str__(self): - result = [] - result.append(self._allocator_type) - if self._symbolized_typeinfo == 'no typeinfo': - result.append('tno_typeinfo') - else: - result.append('t' + self._symbolized_typeinfo) - result.append('n' + self._typeinfo_name) - result.extend(['%s(@%s)' % (function, sourcefile) - for function, sourcefile - in zip(self._symbolized_stackfunction, - self._symbolized_stacksourcefile)]) - return ' '.join(result) - - def symbolize(self, symbol_mapping_cache): - """Makes a symbolized stacktrace and typeinfo with |symbol_mapping_cache|. - - Args: - symbol_mapping_cache: A SymbolMappingCache object. - """ - # TODO(dmikurube): Fill explicitly with numbers if symbol not found. - self._symbolized_stackfunction = [ - symbol_mapping_cache.lookup(FUNCTION_SYMBOLS, address) - for address in self._stacktrace] - self._symbolized_joined_stackfunction = ' '.join( - self._symbolized_stackfunction) - self._symbolized_stacksourcefile = [ - symbol_mapping_cache.lookup(SOURCEFILE_SYMBOLS, address) - for address in self._stacktrace] - self._symbolized_joined_stacksourcefile = ' '.join( - self._symbolized_stacksourcefile) - if not self._typeinfo: - self._symbolized_typeinfo = 'no typeinfo' - else: - self._symbolized_typeinfo = symbol_mapping_cache.lookup( - TYPEINFO_SYMBOLS, self._typeinfo) - if not self._symbolized_typeinfo: - self._symbolized_typeinfo = 'no typeinfo' - - def clear_component_cache(self): - self.component_cache = '' - - @property - def stacktrace(self): - return self._stacktrace - - @property - def allocator_type(self): - return self._allocator_type - - @property - def typeinfo(self): - return self._typeinfo - - @property - def typeinfo_name(self): - return self._typeinfo_name - - @property - def symbolized_stackfunction(self): - return self._symbolized_stackfunction - - @property - def symbolized_joined_stackfunction(self): - return self._symbolized_joined_stackfunction - - @property - def symbolized_stacksourcefile(self): - return self._symbolized_stacksourcefile - - @property - def symbolized_joined_stacksourcefile(self): - return self._symbolized_joined_stacksourcefile - - @property - def symbolized_typeinfo(self): - return self._symbolized_typeinfo - - -class BucketSet(object): - """Represents a set of bucket.""" - def __init__(self): - self._buckets = {} - self._code_addresses = set() - self._typeinfo_addresses = set() - - def load(self, prefix): - """Loads all related bucket files. - - Args: - prefix: A prefix string for bucket file names. - """ - LOGGER.info('Loading bucket files.') - - n = 0 - skipped = 0 - while True: - path = '%s.%04d.buckets' % (prefix, n) - if not os.path.exists(path) or not os.stat(path).st_size: - if skipped > 10: - break - n += 1 - skipped += 1 - continue - LOGGER.info(' %s' % path) - with open(path, 'r') as f: - self._load_file(f) - n += 1 - skipped = 0 - - def _load_file(self, bucket_f): - for line in bucket_f: - words = line.split() - typeinfo = None - typeinfo_name = '' - stacktrace_begin = 2 - for index, word in enumerate(words): - if index < 2: - continue - if word[0] == 't': - typeinfo = int(word[1:], 16) - self._typeinfo_addresses.add(typeinfo) - elif word[0] == 'n': - typeinfo_name = word[1:] - else: - stacktrace_begin = index - break - stacktrace = [int(address, 16) for address in words[stacktrace_begin:]] - for frame in stacktrace: - self._code_addresses.add(frame) - self._buckets[int(words[0])] = Bucket( - stacktrace, words[1], typeinfo, typeinfo_name) - - def __iter__(self): - for bucket_id, bucket_content in self._buckets.iteritems(): - yield bucket_id, bucket_content - - def __getitem__(self, bucket_id): - return self._buckets[bucket_id] - - def get(self, bucket_id): - return self._buckets.get(bucket_id) - - def symbolize(self, symbol_mapping_cache): - for bucket_content in self._buckets.itervalues(): - bucket_content.symbolize(symbol_mapping_cache) - - def clear_component_cache(self): - for bucket_content in self._buckets.itervalues(): - bucket_content.clear_component_cache() - - def iter_addresses(self, symbol_type): - if symbol_type in [FUNCTION_SYMBOLS, SOURCEFILE_SYMBOLS]: - for function in self._code_addresses: - yield function - else: - for function in self._typeinfo_addresses: - yield function diff --git a/tools/deep_memory_profiler/lib/dump.py b/tools/deep_memory_profiler/lib/dump.py deleted file mode 100644 index 115979e0f6..0000000000 --- a/tools/deep_memory_profiler/lib/dump.py +++ /dev/null @@ -1,487 +0,0 @@ -# Copyright 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import copy -import datetime -import logging -import os -import re -import time - -from lib.bucket import BUCKET_ID -from lib.exceptions import EmptyDumpException, InvalidDumpException -from lib.exceptions import ObsoleteDumpVersionException, ParsingException -from lib.pageframe import PageFrame -from lib.range_dict import ExclusiveRangeDict -from lib.symbol import proc_maps - - -LOGGER = logging.getLogger('dmprof') - - -# Heap Profile Dump versions - -# DUMP_DEEP_[1-4] are obsolete. -# DUMP_DEEP_2+ distinct mmap regions and malloc chunks. -# DUMP_DEEP_3+ don't include allocation functions in their stack dumps. -# DUMP_DEEP_4+ support comments with '#' and global stats "nonprofiled-*". -# DUMP_DEEP_[1-2] should be processed by POLICY_DEEP_1. -# DUMP_DEEP_[3-4] should be processed by POLICY_DEEP_2 or POLICY_DEEP_3. -DUMP_DEEP_1 = 'DUMP_DEEP_1' -DUMP_DEEP_2 = 'DUMP_DEEP_2' -DUMP_DEEP_3 = 'DUMP_DEEP_3' -DUMP_DEEP_4 = 'DUMP_DEEP_4' - -DUMP_DEEP_OBSOLETE = (DUMP_DEEP_1, DUMP_DEEP_2, DUMP_DEEP_3, DUMP_DEEP_4) - -# DUMP_DEEP_5 doesn't separate sections for malloc and mmap. -# malloc and mmap are identified in bucket files. -# DUMP_DEEP_5 should be processed by POLICY_DEEP_4. -DUMP_DEEP_5 = 'DUMP_DEEP_5' - -# DUMP_DEEP_6 adds a mmap list to DUMP_DEEP_5. -DUMP_DEEP_6 = 'DUMP_DEEP_6' - - -class Dump(object): - """Represents a heap profile dump.""" - - _PATH_PATTERN = re.compile(r'^(.*)\.([0-9]+)\.([0-9]+)\.heap$') - - _HOOK_PATTERN = re.compile( - r'^ ([ \(])([a-f0-9]+)([ \)])-([ \(])([a-f0-9]+)([ \)])\s+' - r'(hooked|unhooked)\s+(.+)$', re.IGNORECASE) - - _HOOKED_PATTERN = re.compile(r'(?P.+ )?(?P[0-9]+) / ' - '(?P[0-9]+) @ (?P[0-9]+)') - _UNHOOKED_PATTERN = re.compile(r'(?P.+ )?(?P[0-9]+) / ' - '(?P[0-9]+)') - - _OLD_HOOKED_PATTERN = re.compile(r'(?P.+) @ (?P[0-9]+)') - _OLD_UNHOOKED_PATTERN = re.compile(r'(?P.+) (?P[0-9]+)') - - _TIME_PATTERN_FORMAT = re.compile( - r'^Time: ([0-9]+/[0-9]+/[0-9]+ [0-9]+:[0-9]+:[0-9]+)(\.[0-9]+)?') - _TIME_PATTERN_SECONDS = re.compile(r'^Time: ([0-9]+)$') - - def __init__(self, path, modified_time): - self._path = path - matched = self._PATH_PATTERN.match(path) - self._pid = int(matched.group(2)) - self._count = int(matched.group(3)) - self._time = modified_time - self._map = {} - self._procmaps = ExclusiveRangeDict(ProcMapsEntryAttribute) - self._stacktrace_lines = [] - self._global_stats = {} # used only in apply_policy - - self._run_id = '' - self._pagesize = 4096 - self._pageframe_length = 0 - self._pageframe_encoding = '' - self._has_pagecount = False - - self._version = '' - self._lines = [] - - @property - def path(self): - return self._path - - @property - def count(self): - return self._count - - @property - def time(self): - return self._time - - @property - def iter_map(self): - for region in sorted(self._map.iteritems()): - yield region[0], region[1] - - def iter_procmaps(self): - for begin, end, attr in self._map.iter_range(): - yield begin, end, attr - - @property - def iter_stacktrace(self): - for line in self._stacktrace_lines: - yield line - - def global_stat(self, name): - return self._global_stats[name] - - @property - def run_id(self): - return self._run_id - - @property - def pagesize(self): - return self._pagesize - - @property - def pageframe_length(self): - return self._pageframe_length - - @property - def pageframe_encoding(self): - return self._pageframe_encoding - - @property - def has_pagecount(self): - return self._has_pagecount - - @staticmethod - def load(path, log_header='Loading a heap profile dump: '): - """Loads a heap profile dump. - - Args: - path: A file path string to load. - log_header: A preceding string for log messages. - - Returns: - A loaded Dump object. - - Raises: - ParsingException for invalid heap profile dumps. - """ - dump = Dump(path, os.stat(path).st_mtime) - with open(path, 'r') as f: - dump.load_file(f, log_header) - return dump - - def load_file(self, f, log_header): - self._lines = [line for line in f - if line and not line.startswith('#')] - - try: - self._version, ln = self._parse_version() - self._parse_meta_information() - if self._version == DUMP_DEEP_6: - self._parse_mmap_list() - self._parse_global_stats() - self._extract_stacktrace_lines(ln) - except EmptyDumpException: - LOGGER.info('%s%s ...ignored an empty dump.' % (log_header, self._path)) - except ParsingException, e: - LOGGER.error('%s%s ...error %s' % (log_header, self._path, e)) - raise - else: - LOGGER.info('%s%s (version:%s)' % (log_header, self._path, self._version)) - - def _parse_version(self): - """Parses a version string in self._lines. - - Returns: - A pair of (a string representing a version of the stacktrace dump, - and an integer indicating a line number next to the version string). - - Raises: - ParsingException for invalid dump versions. - """ - version = '' - - # Skip until an identifiable line. - headers = ('STACKTRACES:\n', 'MMAP_STACKTRACES:\n', 'heap profile: ') - if not self._lines: - raise EmptyDumpException('Empty heap dump file.') - (ln, found) = skip_while( - 0, len(self._lines), - lambda n: not self._lines[n].startswith(headers)) - if not found: - raise InvalidDumpException('No version header.') - - # Identify a version. - if self._lines[ln].startswith('heap profile: '): - version = self._lines[ln][13:].strip() - if version in (DUMP_DEEP_5, DUMP_DEEP_6): - (ln, _) = skip_while( - ln, len(self._lines), - lambda n: self._lines[n] != 'STACKTRACES:\n') - elif version in DUMP_DEEP_OBSOLETE: - raise ObsoleteDumpVersionException(version) - else: - raise InvalidDumpException('Invalid version: %s' % version) - elif self._lines[ln] == 'STACKTRACES:\n': - raise ObsoleteDumpVersionException(DUMP_DEEP_1) - elif self._lines[ln] == 'MMAP_STACKTRACES:\n': - raise ObsoleteDumpVersionException(DUMP_DEEP_2) - - return (version, ln) - - def _parse_global_stats(self): - """Parses lines in self._lines as global stats.""" - (ln, _) = skip_while( - 0, len(self._lines), - lambda n: self._lines[n] != 'GLOBAL_STATS:\n') - - global_stat_names = [ - 'total', 'absent', 'file-exec', 'file-nonexec', 'anonymous', 'stack', - 'other', 'nonprofiled-absent', 'nonprofiled-anonymous', - 'nonprofiled-file-exec', 'nonprofiled-file-nonexec', - 'nonprofiled-stack', 'nonprofiled-other', - 'profiled-mmap', 'profiled-malloc'] - - for prefix in global_stat_names: - (ln, _) = skip_while( - ln, len(self._lines), - lambda n: self._lines[n].split()[0] != prefix) - words = self._lines[ln].split() - self._global_stats[prefix + '_virtual'] = int(words[-2]) - self._global_stats[prefix + '_committed'] = int(words[-1]) - - def _parse_meta_information(self): - """Parses lines in self._lines for meta information.""" - (ln, found) = skip_while( - 0, len(self._lines), - lambda n: self._lines[n] != 'META:\n') - if not found: - return - ln += 1 - - while True: - if self._lines[ln].startswith('Time:'): - matched_seconds = self._TIME_PATTERN_SECONDS.match(self._lines[ln]) - matched_format = self._TIME_PATTERN_FORMAT.match(self._lines[ln]) - if matched_format: - self._time = time.mktime(datetime.datetime.strptime( - matched_format.group(1), '%Y/%m/%d %H:%M:%S').timetuple()) - if matched_format.group(2): - self._time += float(matched_format.group(2)[1:]) / 1000.0 - elif matched_seconds: - self._time = float(matched_seconds.group(1)) - elif self._lines[ln].startswith('Reason:'): - pass # Nothing to do for 'Reason:' - elif self._lines[ln].startswith('PageSize: '): - self._pagesize = int(self._lines[ln][10:]) - elif self._lines[ln].startswith('CommandLine:'): - pass - elif (self._lines[ln].startswith('PageFrame: ') or - self._lines[ln].startswith('PFN: ')): - if self._lines[ln].startswith('PageFrame: '): - words = self._lines[ln][11:].split(',') - else: - words = self._lines[ln][5:].split(',') - for word in words: - if word == '24': - self._pageframe_length = 24 - elif word == 'Base64': - self._pageframe_encoding = 'base64' - elif word == 'PageCount': - self._has_pagecount = True - elif self._lines[ln].startswith('RunID: '): - self._run_id = self._lines[ln][7:].strip() - elif (self._lines[ln].startswith('MMAP_LIST:') or - self._lines[ln].startswith('GLOBAL_STATS:')): - # Skip until "MMAP_LIST:" or "GLOBAL_STATS" is found. - break - else: - pass - ln += 1 - - def _parse_mmap_list(self): - """Parses lines in self._lines as a mmap list.""" - (ln, found) = skip_while( - 0, len(self._lines), - lambda n: self._lines[n] != 'MMAP_LIST:\n') - if not found: - return {} - - ln += 1 - self._map = {} - current_vma = {} - pageframe_list = [] - while True: - entry = proc_maps.ProcMaps.parse_line(self._lines[ln]) - if entry: - current_vma = {} - for _, _, attr in self._procmaps.iter_range(entry.begin, entry.end): - for key, value in entry.as_dict().iteritems(): - attr[key] = value - current_vma[key] = value - ln += 1 - continue - - if self._lines[ln].startswith(' PF: '): - for pageframe in self._lines[ln][5:].split(): - pageframe_list.append(PageFrame.parse(pageframe, self._pagesize)) - ln += 1 - continue - - matched = self._HOOK_PATTERN.match(self._lines[ln]) - if not matched: - break - # 2: starting address - # 5: end address - # 7: hooked or unhooked - # 8: additional information - if matched.group(7) == 'hooked': - submatched = self._HOOKED_PATTERN.match(matched.group(8)) - if not submatched: - submatched = self._OLD_HOOKED_PATTERN.match(matched.group(8)) - elif matched.group(7) == 'unhooked': - submatched = self._UNHOOKED_PATTERN.match(matched.group(8)) - if not submatched: - submatched = self._OLD_UNHOOKED_PATTERN.match(matched.group(8)) - else: - assert matched.group(7) in ['hooked', 'unhooked'] - - submatched_dict = submatched.groupdict() - region_info = { 'vma': current_vma } - if submatched_dict.get('TYPE'): - region_info['type'] = submatched_dict['TYPE'].strip() - if submatched_dict.get('COMMITTED'): - region_info['committed'] = int(submatched_dict['COMMITTED']) - if submatched_dict.get('RESERVED'): - region_info['reserved'] = int(submatched_dict['RESERVED']) - if submatched_dict.get('BUCKETID'): - region_info['bucket_id'] = int(submatched_dict['BUCKETID']) - - if matched.group(1) == '(': - start = current_vma['begin'] - else: - start = int(matched.group(2), 16) - if matched.group(4) == '(': - end = current_vma['end'] - else: - end = int(matched.group(5), 16) - - if pageframe_list and pageframe_list[0].start_truncated: - pageframe_list[0].set_size( - pageframe_list[0].size - start % self._pagesize) - if pageframe_list and pageframe_list[-1].end_truncated: - pageframe_list[-1].set_size( - pageframe_list[-1].size - (self._pagesize - end % self._pagesize)) - region_info['pageframe'] = pageframe_list - pageframe_list = [] - - self._map[(start, end)] = (matched.group(7), region_info) - ln += 1 - - def _extract_stacktrace_lines(self, line_number): - """Extracts the position of stacktrace lines. - - Valid stacktrace lines are stored into self._stacktrace_lines. - - Args: - line_number: A line number to start parsing in lines. - - Raises: - ParsingException for invalid dump versions. - """ - if self._version in (DUMP_DEEP_5, DUMP_DEEP_6): - (line_number, _) = skip_while( - line_number, len(self._lines), - lambda n: not self._lines[n].split()[0].isdigit()) - stacktrace_start = line_number - (line_number, _) = skip_while( - line_number, len(self._lines), - lambda n: self._check_stacktrace_line(self._lines[n])) - self._stacktrace_lines = self._lines[stacktrace_start:line_number] - - elif self._version in DUMP_DEEP_OBSOLETE: - raise ObsoleteDumpVersionException(self._version) - - else: - raise InvalidDumpException('Invalid version: %s' % self._version) - - @staticmethod - def _check_stacktrace_line(stacktrace_line): - """Checks if a given stacktrace_line is valid as stacktrace. - - Args: - stacktrace_line: A string to be checked. - - Returns: - True if the given stacktrace_line is valid. - """ - words = stacktrace_line.split() - if len(words) < BUCKET_ID + 1: - return False - if words[BUCKET_ID - 1] != '@': - return False - return True - - -class DumpList(object): - """Represents a sequence of heap profile dumps.""" - - def __init__(self, dump_list): - self._dump_list = dump_list - - @staticmethod - def load(path_list): - LOGGER.info('Loading heap dump profiles.') - dump_list = [] - for path in path_list: - dump_list.append(Dump.load(path, ' ')) - return DumpList(dump_list) - - def __len__(self): - return len(self._dump_list) - - def __iter__(self): - for dump in self._dump_list: - yield dump - - def __getitem__(self, index): - return self._dump_list[index] - - -class ProcMapsEntryAttribute(ExclusiveRangeDict.RangeAttribute): - """Represents an entry of /proc/maps in range_dict.ExclusiveRangeDict.""" - _DUMMY_ENTRY = proc_maps.ProcMapsEntry( - 0, # begin - 0, # end - '-', # readable - '-', # writable - '-', # executable - '-', # private - 0, # offset - '00', # major - '00', # minor - 0, # inode - '' # name - ) - - def __init__(self): - super(ProcMapsEntryAttribute, self).__init__() - self._entry = self._DUMMY_ENTRY.as_dict() - - def __str__(self): - return str(self._entry) - - def __repr__(self): - return 'ProcMapsEntryAttribute' + str(self._entry) - - def __getitem__(self, key): - return self._entry[key] - - def __setitem__(self, key, value): - if key not in self._entry: - raise KeyError(key) - self._entry[key] = value - - def copy(self): - new_entry = ProcMapsEntryAttribute() - for key, value in self._entry.iteritems(): - new_entry[key] = copy.deepcopy(value) - return new_entry - - -def skip_while(index, max_index, skipping_condition): - """Increments |index| until |skipping_condition|(|index|) is False. - - Returns: - A pair of an integer indicating a line number after skipped, and a - boolean value which is True if found a line which skipping_condition - is False for. - """ - while skipping_condition(index): - index += 1 - if index >= max_index: - return index, False - return index, True diff --git a/tools/deep_memory_profiler/lib/exceptions.py b/tools/deep_memory_profiler/lib/exceptions.py deleted file mode 100644 index 2c68af72cc..0000000000 --- a/tools/deep_memory_profiler/lib/exceptions.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -class EmptyDumpException(Exception): - def __str__(self): - return repr(self.args[0]) - - -class ParsingException(Exception): - def __str__(self): - return repr(self.args[0]) - - -class InvalidDumpException(ParsingException): - def __str__(self): - return "invalid heap profile dump: %s" % repr(self.args[0]) - - -class ObsoleteDumpVersionException(ParsingException): - def __str__(self): - return "obsolete heap profile dump version: %s" % repr(self.args[0]) diff --git a/tools/deep_memory_profiler/lib/ordered_dict.py b/tools/deep_memory_profiler/lib/ordered_dict.py deleted file mode 100644 index f7d053bd34..0000000000 --- a/tools/deep_memory_profiler/lib/ordered_dict.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# TODO(dmikurube): Remove this file once Python 2.7 is required. - -import os -import sys - -try: - from collections import OrderedDict # pylint: disable=E0611,W0611 -except ImportError: - _BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - _SIMPLEJSON_PATH = os.path.join(_BASE_PATH, - os.pardir, - os.pardir, - 'third_party') - sys.path.insert(0, _SIMPLEJSON_PATH) - from simplejson import OrderedDict # pylint: disable=W0611 diff --git a/tools/deep_memory_profiler/lib/pageframe.py b/tools/deep_memory_profiler/lib/pageframe.py deleted file mode 100644 index 8722243baf..0000000000 --- a/tools/deep_memory_profiler/lib/pageframe.py +++ /dev/null @@ -1,163 +0,0 @@ -# Copyright 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import logging -import os -import re -import struct - - -LOGGER = logging.getLogger('dmprof') - - -class PageFrame(object): - """Represents a pageframe and maybe its shared count.""" - def __init__(self, pfn, size, pagecount, start_truncated, end_truncated): - self._pfn = pfn - self._size = size - self._pagecount = pagecount - self._start_truncated = start_truncated - self._end_truncated = end_truncated - - def __str__(self): - result = str() - if self._start_truncated: - result += '<' - result += '%06x#%d' % (self._pfn, self._pagecount) - if self._end_truncated: - result += '>' - return result - - def __repr__(self): - return str(self) - - @staticmethod - def parse(encoded_pfn, size): - start = 0 - end = len(encoded_pfn) - end_truncated = False - if encoded_pfn.endswith('>'): - end = len(encoded_pfn) - 1 - end_truncated = True - pagecount_found = encoded_pfn.find('#') - pagecount = None - if pagecount_found >= 0: - encoded_pagecount = 'AAA' + encoded_pfn[pagecount_found+1 : end] - pagecount = struct.unpack( - '>I', '\x00' + encoded_pagecount.decode('base64'))[0] - end = pagecount_found - start_truncated = False - if encoded_pfn.startswith('<'): - start = 1 - start_truncated = True - - pfn = struct.unpack( - '>I', '\x00' + (encoded_pfn[start:end]).decode('base64'))[0] - - return PageFrame(pfn, size, pagecount, start_truncated, end_truncated) - - @property - def pfn(self): - return self._pfn - - @property - def size(self): - return self._size - - def set_size(self, size): - self._size = size - - @property - def pagecount(self): - return self._pagecount - - @property - def start_truncated(self): - return self._start_truncated - - @property - def end_truncated(self): - return self._end_truncated - - -class PFNCounts(object): - """Represents counts of PFNs in a process.""" - - _PATH_PATTERN = re.compile(r'^(.*)\.([0-9]+)\.([0-9]+)\.heap$') - - def __init__(self, path, modified_time): - matched = self._PATH_PATTERN.match(path) - if matched: - self._pid = int(matched.group(2)) - else: - self._pid = 0 - self._command_line = '' - self._pagesize = 4096 - self._path = path - self._pfn_meta = '' - self._pfnset = {} - self._reason = '' - self._time = modified_time - - @staticmethod - def load(path, log_header='Loading PFNs from a heap profile dump: '): - pfnset = PFNCounts(path, float(os.stat(path).st_mtime)) - LOGGER.info('%s%s' % (log_header, path)) - - with open(path, 'r') as pfnset_f: - pfnset.load_file(pfnset_f) - - return pfnset - - @property - def path(self): - return self._path - - @property - def pid(self): - return self._pid - - @property - def time(self): - return self._time - - @property - def reason(self): - return self._reason - - @property - def iter_pfn(self): - for pfn, count in self._pfnset.iteritems(): - yield pfn, count - - def load_file(self, pfnset_f): - prev_pfn_end_truncated = None - for line in pfnset_f: - line = line.strip() - if line.startswith('GLOBAL_STATS:') or line.startswith('STACKTRACES:'): - break - elif line.startswith('PF: '): - for encoded_pfn in line[3:].split(): - page_frame = PageFrame.parse(encoded_pfn, self._pagesize) - if page_frame.start_truncated and ( - not prev_pfn_end_truncated or - prev_pfn_end_truncated != page_frame.pfn): - LOGGER.error('Broken page frame number: %s.' % encoded_pfn) - self._pfnset[page_frame.pfn] = self._pfnset.get(page_frame.pfn, 0) + 1 - if page_frame.end_truncated: - prev_pfn_end_truncated = page_frame.pfn - else: - prev_pfn_end_truncated = None - elif line.startswith('PageSize: '): - self._pagesize = int(line[10:]) - elif line.startswith('PFN: '): - self._pfn_meta = line[5:] - elif line.startswith('PageFrame: '): - self._pfn_meta = line[11:] - elif line.startswith('Time: '): - self._time = float(line[6:]) - elif line.startswith('CommandLine: '): - self._command_line = line[13:] - elif line.startswith('Reason: '): - self._reason = line[8:] diff --git a/tools/deep_memory_profiler/lib/policy.py b/tools/deep_memory_profiler/lib/policy.py deleted file mode 100644 index d7a38977eb..0000000000 --- a/tools/deep_memory_profiler/lib/policy.py +++ /dev/null @@ -1,404 +0,0 @@ -# Copyright 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import json -import logging -import os -import re - - -LOGGER = logging.getLogger('dmprof') - -BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) -POLICIES_JSON_PATH = os.path.join(BASE_PATH, 'policies.json') - -# Heap Profile Policy versions - -# POLICY_DEEP_1 DOES NOT include allocation_type columns. -# mmap regions are distincted w/ mmap frames in the pattern column. -POLICY_DEEP_1 = 'POLICY_DEEP_1' - -# POLICY_DEEP_2 DOES include allocation_type columns. -# mmap regions are distincted w/ the allocation_type column. -POLICY_DEEP_2 = 'POLICY_DEEP_2' - -# POLICY_DEEP_3 is in JSON format. -POLICY_DEEP_3 = 'POLICY_DEEP_3' - -# POLICY_DEEP_3 contains typeinfo. -POLICY_DEEP_4 = 'POLICY_DEEP_4' - - -class Rule(object): - """Represents one matching rule in a policy file.""" - - def __init__(self, - name, - allocator_type, - stackfunction_pattern=None, - stacksourcefile_pattern=None, - typeinfo_pattern=None, - mappedpathname_pattern=None, - mappedpermission_pattern=None, - sharedwith=None): - self._name = name - self._allocator_type = allocator_type - - self._stackfunction_pattern = None - if stackfunction_pattern: - self._stackfunction_pattern = re.compile( - stackfunction_pattern + r'\Z') - - self._stacksourcefile_pattern = None - if stacksourcefile_pattern: - self._stacksourcefile_pattern = re.compile( - stacksourcefile_pattern + r'\Z') - - self._typeinfo_pattern = None - if typeinfo_pattern: - self._typeinfo_pattern = re.compile(typeinfo_pattern + r'\Z') - - self._mappedpathname_pattern = None - if mappedpathname_pattern: - self._mappedpathname_pattern = re.compile(mappedpathname_pattern + r'\Z') - - self._mappedpermission_pattern = None - if mappedpermission_pattern: - self._mappedpermission_pattern = re.compile( - mappedpermission_pattern + r'\Z') - - self._sharedwith = [] - if sharedwith: - self._sharedwith = sharedwith - - @property - def name(self): - return self._name - - @property - def allocator_type(self): - return self._allocator_type - - @property - def stackfunction_pattern(self): - return self._stackfunction_pattern - - @property - def stacksourcefile_pattern(self): - return self._stacksourcefile_pattern - - @property - def typeinfo_pattern(self): - return self._typeinfo_pattern - - @property - def mappedpathname_pattern(self): - return self._mappedpathname_pattern - - @property - def mappedpermission_pattern(self): - return self._mappedpermission_pattern - - @property - def sharedwith(self): - return self._sharedwith - - -class Policy(object): - """Represents a policy, a content of a policy file.""" - - def __init__(self, rules, version, components): - self._rules = rules - self._version = version - self._components = components - - @property - def rules(self): - return self._rules - - @property - def version(self): - return self._version - - @property - def components(self): - return self._components - - def find_rule(self, component_name): - """Finds a rule whose name is |component_name|. """ - for rule in self._rules: - if rule.name == component_name: - return rule - return None - - def find_malloc(self, bucket): - """Finds a matching component name which a given |bucket| belongs to. - - Args: - bucket: A Bucket object to be searched for. - - Returns: - A string representing a component name. - """ - assert not bucket or bucket.allocator_type == 'malloc' - - if not bucket: - return 'no-bucket' - if bucket.component_cache: - return bucket.component_cache - - stackfunction = bucket.symbolized_joined_stackfunction - stacksourcefile = bucket.symbolized_joined_stacksourcefile - typeinfo = bucket.symbolized_typeinfo - if typeinfo.startswith('0x'): - typeinfo = bucket.typeinfo_name - - for rule in self._rules: - if (rule.allocator_type == 'malloc' and - (not rule.stackfunction_pattern or - rule.stackfunction_pattern.match(stackfunction)) and - (not rule.stacksourcefile_pattern or - rule.stacksourcefile_pattern.match(stacksourcefile)) and - (not rule.typeinfo_pattern or rule.typeinfo_pattern.match(typeinfo))): - bucket.component_cache = rule.name - return rule.name - - assert False - - def find_mmap(self, region, bucket_set, - pageframe=None, group_pfn_counts=None): - """Finds a matching component which a given mmap |region| belongs to. - - It uses |bucket_set| to match with backtraces. If |pageframe| is given, - it considers memory sharing among processes. - - NOTE: Don't use Bucket's |component_cache| for mmap regions because they're - classified not only with bucket information (mappedpathname for example). - - Args: - region: A tuple representing a memory region. - bucket_set: A BucketSet object to look up backtraces. - pageframe: A PageFrame object representing a pageframe maybe including - a pagecount. - group_pfn_counts: A dict mapping a PFN to the number of times the - the pageframe is mapped by the known "group (Chrome)" processes. - - Returns: - A string representing a component name. - """ - assert region[0] == 'hooked' - bucket = bucket_set.get(region[1]['bucket_id']) - assert not bucket or bucket.allocator_type == 'mmap' - - if not bucket: - return 'no-bucket', None - - stackfunction = bucket.symbolized_joined_stackfunction - stacksourcefile = bucket.symbolized_joined_stacksourcefile - sharedwith = self._categorize_pageframe(pageframe, group_pfn_counts) - - for rule in self._rules: - if (rule.allocator_type == 'mmap' and - (not rule.stackfunction_pattern or - rule.stackfunction_pattern.match(stackfunction)) and - (not rule.stacksourcefile_pattern or - rule.stacksourcefile_pattern.match(stacksourcefile)) and - (not rule.mappedpathname_pattern or - rule.mappedpathname_pattern.match(region[1]['vma']['name'])) and - (not rule.mappedpermission_pattern or - rule.mappedpermission_pattern.match( - region[1]['vma']['readable'] + - region[1]['vma']['writable'] + - region[1]['vma']['executable'] + - region[1]['vma']['private'])) and - (not rule.sharedwith or - not pageframe or sharedwith in rule.sharedwith)): - return rule.name, bucket - - assert False - - def find_unhooked(self, region, pageframe=None, group_pfn_counts=None): - """Finds a matching component which a given unhooked |region| belongs to. - - If |pageframe| is given, it considers memory sharing among processes. - - Args: - region: A tuple representing a memory region. - pageframe: A PageFrame object representing a pageframe maybe including - a pagecount. - group_pfn_counts: A dict mapping a PFN to the number of times the - the pageframe is mapped by the known "group (Chrome)" processes. - - Returns: - A string representing a component name. - """ - assert region[0] == 'unhooked' - sharedwith = self._categorize_pageframe(pageframe, group_pfn_counts) - - for rule in self._rules: - if (rule.allocator_type == 'unhooked' and - (not rule.mappedpathname_pattern or - rule.mappedpathname_pattern.match(region[1]['vma']['name'])) and - (not rule.mappedpermission_pattern or - rule.mappedpermission_pattern.match( - region[1]['vma']['readable'] + - region[1]['vma']['writable'] + - region[1]['vma']['executable'] + - region[1]['vma']['private'])) and - (not rule.sharedwith or - not pageframe or sharedwith in rule.sharedwith)): - return rule.name - - assert False - - @staticmethod - def load(filename, filetype): - """Loads a policy file of |filename| in a |format|. - - Args: - filename: A filename to be loaded. - filetype: A string to specify a type of the file. Only 'json' is - supported for now. - - Returns: - A loaded Policy object. - """ - with open(os.path.join(BASE_PATH, filename)) as policy_f: - return Policy.parse(policy_f, filetype) - - @staticmethod - def parse(policy_f, filetype): - """Parses a policy file content in a |format|. - - Args: - policy_f: An IO object to be loaded. - filetype: A string to specify a type of the file. Only 'json' is - supported for now. - - Returns: - A loaded Policy object. - """ - if filetype == 'json': - return Policy._parse_json(policy_f) - else: - return None - - @staticmethod - def _parse_json(policy_f): - """Parses policy file in json format. - - A policy file contains component's names and their stacktrace pattern - written in regular expression. Those patterns are matched against each - symbols of each stacktraces in the order written in the policy file - - Args: - policy_f: A File/IO object to read. - - Returns: - A loaded policy object. - """ - policy = json.load(policy_f) - - rules = [] - for rule in policy['rules']: - stackfunction = rule.get('stackfunction') or rule.get('stacktrace') - stacksourcefile = rule.get('stacksourcefile') - rules.append(Rule( - rule['name'], - rule['allocator'], # allocator_type - stackfunction, - stacksourcefile, - rule['typeinfo'] if 'typeinfo' in rule else None, - rule.get('mappedpathname'), - rule.get('mappedpermission'), - rule.get('sharedwith'))) - - return Policy(rules, policy['version'], policy['components']) - - @staticmethod - def _categorize_pageframe(pageframe, group_pfn_counts): - """Categorizes a pageframe based on its sharing status. - - Returns: - 'private' if |pageframe| is not shared with other processes. 'group' - if |pageframe| is shared only with group (Chrome-related) processes. - 'others' if |pageframe| is shared with non-group processes. - """ - if not pageframe: - return 'private' - - if pageframe.pagecount: - if pageframe.pagecount == 1: - return 'private' - elif pageframe.pagecount <= group_pfn_counts.get(pageframe.pfn, 0) + 1: - return 'group' - else: - return 'others' - else: - if pageframe.pfn in group_pfn_counts: - return 'group' - else: - return 'private' - - -class PolicySet(object): - """Represents a set of policies.""" - - def __init__(self, policy_directory): - self._policy_directory = policy_directory - - @staticmethod - def load(labels=None): - """Loads a set of policies via the "default policy directory". - - The "default policy directory" contains pairs of policies and their labels. - For example, a policy "policy.l0.json" is labeled "l0" in the default - policy directory "policies.json". - - All policies in the directory are loaded by default. Policies can be - limited by |labels|. - - Args: - labels: An array that contains policy labels to be loaded. - - Returns: - A PolicySet object. - """ - default_policy_directory = PolicySet._load_default_policy_directory() - if labels: - specified_policy_directory = {} - for label in labels: - if label in default_policy_directory: - specified_policy_directory[label] = default_policy_directory[label] - # TODO(dmikurube): Load an un-labeled policy file. - return PolicySet._load_policies(specified_policy_directory) - else: - return PolicySet._load_policies(default_policy_directory) - - def __len__(self): - return len(self._policy_directory) - - def __iter__(self): - for label in self._policy_directory: - yield label - - def __getitem__(self, label): - return self._policy_directory[label] - - @staticmethod - def _load_default_policy_directory(): - with open(POLICIES_JSON_PATH, mode='r') as policies_f: - default_policy_directory = json.load(policies_f) - return default_policy_directory - - @staticmethod - def _load_policies(directory): - LOGGER.info('Loading policy files.') - policies = {} - for label in directory: - LOGGER.info(' %s: %s' % (label, directory[label]['file'])) - loaded = Policy.load(directory[label]['file'], directory[label]['format']) - if loaded: - policies[label] = loaded - return PolicySet(policies) diff --git a/tools/deep_memory_profiler/lib/range_dict.py b/tools/deep_memory_profiler/lib/range_dict.py deleted file mode 100644 index 565789d561..0000000000 --- a/tools/deep_memory_profiler/lib/range_dict.py +++ /dev/null @@ -1,144 +0,0 @@ -# Copyright 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import os -import sys - -_BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) -_BINTREES_PATH = os.path.join( - _BASE_PATH, os.pardir, os.pardir, 'third_party', 'bintrees') -sys.path.insert(0, _BINTREES_PATH) - -from bintrees import FastRBTree # pylint: disable=F0401 - - -class ExclusiveRangeDict(object): - """A class like dict whose key is a range [begin, end) of integers. - - It has an attribute for each range of integers, for example: - [10, 20) => Attribute(0), - [20, 40) => Attribute(1), - [40, 50) => Attribute(2), - ... - - An instance of this class is accessed only via iter_range(begin, end). - The instance is accessed as follows: - - 1) If the given range [begin, end) is not covered by the instance, - the range is newly created and iterated. - - 2) If the given range [begin, end) exactly covers ranges in the instance, - the ranges are iterated. - (See test_set() in tests/range_dict_tests.py.) - - 3) If the given range [begin, end) starts at and/or ends at a mid-point of - an existing range, the existing range is split by the given range, and - ranges in the given range are iterated. For example, consider a case that - [25, 45) is given to an instance of [20, 30), [30, 40), [40, 50). In this - case, [20, 30) is split into [20, 25) and [25, 30), and [40, 50) into - [40, 45) and [45, 50). Then, [25, 30), [30, 40), [40, 45) are iterated. - (See test_split() in tests/range_dict_tests.py.) - - 4) If the given range [begin, end) includes non-existing ranges in an - instance, the gaps are filled with new ranges, and all ranges are iterated. - For example, consider a case that [25, 50) is given to an instance of - [30, 35) and [40, 45). In this case, [25, 30), [35, 40) and [45, 50) are - created in the instance, and then [25, 30), [30, 35), [35, 40), [40, 45) - and [45, 50) are iterated. - (See test_fill() in tests/range_dict_tests.py.) - """ - class RangeAttribute(object): - def __init__(self): - pass - - def __str__(self): - return '' - - def __repr__(self): - return '' - - def copy(self): # pylint: disable=R0201 - return ExclusiveRangeDict.RangeAttribute() - - def __init__(self, attr=RangeAttribute): - self._tree = FastRBTree() - self._attr = attr - - def iter_range(self, begin=None, end=None): - if not begin: - begin = self._tree.min_key() - if not end: - end = self._tree.max_item()[1][0] - - # Assume that self._tree has at least one element. - if self._tree.is_empty(): - self._tree[begin] = (end, self._attr()) - - # Create a beginning range (border) - try: - bound_begin, bound_value = self._tree.floor_item(begin) - bound_end = bound_value[0] - if begin >= bound_end: - # Create a blank range. - try: - new_end, _ = self._tree.succ_item(bound_begin) - except KeyError: - new_end = end - self._tree[begin] = (min(end, new_end), self._attr()) - elif bound_begin < begin and begin < bound_end: - # Split the existing range. - new_end = bound_value[0] - new_value = bound_value[1] - self._tree[bound_begin] = (begin, new_value.copy()) - self._tree[begin] = (new_end, new_value.copy()) - else: # bound_begin == begin - # Do nothing (just saying it clearly since this part is confusing) - pass - except KeyError: # begin is less than the smallest element. - # Create a blank range. - # Note that we can assume self._tree has at least one element. - self._tree[begin] = (min(end, self._tree.min_key()), self._attr()) - - # Create an ending range (border) - try: - bound_begin, bound_value = self._tree.floor_item(end) - bound_end = bound_value[0] - if end > bound_end: - # Create a blank range. - new_begin = bound_end - self._tree[new_begin] = (end, self._attr()) - elif bound_begin < end and end < bound_end: - # Split the existing range. - new_end = bound_value[0] - new_value = bound_value[1] - self._tree[bound_begin] = (end, new_value.copy()) - self._tree[end] = (new_end, new_value.copy()) - else: # bound_begin == begin - # Do nothing (just saying it clearly since this part is confusing) - pass - except KeyError: # end is less than the smallest element. - # It must not happen. A blank range [begin,end) has already been created - # even if [begin,end) is less than the smallest range. - # Do nothing (just saying it clearly since this part is confusing) - raise - - missing_ranges = [] - - prev_end = None - for range_begin, range_value in self._tree.itemslice(begin, end): - range_end = range_value[0] - # Note that we can assume that we have a range beginning with |begin| - # and a range ending with |end| (they may be the same range). - if prev_end and prev_end != range_begin: - missing_ranges.append((prev_end, range_begin)) - prev_end = range_end - - for missing_begin, missing_end in missing_ranges: - self._tree[missing_begin] = (missing_end, self._attr()) - - for range_begin, range_value in self._tree.itemslice(begin, end): - yield range_begin, range_value[0], range_value[1] - - def __str__(self): - return str(self._tree) diff --git a/tools/deep_memory_profiler/lib/sorter.py b/tools/deep_memory_profiler/lib/sorter.py deleted file mode 100644 index 64e0851e17..0000000000 --- a/tools/deep_memory_profiler/lib/sorter.py +++ /dev/null @@ -1,470 +0,0 @@ -# Copyright 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import cStringIO -import json -import logging -import os -import re - - -LOGGER = logging.getLogger('dmprof') - -BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - -DEFAULT_SORTERS = [ - os.path.join(BASE_PATH, 'sorter.malloc-component.json'), - os.path.join(BASE_PATH, 'sorter.malloc-type.json'), - os.path.join(BASE_PATH, 'sorter.vm-map.json'), - os.path.join(BASE_PATH, 'sorter.vm-sharing.json'), - ] - -DEFAULT_TEMPLATES = os.path.join(BASE_PATH, 'templates.json') - - -class Unit(object): - """Represents a minimum unit of memory usage categorization. - - It is supposed to be inherited for some different spaces like the entire - virtual memory and malloc arena. Such different spaces are called "worlds" - in dmprof. (For example, the "vm" world and the "malloc" world.) - """ - def __init__(self, unit_id, size): - self._unit_id = unit_id - self._size = size - - @property - def unit_id(self): - return self._unit_id - - @property - def size(self): - return self._size - - -class VMUnit(Unit): - """Represents a Unit for a memory region on virtual memory.""" - def __init__(self, unit_id, committed, reserved, mmap, region, - pageframe=None, group_pfn_counts=None): - super(VMUnit, self).__init__(unit_id, committed) - self._reserved = reserved - self._mmap = mmap - self._region = region - self._pageframe = pageframe - self._group_pfn_counts = group_pfn_counts - - @property - def committed(self): - return self._size - - @property - def reserved(self): - return self._reserved - - @property - def mmap(self): - return self._mmap - - @property - def region(self): - return self._region - - @property - def pageframe(self): - return self._pageframe - - @property - def group_pfn_counts(self): - return self._group_pfn_counts - - -class MMapUnit(VMUnit): - """Represents a Unit for a mmap'ed region.""" - def __init__(self, unit_id, committed, reserved, region, bucket_set, - pageframe=None, group_pfn_counts=None): - super(MMapUnit, self).__init__(unit_id, committed, reserved, True, - region, pageframe, group_pfn_counts) - self._bucket_set = bucket_set - - def __repr__(self): - return str(self.region) - - @property - def bucket_set(self): - return self._bucket_set - - -class UnhookedUnit(VMUnit): - """Represents a Unit for a non-mmap'ed memory region on virtual memory.""" - def __init__(self, unit_id, committed, reserved, region, - pageframe=None, group_pfn_counts=None): - super(UnhookedUnit, self).__init__(unit_id, committed, reserved, False, - region, pageframe, group_pfn_counts) - - def __repr__(self): - return str(self.region) - - -class MallocUnit(Unit): - """Represents a Unit for a malloc'ed memory block.""" - def __init__(self, unit_id, size, alloc_count, free_count, bucket): - super(MallocUnit, self).__init__(unit_id, size) - self._bucket = bucket - self._alloc_count = alloc_count - self._free_count = free_count - - def __repr__(self): - return str(self.bucket) - - @property - def bucket(self): - return self._bucket - - @property - def alloc_count(self): - return self._alloc_count - - @property - def free_count(self): - return self._free_count - - -class UnitSet(object): - """Represents an iterable set of Units.""" - def __init__(self, world): - self._units = {} - self._world = world - - def __repr__(self): - return str(self._units) - - def __iter__(self): - for unit_id in sorted(self._units): - yield self._units[unit_id] - - def append(self, unit, overwrite=False): - if not overwrite and unit.unit_id in self._units: - LOGGER.error('The unit id=%s already exists.' % str(unit.unit_id)) - self._units[unit.unit_id] = unit - - -class AbstractRule(object): - """An abstract class for rules to be matched with units.""" - def __init__(self, dct): - self._name = dct['name'] - self._hidden = dct.get('hidden', False) - self._subs = dct.get('subs', []) - - def match(self, unit): - raise NotImplementedError() - - @property - def name(self): - return self._name - - @property - def hidden(self): - return self._hidden - - def iter_subs(self): - for sub in self._subs: - yield sub - - -class VMRule(AbstractRule): - """Represents a Rule to match with virtual memory regions.""" - def __init__(self, dct): - super(VMRule, self).__init__(dct) - self._backtrace_function = dct.get('backtrace_function', None) - if self._backtrace_function: - self._backtrace_function = re.compile(self._backtrace_function) - self._backtrace_sourcefile = dct.get('backtrace_sourcefile', None) - if self._backtrace_sourcefile: - self._backtrace_sourcefile = re.compile(self._backtrace_sourcefile) - self._mmap = dct.get('mmap', None) - self._sharedwith = dct.get('sharedwith', []) - self._mapped_pathname = dct.get('mapped_pathname', None) - if self._mapped_pathname: - self._mapped_pathname = re.compile(self._mapped_pathname) - self._mapped_permission = dct.get('mapped_permission', None) - if self._mapped_permission: - self._mapped_permission = re.compile(self._mapped_permission) - - def __repr__(self): - result = cStringIO.StringIO() - result.write('{"%s"=>' % self._name) - attributes = [] - attributes.append('mmap: %s' % self._mmap) - if self._backtrace_function: - attributes.append('backtrace_function: "%s"' % - self._backtrace_function.pattern) - if self._sharedwith: - attributes.append('sharedwith: "%s"' % self._sharedwith) - if self._mapped_pathname: - attributes.append('mapped_pathname: "%s"' % self._mapped_pathname.pattern) - if self._mapped_permission: - attributes.append('mapped_permission: "%s"' % - self._mapped_permission.pattern) - result.write('%s}' % ', '.join(attributes)) - return result.getvalue() - - def match(self, unit): - if unit.mmap: - assert unit.region[0] == 'hooked' - bucket = unit.bucket_set.get(unit.region[1]['bucket_id']) - assert bucket - assert bucket.allocator_type == 'mmap' - - stackfunction = bucket.symbolized_joined_stackfunction - stacksourcefile = bucket.symbolized_joined_stacksourcefile - - # TODO(dmikurube): Support shared memory. - sharedwith = None - - if self._mmap == False: # (self._mmap == None) should go through. - return False - if (self._backtrace_function and - not self._backtrace_function.match(stackfunction)): - return False - if (self._backtrace_sourcefile and - not self._backtrace_sourcefile.match(stacksourcefile)): - return False - if (self._mapped_pathname and - not self._mapped_pathname.match(unit.region[1]['vma']['name'])): - return False - if (self._mapped_permission and - not self._mapped_permission.match( - unit.region[1]['vma']['readable'] + - unit.region[1]['vma']['writable'] + - unit.region[1]['vma']['executable'] + - unit.region[1]['vma']['private'])): - return False - if (self._sharedwith and - unit.pageframe and sharedwith not in self._sharedwith): - return False - - return True - - else: - assert unit.region[0] == 'unhooked' - - # TODO(dmikurube): Support shared memory. - sharedwith = None - - if self._mmap == True: # (self._mmap == None) should go through. - return False - if (self._mapped_pathname and - not self._mapped_pathname.match(unit.region[1]['vma']['name'])): - return False - if (self._mapped_permission and - not self._mapped_permission.match( - unit.region[1]['vma']['readable'] + - unit.region[1]['vma']['writable'] + - unit.region[1]['vma']['executable'] + - unit.region[1]['vma']['private'])): - return False - if (self._sharedwith and - unit.pageframe and sharedwith not in self._sharedwith): - return False - - return True - - -class MallocRule(AbstractRule): - """Represents a Rule to match with malloc'ed blocks.""" - def __init__(self, dct): - super(MallocRule, self).__init__(dct) - self._backtrace_function = dct.get('backtrace_function', None) - if self._backtrace_function: - self._backtrace_function = re.compile(self._backtrace_function) - self._backtrace_sourcefile = dct.get('backtrace_sourcefile', None) - if self._backtrace_sourcefile: - self._backtrace_sourcefile = re.compile(self._backtrace_sourcefile) - self._typeinfo = dct.get('typeinfo', None) - if self._typeinfo: - self._typeinfo = re.compile(self._typeinfo) - - def __repr__(self): - result = cStringIO.StringIO() - result.write('{"%s"=>' % self._name) - attributes = [] - if self._backtrace_function: - attributes.append('backtrace_function: "%s"' % self._backtrace_function) - if self._typeinfo: - attributes.append('typeinfo: "%s"' % self._typeinfo) - result.write('%s}' % ', '.join(attributes)) - return result.getvalue() - - def match(self, unit): - assert unit.bucket.allocator_type == 'malloc' - - stackfunction = unit.bucket.symbolized_joined_stackfunction - stacksourcefile = unit.bucket.symbolized_joined_stacksourcefile - typeinfo = unit.bucket.symbolized_typeinfo - if typeinfo.startswith('0x'): - typeinfo = unit.bucket.typeinfo_name - - return ((not self._backtrace_function or - self._backtrace_function.match(stackfunction)) and - (not self._backtrace_sourcefile or - self._backtrace_sourcefile.match(stacksourcefile)) and - (not self._typeinfo or self._typeinfo.match(typeinfo))) - - -class NoBucketMallocRule(MallocRule): - """Represents a Rule that small ignorable units match with.""" - def __init__(self): - super(NoBucketMallocRule, self).__init__({'name': 'tc-no-bucket'}) - self._no_bucket = True - - @property - def no_bucket(self): - return self._no_bucket - - -class AbstractSorter(object): - """An abstract class for classifying Units with a set of Rules.""" - def __init__(self, dct): - self._type = 'sorter' - self._version = dct['version'] - self._world = dct['world'] - self._name = dct['name'] - self._root = dct.get('root', False) - self._order = dct['order'] - - self._rules = [] - for rule in dct['rules']: - if dct['world'] == 'vm': - self._rules.append(VMRule(rule)) - elif dct['world'] == 'malloc': - self._rules.append(MallocRule(rule)) - else: - LOGGER.error('Unknown sorter world type') - - def __repr__(self): - result = cStringIO.StringIO() - result.write('world=%s' % self._world) - result.write('order=%s' % self._order) - result.write('rules:') - for rule in self._rules: - result.write(' %s' % rule) - return result.getvalue() - - @staticmethod - def load(filename): - with open(filename) as sorter_f: - sorter_dict = json.load(sorter_f) - if sorter_dict['world'] == 'vm': - return VMSorter(sorter_dict) - elif sorter_dict['world'] == 'malloc': - return MallocSorter(sorter_dict) - else: - LOGGER.error('Unknown sorter world type') - return None - - @property - def world(self): - return self._world - - @property - def name(self): - return self._name - - @property - def root(self): - return self._root - - def find(self, unit): - raise NotImplementedError() - - def find_rule(self, name): - """Finds a rule whose name is |name|. """ - for rule in self._rules: - if rule.name == name: - return rule - return None - - -class VMSorter(AbstractSorter): - """Represents a Sorter for memory regions on virtual memory.""" - def __init__(self, dct): - assert dct['world'] == 'vm' - super(VMSorter, self).__init__(dct) - - def find(self, unit): - for rule in self._rules: - if rule.match(unit): - return rule - assert False - - -class MallocSorter(AbstractSorter): - """Represents a Sorter for malloc'ed blocks.""" - def __init__(self, dct): - assert dct['world'] == 'malloc' - super(MallocSorter, self).__init__(dct) - self._no_bucket_rule = NoBucketMallocRule() - - def find(self, unit): - if not unit.bucket: - return self._no_bucket_rule - assert unit.bucket.allocator_type == 'malloc' - - if unit.bucket.component_cache: - return unit.bucket.component_cache - - for rule in self._rules: - if rule.match(unit): - unit.bucket.component_cache = rule - return rule - assert False - - -class SorterTemplates(object): - """Represents a template for sorters.""" - def __init__(self, dct): - self._dict = dct - - def as_dict(self): - return self._dict - - @staticmethod - def load(filename): - with open(filename) as templates_f: - templates_dict = json.load(templates_f) - return SorterTemplates(templates_dict) - - -class SorterSet(object): - """Represents an iterable set of Sorters.""" - def __init__(self, additional=None, default=None): - if not additional: - additional = [] - if not default: - default = DEFAULT_SORTERS - self._sorters = {} - for filename in default + additional: - sorter = AbstractSorter.load(filename) - if sorter.world not in self._sorters: - self._sorters[sorter.world] = [] - self._sorters[sorter.world].append(sorter) - self._templates = SorterTemplates.load(DEFAULT_TEMPLATES) - - def __repr__(self): - result = cStringIO.StringIO() - result.write(self._sorters) - return result.getvalue() - - def __iter__(self): - for sorters in self._sorters.itervalues(): - for sorter in sorters: - yield sorter - - def iter_world(self, world): - for sorter in self._sorters.get(world, []): - yield sorter - - @property - def templates(self): - return self._templates diff --git a/tools/deep_memory_profiler/lib/subcommand.py b/tools/deep_memory_profiler/lib/subcommand.py deleted file mode 100644 index 25416f6ee3..0000000000 --- a/tools/deep_memory_profiler/lib/subcommand.py +++ /dev/null @@ -1,160 +0,0 @@ -# Copyright 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import logging -import optparse -import os -import re - -from lib.bucket import BucketSet -from lib.dump import Dump, DumpList -from lib.symbol import SymbolDataSources, SymbolMappingCache, SymbolFinder -from lib.symbol import proc_maps -from lib.symbol import FUNCTION_SYMBOLS, SOURCEFILE_SYMBOLS, TYPEINFO_SYMBOLS - - -LOGGER = logging.getLogger('dmprof') - -BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) -CHROME_SRC_PATH = os.path.join(BASE_PATH, os.pardir, os.pardir) - - -class SubCommand(object): - """Subclasses are a subcommand for this executable. - - See COMMANDS in main() in dmprof.py. - """ - _DEVICE_BINDIRS = ['/data/data/', '/data/app-lib/', '/data/local/tmp'] - - def __init__(self, usage): - self._parser = optparse.OptionParser(usage) - - @staticmethod - def load_basic_files( - dump_path, multiple, no_dump=False, alternative_dirs=None): - prefix = SubCommand._find_prefix(dump_path) - # If the target process is estimated to be working on Android, converts - # a path in the Android device to a path estimated to be corresponding in - # the host. Use --alternative-dirs to specify the conversion manually. - if not alternative_dirs: - alternative_dirs = SubCommand._estimate_alternative_dirs(prefix) - if alternative_dirs: - for device, host in alternative_dirs.iteritems(): - LOGGER.info('Assuming %s on device as %s on host' % (device, host)) - symbol_data_sources = SymbolDataSources(prefix, alternative_dirs) - symbol_data_sources.prepare() - bucket_set = BucketSet() - bucket_set.load(prefix) - if not no_dump: - if multiple: - dump_list = DumpList.load(SubCommand._find_all_dumps(dump_path)) - else: - dump = Dump.load(dump_path) - symbol_mapping_cache = SymbolMappingCache() - with open(prefix + '.cache.function', 'a+') as cache_f: - symbol_mapping_cache.update( - FUNCTION_SYMBOLS, bucket_set, - SymbolFinder(FUNCTION_SYMBOLS, symbol_data_sources), cache_f) - with open(prefix + '.cache.typeinfo', 'a+') as cache_f: - symbol_mapping_cache.update( - TYPEINFO_SYMBOLS, bucket_set, - SymbolFinder(TYPEINFO_SYMBOLS, symbol_data_sources), cache_f) - with open(prefix + '.cache.sourcefile', 'a+') as cache_f: - symbol_mapping_cache.update( - SOURCEFILE_SYMBOLS, bucket_set, - SymbolFinder(SOURCEFILE_SYMBOLS, symbol_data_sources), cache_f) - bucket_set.symbolize(symbol_mapping_cache) - if no_dump: - return bucket_set - elif multiple: - return (bucket_set, dump_list) - else: - return (bucket_set, dump) - - @staticmethod - def _find_prefix(path): - return re.sub('\.[0-9][0-9][0-9][0-9]\.heap', '', path) - - @staticmethod - def _estimate_alternative_dirs(prefix): - """Estimates a path in host from a corresponding path in target device. - - For Android, dmprof.py should find symbol information from binaries in - the host instead of the Android device because dmprof.py doesn't run on - the Android device. This method estimates a path in the host - corresponding to a path in the Android device. - - Returns: - A dict that maps a path in the Android device to a path in the host. - If a file in SubCommand._DEVICE_BINDIRS is found in /proc/maps, it - assumes the process was running on Android and maps the path to - "out/Debug/lib" in the Chromium directory. An empty dict is returned - unless Android. - """ - device_lib_path_candidates = set() - - with open(prefix + '.maps') as maps_f: - maps = proc_maps.ProcMaps.load(maps_f) - for entry in maps: - name = entry.as_dict()['name'] - if any([base_dir in name for base_dir in SubCommand._DEVICE_BINDIRS]): - device_lib_path_candidates.add(os.path.dirname(name)) - - if len(device_lib_path_candidates) == 1: - return {device_lib_path_candidates.pop(): os.path.join( - CHROME_SRC_PATH, 'out', 'Debug', 'lib')} - else: - return {} - - @staticmethod - def _find_all_dumps(dump_path): - prefix = SubCommand._find_prefix(dump_path) - dump_path_list = [dump_path] - - n = int(dump_path[len(dump_path) - 9 : len(dump_path) - 5]) - n += 1 - skipped = 0 - while True: - p = '%s.%04d.heap' % (prefix, n) - if os.path.exists(p) and os.stat(p).st_size: - dump_path_list.append(p) - else: - if skipped > 10: - break - skipped += 1 - n += 1 - - return dump_path_list - - @staticmethod - def _find_all_buckets(dump_path): - prefix = SubCommand._find_prefix(dump_path) - bucket_path_list = [] - - n = 0 - while True: - path = '%s.%04d.buckets' % (prefix, n) - if not os.path.exists(path): - if n > 10: - break - n += 1 - continue - bucket_path_list.append(path) - n += 1 - - return bucket_path_list - - def _parse_args(self, sys_argv, required): - options, args = self._parser.parse_args(sys_argv) - if len(args) < required + 1: - self._parser.error('needs %d argument(s).\n' % required) - return None - return (options, args) - - @staticmethod - def _parse_policy_list(options_policy): - if options_policy: - return options_policy.split(',') - else: - return None diff --git a/tools/deep_memory_profiler/lib/symbol.py b/tools/deep_memory_profiler/lib/symbol.py deleted file mode 100644 index 897d4098d5..0000000000 --- a/tools/deep_memory_profiler/lib/symbol.py +++ /dev/null @@ -1,189 +0,0 @@ -# Copyright 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import logging -import os -import sys - -_BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) -_FIND_RUNTIME_SYMBOLS_PATH = os.path.join(_BASE_PATH, - os.pardir, - 'find_runtime_symbols') -sys.path.append(_FIND_RUNTIME_SYMBOLS_PATH) - -import find_runtime_symbols -import prepare_symbol_info -import proc_maps # pylint: disable=W0611 - -LOGGER = logging.getLogger('dmprof') - -FUNCTION_SYMBOLS = find_runtime_symbols.FUNCTION_SYMBOLS -SOURCEFILE_SYMBOLS = find_runtime_symbols.SOURCEFILE_SYMBOLS -TYPEINFO_SYMBOLS = find_runtime_symbols.TYPEINFO_SYMBOLS - - -class SymbolDataSources(object): - """Manages symbol data sources in a process. - - The symbol data sources consist of maps (/proc//maps), nm, readelf and - so on. They are collected into a directory '|prefix|.symmap' from the binary - files by 'prepare()' with tools/find_runtime_symbols/prepare_symbol_info.py. - - Binaries are not mandatory to profile. The prepared data sources work in - place of the binary even if the binary has been overwritten with another - binary. - - Note that loading the symbol data sources takes a long time. They are often - very big. So, the 'dmprof' profiler is designed to use 'SymbolMappingCache' - which caches actually used symbols. - """ - def __init__(self, prefix, alternative_dirs=None): - self._prefix = prefix - self._prepared_symbol_data_sources_path = None - self._loaded_symbol_data_sources = None - self._alternative_dirs = alternative_dirs or {} - - def prepare(self): - """Prepares symbol data sources by extracting mapping from a binary. - - The prepared symbol data sources are stored in a directory. The directory - name is stored in |self._prepared_symbol_data_sources_path|. - - Returns: - True if succeeded. - """ - LOGGER.info('Preparing symbol mapping...') - self._prepared_symbol_data_sources_path, used_tempdir = ( - prepare_symbol_info.prepare_symbol_info( - self._prefix + '.maps', - output_dir_path=self._prefix + '.symmap', - alternative_dirs=self._alternative_dirs, - use_tempdir=True, - use_source_file_name=True)) - if self._prepared_symbol_data_sources_path: - LOGGER.info(' Prepared symbol mapping.') - if used_tempdir: - LOGGER.warn(' Using a temporary directory for symbol mapping.') - LOGGER.warn(' Delete it by yourself.') - LOGGER.warn(' Or, move the directory by yourself to use it later.') - return True - else: - LOGGER.warn(' Failed to prepare symbol mapping.') - return False - - def get(self): - """Returns the prepared symbol data sources. - - Returns: - The prepared symbol data sources. None if failed. - """ - if not self._prepared_symbol_data_sources_path and not self.prepare(): - return None - if not self._loaded_symbol_data_sources: - LOGGER.info('Loading symbol mapping...') - self._loaded_symbol_data_sources = ( - find_runtime_symbols.RuntimeSymbolsInProcess.load( - self._prepared_symbol_data_sources_path)) - return self._loaded_symbol_data_sources - - def path(self): - """Returns the path of the prepared symbol data sources if possible.""" - if not self._prepared_symbol_data_sources_path and not self.prepare(): - return None - return self._prepared_symbol_data_sources_path - - -class SymbolFinder(object): - """Finds corresponding symbols from addresses. - - This class does only 'find()' symbols from a specified |address_list|. - It is introduced to make a finder mockable. - """ - def __init__(self, symbol_type, symbol_data_sources): - self._symbol_type = symbol_type - self._symbol_data_sources = symbol_data_sources - - def find(self, address_list): - return find_runtime_symbols.find_runtime_symbols( - self._symbol_type, self._symbol_data_sources.get(), address_list) - - -class SymbolMappingCache(object): - """Caches mapping from actually used addresses to symbols. - - 'update()' updates the cache from the original symbol data sources via - 'SymbolFinder'. Symbols can be looked up by the method 'lookup()'. - """ - def __init__(self): - self._symbol_mapping_caches = { - FUNCTION_SYMBOLS: {}, - SOURCEFILE_SYMBOLS: {}, - TYPEINFO_SYMBOLS: {}, - } - - def update(self, symbol_type, bucket_set, symbol_finder, cache_f): - """Updates symbol mapping cache on memory and in a symbol cache file. - - It reads cached symbol mapping from a symbol cache file |cache_f| if it - exists. Unresolved addresses are then resolved and added to the cache - both on memory and in the symbol cache file with using 'SymbolFinder'. - - A cache file is formatted as follows: -
-
-
- ... - - Args: - symbol_type: A type of symbols to update. It should be one of - FUNCTION_SYMBOLS, SOURCEFILE_SYMBOLS and TYPEINFO_SYMBOLS. - bucket_set: A BucketSet object. - symbol_finder: A SymbolFinder object to find symbols. - cache_f: A readable and writable IO object of the symbol cache file. - """ - cache_f.seek(0, os.SEEK_SET) - self._load(cache_f, symbol_type) - - unresolved_addresses = sorted( - address for address in bucket_set.iter_addresses(symbol_type) - if address not in self._symbol_mapping_caches[symbol_type]) - - if not unresolved_addresses: - LOGGER.info('No need to resolve any more addresses.') - return - - cache_f.seek(0, os.SEEK_END) - LOGGER.info('Loading %d unresolved addresses.' % - len(unresolved_addresses)) - symbol_dict = symbol_finder.find(unresolved_addresses) - - for address, symbol in symbol_dict.iteritems(): - stripped_symbol = symbol.strip() or '?' - self._symbol_mapping_caches[symbol_type][address] = stripped_symbol - cache_f.write('%x %s\n' % (address, stripped_symbol)) - - def lookup(self, symbol_type, address): - """Looks up a symbol for a given |address|. - - Args: - symbol_type: A type of symbols to update. It should be one of - FUNCTION_SYMBOLS, SOURCEFILE_SYMBOLS and TYPEINFO_SYMBOLS. - address: An integer that represents an address. - - Returns: - A string that represents a symbol. - """ - return self._symbol_mapping_caches[symbol_type].get(address) - - def _load(self, cache_f, symbol_type): - try: - for line in cache_f: - items = line.rstrip().split(None, 1) - if len(items) == 1: - items.append('??') - self._symbol_mapping_caches[symbol_type][int(items[0], 16)] = items[1] - LOGGER.info('Loaded %d entries from symbol cache.' % - len(self._symbol_mapping_caches[symbol_type])) - except IOError as e: - LOGGER.info('The symbol cache file is invalid: %s' % e) diff --git a/tools/deep_memory_profiler/policies.json b/tools/deep_memory_profiler/policies.json deleted file mode 100644 index 775045a8c2..0000000000 --- a/tools/deep_memory_profiler/policies.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "android.browser": { - "file": "policy.android.browser.json", - "format": "json" - }, - "android.renderer": { - "file": "policy.android.renderer.json", - "format": "json" - }, - "android.webview": { - "file": "policy.android.webview.json", - "format": "json" - }, - "sourcefile": { - "file": "policy.sourcefile.json", - "format": "json" - }, - "l0": { - "file": "policy.l0.json", - "format": "json" - }, - "l1": { - "file": "policy.l1.json", - "format": "json" - }, - "l2": { - "file": "policy.l2.json", - "format": "json" - }, - "t0": { - "file": "policy.t0.json", - "format": "json" - } -} \ No newline at end of file diff --git a/tools/deep_memory_profiler/policy.android.browser.json b/tools/deep_memory_profiler/policy.android.browser.json deleted file mode 100644 index e34fee7253..0000000000 --- a/tools/deep_memory_profiler/policy.android.browser.json +++ /dev/null @@ -1,301 +0,0 @@ -{ - "components": [ - "second", - "mmap-profiler", - "mmap-type-profiler", - "mmap-tcmalloc", - "FROM_HERE_FOR_TOTAL", - "mustbezero", - "unhooked-absent", - "unhooked-ashmem-dalvik-heap", - "unhooked-ashmem-dalvik-LinearAlloc", - "unhooked-ashmem-dalvik-aux-structure", - "unhooked-ashmem-dalvik-bitmap", - "unhooked-ashmem-dalvik-other", - "unhooked-pvrsrvkm", - "unhooked-system-dex", - "unhooked-chrome-dex", - "unhooked-other-ashmem", - "unhooked-anonymous", - "unhooked-file-exec-lib-chrome", - "unhooked-file-exec", - "unhooked-file-nonexec-lib-chrome", - "unhooked-file-nonexec", - "unhooked-stack", - "unhooked-other", - "no-bucket", - "mmap-gpu-transferbuffer", - "mmap-gpu-ringbuffer", - "mmap-catch-all", - "tc-disk_cache-backing", - "tc-disk_cache-other", - "tc-sqlite3MemAlloc", - "tc-angle", - "tc-crypto", - "tc-net-iobuffer", - "tc-stl-string", - "tc-stl-rbtree", - "tc-stl-vector", - "tc-stl-hashtable", - "tc-stl-node", - "tc-catch-all", - "tc-unused", - "UNTIL_HERE_FOR_TOTAL", - "total-exclude-profiler", - "total", - "absent", - "anonymous", - "file-exec", - "file-nonexec", - "stack", - "other", - "mmap-total-log", - "mmap-no-log", - "mmap-total-record", - "other-total-log", - "tc-total-log", - "tc-no-log", - "tc-total-record", - "tc-total" - ], - "rules": [ - { - "name": "second", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "mmap-profiler", - "stacktrace": ".*(ProfilerMalloc|MemoryRegionMap::).*", - "allocator": "mmap" - }, - { - "name": "mmap-type-profiler", - "stacktrace": ".*(TypeProfilerMalloc).*", - "allocator": "mmap" - }, - { - "name": "mmap-tcmalloc", - "stacktrace": ".*(DoAllocWithArena|SbrkSysAllocator::Alloc|MmapSysAllocator::Alloc|LowLevelAlloc::Alloc|LowLevelAlloc::AllocWithArena).*", - "allocator": "mmap" - }, - { - "name": "FROM_HERE_FOR_TOTAL", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "mustbezero", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "unhooked-absent", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "unhooked-ashmem-dalvik-heap", - "mappedpathname": "/dev/ashmem/dalvik-heap.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-ashmem-dalvik-LinearAlloc", - "mappedpathname": "/dev/ashmem/dalvik-LinearAlloc.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-ashmem-dalvik-aux-structure", - "mappedpathname": "/dev/ashmem/dalvik-aux-structure.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-ashmem-dalvik-bitmap", - "mappedpathname": "/dev/ashmem/dalvik-bitmap.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-ashmem-dalvik-other", - "mappedpathname": "/dev/ashmem/dalvik.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-pvrsrvkm", - "mappedpathname": "/dev/pvrsrvkm.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-system-dex", - "mappedpathname": "/data/dalvik-cache/system.*.dex.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-chrome-dex", - "mappedpathname": "^/.*?(chrome|content).*?apk@classes.dex", - "allocator": "unhooked" - }, - { - "name": "unhooked-other-ashmem", - "mappedpathname": "/dev/ashmem/.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-anonymous", - "mappedpathname": "^$", - "allocator": "unhooked" - }, - { - "name": "unhooked-file-exec-lib-chrome", - "mappedpathname": "^/.*?(chromeview|content).*", - "mappedpermission": "..x.", - "allocator": "unhooked" - }, - { - "name": "unhooked-file-exec", - "mappedpathname": "^/.*", - "mappedpermission": "..x.", - "allocator": "unhooked" - }, - { - "name": "unhooked-file-nonexec-lib-chrome", - "mappedpathname": "^/.*?(chromeview|content).*", - "allocator": "unhooked" - }, - { - "name": "unhooked-file-nonexec", - "mappedpathname": "^/.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-stack", - "mappedpathname": ".stack.", - "allocator": "unhooked" - }, - { - "name": "unhooked-other", - "mappedpathname": ".*", - "allocator": "unhooked" - }, - { - "name": "mmap-gpu-transferbuffer", - "stacktrace": ".*gpu::TransferBufferManager::RegisterTransferBuffer.*", - "allocator": "mmap" - }, - { - "name": "mmap-gpu-ringbuffer", - "stacktrace": ".*gpu::CommandBufferHelper::AllocateRingBuffer.*", - "allocator": "mmap" - }, - { - "name": "mmap-catch-all", - "stacktrace": ".*", - "allocator": "mmap" - }, - { - "name": "tc-disk_cache-backing", - "stacktrace": ".*disk_cache::BackendImpl::InitBackingStore.*", - "allocator": "malloc" - }, - { - "name": "tc-disk_cache-other", - "stacktrace": ".*disk_cache::.*", - "allocator": "malloc" - }, - { - "name": "tc-sqlite3MemAlloc", - "stacktrace": ".*sqlite3MemMalloc.*", - "allocator": "malloc" - }, - { - "name": "tc-angle", - "stacktrace": ".*TPoolAllocator::allocate.*", - "allocator": "malloc" - }, - { - "name": "tc-crypto", - "stacktrace": ".*(CRYPTO_malloc|CRYPTO_realloc).*", - "allocator": "malloc" - }, - { - "name": "tc-net-iobuffer", - "stacktrace": ".*net::IOBuffer::IOBuffer.*", - "allocator": "malloc" - }, - { - "name": "tc-stl-string", - "stacktrace": ".*std::basic_string::.*", - "allocator": "malloc" - }, - { - "name": "tc-stl-rbtree", - "stacktrace": ".*std::priv::_Rb_tree::.*", - "allocator": "malloc" - }, - { - "name": "tc-stl-vector", - "stacktrace": ".*std::priv::_Impl_vector::.*", - "allocator": "malloc" - }, - { - "name": "tc-stl-hashtable", - "stacktrace": ".*std::hashtable::.*", - "allocator": "malloc" - }, - { - "name": "tc-stl-node", - "stacktrace": ".*std::priv::_Impl_vector::.*", - "allocator": "malloc" - }, - { - "name": "tc-catch-all", - "stacktrace": ".*", - "allocator": "malloc" - }, - { - "name": "UNTIL_HERE_FOR_TOTAL", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "total-exclude-profiler", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "total", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "absent", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "anonymous", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "file-exec", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "file-nonexec", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "stack", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "other", - "stacktrace": "optional", - "allocator": "optional" - } - ], - "version": "POLICY_DEEP_3" -} diff --git a/tools/deep_memory_profiler/policy.android.renderer.json b/tools/deep_memory_profiler/policy.android.renderer.json deleted file mode 100644 index c039c6f97a..0000000000 --- a/tools/deep_memory_profiler/policy.android.renderer.json +++ /dev/null @@ -1,579 +0,0 @@ -{ - "components": [ - "second", - "mmap-profiler", - "mmap-type-profiler", - "mmap-tcmalloc", - "FROM_HERE_FOR_TOTAL", - "mustbezero", - "unhooked-absent", - "unhooked-ashmem-dalvik-heap", - "unhooked-ashmem-dalvik-LinearAlloc", - "unhooked-ashmem-dalvik-aux-structure", - "unhooked-ashmem-dalvik-bitmap", - "unhooked-ashmem-dalvik-other", - "unhooked-pvrsrvkm", - "unhooked-system-dex", - "unhooked-chrome-dex", - "unhooked-other-ashmem", - "unhooked-anonymous", - "unhooked-file-exec-lib-chrome", - "unhooked-file-exec", - "unhooked-file-nonexec-lib-chrome", - "unhooked-file-nonexec", - "unhooked-stack", - "unhooked-other", - "no-bucket", - "mmap-v8-heap-newspace", - "mmap-v8-heap-coderange", - "mmap-v8-heap-pagedspace", - "mmap-v8-other", - "mmap-gpu-mappedmemorymanager", - "mmap-gpu-command-ringbuffer", - "mmap-gpu-transfer-ringbuffer", - "mmap-gpu-gles2-createbuffer", - "mmap-skia-font", - "mmap-catch-all", - "tc-webcore-fontcache", - "tc-skia", - "tc-renderobject", - "tc-renderstyle", - "tc-webcore-sharedbuf", - "tc-webcore-XHRcreate", - "tc-webcore-XHRreceived", - "tc-webcore-docwriter-add", - "tc-webcore-node-and-doc", - "tc-webcore-node-factory", - "tc-webcore-element-wrapper", - "tc-webcore-stylepropertyset", - "tc-webcore-style-createsheet", - "tc-webcore-cachedresource", - "tc-webcore-script-execute", - "tc-webcore-events-related", - "tc-webcore-document-write", - "tc-webcore-node-create-renderer", - "tc-webcore-image-frame-generator", - "tc-webcore-render-catch-all", - "tc-webcore-setInnerHTML-except-node", - "tc-wtf-StringImpl-user-catch-all", - "tc-wtf-HashTable-user-catch-all", - "tc-webcore-everything-create", - "tc-webkit-from-v8-catch-all", - "tc-webkit-catch-all", - "tc-v8-catch-all", - "tc-toplevel-string", - "tc-std-treemap", - "tc-std-hashmap", - "tc-std-vector", - "tc-std-other", - "tc-catch-all", - "tc-unused", - "UNTIL_HERE_FOR_TOTAL", - "total-exclude-profiler", - "total", - "absent", - "anonymous", - "file-exec", - "file-nonexec", - "stack", - "other", - "mmap-total-log", - "mmap-no-log", - "mmap-total-record", - "other-total-log", - "tc-total-log", - "tc-no-log", - "tc-total-record", - "tc-total" - ], - "rules": [ - { - "name": "second", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "mmap-profiler", - "stacktrace": ".*(ProfilerMalloc|MemoryRegionMap::).*", - "allocator": "mmap" - }, - { - "name": "mmap-type-profiler", - "stacktrace": ".*(TypeProfilerMalloc).*", - "allocator": "mmap" - }, - { - "name": "mmap-tcmalloc", - "stacktrace": ".*(DoAllocWithArena|SbrkSysAllocator::Alloc|MmapSysAllocator::Alloc|LowLevelAlloc::Alloc|LowLevelAlloc::AllocWithArena).*", - "allocator": "mmap" - }, - { - "name": "FROM_HERE_FOR_TOTAL", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "mustbezero", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "unhooked-absent", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "unhooked-ashmem-dalvik-heap", - "mappedpathname": "/dev/ashmem/dalvik-heap.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-ashmem-dalvik-LinearAlloc", - "mappedpathname": "/dev/ashmem/dalvik-LinearAlloc.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-ashmem-dalvik-aux-structure", - "mappedpathname": "/dev/ashmem/dalvik-aux-structure.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-ashmem-dalvik-bitmap", - "mappedpathname": "/dev/ashmem/dalvik-bitmap.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-ashmem-dalvik-other", - "mappedpathname": "/dev/ashmem/dalvik.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-pvrsrvkm", - "mappedpathname": "/dev/pvrsrvkm.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-system-dex", - "mappedpathname": "/data/dalvik-cache/system.*.dex.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-chrome-dex", - "mappedpathname": "^/.*?(chrome|content).*?apk@classes.dex", - "allocator": "unhooked" - }, - { - "name": "unhooked-other-ashmem", - "mappedpathname": "/dev/ashmem/.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-anonymous", - "mappedpathname": "^$", - "allocator": "unhooked" - }, - { - "name": "unhooked-file-exec-lib-chrome", - "mappedpathname": "^/.*?(chromeview|content).*", - "mappedpermission": "..x.", - "allocator": "unhooked" - }, - { - "name": "unhooked-file-exec", - "mappedpathname": "^/.*", - "mappedpermission": "..x.", - "allocator": "unhooked" - }, - { - "name": "unhooked-file-nonexec-lib-chrome", - "mappedpathname": "^/.*?(chromeview|content).*", - "allocator": "unhooked" - }, - { - "name": "unhooked-file-nonexec", - "mappedpathname": "^/.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-stack", - "mappedpathname": ".stack.", - "allocator": "unhooked" - }, - { - "name": "unhooked-other", - "mappedpathname": ".*", - "allocator": "unhooked" - }, - { - "name": "mmap-v8-heap-newspace", - "stacktrace": ".*v8::internal::NewSpace::SetUp.*", - "allocator": "mmap" - }, - { - "name": "mmap-v8-heap-coderange", - "stacktrace": ".*v8::internal::CodeRange::SetUp.*", - "allocator": "mmap" - }, - { - "name": "mmap-v8-heap-pagedspace", - "stacktrace": ".*v8::internal::PagedSpace::AllocateRaw.*", - "allocator": "mmap" - }, - { - "name": "mmap-v8-other", - "stacktrace": ".*v8::.*", - "allocator": "mmap" - }, - { - "name": "mmap-gpu-mappedmemorymanager", - "stacktrace": ".*gpu::MappedMemoryManager::Alloc.*", - "allocator": "mmap" - }, - { - "name": "mmap-gpu-command-ringbuffer", - "stacktrace": ".*gpu::CommandBufferHelper::AllocateRingBuffer.*", - "allocator": "mmap" - }, - { - "name": "mmap-gpu-transfer-ringbuffer", - "stacktrace": ".*gpu::TransferBuffer::AllocateRingBuffer.*", - "allocator": "mmap" - }, - { - "name": "mmap-gpu-gles2-createbuffer", - "stacktrace": ".*gpu::gles2::BufferTracker::CreateBuffer.*", - "allocator": "mmap" - }, - { - "name": "mmap-skia-font", - "stacktrace": ".*SkTypeface::openStream.*", - "allocator": "mmap" - }, - { - "name": "mmap-catch-all", - "stacktrace": ".*", - "allocator": "mmap" - }, - { - "name": "tc-webcore-fontcache", - "stacktrace": ".*WebCore::FontCache::getCachedFontData.*", - "allocator": "malloc" - }, - { - "name": "tc-skia", - "stacktrace": ".* Sk[A-Za-z_]+::.*", - "allocator": "malloc" - }, - { - "name": "tc-renderobject", - "stacktrace": ".*WebCore::RenderArena::allocate.*", - "allocator": "malloc" - }, - { - "name": "tc-renderstyle", - "stacktrace": ".*WebCore::RenderStyle::create.*", - "allocator": "malloc" - }, - { - "name": "tc-renderstyle", - "stacktrace": ".*WebCore::RenderStyle::clone.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-sharedbuf", - "stacktrace": ".*WebCore::SharedBuffer::create.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-sharedbuf", - "stacktrace": ".*WebCore::SharedBuffer::buffer.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-sharedbuf", - "stacktrace": ".*WebCore::SharedBuffer::append.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-XHRcreate", - "stacktrace": ".*WebCore::XMLHttpRequest::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-XHRreceived", - "stacktrace": ".*WebCore::XMLHttpRequest::didReceiveData.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-docwriter-add", - "stacktrace": ".*WebCore::DocumentWriter::addData.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-and-doc", - "stacktrace": ".*WebCore::HTML[a-zA-Z0-9_]*Element::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-and-doc", - "stacktrace": ".*WebCore::Text::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-and-doc", - "stacktrace": ".*WebCore::Comment::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-and-doc", - "stacktrace": ".*WebCore::HTMLDocument::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-and-doc", - "stacktrace": ".*WebCore::CSSStyleRule::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-and-doc", - "stacktrace": ".*WebCore::Attribute::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-and-doc", - "stacktrace": ".*WebCore::DOMWindow::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-factory", - "stacktrace": ".*WebCore::HTML[a-zA-Z0-9_]*Factory::create[a-zA-Z0-9_]*Element.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-element-wrapper", - "stacktrace": ".*WebCore::createHTML[a-zA-Z0-9_]*ElementWrapper.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-stylepropertyset", - "stacktrace": ".*WebCore::StylePropertySet::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-style-createsheet", - "stacktrace": ".*WebCore::StyleElement::createSheet.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-cachedresource", - "stacktrace": ".*WebCore::CachedResource::data .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-cachedresource", - "stacktrace": ".*WebCore::CachedResource::load .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-script-execute", - "stacktrace": ".*WebCore::ScriptElement::execute.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-events-related", - "stacktrace": ".*WebCore::createAttributeEventListener.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-events-related", - "stacktrace": ".*WebCore::V8LazyEventListener::create.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-events-related", - "stacktrace": ".*WebCore::V8EventListener::create.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-events-related", - "stacktrace": ".*WebCore::Event::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-events-related", - "stacktrace": ".*WebCore::EventListener::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-document-write", - "stacktrace": ".*WebCore::Document::write.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-create-renderer", - "stacktrace": ".*WebCore::Node::createRendererIfNeeded.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-image-frame-generator", - "stacktrace": ".*WebCore::ImageFrameGenerator.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-render-catch-all", - "stacktrace": ".*WebCore::RenderLayer.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-render-catch-all", - "stacktrace": ".*WebCore::RenderBlock.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-render-catch-all", - "stacktrace": ".*WebCore::RenderWidget.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-render-catch-all", - "stacktrace": ".*WebCore::RenderView.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-render-catch-all", - "stacktrace": ".*WebCore::RenderViewImpl.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-render-catch-all", - "stacktrace": ".*WebCore::RenderStyle.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-render-catch-all", - "stacktrace": ".*WebCore::RenderText.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-render-catch-all", - "stacktrace": ".* RendererMain .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-setInnerHTML-except-node", - "stacktrace": ".*WebCore::HTMLElement::setInnerHTML.*", - "allocator": "malloc" - }, - { - "name": "tc-wtf-StringImpl-user-catch-all", - "stacktrace": ".*WTF::StringImpl::create .*", - "allocator": "malloc" - }, - { - "name": "tc-wtf-StringImpl-user-catch-all", - "stacktrace": ".*WTF::StringImpl::createUninitialized.*", - "allocator": "malloc" - }, - { - "name": "tc-wtf-HashTable-user-catch-all", - "stacktrace": ".*WTF::HashTable::allocateTable.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-everything-create", - "stacktrace": ".*WebCore::[a-zA-Z0-9_]*::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webkit-from-v8-catch-all", - "stacktrace": ".*(WTF::|WebCore::|WebKit::).*v8::.*", - "allocator": "malloc" - }, - { - "name": "tc-webkit-catch-all", - "stacktrace": ".*(WTF::|WebCore::|WebKit::).*", - "allocator": "malloc" - }, - { - "name": "tc-v8-catch-all", - "stacktrace": ".*v8::.*", - "allocator": "malloc" - }, - { - "name": "tc-toplevel-string", - "stacktrace": "std::basic_string::_Rep::_S_create", - "allocator": "malloc" - }, - { - "name": "tc-std-treemap", - "stacktrace": ".*::allocate std::(_Rb_tree|__1::__tree).*", - "allocator": "malloc" - }, - { - "name": "tc-std-hashmap", - "stacktrace": ".*(std::vector::reserve __gnu_cxx::hashtable|::allocate std::_Hashtable|::allocate std::__1::__hash_table).*", - "allocator": "malloc" - }, - { - "name": "tc-std-vector", - "stacktrace": ".*std::(_Vector_base::_M_allocate|__1::vector::allocate).*", - "allocator": "malloc" - }, - { - "name": "tc-std-other", - "stacktrace": ".*(__gnu_cxx::new_allocator::allocate|std::__1::allocator::allocate).*", - "allocator": "malloc" - }, - { - "name": "tc-catch-all", - "stacktrace": ".*", - "allocator": "malloc" - }, - { - "name": "UNTIL_HERE_FOR_TOTAL", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "total-exclude-profiler", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "total", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "absent", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "anonymous", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "file-exec", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "file-nonexec", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "stack", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "other", - "stacktrace": "optional", - "allocator": "optional" - } - ], - "version": "POLICY_DEEP_3" -} diff --git a/tools/deep_memory_profiler/policy.android.webview.json b/tools/deep_memory_profiler/policy.android.webview.json deleted file mode 100644 index d3611ce843..0000000000 --- a/tools/deep_memory_profiler/policy.android.webview.json +++ /dev/null @@ -1,639 +0,0 @@ -{ - "components": [ - "second", - "mmap-profiler", - "mmap-type-profiler", - "mmap-tcmalloc", - "FROM_HERE_FOR_TOTAL", - "mustbezero", - "unhooked-absent", - "unhooked-ashmem-dalvik-heap", - "unhooked-ashmem-dalvik-LinearAlloc", - "unhooked-ashmem-dalvik-aux-structure", - "unhooked-ashmem-dalvik-bitmap", - "unhooked-ashmem-dalvik-other", - "unhooked-pvrsrvkm", - "unhooked-system-dex", - "unhooked-chrome-dex", - "unhooked-other-ashmem", - "unhooked-anonymous", - "unhooked-file-exec-lib-chrome", - "unhooked-file-exec", - "unhooked-file-nonexec-lib-chrome", - "unhooked-file-nonexec", - "unhooked-stack", - "unhooked-other", - "no-bucket", - "mmap-v8-heap-newspace", - "mmap-v8-heap-coderange", - "mmap-v8-heap-pagedspace", - "mmap-v8-other", - "mmap-gpu-mappedmemorymanager", - "mmap-gpu-command-ringbuffer", - "mmap-gpu-transfer-ringbuffer", - "mmap-gpu-gles2-createbuffer", - "mmap-skia-font", - "mmap-catch-all", - "tc-disk_cache-backing", - "tc-disk_cache-other", - "tc-sqlite3MemAlloc", - "tc-angle", - "tc-crypto", - "tc-net-iobuffer", - "tc-stl-string", - "tc-stl-rbtree", - "tc-stl-vector", - "tc-stl-hashtable", - "tc-stl-node", - "tc-webcore-fontcache", - "tc-skia", - "tc-renderobject", - "tc-renderstyle", - "tc-webcore-sharedbuf", - "tc-webcore-XHRcreate", - "tc-webcore-XHRreceived", - "tc-webcore-docwriter-add", - "tc-webcore-node-and-doc", - "tc-webcore-node-factory", - "tc-webcore-element-wrapper", - "tc-webcore-stylepropertyset", - "tc-webcore-style-createsheet", - "tc-webcore-cachedresource", - "tc-webcore-script-execute", - "tc-webcore-events-related", - "tc-webcore-document-write", - "tc-webcore-node-create-renderer", - "tc-webcore-render-catch-all", - "tc-webcore-setInnerHTML-except-node", - "tc-wtf-StringImpl-user-catch-all", - "tc-wtf-HashTable-user-catch-all", - "tc-webcore-everything-create", - "tc-webkit-from-v8-catch-all", - "tc-webkit-catch-all", - "tc-v8-catch-all", - "tc-toplevel-string", - "tc-std-treemap", - "tc-std-hashmap", - "tc-std-vector", - "tc-std-other", - "tc-catch-all", - "tc-unused", - "UNTIL_HERE_FOR_TOTAL", - "total-exclude-profiler", - "total", - "absent", - "anonymous", - "file-exec", - "file-nonexec", - "stack", - "other", - "mmap-total-log", - "mmap-no-log", - "mmap-total-record", - "other-total-log", - "tc-total-log", - "tc-no-log", - "tc-total-record", - "tc-total" - ], - "rules": [ - { - "name": "second", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "mmap-profiler", - "stacktrace": ".*(ProfilerMalloc|MemoryRegionMap::).*", - "allocator": "mmap" - }, - { - "name": "mmap-type-profiler", - "stacktrace": ".*(TypeProfilerMalloc).*", - "allocator": "mmap" - }, - { - "name": "mmap-tcmalloc", - "stacktrace": ".*(DoAllocWithArena|SbrkSysAllocator::Alloc|MmapSysAllocator::Alloc|LowLevelAlloc::Alloc|LowLevelAlloc::AllocWithArena).*", - "allocator": "mmap" - }, - { - "name": "FROM_HERE_FOR_TOTAL", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "mustbezero", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "unhooked-absent", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "unhooked-ashmem-dalvik-heap", - "mappedpathname": "/dev/ashmem/dalvik-heap.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-ashmem-dalvik-LinearAlloc", - "mappedpathname": "/dev/ashmem/dalvik-LinearAlloc.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-ashmem-dalvik-aux-structure", - "mappedpathname": "/dev/ashmem/dalvik-aux-structure.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-ashmem-dalvik-bitmap", - "mappedpathname": "/dev/ashmem/dalvik-bitmap.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-ashmem-dalvik-other", - "mappedpathname": "/dev/ashmem/dalvik.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-pvrsrvkm", - "mappedpathname": "/dev/pvrsrvkm.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-system-dex", - "mappedpathname": "/data/dalvik-cache/system.*.dex.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-chrome-dex", - "mappedpathname": "^/.*?(chrome|content).*?apk@classes.dex", - "allocator": "unhooked" - }, - { - "name": "unhooked-other-ashmem", - "mappedpathname": "/dev/ashmem/.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-anonymous", - "mappedpathname": "^$", - "allocator": "unhooked" - }, - { - "name": "unhooked-file-exec-lib-chrome", - "mappedpathname": "^/.*?(chromeview|content).*", - "mappedpermission": "..x.", - "allocator": "unhooked" - }, - { - "name": "unhooked-file-exec", - "mappedpathname": "^/.*", - "mappedpermission": "..x.", - "allocator": "unhooked" - }, - { - "name": "unhooked-file-nonexec-lib-chrome", - "mappedpathname": "^/.*?(chromeview|content).*", - "allocator": "unhooked" - }, - { - "name": "unhooked-file-nonexec", - "mappedpathname": "^/.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-stack", - "mappedpathname": ".stack.", - "allocator": "unhooked" - }, - { - "name": "unhooked-other", - "mappedpathname": ".*", - "allocator": "unhooked" - }, - { - "name": "mmap-v8-heap-newspace", - "stacktrace": ".*v8::internal::NewSpace::SetUp.*", - "allocator": "mmap" - }, - { - "name": "mmap-v8-heap-coderange", - "stacktrace": ".*v8::internal::CodeRange::SetUp.*", - "allocator": "mmap" - }, - { - "name": "mmap-v8-heap-pagedspace", - "stacktrace": ".*v8::internal::PagedSpace::AllocateRaw.*", - "allocator": "mmap" - }, - { - "name": "mmap-v8-other", - "stacktrace": ".*v8::.*", - "allocator": "mmap" - }, - { - "name": "mmap-gpu-mappedmemorymanager", - "stacktrace": ".*gpu::MappedMemoryManager::Alloc.*", - "allocator": "mmap" - }, - { - "name": "mmap-gpu-command-ringbuffer", - "stacktrace": ".*gpu::CommandBufferHelper::AllocateRingBuffer.*", - "allocator": "mmap" - }, - { - "name": "mmap-gpu-transfer-ringbuffer", - "stacktrace": ".*gpu::TransferBuffer::AllocateRingBuffer.*", - "allocator": "mmap" - }, - { - "name": "mmap-gpu-gles2-createbuffer", - "stacktrace": ".*gpu::gles2::BufferTracker::CreateBuffer.*", - "allocator": "mmap" - }, - { - "name": "mmap-skia-font", - "stacktrace": ".*SkTypeface::openStream.*", - "allocator": "mmap" - }, - { - "name": "mmap-catch-all", - "stacktrace": ".*", - "allocator": "mmap" - }, - { - "name": "tc-disk_cache-backing", - "stacktrace": ".*disk_cache::BackendImpl::InitBackingStore.*", - "allocator": "malloc" - }, - { - "name": "tc-disk_cache-other", - "stacktrace": ".*disk_cache::.*", - "allocator": "malloc" - }, - { - "name": "tc-sqlite3MemAlloc", - "stacktrace": ".*sqlite3MemMalloc.*", - "allocator": "malloc" - }, - { - "name": "tc-angle", - "stacktrace": ".*TPoolAllocator::allocate.*", - "allocator": "malloc" - }, - { - "name": "tc-crypto", - "stacktrace": ".*(CRYPTO_malloc|CRYPTO_realloc).*", - "allocator": "malloc" - }, - { - "name": "tc-net-iobuffer", - "stacktrace": ".*net::IOBuffer::IOBuffer.*", - "allocator": "malloc" - }, - { - "name": "tc-stl-string", - "stacktrace": ".*std::basic_string::.*", - "allocator": "malloc" - }, - { - "name": "tc-stl-rbtree", - "stacktrace": ".*std::priv::_Rb_tree::.*", - "allocator": "malloc" - }, - { - "name": "tc-stl-vector", - "stacktrace": ".*std::priv::_Impl_vector::.*", - "allocator": "malloc" - }, - { - "name": "tc-stl-hashtable", - "stacktrace": ".*std::hashtable::.*", - "allocator": "malloc" - }, - { - "name": "tc-stl-node", - "stacktrace": ".*std::priv::_Impl_vector::.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-fontcache", - "stacktrace": ".*WebCore::FontCache::getCachedFontData.*", - "allocator": "malloc" - }, - { - "name": "tc-skia", - "stacktrace": ".* Sk[A-Za-z_]+::.*", - "allocator": "malloc" - }, - { - "name": "tc-renderobject", - "stacktrace": ".*WebCore::RenderArena::allocate.*", - "allocator": "malloc" - }, - { - "name": "tc-renderstyle", - "stacktrace": ".*WebCore::RenderStyle::create.*", - "allocator": "malloc" - }, - { - "name": "tc-renderstyle", - "stacktrace": ".*WebCore::RenderStyle::clone.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-sharedbuf", - "stacktrace": ".*WebCore::SharedBuffer::create.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-sharedbuf", - "stacktrace": ".*WebCore::SharedBuffer::buffer.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-sharedbuf", - "stacktrace": ".*WebCore::SharedBuffer::append.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-XHRcreate", - "stacktrace": ".*WebCore::XMLHttpRequest::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-XHRreceived", - "stacktrace": ".*WebCore::XMLHttpRequest::didReceiveData.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-docwriter-add", - "stacktrace": ".*WebCore::DocumentWriter::addData.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-and-doc", - "stacktrace": ".*WebCore::HTML[a-zA-Z0-9_]*Element::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-and-doc", - "stacktrace": ".*WebCore::Text::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-and-doc", - "stacktrace": ".*WebCore::Comment::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-and-doc", - "stacktrace": ".*WebCore::HTMLDocument::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-and-doc", - "stacktrace": ".*WebCore::CSSStyleRule::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-and-doc", - "stacktrace": ".*WebCore::Attribute::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-and-doc", - "stacktrace": ".*WebCore::DOMWindow::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-factory", - "stacktrace": ".*WebCore::HTML[a-zA-Z0-9_]*Factory::create[a-zA-Z0-9_]*Element.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-element-wrapper", - "stacktrace": ".*WebCore::createHTML[a-zA-Z0-9_]*ElementWrapper.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-stylepropertyset", - "stacktrace": ".*WebCore::StylePropertySet::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-style-createsheet", - "stacktrace": ".*WebCore::StyleElement::createSheet.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-cachedresource", - "stacktrace": ".*WebCore::CachedResource::data .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-cachedresource", - "stacktrace": ".*WebCore::CachedResource::load .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-script-execute", - "stacktrace": ".*WebCore::ScriptElement::execute.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-events-related", - "stacktrace": ".*WebCore::createAttributeEventListener.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-events-related", - "stacktrace": ".*WebCore::V8LazyEventListener::create.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-events-related", - "stacktrace": ".*WebCore::V8EventListener::create.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-events-related", - "stacktrace": ".*WebCore::Event::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-events-related", - "stacktrace": ".*WebCore::EventListener::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-document-write", - "stacktrace": ".*WebCore::Document::write.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-create-renderer", - "stacktrace": ".*WebCore::Node::createRendererIfNeeded.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-render-catch-all", - "stacktrace": ".*WebCore::RenderLayer.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-render-catch-all", - "stacktrace": ".*WebCore::RenderBlock.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-render-catch-all", - "stacktrace": ".*WebCore::RenderWidget.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-render-catch-all", - "stacktrace": ".*WebCore::RenderView.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-render-catch-all", - "stacktrace": ".*WebCore::RenderViewImpl.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-render-catch-all", - "stacktrace": ".*WebCore::RenderStyle.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-render-catch-all", - "stacktrace": ".*WebCore::RenderText.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-render-catch-all", - "stacktrace": ".* RendererMain .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-setInnerHTML-except-node", - "stacktrace": ".*WebCore::HTMLElement::setInnerHTML.*", - "allocator": "malloc" - }, - { - "name": "tc-wtf-StringImpl-user-catch-all", - "stacktrace": ".*WTF::StringImpl::create .*", - "allocator": "malloc" - }, - { - "name": "tc-wtf-StringImpl-user-catch-all", - "stacktrace": ".*WTF::StringImpl::createUninitialized.*", - "allocator": "malloc" - }, - { - "name": "tc-wtf-HashTable-user-catch-all", - "stacktrace": ".*WTF::HashTable::allocateTable.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-everything-create", - "stacktrace": ".*WebCore::[a-zA-Z0-9_]*::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webkit-from-v8-catch-all", - "stacktrace": ".*(WTF::|WebCore::|WebKit::).*v8::.*", - "allocator": "malloc" - }, - { - "name": "tc-webkit-catch-all", - "stacktrace": ".*(WTF::|WebCore::|WebKit::).*", - "allocator": "malloc" - }, - { - "name": "tc-v8-catch-all", - "stacktrace": ".*v8::.*", - "allocator": "malloc" - }, - { - "name": "tc-toplevel-string", - "stacktrace": "std::basic_string::_Rep::_S_create", - "allocator": "malloc" - }, - { - "name": "tc-std-treemap", - "stacktrace": ".*::allocate std::(_Rb_tree|__1::__tree).*", - "allocator": "malloc" - }, - { - "name": "tc-std-hashmap", - "stacktrace": ".*(std::vector::reserve __gnu_cxx::hashtable|::allocate std::_Hashtable|::allocate std::__1::__hash_table).*", - "allocator": "malloc" - }, - { - "name": "tc-std-vector", - "stacktrace": ".*std::(_Vector_base::_M_allocate|__1::vector::allocate).*", - "allocator": "malloc" - }, - { - "name": "tc-std-other", - "stacktrace": ".*(__gnu_cxx::new_allocator::allocate|std::__1::allocator::allocate).*", - "allocator": "malloc" - }, - { - "name": "tc-catch-all", - "stacktrace": ".*", - "allocator": "malloc" - }, - { - "name": "UNTIL_HERE_FOR_TOTAL", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "total-exclude-profiler", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "total", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "absent", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "anonymous", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "file-exec", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "file-nonexec", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "stack", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "other", - "stacktrace": "optional", - "allocator": "optional" - } - ], - "version": "POLICY_DEEP_3" -} diff --git a/tools/deep_memory_profiler/policy.l0.json b/tools/deep_memory_profiler/policy.l0.json deleted file mode 100644 index 14eeb9f3ec..0000000000 --- a/tools/deep_memory_profiler/policy.l0.json +++ /dev/null @@ -1,162 +0,0 @@ -{ - "components": [ - "second", - "mmap-profiler", - "mmap-type-profiler", - "mmap-tcmalloc", - "FROM_HERE_FOR_TOTAL", - "mustbezero", - "unhooked-absent", - "unhooked-anonymous", - "unhooked-file-exec", - "unhooked-file-nonexec", - "unhooked-stack", - "unhooked-other", - "no-bucket", - "mmap-v8", - "mmap-catch-all", - "tc-used-all", - "tc-unused", - "UNTIL_HERE_FOR_TOTAL", - "total-exclude-profiler", - "total", - "absent", - "anonymous", - "file-exec", - "file-nonexec", - "stack", - "other", - "mmap-total-log", - "mmap-no-log", - "mmap-total-record", - "other-total-log", - "tc-total-log", - "tc-no-log", - "tc-total-record", - "tc-total" - ], - "rules": [ - { - "name": "second", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "mmap-profiler", - "stacktrace": ".*(ProfilerMalloc|MemoryRegionMap::).*", - "allocator": "mmap" - }, - { - "name": "mmap-type-profiler", - "stacktrace": ".*(TypeProfilerMalloc).*", - "allocator": "mmap" - }, - { - "name": "mmap-tcmalloc", - "stacktrace": ".*(DoAllocWithArena|SbrkSysAllocator::Alloc|MmapSysAllocator::Alloc|LowLevelAlloc::Alloc|LowLevelAlloc::AllocWithArena).*", - "allocator": "mmap" - }, - { - "name": "FROM_HERE_FOR_TOTAL", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "mustbezero", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "unhooked-absent", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "unhooked-anonymous", - "mappedpathname": "^$", - "allocator": "unhooked" - }, - { - "name": "unhooked-file-exec", - "mappedpathname": "^/.*", - "mappedpermission": "..x.", - "allocator": "unhooked" - }, - { - "name": "unhooked-file-nonexec", - "mappedpathname": "^/.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-stack", - "mappedpathname": ".stack.", - "allocator": "unhooked" - }, - { - "name": "unhooked-other", - "mappedpathname": ".*", - "allocator": "unhooked" - }, - { - "name": "mmap-v8", - "stacktrace": ".*v8::.*", - "allocator": "mmap" - }, - { - "name": "mmap-catch-all", - "stacktrace": ".*", - "allocator": "mmap" - }, - { - "name": "tc-used-all", - "stacktrace": ".*", - "allocator": "malloc" - }, - { - "name": "UNTIL_HERE_FOR_TOTAL", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "total-exclude-profiler", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "total", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "absent", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "anonymous", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "file-exec", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "file-nonexec", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "stack", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "other", - "stacktrace": "optional", - "allocator": "optional" - } - ], - "version": "POLICY_DEEP_3" -} diff --git a/tools/deep_memory_profiler/policy.l1.json b/tools/deep_memory_profiler/policy.l1.json deleted file mode 100644 index 599c540693..0000000000 --- a/tools/deep_memory_profiler/policy.l1.json +++ /dev/null @@ -1,204 +0,0 @@ -{ - "components": [ - "second", - "mmap-profiler", - "mmap-type-profiler", - "mmap-tcmalloc", - "FROM_HERE_FOR_TOTAL", - "mustbezero", - "unhooked-absent", - "unhooked-anonymous", - "unhooked-file-exec", - "unhooked-file-nonexec", - "unhooked-stack", - "unhooked-other", - "no-bucket", - "mmap-v8-heap-newspace", - "mmap-v8-heap-coderange", - "mmap-v8-heap-pagedspace", - "mmap-v8-other", - "mmap-catch-all", - "tc-v8", - "tc-skia", - "tc-webkit-catch-all", - "tc-unknown-string", - "tc-catch-all", - "tc-unused", - "UNTIL_HERE_FOR_TOTAL", - "total-exclude-profiler", - "total", - "absent", - "anonymous", - "file-exec", - "file-nonexec", - "stack", - "other", - "mmap-total-log", - "mmap-no-log", - "mmap-total-record", - "other-total-log", - "tc-total-log", - "tc-no-log", - "tc-total-record", - "tc-total" - ], - "rules": [ - { - "name": "second", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "mmap-profiler", - "stacktrace": ".*(ProfilerMalloc|MemoryRegionMap::).*", - "allocator": "mmap" - }, - { - "name": "mmap-type-profiler", - "stacktrace": ".*(TypeProfilerMalloc).*", - "allocator": "mmap" - }, - { - "name": "mmap-tcmalloc", - "stacktrace": ".*(DoAllocWithArena|SbrkSysAllocator::Alloc|MmapSysAllocator::Alloc|LowLevelAlloc::Alloc|LowLevelAlloc::AllocWithArena).*", - "allocator": "mmap" - }, - { - "name": "FROM_HERE_FOR_TOTAL", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "mustbezero", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "unhooked-absent", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "unhooked-anonymous", - "mappedpathname": "^$", - "allocator": "unhooked" - }, - { - "name": "unhooked-file-exec", - "mappedpathname": "^/.*", - "mappedpermission": "..x.", - "allocator": "unhooked" - }, - { - "name": "unhooked-file-nonexec", - "mappedpathname": "^/.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-stack", - "mappedpathname": ".stack.", - "allocator": "unhooked" - }, - { - "name": "unhooked-other", - "mappedpathname": ".*", - "allocator": "unhooked" - }, - { - "name": "mmap-v8-heap-newspace", - "stacktrace": ".*v8::internal::NewSpace::SetUp.*", - "allocator": "mmap" - }, - { - "name": "mmap-v8-heap-coderange", - "stacktrace": ".*v8::internal::CodeRange::SetUp.*", - "allocator": "mmap" - }, - { - "name": "mmap-v8-heap-pagedspace", - "stacktrace": ".*v8::internal::PagedSpace::AllocateRaw.*", - "allocator": "mmap" - }, - { - "name": "mmap-v8-other", - "stacktrace": ".*v8::.*", - "allocator": "mmap" - }, - { - "name": "mmap-catch-all", - "stacktrace": ".*", - "allocator": "mmap" - }, - { - "name": "tc-v8", - "stacktrace": ".*v8::.*", - "allocator": "malloc" - }, - { - "name": "tc-skia", - "stacktrace": ".*Sk[A-Za-z_]+::.*", - "allocator": "malloc" - }, - { - "name": "tc-webkit-catch-all", - "stacktrace": ".*(WTF::|WebCore::|WebKit::).*", - "allocator": "malloc" - }, - { - "name": "tc-unknown-string", - "stacktrace": ".*std::basic_string::_Rep::_S_create.*", - "allocator": "malloc" - }, - { - "name": "tc-catch-all", - "stacktrace": ".*", - "allocator": "malloc" - }, - { - "name": "UNTIL_HERE_FOR_TOTAL", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "total-exclude-profiler", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "total", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "absent", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "anonymous", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "file-exec", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "file-nonexec", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "stack", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "other", - "stacktrace": "optional", - "allocator": "optional" - } - ], - "version": "POLICY_DEEP_3" -} diff --git a/tools/deep_memory_profiler/policy.l2.json b/tools/deep_memory_profiler/policy.l2.json deleted file mode 100644 index f0a007b133..0000000000 --- a/tools/deep_memory_profiler/policy.l2.json +++ /dev/null @@ -1,490 +0,0 @@ -{ - "components": [ - "second", - "mmap-profiler", - "mmap-type-profiler", - "mmap-tcmalloc", - "FROM_HERE_FOR_TOTAL", - "mustbezero", - "unhooked-absent", - "unhooked-anonymous", - "unhooked-file-exec", - "unhooked-file-nonexec-others", - "unhooked-file-nonexec-group", - "unhooked-file-nonexec", - "unhooked-stack", - "unhooked-other", - "no-bucket", - "mmap-v8-heap-newspace", - "mmap-v8-heap-coderange", - "mmap-v8-heap-pagedspace", - "mmap-v8-other", - "mmap-catch-all", - "tc-webcore-fontcache", - "tc-skia", - "tc-renderobject", - "tc-renderstyle", - "tc-webcore-sharedbuf", - "tc-webcore-XHRcreate", - "tc-webcore-XHRreceived", - "tc-webcore-docwriter-add", - "tc-webcore-node-and-doc", - "tc-webcore-node-factory", - "tc-webcore-element-wrapper", - "tc-webcore-stylepropertyset", - "tc-webcore-style-createsheet", - "tc-webcore-cachedresource", - "tc-webcore-script-execute", - "tc-webcore-events-related", - "tc-webcore-document-write", - "tc-webcore-node-create-renderer", - "tc-webcore-render-catch-all", - "tc-webcore-setInnerHTML-except-node", - "tc-wtf-StringImpl-user-catch-all", - "tc-wtf-HashTable-user-catch-all", - "tc-webcore-everything-create", - "tc-webkit-from-v8-catch-all", - "tc-webkit-catch-all", - "tc-v8-catch-all", - "tc-toplevel-string", - "tc-std-treemap", - "tc-std-hashmap", - "tc-std-vector", - "tc-std-other", - "tc-catch-all", - "tc-unused", - "UNTIL_HERE_FOR_TOTAL", - "total-exclude-profiler", - "total", - "absent", - "anonymous", - "file-exec", - "file-nonexec", - "stack", - "other", - "mmap-total-log", - "mmap-no-log", - "mmap-total-record", - "other-total-log", - "tc-total-log", - "tc-no-log", - "tc-total-record", - "tc-total" - ], - "rules": [ - { - "name": "second", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "mmap-profiler", - "stacktrace": ".*(ProfilerMalloc|MemoryRegionMap::).*", - "allocator": "mmap" - }, - { - "name": "mmap-type-profiler", - "stacktrace": ".*(TypeProfilerMalloc).*", - "allocator": "mmap" - }, - { - "name": "mmap-tcmalloc", - "stacktrace": ".*(DoAllocWithArena|SbrkSysAllocator::Alloc|MmapSysAllocator::Alloc|LowLevelAlloc::Alloc|LowLevelAlloc::AllocWithArena).*", - "allocator": "mmap" - }, - { - "name": "FROM_HERE_FOR_TOTAL", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "mustbezero", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "unhooked-absent", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "unhooked-anonymous", - "mappedpathname": "^$", - "allocator": "unhooked" - }, - { - "name": "unhooked-file-exec", - "mappedpathname": "^/.*", - "mappedpermission": "..x.", - "allocator": "unhooked" - }, - { - "name": "unhooked-file-nonexec-others", - "mappedpathname": "^/.*", - "allocator": "unhooked", - "sharedwith": ["others"] - }, - { - "name": "unhooked-file-nonexec-group", - "mappedpathname": "^/.*", - "allocator": "unhooked", - "sharedwith": ["group"] - }, - { - "name": "unhooked-file-nonexec", - "mappedpathname": "^/.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-stack", - "mappedpathname": ".stack.", - "allocator": "unhooked" - }, - { - "name": "unhooked-other", - "mappedpathname": ".*", - "allocator": "unhooked" - }, - { - "name": "mmap-v8-heap-newspace", - "stacktrace": ".*v8::internal::NewSpace::SetUp.*", - "allocator": "mmap" - }, - { - "name": "mmap-v8-heap-coderange", - "stacktrace": ".*v8::internal::CodeRange::SetUp.*", - "allocator": "mmap" - }, - { - "name": "mmap-v8-heap-pagedspace", - "stacktrace": ".*v8::internal::PagedSpace::AllocateRaw.*", - "allocator": "mmap" - }, - { - "name": "mmap-v8-other", - "stacktrace": ".*v8::.*", - "allocator": "mmap" - }, - { - "name": "mmap-catch-all", - "stacktrace": ".*", - "allocator": "mmap" - }, - { - "name": "tc-webcore-fontcache", - "stacktrace": ".*WebCore::FontCache::getCachedFontData.*", - "allocator": "malloc" - }, - { - "name": "tc-skia", - "stacktrace": ".* Sk[A-Za-z_]+::.*", - "allocator": "malloc" - }, - { - "name": "tc-renderobject", - "stacktrace": ".*WebCore::RenderArena::allocate.*", - "allocator": "malloc" - }, - { - "name": "tc-renderstyle", - "stacktrace": ".*WebCore::RenderStyle::create.*", - "allocator": "malloc" - }, - { - "name": "tc-renderstyle", - "stacktrace": ".*WebCore::RenderStyle::clone.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-sharedbuf", - "stacktrace": ".*WebCore::SharedBuffer::create.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-sharedbuf", - "stacktrace": ".*WebCore::SharedBuffer::buffer.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-sharedbuf", - "stacktrace": ".*WebCore::SharedBuffer::append.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-XHRcreate", - "stacktrace": ".*WebCore::XMLHttpRequest::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-XHRreceived", - "stacktrace": ".*WebCore::XMLHttpRequest::didReceiveData.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-docwriter-add", - "stacktrace": ".*WebCore::DocumentWriter::addData.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-and-doc", - "stacktrace": ".*WebCore::HTML[a-zA-Z0-9_]*Element::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-and-doc", - "stacktrace": ".*WebCore::Text::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-and-doc", - "stacktrace": ".*WebCore::Comment::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-and-doc", - "stacktrace": ".*WebCore::HTMLDocument::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-and-doc", - "stacktrace": ".*WebCore::CSSStyleRule::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-and-doc", - "stacktrace": ".*WebCore::Attribute::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-and-doc", - "stacktrace": ".*WebCore::DOMWindow::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-factory", - "stacktrace": ".*WebCore::HTML[a-zA-Z0-9_]*Factory::create[a-zA-Z0-9_]*Element.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-element-wrapper", - "stacktrace": ".*WebCore::createHTML[a-zA-Z0-9_]*ElementWrapper.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-stylepropertyset", - "stacktrace": ".*WebCore::StylePropertySet::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-style-createsheet", - "stacktrace": ".*WebCore::StyleElement::createSheet.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-cachedresource", - "stacktrace": ".*WebCore::CachedResource::data .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-cachedresource", - "stacktrace": ".*WebCore::CachedResource::load .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-script-execute", - "stacktrace": ".*WebCore::ScriptElement::execute.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-events-related", - "stacktrace": ".*WebCore::createAttributeEventListener.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-events-related", - "stacktrace": ".*WebCore::V8LazyEventListener::create.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-events-related", - "stacktrace": ".*WebCore::V8EventListener::create.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-events-related", - "stacktrace": ".*WebCore::Event::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-events-related", - "stacktrace": ".*WebCore::EventListener::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-document-write", - "stacktrace": ".*WebCore::Document::write.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-node-create-renderer", - "stacktrace": ".*WebCore::Node::createRendererIfNeeded.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-render-catch-all", - "stacktrace": ".*WebCore::RenderLayer.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-render-catch-all", - "stacktrace": ".*WebCore::RenderBlock.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-render-catch-all", - "stacktrace": ".*WebCore::RenderWidget.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-render-catch-all", - "stacktrace": ".*WebCore::RenderView.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-render-catch-all", - "stacktrace": ".*WebCore::RenderViewImpl.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-render-catch-all", - "stacktrace": ".*WebCore::RenderStyle.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-render-catch-all", - "stacktrace": ".*WebCore::RenderText.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-render-catch-all", - "stacktrace": ".* RendererMain .*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-setInnerHTML-except-node", - "stacktrace": ".*WebCore::HTMLElement::setInnerHTML.*", - "allocator": "malloc" - }, - { - "name": "tc-wtf-StringImpl-user-catch-all", - "stacktrace": ".*WTF::StringImpl::create .*", - "allocator": "malloc" - }, - { - "name": "tc-wtf-StringImpl-user-catch-all", - "stacktrace": ".*WTF::StringImpl::createUninitialized.*", - "allocator": "malloc" - }, - { - "name": "tc-wtf-HashTable-user-catch-all", - "stacktrace": ".*WTF::HashTable::allocateTable.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore-everything-create", - "stacktrace": ".*WebCore::[a-zA-Z0-9_]*::create .*", - "allocator": "malloc" - }, - { - "name": "tc-webkit-from-v8-catch-all", - "stacktrace": ".*(WTF::|WebCore::|WebKit::).*v8::.*", - "allocator": "malloc" - }, - { - "name": "tc-webkit-catch-all", - "stacktrace": ".*(WTF::|WebCore::|WebKit::).*", - "allocator": "malloc" - }, - { - "name": "tc-v8-catch-all", - "stacktrace": ".*v8::.*", - "allocator": "malloc" - }, - { - "name": "tc-toplevel-string", - "stacktrace": "std::basic_string::_Rep::_S_create", - "allocator": "malloc" - }, - { - "name": "tc-std-treemap", - "stacktrace": ".*::allocate std::(_Rb_tree|__1::__tree).*", - "allocator": "malloc" - }, - { - "name": "tc-std-hashmap", - "stacktrace": ".*(std::vector::reserve __gnu_cxx::hashtable|::allocate std::_Hashtable|::allocate std::__1::__hash_table).*", - "allocator": "malloc" - }, - { - "name": "tc-std-vector", - "stacktrace": ".*std::(_Vector_base::_M_allocate|__1::vector::allocate).*", - "allocator": "malloc" - }, - { - "name": "tc-std-other", - "stacktrace": ".*(__gnu_cxx::new_allocator::allocate|std::__1::allocator::allocate).*", - "allocator": "malloc" - }, - { - "name": "tc-catch-all", - "stacktrace": ".*", - "allocator": "malloc" - }, - { - "name": "UNTIL_HERE_FOR_TOTAL", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "total-exclude-profiler", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "total", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "absent", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "anonymous", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "file-exec", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "file-nonexec", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "stack", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "other", - "stacktrace": "optional", - "allocator": "optional" - } - ], - "version": "POLICY_DEEP_3" -} diff --git a/tools/deep_memory_profiler/policy.sourcefile.json b/tools/deep_memory_profiler/policy.sourcefile.json deleted file mode 100644 index 7a037e5973..0000000000 --- a/tools/deep_memory_profiler/policy.sourcefile.json +++ /dev/null @@ -1,186 +0,0 @@ -{ - "components": [ - "second", - "mmap-profiler", - "mmap-type-profiler", - "mmap-tcmalloc", - "FROM_HERE_FOR_TOTAL", - "mustbezero", - "unhooked-absent", - "unhooked-anonymous", - "unhooked-file-exec", - "unhooked-file-nonexec", - "unhooked-stack", - "unhooked-other", - "no-bucket", - "mmap-v8", - "mmap-catch-all", - "tc-v8", - "tc-skia", - "tc-webcore", - "tc-webkit", - "tc-catch-all", - "tc-unused", - "UNTIL_HERE_FOR_TOTAL", - "total-exclude-profiler", - "total", - "absent", - "anonymous", - "file-exec", - "file-nonexec", - "stack", - "other", - "mmap-total-log", - "mmap-no-log", - "mmap-total-record", - "other-total-log", - "tc-total-log", - "tc-no-log", - "tc-total-record", - "tc-total" - ], - "rules": [ - { - "name": "second", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "mmap-profiler", - "stacktrace": ".*(ProfilerMalloc|MemoryRegionMap::).*", - "allocator": "mmap" - }, - { - "name": "mmap-type-profiler", - "stacktrace": ".*(TypeProfilerMalloc).*", - "allocator": "mmap" - }, - { - "name": "mmap-tcmalloc", - "stacktrace": ".*(DoAllocWithArena|SbrkSysAllocator::Alloc|MmapSysAllocator::Alloc|LowLevelAlloc::Alloc|LowLevelAlloc::AllocWithArena).*", - "allocator": "mmap" - }, - { - "name": "FROM_HERE_FOR_TOTAL", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "mustbezero", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "unhooked-absent", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "unhooked-anonymous", - "mappedpathname": "^$", - "allocator": "unhooked" - }, - { - "name": "unhooked-file-exec", - "mappedpathname": "^/.*", - "mappedpermission": "..x.", - "allocator": "unhooked" - }, - { - "name": "unhooked-file-nonexec", - "mappedpathname": "^/.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-stack", - "mappedpathname": ".stack.", - "allocator": "unhooked" - }, - { - "name": "unhooked-other", - "mappedpathname": ".*", - "allocator": "unhooked" - }, - { - "name": "mmap-v8", - "stacksourcefile": ".*\\.\\./\\.\\./v8/src/.*", - "allocator": "mmap" - }, - { - "name": "mmap-catch-all", - "stacksourcefile": ".*", - "allocator": "mmap" - }, - { - "name": "tc-v8", - "stacksourcefile": ".*\\.\\./\\.\\./v8/src/.*", - "allocator": "malloc" - }, - { - "name": "tc-skia", - "stacksourcefile": ".*\\.\\./\\.\\./third_party/skia/src/.*", - "allocator": "malloc" - }, - { - "name": "tc-webcore", - "stacksourcefile": ".*\\.\\./\\.\\./third_party/WebKit/Source/WebCore/.*", - "allocator": "malloc" - }, - { - "name": "tc-webkit", - "stacksourcefile": ".*\\.\\./\\.\\./third_party/WebKit/Source/.*", - "allocator": "malloc" - }, - { - "name": "tc-catch-all", - "stacksourcefile": ".*", - "allocator": "malloc" - }, - { - "name": "UNTIL_HERE_FOR_TOTAL", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "total-exclude-profiler", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "total", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "absent", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "anonymous", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "file-exec", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "file-nonexec", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "stack", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "other", - "stacktrace": "optional", - "allocator": "optional" - } - ], - "version": "POLICY_DEEP_3" -} diff --git a/tools/deep_memory_profiler/policy.t0.json b/tools/deep_memory_profiler/policy.t0.json deleted file mode 100644 index fd716babe0..0000000000 --- a/tools/deep_memory_profiler/policy.t0.json +++ /dev/null @@ -1,205 +0,0 @@ -{ - "components": [ - "second", - "mmap-profiler", - "mmap-type-profiler", - "mmap-tcmalloc", - "FROM_HERE_FOR_TOTAL", - "mustbezero", - "unhooked-absent", - "unhooked-anonymous", - "unhooked-file-exec", - "unhooked-file-nonexec", - "unhooked-stack", - "unhooked-other", - "no-bucket", - "mmap-v8", - "mmap-catch-all", - "tc-std-string", - "tc-WTF-String", - "tc-no-typeinfo-StringImpl", - "tc-Skia", - "tc-WebCore-Style", - "tc-no-typeinfo-other", - "tc-other", - "tc-unused", - "UNTIL_HERE_FOR_TOTAL", - "total-exclude-profiler", - "total", - "absent", - "anonymous", - "file-exec", - "file-nonexec", - "stack", - "other", - "mmap-total-log", - "mmap-no-log", - "mmap-total-record", - "other-total-log", - "tc-total-log", - "tc-no-log", - "tc-total-record", - "tc-total" - ], - "rules": [ - { - "name": "second", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "mmap-profiler", - "stacktrace": ".*(ProfilerMalloc|MemoryRegionMap::).*", - "allocator": "mmap" - }, - { - "name": "mmap-type-profiler", - "stacktrace": ".*(TypeProfilerMalloc).*", - "allocator": "mmap" - }, - { - "name": "mmap-tcmalloc", - "stacktrace": ".*(DoAllocWithArena|SbrkSysAllocator::Alloc|MmapSysAllocator::Alloc|LowLevelAlloc::Alloc|LowLevelAlloc::AllocWithArena).*", - "allocator": "mmap" - }, - { - "name": "FROM_HERE_FOR_TOTAL", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "mustbezero", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "unhooked-absent", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "unhooked-anonymous", - "mappedpathname": "^$", - "allocator": "unhooked" - }, - { - "name": "unhooked-file-exec", - "mappedpathname": "^/.*", - "mappedpermission": "..x.", - "allocator": "unhooked" - }, - { - "name": "unhooked-file-nonexec", - "mappedpathname": "^/.*", - "allocator": "unhooked" - }, - { - "name": "unhooked-stack", - "mappedpathname": ".stack.", - "allocator": "unhooked" - }, - { - "name": "unhooked-other", - "mappedpathname": ".*", - "allocator": "unhooked" - }, - { - "name": "mmap-v8", - "stacktrace": ".*v8::.*", - "allocator": "mmap" - }, - { - "name": "mmap-catch-all", - "stacktrace": ".*", - "allocator": "mmap" - }, - { - "name": "tc-std-string", - "stacktrace": ".*", - "typeinfo": "std::basic_string.*", - "allocator": "malloc" - }, - { - "name": "tc-WTF-String", - "stacktrace": ".*", - "typeinfo": "WTF::String.*", - "allocator": "malloc" - }, - { - "name": "tc-no-typeinfo-StringImpl", - "stacktrace": ".*WTF::StringImpl::getData16SlowCase.*", - "typeinfo": "no typeinfo", - "allocator": "malloc" - }, - { - "name": "tc-Skia", - "stacktrace": ".*", - "typeinfo": "(skia::|SkGlyph).*", - "allocator": "malloc" - }, - { - "name": "tc-WebCore-Style", - "stacktrace": ".*", - "typeinfo": "WebCore::Style.*", - "allocator": "malloc" - }, - { - "name": "tc-no-typeinfo-other", - "stacktrace": ".*", - "typeinfo": "no typeinfo", - "allocator": "malloc" - }, - { - "name": "tc-other", - "stacktrace": ".*", - "typeinfo": ".*", - "allocator": "malloc" - }, - { - "name": "UNTIL_HERE_FOR_TOTAL", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "total-exclude-profiler", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "total", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "absent", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "anonymous", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "file-exec", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "file-nonexec", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "stack", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "other", - "stacktrace": "optional", - "allocator": "optional" - } - ], - "version": "POLICY_DEEP_4" -} diff --git a/tools/deep_memory_profiler/sorter.malloc-component.json b/tools/deep_memory_profiler/sorter.malloc-component.json deleted file mode 100644 index c5c809507a..0000000000 --- a/tools/deep_memory_profiler/sorter.malloc-component.json +++ /dev/null @@ -1,261 +0,0 @@ -{ - "type": "sorter", - "version": 1, - "world": "malloc", - "name": "component", - "order": { - "preset1": [ - "tc-webcore-fontcache", - "tc-skia", - "tc-renderobject", - "tc-renderstyle", - "tc-webcore-sharedbuf", - "tc-webcore-XHRcreate", - "tc-webcore-XHRreceived", - "tc-webcore-docwriter-add", - "tc-webcore-node-and-doc", - "tc-webcore-node-factory", - "tc-webcore-element-wrapper", - "tc-webcore-stylepropertyset", - "tc-webcore-style-createsheet", - "tc-webcore-cachedresource", - "tc-webcore-script-execute", - "tc-webcore-events-related", - "tc-webcore-document-write", - "tc-webcore-node-create-renderer", - "tc-webcore-render-catch-all", - "tc-webcore-setInnerHTML-except-node", - "tc-wtf-StringImpl-user-catch-all", - "tc-wtf-HashTable-user-catch-all", - "tc-webcore-everything-create", - "tc-webkit-from-v8-catch-all", - "tc-webkit-catch-all", - "tc-v8-catch-all", - "tc-toplevel-string", - "tc-std-treemap", - "tc-std-hashmap", - "tc-std-vector", - "tc-std-other", - "tc-catch-all", - "tc-unused" - ] - }, - "rules": [ - { - "name": "tc-webcore-fontcache", - "backtrace_function": ".*WebCore::FontCache::getCachedFontData.*" - }, - { - "name": "tc-skia", - "backtrace_function": ".* Sk[A-Za-z_]+::.*" - }, - { - "name": "tc-renderobject", - "backtrace_function": ".*WebCore::RenderArena::allocate.*" - }, - { - "name": "tc-renderstyle", - "backtrace_function": ".*WebCore::RenderStyle::create.*" - }, - { - "name": "tc-renderstyle", - "backtrace_function": ".*WebCore::RenderStyle::clone.*" - }, - { - "name": "tc-webcore-sharedbuf", - "backtrace_function": ".*WebCore::SharedBuffer::create.*" - }, - { - "name": "tc-webcore-sharedbuf", - "backtrace_function": ".*WebCore::SharedBuffer::buffer.*" - }, - { - "name": "tc-webcore-sharedbuf", - "backtrace_function": ".*WebCore::SharedBuffer::append.*" - }, - { - "name": "tc-webcore-XHRcreate", - "backtrace_function": ".*WebCore::XMLHttpRequest::create .*" - }, - { - "name": "tc-webcore-XHRreceived", - "backtrace_function": ".*WebCore::XMLHttpRequest::didReceiveData.*" - }, - { - "name": "tc-webcore-docwriter-add", - "backtrace_function": ".*WebCore::DocumentWriter::addData.*" - }, - { - "name": "tc-webcore-node-and-doc", - "backtrace_function": ".*WebCore::HTML[a-zA-Z0-9_]*Element::create .*" - }, - { - "name": "tc-webcore-node-and-doc", - "backtrace_function": ".*WebCore::Text::create .*" - }, - { - "name": "tc-webcore-node-and-doc", - "backtrace_function": ".*WebCore::Comment::create .*" - }, - { - "name": "tc-webcore-node-and-doc", - "backtrace_function": ".*WebCore::HTMLDocument::create .*" - }, - { - "name": "tc-webcore-node-and-doc", - "backtrace_function": ".*WebCore::CSSStyleRule::create .*" - }, - { - "name": "tc-webcore-node-and-doc", - "backtrace_function": ".*WebCore::Attribute::create .*" - }, - { - "name": "tc-webcore-node-and-doc", - "backtrace_function": ".*WebCore::DOMWindow::create .*" - }, - { - "name": "tc-webcore-node-factory", - "backtrace_function": ".*WebCore::HTML[a-zA-Z0-9_]*Factory::create[a-zA-Z0-9_]*Element.*" - }, - { - "name": "tc-webcore-element-wrapper", - "backtrace_function": ".*WebCore::createHTML[a-zA-Z0-9_]*ElementWrapper.*" - }, - { - "name": "tc-webcore-stylepropertyset", - "backtrace_function": ".*WebCore::StylePropertySet::create .*" - }, - { - "name": "tc-webcore-style-createsheet", - "backtrace_function": ".*WebCore::StyleElement::createSheet.*" - }, - { - "name": "tc-webcore-cachedresource", - "backtrace_function": ".*WebCore::CachedResource::data .*" - }, - { - "name": "tc-webcore-cachedresource", - "backtrace_function": ".*WebCore::CachedResource::load .*" - }, - { - "name": "tc-webcore-script-execute", - "backtrace_function": ".*WebCore::ScriptElement::execute.*" - }, - { - "name": "tc-webcore-events-related", - "backtrace_function": ".*WebCore::createAttributeEventListener.*" - }, - { - "name": "tc-webcore-events-related", - "backtrace_function": ".*WebCore::V8LazyEventListener::create.*" - }, - { - "name": "tc-webcore-events-related", - "backtrace_function": ".*WebCore::V8EventListener::create.*" - }, - { - "name": "tc-webcore-events-related", - "backtrace_function": ".*WebCore::Event::create .*" - }, - { - "name": "tc-webcore-events-related", - "backtrace_function": ".*WebCore::EventListener::create .*" - }, - { - "name": "tc-webcore-document-write", - "backtrace_function": ".*WebCore::Document::write.*" - }, - { - "name": "tc-webcore-node-create-renderer", - "backtrace_function": ".*WebCore::Node::createRendererIfNeeded.*" - }, - { - "name": "tc-webcore-render-catch-all", - "backtrace_function": ".*WebCore::RenderLayer.*" - }, - { - "name": "tc-webcore-render-catch-all", - "backtrace_function": ".*WebCore::RenderBlock.*" - }, - { - "name": "tc-webcore-render-catch-all", - "backtrace_function": ".*WebCore::RenderWidget.*" - }, - { - "name": "tc-webcore-render-catch-all", - "backtrace_function": ".*WebCore::RenderView.*" - }, - { - "name": "tc-webcore-render-catch-all", - "backtrace_function": ".*WebCore::RenderViewImpl.*" - }, - { - "name": "tc-webcore-render-catch-all", - "backtrace_function": ".*WebCore::RenderStyle.*" - }, - { - "name": "tc-webcore-render-catch-all", - "backtrace_function": ".*WebCore::RenderText.*" - }, - { - "name": "tc-webcore-render-catch-all", - "backtrace_function": ".* RendererMain .*" - }, - { - "name": "tc-webcore-setInnerHTML-except-node", - "backtrace_function": ".*WebCore::HTMLElement::setInnerHTML.*" - }, - { - "name": "tc-wtf-StringImpl-user-catch-all", - "backtrace_function": ".*WTF::StringImpl::create .*" - }, - { - "name": "tc-wtf-StringImpl-user-catch-all", - "backtrace_function": ".*WTF::StringImpl::createUninitialized.*" - }, - { - "name": "tc-wtf-HashTable-user-catch-all", - "backtrace_function": ".*WTF::HashTable::allocateTable.*" - }, - { - "name": "tc-webcore-everything-create", - "backtrace_function": ".*WebCore::[a-zA-Z0-9_]*::create .*" - }, - { - "name": "tc-webkit-from-v8-catch-all", - "backtrace_function": ".*(WTF::|WebCore::|WebKit::).*v8::.*" - }, - { - "name": "tc-webkit-catch-all", - "backtrace_function": ".*(WTF::|WebCore::|WebKit::).*" - }, - { - "name": "tc-v8-catch-all", - "backtrace_function": ".*v8::.*" - }, - { - "name": "tc-toplevel-string", - "backtrace_function": "std::basic_string::_Rep::_S_create" - }, - { - "name": "tc-std-treemap", - "backtrace_function": ".*::allocate std::(_Rb_tree|__1::__tree).*" - }, - { - "name": "tc-std-hashmap", - "backtrace_function": ".*(std::vector::reserve __gnu_cxx::hashtable|::allocate std::_Hashtable|::allocate std::__1::__hash_table).*" - }, - { - "name": "tc-std-vector", - "backtrace_function": ".*std::(_Vector_base::_M_allocate|__1::vector::allocate).*" - }, - { - "name": "tc-std-other", - "backtrace_function": ".*(__gnu_cxx::new_allocator::allocate|std::__1::allocator::allocate).*" - }, - { - "name": "tc-catch-all", - "backtrace_function": ".*" - } - ] -} diff --git a/tools/deep_memory_profiler/sorter.malloc-type.json b/tools/deep_memory_profiler/sorter.malloc-type.json deleted file mode 100644 index cc8ee65c6a..0000000000 --- a/tools/deep_memory_profiler/sorter.malloc-type.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "type": "sorter", - "version": 1, - "world": "malloc", - "name": "type", - "order": {}, - "rules": [ - { - "name": "tc-std-string", - "typeinfo": "std::basic_string.*" - }, - { - "name": "tc-WTF-String", - "typeinfo": "WTF::String.*" - }, - { - "name": "tc-no-typeinfo-StringImpl", - "backtrace_function": ".*WTF::StringImpl::getData16SlowCase.*", - "typeinfo": "no typeinfo" - }, - { - "name": "tc-Skia", - "typeinfo": "(skia::|SkGlyph).*" - }, - { - "name": "tc-WebCore-Style", - "typeinfo": "WebCore::Style.*" - }, - { - "name": "tc-no-typeinfo-other", - "typeinfo": "no typeinfo" - }, - { - "name": "tc-other", - "typeinfo": ".*" - } - ] -} diff --git a/tools/deep_memory_profiler/sorter.vm-map.json b/tools/deep_memory_profiler/sorter.vm-map.json deleted file mode 100644 index 7fc4d27785..0000000000 --- a/tools/deep_memory_profiler/sorter.vm-map.json +++ /dev/null @@ -1,107 +0,0 @@ -{ - "type": "sorter", - "version": 1, - "world": "vm", - "name": "map", - "root": true, - "order": {}, - "rules": [ - { - "name": "mmap-profiler", - "backtrace_function": ".*(ProfilerMalloc|MemoryRegionMap::).*", - "mmap": true, - "hidden": true - }, - { - "name": "mmap-type-profiler", - "backtrace_function": ".*(TypeProfilerMalloc).*", - "mmap": true, - "hidden": true - }, - { - "name": "unhooked-anonymous", - "mapped_pathname": "^$", - "mmap": false - }, - { - "name": "unhooked-file-exec", - "mapped_pathname": "^/.*", - "mapped_permission": "..x.", - "mmap": false - }, - { - "name": "unhooked-file-nonexec", - "mapped_pathname": "^/.*", - "mmap": false - }, - { - "name": "unhooked-stack", - "mapped_pathname": ".stack.", - "mmap": false - }, - { - "name": "unhooked-other", - "mapped_pathname": ".*", - "mmap": false - }, - { - "name": "mmap-tcmalloc", - "backtrace_function": ".*(DoAllocWithArena|SbrkSysAllocator::Alloc|MmapSysAllocator::Alloc|LowLevelAlloc::Alloc|LowLevelAlloc::AllocWithArena).*", - "subs": [ - [ "malloc", "component" ], - [ "malloc", "type" ] - ], - "mmap": true - }, - { - "name": "mmap-v8-heap-newspace", - "backtrace_function": ".*v8::internal::NewSpace::SetUp.*", - "mmap": true - }, - { - "name": "mmap-v8-heap-coderange", - "backtrace_function": ".*v8::internal::CodeRange::SetUp.*", - "mmap": true - }, - { - "name": "mmap-v8-heap-pagedspace", - "backtrace_function": ".*v8::internal::PagedSpace::AllocateRaw.*", - "mmap": true - }, - { - "name": "mmap-v8-other", - "backtrace_function": ".*v8::.*", - "mmap": true - }, - { - "name": "mmap-gpu-mappedmemorymanager", - "backtrace_function": ".*gpu::MappedMemoryManager::Alloc.*", - "mmap": true - }, - { - "name": "mmap-gpu-command-ringbuffer", - "backtrace_function": ".*gpu::CommandBufferHelper::AllocateRingBuffer.*", - "mmap": true - }, - { - "name": "mmap-gpu-transfer-ringbuffer", - "backtrace_function": ".*gpu::TransferBuffer::AllocateRingBuffer.*", - "mmap": true - }, - { - "name": "mmap-gpu-gles2-createbuffer", - "backtrace_function": ".*gpu::gles2::BufferTracker::CreateBuffer.*", - "mmap": true - }, - { - "name": "mmap-skia-font", - "backtrace_function": ".*SkTypeface::openStream.*", - "mmap": true - }, - { - "name": "mmap-catch-all", - "backtrace_function": ".*", - "mmap": true - } - ] -} diff --git a/tools/deep_memory_profiler/sorter.vm-sharing.json b/tools/deep_memory_profiler/sorter.vm-sharing.json deleted file mode 100644 index 4cb52a61f3..0000000000 --- a/tools/deep_memory_profiler/sorter.vm-sharing.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "type": "sorter", - "version": 1, - "world": "vm", - "name": "sharing", - "root": true, - "order": {}, - "rules": [ - { - "name": "others", - "sharedwith": ["others"] - }, - { - "name": "chrome", - "sharedwith": ["group"] - }, - { - "name": "private", - "sharedwith": ["private"] - }, - { - "name": "any" - } - ] -} diff --git a/tools/deep_memory_profiler/subcommands/__init__.py b/tools/deep_memory_profiler/subcommands/__init__.py deleted file mode 100644 index 4fb29d0c37..0000000000 --- a/tools/deep_memory_profiler/subcommands/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -from subcommands.buckets import BucketsCommand -from subcommands.cat import CatCommand -from subcommands.expand import ExpandCommand -from subcommands.map import MapCommand -from subcommands.policies import CSVCommand -from subcommands.policies import JSONCommand -from subcommands.policies import ListCommand -from subcommands.pprof import PProfCommand -from subcommands.stacktrace import StacktraceCommand -from subcommands.upload import UploadCommand diff --git a/tools/deep_memory_profiler/subcommands/buckets.py b/tools/deep_memory_profiler/subcommands/buckets.py deleted file mode 100644 index 4ea8640ca9..0000000000 --- a/tools/deep_memory_profiler/subcommands/buckets.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import logging -import sys - -from lib.subcommand import SubCommand - - -LOGGER = logging.getLogger('dmprof') - - -class BucketsCommand(SubCommand): - def __init__(self): - super(BucketsCommand, self).__init__('Usage: %prog buckets ') - - def do(self, sys_argv, out=sys.stdout): - _, args = self._parse_args(sys_argv, 1) - dump_path = args[1] - bucket_set = SubCommand.load_basic_files(dump_path, True, True) - - BucketsCommand._output(bucket_set, out) - return 0 - - @staticmethod - def _output(bucket_set, out): - """Prints all buckets with resolving symbols. - - Args: - bucket_set: A BucketSet object. - out: An IO object to output. - """ - for bucket_id, bucket in sorted(bucket_set): - out.write('%d: %s\n' % (bucket_id, bucket)) diff --git a/tools/deep_memory_profiler/subcommands/cat.py b/tools/deep_memory_profiler/subcommands/cat.py deleted file mode 100644 index 1e9e5b39d8..0000000000 --- a/tools/deep_memory_profiler/subcommands/cat.py +++ /dev/null @@ -1,179 +0,0 @@ -# Copyright 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import json -import logging -import sys - -from lib.bucket import BUCKET_ID, COMMITTED, ALLOC_COUNT, FREE_COUNT -from lib.ordered_dict import OrderedDict -from lib.subcommand import SubCommand -from lib.sorter import MallocUnit, MMapUnit, SorterSet, UnhookedUnit, UnitSet - - -LOGGER = logging.getLogger('dmprof') - - -class CatCommand(SubCommand): - def __init__(self): - super(CatCommand, self).__init__('Usage: %prog cat ') - self._parser.add_option('--alternative-dirs', dest='alternative_dirs', - metavar='/path/on/target@/path/on/host[:...]', - help='Read files in /path/on/host/ instead of ' - 'files in /path/on/target/.') - self._parser.add_option('--indent', dest='indent', action='store_true', - help='Indent the output.') - - def do(self, sys_argv): - options, args = self._parse_args(sys_argv, 1) - dump_path = args[1] - # TODO(dmikurube): Support shared memory. - alternative_dirs_dict = {} - if options.alternative_dirs: - for alternative_dir_pair in options.alternative_dirs.split(':'): - target_path, host_path = alternative_dir_pair.split('@', 1) - alternative_dirs_dict[target_path] = host_path - (bucket_set, dumps) = SubCommand.load_basic_files( - dump_path, True, alternative_dirs=alternative_dirs_dict) - - # Load all sorters. - sorters = SorterSet() - - json_root = OrderedDict() - json_root['version'] = 1 - json_root['run_id'] = None - for dump in dumps: - if json_root['run_id'] and json_root['run_id'] != dump.run_id: - LOGGER.error('Inconsistent heap profile dumps.') - json_root['run_id'] = '' - break - json_root['run_id'] = dump.run_id - json_root['roots'] = [] - for sorter in sorters: - if sorter.root: - json_root['roots'].append([sorter.world, sorter.name]) - json_root['default_template'] = 'l2' - json_root['templates'] = sorters.templates.as_dict() - - json_root['snapshots'] = [] - - for dump in dumps: - json_root['snapshots'].append( - self._fill_snapshot(dump, bucket_set, sorters)) - - if options.indent: - json.dump(json_root, sys.stdout, indent=2) - else: - json.dump(json_root, sys.stdout) - print '' - - @staticmethod - def _fill_snapshot(dump, bucket_set, sorters): - root = OrderedDict() - root['time'] = dump.time - root['worlds'] = OrderedDict() - root['worlds']['vm'] = CatCommand._fill_world( - dump, bucket_set, sorters, 'vm') - root['worlds']['malloc'] = CatCommand._fill_world( - dump, bucket_set, sorters, 'malloc') - return root - - @staticmethod - def _fill_world(dump, bucket_set, sorters, world): - root = OrderedDict() - - root['name'] = world - if world == 'vm': - root['unit_fields'] = ['size', 'reserved'] - elif world == 'malloc': - root['unit_fields'] = ['size', 'alloc_count', 'free_count'] - - # Make { vm | malloc } units with their sizes. - root['units'] = OrderedDict() - unit_set = UnitSet(world) - if world == 'vm': - for unit in CatCommand._iterate_vm_unit(dump, None, bucket_set): - unit_set.append(unit) - for unit in unit_set: - root['units'][unit.unit_id] = [unit.committed, unit.reserved] - elif world == 'malloc': - for unit in CatCommand._iterate_malloc_unit(dump, bucket_set): - unit_set.append(unit) - for unit in unit_set: - root['units'][unit.unit_id] = [ - unit.size, unit.alloc_count, unit.free_count] - - # Iterate for { vm | malloc } sorters. - root['breakdown'] = OrderedDict() - for sorter in sorters.iter_world(world): - breakdown = OrderedDict() - for unit in unit_set: - found = sorter.find(unit) - if found.name not in breakdown: - category = OrderedDict() - category['name'] = found.name - category['color'] = 'random' - subs = [] - for sub_world, sub_breakdown in found.iter_subs(): - subs.append([sub_world, sub_breakdown]) - if subs: - category['subs'] = subs - if found.hidden: - category['hidden'] = True - category['units'] = [] - breakdown[found.name] = category - breakdown[found.name]['units'].append(unit.unit_id) - root['breakdown'][sorter.name] = breakdown - - return root - - @staticmethod - def _iterate_vm_unit(dump, pfn_dict, bucket_set): - unit_id = 0 - for _, region in dump.iter_map: - unit_id += 1 - if region[0] == 'unhooked': - if pfn_dict and dump.pageframe_length: - for pageframe in region[1]['pageframe']: - yield UnhookedUnit(unit_id, pageframe.size, pageframe.size, - region, pageframe, pfn_dict) - else: - yield UnhookedUnit(unit_id, - int(region[1]['committed']), - int(region[1]['reserved']), - region) - elif region[0] == 'hooked': - if pfn_dict and dump.pageframe_length: - for pageframe in region[1]['pageframe']: - yield MMapUnit(unit_id, - pageframe.size, - pageframe.size, - region, bucket_set, pageframe, pfn_dict) - else: - yield MMapUnit(unit_id, - int(region[1]['committed']), - int(region[1]['reserved']), - region, - bucket_set) - else: - LOGGER.error('Unrecognized mapping status: %s' % region[0]) - - @staticmethod - def _iterate_malloc_unit(dump, bucket_set): - for line in dump.iter_stacktrace: - words = line.split() - bucket = bucket_set.get(int(words[BUCKET_ID])) - if bucket and bucket.allocator_type == 'malloc': - yield MallocUnit(int(words[BUCKET_ID]), - int(words[COMMITTED]), - int(words[ALLOC_COUNT]), - int(words[FREE_COUNT]), - bucket) - elif not bucket: - # 'Not-found' buckets are all assumed as malloc buckets. - yield MallocUnit(int(words[BUCKET_ID]), - int(words[COMMITTED]), - int(words[ALLOC_COUNT]), - int(words[FREE_COUNT]), - None) diff --git a/tools/deep_memory_profiler/subcommands/expand.py b/tools/deep_memory_profiler/subcommands/expand.py deleted file mode 100644 index 4058a00180..0000000000 --- a/tools/deep_memory_profiler/subcommands/expand.py +++ /dev/null @@ -1,104 +0,0 @@ -# Copyright 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import logging -import sys - -from lib.bucket import BUCKET_ID, COMMITTED, ALLOC_COUNT, FREE_COUNT -from lib.policy import PolicySet -from lib.subcommand import SubCommand - - -LOGGER = logging.getLogger('dmprof') - - -class ExpandCommand(SubCommand): - def __init__(self): - super(ExpandCommand, self).__init__( - 'Usage: %prog expand ') - - def do(self, sys_argv): - _, args = self._parse_args(sys_argv, 4) - dump_path = args[1] - target_policy = args[2] - component_name = args[3] - depth = args[4] - (bucket_set, dump) = SubCommand.load_basic_files(dump_path, False) - policy_set = PolicySet.load(SubCommand._parse_policy_list(target_policy)) - - ExpandCommand._output(dump, policy_set[target_policy], bucket_set, - component_name, int(depth), sys.stdout) - return 0 - - @staticmethod - def _output(dump, policy, bucket_set, component_name, depth, out): - """Prints all stacktraces in a given component of given depth. - - Args: - dump: A Dump object. - policy: A Policy object. - bucket_set: A BucketSet object. - component_name: A name of component for filtering. - depth: An integer representing depth to be printed. - out: An IO object to output. - """ - sizes = {} - - ExpandCommand._accumulate( - dump, policy, bucket_set, component_name, depth, sizes) - - sorted_sizes_list = sorted( - sizes.iteritems(), key=(lambda x: x[1]), reverse=True) - total = 0 - # TODO(dmikurube): Better formatting. - for size_pair in sorted_sizes_list: - out.write('%10d %s\n' % (size_pair[1], size_pair[0])) - total += size_pair[1] - LOGGER.info('total: %d\n' % total) - - @staticmethod - def _add_size(precedence, bucket, depth, committed, sizes): - stacktrace_sequence = precedence - for function, sourcefile in zip( - bucket.symbolized_stackfunction[ - 0 : min(len(bucket.symbolized_stackfunction), 1 + depth)], - bucket.symbolized_stacksourcefile[ - 0 : min(len(bucket.symbolized_stacksourcefile), 1 + depth)]): - stacktrace_sequence += '%s(@%s) ' % (function, sourcefile) - if not stacktrace_sequence in sizes: - sizes[stacktrace_sequence] = 0 - sizes[stacktrace_sequence] += committed - - @staticmethod - def _accumulate(dump, policy, bucket_set, component_name, depth, sizes): - rule = policy.find_rule(component_name) - if not rule: - pass - elif rule.allocator_type == 'malloc': - for line in dump.iter_stacktrace: - words = line.split() - bucket = bucket_set.get(int(words[BUCKET_ID])) - if not bucket or bucket.allocator_type == 'malloc': - component_match = policy.find_malloc(bucket) - elif bucket.allocator_type == 'mmap': - continue - else: - assert False - if component_match == component_name: - precedence = '' - precedence += '(alloc=%d) ' % int(words[ALLOC_COUNT]) - precedence += '(free=%d) ' % int(words[FREE_COUNT]) - if bucket.typeinfo: - precedence += '(type=%s) ' % bucket.symbolized_typeinfo - precedence += '(type.name=%s) ' % bucket.typeinfo_name - ExpandCommand._add_size(precedence, bucket, depth, - int(words[COMMITTED]), sizes) - elif rule.allocator_type == 'mmap': - for _, region in dump.iter_map: - if region[0] != 'hooked': - continue - component_match, bucket = policy.find_mmap(region, bucket_set) - if component_match == component_name: - ExpandCommand._add_size('', bucket, depth, - region[1]['committed'], sizes) diff --git a/tools/deep_memory_profiler/subcommands/map.py b/tools/deep_memory_profiler/subcommands/map.py deleted file mode 100644 index 2237d6f200..0000000000 --- a/tools/deep_memory_profiler/subcommands/map.py +++ /dev/null @@ -1,102 +0,0 @@ -# Copyright 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import copy -import logging -import sys - -from lib.range_dict import ExclusiveRangeDict -from lib.policy import PolicySet -from lib.subcommand import SubCommand - - -LOGGER = logging.getLogger('dmprof') - - -class MapCommand(SubCommand): - def __init__(self): - super(MapCommand, self).__init__('Usage: %prog map ') - - def do(self, sys_argv, out=sys.stdout): - _, args = self._parse_args(sys_argv, 2) - dump_path = args[1] - target_policy = args[2] - (bucket_set, dumps) = SubCommand.load_basic_files(dump_path, True) - policy_set = PolicySet.load(SubCommand._parse_policy_list(target_policy)) - - MapCommand._output(dumps, bucket_set, policy_set[target_policy], out) - return 0 - - @staticmethod - def _output(dumps, bucket_set, policy, out): - """Prints all stacktraces in a given component of given depth. - - Args: - dumps: A list of Dump objects. - bucket_set: A BucketSet object. - policy: A Policy object. - out: An IO object to output. - """ - max_dump_count = 0 - range_dict = ExclusiveRangeDict(ListAttribute) - for dump in dumps: - max_dump_count = max(max_dump_count, dump.count) - for key, value in dump.iter_map: - for begin, end, attr in range_dict.iter_range(key[0], key[1]): - attr[dump.count] = value - - max_dump_count_digit = len(str(max_dump_count)) - for begin, end, attr in range_dict.iter_range(): - out.write('%x-%x\n' % (begin, end)) - if len(attr) < max_dump_count: - attr[max_dump_count] = None - for index, value in enumerate(attr[1:]): - out.write(' #%0*d: ' % (max_dump_count_digit, index + 1)) - if not value: - out.write('None\n') - elif value[0] == 'hooked': - component_match, _ = policy.find_mmap(value, bucket_set) - out.write('%s @ %d\n' % (component_match, value[1]['bucket_id'])) - else: - component_match = policy.find_unhooked(value) - region_info = value[1] - size = region_info['committed'] - out.write('%s [%d bytes] %s%s%s%s %s\n' % ( - component_match, size, value[1]['vma']['readable'], - value[1]['vma']['writable'], value[1]['vma']['executable'], - value[1]['vma']['private'], value[1]['vma']['name'])) - - -class ListAttribute(ExclusiveRangeDict.RangeAttribute): - """Represents a list for an attribute in range_dict.ExclusiveRangeDict.""" - def __init__(self): - super(ListAttribute, self).__init__() - self._list = [] - - def __str__(self): - return str(self._list) - - def __repr__(self): - return 'ListAttribute' + str(self._list) - - def __len__(self): - return len(self._list) - - def __iter__(self): - for x in self._list: - yield x - - def __getitem__(self, index): - return self._list[index] - - def __setitem__(self, index, value): - if index >= len(self._list): - self._list.extend([None] * (index + 1 - len(self._list))) - self._list[index] = value - - def copy(self): - new_list = ListAttribute() - for index, item in enumerate(self._list): - new_list[index] = copy.deepcopy(item) - return new_list diff --git a/tools/deep_memory_profiler/subcommands/policies.py b/tools/deep_memory_profiler/subcommands/policies.py deleted file mode 100644 index 182959b10f..0000000000 --- a/tools/deep_memory_profiler/subcommands/policies.py +++ /dev/null @@ -1,375 +0,0 @@ -# Copyright 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import datetime -import json -import logging -import sys - -from lib.bucket import BUCKET_ID, COMMITTED -from lib.pageframe import PFNCounts -from lib.policy import PolicySet -from lib.subcommand import SubCommand - - -LOGGER = logging.getLogger('dmprof') - - -class PolicyCommands(SubCommand): - def __init__(self, command): - super(PolicyCommands, self).__init__( - 'Usage: %%prog %s [-p POLICY] [shared-first-dumps...]' % - command) - self._parser.add_option('-p', '--policy', type='string', dest='policy', - help='profile with POLICY', metavar='POLICY') - self._parser.add_option('--alternative-dirs', dest='alternative_dirs', - metavar='/path/on/target@/path/on/host[:...]', - help='Read files in /path/on/host/ instead of ' - 'files in /path/on/target/.') - - def _set_up(self, sys_argv): - options, args = self._parse_args(sys_argv, 1) - dump_path = args[1] - shared_first_dump_paths = args[2:] - alternative_dirs_dict = {} - if options.alternative_dirs: - for alternative_dir_pair in options.alternative_dirs.split(':'): - target_path, host_path = alternative_dir_pair.split('@', 1) - alternative_dirs_dict[target_path] = host_path - (bucket_set, dumps) = SubCommand.load_basic_files( - dump_path, True, alternative_dirs=alternative_dirs_dict) - - pfn_counts_dict = {} - for shared_first_dump_path in shared_first_dump_paths: - shared_dumps = SubCommand._find_all_dumps(shared_first_dump_path) - for shared_dump in shared_dumps: - pfn_counts = PFNCounts.load(shared_dump) - if pfn_counts.pid not in pfn_counts_dict: - pfn_counts_dict[pfn_counts.pid] = [] - pfn_counts_dict[pfn_counts.pid].append(pfn_counts) - - policy_set = PolicySet.load(SubCommand._parse_policy_list(options.policy)) - return policy_set, dumps, pfn_counts_dict, bucket_set - - @staticmethod - def _apply_policy(dump, pfn_counts_dict, policy, bucket_set, first_dump_time): - """Aggregates the total memory size of each component. - - Iterate through all stacktraces and attribute them to one of the components - based on the policy. It is important to apply policy in right order. - - Args: - dump: A Dump object. - pfn_counts_dict: A dict mapping a pid to a list of PFNCounts. - policy: A Policy object. - bucket_set: A BucketSet object. - first_dump_time: An integer representing time when the first dump is - dumped. - - Returns: - A dict mapping components and their corresponding sizes. - """ - LOGGER.info(' %s' % dump.path) - all_pfn_dict = {} - if pfn_counts_dict: - LOGGER.info(' shared with...') - for pid, pfnset_list in pfn_counts_dict.iteritems(): - closest_pfnset_index = None - closest_pfnset_difference = 1024.0 - for index, pfnset in enumerate(pfnset_list): - time_difference = pfnset.time - dump.time - if time_difference >= 3.0: - break - elif ((time_difference < 0.0 and pfnset.reason != 'Exiting') or - (0.0 <= time_difference and time_difference < 3.0)): - closest_pfnset_index = index - closest_pfnset_difference = time_difference - elif time_difference < 0.0 and pfnset.reason == 'Exiting': - closest_pfnset_index = None - break - if closest_pfnset_index: - for pfn, count in pfnset_list[closest_pfnset_index].iter_pfn: - all_pfn_dict[pfn] = all_pfn_dict.get(pfn, 0) + count - LOGGER.info(' %s (time difference = %f)' % - (pfnset_list[closest_pfnset_index].path, - closest_pfnset_difference)) - else: - LOGGER.info(' (no match with pid:%d)' % pid) - - sizes = dict((c, 0) for c in policy.components) - - PolicyCommands._accumulate_malloc(dump, policy, bucket_set, sizes) - verify_global_stats = PolicyCommands._accumulate_maps( - dump, all_pfn_dict, policy, bucket_set, sizes) - - # TODO(dmikurube): Remove the verifying code when GLOBAL_STATS is removed. - # http://crbug.com/245603. - for verify_key, verify_value in verify_global_stats.iteritems(): - dump_value = dump.global_stat('%s_committed' % verify_key) - if dump_value != verify_value: - LOGGER.warn('%25s: %12d != %d (%d)' % ( - verify_key, dump_value, verify_value, dump_value - verify_value)) - - sizes['mmap-no-log'] = ( - dump.global_stat('profiled-mmap_committed') - - sizes['mmap-total-log']) - sizes['mmap-total-record'] = dump.global_stat('profiled-mmap_committed') - sizes['mmap-total-record-vm'] = dump.global_stat('profiled-mmap_virtual') - - sizes['tc-no-log'] = ( - dump.global_stat('profiled-malloc_committed') - - sizes['tc-total-log']) - sizes['tc-total-record'] = dump.global_stat('profiled-malloc_committed') - sizes['tc-unused'] = ( - sizes['mmap-tcmalloc'] - - dump.global_stat('profiled-malloc_committed')) - if sizes['tc-unused'] < 0: - LOGGER.warn(' Assuming tc-unused=0 as it is negative: %d (bytes)' % - sizes['tc-unused']) - sizes['tc-unused'] = 0 - sizes['tc-total'] = sizes['mmap-tcmalloc'] - - # TODO(dmikurube): global_stat will be deprecated. - # See http://crbug.com/245603. - for key, value in { - 'total': 'total_committed', - 'filemapped': 'file_committed', - 'absent': 'absent_committed', - 'file-exec': 'file-exec_committed', - 'file-nonexec': 'file-nonexec_committed', - 'anonymous': 'anonymous_committed', - 'stack': 'stack_committed', - 'other': 'other_committed', - 'unhooked-absent': 'nonprofiled-absent_committed', - 'total-vm': 'total_virtual', - 'filemapped-vm': 'file_virtual', - 'anonymous-vm': 'anonymous_virtual', - 'other-vm': 'other_virtual' }.iteritems(): - if key in sizes: - sizes[key] = dump.global_stat(value) - - if 'mustbezero' in sizes: - removed_list = ( - 'profiled-mmap_committed', - 'nonprofiled-absent_committed', - 'nonprofiled-anonymous_committed', - 'nonprofiled-file-exec_committed', - 'nonprofiled-file-nonexec_committed', - 'nonprofiled-stack_committed', - 'nonprofiled-other_committed') - sizes['mustbezero'] = ( - dump.global_stat('total_committed') - - sum(dump.global_stat(removed) for removed in removed_list)) - if 'total-exclude-profiler' in sizes: - sizes['total-exclude-profiler'] = ( - dump.global_stat('total_committed') - - (sizes['mmap-profiler'] + sizes['mmap-type-profiler'])) - if 'hour' in sizes: - sizes['hour'] = (dump.time - first_dump_time) / 60.0 / 60.0 - if 'minute' in sizes: - sizes['minute'] = (dump.time - first_dump_time) / 60.0 - if 'second' in sizes: - sizes['second'] = dump.time - first_dump_time - - return sizes - - @staticmethod - def _accumulate_malloc(dump, policy, bucket_set, sizes): - for line in dump.iter_stacktrace: - words = line.split() - bucket = bucket_set.get(int(words[BUCKET_ID])) - if not bucket or bucket.allocator_type == 'malloc': - component_match = policy.find_malloc(bucket) - elif bucket.allocator_type == 'mmap': - continue - else: - assert False - sizes[component_match] += int(words[COMMITTED]) - - assert not component_match.startswith('mmap-') - if component_match.startswith('tc-'): - sizes['tc-total-log'] += int(words[COMMITTED]) - else: - sizes['other-total-log'] += int(words[COMMITTED]) - - @staticmethod - def _accumulate_maps(dump, pfn_dict, policy, bucket_set, sizes): - # TODO(dmikurube): Remove the dict when GLOBAL_STATS is removed. - # http://crbug.com/245603. - global_stats = { - 'total': 0, - 'file-exec': 0, - 'file-nonexec': 0, - 'anonymous': 0, - 'stack': 0, - 'other': 0, - 'nonprofiled-file-exec': 0, - 'nonprofiled-file-nonexec': 0, - 'nonprofiled-anonymous': 0, - 'nonprofiled-stack': 0, - 'nonprofiled-other': 0, - 'profiled-mmap': 0, - } - - for key, value in dump.iter_map: - # TODO(dmikurube): Remove the subtotal code when GLOBAL_STATS is removed. - # It's temporary verification code for transition described in - # http://crbug.com/245603. - committed = 0 - if 'committed' in value[1]: - committed = value[1]['committed'] - global_stats['total'] += committed - key = 'other' - name = value[1]['vma']['name'] - if name.startswith('/'): - if value[1]['vma']['executable'] == 'x': - key = 'file-exec' - else: - key = 'file-nonexec' - elif name == '[stack]': - key = 'stack' - elif name == '': - key = 'anonymous' - global_stats[key] += committed - if value[0] == 'unhooked': - global_stats['nonprofiled-' + key] += committed - if value[0] == 'hooked': - global_stats['profiled-mmap'] += committed - - if value[0] == 'unhooked': - if pfn_dict and dump.pageframe_length: - for pageframe in value[1]['pageframe']: - component_match = policy.find_unhooked(value, pageframe, pfn_dict) - sizes[component_match] += pageframe.size - else: - component_match = policy.find_unhooked(value) - sizes[component_match] += int(value[1]['committed']) - elif value[0] == 'hooked': - if pfn_dict and dump.pageframe_length: - for pageframe in value[1]['pageframe']: - component_match, _ = policy.find_mmap( - value, bucket_set, pageframe, pfn_dict) - sizes[component_match] += pageframe.size - assert not component_match.startswith('tc-') - if component_match.startswith('mmap-'): - sizes['mmap-total-log'] += pageframe.size - else: - sizes['other-total-log'] += pageframe.size - else: - component_match, _ = policy.find_mmap(value, bucket_set) - sizes[component_match] += int(value[1]['committed']) - if component_match.startswith('mmap-'): - sizes['mmap-total-log'] += int(value[1]['committed']) - else: - sizes['other-total-log'] += int(value[1]['committed']) - else: - LOGGER.error('Unrecognized mapping status: %s' % value[0]) - - return global_stats - - -class CSVCommand(PolicyCommands): - def __init__(self): - super(CSVCommand, self).__init__('csv') - - def do(self, sys_argv): - policy_set, dumps, pfn_counts_dict, bucket_set = self._set_up(sys_argv) - return CSVCommand._output( - policy_set, dumps, pfn_counts_dict, bucket_set, sys.stdout) - - @staticmethod - def _output(policy_set, dumps, pfn_counts_dict, bucket_set, out): - max_components = 0 - for label in policy_set: - max_components = max(max_components, len(policy_set[label].components)) - - for label in sorted(policy_set): - components = policy_set[label].components - if len(policy_set) > 1: - out.write('%s%s\n' % (label, ',' * (max_components - 1))) - out.write('%s%s\n' % ( - ','.join(components), ',' * (max_components - len(components)))) - - LOGGER.info('Applying a policy %s to...' % label) - for dump in dumps: - component_sizes = PolicyCommands._apply_policy( - dump, pfn_counts_dict, policy_set[label], bucket_set, dumps[0].time) - s = [] - for c in components: - if c in ('hour', 'minute', 'second'): - s.append('%05.5f' % (component_sizes[c])) - else: - s.append('%05.5f' % (component_sizes[c] / 1024.0 / 1024.0)) - out.write('%s%s\n' % ( - ','.join(s), ',' * (max_components - len(components)))) - - bucket_set.clear_component_cache() - - return 0 - - -class JSONCommand(PolicyCommands): - def __init__(self): - super(JSONCommand, self).__init__('json') - - def do(self, sys_argv): - policy_set, dumps, pfn_counts_dict, bucket_set = self._set_up(sys_argv) - return JSONCommand._output( - policy_set, dumps, pfn_counts_dict, bucket_set, sys.stdout) - - @staticmethod - def _output(policy_set, dumps, pfn_counts_dict, bucket_set, out): - json_base = { - 'version': 'JSON_DEEP_2', - 'policies': {}, - } - - for label in sorted(policy_set): - json_base['policies'][label] = { - 'legends': policy_set[label].components, - 'snapshots': [], - } - - LOGGER.info('Applying a policy %s to...' % label) - for dump in dumps: - component_sizes = PolicyCommands._apply_policy( - dump, pfn_counts_dict, policy_set[label], bucket_set, dumps[0].time) - component_sizes['dump_path'] = dump.path - component_sizes['dump_time'] = datetime.datetime.fromtimestamp( - dump.time).strftime('%Y-%m-%d %H:%M:%S') - json_base['policies'][label]['snapshots'].append(component_sizes) - - bucket_set.clear_component_cache() - - json.dump(json_base, out, indent=2, sort_keys=True) - - return 0 - - -class ListCommand(PolicyCommands): - def __init__(self): - super(ListCommand, self).__init__('list') - - def do(self, sys_argv): - policy_set, dumps, pfn_counts_dict, bucket_set = self._set_up(sys_argv) - return ListCommand._output( - policy_set, dumps, pfn_counts_dict, bucket_set, sys.stdout) - - @staticmethod - def _output(policy_set, dumps, pfn_counts_dict, bucket_set, out): - for label in sorted(policy_set): - LOGGER.info('Applying a policy %s to...' % label) - for dump in dumps: - component_sizes = PolicyCommands._apply_policy( - dump, pfn_counts_dict, policy_set[label], bucket_set, dump.time) - out.write('%s for %s:\n' % (label, dump.path)) - for c in policy_set[label].components: - if c in ['hour', 'minute', 'second']: - out.write('%40s %12.3f\n' % (c, component_sizes[c])) - else: - out.write('%40s %12d\n' % (c, component_sizes[c])) - - bucket_set.clear_component_cache() - - return 0 diff --git a/tools/deep_memory_profiler/subcommands/pprof.py b/tools/deep_memory_profiler/subcommands/pprof.py deleted file mode 100644 index 506d811711..0000000000 --- a/tools/deep_memory_profiler/subcommands/pprof.py +++ /dev/null @@ -1,161 +0,0 @@ -# Copyright 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import logging -import sys - -from lib.bucket import BUCKET_ID, COMMITTED, ALLOC_COUNT, FREE_COUNT -from lib.policy import PolicySet -from lib.subcommand import SubCommand - - -LOGGER = logging.getLogger('dmprof') - - -class PProfCommand(SubCommand): - def __init__(self): - super(PProfCommand, self).__init__( - 'Usage: %prog pprof [-c COMPONENT] ') - self._parser.add_option('-c', '--component', type='string', - dest='component', - help='restrict to COMPONENT', metavar='COMPONENT') - - def do(self, sys_argv): - options, args = self._parse_args(sys_argv, 2) - - dump_path = args[1] - target_policy = args[2] - component = options.component - - (bucket_set, dump) = SubCommand.load_basic_files(dump_path, False) - policy_set = PolicySet.load(SubCommand._parse_policy_list(target_policy)) - - with open(SubCommand._find_prefix(dump_path) + '.maps', 'r') as maps_f: - maps_lines = maps_f.readlines() - PProfCommand._output( - dump, policy_set[target_policy], bucket_set, maps_lines, component, - sys.stdout) - - return 0 - - @staticmethod - def _output(dump, policy, bucket_set, maps_lines, component_name, out): - """Converts the heap profile dump so it can be processed by pprof. - - Args: - dump: A Dump object. - policy: A Policy object. - bucket_set: A BucketSet object. - maps_lines: A list of strings containing /proc/.../maps. - component_name: A name of component for filtering. - out: An IO object to output. - """ - out.write('heap profile: ') - com_committed, com_allocs = PProfCommand._accumulate( - dump, policy, bucket_set, component_name) - - out.write('%6d: %8s [%6d: %8s] @ heapprofile\n' % ( - com_allocs, com_committed, com_allocs, com_committed)) - - PProfCommand._output_stacktrace_lines( - dump, policy, bucket_set, component_name, out) - - out.write('MAPPED_LIBRARIES:\n') - for line in maps_lines: - out.write(line) - - @staticmethod - def _accumulate(dump, policy, bucket_set, component_name): - """Accumulates size of committed chunks and the number of allocated chunks. - - Args: - dump: A Dump object. - policy: A Policy object. - bucket_set: A BucketSet object. - component_name: A name of component for filtering. - - Returns: - Two integers which are the accumulated size of committed regions and the - number of allocated chunks, respectively. - """ - com_committed = 0 - com_allocs = 0 - - for _, region in dump.iter_map: - if region[0] != 'hooked': - continue - component_match, bucket = policy.find_mmap(region, bucket_set) - - if (component_name and component_name != component_match) or ( - region[1]['committed'] == 0): - continue - - com_committed += region[1]['committed'] - com_allocs += 1 - - for line in dump.iter_stacktrace: - words = line.split() - bucket = bucket_set.get(int(words[BUCKET_ID])) - if not bucket or bucket.allocator_type == 'malloc': - component_match = policy.find_malloc(bucket) - elif bucket.allocator_type == 'mmap': - continue - else: - assert False - if (not bucket or - (component_name and component_name != component_match)): - continue - - com_committed += int(words[COMMITTED]) - com_allocs += int(words[ALLOC_COUNT]) - int(words[FREE_COUNT]) - - return com_committed, com_allocs - - @staticmethod - def _output_stacktrace_lines(dump, policy, bucket_set, component_name, out): - """Prints information of stacktrace lines for pprof. - - Args: - dump: A Dump object. - policy: A Policy object. - bucket_set: A BucketSet object. - component_name: A name of component for filtering. - out: An IO object to output. - """ - for _, region in dump.iter_map: - if region[0] != 'hooked': - continue - component_match, bucket = policy.find_mmap(region, bucket_set) - - if (component_name and component_name != component_match) or ( - region[1]['committed'] == 0): - continue - - out.write(' 1: %8s [ 1: %8s] @' % ( - region[1]['committed'], region[1]['committed'])) - for address in bucket.stacktrace: - out.write(' 0x%016x' % address) - out.write('\n') - - for line in dump.iter_stacktrace: - words = line.split() - bucket = bucket_set.get(int(words[BUCKET_ID])) - if not bucket or bucket.allocator_type == 'malloc': - component_match = policy.find_malloc(bucket) - elif bucket.allocator_type == 'mmap': - continue - else: - assert False - if (not bucket or - (component_name and component_name != component_match)): - continue - - out.write('%6d: %8s [%6d: %8s] @' % ( - int(words[ALLOC_COUNT]) - int(words[FREE_COUNT]), - words[COMMITTED], - int(words[ALLOC_COUNT]) - int(words[FREE_COUNT]), - words[COMMITTED])) - for address in bucket.stacktrace: - out.write(' 0x%016x' % address) - out.write('\n') diff --git a/tools/deep_memory_profiler/subcommands/stacktrace.py b/tools/deep_memory_profiler/subcommands/stacktrace.py deleted file mode 100644 index 72b850981a..0000000000 --- a/tools/deep_memory_profiler/subcommands/stacktrace.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import sys - -from lib.bucket import BUCKET_ID -from lib.subcommand import SubCommand - - -class StacktraceCommand(SubCommand): - def __init__(self): - super(StacktraceCommand, self).__init__( - 'Usage: %prog stacktrace ') - - def do(self, sys_argv): - _, args = self._parse_args(sys_argv, 1) - dump_path = args[1] - (bucket_set, dump) = SubCommand.load_basic_files(dump_path, False) - - StacktraceCommand._output(dump, bucket_set, sys.stdout) - return 0 - - @staticmethod - def _output(dump, bucket_set, out): - """Outputs a given stacktrace. - - Args: - bucket_set: A BucketSet object. - out: A file object to output. - """ - for line in dump.iter_stacktrace: - words = line.split() - bucket = bucket_set.get(int(words[BUCKET_ID])) - if not bucket: - continue - for i in range(0, BUCKET_ID - 1): - out.write(words[i] + ' ') - for frame in bucket.symbolized_stackfunction: - out.write(frame + ' ') - out.write('\n') diff --git a/tools/deep_memory_profiler/subcommands/upload.py b/tools/deep_memory_profiler/subcommands/upload.py deleted file mode 100644 index de34a8a715..0000000000 --- a/tools/deep_memory_profiler/subcommands/upload.py +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import logging -import os -import subprocess -import tempfile -import zipfile - -from lib.subcommand import SubCommand -from lib.symbol import SymbolDataSources - - -LOGGER = logging.getLogger('dmprof') - - -class UploadCommand(SubCommand): - def __init__(self): - super(UploadCommand, self).__init__( - 'Usage: %prog upload [--gsutil path/to/gsutil] ' - ' ') - self._parser.add_option('--gsutil', default='gsutil', - help='path to GSUTIL', metavar='GSUTIL') - - def do(self, sys_argv): - options, args = self._parse_args(sys_argv, 2) - dump_path = args[1] - gs_path = args[2] - - dump_files = SubCommand._find_all_dumps(dump_path) - bucket_files = SubCommand._find_all_buckets(dump_path) - prefix = SubCommand._find_prefix(dump_path) - symbol_data_sources = SymbolDataSources(prefix) - symbol_data_sources.prepare() - symbol_path = symbol_data_sources.path() - - handle_zip, filename_zip = tempfile.mkstemp('.zip', 'dmprof') - os.close(handle_zip) - - try: - file_zip = zipfile.ZipFile(filename_zip, 'w', zipfile.ZIP_DEFLATED) - for filename in dump_files: - file_zip.write(filename, os.path.basename(os.path.abspath(filename))) - for filename in bucket_files: - file_zip.write(filename, os.path.basename(os.path.abspath(filename))) - - symbol_basename = os.path.basename(os.path.abspath(symbol_path)) - for filename in os.listdir(symbol_path): - if not filename.startswith('.'): - file_zip.write(os.path.join(symbol_path, filename), - os.path.join(symbol_basename, os.path.basename( - os.path.abspath(filename)))) - file_zip.close() - - returncode = UploadCommand._run_gsutil( - options.gsutil, 'cp', '-a', 'public-read', filename_zip, gs_path) - finally: - os.remove(filename_zip) - - return returncode - - @staticmethod - def _run_gsutil(gsutil, *args): - """Run gsutil as a subprocess. - - Args: - *args: Arguments to pass to gsutil. The first argument should be an - operation such as ls, cp or cat. - Returns: - The return code from the process. - """ - command = [gsutil] + list(args) - LOGGER.info("Running: %s", command) - - try: - return subprocess.call(command) - except OSError, e: - LOGGER.error('Error to run gsutil: %s', e) diff --git a/tools/deep_memory_profiler/templates.json b/tools/deep_memory_profiler/templates.json deleted file mode 100644 index b4d9a4eb60..0000000000 --- a/tools/deep_memory_profiler/templates.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "l2": ["vm", "map", { - "mmap-tcmalloc": ["malloc", "component", {}] - }], - "details": ["vm", "map", { - "mmap-tcmalloc": ["malloc", "component", { - "webkit": ["malloc", "webkit-details", {}], - "skia": ["malloc", "skia-details", {}] - }], - "mmap-v8-heap": ["javascript", "type", {}] - }] -} diff --git a/tools/deep_memory_profiler/tests/data/.gitignore b/tools/deep_memory_profiler/tests/data/.gitignore deleted file mode 100644 index ca08f425bd..0000000000 --- a/tools/deep_memory_profiler/tests/data/.gitignore +++ /dev/null @@ -1 +0,0 @@ -heap.01234.cache.* diff --git a/tools/deep_memory_profiler/tests/data/heap.01234.0001.buckets b/tools/deep_memory_profiler/tests/data/heap.01234.0001.buckets deleted file mode 100644 index c7de4bdbcf..0000000000 --- a/tools/deep_memory_profiler/tests/data/heap.01234.0001.buckets +++ /dev/null @@ -1,5 +0,0 @@ -4 mmap t0x0 nno_typeinfo 0x7f6306ff0571 0x7f630c5d52da 0x7f6306fdad6c 0x7f6306ffc365 0x7f6306ffc4cb 0x7f6306fdbc77 0x7f6306fdadd0 0x7f6306fde66e 0x7f6306fe2294 0x7f630c5d56a6 0x7f630b0e1c3c 0x7f6308e3d455 0x7f6308e3d311 0x7f6308e3d29d 0x7f6308e3cff7 0x7f6308e3cb70 0x7f6308e3aa88 0x7f6308e3a30d 0x7f6308e3a9ee 0x7f630985c298 0x7f63087cd903 0x7f63087c858d 0x7f63087c3f15 0x7f6306dbf057 0x7f6306deee40 0x7f6309c5bc11 0x7f6309c5dcd3 0x7f6309c53644 0x7f6309c563e7 0x7f6309c55dfb 0x7f6309c53271 0x7f6309c5386f -2 malloc t0x7f630ff7e718 nN7WebCore8RuleDataE 0x7f630b0e1c3c 0x7f6308a255e2 0x7f6308a25341 0x7f6308a24f75 0x7f6308a24592 0x7f6308a244b9 0x7f6308a24475 0x7f63089c6204 0x7f63089c660a 0x7f63084a5961 0x7f6308d5a7fc 0x7f6308dcdf99 0x7f630b88a4e8 0x7f630b88a3fe 0x7f6308d3dd77 0x7f6307514142 0x7f63075169f1 0x7f63074d019d 0x7f63074ceafe 0x7f63074ca99b 0x7f63074c9d0b 0x7f63074a3331 0x7f63074a1927 0x7f63074a10c5 0x7f63074a3ae3 0x7f6308d4df27 0x7f63086cdb28 0x7f63086b2969 0x7f6306db7a37 0x7f6306e48c5e 0x7f63086b2a50 0x7f63086b2f7b -1 malloc t0x0 nno_typeinfo 0x7f6307289164 0x7f6307288f89 0x7f6307288f10 0x7f6307288a98 0x7f63072887a5 0x7f63072884c0 0x7f6307286613 0x7f6307284cbc 0x7f6307285022 0x7f63072358a4 0x7f6307235845 0x7f63091b2836 0x7f63091b1d98 0x7f63090935bb 0x7f63069a33e6 0x7f63069a8eda 0x7f63069a8e31 0x7f63069a8dcc 0x7f6305c6eade 0x7f630720564e 0x7f630720592b 0x7f6307205ad5 0x7f630720f418 0x7f63072050c6 0x7f6307204f75 0x7f6307236682 0x7f6307204811 0x7f6309cb5190 0x7f6309c39b8a 0x7f6309c39ea4 0x7f6309c3ae5d 0x7f6309c392d4 -3 malloc t0x7f630feeb3a0 nN7WebCore17CSSPrimitiveValueE 0x7f630b0e1c3c 0x7f6306e67075 0x7f630844b318 0x7f630846fc1e 0x7f63083eab7a 0x7f63098737df 0x7f63083e71c7 0x7f630850ed0c 0x7f630850ec92 0x7f63089c63bf 0x7f63089c650b 0x7f63089c5e1d 0x7f63089c5bf6 0x7f63084a4e42 0x7f6308d5b114 0x7f6306e2423b 0x7f6308dcad80 0x7f6308e2e1e4 0x7f6308dca1ed 0x7f6308dca245 0x7f63075141d7 0x7f6307513ff1 0x7f63075147fd 0x7f63074d4158 0x7f63074cec74 0x7f63074ca9b7 0x7f63074c9d0b 0x7f63074a3331 0x7f63074a1927 0x7f63074a10c5 0x7f63074a0f3d 0x7f63074a3c73 -5 malloc t0x0 nno_typeinfo 0x7f62fd455a89 0x7f62fd4575e3 0x7fff9439ce50 diff --git a/tools/deep_memory_profiler/tests/data/heap.01234.0001.heap b/tools/deep_memory_profiler/tests/data/heap.01234.0001.heap deleted file mode 100644 index 1c1d28a5ce..0000000000 --- a/tools/deep_memory_profiler/tests/data/heap.01234.0001.heap +++ /dev/null @@ -1,25 +0,0 @@ -heap profile: DUMP_DEEP_6 -GLOBAL_STATS: - virtual committed - total 1022775296 64831488 - file-exec 207237120 32600064 - file-nonexec 194805760 10862592 - anonymous 620589056 21233664 - stack 139264 131072 - other 4096 4096 - nonprofiled-total 414846427 47091700 - nonprofiled-absent 0 0 - nonprofiled-anonymous 23650304 3751936 - nonprofiled-file-exec 207237120 32600064 - nonprofiled-file-nonexec 183815643 10604532 - nonprofiled-stack 139264 131072 - nonprofiled-other 4096 4096 - profiled-mmap 607928869 17727500 - profiled-malloc 1935377 1873937 -STACKTRACES: - virtual committed - 65536 65536 1 0 @ 4 - 32 32 1 0 @ 1 - 48 48 1 0 @ 3 - 8288 8288 109 0 @ 2 - 72 72 1 0 @ 5 diff --git a/tools/deep_memory_profiler/tests/data/heap.01234.0002.buckets b/tools/deep_memory_profiler/tests/data/heap.01234.0002.buckets deleted file mode 100644 index 9a4c71d777..0000000000 --- a/tools/deep_memory_profiler/tests/data/heap.01234.0002.buckets +++ /dev/null @@ -1,2 +0,0 @@ -6 malloc t0x0 nno_typeinfo 0x7f630b0e1c3c 0x7f630b0e1ba5 0x7f6308e1d21b 0x7f6308e1d157 0x7f6308e1e2e0 0x7f6308e1dff9 0x7f6308e1db4c 0x7f6308e17cd0 0x7f6308e13370 0x7f6308de1b18 0x7f6308e12f9f 0x7f6308e12f2f 0x7f630978f482 0x7f630978e785 0x12e93499fa0f 0x12e93499f038 0x12e93499ee28 0x12e934925d44 0x12e934907177 0x7f630a88841d 0x7f630a887f04 0x7f630a7ea908 0x7f6308342a17 0x7f63083427a6 0x7f6308390b75 0x7f630897225b 0x7f6308971f0f 0x7f6308de27da 0x7f6308de2379 0x7f6308e13d89 0x7f6308ea5011 0x7f6308ea52ec -7 mmap t0x0 nno_typeinfo 0x7f6306ff0571 0x7f630c5d52da 0x7f630763cbac 0x7f630763cae7 0x7f630763c51a 0x7f630763c34b 0x7f630b91ba67 0x7f63072f33d4 0x7f630aa68d19 0x7f630aa61012 0x7f630aa581e2 0x7f630aa579d9 0x7f630aa5745a 0x7f630aa56fc4 0x7f630aa56ddf 0x7f630aa56d45 0x7f630aa5625b 0x7f630aa55f0d 0x7f630aa55156 0x7f630aa5558f 0x7f630aa584cc 0x7f630aa579d9 0x7f630aa5745a 0x7f630aa56fc4 0x7f630aa56ddf 0x7f630aa56d45 0x7f630aa5625b 0x7f630aa55f0d 0x7f630aa55156 0x7f630aa5488c 0x7f630aa4d56d 0x7f630aa4e0e4 diff --git a/tools/deep_memory_profiler/tests/data/heap.01234.0002.heap b/tools/deep_memory_profiler/tests/data/heap.01234.0002.heap deleted file mode 100644 index 800913983b..0000000000 --- a/tools/deep_memory_profiler/tests/data/heap.01234.0002.heap +++ /dev/null @@ -1,28 +0,0 @@ -heap profile: DUMP_DEEP_6 -GLOBAL_STATS: - virtual committed - total 1067888640 101031936 - file-exec 207237120 35569664 - file-nonexec 192380928 8441856 - anonymous 666476544 55226368 - stack 1789952 1789952 - other 4096 4096 - nonprofiled-total 416234971 50352116 - nonprofiled-absent 0 0 - nonprofiled-anonymous 25812992 4808704 - nonprofiled-file-exec 207237120 35569664 - nonprofiled-file-nonexec 181390811 8179700 - nonprofiled-stack 1789952 1789952 - nonprofiled-other 4096 4096 - profiled-mmap 651653669 50679820 - profiled-malloc 3054552 3025880 - unhooked-arena 64128 64128 -STACKTRACES: - virtual committed - 65536 65536 1 0 @ 4 - 32 32 1 0 @ 1 - 48 48 1 0 @ 3 - 8288 8288 109 0 @ 2 - 72 72 1 0 @ 5 - 32768 32768 7 6 @ 7 - 29 29 1 0 @ 6 diff --git a/tools/deep_memory_profiler/tests/data/heap.01234.maps b/tools/deep_memory_profiler/tests/data/heap.01234.maps deleted file mode 100644 index a2555247d1..0000000000 --- a/tools/deep_memory_profiler/tests/data/heap.01234.maps +++ /dev/null @@ -1,410 +0,0 @@ -114147900000-114147935000 rw-p 00000000 00:00 0 -12e93464c000-12e934700000 ---p 00000000 00:00 0 -12e934700000-12e934705000 rw-p 00000000 00:00 0 -12e934705000-12e934706000 ---p 00000000 00:00 0 -12e934706000-12e934707000 rwxp 00000000 00:00 0 -12e934707000-12e934800000 ---p 00000000 00:00 0 -12e934800000-12e934805000 rw-p 00000000 00:00 0 -12e934805000-12e934806000 ---p 00000000 00:00 0 -12e934806000-12e934807000 rwxp 00000000 00:00 0 -12e934807000-12e934900000 ---p 00000000 00:00 0 -12e934900000-12e934905000 rw-p 00000000 00:00 0 -12e934905000-12e934906000 ---p 00000000 00:00 0 -12e934906000-12e9349ff000 rwxp 00000000 00:00 0 -12e9349ff000-12e95464c000 ---p 00000000 00:00 0 -16b0892d7000-16b0892d8000 r-xp 00000000 00:00 0 -19fc4e858000-19fc4e859000 r-xp 00000000 00:00 0 -1ae6500da000-1ae6503ea000 rw-p 00000000 00:00 0 -1c8ad47d9000-1c8ad47da000 r-xp 00000000 00:00 0 -1cca7ce6a000-1cca7ce80000 ---p 00000000 00:00 0 -1cca7ce80000-1cca7cea0000 rw-p 00000000 00:00 0 -1cca7cea0000-1cca7ceca000 ---p 00000000 00:00 0 -2195f26d4000-2195f26d5000 r-xp 00000000 00:00 0 -21c091300000-21c091325000 rw-p 00000000 00:00 0 -277034700000-277034800000 rw-p 00000000 00:00 0 -280bd8000000-280bd8f00000 ---p 00000000 00:00 0 -280bd8f00000-280bd9000000 rw-p 00000000 00:00 0 -280bd9000000-280bda000000 ---p 00000000 00:00 0 -2bb801c00000-2bb801c85000 rw-p 00000000 00:00 0 -30713ff00000-30713ff25000 rw-p 00000000 00:00 0 -31278c7c9000-31278c7ca000 r-xp 00000000 00:00 0 -3190d6f35000-3190d6f36000 rw-p 00000000 00:00 0 -3190d6f36000-3190d7135000 ---p 00000000 00:00 0 -7f62f5a2b000-7f62f607b000 rw-p 00000000 00:00 0 -7f62f607b000-7f62f6301000 rw-- 00000000 00:00 888963090 /SYSV00000000 (deleted) -7f62f6301000-7f62f6311000 rw-p 00000000 00:00 0 -7f62f6311000-7f62f6362000 r--- 00000000 00:00 1323029 /usr/share/fonts/truetype/msttcorefonts/Times_New_Roman.ttf -7f62f6362000-7f62f64d2000 rw-p 00000000 00:00 0 -7f62f64fe000-7f62f6542000 r--- 00000000 00:00 1323020 /usr/share/fonts/truetype/msttcorefonts/Arial.ttf -7f62f6542000-7f62f65b2000 rw-p 00000000 00:00 0 -7f62f65b2000-7f62f6804000 rw-- 00000000 00:00 888930318 /SYSV00000000 (deleted) -7f62f6804000-7f62f6984000 rw-p 00000000 00:00 0 -7f62f6984000-7f62f69a4000 r--- 00000000 00:00 14645040 /run/shm/.org.chromium.Chromium.KmCcUm (deleted) -7f62f69a4000-7f62f6a44000 rw-p 00000000 00:00 0 -7f62f6a44000-7f62f6a45000 ---p 00000000 00:00 0 -7f62f6a45000-7f62f6a55000 rw-p 00000000 00:00 0 -7f62f6a55000-7f62f6a56000 ---p 00000000 00:00 0 -7f62f6a56000-7f62f6af6000 rw-p 00000000 00:00 0 -7f62f6af6000-7f62f6af7000 ---p 00000000 00:00 0 -7f62f6af7000-7f62f72f7000 rw-p 00000000 00:00 0 -7f62f72f7000-7f62f72f8000 ---p 00000000 00:00 0 -7f62f72f8000-7f62f7af8000 rw-p 00000000 00:00 0 -7f62f7af8000-7f62f7bd6000 r-xp 00000000 00:00 6311146 /home/user/chromium/src/out/Debug/libppGoogleNaClPluginChrome.so -7f62f7bd6000-7f62f7bd7000 ---p 000de000 00:00 6311146 /home/user/chromium/src/out/Debug/libppGoogleNaClPluginChrome.so -7f62f7bd7000-7f62f7bda000 r--p 000de000 00:00 6311146 /home/user/chromium/src/out/Debug/libppGoogleNaClPluginChrome.so -7f62f7bda000-7f62f7bdc000 rw-p 000e1000 00:00 6311146 /home/user/chromium/src/out/Debug/libppGoogleNaClPluginChrome.so -7f62f7bdc000-7f62f7c3e000 r-xp 00000000 00:00 422206 /usr/lib/x86_64-linux-gnu/nss/libfreebl3.so -7f62f7c3e000-7f62f7e3d000 ---p 00062000 00:00 422206 /usr/lib/x86_64-linux-gnu/nss/libfreebl3.so -7f62f7e3d000-7f62f7e3f000 r--p 00061000 00:00 422206 /usr/lib/x86_64-linux-gnu/nss/libfreebl3.so -7f62f7e3f000-7f62f7e40000 rw-p 00063000 00:00 422206 /usr/lib/x86_64-linux-gnu/nss/libfreebl3.so -7f62f7e40000-7f62f7e44000 rw-p 00000000 00:00 0 -7f62f7e44000-7f62f7ee2000 r-xp 00000000 00:00 419056 /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6 -7f62f7ee2000-7f62f80e2000 ---p 0009e000 00:00 419056 /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6 -7f62f80e2000-7f62f80e4000 r--p 0009e000 00:00 419056 /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6 -7f62f80e4000-7f62f80e6000 rw-p 000a0000 00:00 419056 /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6 -7f62f80e6000-7f62f80e7000 rw-p 00000000 00:00 0 -7f62f80f6000-7f62f8106000 rw-p 00000000 00:00 0 -7f62f8106000-7f62f813e000 r-xp 00000000 00:00 422227 /usr/lib/x86_64-linux-gnu/nss/libsoftokn3.so -7f62f813e000-7f62f833d000 ---p 00038000 00:00 422227 /usr/lib/x86_64-linux-gnu/nss/libsoftokn3.so -7f62f833d000-7f62f833f000 r--p 00037000 00:00 422227 /usr/lib/x86_64-linux-gnu/nss/libsoftokn3.so -7f62f833f000-7f62f8340000 rw-p 00039000 00:00 422227 /usr/lib/x86_64-linux-gnu/nss/libsoftokn3.so -7f62f8340000-7f62f84fd000 r-xp 00000000 00:00 6311921 /home/user/chromium/src/out/Debug/libffmpegsumo.so -7f62f84fd000-7f62f84fe000 ---p 001bd000 00:00 6311921 /home/user/chromium/src/out/Debug/libffmpegsumo.so -7f62f84fe000-7f62f850e000 r--p 001bd000 00:00 6311921 /home/user/chromium/src/out/Debug/libffmpegsumo.so -7f62f850e000-7f62f8510000 rw-p 001cd000 00:00 6311921 /home/user/chromium/src/out/Debug/libffmpegsumo.so -7f62f8510000-7f62f85b3000 rw-p 00000000 00:00 0 -7f62f85b3000-7f62f8ad7000 r--- 00000000 00:00 6968058 /home/user/chromium/src/out/Debug/resources.pak -7f62f8ad7000-7f62f8b01000 r--- 00000000 00:00 6966120 /home/user/chromium/src/out/Debug/locales/en-US.pak -7f62f8b01000-7f62f8bd6000 r--- 00000000 00:00 6966021 /home/user/chromium/src/out/Debug/chrome_100_percent.pak -7f62f8bd6000-7f62f8f7d000 r--- 00000000 00:00 6966014 /home/user/chromium/src/out/Debug/chrome.pak -7f62f8f7d000-7f62f8fce000 rw-p 00000000 00:00 0 -7f62f8fce000-7f62f9d21000 r--p 00000000 00:00 795151 /usr/lib/locale/locale-archive -7f62f9d21000-7f62fa621000 rw-p 00000000 00:00 0 -7f62fa621000-7f62fa626000 r-xp 00000000 00:00 418995 /usr/lib/x86_64-linux-gnu/libXdmcp.so.6.0.0 -7f62fa626000-7f62fa825000 ---p 00005000 00:00 418995 /usr/lib/x86_64-linux-gnu/libXdmcp.so.6.0.0 -7f62fa825000-7f62fa826000 r--p 00004000 00:00 418995 /usr/lib/x86_64-linux-gnu/libXdmcp.so.6.0.0 -7f62fa826000-7f62fa827000 rw-p 00005000 00:00 418995 /usr/lib/x86_64-linux-gnu/libXdmcp.so.6.0.0 -7f62fa827000-7f62fa829000 r-xp 00000000 00:00 419161 /usr/lib/x86_64-linux-gnu/libXau.so.6.0.0 -7f62fa829000-7f62faa28000 ---p 00002000 00:00 419161 /usr/lib/x86_64-linux-gnu/libXau.so.6.0.0 -7f62faa28000-7f62faa29000 r--p 00001000 00:00 419161 /usr/lib/x86_64-linux-gnu/libXau.so.6.0.0 -7f62faa29000-7f62faa2a000 rw-p 00002000 00:00 419161 /usr/lib/x86_64-linux-gnu/libXau.so.6.0.0 -7f62faa2a000-7f62faa2d000 r-xp 00000000 00:00 262419 /lib/x86_64-linux-gnu/libgpg-error.so.0.8.0 -7f62faa2d000-7f62fac2c000 ---p 00003000 00:00 262419 /lib/x86_64-linux-gnu/libgpg-error.so.0.8.0 -7f62fac2c000-7f62fac2d000 r--p 00002000 00:00 262419 /lib/x86_64-linux-gnu/libgpg-error.so.0.8.0 -7f62fac2d000-7f62fac2e000 rw-p 00003000 00:00 262419 /lib/x86_64-linux-gnu/libgpg-error.so.0.8.0 -7f62fac2e000-7f62fac3f000 r-xp 00000000 00:00 419811 /usr/lib/x86_64-linux-gnu/libp11-kit.so.0.0.0 -7f62fac3f000-7f62fae3e000 ---p 00011000 00:00 419811 /usr/lib/x86_64-linux-gnu/libp11-kit.so.0.0.0 -7f62fae3e000-7f62fae3f000 r--p 00010000 00:00 419811 /usr/lib/x86_64-linux-gnu/libp11-kit.so.0.0.0 -7f62fae3f000-7f62fae40000 rw-p 00011000 00:00 419811 /usr/lib/x86_64-linux-gnu/libp11-kit.so.0.0.0 -7f62fae40000-7f62fae50000 r-xp 00000000 00:00 420094 /usr/lib/x86_64-linux-gnu/libtasn1.so.3.1.12 -7f62fae50000-7f62fb04f000 ---p 00010000 00:00 420094 /usr/lib/x86_64-linux-gnu/libtasn1.so.3.1.12 -7f62fb04f000-7f62fb050000 r--p 0000f000 00:00 420094 /usr/lib/x86_64-linux-gnu/libtasn1.so.3.1.12 -7f62fb050000-7f62fb051000 rw-p 00010000 00:00 420094 /usr/lib/x86_64-linux-gnu/libtasn1.so.3.1.12 -7f62fb051000-7f62fb054000 r-xp 00000000 00:00 262413 /lib/x86_64-linux-gnu/libkeyutils.so.1.4 -7f62fb054000-7f62fb253000 ---p 00003000 00:00 262413 /lib/x86_64-linux-gnu/libkeyutils.so.1.4 -7f62fb253000-7f62fb254000 r--p 00002000 00:00 262413 /lib/x86_64-linux-gnu/libkeyutils.so.1.4 -7f62fb254000-7f62fb255000 rw-p 00003000 00:00 262413 /lib/x86_64-linux-gnu/libkeyutils.so.1.4 -7f62fb255000-7f62fb25c000 r-xp 00000000 00:00 418378 /usr/lib/x86_64-linux-gnu/libkrb5support.so.0.1 -7f62fb25c000-7f62fb45b000 ---p 00007000 00:00 418378 /usr/lib/x86_64-linux-gnu/libkrb5support.so.0.1 -7f62fb45b000-7f62fb45c000 r--p 00006000 00:00 418378 /usr/lib/x86_64-linux-gnu/libkrb5support.so.0.1 -7f62fb45c000-7f62fb45d000 rw-p 00007000 00:00 418378 /usr/lib/x86_64-linux-gnu/libkrb5support.so.0.1 -7f62fb45d000-7f62fb46d000 r-xp 00000000 00:00 419369 /usr/lib/x86_64-linux-gnu/libavahi-client.so.3.2.9 -7f62fb46d000-7f62fb66c000 ---p 00010000 00:00 419369 /usr/lib/x86_64-linux-gnu/libavahi-client.so.3.2.9 -7f62fb66c000-7f62fb66d000 r--p 0000f000 00:00 419369 /usr/lib/x86_64-linux-gnu/libavahi-client.so.3.2.9 -7f62fb66d000-7f62fb66e000 rw-p 00010000 00:00 419369 /usr/lib/x86_64-linux-gnu/libavahi-client.so.3.2.9 -7f62fb66e000-7f62fb679000 r-xp 00000000 00:00 420318 /usr/lib/x86_64-linux-gnu/libavahi-common.so.3.5.3 -7f62fb679000-7f62fb878000 ---p 0000b000 00:00 420318 /usr/lib/x86_64-linux-gnu/libavahi-common.so.3.5.3 -7f62fb878000-7f62fb879000 r--p 0000a000 00:00 420318 /usr/lib/x86_64-linux-gnu/libavahi-common.so.3.5.3 -7f62fb879000-7f62fb87a000 rw-p 0000b000 00:00 420318 /usr/lib/x86_64-linux-gnu/libavahi-common.so.3.5.3 -7f62fb87a000-7f62fb89f000 r-xp 00000000 00:00 420145 /usr/lib/x86_64-linux-gnu/libdbus-glib-1.so.2.2.2 -7f62fb89f000-7f62fba9f000 ---p 00025000 00:00 420145 /usr/lib/x86_64-linux-gnu/libdbus-glib-1.so.2.2.2 -7f62fba9f000-7f62fbaa0000 r--p 00025000 00:00 420145 /usr/lib/x86_64-linux-gnu/libdbus-glib-1.so.2.2.2 -7f62fbaa0000-7f62fbaa1000 rw-p 00026000 00:00 420145 /usr/lib/x86_64-linux-gnu/libdbus-glib-1.so.2.2.2 -7f62fbaa1000-7f62fbaa9000 r-xp 00000000 00:00 401299 /usr/lib/x86_64-linux-gnu/libxcb-render.so.0.0.0 -7f62fbaa9000-7f62fbca9000 ---p 00008000 00:00 401299 /usr/lib/x86_64-linux-gnu/libxcb-render.so.0.0.0 -7f62fbca9000-7f62fbcaa000 r--p 00008000 00:00 401299 /usr/lib/x86_64-linux-gnu/libxcb-render.so.0.0.0 -7f62fbcaa000-7f62fbcab000 rw-p 00009000 00:00 401299 /usr/lib/x86_64-linux-gnu/libxcb-render.so.0.0.0 -7f62fbcab000-7f62fbcad000 r-xp 00000000 00:00 396366 /usr/lib/x86_64-linux-gnu/libxcb-shm.so.0.0.0 -7f62fbcad000-7f62fbeac000 ---p 00002000 00:00 396366 /usr/lib/x86_64-linux-gnu/libxcb-shm.so.0.0.0 -7f62fbeac000-7f62fbead000 r--p 00001000 00:00 396366 /usr/lib/x86_64-linux-gnu/libxcb-shm.so.0.0.0 -7f62fbead000-7f62fbeae000 rw-p 00002000 00:00 396366 /usr/lib/x86_64-linux-gnu/libxcb-shm.so.0.0.0 -7f62fbeae000-7f62fbed4000 r-xp 00000000 00:00 262376 /lib/x86_64-linux-gnu/libpng12.so.0.46.0 -7f62fbed4000-7f62fc0d4000 ---p 00026000 00:00 262376 /lib/x86_64-linux-gnu/libpng12.so.0.46.0 -7f62fc0d4000-7f62fc0d5000 r--p 00026000 00:00 262376 /lib/x86_64-linux-gnu/libpng12.so.0.46.0 -7f62fc0d5000-7f62fc0d6000 rw-p 00027000 00:00 262376 /lib/x86_64-linux-gnu/libpng12.so.0.46.0 -7f62fc0d6000-7f62fc157000 r-xp 00000000 00:00 419692 /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.24.4 -7f62fc157000-7f62fc356000 ---p 00081000 00:00 419692 /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.24.4 -7f62fc356000-7f62fc35c000 r--p 00080000 00:00 419692 /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.24.4 -7f62fc35c000-7f62fc35d000 rw-p 00086000 00:00 419692 /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.24.4 -7f62fc35d000-7f62fc37a000 r-xp 00000000 00:00 262459 /lib/x86_64-linux-gnu/libselinux.so.1 -7f62fc37a000-7f62fc579000 ---p 0001d000 00:00 262459 /lib/x86_64-linux-gnu/libselinux.so.1 -7f62fc579000-7f62fc57a000 r--p 0001c000 00:00 262459 /lib/x86_64-linux-gnu/libselinux.so.1 -7f62fc57a000-7f62fc57b000 rw-p 0001d000 00:00 262459 /lib/x86_64-linux-gnu/libselinux.so.1 -7f62fc57b000-7f62fc57c000 rw-p 00000000 00:00 0 -7f62fc57c000-7f62fc57e000 r-xp 00000000 00:00 419344 /usr/lib/x86_64-linux-gnu/libXinerama.so.1.0.0 -7f62fc57e000-7f62fc77d000 ---p 00002000 00:00 419344 /usr/lib/x86_64-linux-gnu/libXinerama.so.1.0.0 -7f62fc77d000-7f62fc77e000 r--p 00001000 00:00 419344 /usr/lib/x86_64-linux-gnu/libXinerama.so.1.0.0 -7f62fc77e000-7f62fc77f000 rw-p 00002000 00:00 419344 /usr/lib/x86_64-linux-gnu/libXinerama.so.1.0.0 -7f62fc77f000-7f62fc7bb000 r-xp 00000000 00:00 262390 /lib/x86_64-linux-gnu/libpcre.so.3.12.1 -7f62fc7bb000-7f62fc9ba000 ---p 0003c000 00:00 262390 /lib/x86_64-linux-gnu/libpcre.so.3.12.1 -7f62fc9ba000-7f62fc9bb000 r--p 0003b000 00:00 262390 /lib/x86_64-linux-gnu/libpcre.so.3.12.1 -7f62fc9bb000-7f62fc9bc000 rw-p 0003c000 00:00 262390 /lib/x86_64-linux-gnu/libpcre.so.3.12.1 -7f62fc9bc000-7f62fc9c3000 r-xp 00000000 00:00 419528 /usr/lib/x86_64-linux-gnu/libffi.so.6.0.0 -7f62fc9c3000-7f62fcbc2000 ---p 00007000 00:00 419528 /usr/lib/x86_64-linux-gnu/libffi.so.6.0.0 -7f62fcbc2000-7f62fcbc3000 r--p 00006000 00:00 419528 /usr/lib/x86_64-linux-gnu/libffi.so.6.0.0 -7f62fcbc3000-7f62fcbc4000 rw-p 00007000 00:00 419528 /usr/lib/x86_64-linux-gnu/libffi.so.6.0.0 -7f62fcbc4000-7f62fcbe1000 r-xp 00000000 00:00 400302 /usr/lib/x86_64-linux-gnu/libxcb.so.1.1.0 -7f62fcbe1000-7f62fcde0000 ---p 0001d000 00:00 400302 /usr/lib/x86_64-linux-gnu/libxcb.so.1.1.0 -7f62fcde0000-7f62fcde1000 r--p 0001c000 00:00 400302 /usr/lib/x86_64-linux-gnu/libxcb.so.1.1.0 -7f62fcde1000-7f62fcde2000 rw-p 0001d000 00:00 400302 /usr/lib/x86_64-linux-gnu/libxcb.so.1.1.0 -7f62fcde2000-7f62fcf97000 r-xp 00000000 00:00 263480 /lib/x86_64-linux-gnu/libc-2.15.so -7f62fcf97000-7f62fd196000 ---p 001b5000 00:00 263480 /lib/x86_64-linux-gnu/libc-2.15.so -7f62fd196000-7f62fd19a000 r--p 001b4000 00:00 263480 /lib/x86_64-linux-gnu/libc-2.15.so -7f62fd19a000-7f62fd19c000 rw-p 001b8000 00:00 263480 /lib/x86_64-linux-gnu/libc-2.15.so -7f62fd19c000-7f62fd1a1000 rw-p 00000000 00:00 0 -7f62fd1a1000-7f62fd1b6000 r-xp 00000000 00:00 262366 /lib/x86_64-linux-gnu/libgcc_s.so.1 -7f62fd1b6000-7f62fd3b5000 ---p 00015000 00:00 262366 /lib/x86_64-linux-gnu/libgcc_s.so.1 -7f62fd3b5000-7f62fd3b6000 r--p 00014000 00:00 262366 /lib/x86_64-linux-gnu/libgcc_s.so.1 -7f62fd3b6000-7f62fd3b7000 rw-p 00015000 00:00 262366 /lib/x86_64-linux-gnu/libgcc_s.so.1 -7f62fd3b7000-7f62fd499000 r-xp 00000000 00:00 419083 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16 -7f62fd499000-7f62fd698000 ---p 000e2000 00:00 419083 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16 -7f62fd698000-7f62fd6a0000 r--p 000e1000 00:00 419083 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16 -7f62fd6a0000-7f62fd6a2000 rw-p 000e9000 00:00 419083 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16 -7f62fd6a2000-7f62fd6b7000 rw-p 00000000 00:00 0 -7f62fd6b7000-7f62fd6c3000 r-xp 00000000 00:00 262197 /lib/x86_64-linux-gnu/libudev.so.0.13.0 -7f62fd6c3000-7f62fd8c2000 ---p 0000c000 00:00 262197 /lib/x86_64-linux-gnu/libudev.so.0.13.0 -7f62fd8c2000-7f62fd8c3000 r--p 0000b000 00:00 262197 /lib/x86_64-linux-gnu/libudev.so.0.13.0 -7f62fd8c3000-7f62fd8c4000 rw-p 0000c000 00:00 262197 /lib/x86_64-linux-gnu/libudev.so.0.13.0 -7f62fd8c4000-7f62fd8eb000 r-xp 00000000 00:00 262435 /lib/x86_64-linux-gnu/libexpat.so.1.5.2 -7f62fd8eb000-7f62fdaeb000 ---p 00027000 00:00 262435 /lib/x86_64-linux-gnu/libexpat.so.1.5.2 -7f62fdaeb000-7f62fdaed000 r--p 00027000 00:00 262435 /lib/x86_64-linux-gnu/libexpat.so.1.5.2 -7f62fdaed000-7f62fdaee000 rw-p 00029000 00:00 262435 /lib/x86_64-linux-gnu/libexpat.so.1.5.2 -7f62fdaee000-7f62fdafd000 r-xp 00000000 00:00 262446 /lib/x86_64-linux-gnu/libbz2.so.1.0.4 -7f62fdafd000-7f62fdcfc000 ---p 0000f000 00:00 262446 /lib/x86_64-linux-gnu/libbz2.so.1.0.4 -7f62fdcfc000-7f62fdcfd000 r--p 0000e000 00:00 262446 /lib/x86_64-linux-gnu/libbz2.so.1.0.4 -7f62fdcfd000-7f62fdcfe000 rw-p 0000f000 00:00 262446 /lib/x86_64-linux-gnu/libbz2.so.1.0.4 -7f62fdcfe000-7f62fddf9000 r-xp 00000000 00:00 296562 /lib/x86_64-linux-gnu/libm-2.15.so -7f62fddf9000-7f62fdff8000 ---p 000fb000 00:00 296562 /lib/x86_64-linux-gnu/libm-2.15.so -7f62fdff8000-7f62fdff9000 r--p 000fa000 00:00 296562 /lib/x86_64-linux-gnu/libm-2.15.so -7f62fdff9000-7f62fdffa000 rw-p 000fb000 00:00 296562 /lib/x86_64-linux-gnu/libm-2.15.so -7f62fdffa000-7f62fe003000 r-xp 00000000 00:00 296563 /lib/x86_64-linux-gnu/libcrypt-2.15.so -7f62fe003000-7f62fe203000 ---p 00009000 00:00 296563 /lib/x86_64-linux-gnu/libcrypt-2.15.so -7f62fe203000-7f62fe204000 r--p 00009000 00:00 296563 /lib/x86_64-linux-gnu/libcrypt-2.15.so -7f62fe204000-7f62fe205000 rw-p 0000a000 00:00 296563 /lib/x86_64-linux-gnu/libcrypt-2.15.so -7f62fe205000-7f62fe233000 rw-p 00000000 00:00 0 -7f62fe233000-7f62fe249000 r-xp 00000000 00:00 262537 /lib/x86_64-linux-gnu/libz.so.1.2.3.4 -7f62fe249000-7f62fe448000 ---p 00016000 00:00 262537 /lib/x86_64-linux-gnu/libz.so.1.2.3.4 -7f62fe448000-7f62fe449000 r--p 00015000 00:00 262537 /lib/x86_64-linux-gnu/libz.so.1.2.3.4 -7f62fe449000-7f62fe44a000 rw-p 00016000 00:00 262537 /lib/x86_64-linux-gnu/libz.so.1.2.3.4 -7f62fe44a000-7f62fe4c4000 r-xp 00000000 00:00 262361 /lib/x86_64-linux-gnu/libgcrypt.so.11.7.0 -7f62fe4c4000-7f62fe6c4000 ---p 0007a000 00:00 262361 /lib/x86_64-linux-gnu/libgcrypt.so.11.7.0 -7f62fe6c4000-7f62fe6c5000 r--p 0007a000 00:00 262361 /lib/x86_64-linux-gnu/libgcrypt.so.11.7.0 -7f62fe6c5000-7f62fe6c8000 rw-p 0007b000 00:00 262361 /lib/x86_64-linux-gnu/libgcrypt.so.11.7.0 -7f62fe6c8000-7f62fe77c000 r-xp 00000000 00:00 419320 /usr/lib/x86_64-linux-gnu/libgnutls.so.26.21.8 -7f62fe77c000-7f62fe97c000 ---p 000b4000 00:00 419320 /usr/lib/x86_64-linux-gnu/libgnutls.so.26.21.8 -7f62fe97c000-7f62fe982000 r--p 000b4000 00:00 419320 /usr/lib/x86_64-linux-gnu/libgnutls.so.26.21.8 -7f62fe982000-7f62fe983000 rw-p 000ba000 00:00 419320 /usr/lib/x86_64-linux-gnu/libgnutls.so.26.21.8 -7f62fe983000-7f62fe984000 rw-p 00000000 00:00 0 -7f62fe984000-7f62fe987000 r-xp 00000000 00:00 262402 /lib/x86_64-linux-gnu/libcom_err.so.2.1 -7f62fe987000-7f62feb86000 ---p 00003000 00:00 262402 /lib/x86_64-linux-gnu/libcom_err.so.2.1 -7f62feb86000-7f62feb87000 r--p 00002000 00:00 262402 /lib/x86_64-linux-gnu/libcom_err.so.2.1 -7f62feb87000-7f62feb88000 rw-p 00003000 00:00 262402 /lib/x86_64-linux-gnu/libcom_err.so.2.1 -7f62feb88000-7f62febad000 r-xp 00000000 00:00 419096 /usr/lib/x86_64-linux-gnu/libk5crypto.so.3.1 -7f62febad000-7f62fedad000 ---p 00025000 00:00 419096 /usr/lib/x86_64-linux-gnu/libk5crypto.so.3.1 -7f62fedad000-7f62fedae000 r--p 00025000 00:00 419096 /usr/lib/x86_64-linux-gnu/libk5crypto.so.3.1 -7f62fedae000-7f62fedaf000 rw-p 00026000 00:00 419096 /usr/lib/x86_64-linux-gnu/libk5crypto.so.3.1 -7f62fedaf000-7f62fedb0000 rw-p 00000000 00:00 0 -7f62fedb0000-7f62fee74000 r-xp 00000000 00:00 420204 /usr/lib/x86_64-linux-gnu/libkrb5.so.3.3 -7f62fee74000-7f62ff073000 ---p 000c4000 00:00 420204 /usr/lib/x86_64-linux-gnu/libkrb5.so.3.3 -7f62ff073000-7f62ff07d000 r--p 000c3000 00:00 420204 /usr/lib/x86_64-linux-gnu/libkrb5.so.3.3 -7f62ff07d000-7f62ff07e000 rw-p 000cd000 00:00 420204 /usr/lib/x86_64-linux-gnu/libkrb5.so.3.3 -7f62ff07e000-7f62ff0b9000 r-xp 00000000 00:00 420086 /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2 -7f62ff0b9000-7f62ff2b9000 ---p 0003b000 00:00 420086 /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2 -7f62ff2b9000-7f62ff2ba000 r--p 0003b000 00:00 420086 /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2 -7f62ff2ba000-7f62ff2bc000 rw-p 0003c000 00:00 420086 /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2 -7f62ff2bc000-7f62ff30c000 r-xp 00000000 00:00 444357 /usr/lib/x86_64-linux-gnu/libcups.so.2 -7f62ff30c000-7f62ff50b000 ---p 00050000 00:00 444357 /usr/lib/x86_64-linux-gnu/libcups.so.2 -7f62ff50b000-7f62ff50f000 r--p 0004f000 00:00 444357 /usr/lib/x86_64-linux-gnu/libcups.so.2 -7f62ff50f000-7f62ff510000 rw-p 00053000 00:00 444357 /usr/lib/x86_64-linux-gnu/libcups.so.2 -7f62ff510000-7f62ff515000 r-xp 00000000 00:00 419317 /usr/lib/x86_64-linux-gnu/libXfixes.so.3.1.0 -7f62ff515000-7f62ff714000 ---p 00005000 00:00 419317 /usr/lib/x86_64-linux-gnu/libXfixes.so.3.1.0 -7f62ff714000-7f62ff715000 r--p 00004000 00:00 419317 /usr/lib/x86_64-linux-gnu/libXfixes.so.3.1.0 -7f62ff715000-7f62ff716000 rw-p 00005000 00:00 419317 /usr/lib/x86_64-linux-gnu/libXfixes.so.3.1.0 -7f62ff716000-7f62ff718000 r-xp 00000000 00:00 419868 /usr/lib/x86_64-linux-gnu/libXdamage.so.1.1.0 -7f62ff718000-7f62ff917000 ---p 00002000 00:00 419868 /usr/lib/x86_64-linux-gnu/libXdamage.so.1.1.0 -7f62ff917000-7f62ff918000 r--p 00001000 00:00 419868 /usr/lib/x86_64-linux-gnu/libXdamage.so.1.1.0 -7f62ff918000-7f62ff919000 rw-p 00002000 00:00 419868 /usr/lib/x86_64-linux-gnu/libXdamage.so.1.1.0 -7f62ff919000-7f62ff9ff000 r-xp 00000000 00:00 419887 /usr/lib/x86_64-linux-gnu/libasound.so.2.0.0 -7f62ff9ff000-7f62ffbff000 ---p 000e6000 00:00 419887 /usr/lib/x86_64-linux-gnu/libasound.so.2.0.0 -7f62ffbff000-7f62ffc05000 r--p 000e6000 00:00 419887 /usr/lib/x86_64-linux-gnu/libasound.so.2.0.0 -7f62ffc05000-7f62ffc06000 rw-p 000ec000 00:00 419887 /usr/lib/x86_64-linux-gnu/libasound.so.2.0.0 -7f62ffc06000-7f62ffc08000 r-xp 00000000 00:00 419816 /usr/lib/x86_64-linux-gnu/libXcomposite.so.1.0.0 -7f62ffc08000-7f62ffe07000 ---p 00002000 00:00 419816 /usr/lib/x86_64-linux-gnu/libXcomposite.so.1.0.0 -7f62ffe07000-7f62ffe08000 r--p 00001000 00:00 419816 /usr/lib/x86_64-linux-gnu/libXcomposite.so.1.0.0 -7f62ffe08000-7f62ffe09000 rw-p 00002000 00:00 419816 /usr/lib/x86_64-linux-gnu/libXcomposite.so.1.0.0 -7f62ffe09000-7f62ffe21000 r-xp 00000000 00:00 263482 /lib/x86_64-linux-gnu/libpthread-2.15.so -7f62ffe21000-7f6300020000 ---p 00018000 00:00 263482 /lib/x86_64-linux-gnu/libpthread-2.15.so -7f6300020000-7f6300021000 r--p 00017000 00:00 263482 /lib/x86_64-linux-gnu/libpthread-2.15.so -7f6300021000-7f6300022000 rw-p 00018000 00:00 263482 /lib/x86_64-linux-gnu/libpthread-2.15.so -7f6300022000-7f6300026000 rw-p 00000000 00:00 0 -7f6300026000-7f6300068000 r-xp 00000000 00:00 262204 /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8 -7f6300068000-7f6300268000 ---p 00042000 00:00 262204 /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8 -7f6300268000-7f6300269000 r--p 00042000 00:00 262204 /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8 -7f6300269000-7f630026a000 rw-p 00043000 00:00 262204 /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8 -7f630026a000-7f6300282000 r-xp 00000000 00:00 289099 /lib/x86_64-linux-gnu/libresolv-2.15.so -7f6300282000-7f6300482000 ---p 00018000 00:00 289099 /lib/x86_64-linux-gnu/libresolv-2.15.so -7f6300482000-7f6300483000 r--p 00018000 00:00 289099 /lib/x86_64-linux-gnu/libresolv-2.15.so -7f6300483000-7f6300484000 rw-p 00019000 00:00 289099 /lib/x86_64-linux-gnu/libresolv-2.15.so -7f6300484000-7f6300486000 rw-p 00000000 00:00 0 -7f6300486000-7f63004b3000 r-xp 00000000 00:00 419655 /usr/lib/x86_64-linux-gnu/libgconf-2.so.4.1.5 -7f63004b3000-7f63006b2000 ---p 0002d000 00:00 419655 /usr/lib/x86_64-linux-gnu/libgconf-2.so.4.1.5 -7f63006b2000-7f63006b3000 r--p 0002c000 00:00 419655 /usr/lib/x86_64-linux-gnu/libgconf-2.so.4.1.5 -7f63006b3000-7f63006b4000 rw-p 0002d000 00:00 419655 /usr/lib/x86_64-linux-gnu/libgconf-2.so.4.1.5 -7f63006b4000-7f63006ee000 r-xp 00000000 00:00 422225 /usr/lib/x86_64-linux-gnu/libnspr4.so -7f63006ee000-7f63008ee000 ---p 0003a000 00:00 422225 /usr/lib/x86_64-linux-gnu/libnspr4.so -7f63008ee000-7f63008ef000 r--p 0003a000 00:00 422225 /usr/lib/x86_64-linux-gnu/libnspr4.so -7f63008ef000-7f63008f1000 rw-p 0003b000 00:00 422225 /usr/lib/x86_64-linux-gnu/libnspr4.so -7f63008f1000-7f63008f3000 rw-p 00000000 00:00 0 -7f63008f3000-7f63008f7000 r-xp 00000000 00:00 422220 /usr/lib/x86_64-linux-gnu/libplc4.so -7f63008f7000-7f6300af6000 ---p 00004000 00:00 422220 /usr/lib/x86_64-linux-gnu/libplc4.so -7f6300af6000-7f6300af7000 r--p 00003000 00:00 422220 /usr/lib/x86_64-linux-gnu/libplc4.so -7f6300af7000-7f6300af8000 rw-p 00004000 00:00 422220 /usr/lib/x86_64-linux-gnu/libplc4.so -7f6300af8000-7f6300afb000 r-xp 00000000 00:00 422218 /usr/lib/x86_64-linux-gnu/libplds4.so -7f6300afb000-7f6300cfa000 ---p 00003000 00:00 422218 /usr/lib/x86_64-linux-gnu/libplds4.so -7f6300cfa000-7f6300cfb000 r--p 00002000 00:00 422218 /usr/lib/x86_64-linux-gnu/libplds4.so -7f6300cfb000-7f6300cfc000 rw-p 00003000 00:00 422218 /usr/lib/x86_64-linux-gnu/libplds4.so -7f6300cfc000-7f6300d1f000 r-xp 00000000 00:00 422231 /usr/lib/x86_64-linux-gnu/libsmime3.so -7f6300d1f000-7f6300f1f000 ---p 00023000 00:00 422231 /usr/lib/x86_64-linux-gnu/libsmime3.so -7f6300f1f000-7f6300f22000 r--p 00023000 00:00 422231 /usr/lib/x86_64-linux-gnu/libsmime3.so -7f6300f22000-7f6300f23000 rw-p 00026000 00:00 422231 /usr/lib/x86_64-linux-gnu/libsmime3.so -7f6300f23000-7f6300f44000 r-xp 00000000 00:00 420737 /usr/lib/x86_64-linux-gnu/libnssutil3.so -7f6300f44000-7f6301143000 ---p 00021000 00:00 420737 /usr/lib/x86_64-linux-gnu/libnssutil3.so -7f6301143000-7f6301149000 r--p 00020000 00:00 420737 /usr/lib/x86_64-linux-gnu/libnssutil3.so -7f6301149000-7f630114a000 rw-p 00026000 00:00 420737 /usr/lib/x86_64-linux-gnu/libnssutil3.so -7f630114a000-7f6301249000 r-xp 00000000 00:00 420704 /usr/lib/x86_64-linux-gnu/libnss3.so -7f6301249000-7f6301448000 ---p 000ff000 00:00 420704 /usr/lib/x86_64-linux-gnu/libnss3.so -7f6301448000-7f630144d000 r--p 000fe000 00:00 420704 /usr/lib/x86_64-linux-gnu/libnss3.so -7f630144d000-7f630144f000 rw-p 00103000 00:00 420704 /usr/lib/x86_64-linux-gnu/libnss3.so -7f630144f000-7f6301451000 rw-p 00000000 00:00 0 -7f6301451000-7f6301485000 r-xp 00000000 00:00 419748 /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4 -7f6301485000-7f6301685000 ---p 00034000 00:00 419748 /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4 -7f6301685000-7f6301686000 r--p 00034000 00:00 419748 /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4 -7f6301686000-7f6301687000 rw-p 00035000 00:00 419748 /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4 -7f6301687000-7f630171d000 r-xp 00000000 00:00 420767 /usr/lib/x86_64-linux-gnu/libfreetype.so.6.8.0 -7f630171d000-7f630191c000 ---p 00096000 00:00 420767 /usr/lib/x86_64-linux-gnu/libfreetype.so.6.8.0 -7f630191c000-7f6301922000 r--p 00095000 00:00 420767 /usr/lib/x86_64-linux-gnu/libfreetype.so.6.8.0 -7f6301922000-7f6301923000 rw-p 0009b000 00:00 420767 /usr/lib/x86_64-linux-gnu/libfreetype.so.6.8.0 -7f6301923000-7f6301969000 r-xp 00000000 00:00 419045 /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0 -7f6301969000-7f6301b69000 ---p 00046000 00:00 419045 /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0 -7f6301b69000-7f6301b6b000 r--p 00046000 00:00 419045 /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0 -7f6301b6b000-7f6301b6c000 rw-p 00048000 00:00 419045 /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0 -7f6301b6c000-7f6301c25000 r-xp 00000000 00:00 418996 /usr/lib/x86_64-linux-gnu/libcairo.so.2.11000.2 -7f6301c25000-7f6301e24000 ---p 000b9000 00:00 418996 /usr/lib/x86_64-linux-gnu/libcairo.so.2.11000.2 -7f6301e24000-7f6301e26000 r--p 000b8000 00:00 418996 /usr/lib/x86_64-linux-gnu/libcairo.so.2.11000.2 -7f6301e26000-7f6301e27000 rw-p 000ba000 00:00 418996 /usr/lib/x86_64-linux-gnu/libcairo.so.2.11000.2 -7f6301e27000-7f6301e2a000 rw-p 00000000 00:00 0 -7f6301e2a000-7f6301e48000 r-xp 00000000 00:00 419133 /usr/lib/x86_64-linux-gnu/libgdk_pixbuf-2.0.so.0.2600.1 -7f6301e48000-7f6302048000 ---p 0001e000 00:00 419133 /usr/lib/x86_64-linux-gnu/libgdk_pixbuf-2.0.so.0.2600.1 -7f6302048000-7f6302049000 r--p 0001e000 00:00 419133 /usr/lib/x86_64-linux-gnu/libgdk_pixbuf-2.0.so.0.2600.1 -7f6302049000-7f630204a000 rw-p 0001f000 00:00 419133 /usr/lib/x86_64-linux-gnu/libgdk_pixbuf-2.0.so.0.2600.1 -7f630204a000-7f6302055000 r-xp 00000000 00:00 419820 /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0.3000.0 -7f6302055000-7f6302254000 ---p 0000b000 00:00 419820 /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0.3000.0 -7f6302254000-7f6302255000 r--p 0000a000 00:00 419820 /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0.3000.0 -7f6302255000-7f6302256000 rw-p 0000b000 00:00 419820 /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0.3000.0 -7f6302256000-7f630227f000 r-xp 00000000 00:00 419157 /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0 -7f630227f000-7f630247e000 ---p 00029000 00:00 419157 /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0 -7f630247e000-7f630247f000 r--p 00028000 00:00 419157 /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0 -7f630247f000-7f6302480000 rw-p 00029000 00:00 419157 /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0 -7f6302480000-7f63025c8000 r-xp 00000000 00:00 419294 /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.3200.3 -7f63025c8000-7f63027c7000 ---p 00148000 00:00 419294 /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.3200.3 -7f63027c7000-7f63027cb000 r--p 00147000 00:00 419294 /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.3200.3 -7f63027cb000-7f63027cd000 rw-p 0014b000 00:00 419294 /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.3200.3 -7f63027cd000-7f63027cf000 rw-p 00000000 00:00 0 -7f63027cf000-7f63027ee000 r-xp 00000000 00:00 420188 /usr/lib/x86_64-linux-gnu/libatk-1.0.so.0.20409.1 -7f63027ee000-7f63029ee000 ---p 0001f000 00:00 420188 /usr/lib/x86_64-linux-gnu/libatk-1.0.so.0.20409.1 -7f63029ee000-7f63029f0000 r--p 0001f000 00:00 420188 /usr/lib/x86_64-linux-gnu/libatk-1.0.so.0.20409.1 -7f63029f0000-7f63029f1000 rw-p 00021000 00:00 420188 /usr/lib/x86_64-linux-gnu/libatk-1.0.so.0.20409.1 -7f63029f1000-7f6302a9e000 r-xp 00000000 00:00 419013 /usr/lib/x86_64-linux-gnu/libgdk-x11-2.0.so.0.2400.10 -7f6302a9e000-7f6302c9d000 ---p 000ad000 00:00 419013 /usr/lib/x86_64-linux-gnu/libgdk-x11-2.0.so.0.2400.10 -7f6302c9d000-7f6302ca1000 r--p 000ac000 00:00 419013 /usr/lib/x86_64-linux-gnu/libgdk-x11-2.0.so.0.2400.10 -7f6302ca1000-7f6302ca3000 rw-p 000b0000 00:00 419013 /usr/lib/x86_64-linux-gnu/libgdk-x11-2.0.so.0.2400.10 -7f6302ca3000-7f63030d0000 r-xp 00000000 00:00 419385 /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.10 -7f63030d0000-7f63032d0000 ---p 0042d000 00:00 419385 /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.10 -7f63032d0000-7f63032d7000 r--p 0042d000 00:00 419385 /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.10 -7f63032d7000-7f63032db000 rw-p 00434000 00:00 419385 /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.10 -7f63032db000-7f63032dd000 rw-p 00000000 00:00 0 -7f63032dd000-7f63032eb000 r-xp 00000000 00:00 419600 /usr/lib/x86_64-linux-gnu/libXi.so.6.1.0 -7f63032eb000-7f63034ea000 ---p 0000e000 00:00 419600 /usr/lib/x86_64-linux-gnu/libXi.so.6.1.0 -7f63034ea000-7f63034eb000 r--p 0000d000 00:00 419600 /usr/lib/x86_64-linux-gnu/libXi.so.6.1.0 -7f63034eb000-7f63034ec000 rw-p 0000e000 00:00 419600 /usr/lib/x86_64-linux-gnu/libXi.so.6.1.0 -7f63034ec000-7f63035de000 r-xp 00000000 00:00 262368 /lib/x86_64-linux-gnu/libglib-2.0.so.0.3200.3 -7f63035de000-7f63037de000 ---p 000f2000 00:00 262368 /lib/x86_64-linux-gnu/libglib-2.0.so.0.3200.3 -7f63037de000-7f63037df000 r--p 000f2000 00:00 262368 /lib/x86_64-linux-gnu/libglib-2.0.so.0.3200.3 -7f63037df000-7f63037e0000 rw-p 000f3000 00:00 262368 /lib/x86_64-linux-gnu/libglib-2.0.so.0.3200.3 -7f63037e0000-7f63037e1000 rw-p 00000000 00:00 0 -7f63037e1000-7f63037e2000 r-xp 00000000 00:00 419135 /usr/lib/x86_64-linux-gnu/libgthread-2.0.so.0.3200.3 -7f63037e2000-7f63039e1000 ---p 00001000 00:00 419135 /usr/lib/x86_64-linux-gnu/libgthread-2.0.so.0.3200.3 -7f63039e1000-7f63039e2000 r--p 00000000 00:00 419135 /usr/lib/x86_64-linux-gnu/libgthread-2.0.so.0.3200.3 -7f63039e2000-7f63039e3000 rw-p 00001000 00:00 419135 /usr/lib/x86_64-linux-gnu/libgthread-2.0.so.0.3200.3 -7f63039e3000-7f6303a30000 r-xp 00000000 00:00 419601 /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3200.3 -7f6303a30000-7f6303c30000 ---p 0004d000 00:00 419601 /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3200.3 -7f6303c30000-7f6303c31000 r--p 0004d000 00:00 419601 /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3200.3 -7f6303c31000-7f6303c32000 rw-p 0004e000 00:00 419601 /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3200.3 -7f6303c32000-7f6303c35000 r-xp 00000000 00:00 420150 /usr/lib/x86_64-linux-gnu/libgmodule-2.0.so.0.3200.3 -7f6303c35000-7f6303e34000 ---p 00003000 00:00 420150 /usr/lib/x86_64-linux-gnu/libgmodule-2.0.so.0.3200.3 -7f6303e34000-7f6303e35000 r--p 00002000 00:00 420150 /usr/lib/x86_64-linux-gnu/libgmodule-2.0.so.0.3200.3 -7f6303e35000-7f6303e36000 rw-p 00003000 00:00 420150 /usr/lib/x86_64-linux-gnu/libgmodule-2.0.so.0.3200.3 -7f6303e36000-7f6303e38000 r-xp 00000000 00:00 263479 /lib/x86_64-linux-gnu/libdl-2.15.so -7f6303e38000-7f6304038000 ---p 00002000 00:00 263479 /lib/x86_64-linux-gnu/libdl-2.15.so -7f6304038000-7f6304039000 r--p 00002000 00:00 263479 /lib/x86_64-linux-gnu/libdl-2.15.so -7f6304039000-7f630403a000 rw-p 00003000 00:00 263479 /lib/x86_64-linux-gnu/libdl-2.15.so -7f630403a000-7f6304041000 r-xp 00000000 00:00 265235 /lib/x86_64-linux-gnu/librt-2.15.so -7f6304041000-7f6304240000 ---p 00007000 00:00 265235 /lib/x86_64-linux-gnu/librt-2.15.so -7f6304240000-7f6304241000 r--p 00006000 00:00 265235 /lib/x86_64-linux-gnu/librt-2.15.so -7f6304241000-7f6304242000 rw-p 00007000 00:00 265235 /lib/x86_64-linux-gnu/librt-2.15.so -7f6304242000-7f6304252000 r-xp 00000000 00:00 419652 /usr/lib/x86_64-linux-gnu/libXext.so.6.4.0 -7f6304252000-7f6304451000 ---p 00010000 00:00 419652 /usr/lib/x86_64-linux-gnu/libXext.so.6.4.0 -7f6304451000-7f6304452000 r--p 0000f000 00:00 419652 /usr/lib/x86_64-linux-gnu/libXext.so.6.4.0 -7f6304452000-7f6304453000 rw-p 00010000 00:00 419652 /usr/lib/x86_64-linux-gnu/libXext.so.6.4.0 -7f6304453000-7f6304455000 r-xp 00000000 00:00 420132 /usr/lib/x86_64-linux-gnu/libXss.so.1.0.0 -7f6304455000-7f6304655000 ---p 00002000 00:00 420132 /usr/lib/x86_64-linux-gnu/libXss.so.1.0.0 -7f6304655000-7f6304656000 r--p 00002000 00:00 420132 /usr/lib/x86_64-linux-gnu/libXss.so.1.0.0 -7f6304656000-7f6304657000 rw-p 00003000 00:00 420132 /usr/lib/x86_64-linux-gnu/libXss.so.1.0.0 -7f6304657000-7f6304660000 r-xp 00000000 00:00 420211 /usr/lib/x86_64-linux-gnu/libXrender.so.1.3.0 -7f6304660000-7f630485f000 ---p 00009000 00:00 420211 /usr/lib/x86_64-linux-gnu/libXrender.so.1.3.0 -7f630485f000-7f6304860000 r--p 00008000 00:00 420211 /usr/lib/x86_64-linux-gnu/libXrender.so.1.3.0 -7f6304860000-7f6304861000 rw-p 00009000 00:00 420211 /usr/lib/x86_64-linux-gnu/libXrender.so.1.3.0 -7f6304861000-7f6304869000 r-xp 00000000 00:00 419998 /usr/lib/x86_64-linux-gnu/libXrandr.so.2.2.0 -7f6304869000-7f6304a68000 ---p 00008000 00:00 419998 /usr/lib/x86_64-linux-gnu/libXrandr.so.2.2.0 -7f6304a68000-7f6304a69000 r--p 00007000 00:00 419998 /usr/lib/x86_64-linux-gnu/libXrandr.so.2.2.0 -7f6304a69000-7f6304a6a000 rw-p 00008000 00:00 419998 /usr/lib/x86_64-linux-gnu/libXrandr.so.2.2.0 -7f6304a6a000-7f6304a73000 r-xp 00000000 00:00 419293 /usr/lib/x86_64-linux-gnu/libXcursor.so.1.0.2 -7f6304a73000-7f6304c72000 ---p 00009000 00:00 419293 /usr/lib/x86_64-linux-gnu/libXcursor.so.1.0.2 -7f6304c72000-7f6304c73000 r--p 00008000 00:00 419293 /usr/lib/x86_64-linux-gnu/libXcursor.so.1.0.2 -7f6304c73000-7f6304c74000 rw-p 00009000 00:00 419293 /usr/lib/x86_64-linux-gnu/libXcursor.so.1.0.2 -7f6304c74000-7f6304da3000 r-xp 00000000 00:00 419233 /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0 -7f6304da3000-7f6304fa3000 ---p 0012f000 00:00 419233 /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0 -7f6304fa3000-7f6304fa4000 r--p 0012f000 00:00 419233 /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0 -7f6304fa4000-7f6304fa8000 rw-p 00130000 00:00 419233 /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0 -7f6304fa8000-7f6304fca000 r-xp 00000000 00:00 297771 /lib/x86_64-linux-gnu/ld-2.15.so -7f6304fcd000-7f6304fce000 r--- 00000000 00:00 14846136 /run/shm/.org.chromium.Chromium.zsFhgx (deleted) -7f6304fce000-7f6304fdf000 rw-p 00000000 00:00 0 -7f6304fdf000-7f6305107000 rw-p 00000000 00:00 0 -7f6305107000-7f6305108000 ---p 00000000 00:00 0 -7f6305108000-7f6305127000 rw-p 00000000 00:00 0 -7f6305127000-7f6305128000 ---p 00000000 00:00 0 -7f6305128000-7f6305147000 rw-p 00000000 00:00 0 -7f6305147000-7f6305148000 ---p 00000000 00:00 0 -7f6305148000-7f6305167000 rw-p 00000000 00:00 0 -7f6305167000-7f6305168000 ---p 00000000 00:00 0 -7f6305168000-7f63051b1000 rw-p 00000000 00:00 0 -7f63051b1000-7f63051ca000 rw-p 00000000 00:00 0 -7f63051ca000-7f63051cb000 r--p 00022000 00:00 297771 /lib/x86_64-linux-gnu/ld-2.15.so -7f63051cb000-7f63051cd000 rw-p 00023000 00:00 297771 /lib/x86_64-linux-gnu/ld-2.15.so -7f63051cd000-7f630fd06000 r-xp 00000000 00:00 6308662 /home/user/chromium/src/out/Debug/chrome -7f630fd06000-7f631010d000 r--p 0ab38000 00:00 6308662 /home/user/chromium/src/out/Debug/chrome -7f631010d000-7f631014a000 rw-p 0af3f000 00:00 6308662 /home/user/chromium/src/out/Debug/chrome -7f631014a000-7f63101c2000 rw-p 00000000 00:00 0 -7fff9437f000-7fff943a1000 rw-p 00000000 00:00 0 [stack] -7fff943ff000-7fff94400000 r-xp 00000000 00:00 0 [vdso] -ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] diff --git a/tools/deep_memory_profiler/tests/data/heap.01234.symmap/chrome.abcdef.nm b/tools/deep_memory_profiler/tests/data/heap.01234.symmap/chrome.abcdef.nm deleted file mode 100644 index 0f61c8ed9d..0000000000 --- a/tools/deep_memory_profiler/tests/data/heap.01234.symmap/chrome.abcdef.nm +++ /dev/null @@ -1,914 +0,0 @@ -0000000000aa1820 t WebKit::WebSize::WebSize(gfx::Size const&)<0000000000aa1820> -0000000000aa1850 t webkit_glue::WebPreferences::WebPreferences(webkit_glue::WebPreferences const&)<0000000000aa1850> -0000000000aa1880 t WebKit::WebURLRequest::WebURLRequest(WebKit::WebURL const&)<0000000000aa1880> -0000000000aa18b0 t WebKit::WebURLRequest::~WebURLRequest()<0000000000aa18b0> -0000000000aa18d0 t base::Callback::RunnableType, base::internal::FunctorTraits::RunType, void (base::internal::CallbackParamTraits >::StorageType)>::UnboundRunType> base::Bind >(void (printing::PrepareFrameAndViewForPrint::*)(), base::WeakPtr const&)<0000000000aa18d0> -0000000000aa1980 t base::WeakPtrFactory::GetWeakPtr()<0000000000aa1980> -0000000000aa1a90 t base::WeakPtr::~WeakPtr()<0000000000aa1a90> -0000000000aa1ab0 t base::Callback::Run() const<0000000000aa1ab0> -0000000000aa1af0 t content::RenderViewObserverTracker::RenderViewObserverTracker(content::RenderView const*)<0000000000aa1af0> -0000000000aa1b40 t scoped_ptr >::scoped_ptr()<0000000000aa1b40> -0000000000aa1b60 t scoped_ptr >::scoped_ptr()<0000000000aa1b60> -0000000000aa1b80 t scoped_ptr >::~scoped_ptr()<0000000000aa1b80> -0000000000aa1ba0 t scoped_ptr >::~scoped_ptr()<0000000000aa1ba0> -0000000000aa1bc0 t content::RenderViewObserverTracker::~RenderViewObserverTracker()<0000000000aa1bc0> -0000000000aa1c00 t ChromeViewHostMsg_CancelPrerenderForPrinting::ChromeViewHostMsg_CancelPrerenderForPrinting(int)<0000000000aa1c00> -0000000000aa1c30 t bool IPC::Message::Dispatch(IPC::Message const*, printing::PrintWebViewHelper*, printing::PrintWebViewHelper*, void (printing::PrintWebViewHelper::*)())<0000000000aa1c30> -0000000000aa1cd0 t bool PrintMsg_InitiatePrintPreview::Dispatch(IPC::Message const*, printing::PrintWebViewHelper*, printing::PrintWebViewHelper*, void (printing::PrintWebViewHelper::*)(bool))<0000000000aa1cd0> -0000000000aa1d60 t bool PrintMsg_PrintPreview::Dispatch(IPC::Message const*, printing::PrintWebViewHelper*, printing::PrintWebViewHelper*, void (printing::PrintWebViewHelper::*)(base::DictionaryValue const&))<0000000000aa1d60> -00000000017d6130 t IPC::ChannelProxy::Context::OnMessageReceived(IPC::Message const&)<00000000017d6130> -00000000017d6190 t IPC::ChannelProxy::Context::OnMessageReceivedNoFilter(IPC::Message const&)<00000000017d6190> -00000000017d6270 t IPC::ChannelProxy::Context::OnDispatchMessage(IPC::Message const&)<00000000017d6270> -00000000017d6450 t IPC::ChannelProxy::Context::OnChannelConnected(int)<00000000017d6450> -00000000017d65e0 t IPC::ChannelProxy::Context::OnAddFilter()<00000000017d65e0> -00000000017dbaf0 t base::internal::FunctorTraits::RunnableType base::internal::MakeRunnable(void (IPC::ChannelProxy::Context::* const&)(IPC::Message const&))<00000000017dbaf0> -00000000017dbb30 t base::internal::RunnableAdapter::RunnableAdapter(void (IPC::ChannelProxy::Context::*)(IPC::Message const&))<00000000017dbb30> -00000000017dbb80 t base::internal::RunnableAdapter::RunnableAdapter(void (IPC::ChannelProxy::Context::*)(IPC::Message const&))<00000000017dbb80> -00000000017dbbc0 t base::internal::BindState, void (IPC::ChannelProxy::Context*, IPC::Message const&), void (IPC::ChannelProxy::Context*, IPC::Message)>::BindState(base::internal::RunnableAdapter const&, IPC::ChannelProxy::Context* const&, IPC::Message const&)<00000000017dbbc0> -00000000017dbc50 t base::internal::BindState, void (IPC::ChannelProxy::Context*, IPC::Message const&), void (IPC::ChannelProxy::Context*, IPC::Message)>::~BindState()<00000000017dbc50> -00000000017dbc70 t base::internal::BindState, void (IPC::ChannelProxy::Context*, IPC::Message const&), void (IPC::ChannelProxy::Context*, IPC::Message)>::~BindState()<00000000017dbc70> -00000000017dbca0 t base::internal::BindState, void (IPC::ChannelProxy::Context*, IPC::Message const&), void (IPC::ChannelProxy::Context*, IPC::Message)>::~BindState()<00000000017dbca0> -00000000017dbd00 t base::Callback::Callback, void (IPC::ChannelProxy::Context*, IPC::Message const&), void (IPC::ChannelProxy::Context*, IPC::Message)>(base::internal::BindState, void (IPC::ChannelProxy::Context*, IPC::Message const&), void (IPC::ChannelProxy::Context*, IPC::Message)>*)<00000000017dbd00> -00000000017dbd50 t base::internal::Invoker<2, base::internal::BindState, void (IPC::ChannelProxy::Context*, IPC::Message const&), void (IPC::ChannelProxy::Context*, IPC::Message)>, void (IPC::ChannelProxy::Context*, IPC::Message const&)>::Run(base::internal::BindStateBase*)<00000000017dbd50> -00000000017dbde0 t base::internal::UnwrapTraits::Unwrap(IPC::Message const&)<00000000017dbde0> -00000000017dbdf0 t base::internal::InvokeHelper, void (IPC::ChannelProxy::Context* const&, IPC::Message const&)>::MakeItSo(base::internal::RunnableAdapter, IPC::ChannelProxy::Context* const&, IPC::Message const&)<00000000017dbdf0> -00000000017dbe40 t IPC::Message const& base::internal::CallbackForward(IPC::Message const&)<00000000017dbe40> -00000000017dbe50 t base::internal::RunnableAdapter::Run(IPC::ChannelProxy::Context*, IPC::Message const&)<00000000017dbe50> -00000000017dbee0 t std::vector, std::allocator > >::~vector()<00000000017dbee0> -00000000017dbf30 t std::_Vector_base, std::allocator > >::~_Vector_base()<00000000017dbf30> -00000000017dbf70 t std::_Vector_base, std::allocator > >::_Vector_impl::~_Vector_impl()<00000000017dbf70> -00000000017dbf90 t std::_Vector_base, std::allocator > >::_Vector_impl::~_Vector_impl()<00000000017dbf90> -00000000017dbfb0 t std::allocator >::~allocator()<00000000017dbfb0> -00000000017dbfd0 t __gnu_cxx::new_allocator >::~new_allocator()<00000000017dbfd0> -00000000017dbfe0 t std::vector, std::allocator > >::vector()<00000000017dbfe0> -00000000017dc000 t std::_Vector_base, std::allocator > >::_Vector_base()<00000000017dc000> -00000000017dc020 t std::_Vector_base, std::allocator > >::_Vector_impl::_Vector_impl()<00000000017dc020> -00000000017dc040 t std::_Vector_base, std::allocator > >::_Vector_impl::_Vector_impl()<00000000017dc040> -00000000017dc080 t std::allocator >::allocator()<00000000017dc080> -00000000017dc0a0 t __gnu_cxx::new_allocator >::new_allocator()<00000000017dc0a0> -00000000017dc0b0 t scoped_refptr::scoped_refptr(base::SingleThreadTaskRunner*)<00000000017dc0b0> -0000000001bea890 t WebKit::WebFrameImpl::dispatchWillSendRequest(WebKit::WebURLRequest&)<0000000001bea890> -0000000001bea960 t WebKit::WebFrameImpl::createAssociatedURLLoader(WebKit::WebURLLoaderOptions const&)<0000000001bea960> -0000000001bea9f0 t WebKit::WebFrameImpl::commitDocumentData(char const*, unsigned long)<0000000001bea9f0> -0000000001beaa40 t WebKit::WebFrameImpl::unloadListenerCount() const<0000000001beaa40> -0000000001beaa80 t WebKit::WebFrameImpl::isProcessingUserGesture() const<0000000001beaa80> -0000000001beaaa0 t WebKit::WebFrameImpl::consumeUserGesture() const<0000000001beaaa0> -0000000001beaac0 t WebKit::WebFrameImpl::willSuppressOpenerInNewFrame() const<0000000001beaac0> -0000000001beab00 t WebKit::WebFrameImpl::replaceSelection(WebKit::WebString const&)<0000000001beab00> -0000000001beab80 t WebKit::WebFrameImpl::insertText(WebKit::WebString const&)<0000000001beab80> -0000000001beac60 t WebKit::WebFrameImpl::setMarkedText(WebKit::WebString const&, unsigned int, unsigned int)<0000000001beac60> -0000000001beacf0 t WebKit::WebFrameImpl::unmarkText()<0000000001beacf0> -0000000001bead30 t WebKit::WebFrameImpl::hasMarkedText() const<0000000001bead30> -0000000001bf1da0 t WebKit::generateFrameIdentifier()<0000000001bf1da0> -0000000001bf1dc0 t WebKit::WebFrameImpl::~WebFrameImpl()<0000000001bf1dc0> -0000000001bf1df0 t non-virtual thunk to WebKit::WebFrameImpl::~WebFrameImpl()<0000000001bf1df0> -0000000001bf1e20 t WebKit::WebFrameImpl::~WebFrameImpl() -0000000001bf1f50 t non-virtual thunk to WebKit::WebFrameImpl::~WebFrameImpl()<0000000001bf1f50> -0000000001bf1f80 t WebKit::WebFrameImpl::setWebCoreFrame(WebCore::Frame*)<0000000001bf1f80> -0000000001bf2010 t WebKit::WebFrameImpl::initializeAsMainFrame(WebCore::Page*)<0000000001bf2010> -0000000001bf20c0 t WebKit::WebFrameImpl::createChildFrame(WebCore::FrameLoadRequest const&, WebCore::HTMLFrameOwnerElement*)<0000000001bf20c0> -0000000001c21ca0 t WebKit::pageGroupLoadDeferrerStack()<0000000001c21ca0> -0000000001c21d10 t WebKit::WebView::didExitModalLoop()<0000000001c21d10> -0000000001c21de0 t WebKit::WebViewImpl::initializeMainFrame(WebKit::WebFrameClient*)<0000000001c21de0> -0000000001c21e60 t WebKit::WebViewImpl::initializeHelperPluginFrame(WebKit::WebFrameClient*)<0000000001c21e60> -0000000001c21eb0 t WebKit::WebViewImpl::setAutofillClient(WebKit::WebAutofillClient*)<0000000001c21eb0> -0000000001c21ed0 t WebKit::WebViewImpl::setDevToolsAgentClient(WebKit::WebDevToolsAgentClient*)<0000000001c21ed0> -0000000001c21f90 t WebKit::WebViewImpl::setPermissionClient(WebKit::WebPermissionClient*)<0000000001c21f90> -0000000001c21fd0 t WebKit::WebViewImpl::setPrerendererClient(WebKit::WebPrerendererClient*)<0000000001c21fd0> -0000000001c22050 t WebKit::WebViewImpl::setSpellCheckClient(WebKit::WebSpellCheckClient*)<0000000001c22050> -0000000001c22070 t WebKit::WebViewImpl::addTextFieldDecoratorClient(WebKit::WebTextFieldDecoratorClient*)<0000000001c22070> -0000000001c56f90 t WTF::Vector::remove(unsigned long)<0000000001c56f90> -0000000001c57060 t WTF::Vector::operator[](unsigned long)<0000000001c57060> -0000000001c57090 t WTF::Vector::size() const<0000000001c57090> -0000000001c570a0 t WebKit::WebViewImpl::autofillClient()<0000000001c570a0> -0000000001c570b0 t WebKit::AutofillPopupMenuClient::getTextField() const<0000000001c570b0> -0000000001c570e0 t WebCore::PopupMenuStyle::PopupMenuStyle(WebCore::PopupMenuStyle const&)<0000000001c570e0> -0000000001c57110 t WTF::OwnPtr::operator*() const<0000000001c57110> -0000000001c57190 t WTF::PassRefPtr::operator->() const<0000000001c57190> -0000000001c571a0 t WebKit::WebViewImpl::autofillPopupDidHide()<0000000001c571a0> -0000000001c571c0 t WTF::Vector::operator[](unsigned long) const<0000000001c571c0> -0000000001c571f0 t WTF::RefPtr::operator->() const<0000000001c571f0> -0000000001c57200 t WebCore::Document::styleResolver()<0000000001c57200> -0000000001c57260 t WebCore::StyleResolver::fontSelector() const<0000000001c57260> -0000000001c57290 t WTF::RefPtr::operator=(WebCore::HTMLInputElement*)<0000000001c57290> -0000000001c572e0 t WebKit::WebVector::WebVector(unsigned long)<0000000001c572e0> -0000000001c57310 t WebKit::WebVector::operator[](unsigned long)<0000000001c57310> -0000000001c57380 t WebCore::FontDescription::FontDescription()<0000000001c57380> -0000000001c573a0 t WebCore::FontDescription::setComputedSize(float)<0000000001c573a0> -0000000001c573e0 t WebCore::FontDescription::computedSize() const<0000000001c573e0> -0000000001c573f0 t WTF::PassRefPtr::PassRefPtr(WebCore::FontSelector*)<0000000001c573f0> -0000000001c57420 t WTF::PassRefPtr::~PassRefPtr()<0000000001c57420> -0000000001c57440 t WTF::OwnPtr::operator=(WTF::PassOwnPtr const&)<0000000001c57440> -0000000001c574f0 t WTF::PassOwnPtr WTF::adoptPtr(WebCore::PopupMenuStyle*)<0000000001c574f0> -0000000001c57520 t WebCore::PopupMenuStyle::PopupMenuStyle(WebCore::Color const&, WebCore::Color const&, WebCore::Font const&, bool, bool, WebCore::Length, WebCore::TextDirection, bool, WebCore::PopupMenuStyle::PopupMenuType)<0000000001c57520> -0000000001c7b970 t WebKit::FrameLoaderClientImpl::postProgressEstimateChangedNotification()<0000000001c7b970> -0000000001c7ba20 t WebKit::FrameLoaderClientImpl::postProgressFinishedNotification()<0000000001c7ba20> -0000000001c7ba90 t WebKit::FrameLoaderClientImpl::setMainFrameDocumentReady(bool)<0000000001c7ba90> -0000000001c7baa0 t WebKit::FrameLoaderClientImpl::startDownload(WebCore::ResourceRequest const&, WTF::String const&)<0000000001c7baa0> -0000000001c7bb60 t WebKit::FrameLoaderClientImpl::willChangeTitle(WebCore::DocumentLoader*)<0000000001c7bb60> -0000000001c7bb70 t WebKit::FrameLoaderClientImpl::didChangeTitle(WebCore::DocumentLoader*)<0000000001c7bb70> -0000000001c7bb80 t WebKit::FrameLoaderClientImpl::committedLoad(WebCore::DocumentLoader*, char const*, int)<0000000001c7bb80> -0000000001c7bde0 t WebKit::FrameLoaderClientImpl::finishedLoading(WebCore::DocumentLoader*)<0000000001c7bde0> -0000000001c7be60 t WebKit::FrameLoaderClientImpl::updateGlobalHistory()<0000000001c7be60> -0000000001c7be70 t WebKit::FrameLoaderClientImpl::updateGlobalHistoryRedirectLinks()<0000000001c7be70> -0000000001c7be80 t WebKit::FrameLoaderClientImpl::shouldGoToHistoryItem(WebCore::HistoryItem*) const<0000000001c7be80> -0000000001c99d90 t WebCore::PlainTextRange::PlainTextRange(unsigned int, unsigned int)<0000000001c99d90> -0000000001c99dc0 t WebCore::Node::computedStyle(WebCore::PseudoId)<0000000001c99dc0> -0000000001c99df0 t WTF::PassRefPtr WebCore::CSSPrimitiveValue::create(WebCore::EDisplay)<0000000001c99df0> -0000000001c99e60 t WebCore::RenderStyle::display() const<0000000001c99e60> -0000000001c99e80 t WTF::PassRefPtr::operator->() const<0000000001c99e80> -0000000001c99e90 t WTF::PassRefPtr::~PassRefPtr()<0000000001c99e90> -0000000001c99eb0 t WebKit::WebVector::swap(WebKit::WebVector&)<0000000001c99eb0> -0000000001c99f10 t WebKit::WebPrivatePtr::WebPrivatePtr(WTF::PassRefPtr const&)<0000000001c99f10> -0000000001c99f40 t WebKit::WebPrivatePtr::operator=(WTF::PassRefPtr const&)<0000000001c99f40> -0000000001c99f80 t WebKit::WebPrivatePtr::assign(WebCore::AccessibilityObject*)<0000000001c99f80> -0000000001c99fd0 t WTF::PassRefPtr::leakRef() const<0000000001c99fd0> -0000000001c99ff0 t WebKit::WebPrivatePtr::WebPrivatePtr(WTF::PassRefPtr const&)<0000000001c99ff0> -0000000001c9a020 t WTF::PassRefPtr WTF::adoptRef(WebCore::CSSPrimitiveValue*)<0000000001c9a020> -0000000001c9a060 t WTF::RefCounted::operator new(unsigned long)<0000000001c9a060> -0000000001c9a0a0 t WebCore::CSSPrimitiveValue::CSSPrimitiveValue(WebCore::EDisplay)<0000000001c9a0a0> -0000000001c9a0d0 t WebCore::CSSPrimitiveValue::CSSPrimitiveValue(WebCore::EDisplay)<0000000001c9a0d0> -0000000001c9a320 t WebCore::CSSValue::CSSValue(WebCore::CSSValue::ClassType, bool)<0000000001c9a320> -0000000001e0dbc0 t MmapHook(void const*, void const*, unsigned long, int, int, int, long)<0000000001e0dbc0> -0000000001e0dc40 t MremapHook(void const*, void const*, unsigned long, unsigned long, int, void const*)<0000000001e0dc40> -0000000001e0dcb0 t MunmapHook(void const*, unsigned long)<0000000001e0dcb0> -0000000001e0dd00 t SbrkHook(void const*, long)<0000000001e0dd00> -0000000001e0dd50 t ProfilerMalloc(unsigned long)<0000000001e0dd50> -0000000001e0dd80 t ProfilerFree(void*)<0000000001e0dd80> -0000000001e0dda0 t NewHook(void const*, unsigned long)<0000000001e0dda0> -0000000001e0dde0 T DeleteHook(void const*)<0000000001e0dde0> -0000000001e0de10 T IterateAllocatedObjects<0000000001e0de10> -0000000001e0de90 T IsHeapProfilerRunning<0000000001e0de90> -0000000001e0dee0 t HeapProfilerStop<0000000001e0dee0> -0000000001e0ec00 t RecordAlloc(void const*, unsigned long, int)<0000000001e0ec00> -0000000001e0eca0 t MMapProfilerMalloc(unsigned long)<0000000001e0eca0> -0000000001e0ecd0 t MMapProfilerFree(void*)<0000000001e0ecd0> -0000000001e0ecf0 t __cxx_global_var_init<0000000001e0ecf0> -0000000001e0ed60 t __cxx_global_var_init1<0000000001e0ed60> -0000000001e0edd0 t __cxx_global_var_init3<0000000001e0edd0> -0000000001e0ee40 t __cxx_global_var_init5<0000000001e0ee40> -0000000001e0eeb0 t __cxx_global_var_init7<0000000001e0eeb0> -0000000001e0ef20 t __cxx_global_var_init10<0000000001e0ef20> -0000000001e113a0 T MallocHook_AddSbrkHook<0000000001e113a0> -0000000001e113e0 T MallocHook_RemoveSbrkHook<0000000001e113e0> -0000000001e11420 T MallocHook_SetNewHook<0000000001e11420> -0000000001e11460 T MallocHook_SetDeleteHook<0000000001e11460> -0000000001e114a0 T MallocHook_SetPreMmapHook<0000000001e114a0> -0000000001e114e0 T MallocHook_SetMmapHook<0000000001e114e0> -0000000001e11520 T MallocHook_SetMunmapHook<0000000001e11520> -0000000001e11560 T MallocHook_SetMremapHook<0000000001e11560> -0000000001e115a0 T MallocHook_SetPreSbrkHook<0000000001e115a0> -0000000001e115e0 T MallocHook_SetSbrkHook<0000000001e115e0> -0000000001e11620 T MallocHook::InvokeNewHookSlow(void const*, unsigned long)<0000000001e11620> -0000000001e11690 T MallocHook::InvokeDeleteHookSlow(void const*)<0000000001e11690> -0000000001e11700 T MallocHook::InvokePreMmapHookSlow(void const*, unsigned long, int, int, int, long)<0000000001e11700> -0000000001e11790 T MallocHook::InvokeMmapHookSlow(void const*, void const*, unsigned long, int, int, int, long)<0000000001e11790> -0000000001e11830 T MallocHook::InvokeMmapReplacementSlow(void const*, unsigned long, int, int, int, long, void**)<0000000001e11830> -0000000001e118d0 T MallocHook::InvokeMunmapHookSlow(void const*, unsigned long)<0000000001e118d0> -0000000001e11940 T MallocHook::InvokeMunmapReplacementSlow(void const*, unsigned long, int*)<0000000001e11940> -0000000001e14fc0 t MallocHook::GetSbrkHook()<0000000001e14fc0> -0000000001e14fe0 t base::internal::AtomicPtr::Get() const<0000000001e14fe0> -0000000001e15000 t base::internal::HookList::empty() const<0000000001e15000> -0000000001e15030 t MallocHook::GetPreSbrkHook()<0000000001e15030> -0000000001e15050 t base::internal::AtomicPtr::Get() const<0000000001e15050> -0000000001e15070 t base::internal::HookList::empty() const<0000000001e15070> -0000000001e150a0 t MallocHook::GetMremapHook()<0000000001e150a0> -0000000001e150c0 t base::internal::AtomicPtr::Get() const<0000000001e150c0> -0000000001e150e0 t MallocHook::GetMunmapHook()<0000000001e150e0> -0000000001e15100 t base::internal::AtomicPtr::Get() const<0000000001e15100> -0000000001e15120 t base::internal::HookList::empty() const<0000000001e15120> -0000000001e15150 t MallocHook::GetMmapHook()<0000000001e15150> -0000000001e15170 t base::internal::AtomicPtr::Get() const<0000000001e15170> -0000000001e15190 t base::internal::HookList::empty() const<0000000001e15190> -0000000001e151c0 t MallocHook::GetPreMmapHook()<0000000001e151c0> -0000000001e151e0 t base::internal::AtomicPtr::Get() const<0000000001e151e0> -0000000001e15200 t MallocHook::RemovePreMmapHook(void (*)(void const*, unsigned long, int, int, int, long))<0000000001e15200> -0000000001e15230 t MallocHook::RemovePreSbrkHook(void (*)(long))<0000000001e15230> -0000000001e15260 t MallocHook::InvokeNewHook(void const*, unsigned long)<0000000001e15260> -0000000001e152c0 T MallocHook::GetNewHook()<0000000001e152c0> -0000000001e152e0 T perftools_pthread_key_create(unsigned int*, void (*)(void*))<0000000001e152e0> -0000000001e15380 T perftools_pthread_getspecific(unsigned int)<0000000001e15380> -0000000001e153d0 T perftools_pthread_setspecific(unsigned int, void*)<0000000001e153d0> -0000000001e15430 T perftools_pthread_once(int*, void (*)())<0000000001e15430> -0000000001e154b0 T MemoryRegionMap::Init(int)<0000000001e154b0> -0000000001e233b0 T DoAllocWithArena(unsigned long, LowLevelAlloc::Arena*)<0000000001e233b0> -0000000001e237b0 T LowLevelAlloc::DefaultArena()<0000000001e237b0> -0000000001e237c0 t LowLevelAlloc::GetSizeOfUnhookedArena()<0000000001e237c0> -0000000001e237e0 t RoundUp(long, long)<0000000001e237e0> -0000000001e23820 t LLA_SkiplistLevels(unsigned long, unsigned long, bool)<0000000001e23820> -0000000001e2f0c0 T HeapProfileTable::DeallocateBucketTable(HeapProfileTable::Bucket**)<0000000001e2f0c0> -0000000001e2f190 T HeapProfileTable::DeallocateAllocationMap(AddressMap*)<0000000001e2f190> -0000000001e2f1f0 T HeapProfileTable::GetBucket(int, void const* const*, HeapProfileTable::Bucket**, int*)<0000000001e2f1f0> -0000000001e2f440 T HeapProfileTable::GetCallerStackTrace(int, void**)<0000000001e2f440> -0000000001e2f480 T HeapProfileTable::RecordAlloc(void const*, unsigned long, int, void const* const*)<0000000001e2f480> -0000000001e2f560 T HeapProfileTable::RecordFree(void const*)<0000000001e2f560> -0000000001e2f5f0 T HeapProfileTable::FindAlloc(void const*, unsigned long*) const<0000000001e2f5f0> -0000000001e2f650 T HeapProfileTable::FindAllocDetails(void const*, HeapProfileTable::AllocInfo*) const<0000000001e2f650> -0000000002037650 t MessageLoop::PostNonNestableDelayedTask(tracked_objects::Location const&, base::Callback const&, base::TimeDelta)<0000000002037650> -00000000020377f0 t MessageLoop::Run()<00000000020377f0> -0000000002037820 t MessageLoop::RunUntilIdle()<0000000002037820> -0000000002037850 t MessageLoop::QuitWhenIdle()<0000000002037850> -0000000002037990 t MessageLoop::QuitNow()<0000000002037990> -0000000002037ae0 t MessageLoop::IsType(MessageLoop::Type) const<0000000002037ae0> -0000000002037b00 t MessageLoop::QuitWhenIdleClosure()<0000000002037b00> -00000000020380d0 t MessageLoop::StartHistogrammer()<00000000020380d0> -0000000002038230 t MessageLoop::ProcessNextDelayedNonNestableTask()<0000000002038230> -00000000020388e0 t MessageLoop::DeferOrRunPendingTask(base::PendingTask const&)<00000000020388e0> -0000000002042120 t void base::subtle::DeleteHelperInternal::DeleteViaSequencedTaskRunner(MessageLoop*, tracked_objects::Location const&, base::MessageLoopProxyImpl const*)<0000000002042120> -0000000002042160 t base::DeleteHelper::DoDelete(void const*)<0000000002042160> -00000000020421a0 t base::ThreadRestrictions::ScopedAllowSingleton::~ScopedAllowSingleton()<00000000020421a0> -00000000020421d0 t base::ThreadRestrictions::ScopedAllowSingleton::ScopedAllowSingleton()<00000000020421d0> -0000000002042200 t base::MessagePump::MessagePump()<0000000002042200> -0000000002042240 t base::MessagePump::~MessagePump()<0000000002042240> -0000000002042270 t base::MessagePump::~MessagePump() -00000000020422a0 t base::RefCountedThreadSafe >::RefCountedThreadSafe()<00000000020422a0> -00000000020422c0 t base::RefCountedThreadSafe >::~RefCountedThreadSafe()<00000000020422c0> -00000000020422e0 t base::MessagePumpDefault::MessagePumpDefault() -0000000002042350 t base::MessagePumpDefault::Run(base::MessagePump::Delegate*)<0000000002042350> -0000000002042620 t base::MessagePumpDefault::Quit()<0000000002042620> -0000000002042630 t base::MessagePumpDefault::ScheduleWork()<0000000002042630> -0000000002042660 t base::MessagePumpDefault::ScheduleDelayedWork(base::TimeTicks const&)<0000000002042660> -00000000020426b0 t base::MessagePumpDefault::~MessagePumpDefault()<00000000020426b0> -00000000020426d0 t base::MessagePumpDefault::~MessagePumpDefault()<00000000020426d0> -0000000002042700 t base::MessagePumpDefault::~MessagePumpDefault()<0000000002042700> -0000000002068570 t base::FileDescriptorTableInjection::FileDescriptorTableInjection()<0000000002068570> -0000000002068590 t base::FileDescriptorTableInjection::~FileDescriptorTableInjection()<0000000002068590> -00000000020685b0 t base::FileDescriptorTableInjection::~FileDescriptorTableInjection()<00000000020685b0> -00000000020685d0 t base::InjectionDelegate::~InjectionDelegate()<00000000020685d0> -00000000020685e0 t base::FileDescriptorTableInjection::FileDescriptorTableInjection()<00000000020685e0> -0000000002068620 t base::InjectionDelegate::InjectionDelegate()<0000000002068620> -0000000002068640 t base::InjectionDelegate::~InjectionDelegate()<0000000002068640> -0000000002068660 t base::InjectionDelegate::~InjectionDelegate()<0000000002068660> -0000000002068690 t base::InjectionArc::InjectionArc(int, int, bool)<0000000002068690> -00000000020686d0 t base::DirReaderLinux::~DirReaderLinux()<00000000020686d0> -0000000002068780 t base::DirReaderLinux::DirReaderLinux(char const*)<0000000002068780> -00000000020687f0 t tracked_objects::ScopedProfile::ScopedProfile(tracked_objects::Location const&) -0000000002068830 t tracked_objects::ScopedProfile::~ScopedProfile() -0000000002068850 t tracked_objects::ScopedProfile::StopClockAndTally()<0000000002068850> -00000000020688c0 t tracked_objects::SetAlternateTimeSource(unsigned int (*)(), tracked_objects::TimeSourceType)<00000000020688c0> -0000000002068970 t tracked_objects::GetAlternateTimeSource()<0000000002068970> -0000000002068980 t tracked_objects::GetTimeSourceType()<0000000002068980> -0000000002068990 t std::basic_string, std::allocator >* logging::CheckEQImpl(unsigned int (* const&)(), unsigned int (* const&)(), char const*)<0000000002068990> -00000000020689f0 t std::basic_string, std::allocator >* logging::MakeCheckOpString(unsigned int (* const&)(), unsigned int (* const&)(), char const*)<00000000020689f0> -0000000002068b30 t base::RandInt(int, int)<0000000002068b30> -0000000002069470 t (anonymous namespace)::URandomFd::URandomFd() -0000000002069540 t base::RunLoop::RunLoop() -00000000020695b0 t base::RunLoop::RunLoop(base::MessagePumpDispatcher*) -0000000002069620 t base::RunLoop::~RunLoop() -0000000002069650 t base::RunLoop::Run()<0000000002069650> -00000000020696a0 t base::RunLoop::BeforeRun()<00000000020696a0> -00000000020697f0 t base::RunLoop::AfterRun()<00000000020697f0> -0000000002069850 t base::RunLoop::RunUntilIdle()<0000000002069850> -0000000002069870 t base::RunLoop::Quit()<0000000002069870> -00000000020698c0 t base::RunLoop::QuitClosure()<00000000020698c0> -0000000002069930 t base::WeakPtrFactory::WeakPtrFactory(base::RunLoop*)<0000000002069930> -0000000002069960 t base::WeakPtrFactory::~WeakPtrFactory()<0000000002069960> -0000000002069980 t base::Callback::RunnableType, base::internal::FunctorTraits::RunType, void (base::internal::CallbackParamTraits >::StorageType)>::UnboundRunType> base::Bind >(void (base::RunLoop::*)(), base::WeakPtr const&)<0000000002069980> -00000000020b7a00 t tracked_objects::ThreadData::SnapshotAllExecutedTasks(bool, tracked_objects::ProcessDataSnapshot*, std::map, std::allocator > >*)<00000000020b7a00> -00000000020b7a70 t tracked_objects::ThreadData::TallyABirth(tracked_objects::Location const&)<00000000020b7a70> -00000000020b7ba0 t tracked_objects::ThreadData::TallyADeath(tracked_objects::Births const&, int, int)<00000000020b7ba0> -00000000020b7cf0 t tracked_objects::ThreadData::TallyABirthIfActive(tracked_objects::Location const&)<00000000020b7cf0> -00000000020b7d60 t tracked_objects::ThreadData::TrackingStatus()<00000000020b7d60> -00000000020b7d80 t tracked_objects::ThreadData::TallyRunOnNamedThreadIfTracking(base::TrackingInfo const&, tracked_objects::TrackedTime const&, tracked_objects::TrackedTime const&)<00000000020b7d80> -00000000020b7eb0 t tracked_objects::ThreadData::TallyRunOnWorkerThreadIfTracking(tracked_objects::Births const*, tracked_objects::TrackedTime const&, tracked_objects::TrackedTime const&, tracked_objects::TrackedTime const&)<00000000020b7eb0> -00000000020b7f80 t tracked_objects::ThreadData::TallyRunInAScopedRegionIfTracking(tracked_objects::Births const*, tracked_objects::TrackedTime const&, tracked_objects::TrackedTime const&)<00000000020b7f80> -00000000020b9330 t std::_Rb_tree_iterator >::operator->() const<00000000020b9330> -00000000020b9360 t std::map, std::allocator > >::operator[](tracked_objects::Location const&)<00000000020b9360> -00000000020b9450 t std::map, std::allocator > >::find(tracked_objects::Births const* const&)<00000000020b9450> -00000000020b9480 t std::_Rb_tree_iterator >::operator!=(std::_Rb_tree_iterator > const&) const<00000000020b9480> -00000000020b94b0 t std::map, std::allocator > >::end()<00000000020b94b0> -00000000020b94e0 t std::_Rb_tree_iterator >::operator->() const<00000000020b94e0> -00000000020b9510 t std::map, std::allocator > >::operator[](tracked_objects::Births const* const&)<00000000020b9510> -00000000020b9640 t std::_Rb_tree_const_iterator >::_Rb_tree_const_iterator(std::_Rb_tree_iterator > const&)<00000000020b9640> -00000000020b9670 t std::map, std::allocator > >::begin()<00000000020b9670> -00000000020b96a0 t std::_Rb_tree_const_iterator >::operator!=(std::_Rb_tree_const_iterator > const&) const<00000000020b96a0> -00000000020b96d0 t std::_Rb_tree_const_iterator >::operator->() const<00000000020b96d0> -00000000020b9700 t std::map, std::allocator > >::operator[](tracked_objects::BirthOnThread const* const&)<00000000020b9700> -00000000020b97e0 t std::_Rb_tree_const_iterator >::operator++()<00000000020b97e0> -00000000020b9810 t std::_Rb_tree_const_iterator >::_Rb_tree_const_iterator(std::_Rb_tree_iterator > const&)<00000000020b9810> -00000000020b9840 t std::map, std::allocator > >::begin()<00000000020b9840> -00000000020b9870 t std::_Rb_tree_const_iterator >::operator!=(std::_Rb_tree_const_iterator > const&) const<00000000020b9870> -00000000020b98a0 t std::_Rb_tree_const_iterator >::operator->() const<00000000020b98a0> -00000000020b98d0 t std::_Rb_tree_const_iterator >::operator++()<00000000020b98d0> -00000000020b9900 t std::_Rb_tree_iterator >::operator++()<00000000020b9900> -00000000020bb1d0 t std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_S_value(std::_Rb_tree_node_base const*)<00000000020bb1d0> -00000000020bb1f0 t std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::key_comp() const<00000000020bb1f0> -00000000020bb200 W std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::lower_bound(tracked_objects::BirthOnThread const* const&)<00000000020bb200> -00000000020bb250 W std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_lower_bound(std::_Rb_tree_node >*, std::_Rb_tree_node >*, tracked_objects::BirthOnThread const* const&)<00000000020bb250> -00000000020bb2f0 t std::pair const* std::__addressof const>(std::pair const&)<00000000020bb2f0> -00000000020bb300 t std::_Rb_tree_const_iterator >::_Rb_tree_const_iterator(std::_Rb_tree_iterator > const&)<00000000020bb300> -00000000020bb320 t std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::begin()<00000000020bb320> -00000000020bb360 t std::_Rb_tree_iterator >::_Rb_tree_iterator(std::_Rb_tree_node >*)<00000000020bb360> -00000000020bb390 t std::_Rb_tree_iterator >::_Rb_tree_iterator(std::_Rb_tree_node >*)<00000000020bb390> -00000000020bb3b0 t std::map, std::allocator > >::lower_bound(tracked_objects::Births const* const&)<00000000020bb3b0> -00000000020bb3e0 t std::_Rb_tree_iterator >::operator==(std::_Rb_tree_iterator > const&) const<00000000020bb3e0> -00000000020bb410 t std::map, std::allocator > >::key_comp() const<00000000020bb410> -00000000020bb430 t std::less::operator()(tracked_objects::Births const* const&, tracked_objects::Births const* const&) const<00000000020bb430> -00000000020bb460 t std::_Rb_tree_iterator >::operator*() const<00000000020bb460> -00000000020bb480 t std::map, std::allocator > >::insert(std::_Rb_tree_iterator >, std::pair const&)<00000000020bb480> -00000000020bb4d0 t std::pair::pair(tracked_objects::Births const* const&, tracked_objects::DeathData const&)<00000000020bb4d0> -00000000020bb500 W std::pair::pair(tracked_objects::Births const* const&, tracked_objects::DeathData const&)<00000000020bb500> -00000000020bb550 t std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_unique_(std::_Rb_tree_const_iterator >, std::pair const&)<00000000020bb550> -0000000002126100 t google::protobuf::RepeatedPtrField::RepeatedPtrField()<0000000002126100> -0000000002126120 t google::protobuf::RepeatedField::CopyArray(int*, int const*, int)<0000000002126120> -0000000002126160 t google::protobuf::RepeatedField::~RepeatedField()<0000000002126160> -00000000021261e0 t google::protobuf::RepeatedField::RepeatedField()<00000000021261e0> -0000000002126210 t void google::protobuf::internal::RepeatedPtrFieldBase::Clear::TypeHandler>()<0000000002126210> -0000000002126280 t google::protobuf::internal::GenericTypeHandler::Clear(chrome_variations::Study_Experiment*)<0000000002126280> -00000000021262a0 t chrome_variations::Study::set_has_default_experiment_name()<00000000021262a0> -00000000021262c0 t chrome_variations::Study::set_has_name()<00000000021262c0> -00000000021262e0 t chrome_variations::Study::set_has_filter()<00000000021262e0> -0000000002126300 t google::protobuf::RepeatedPtrField::Add()<0000000002126300> -0000000002126320 t chrome_variations::Study::set_has_consistency()<0000000002126320> -0000000002126340 t chrome_variations::Study_Filter::set_has_max_version()<0000000002126340> -0000000002126360 t chrome_variations::Study_Filter::set_has_min_version()<0000000002126360> -0000000002126380 t chrome_variations::Study_Experiment::set_has_name()<0000000002126380> -00000000021263a0 t __op_new_intercept__(void*, unsigned long, std::type_info const&)<00000000021263a0> -00000000021263e0 t __op_delete_intercept__(void*, unsigned long, std::type_info const&)<00000000021263e0> -0000000002126420 t base::type_profiler::InterceptFunctions::SetFunctions(void* (*)(void*, unsigned long, std::type_info const&), void* (*)(void*, unsigned long, std::type_info const&))<0000000002126420> -00000000021264c0 t (anonymous namespace)::NopIntercept(void*, unsigned long, std::type_info const&)<00000000021264c0> -00000000021264e0 t base::type_profiler::InterceptFunctions::ResetFunctions()<00000000021264e0> -0000000002126500 t base::type_profiler::InterceptFunctions::IsAvailable()<0000000002126500> -0000000002126540 t LibSpeechdLoader::LibSpeechdLoader() -0000000002126550 t LibSpeechdLoader::~LibSpeechdLoader() -0000000002126580 t LibSpeechdLoader::CleanUp(bool)<0000000002126580> -0000000002126610 t LibSpeechdLoader::Load(std::basic_string, std::allocator > const&)<0000000002126610> -00000000022d3c90 t WebCore::HTMLDocumentParser::stopBackgroundParser()<00000000022d3c90> -00000000022d3dd0 t WebCore::HTMLDocumentParser::stopParsing()<00000000022d3dd0> -00000000022d3e30 t WebCore::HTMLDocumentParser::prepareToStopParsing()<00000000022d3e30> -00000000022d4000 t WebCore::HTMLDocumentParser::pumpTokenizerIfPossible(WebCore::HTMLDocumentParser::SynchronousMode)<00000000022d4000> -00000000022d40d0 t WebCore::HTMLDocumentParser::attemptToRunDeferredScriptsAndEnd()<00000000022d40d0> -00000000022d4200 t WebCore::HTMLDocumentParser::isParsingFragment() const<00000000022d4200> -00000000022d4230 t WebCore::HTMLDocumentParser::processingData() const<00000000022d4230> -00000000022d62a0 t WebCore::HTMLDocumentParser::constructTreeFromHTMLToken(WebCore::HTMLToken&)<00000000022d62a0> -00000000022d63d0 t WebCore::HTMLDocumentParser::hasInsertionPoint()<00000000022d63d0> -00000000022d6450 t WebCore::HTMLDocumentParser::insert(WebCore::SegmentedString const&)<00000000022d6450> -00000000022d6c30 t WebCore::HTMLDocumentParser::attemptToEnd()<00000000022d6c30> -00000000022d6c80 t WebCore::HTMLDocumentParser::finish()<00000000022d6c80> -00000000022fca50 t WebCore::HTMLTreeBuilder::~HTMLTreeBuilder() -00000000022fcad0 t WebCore::HTMLTreeBuilder::detach()<00000000022fcad0> -00000000022fcb00 t WebCore::HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext() -00000000022fcb30 t WebCore::HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext(WebCore::DocumentFragment*, WebCore::Element*, WebCore::FragmentScriptingPermission) -00000000022fcbd0 t WebCore::HTMLTreeBuilder::FragmentParsingContext::~FragmentParsingContext() -00000000022fcbe0 t WebCore::HTMLTreeBuilder::takeScriptToProcess(WTF::TextPosition&)<00000000022fcbe0> -00000000022fccb0 t WebCore::HTMLTreeBuilder::constructTree(WebCore::AtomicHTMLToken*)<00000000022fccb0> -00000000022fce40 t WebCore::HTMLTreeBuilder::processTokenInForeignContent(WebCore::AtomicHTMLToken*)<00000000022fce40> -00000000022fd890 t WebCore::HTMLTreeBuilder::processToken(WebCore::AtomicHTMLToken*)<00000000022fd890> -00000000022fd9e0 t WebCore::HTMLTreeBuilder::processDoctypeToken(WebCore::AtomicHTMLToken*)<00000000022fd9e0> -00000000022fdad0 t WebCore::HTMLTreeBuilder::processStartTag(WebCore::AtomicHTMLToken*)<00000000022fdad0> -0000000002301910 t WebCore::HTMLTreeBuilder::processComment(WebCore::AtomicHTMLToken*)<0000000002301910> -0000000002301a70 t WebCore::HTMLTreeBuilder::processCharacter(WebCore::AtomicHTMLToken*)<0000000002301a70> -0000000002301b10 t WebCore::HTMLTreeBuilder::processEndOfFile(WebCore::AtomicHTMLToken*)<0000000002301b10> -0000000002306f60 t WebCore::HTMLTreeBuilder::processTableEndTagForInTable()<0000000002306f60> -0000000002307050 t WebCore::HTMLTreeBuilder::defaultForInitial()<0000000002307050> -00000000023070d0 t WebCore::HTMLTreeBuilder::defaultForBeforeHTML()<00000000023070d0> -0000000002307180 t WebCore::HTMLTreeBuilder::defaultForBeforeHead()<0000000002307180> -0000000002307210 t WebCore::HTMLTreeBuilder::defaultForInHead()<0000000002307210> -00000000023072a0 t WebCore::HTMLTreeBuilder::defaultForAfterHead()<00000000023072a0> -0000000002307330 t WebCore::HTMLTreeBuilder::processCaptionEndTagForInCaption()<0000000002307330> -0000000002346e20 t WebCore::HTMLConstructionSite::shouldFosterParent() const<0000000002346e20> -0000000002346e90 t WebCore::HTMLConstructionSite::fosterParent(WTF::PassRefPtr)<0000000002346e90> -0000000002346f60 t WebCore::HTMLConstructionSite::executeQueuedTasks()<0000000002346f60> -0000000002347030 t WebCore::executeTask(WebCore::HTMLConstructionSiteTask&)<0000000002347030> -0000000002347240 t WebCore::HTMLConstructionSite::HTMLConstructionSite(WebCore::Document*, unsigned int) -00000000023479f0 t WebCore::HTMLConstructionSite::setDefaultCompatibilityMode()<00000000023479f0> -0000000002347a50 t WebCore::HTMLConstructionSite::setCompatibilityMode(WebCore::Document::CompatibilityMode)<0000000002347a50> -0000000002347a90 t WebCore::HTMLConstructionSite::setCompatibilityModeFromDoctype(WTF::String const&, WTF::String const&, WTF::String const&)<0000000002347a90> -0000000002349a20 t WebCore::HTMLConstructionSite::findFosterSite(WebCore::HTMLConstructionSiteTask&)<0000000002349a20> -0000000002349c20 t WebCore::isAllWhitespace(WTF::String const&)<0000000002349c20> -0000000002349c40 t WebCore::HTMLConstructionSite::createElementFromSavedToken(WebCore::HTMLStackItem*)<0000000002349c40> -000000000246f060 t std::_Vector_base >::_Vector_impl::~_Vector_impl()<000000000246f060> -000000000246f080 t std::_Vector_base >::_Vector_impl::~_Vector_impl()<000000000246f080> -000000000246f0a0 t std::allocator::~allocator()<000000000246f0a0> -000000000246f0c0 t __gnu_cxx::new_allocator::~new_allocator()<000000000246f0c0> -000000000246f0d0 t std::pair::~pair()<000000000246f0d0> -000000000246f100 t std::pair::~pair()<000000000246f100> -000000000246f130 t std::map, std::allocator > >::~map()<000000000246f130> -000000000246f150 t std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::~_Rb_tree()<000000000246f150> -000000000246f170 t std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::~_Rb_tree()<000000000246f170> -000000000246f1b0 t std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_Rb_tree_impl, false>::~_Rb_tree_impl()<000000000246f1b0> -000000000246f1d0 t std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_Rb_tree_impl, false>::~_Rb_tree_impl()<000000000246f1d0> -000000000246f1f0 t std::allocator > >::~allocator()<000000000246f1f0> -000000000246f210 t __gnu_cxx::new_allocator > >::~new_allocator()<000000000246f210> -000000000246f220 t gpu::gles2::CachedProgramInfoManager::ProgramInfo::UniformInfo::~UniformInfo()<000000000246f220> -000000000246f260 t gpu::gles2::CachedProgramInfoManager::ProgramInfo::VertexAttribInfo::~VertexAttribInfo()<000000000246f260> -000000000246f290 t gpu::gles2::CachedProgramInfoManager::ProgramInfo::VertexAttribInfo::VertexAttribInfo(int, unsigned int, std::basic_string, std::allocator > const&, int)<000000000246f290> -000000000246f2e0 t InsertType(void*, unsigned long, std::type_info const&)<000000000246f2e0> -000000000246f360 t (anonymous namespace)::InitializeTypeProfilerMemory()<000000000246f360> -000000000246f450 t AddressMap<(anonymous namespace)::ObjectInfo>::Insert(void const*, (anonymous namespace)::ObjectInfo)<000000000246f450> -000000000246f5f0 t EraseType(void*)<000000000246f5f0> -000000000246fd30 t global constructors keyed to a<000000000246fd30> -000000000246fd40 t GURL::GURL() -000000000246fd80 t GURL::GURL(GURL const&) -00000000031755b0 t WebCore::ScriptController::clearForOutOfMemory()<00000000031755b0> -00000000031755d0 t WebCore::ScriptController::clearForClose()<00000000031755d0> -0000000003175640 t WebCore::ScriptController::updateSecurityOrigin()<0000000003175640> -0000000003175670 t WebCore::ScriptController::updatePlatformScriptObjects()<0000000003175670> -00000000031756d0 t WebCore::ScriptController::processingUserGesture()<00000000031756d0> -00000000031756e0 t WebCore::ScriptController::callFunction(v8::Handle, v8::Handle, int, v8::Handle*)<00000000031756e0> -00000000031757d0 t WebCore::ScriptController::callFunctionWithInstrumentation(WebCore::ScriptExecutionContext*, v8::Handle, v8::Handle, int, v8::Handle*)<00000000031757d0> -0000000003175a80 t WebCore::resourceInfo(v8::Handle, WTF::String&, int&)<0000000003175a80> -00000000031c3b90 t WebCore::V8LazyEventListener::prepareListenerObject(WebCore::ScriptExecutionContext*)<00000000031c3b90> -000000000321a0c0 t WebCore::CSSParser::parseSheet(WebCore::StyleSheetContents*, WTF::String const&, int, WTF::Vector, 0ul>*)<000000000321a0c0> -000000000321a220 t WebCore::CSSParser::parseRule(WebCore::StyleSheetContents*, WTF::String const&)<000000000321a220> -000000000321a2b0 t WebCore::CSSParser::parseKeyframeRule(WebCore::StyleSheetContents*, WTF::String const&)<000000000321a2b0> -000000000321a330 t WebCore::CSSParser::parseFontFaceValue(WTF::AtomicString const&)<000000000321a330> -000000000321a450 t WebCore::CSSParser::parseValue(WebCore::StylePropertySet*, WebCore::CSSPropertyID, WTF::String const&, bool, WebCore::CSSParserMode, WebCore::StyleSheetContents*)<000000000321a450> -000000000327e070 t void WTF::Vector::insert(unsigned long, WebCore::CSSParserValue const&)<000000000327e070> -000000000327e220 t WTF::Vector::remove(unsigned long)<000000000327e220> -000000000327e2f0 t WebCore::CSSPrimitiveValue::createIdentifier(int)<000000000327e2f0> -000000000327e360 t WebCore::CSSPrimitiveValue::setPrimitiveType(unsigned short)<000000000327e360> -000000000327e3b0 t WTF::PassRefPtr::PassRefPtr(WTF::PassRefPtr const&)<000000000327e3b0> -000000000327e3e0 t WebCore::CSSFunctionValue::create(WebCore::CSSParserFunction*)<000000000327e3e0> -000000000327e450 t WTF::PassRefPtr::~PassRefPtr()<000000000327e450> -000000000327e470 t WebCore::CSSPrimitiveValue::create(double, WebCore::CSSPrimitiveValue::UnitTypes)<000000000327e470> -000000000327e4f0 t WTF::OwnPtr::OwnPtr(WTF::PassOwnPtr const&)<000000000327e4f0> -000000000327e520 t WTF::PassOwnPtr WTF::adoptPtr(WebCore::CSSSelector*)<000000000327e520> -000000000327e550 t WebCore::CSSSelector* WTF::fastNew()<000000000327e550> -000000000327e610 t WTF::PassOwnPtr::~PassOwnPtr()<000000000327e610> -00000000032a2b80 t WebCore::CSSValuePool::createIdentifierValue(int)<00000000032a2b80> -00000000032a2c70 t WebCore::CSSValuePool::createColorValue(unsigned int)<00000000032a2c70> -00000000032a2e20 t WebCore::CSSValuePool::createValue(double, WebCore::CSSPrimitiveValue::UnitTypes)<00000000032a2e20> -00000000032d7bb0 t WebCore::StylePropertyShorthand::StylePropertyShorthand(WebCore::CSSPropertyID const*, WebCore::StylePropertyShorthand const**, unsigned int)<00000000032d7bb0> -00000000032d7bf0 t WebCore::StylePropertyShorthand::StylePropertyShorthand()<00000000032d7bf0> -00000000032d7c10 t WebCore::StylePropertyShorthand::StylePropertyShorthand()<00000000032d7c10> -00000000032d7c40 t WebCore::StylePropertyShorthand::StylePropertyShorthand(WebCore::CSSPropertyID const*, WebCore::StylePropertyShorthand const**, unsigned int)<00000000032d7c40> -00000000032d7c80 t WebCore::StyleResolver::StyleResolver(WebCore::Document*, bool) -00000000032d8ae0 t WebCore::StyleResolver::appendAuthorStyleSheets(unsigned int, WTF::Vector, 0ul> const&)<00000000032d8ae0> -00000000032d8c10 t WebCore::StyleResolver::pushParentElement(WebCore::Element*)<00000000032d8c10> -0000000003341c70 t WebCore::StyleSheetContents::parseString(WTF::String const&)<0000000003341c70> -0000000003341ca0 t WebCore::StyleSheetContents::parseStringAtLine(WTF::String const&, int)<0000000003341ca0> -0000000003341d50 t WebCore::StyleSheetContents::isLoading() const<0000000003341d50> -0000000003341e00 t WebCore::StyleSheetContents::checkLoaded()<0000000003341e00> -0000000003341f90 t WebCore::StyleSheetContents::parentStyleSheet() const<0000000003341f90> -00000000034e56b0 t WebCore::DocumentLoader::commitData(char const*, unsigned long)<00000000034e56b0> -00000000034e5980 t WebCore::DocumentLoader::commitLoad(char const*, int)<00000000034e5980> -00000000034e5a90 t WebCore::DocumentLoader::documentURL() const<00000000034e5a90> -00000000034e5b60 t WebCore::DocumentLoader::isMultipartReplacingLoad() const<00000000034e5b60> -00000000034e5bb0 t WebCore::DocumentLoader::reportMemoryUsage(WTF::MemoryObjectInfo*) const<00000000034e5bb0> -00000000035008b0 t WebCore::canReferToParentFrameEncoding(WebCore::Frame const*, WebCore::Frame const*)<00000000035008b0> -0000000003500930 t WebCore::DocumentWriter::reportDataReceived()<0000000003500930> -0000000003500a20 t WebCore::DocumentWriter::addData(char const*, unsigned long)<0000000003500a20> -0000000003500b30 t WebCore::DocumentWriter::setEncoding(WTF::String const&, bool)<0000000003500b30> -0000000003500b80 t WebCore::DocumentWriter::setDocumentWasLoadedAsPartOfNavigation()<0000000003500b80> -0000000003500c40 t WTF::RefPtr::RefPtr()<0000000003500c40> -0000000003500c60 t WTF::RefPtr::operator=(WebCore::TextResourceDecoder*)<0000000003500c60> -0000000003500cb0 t WebCore::PluginDocument::create(WebCore::Frame*, WebCore::KURL const&)<0000000003500cb0> -0000000003500d30 t WTF::PassRefPtr::~PassRefPtr()<0000000003500d30> -0000000003500d50 t WTF::PassRefPtr::PassRefPtr(WTF::PassRefPtr const&)<0000000003500d50> -0000000003500d80 t WebCore::PlaceholderDocument::create(WebCore::Frame*, WebCore::KURL const&)<0000000003500d80> -0000000003500e00 t WTF::PassRefPtr::~PassRefPtr()<0000000003500e00> -0000000003500e20 t WTF::RefPtr& WTF::RefPtr::operator=(WTF::PassRefPtr const&)<0000000003500e20> -00000000035f6c90 t WTF::PassRefPtr::get() const<00000000035f6c90> -00000000035f6ca0 t bool WTF::operator!=(WTF::RefPtr const&, WTF::RefPtr const&)<00000000035f6ca0> -00000000035f6ce0 t WebCore::Page::shouldSuppressScrollbarAnimations() const<00000000035f6ce0> -00000000035f6d00 t WebCore::ElementTraversal::firstWithin(WebCore::Node const*)<00000000035f6d00> -00000000035f6d20 t WebCore::FocusCandidate::FocusCandidate()<00000000035f6d20> -00000000035f6d40 t WebCore::FocusCandidate::isNull() const<00000000035f6d40> -00000000035f6d60 t WTF::PassOwnPtr::PassOwnPtr(WebCore::FocusController*)<00000000035f6d60> -00000000035f6d90 t WTF::PassOwnPtr::PassOwnPtr(WebCore::FocusController*)<00000000035f6d90> -00000000035f6db0 t WebCore::maxDistance()<00000000035f6db0> -00000000035f6dc0 t WebCore::FocusCandidate::FocusCandidate()<00000000035f6dc0> -00000000035f6e40 t WebCore::Element* WebCore::ElementTraversal::firstElementWithinTemplate(WebCore::Node const*)<00000000035f6e40> -00000000035f6eb0 t WebCore::Frame::create(WebCore::Page*, WebCore::HTMLFrameOwnerElement*, WebCore::FrameLoaderClient*)<00000000035f6eb0> -00000000035f6fa0 t WebCore::Frame::~Frame() -00000000035f71b0 t WebCore::Frame::setView(WTF::PassRefPtr)<00000000035f71b0> -00000000035fb390 t WebCore::parentFromOwnerElement(WebCore::HTMLFrameOwnerElement*)<00000000035fb390> -00000000035fb3e0 t WebCore::parentPageZoomFactor(WebCore::Frame*)<00000000035fb3e0> -00000000035fb450 t WebCore::parentTextZoomFactor(WebCore::Frame*)<00000000035fb450> -00000000035fb4c0 t __cxx_global_var_init<00000000035fb4c0> -00000000035fb510 t global constructors keyed to a<00000000035fb510> -00000000035fb520 t WTF::RefCounted::operator new(unsigned long)<00000000035fb520> -00000000035fb560 t WebCore::Frame::Frame(WebCore::Page*, WebCore::HTMLFrameOwnerElement*, WebCore::FrameLoaderClient*)<00000000035fb560> -00000000035fb5a0 t WTF::HashSet, WTF::HashTraits >::end() const<00000000035fb5a0> -00000000035fb5f0 t WTF::HashSet, WTF::HashTraits >::begin() const<00000000035fb5f0> -00000000035fb640 t bool WTF::operator!=, WTF::HashTraits, WTF::HashTraits >, WebCore::FrameDestructionObserver*>(WTF::HashTableConstIteratorAdapter, WTF::HashTraits, WTF::HashTraits >, WebCore::FrameDestructionObserver*> const&, WTF::HashTableConstIteratorAdapter, WTF::HashTraits, WTF::HashTraits >, WebCore::FrameDestructionObserver*> const&)<00000000035fb640> -00000000035fb670 t WTF::HashTableConstIteratorAdapter, WTF::HashTraits, WTF::HashTraits >, WebCore::FrameDestructionObserver*>::operator*() const<00000000035fb670> -00000000035fb690 t WTF::HashTableConstIteratorAdapter, WTF::HashTraits, WTF::HashTraits >, WebCore::FrameDestructionObserver*>::operator++()<00000000035fb690> -00000000035fb6c0 t WTF::HashTableConstIteratorAdapter, WTF::HashTraits, WTF::HashTraits >, WebCore::FrameDestructionObserver*>::~HashTableConstIteratorAdapter()<00000000035fb6c0> -00000000035fb6e0 t WTF::HashSet, WTF::HashTraits >::~HashSet()<00000000035fb6e0> -00000000035fb700 t WTF::RefCounted::~RefCounted()<00000000035fb700> -00000000035fb720 t WTF::HashSet, WTF::HashTraits >::add(WebCore::FrameDestructionObserver* const&)<00000000035fb720> -00000000035fb750 t WTF::HashTableAddResult, WTF::HashTraits, WTF::HashTraits > >::~HashTableAddResult()<00000000035fb750> -00000000035fb770 t WTF::HashSet, WTF::HashTraits >::remove(WebCore::FrameDestructionObserver* const&)<00000000035fb770> -00000000035fb7c0 t WTF::PassRefPtr::operator!() const<00000000035fb7c0> -00000000035fb7e0 t WTF::RefPtr::operator=(WTF::PassRefPtr const&)<00000000035fb7e0> -00000000035fb830 t WTF::PassRefPtr::operator!() const<00000000035fb830> -00000000035fb850 t WTF::PassRefPtr::operator->() const<00000000035fb850> -00000000035fb860 t WTF::RefPtr::operator=(WTF::PassRefPtr const&)<00000000035fb860> -0000000003600630 t WTF::PassOwnPtr::PassOwnPtr(WebCore::RegularExpression*)<0000000003600630> -0000000003600650 t WTF::HashTableAddResult, WTF::HashTraits, WTF::HashTraits > >::~HashTableAddResult()<0000000003600650> -0000000003600670 t WTF::HashSet, WTF::HashTraits >::~HashSet()<0000000003600670> -0000000003600690 t WTF::HashTable, WTF::HashTraits, WTF::HashTraits >::~HashTable()<0000000003600690> -00000000036006b0 t WTF::HashTable, WTF::HashTraits, WTF::HashTraits >::~HashTable()<00000000036006b0> -0000000003600710 t WTF::HashTableConstIteratorAdapter, WTF::HashTraits, WTF::HashTraits >, WebCore::FrameDestructionObserver*>::~HashTableConstIteratorAdapter()<0000000003600710> -0000000003600730 t WebCore::Frame::Frame(WebCore::Page*, WebCore::HTMLFrameOwnerElement*, WebCore::FrameLoaderClient*)<0000000003600730> -00000000036009a0 t WTF::RefCounted::RefCounted()<00000000036009a0> -00000000036009c0 t WTF::HashSet, WTF::HashTraits >::HashSet()<00000000036009c0> -00000000036009e0 t WebCore::FrameTree::FrameTree(WebCore::Frame*, WebCore::Frame*)<00000000036009e0> -0000000003600a10 t WebCore::Page::incrementSubframeCount()<0000000003600a10> -0000000003600a30 t WebCore::FrameTree::FrameTree(WebCore::Frame*, WebCore::Frame*)<0000000003600a30> -0000000003600ad0 t WTF::HashSet, WTF::HashTraits >::HashSet()<0000000003600ad0> -0000000003600af0 t WTF::HashTable, WTF::HashTraits, WTF::HashTraits >::HashTable()<0000000003600af0> -0000000003600b10 t WTF::HashTable, WTF::HashTraits, WTF::HashTraits >::HashTable()<0000000003600b10> -0000000003600bc0 t WebCore::FrameDestructionObserver::FrameDestructionObserver(WebCore::Frame*) -00000000037a4cf0 t WebCore::V8AbstractEventListener::handleEvent(WebCore::ScriptExecutionContext*, WebCore::Event*)<00000000037a4cf0> -00000000037a4f80 t WebCore::V8AbstractEventListener::invokeEventHandler(WebCore::ScriptExecutionContext*, WebCore::Event*, v8::Handle)<00000000037a4f80> -00000000037f8920 t WTF::RefPtr >::operator!() const<00000000037f8920> -00000000037f8940 t WTF::RefPtr >::operator->() const<00000000037f8940> -00000000037f8950 t WebCore::SVGPropertyTearOff::propertyReference()<00000000037f8950> -00000000037f8960 t WebCore::SVGAnimatedPropertyTearOff* WebCore::SVGAnimatedProperty::lookupWrapper >(WebCore::SVGCursorElement*, WebCore::SVGPropertyInfo const*)<00000000037f8960> -00000000037f8a00 t WTF::HashSet, WTF::HashTraits >::~HashSet()<00000000037f8a00> -00000000037f8a20 t WTF::HashTable, WTF::HashTraits, WTF::HashTraits >::~HashTable()<00000000037f8a20> -00000000037f8a40 t WTF::HashTable, WTF::HashTraits, WTF::HashTraits >::~HashTable()<00000000037f8a40> -00000000037f8aa0 t WTF::HashTableConstIteratorAdapter, WTF::HashTraits, WTF::HashTraits >, WebCore::SVGElement*>::~HashTableConstIteratorAdapter()<00000000037f8aa0> -00000000037f8ac0 t WTF::HashSet, WTF::HashTraits >::HashSet()<00000000037f8ac0> -00000000037f8ae0 t WTF::HashTable, WTF::HashTraits, WTF::HashTraits >::HashTable()<00000000037f8ae0> -00000000037f8b00 t WTF::HashTable, WTF::HashTraits, WTF::HashTraits >::HashTable()<00000000037f8b00> -00000000037f8bb0 t WebCore::CSSDefaultStyleSheets::initDefaultStyle(WebCore::Element*)<00000000037f8bb0> -00000000037f8c10 t WebCore::elementCanUseSimpleDefaultStyle(WebCore::Element*)<00000000037f8c10> -00000000037f8cf0 t WebCore::CSSDefaultStyleSheets::loadSimpleDefaultStyle()<00000000037f8cf0> -00000000037f8e70 t WebCore::CSSDefaultStyleSheets::loadFullDefaultStyle()<00000000037f8e70> -0000000003857250 t WebCore::RuleSet::addRulesFromSheet(WebCore::StyleSheetContents*, WebCore::MediaQueryEvaluator const&, WebCore::StyleResolver*, WebCore::ContainerNode const*)<0000000003857250> -0000000003857480 t WebCore::RuleSet::shrinkToFit()<0000000003857480> -0000000003857520 t WebCore::shrinkMapVectorsToFit(WTF::HashMap >, WTF::PtrHash, WTF::HashTraits, WTF::HashTraits > > >&)<0000000003857520> -00000000038575c0 t WebCore::isCommonAttributeSelectorAttribute(WebCore::QualifiedName const&)<00000000038575c0> -0000000003857610 t WebCore::selectorListContainsUncommonAttributeSelector(WebCore::CSSSelector const*)<0000000003857610> -00000000038576d0 t WTF::MemoryClassInfo::MemoryClassInfo(WTF::MemoryObjectInfo*, WebCore::RuleData const*, char const*, unsigned long)<00000000038576d0> -0000000003857710 t WTF::MemoryClassInfo::MemoryClassInfo(WTF::MemoryObjectInfo*, WebCore::RuleSet const*, char const*, unsigned long)<0000000003857710> -0000000003857750 t void WTF::MemoryClassInfo::addMember >, WTF::PtrHash, WTF::HashTraits, WTF::HashTraits > > > >(WTF::HashMap >, WTF::PtrHash, WTF::HashTraits, WTF::HashTraits > > > const&, char const*)<0000000003857750> -0000000003857da0 t WebCore::RuleSet::RuleSetSelectorPair::RuleSetSelectorPair(WebCore::CSSSelector const*, WTF::PassOwnPtr)<0000000003857da0> -0000000003857dd0 t WebCore::StyleResolver::ruleSets()<0000000003857dd0> -0000000003857de0 t WebCore::CSSSelectorList::indexOfNextSelectorAfter(unsigned long) const<0000000003857de0> -0000000003857e60 t WTF::PassRefPtr::PassRefPtr(WebCore::StyleRuleKeyframes*)<0000000003857e60> -0000000003857e90 t WebCore::StyleRuleBase::isHostRule() const<0000000003857e90> -0000000003857ec0 t WebCore::StyleResolver::addHostRule(WebCore::StyleRuleHost*, bool, WebCore::ContainerNode const*)<0000000003857ec0> -0000000003857f10 t WebCore::StyleSheetContents::importRules() const<0000000003857f10> -0000000003857f30 t WebCore::StyleSheetContents::childRules() const<0000000003857f30> -0000000003857f50 t WTF::Vector::shrinkToFit()<0000000003857f50> -0000000003857f80 t WTF::Vector::shrinkToFit()<0000000003857f80> -0000000003857fb0 t WTF::Vector::shrinkCapacity(unsigned long)<0000000003857fb0> -0000000003858110 t WTF::VectorBufferBase::shouldReallocateBuffer(unsigned long) const<0000000003858110> -0000000003858150 t WTF::VectorBufferBase::reallocateBuffer(unsigned long)<0000000003858150> -0000000003858250 t WTF::VectorBuffer::restoreInlineBufferIfNeeded()<0000000003858250> -0000000003858260 t WTF::Vector::shrinkCapacity(unsigned long)<0000000003858260> -0000000003b70db0 t WebCore::ContainerNode::~ContainerNode()<0000000003b70db0> -0000000003b70de0 t WebCore::ContainerNode::~ContainerNode() -0000000003b70e90 t WebCore::ContainerNode::insertBefore(WTF::PassRefPtr, WebCore::Node*, int&, bool)<0000000003b70e90> -0000000003b80ce0 t void std::make_heap(WTF::String*, WTF::String*, bool (*)(WTF::String const&, WTF::String const&))<0000000003b80ce0> -0000000003b80e10 t WebCore::DecodedDataDocumentParser::DecodedDataDocumentParser(WebCore::Document*)<0000000003b80e10> -0000000003b80e60 t WebCore::DecodedDataDocumentParser::appendBytes(WebCore::DocumentWriter*, char const*, unsigned long)<0000000003b80e60> -0000000003b80f70 t WebCore::DecodedDataDocumentParser::flush(WebCore::DocumentWriter*)<0000000003b80f70> -0000000003b81050 t WebCore::DecodedDataDocumentParser::~DecodedDataDocumentParser()<0000000003b81050> -0000000003b81070 t WebCore::DecodedDataDocumentParser::~DecodedDataDocumentParser()<0000000003b81070> -0000000003b810a0 t WebCore::DeviceMotionController::DeviceMotionController(WebCore::DeviceMotionClient*) -0000000003b81160 t WebCore::DeviceMotionController::deviceMotionClient()<0000000003b81160> -0000000003b81180 t WebCore::DeviceMotionController::create(WebCore::DeviceMotionClient*)<0000000003b81180> -0000000003b811f0 t WebCore::DeviceMotionController::didChangeDeviceMotion(WebCore::DeviceMotionData*)<0000000003b811f0> -0000000003b8d570 t WebCore::Document::haveStylesheetsLoaded() const<0000000003b8d570> -0000000003b8d5d0 t WebCore::Document::body() const<0000000003b8d5d0> -0000000003b8d6c0 t WebCore::Document::styleForElementIgnoringPendingStylesheets(WebCore::Element*)<0000000003b8d6c0> -0000000003b8d850 t WebCore::Document::styleForPage(int)<0000000003b8d850> -0000000003b8d8d0 t WebCore::Document::isPageBoxVisible(int)<0000000003b8d8d0> -0000000003b8d950 t WebCore::Document::pageSizeAndMarginsInPixels(int, WebCore::IntSize&, int&, int&, int&, int&)<0000000003b8d950> -0000000003b8e000 t WebCore::Document::setIsViewSource(bool)<0000000003b8e000> -0000000003b8e080 t WebCore::Document::createStyleResolver()<0000000003b8e080> -0000000003b8e160 t WebCore::Document::attach()<0000000003b8e160> -0000000003b8e400 t WebCore::Document::topDocument() const<0000000003b8e400> -0000000003bfd150 t WebCore::Element::setSavedLayerScrollOffset(WebCore::IntSize const&)<0000000003bfd150> -0000000003bfd1c0 t WebCore::Element::createRendererIfNeeded()<0000000003bfd1c0> -0000000003bfd200 t WebCore::Element::attach()<0000000003bfd200> -0000000003bfd3f0 t WebCore::Element::isInCanvasSubtree() const<0000000003bfd3f0> -0000000003bfd450 t WebCore::Element::setIsInCanvasSubtree(bool)<0000000003bfd450> -0000000003bfd490 t WebCore::Element::updatePseudoElement(WebCore::PseudoId, WebCore::Node::StyleChange)<0000000003bfd490> -0000000003bfdc90 t WebCore::Element::styleForRenderer()<0000000003bfdc90> -0000000003bfddc0 t WebCore::Element::recalcStyle(WebCore::Node::StyleChange)<0000000003bfddc0> -0000000003c00cd0 t WebCore::Element::outerText()<0000000003c00cd0> -0000000003c00d00 t WebCore::Element::title() const<0000000003c00d00> -0000000003c00d30 t WebCore::Element::setPseudo(WTF::AtomicString const&)<0000000003c00d30> -0000000003c00d60 t WebCore::Element::minimumSizeForResizing() const<0000000003c00d60> -0000000003c00de0 t WebCore::Element::setMinimumSizeForResizing(WebCore::LayoutSize const&)<0000000003c00de0> -0000000003c00e80 t WebCore::Element::computedStyle(WebCore::PseudoId)<0000000003c00e80> -0000000003c01000 t WebCore::Element::setStyleAffectedByEmpty()<0000000003c01000> -0000000003c01030 t WebCore::Element::setChildrenAffectedByHover(bool)<0000000003c01030> -0000000003c01090 t WebCore::Element::setChildrenAffectedByActive(bool)<0000000003c01090> -0000000003c010f0 t WebCore::Element::setChildrenAffectedByDrag(bool)<0000000003c010f0> -0000000003c01150 t WebCore::Element::setChildrenAffectedByFirstChildRules()<0000000003c01150> -0000000003c01180 t WebCore::Element::setChildrenAffectedByLastChildRules()<0000000003c01180> -0000000003c011b0 t WebCore::Element::setChildrenAffectedByDirectAdjacentRules()<0000000003c011b0> -0000000003c011e0 t WebCore::Element::setChildrenAffectedByForwardPositionalRules()<0000000003c011e0> -0000000003c01210 t WebCore::Element::setChildrenAffectedByBackwardPositionalRules()<0000000003c01210> -0000000003c01240 t WebCore::Element::setChildIndex(unsigned int)<0000000003c01240> -0000000003c14980 t WebCore::shadowOfParent(WebCore::Node const*)<0000000003c14980> -0000000003c14a10 t WebCore::EventTargetData::EventTargetData() -0000000003c14a40 t WebCore::EventTargetData::~EventTargetData() -0000000003c14a80 t WebCore::EventTarget::~EventTarget()<0000000003c14a80> -0000000003c14ab0 t WebCore::EventTarget::~EventTarget() -0000000003c14ac0 t WebCore::EventTarget::toNode()<0000000003c14ac0> -0000000003c14ad0 t WebCore::EventTarget::toDOMWindow()<0000000003c14ad0> -0000000003c14ae0 t WebCore::EventTarget::addEventListener(WTF::AtomicString const&, WTF::PassRefPtr, bool)<0000000003c14ae0> -0000000003c14b80 t WebCore::EventTarget::removeEventListener(WTF::AtomicString const&, WebCore::EventListener*, bool)<0000000003c14b80> -0000000003c14d20 t WebCore::EventTarget::setAttributeEventListener(WTF::AtomicString const&, WTF::PassRefPtr)<0000000003c14d20> -0000000003c14de0 t WebCore::EventTarget::clearAttributeEventListener(WTF::AtomicString const&)<0000000003c14de0> -0000000003c15520 t WebCore::EventTarget::uncaughtExceptionInEventHandler()<0000000003c15520> -0000000003c15530 t WebCore::prefixedType(WebCore::Event const*)<0000000003c15530> -0000000003c155c0 t WebCore::EventTarget::fireEventListeners(WebCore::Event*, WebCore::EventTargetData*, WTF::Vector&)<0000000003c155c0> -0000000003c45e70 t WebCore::Node::mutationObserverRegistry()<0000000003c45e70> -0000000003c45ee0 t WebCore::Node::addEventListener(WTF::AtomicString const&, WTF::PassRefPtr, bool)<0000000003c45ee0> -0000000003c45f50 t WebCore::tryAddEventListener(WebCore::Node*, WTF::AtomicString const&, WTF::PassRefPtr, bool)<0000000003c45f50> -0000000003c46070 t WebCore::Node::removeEventListener(WTF::AtomicString const&, WebCore::EventListener*, bool)<0000000003c46070> -0000000003c460b0 t WebCore::tryRemoveEventListener(WebCore::Node*, WTF::AtomicString const&, WebCore::EventListener*, bool)<0000000003c460b0> -0000000003c461a0 t WebCore::Node::eventTargetData()<0000000003c461a0> -0000000003c46210 t WebCore::eventTargetDataMap()<0000000003c46210> -0000000003c46d10 t WebCore::Node::handleLocalEvents(WebCore::Event*)<0000000003c46d10> -0000000003c46da0 t WebCore::Node::dispatchScopedEvent(WTF::PassRefPtr)<0000000003c46da0> -0000000003c46e00 t WebCore::Node::dispatchScopedEventDispatchMediator(WTF::PassRefPtr)<0000000003c46e00> -0000000003c46e40 t WebCore::Node::dispatchEvent(WTF::PassRefPtr)<0000000003c46e40> -0000000003c46f30 t WebCore::Node::dispatchSubtreeModifiedEvent()<0000000003c46f30> -0000000003c4aa30 t WTF::Vector, 0ul>::size() const<0000000003c4aa30> -0000000003c4aa40 t WebCore::Document::addMutationObserverTypes(unsigned char)<0000000003c4aa40> -0000000003c4aa70 t WTF::Vector, 0ul>::at(unsigned long)<0000000003c4aa70> -0000000003c4ab20 t WTF::OwnPtr::operator->() const<0000000003c4ab20> -0000000003c4aba0 t WebCore::MutationObserverRegistration::mutationTypes() const<0000000003c4aba0> -0000000003c4abc0 t WTF::HashMap, WTF::PtrHash, WTF::HashTraits, WTF::HashTraits > >::get(WebCore::Node* const&) const<0000000003c4abc0> -0000000003c4ac30 t WebCore::Node::setHasEventTargetData(bool)<0000000003c4ac30> -0000000003c4ac60 t WebCore::EventTargetData::operator new(unsigned long)<0000000003c4ac60> -0000000003c4aca0 t WTF::HashMap, WTF::PtrHash, WTF::HashTraits, WTF::HashTraits > >::set(WebCore::Node* const&, WTF::PassOwnPtr)<0000000003c4aca0> -0000000003c4ad40 t WTF::PassOwnPtr WTF::adoptPtr(WebCore::EventTargetData*)<0000000003c4ad40> -0000000003c4ad70 t WTF::HashTableAddResult >, WTF::KeyValuePairKeyExtractor > >, WTF::PtrHash, WTF::HashMapValueTraits, WTF::HashTraits > >, WTF::HashTraits > >::~HashTableAddResult()<0000000003c4ad70> -0000000003c4ad90 t WTF::PassOwnPtr::~PassOwnPtr()<0000000003c4ad90> -0000000003c4adb0 t WTF::HashMap, WTF::PtrHash, WTF::HashTraits, WTF::HashTraits > >::remove(WebCore::Node* const&)<0000000003c4adb0> -0000000003c4ae00 t WebCore::NodeRareData::mutationObserverData()<0000000003c4ae00> -0000000003c4ae30 t WebCore::NodeRareData::ensureMutationObserverData()<0000000003c4ae30> -0000000003c4aeb0 t WTF::Vector, 0ul>::operator[](unsigned long)<0000000003c4aeb0> -0000000003c4aee0 t WebCore::MutationObserverRegistration::observer() const<0000000003c4aee0> -0000000003c4af00 t WTF::OwnPtr::get() const<0000000003c4af00> -0000000003c4af10 t void WTF::Vector, 0ul>::append >(WTF::PassOwnPtr const&)<0000000003c4af10> -0000000003c4afc0 t WTF::PassRefPtr::PassRefPtr(WebCore::MutationObserver*)<0000000003c4afc0> -0000000003c4fe80 t WTF::HashTable >, WTF::KeyValuePairKeyExtractor > >, WTF::PtrHash, WTF::HashMapValueTraits, WTF::HashTraits > >, WTF::HashTraits >::internalCheckTableConsistency()<0000000003c4fe80> -0000000003c4fe90 t WTF::HashTable >, WTF::KeyValuePairKeyExtractor > >, WTF::PtrHash, WTF::HashMapValueTraits, WTF::HashTraits > >, WTF::HashTraits >::removeWithoutEntryConsistencyCheck(WTF::HashTableIterator >, WTF::KeyValuePairKeyExtractor > >, WTF::PtrHash, WTF::HashMapValueTraits, WTF::HashTraits > >, WTF::HashTraits >)<0000000003c4fe90> -0000000003c4ff00 t WTF::HashTable >, WTF::KeyValuePairKeyExtractor > >, WTF::PtrHash, WTF::HashMapValueTraits, WTF::HashTraits > >, WTF::HashTraits >::removeAndInvalidateWithoutEntryConsistencyCheck(WTF::KeyValuePair >*)<0000000003c4ff00> -0000000003c4ff40 t WTF::HashTable >, WTF::KeyValuePairKeyExtractor > >, WTF::PtrHash, WTF::HashMapValueTraits, WTF::HashTraits > >, WTF::HashTraits >::invalidateIterators()<0000000003c4ff40> -0000000003c4fff0 t WTF::HashTable >, WTF::KeyValuePairKeyExtractor > >, WTF::PtrHash, WTF::HashMapValueTraits, WTF::HashTraits > >, WTF::HashTraits >::remove(WTF::KeyValuePair >*)<0000000003c4fff0> -0000000003c50060 t WTF::HashTable >, WTF::KeyValuePairKeyExtractor > >, WTF::PtrHash, WTF::HashMapValueTraits, WTF::HashTraits > >, WTF::HashTraits >::deleteBucket(WTF::KeyValuePair >&)<0000000003c50060> -0000000003c50090 t WTF::HashTable >, WTF::KeyValuePairKeyExtractor > >, WTF::PtrHash, WTF::HashMapValueTraits, WTF::HashTraits > >, WTF::HashTraits >::shouldShrink() const<0000000003c50090> -0000000003c500e0 t WTF::HashTable >, WTF::KeyValuePairKeyExtractor > >, WTF::PtrHash, WTF::HashMapValueTraits, WTF::HashTraits > >, WTF::HashTraits >::shrink()<0000000003c500e0> -0000000003c50110 t WTF::HashTable >, WTF::KeyValuePairKeyExtractor > >, WTF::PtrHash, WTF::HashMapValueTraits, WTF::HashTraits > >, WTF::HashTraits >::rehash(int)<0000000003c50110> -0000000003c501f0 t WTF::HashTable >, WTF::KeyValuePairKeyExtractor > >, WTF::PtrHash, WTF::HashMapValueTraits, WTF::HashTraits > >, WTF::HashTraits >::internalCheckTableConsistencyExceptSize()<0000000003c501f0> -0000000003c50200 t WTF::HashTable >, WTF::KeyValuePairKeyExtractor > >, WTF::PtrHash, WTF::HashMapValueTraits, WTF::HashTraits > >, WTF::HashTraits >::allocateTable(int)<0000000003c50200> -0000000003c50230 t WTF::HashTable >, WTF::KeyValuePairKeyExtractor > >, WTF::PtrHash, WTF::HashMapValueTraits, WTF::HashTraits > >, WTF::HashTraits >::isEmptyOrDeletedBucket(WTF::KeyValuePair > const&)<0000000003c50230> -0000000003c50270 t WTF::HashTable >, WTF::KeyValuePairKeyExtractor > >, WTF::PtrHash, WTF::HashMapValueTraits, WTF::HashTraits > >, WTF::HashTraits >::reinsert(WTF::KeyValuePair >&)<0000000003c50270> -0000000003c50400 t WTF::HashTable >, WTF::KeyValuePairKeyExtractor > >, WTF::PtrHash, WTF::HashMapValueTraits, WTF::HashTraits > >, WTF::HashTraits >::deallocateTable(WTF::KeyValuePair >*, int)<0000000003c50400> -0000000003c50ab0 t WTF::PassOwnPtr::~PassOwnPtr()<0000000003c50ab0> -0000000003c50ad0 t WTF::PassOwnPtr::PassOwnPtr(WebCore::EventTargetData*)<0000000003c50ad0> -0000000003c50b00 t WTF::PassOwnPtr::PassOwnPtr(WebCore::EventTargetData*)<0000000003c50b00> -0000000003c50b20 t WTF::HashMap, WTF::PtrHash, WTF::HashTraits, WTF::HashTraits > >::inlineAdd(WebCore::Node* const&, WTF::PassOwnPtr&)<0000000003c50b20> -0000000003c50b60 t WTF::HashTraits >::store(WTF::PassOwnPtr, WTF::OwnPtr&)<0000000003c50b60> -0000000003c50b90 t WTF::PassOwnPtr::PassOwnPtr(WTF::PassOwnPtr const&)<0000000003c50b90> -0000000003c50bc0 t WTF::HashTableIterator >, WTF::KeyValuePairKeyExtractor > >, WTF::PtrHash, WTF::HashMapValueTraits, WTF::HashTraits > >, WTF::HashTraits >::operator->() const<0000000003c50bc0> -0000000003c50be0 t WTF::HashTableIterator >, WTF::KeyValuePairKeyExtractor > >, WTF::PtrHash, WTF::HashMapValueTraits, WTF::HashTraits > >, WTF::HashTraits >::get() const<0000000003c50be0> -0000000003c50c00 t WTF::HashTableConstIterator >, WTF::KeyValuePairKeyExtractor > >, WTF::PtrHash, WTF::HashMapValueTraits, WTF::HashTraits > >, WTF::HashTraits >::get() const<0000000003c50c00> -0000000003c50c30 t WTF::HashTableConstIterator >, WTF::KeyValuePairKeyExtractor > >, WTF::PtrHash, WTF::HashMapValueTraits, WTF::HashTraits > >, WTF::HashTraits >::checkValidity() const<0000000003c50c30> -0000000003c50ca0 t WTF::PassOwnPtr::PassOwnPtr(WTF::PassOwnPtr const&)<0000000003c50ca0> -0000000003c50cd0 t WTF::PassOwnPtr::leakPtr() const<0000000003c50cd0> -0000000003c50cf0 t WTF::OwnPtr::operator=(WTF::PassOwnPtr const&)<0000000003c50cf0> -0000000003c50da0 t WTF::HashTableAddResult >, WTF::KeyValuePairKeyExtractor > >, WTF::PtrHash, WTF::HashMapValueTraits, WTF::HashTraits > >, WTF::HashTraits > > WTF::HashTable >, WTF::KeyValuePairKeyExtractor > >, WTF::PtrHash, WTF::HashMapValueTraits, WTF::HashTraits > >, WTF::HashTraits >::add, WTF::HashTraits > >, WTF::PtrHash >, WebCore::Node*, WTF::PassOwnPtr >(WebCore::Node* const&, WTF::PassOwnPtr const&)<0000000003c50da0> -0000000003c61050 t WebCore::NodeRenderingContext::isOnEncapsulationBoundary() const<0000000003c61050> -0000000003c610d0 t WebCore::NodeRenderingContext::isOnUpperEncapsulationBoundary() const<0000000003c610d0> -0000000003c61130 t WebCore::NodeRenderingContext::createRendererForElementIfNeeded()<0000000003c61130> -0000000003c61460 t WebCore::NodeRenderingContext::createRendererForTextIfNeeded()<0000000003c61460> -0000000003c6d0d0 t WebCore::toRenderQuote(WebCore::RenderObject*)<0000000003c6d0d0> -0000000003c6d160 t WebCore::PseudoElement::~PseudoElement()<0000000003c6d160> -0000000003c6d180 t WebCore::PseudoElement::~PseudoElement()<0000000003c6d180> -0000000003c6d1b0 t WebCore::PseudoElement::canContainRangeEndPoint() const<0000000003c6d1b0> -0000000003c6d1c0 t WebCore::PseudoElement::canStartSelection() const<0000000003c6d1c0> -0000000003c6d1d0 t WebCore::PseudoElement::customPseudoId() const<0000000003c6d1d0> -0000000003c6d1e0 t WebCore::PseudoElement::~PseudoElement()<0000000003c6d1e0> -0000000003c6d200 t WebCore::QualifiedName::QualifiedName(WTF::AtomicString const&, WTF::AtomicString const&, WTF::AtomicString const&) -0000000003c6d350 t WebCore::QualifiedName::~QualifiedName() -0000000003c6d370 t WebCore::QualifiedName::deref()<0000000003c6d370> -0000000003c6d3f0 t WebCore::QualifiedName::QualifiedNameImpl::~QualifiedNameImpl() -0000000003c6d480 t WebCore::QualifiedName::toString() const<0000000003c6d480> -0000000003c6d570 t WebCore::QualifiedName::init()<0000000003c6d570> -0000000003c6d5f0 t WebCore::nullQName()<0000000003c6d5f0> -0000000003c6db30 t WTF::RefCounted::~RefCounted()<0000000003c6db30> -0000000003c6db50 t WebCore::QualifiedName::operator new(unsigned long, void*)<0000000003c6db50> -0000000003c6db60 t WTF::AtomicString::upper() const<0000000003c6db60> -0000000003c6dbd0 t WTF::MemoryClassInfo::MemoryClassInfo(WTF::MemoryObjectInfo*, WebCore::QualifiedName const*, char const*, unsigned long)<0000000003c6dbd0> -0000000003c6dc10 t void WTF::MemoryClassInfo::addMember(WebCore::QualifiedName::QualifiedNameImpl* const&, char const*)<0000000003c6dc10> -0000000003c6dc60 t WTF::MemoryClassInfo::MemoryClassInfo(WTF::MemoryObjectInfo*, WebCore::QualifiedName::QualifiedNameImpl const*, char const*, unsigned long)<0000000003c6dc60> -0000000003c6dca0 t WTF::AtomicString::AtomicString(char const*, unsigned int, WTF::AtomicString::ConstructFromLiteralTag)<0000000003c6dca0> -0000000003c6dcd0 t WTF::MemoryClassInfo::MemoryClassInfo(WTF::MemoryObjectInfo*, WebCore::QualifiedName::QualifiedNameImpl const*, char const*, unsigned long)<0000000003c6dcd0> -0000000003c6f990 t WTF::HashTableIterator::get() const<0000000003c6f990> -0000000003c6f9b0 t WTF::HashTableConstIterator::get() const<0000000003c6f9b0> -0000000003c6f9e0 t WTF::HashTableConstIterator::checkValidity() const<0000000003c6f9e0> -0000000003c6fa50 t WTF::HashTableAddResult > WTF::HashTable::addPassingHashCode, WebCore::QualifiedNameComponents, WebCore::QualifiedNameComponents>(WebCore::QualifiedNameComponents const&, WebCore::QualifiedNameComponents const&)<0000000003c6fa50> -0000000003c6fd00 t void WTF::HashTable::checkKey, WebCore::QualifiedNameComponents>(WebCore::QualifiedNameComponents const&)<0000000003c6fd00> -0000000003c6fd40 t WTF::HashTable::expand()<0000000003c6fd40> -0000000003c6fdc0 t std::pair, unsigned int> WTF::HashTable::fullLookupForWriting, WebCore::QualifiedNameComponents>(WebCore::QualifiedNameComponents const&)<0000000003c6fdc0> -0000000003cd7d20 t WTF::PassRefPtr::PassRefPtr(WebCore::CustomElementConstructor*, bool)<0000000003cd7d20> -0000000003cd7d60 t WTF::PassRefPtr::PassRefPtr(WebCore::CustomElementConstructor*, bool)<0000000003cd7d60> -0000000003cd7d80 t WebCore::EventContext::EventContext(WTF::PassRefPtr, WTF::PassRefPtr, WTF::PassRefPtr) -0000000003cd7ed0 t WebCore::EventContext::~EventContext()<0000000003cd7ed0> -0000000003cd7f00 t WebCore::EventContext::~EventContext() -0000000003cd7f60 t WebCore::EventContext::handleLocalEvents(WebCore::Event*) const<0000000003cd7f60> -0000000003cd8020 t WebCore::EventContext::isMouseOrFocusEventContext() const<0000000003cd8020> -0000000003cd8030 t WebCore::MouseOrFocusEventContext::MouseOrFocusEventContext(WTF::PassRefPtr, WTF::PassRefPtr, WTF::PassRefPtr) -0000000003cd80e0 t WebCore::MouseOrFocusEventContext::~MouseOrFocusEventContext()<0000000003cd80e0> -0000000003cd8110 t WebCore::MouseOrFocusEventContext::~MouseOrFocusEventContext() -0000000003cd8160 t WebCore::MouseOrFocusEventContext::handleLocalEvents(WebCore::Event*) const<0000000003cd8160> -0000000003cd8300 t WebCore::MouseOrFocusEventContext::isMouseOrFocusEventContext() const<0000000003cd8300> -0000000003cd8310 t WebCore::MouseEvent::setRelatedTarget(WTF::PassRefPtr)<0000000003cd8310> -0000000003ec6560 t content::ChildThread::OnMessageReceived(IPC::Message const&)<0000000003ec6560> -0000000003fe4db0 t content::ResourceDispatcher::IsResourceDispatcherMessage(IPC::Message const&)<0000000003fe4db0> -0000000003fe4e20 t content::ResourceDispatcher::GetPendingRequestInfo(int)<0000000003fe4e20> -0000000003fe4ec0 t content::ResourceDispatcher::ReleaseResourcesInDataMessage(IPC::Message const&)<0000000003fe4ec0> -0000000003fe4ff0 t content::ResourceDispatcher::FlushDeferredMessages(int)<0000000003fe4ff0> -0000000003fe59c0 t content::ResourceDispatcher::OnUploadProgress(IPC::Message const&, int, long, long)<0000000003fe59c0> -0000000003fe5aa0 t content::ResourceDispatcher::OnReceivedResponse(int, content::ResourceResponseHead const&)<0000000003fe5aa0> -00000000045c1560 t WebCore::NodeV8Internal::insertBeforeMethodCallback(v8::Arguments const&)<00000000045c1560> -00000000045c1590 t WebCore::NodeV8Internal::replaceChildMethodCallback(v8::Arguments const&)<00000000045c1590> -00000000045c15c0 t WebCore::NodeV8Internal::removeChildMethodCallback(v8::Arguments const&)<00000000045c15c0> -00000000045c15f0 t WebCore::NodeV8Internal::appendChildMethodCallback(v8::Arguments const&)<00000000045c15f0> -00000000045c1620 t WebCore::NodeV8Internal::hasChildNodesMethodCallback(v8::Arguments const&)<00000000045c1620> -00000000045c1650 t WebCore::NodeV8Internal::cloneNodeMethodCallback(v8::Arguments const&)<00000000045c1650> -00000000045c1680 t WebCore::NodeV8Internal::normalizeMethodCallback(v8::Arguments const&)<00000000045c1680> -00000000045c16b0 t WebCore::NodeV8Internal::isSupportedMethodCallback(v8::Arguments const&)<00000000045c16b0> -00000000045c16e0 t WebCore::NodeV8Internal::lookupPrefixMethodCallback(v8::Arguments const&)<00000000045c16e0> -00000000045c1710 t WebCore::NodeV8Internal::isDefaultNamespaceMethodCallback(v8::Arguments const&)<00000000045c1710> -00000000045c1740 t WebCore::NodeV8Internal::lookupNamespaceURIMethodCallback(v8::Arguments const&)<00000000045c1740> -00000000045c1770 t WebCore::NodeV8Internal::addEventListenerMethodCallback(v8::Arguments const&)<00000000045c1770> -00000000045c17a0 t WebCore::NodeV8Internal::removeEventListenerMethodCallback(v8::Arguments const&)<00000000045c17a0> -00000000045c17d0 t WebCore::NodeV8Internal::removeEventListenerMethod(v8::Arguments const&)<00000000045c17d0> -00000000045c2500 t WebCore::NodeV8Internal::lookupNamespaceURIMethod(v8::Arguments const&)<00000000045c2500> -0000000004a6c010 t sigslot::_signal_base4::_signal_base4()<0000000004a6c010> -0000000004a6c070 t sigslot::signal4::~signal4()<0000000004a6c070> -0000000004a6c0a0 t non-virtual thunk to sigslot::signal4::~signal4()<0000000004a6c0a0> -0000000004a6c0d0 t std::list*, std::allocator*> >::list()<0000000004a6c0d0> -0000000004a6c0f0 t std::list*, std::allocator*> >::list()<0000000004a6c0f0> -0000000004a6c110 t std::_List_base*, std::allocator*> >::_List_base()<0000000004a6c110> -0000000004a6c140 t std::_List_base*, std::allocator*> >::_List_impl::_List_impl()<0000000004a6c140> -0000000004a6c160 t std::_List_base*, std::allocator*> >::_M_init()<0000000004a6c160> -0000000004a6c180 t std::_List_base*, std::allocator*> >::_List_impl::_List_impl()<0000000004a6c180> -0000000004a6c1c0 t std::allocator*> >::allocator()<0000000004a6c1c0> -0000000004a6c1e0 t __gnu_cxx::new_allocator*> >::new_allocator()<0000000004a6c1e0> -0000000004a6c1f0 t talk_base::PacketSocketFactory::~PacketSocketFactory()<0000000004a6c1f0> -0000000004a6c210 t talk_base::PacketSocketFactory::~PacketSocketFactory()<0000000004a6c210> -0000000004a6c240 t content::ContentMain(int, char const**, content::ContentMainDelegate*)<0000000004a6c240> -0000000004a6c310 t scoped_ptr >::scoped_ptr(content::ContentMainRunner*)<0000000004a6c310> -0000000004a6c340 t scoped_ptr >::operator->() const<0000000004a6c340> -0000000004a6c3a0 t scoped_ptr >::~scoped_ptr()<0000000004a6c3a0> -0000000004a6c3c0 t base::internal::scoped_ptr_impl >::get() const<0000000004a6c3c0> -0000000004a6c3d0 t scoped_ptr >::scoped_ptr(content::ContentMainRunner*)<0000000004a6c3d0> -0000000004a6c400 t base::internal::scoped_ptr_impl >::scoped_ptr_impl(content::ContentMainRunner*)<0000000004a6c400> -0000000004a6c430 t base::internal::scoped_ptr_impl >::scoped_ptr_impl(content::ContentMainRunner*)<0000000004a6c430> -0000000004a6c460 t base::internal::scoped_ptr_impl >::Data::Data(content::ContentMainRunner*)<0000000004a6c460> -0000000004a6c490 t base::internal::scoped_ptr_impl >::Data::Data(content::ContentMainRunner*)<0000000004a6c490> -0000000004a6c4d0 t base::DefaultDeleter::DefaultDeleter()<0000000004a6c4d0> -0000000004a6c4e0 t scoped_ptr >::~scoped_ptr()<0000000004a6c4e0> -0000000004a6c500 t base::internal::scoped_ptr_impl >::~scoped_ptr_impl()<0000000004a6c500> -0000000004a6c520 t base::internal::scoped_ptr_impl >::~scoped_ptr_impl()<0000000004a6c520> -0000000004a6c560 t base::DefaultDeleter::operator()(content::ContentMainRunner*) const<0000000004a6c560> -0000000004a6c5a0 t content::SetupSignalHandlers()<0000000004a6c5a0> -0000000004a6cca0 t content::InitializeStatsTable(CommandLine const&)<0000000004a6cca0> -0000000004a6cda0 t content::RunNamedProcessTypeMain(std::basic_string, std::allocator > const&, content::MainFunctionParams const&, content::ContentMainDelegate*)<0000000004a6cda0> -0000000004a6dc80 t content::ContentMainRunnerImpl::Run()<0000000004a6dc80> -0000000004a6de90 t content::ContentMainRunnerImpl::Shutdown()<0000000004a6de90> -0000000004a6e0e0 t scoped_ptr >::reset(base::AtExitManager*)<0000000004a6e0e0> -0000000004a6e110 t base::internal::scoped_ptr_impl >::reset(base::AtExitManager*)<0000000004a6e110> -0000000004a864e0 t content::RenderThreadImpl::OnCreateNewView(ViewMsg_New_Params const&)<0000000004a864e0> -0000000004a88b20 t scoped_ptr >::reset(media::AudioHardwareConfig*)<0000000004a88b20> -0000000004a88b50 t scoped_refptr::operator->() const<0000000004a88b50> -0000000004a88bb0 t scoped_ptr >::get() const<0000000004a88bb0> -0000000004a88bd0 t content::ChildProcess::io_message_loop()<0000000004a88bd0> -0000000004a88c00 t scoped_ptr >::operator->() const<0000000004a88c00> -0000000004a88c60 t scoped_ptr >::operator->() const<0000000004a88c60> -0000000004a88cc0 t bool ViewMsg_SetZoomLevelForCurrentURL::Dispatch, std::allocator > const&, double)>(IPC::Message const*, content::RenderThreadImpl*, content::RenderThreadImpl*, void (content::RenderThreadImpl::*)(std::basic_string, std::allocator > const&, double))<0000000004a88cc0> -0000000004a88d70 t bool ViewMsg_New::Dispatch(IPC::Message const*, content::RenderThreadImpl*, content::RenderThreadImpl*, void (content::RenderThreadImpl::*)(ViewMsg_New_Params const&))<0000000004a88d70> -0000000004a88e40 t bool ViewMsg_PurgePluginListCache::Dispatch(IPC::Message const*, content::RenderThreadImpl*, content::RenderThreadImpl*, void (content::RenderThreadImpl::*)(bool))<0000000004a88e40> -0000000004a88ed0 t bool ViewMsg_NetworkStateChanged::Dispatch(IPC::Message const*, content::RenderThreadImpl*, content::RenderThreadImpl*, void (content::RenderThreadImpl::*)(bool))<0000000004a88ed0> -0000000004a88f60 t bool ViewMsg_TempCrashWithData::Dispatch(IPC::Message const*, content::RenderThreadImpl*, content::RenderThreadImpl*, void (content::RenderThreadImpl::*)(GURL const&))<0000000004a88f60> -0000000004a89030 t base::RefCountedData::RefCountedData(int const&)<0000000004a89030> -0000000004a89060 t scoped_ptr >::get() const<0000000004a89060> -0000000004a89080 t scoped_ptr >::reset(content::MediaStreamDependencyFactory*)<0000000004a89080> -0000000004a890b0 t scoped_refptr::operator content::VideoCaptureImplManager*() const<0000000004a890b0> -0000000004a890c0 t content::RendererWebKitPlatformSupportImpl::set_plugin_refresh_allowed(bool)<0000000004a890c0> -0000000004a890e0 t base::internal::scoped_ptr_impl >::reset(content::MediaStreamDependencyFactory*)<0000000004a890e0> -0000000004a89640 t base::DefaultDeleter::operator()(content::AudioRendererMixerManager*) const<0000000004a89640> -0000000004a896b0 t base::internal::scoped_ptr_impl >::get() const<0000000004a896b0> -0000000004a896c0 t base::internal::scoped_ptr_impl >::get() const<0000000004a896c0> -0000000004a896d0 t base::internal::scoped_ptr_impl >::reset(content::WebGraphicsContext3DCommandBufferImpl*)<0000000004a896d0> -0000000004a909f0 t content::RenderView::ForEach(content::RenderViewVisitor*)<0000000004a909f0> -0000000004a90ad0 t content::RenderViewImpl::Create(int, content::RendererPreferences const&, webkit_glue::WebPreferences const&, base::RefCountedData*, int, int, long, std::basic_string > const&, bool, bool, int, WebKit::WebScreenInfo const&, AccessibilityMode)<0000000004a90ad0> -0000000004a90d10 t content::RenderViewImpl::InstallCreateHook(content::RenderViewImpl* (*)(content::RenderViewImplParams*))<0000000004a90d10> -0000000004a90dd0 t content::RenderViewImpl::AddObserver(content::RenderViewObserver*)<0000000004a90dd0> -0000000004a90e10 t content::RenderViewImpl::RemoveObserver(content::RenderViewObserver*)<0000000004a90e10> -0000000004a90e60 t content::RenderViewImpl::PluginCrashed(base::FilePath const&, int)<0000000004a90e60> -0000000004a90ef0 t content::RenderViewImpl::RegisterPluginDelegate(content::WebPluginDelegateProxy*)<0000000004a90ef0> -0000000004a90f80 t content::RenderViewImpl::UnregisterPluginDelegate(content::WebPluginDelegateProxy*)<0000000004a90f80> -0000000004a90fc0 t content::RenderViewImpl::GetPluginInfo(GURL const&, GURL const&, std::basic_string, std::allocator > const&, webkit::WebPluginInfo*, std::basic_string, std::allocator >*)<0000000004a90fc0> -0000000004ae8260 t content::HandleRendererErrorTestParameters(CommandLine const&)<0000000004ae8260> -0000000004ae8450 t content::RendererMessageLoopObserver::RendererMessageLoopObserver()<0000000004ae8450> -0000000004ae8470 t scoped_ptr >::scoped_ptr()<0000000004ae8470> -000000000561d6c0 t v8::Function::Call(v8::Handle, int, v8::Handle*)<000000000561d6c0> -000000000561daa0 t v8::Function::SetName(v8::Handle)<000000000561daa0> -000000000561dba0 t v8::Function::GetName() const<000000000561dba0> -00000000056bac10 t v8::internal::Double::AsUint64() const<00000000056bac10> -00000000056bac20 t v8::internal::Double::IsDenormal() const<00000000056bac20> -00000000056bac60 t v8::internal::Double::Double(double)<00000000056bac60> -00000000056bac90 t v8::internal::double_to_uint64(double)<00000000056bac90> -00000000056bacb0 t v8::internal::StackGuard::StackGuard() -00000000056bace0 t v8::internal::Execution::Call(v8::internal::Handle, v8::internal::Handle, int, v8::internal::Handle*, bool*, bool)<00000000056bace0> -00000000056baf20 t v8::internal::Execution::TryGetFunctionDelegate(v8::internal::Handle, bool*)<00000000056baf20> -00000000056bb110 t v8::internal::Execution::ToObject(v8::internal::Handle, bool*)<00000000056bb110> -00000000056bb200 t v8::internal::Invoke(bool, v8::internal::Handle, v8::internal::Handle, int, v8::internal::Handle*, bool*)<00000000056bb200> -00000000058802e0 t v8::internal::Parser::ParseFunctionDeclaration(v8::internal::ZoneList >*, bool*)<00000000058802e0> -0000000005880520 t v8::internal::Parser::ParseVariableStatement(v8::internal::Parser::VariableDeclarationContext, v8::internal::ZoneList >*, bool*)<0000000005880520> -00000000058805d0 t v8::internal::Parser::ParseImportDeclaration(bool*)<00000000058805d0> -0000000005880fd0 t v8::internal::Parser::ParseStatement(v8::internal::ZoneList >*, bool*)<0000000005880fd0> -0000000005888100 t v8::internal::Parser::ParseAssignmentExpression(bool, bool*)<0000000005888100> -0000000005888e60 t v8::internal::Parser::NewThrowReferenceError(v8::internal::Handle)<0000000005888e60> -0000000005888ed0 t v8::internal::Parser::ParseConditionalExpression(bool, bool*)<0000000005888ed0> -0000000005889060 t v8::internal::Parser::CheckStrictModeLValue(v8::internal::Expression*, char const*, bool*)<0000000005889060> -0000000005889180 t v8::internal::Parser::MarkAsLValue(v8::internal::Expression*)<0000000005889180> -00000000058891f0 t v8::internal::Parser::ParseBinaryExpression(int, bool, bool*)<00000000058891f0> -0000000005889d60 t v8::internal::Precedence(v8::internal::Token::Value, bool)<0000000005889d60> -0000000005889db0 t v8::internal::Parser::ParsePostfixExpression(bool*)<0000000005889db0> -0000000005889f50 t v8::internal::Parser::ParseLeftHandSideExpression(bool*)<0000000005889f50> -0000000005893d30 t v8::internal::Interface::MakeModule(bool*)<0000000005893d30> -0000000005893d80 t v8::internal::Interface::Freeze(bool*)<0000000005893d80> -0000000005893df0 t v8::internal::AstNodeFactory::NewModuleLiteral(v8::internal::Block*, v8::internal::Interface*)<0000000005893df0> -0000000005893e80 t v8::internal::AstNodeFactory::NewModulePath(v8::internal::Module*, v8::internal::Handle)<0000000005893e80> -0000000005893f20 t v8::internal::Interface::Add(v8::internal::Handle, v8::internal::Interface*, v8::internal::Zone*, bool*)<0000000005893f20> -0000000005893f90 t v8::internal::VariableProxy* v8::internal::Scope::NewUnresolved(v8::internal::AstNodeFactory*, v8::internal::Handle, v8::internal::Interface*, int)<0000000005893f90> -0000000005894050 t v8::internal::Interface::NewModule(v8::internal::Zone*)<0000000005894050> -00000000058940b0 t v8::internal::AstNodeFactory::NewModuleVariable(v8::internal::VariableProxy*)<00000000058940b0> -0000000005894150 t void v8::internal::USE >(v8::internal::Handle)<0000000005894150> -0000000005894160 t v8::internal::Parser::Consume(v8::internal::Token::Value)<0000000005894160> -00000000058941d0 t v8::internal::List, v8::internal::ZoneAllocationPolicy>::operator[](int) const<00000000058941d0> -0000000005894280 t v8::internal::Interface::NewUnknown(v8::internal::Zone*)<0000000005894280> -00000000058942e0 t v8::internal::AstNodeFactory::NewImportDeclaration(v8::internal::VariableProxy*, v8::internal::Module*, v8::internal::Scope*)<00000000058942e0> -000000000589ba70 t v8::internal::ImportDeclaration::ImportDeclaration(v8::internal::VariableProxy*, v8::internal::Module*, v8::internal::Scope*)<000000000589ba70> -000000000589bab0 t v8::internal::ImportDeclaration::ImportDeclaration(v8::internal::VariableProxy*, v8::internal::Module*, v8::internal::Scope*)<000000000589bab0> -000000000589bb20 t v8::internal::ModuleVariable::ModuleVariable(v8::internal::VariableProxy*)<000000000589bb20> -000000000589bb50 t v8::internal::ModuleVariable::ModuleVariable(v8::internal::VariableProxy*)<000000000589bb50> -000000000589bbc0 t v8::internal::Module::Module(v8::internal::Interface*, v8::internal::Block*)<000000000589bbc0> -000000000589bc20 t v8::internal::Module::~Module()<000000000589bc20> -000000000589bc40 t v8::internal::Module::~Module()<000000000589bc40> -000000000589bc80 t v8::internal::Module::~Module()<000000000589bc80> -000000000589bca0 t v8::internal::Scope::already_resolved()<000000000589bca0> -000000000589bcc0 t v8::internal::AstNodeFactory::NewVariableProxy(v8::internal::Handle, bool, v8::internal::Interface*, int)<000000000589bcc0> -000000000589bd80 t v8::internal::ZoneList::Add(v8::internal::VariableProxy* const&, v8::internal::Zone*)<000000000589bd80> -000000000589bde0 t v8::internal::List::Add(v8::internal::VariableProxy* const&, v8::internal::ZoneAllocationPolicy)<000000000589bde0> -000000000589be50 t v8::internal::List::ResizeAdd(v8::internal::VariableProxy* const&, v8::internal::ZoneAllocationPolicy)<000000000589be50> -000000000589be90 t v8::internal::List::ResizeAddInternal(v8::internal::VariableProxy* const&, v8::internal::ZoneAllocationPolicy)<000000000589be90> -000000000589bf40 t v8::internal::List::Resize(int, v8::internal::ZoneAllocationPolicy)<000000000589bf40> -000000000589c000 t v8::internal::List::NewData(int, v8::internal::ZoneAllocationPolicy)<000000000589c000> -0000000005f14a50 t WTFAnnotateBenignRaceSized<0000000005f14a50> -0000000005f14a70 t WTFAnnotateHappensBefore<0000000005f14a70> -0000000005f14a90 t WTFAnnotateHappensAfter<0000000005f14a90> -0000000005f14ab0 t WTF::fastMallocForbid()<0000000005f14ab0> -0000000005f14af0 t WTF::initializeIsForbiddenKey()<0000000005f14af0> -0000000005f14b20 t WTF::fastMallocAllow()<0000000005f14b20> -0000000005f14b60 t WTF::Internal::fastMallocMatchFailed(void*)<0000000005f14b60> -0000000005f14b90 t WTF::fastZeroedMalloc(unsigned long)<0000000005f14b90> -0000000005f14bd0 t WTF::fastMalloc(unsigned long)<0000000005f14bd0> -0000000005f14c80 t WTF::fastStrDup(char const*)<0000000005f14c80> -0000000005f14cd0 t WTF::tryFastZeroedMalloc(unsigned long)<0000000005f14cd0> -0000000005f14d70 t WTF::tryFastMalloc(unsigned long)<0000000005f14d70> -0000000005f14e00 t WTF::fastMallocGoodSize(unsigned long)<0000000005f14e00> -0000000005f14e10 t WTF::isForbidden()<0000000005f14e10> -0000000005f14e60 t WTF::tryFastCalloc(unsigned long, unsigned long)<0000000005f14e60> -00000000066bd110 t WTF::RefPtr::RefPtr(WTF::PassRefPtr const&)<00000000066bd110> -00000000066bd140 t WTF::PassRefPtr::PassRefPtr(WebCore::HTMLTextAreaElement*, bool)<00000000066bd140> -00000000066bd180 t WTF::PassRefPtr::PassRefPtr(WebCore::HTMLTextAreaElement*, bool)<00000000066bd180> -00000000066bd1a0 t WebCore::HTMLTextAreaElement::~HTMLTextAreaElement()<00000000066bd1a0> -00000000066bd200 t WebCore::HTMLTitleElement::create(WebCore::QualifiedName const&, WebCore::Document*)<00000000066bd200> -00000000066bd280 t WebCore::HTMLTitleElement::insertedInto(WebCore::ContainerNode*)<00000000066bd280> -00000000066bd310 t WebCore::HTMLTitleElement::removedFrom(WebCore::ContainerNode*)<00000000066bd310> -00000000066bd390 t WebCore::HTMLTitleElement::childrenChanged(bool, WebCore::Node*, WebCore::Node*, int)<00000000066bd390> -00000000066bd4b0 t WebCore::HTMLTitleElement::textWithDirection()<00000000066bd4b0> -00000000066bd5a0 t WebCore::HTMLTitleElement::text() const<00000000066bd5a0> -00000000066bd670 t WebCore::HTMLTitleElement::setText(WTF::String const&)<00000000066bd670> -000000000674ea00 t close_display<000000000674ea00> -000000000674ea30 t base::type_profiler::NewInterceptForTCMalloc(void*, unsigned long, std::type_info const&)<000000000674ea30> -000000000674ea80 t base::type_profiler::DeleteInterceptForTCMalloc(void*, unsigned long, std::type_info const&)<000000000674ea80> -000000000674eac0 t JSC::Yarr::byteCompile(JSC::Yarr::YarrPattern&, WTF::BumpPointerAllocator*)<000000000674eac0> -000000000674eb10 t JSC::Yarr::interpret(JSC::Yarr::BytecodePattern*, WTF::String const&, unsigned int, unsigned int*)<000000000674eb10> -000000000674ec20 t JSC::Yarr::interpret(JSC::Yarr::BytecodePattern*, unsigned char const*, unsigned int, unsigned int, unsigned int*)<000000000674ec20> -000000000674ec70 t JSC::Yarr::interpret(JSC::Yarr::BytecodePattern*, unsigned short const*, unsigned int, unsigned int, unsigned int*)<000000000674ec70> -000000000674ecc0 t bool WTF::isInBounds(unsigned int)<000000000674ecc0> -000000000674ece0 t bool WTF::safeEquals(unsigned int, int)<000000000674ece0> -000000000674ed10 t JSC::Yarr::ByteCompiler::ByteCompiler(JSC::Yarr::YarrPattern&)<000000000674ed10> -000000000674ed40 t JSC::Yarr::ByteCompiler::compile(WTF::BumpPointerAllocator*)<000000000674ed40> -0000000007408020 T mremap<0000000007408020> -0000000007408240 T sbrk<0000000007408240> -000000000740827a T LowLevelAlloc::AllocWithArena(unsigned long, LowLevelAlloc::Arena*)<000000000740827a> -0000000007408312 T LowLevelAlloc::Free(void*)<0000000007408312> -0000000007408462 T LowLevelAlloc::Alloc(unsigned long)<0000000007408462> -00000000074084b1 T __stop_malloc_hook<00000000074084b1> -00000000074084c0 T tc_new -0000000007408500 T tc_delete -0000000007408530 T tc_newarray -0000000007408570 T tc_deletearray -00000000074085a0 T tc_new_nothrow diff --git a/tools/deep_memory_profiler/tests/data/heap.01234.symmap/chrome.uvwxyz.readelf-e b/tools/deep_memory_profiler/tests/data/heap.01234.symmap/chrome.uvwxyz.readelf-e deleted file mode 100644 index 37bd98ea0c..0000000000 --- a/tools/deep_memory_profiler/tests/data/heap.01234.symmap/chrome.uvwxyz.readelf-e +++ /dev/null @@ -1,101 +0,0 @@ -ELF Header: - Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 - Class: ELF64 - Data: 2's complement, little endian - Version: 1 (current) - OS/ABI: UNIX - System V - ABI Version: 0 - Type: DYN (Shared object file) - Machine: Advanced Micro Devices X86-64 - Version: 0x1 - Entry point address: 0x9fbcc0 - Start of program headers: 64 (bytes into file) - Start of section headers: 418040784 (bytes into file) - Flags: 0x0 - Size of this header: 64 (bytes) - Size of program headers: 56 (bytes) - Number of program headers: 10 - Size of section headers: 64 (bytes) - Number of section headers: 47 - Section header string table index: 46 - -Section Headers: - [Nr] Name Type Address Off Size ES Flg Lk Inf Al - [ 0] NULL 0000000000000000 000000 000000 00 0 0 0 - [ 1] .interp PROGBITS 0000000000000270 000270 00001c 00 A 0 0 1 - [ 2] .note.ABI-tag NOTE 000000000000028c 00028c 000020 00 A 0 0 4 - [ 3] .note.gnu.build-id NOTE 00000000000002ac 0002ac 000024 00 A 0 0 4 - [ 4] .dynsym DYNSYM 00000000000002d0 0002d0 00fb70 18 A 5 1 8 - [ 5] .dynstr STRTAB 000000000000fe40 00fe40 00e678 00 A 0 0 1 - [ 6] .gnu.hash GNU_HASH 000000000001e4b8 01e4b8 0001d0 00 A 4 0 8 - [ 7] .gnu.version VERSYM 000000000001e688 01e688 0014f4 02 A 4 0 2 - [ 8] .gnu.version_r VERNEED 000000000001fb7c 01fb7c 0003b0 00 A 5 13 4 - [ 9] .rela.dyn RELA 000000000001ff30 01ff30 9c3210 18 A 4 0 8 - [10] .rela.plt RELA 00000000009e3140 9e3140 00ed30 18 AI 4 12 8 - [11] .init PROGBITS 00000000009f1e70 9f1e70 000018 00 AX 0 0 4 - [12] .plt PROGBITS 00000000009f1e88 9f1e88 009e30 10 AX 0 0 8 - [13] .text PROGBITS 00000000009fbcc0 9fbcc0 6a0c238 00 AX 0 0 16 - [14] malloc_hook PROGBITS 0000000007407f00 7407f00 0005b1 00 AX 0 0 16 - [15] google_malloc PROGBITS 00000000074084c0 74084c0 0005a2 00 AX 0 0 16 - [16] .fini PROGBITS 0000000007408a64 7408a64 00000e 00 AX 0 0 4 - [17] .rodata PROGBITS 0000000007408a80 7408a80 18388f0 00 A 0 0 64 - [18] .gcc_except_table PROGBITS 0000000008c41370 8c41370 0014f4 00 A 0 0 4 - [19] .eh_frame PROGBITS 0000000008c42868 8c42868 1887a54 00 A 0 0 8 - [20] .eh_frame_hdr PROGBITS 000000000a4ca2bc a4ca2bc 66e33c 00 A 0 0 4 - [21] .tbss NOBITS 000000000ab39720 ab38720 000028 00 WAT 0 0 8 - [22] .data.rel.ro.local PROGBITS 000000000ab39720 ab38720 1907e0 00 WA 0 0 16 - [23] .ctors PROGBITS 000000000acc9f00 acc8f00 0001f8 00 WA 0 0 8 - [24] .dtors PROGBITS 000000000acca0f8 acc90f8 000010 00 WA 0 0 8 - [25] .jcr PROGBITS 000000000acca108 acc9108 000008 00 WA 0 0 8 - [26] .data.rel.ro PROGBITS 000000000acca110 acc9110 257380 00 WA 0 0 16 - [27] .dynamic DYNAMIC 000000000af21490 af20490 000520 10 WA 5 0 8 - [28] .got PROGBITS 000000000af219b0 af209b0 01e638 00 WA 0 0 8 - [29] .got.plt PROGBITS 000000000af3ffe8 af3efe8 004f28 00 WA 0 0 8 - [30] .data PROGBITS 000000000af44f10 af43f10 0372b8 00 WA 0 0 16 - [31] .bss NOBITS 000000000af7c1d0 af7b1d0 07895a 00 WA 0 0 16 - [32] .comment PROGBITS 0000000000000000 af7b1c8 00002b 01 MS 0 0 1 - [33] .debug_info PROGBITS 0000000000000000 af7b1f3 2fd3510 00 0 0 1 - [34] .debug_abbrev PROGBITS 0000000000000000 df4e703 156ae4 00 0 0 1 - [35] .debug_aranges PROGBITS 0000000000000000 e0a51e7 000120 00 0 0 1 - [36] .debug_macinfo PROGBITS 0000000000000000 e0a5307 000000 00 0 0 1 - [37] .debug_line PROGBITS 0000000000000000 e0a5307 2e73466 00 0 0 1 - [38] .debug_loc PROGBITS 0000000000000000 10f1876d 000934 00 0 0 1 - [39] .debug_pubtypes PROGBITS 0000000000000000 10f190a1 000000 00 0 0 1 - [40] .debug_str PROGBITS 0000000000000000 10f190a1 fd980a 01 MS 0 0 1 - [41] .debug_ranges PROGBITS 0000000000000000 11ef28ab 08d950 00 0 0 1 - [42] .debug_frame PROGBITS 0000000000000000 11f80200 000058 00 0 0 8 - [43] .note.gnu.gold-version NOTE 0000000000000000 11f80258 00001c 00 0 0 4 - [44] .symtab SYMTAB 0000000000000000 11f80278 1c2e928 18 45 1175494 8 - [45] .strtab STRTAB 0000000000000000 13baeba0 52fde3d 00 0 0 1 - [46] .shstrtab STRTAB 0000000000000000 18eac9dd 0001ec 00 0 0 1 -Key to Flags: - W (write), A (alloc), X (execute), M (merge), S (strings), l (large) - I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) - O (extra OS processing required) o (OS specific), p (processor specific) - -Program Headers: - Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align - PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x000230 0x000230 R 0x8 - INTERP 0x000270 0x0000000000000270 0x0000000000000270 0x00001c 0x00001c R 0x1 - [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] - LOAD 0x000000 0x0000000000000000 0x0000000000000000 0xab385f8 0xab385f8 R E 0x1000 - LOAD 0xab38720 0x000000000ab39720 0x000000000ab39720 0x442aa8 0x4bb40a RW 0x1000 - DYNAMIC 0xaf20490 0x000000000af21490 0x000000000af21490 0x000520 0x000520 RW 0x8 - NOTE 0x00028c 0x000000000000028c 0x000000000000028c 0x000044 0x000044 R 0x4 - GNU_EH_FRAME 0xa4ca2bc 0x000000000a4ca2bc 0x000000000a4ca2bc 0x66e33c 0x66e33c R 0x4 - GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0 - TLS 0xab38720 0x000000000ab39720 0x000000000ab39720 0x000000 0x000028 R 0x8 - GNU_RELRO 0xab38720 0x000000000ab39720 0x000000000ab39720 0x4068e0 0x4068e0 RW 0x10 - - Section to Segment mapping: - Segment Sections... - 00 - 01 .interp - 02 .interp .note.ABI-tag .note.gnu.build-id .dynsym .dynstr .gnu.hash .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text malloc_hook google_malloc .fini .rodata .gcc_except_table .eh_frame .eh_frame_hdr - 03 .data.rel.ro.local .ctors .dtors .jcr .data.rel.ro .dynamic .got .got.plt .data .bss - 04 .dynamic - 05 .note.ABI-tag .note.gnu.build-id - 06 .eh_frame_hdr - 07 - 08 .tbss - 09 .data.rel.ro.local .ctors .dtors .jcr .data.rel.ro .dynamic .got diff --git a/tools/deep_memory_profiler/tests/data/heap.01234.symmap/files.json b/tools/deep_memory_profiler/tests/data/heap.01234.symmap/files.json deleted file mode 100644 index 64d3449242..0000000000 --- a/tools/deep_memory_profiler/tests/data/heap.01234.symmap/files.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "/home/user/chromium/src/out/Debug/chrome": { - "nm": { - "file": "chrome.abcdef.nm", - "format": "bsd", - "mangled": false - }, - "readelf-e": { - "file": "chrome.uvwxyz.readelf-e" - } - } -} \ No newline at end of file diff --git a/tools/deep_memory_profiler/tests/data/heap.01234.symmap/maps b/tools/deep_memory_profiler/tests/data/heap.01234.symmap/maps deleted file mode 100644 index a2555247d1..0000000000 --- a/tools/deep_memory_profiler/tests/data/heap.01234.symmap/maps +++ /dev/null @@ -1,410 +0,0 @@ -114147900000-114147935000 rw-p 00000000 00:00 0 -12e93464c000-12e934700000 ---p 00000000 00:00 0 -12e934700000-12e934705000 rw-p 00000000 00:00 0 -12e934705000-12e934706000 ---p 00000000 00:00 0 -12e934706000-12e934707000 rwxp 00000000 00:00 0 -12e934707000-12e934800000 ---p 00000000 00:00 0 -12e934800000-12e934805000 rw-p 00000000 00:00 0 -12e934805000-12e934806000 ---p 00000000 00:00 0 -12e934806000-12e934807000 rwxp 00000000 00:00 0 -12e934807000-12e934900000 ---p 00000000 00:00 0 -12e934900000-12e934905000 rw-p 00000000 00:00 0 -12e934905000-12e934906000 ---p 00000000 00:00 0 -12e934906000-12e9349ff000 rwxp 00000000 00:00 0 -12e9349ff000-12e95464c000 ---p 00000000 00:00 0 -16b0892d7000-16b0892d8000 r-xp 00000000 00:00 0 -19fc4e858000-19fc4e859000 r-xp 00000000 00:00 0 -1ae6500da000-1ae6503ea000 rw-p 00000000 00:00 0 -1c8ad47d9000-1c8ad47da000 r-xp 00000000 00:00 0 -1cca7ce6a000-1cca7ce80000 ---p 00000000 00:00 0 -1cca7ce80000-1cca7cea0000 rw-p 00000000 00:00 0 -1cca7cea0000-1cca7ceca000 ---p 00000000 00:00 0 -2195f26d4000-2195f26d5000 r-xp 00000000 00:00 0 -21c091300000-21c091325000 rw-p 00000000 00:00 0 -277034700000-277034800000 rw-p 00000000 00:00 0 -280bd8000000-280bd8f00000 ---p 00000000 00:00 0 -280bd8f00000-280bd9000000 rw-p 00000000 00:00 0 -280bd9000000-280bda000000 ---p 00000000 00:00 0 -2bb801c00000-2bb801c85000 rw-p 00000000 00:00 0 -30713ff00000-30713ff25000 rw-p 00000000 00:00 0 -31278c7c9000-31278c7ca000 r-xp 00000000 00:00 0 -3190d6f35000-3190d6f36000 rw-p 00000000 00:00 0 -3190d6f36000-3190d7135000 ---p 00000000 00:00 0 -7f62f5a2b000-7f62f607b000 rw-p 00000000 00:00 0 -7f62f607b000-7f62f6301000 rw-- 00000000 00:00 888963090 /SYSV00000000 (deleted) -7f62f6301000-7f62f6311000 rw-p 00000000 00:00 0 -7f62f6311000-7f62f6362000 r--- 00000000 00:00 1323029 /usr/share/fonts/truetype/msttcorefonts/Times_New_Roman.ttf -7f62f6362000-7f62f64d2000 rw-p 00000000 00:00 0 -7f62f64fe000-7f62f6542000 r--- 00000000 00:00 1323020 /usr/share/fonts/truetype/msttcorefonts/Arial.ttf -7f62f6542000-7f62f65b2000 rw-p 00000000 00:00 0 -7f62f65b2000-7f62f6804000 rw-- 00000000 00:00 888930318 /SYSV00000000 (deleted) -7f62f6804000-7f62f6984000 rw-p 00000000 00:00 0 -7f62f6984000-7f62f69a4000 r--- 00000000 00:00 14645040 /run/shm/.org.chromium.Chromium.KmCcUm (deleted) -7f62f69a4000-7f62f6a44000 rw-p 00000000 00:00 0 -7f62f6a44000-7f62f6a45000 ---p 00000000 00:00 0 -7f62f6a45000-7f62f6a55000 rw-p 00000000 00:00 0 -7f62f6a55000-7f62f6a56000 ---p 00000000 00:00 0 -7f62f6a56000-7f62f6af6000 rw-p 00000000 00:00 0 -7f62f6af6000-7f62f6af7000 ---p 00000000 00:00 0 -7f62f6af7000-7f62f72f7000 rw-p 00000000 00:00 0 -7f62f72f7000-7f62f72f8000 ---p 00000000 00:00 0 -7f62f72f8000-7f62f7af8000 rw-p 00000000 00:00 0 -7f62f7af8000-7f62f7bd6000 r-xp 00000000 00:00 6311146 /home/user/chromium/src/out/Debug/libppGoogleNaClPluginChrome.so -7f62f7bd6000-7f62f7bd7000 ---p 000de000 00:00 6311146 /home/user/chromium/src/out/Debug/libppGoogleNaClPluginChrome.so -7f62f7bd7000-7f62f7bda000 r--p 000de000 00:00 6311146 /home/user/chromium/src/out/Debug/libppGoogleNaClPluginChrome.so -7f62f7bda000-7f62f7bdc000 rw-p 000e1000 00:00 6311146 /home/user/chromium/src/out/Debug/libppGoogleNaClPluginChrome.so -7f62f7bdc000-7f62f7c3e000 r-xp 00000000 00:00 422206 /usr/lib/x86_64-linux-gnu/nss/libfreebl3.so -7f62f7c3e000-7f62f7e3d000 ---p 00062000 00:00 422206 /usr/lib/x86_64-linux-gnu/nss/libfreebl3.so -7f62f7e3d000-7f62f7e3f000 r--p 00061000 00:00 422206 /usr/lib/x86_64-linux-gnu/nss/libfreebl3.so -7f62f7e3f000-7f62f7e40000 rw-p 00063000 00:00 422206 /usr/lib/x86_64-linux-gnu/nss/libfreebl3.so -7f62f7e40000-7f62f7e44000 rw-p 00000000 00:00 0 -7f62f7e44000-7f62f7ee2000 r-xp 00000000 00:00 419056 /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6 -7f62f7ee2000-7f62f80e2000 ---p 0009e000 00:00 419056 /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6 -7f62f80e2000-7f62f80e4000 r--p 0009e000 00:00 419056 /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6 -7f62f80e4000-7f62f80e6000 rw-p 000a0000 00:00 419056 /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6 -7f62f80e6000-7f62f80e7000 rw-p 00000000 00:00 0 -7f62f80f6000-7f62f8106000 rw-p 00000000 00:00 0 -7f62f8106000-7f62f813e000 r-xp 00000000 00:00 422227 /usr/lib/x86_64-linux-gnu/nss/libsoftokn3.so -7f62f813e000-7f62f833d000 ---p 00038000 00:00 422227 /usr/lib/x86_64-linux-gnu/nss/libsoftokn3.so -7f62f833d000-7f62f833f000 r--p 00037000 00:00 422227 /usr/lib/x86_64-linux-gnu/nss/libsoftokn3.so -7f62f833f000-7f62f8340000 rw-p 00039000 00:00 422227 /usr/lib/x86_64-linux-gnu/nss/libsoftokn3.so -7f62f8340000-7f62f84fd000 r-xp 00000000 00:00 6311921 /home/user/chromium/src/out/Debug/libffmpegsumo.so -7f62f84fd000-7f62f84fe000 ---p 001bd000 00:00 6311921 /home/user/chromium/src/out/Debug/libffmpegsumo.so -7f62f84fe000-7f62f850e000 r--p 001bd000 00:00 6311921 /home/user/chromium/src/out/Debug/libffmpegsumo.so -7f62f850e000-7f62f8510000 rw-p 001cd000 00:00 6311921 /home/user/chromium/src/out/Debug/libffmpegsumo.so -7f62f8510000-7f62f85b3000 rw-p 00000000 00:00 0 -7f62f85b3000-7f62f8ad7000 r--- 00000000 00:00 6968058 /home/user/chromium/src/out/Debug/resources.pak -7f62f8ad7000-7f62f8b01000 r--- 00000000 00:00 6966120 /home/user/chromium/src/out/Debug/locales/en-US.pak -7f62f8b01000-7f62f8bd6000 r--- 00000000 00:00 6966021 /home/user/chromium/src/out/Debug/chrome_100_percent.pak -7f62f8bd6000-7f62f8f7d000 r--- 00000000 00:00 6966014 /home/user/chromium/src/out/Debug/chrome.pak -7f62f8f7d000-7f62f8fce000 rw-p 00000000 00:00 0 -7f62f8fce000-7f62f9d21000 r--p 00000000 00:00 795151 /usr/lib/locale/locale-archive -7f62f9d21000-7f62fa621000 rw-p 00000000 00:00 0 -7f62fa621000-7f62fa626000 r-xp 00000000 00:00 418995 /usr/lib/x86_64-linux-gnu/libXdmcp.so.6.0.0 -7f62fa626000-7f62fa825000 ---p 00005000 00:00 418995 /usr/lib/x86_64-linux-gnu/libXdmcp.so.6.0.0 -7f62fa825000-7f62fa826000 r--p 00004000 00:00 418995 /usr/lib/x86_64-linux-gnu/libXdmcp.so.6.0.0 -7f62fa826000-7f62fa827000 rw-p 00005000 00:00 418995 /usr/lib/x86_64-linux-gnu/libXdmcp.so.6.0.0 -7f62fa827000-7f62fa829000 r-xp 00000000 00:00 419161 /usr/lib/x86_64-linux-gnu/libXau.so.6.0.0 -7f62fa829000-7f62faa28000 ---p 00002000 00:00 419161 /usr/lib/x86_64-linux-gnu/libXau.so.6.0.0 -7f62faa28000-7f62faa29000 r--p 00001000 00:00 419161 /usr/lib/x86_64-linux-gnu/libXau.so.6.0.0 -7f62faa29000-7f62faa2a000 rw-p 00002000 00:00 419161 /usr/lib/x86_64-linux-gnu/libXau.so.6.0.0 -7f62faa2a000-7f62faa2d000 r-xp 00000000 00:00 262419 /lib/x86_64-linux-gnu/libgpg-error.so.0.8.0 -7f62faa2d000-7f62fac2c000 ---p 00003000 00:00 262419 /lib/x86_64-linux-gnu/libgpg-error.so.0.8.0 -7f62fac2c000-7f62fac2d000 r--p 00002000 00:00 262419 /lib/x86_64-linux-gnu/libgpg-error.so.0.8.0 -7f62fac2d000-7f62fac2e000 rw-p 00003000 00:00 262419 /lib/x86_64-linux-gnu/libgpg-error.so.0.8.0 -7f62fac2e000-7f62fac3f000 r-xp 00000000 00:00 419811 /usr/lib/x86_64-linux-gnu/libp11-kit.so.0.0.0 -7f62fac3f000-7f62fae3e000 ---p 00011000 00:00 419811 /usr/lib/x86_64-linux-gnu/libp11-kit.so.0.0.0 -7f62fae3e000-7f62fae3f000 r--p 00010000 00:00 419811 /usr/lib/x86_64-linux-gnu/libp11-kit.so.0.0.0 -7f62fae3f000-7f62fae40000 rw-p 00011000 00:00 419811 /usr/lib/x86_64-linux-gnu/libp11-kit.so.0.0.0 -7f62fae40000-7f62fae50000 r-xp 00000000 00:00 420094 /usr/lib/x86_64-linux-gnu/libtasn1.so.3.1.12 -7f62fae50000-7f62fb04f000 ---p 00010000 00:00 420094 /usr/lib/x86_64-linux-gnu/libtasn1.so.3.1.12 -7f62fb04f000-7f62fb050000 r--p 0000f000 00:00 420094 /usr/lib/x86_64-linux-gnu/libtasn1.so.3.1.12 -7f62fb050000-7f62fb051000 rw-p 00010000 00:00 420094 /usr/lib/x86_64-linux-gnu/libtasn1.so.3.1.12 -7f62fb051000-7f62fb054000 r-xp 00000000 00:00 262413 /lib/x86_64-linux-gnu/libkeyutils.so.1.4 -7f62fb054000-7f62fb253000 ---p 00003000 00:00 262413 /lib/x86_64-linux-gnu/libkeyutils.so.1.4 -7f62fb253000-7f62fb254000 r--p 00002000 00:00 262413 /lib/x86_64-linux-gnu/libkeyutils.so.1.4 -7f62fb254000-7f62fb255000 rw-p 00003000 00:00 262413 /lib/x86_64-linux-gnu/libkeyutils.so.1.4 -7f62fb255000-7f62fb25c000 r-xp 00000000 00:00 418378 /usr/lib/x86_64-linux-gnu/libkrb5support.so.0.1 -7f62fb25c000-7f62fb45b000 ---p 00007000 00:00 418378 /usr/lib/x86_64-linux-gnu/libkrb5support.so.0.1 -7f62fb45b000-7f62fb45c000 r--p 00006000 00:00 418378 /usr/lib/x86_64-linux-gnu/libkrb5support.so.0.1 -7f62fb45c000-7f62fb45d000 rw-p 00007000 00:00 418378 /usr/lib/x86_64-linux-gnu/libkrb5support.so.0.1 -7f62fb45d000-7f62fb46d000 r-xp 00000000 00:00 419369 /usr/lib/x86_64-linux-gnu/libavahi-client.so.3.2.9 -7f62fb46d000-7f62fb66c000 ---p 00010000 00:00 419369 /usr/lib/x86_64-linux-gnu/libavahi-client.so.3.2.9 -7f62fb66c000-7f62fb66d000 r--p 0000f000 00:00 419369 /usr/lib/x86_64-linux-gnu/libavahi-client.so.3.2.9 -7f62fb66d000-7f62fb66e000 rw-p 00010000 00:00 419369 /usr/lib/x86_64-linux-gnu/libavahi-client.so.3.2.9 -7f62fb66e000-7f62fb679000 r-xp 00000000 00:00 420318 /usr/lib/x86_64-linux-gnu/libavahi-common.so.3.5.3 -7f62fb679000-7f62fb878000 ---p 0000b000 00:00 420318 /usr/lib/x86_64-linux-gnu/libavahi-common.so.3.5.3 -7f62fb878000-7f62fb879000 r--p 0000a000 00:00 420318 /usr/lib/x86_64-linux-gnu/libavahi-common.so.3.5.3 -7f62fb879000-7f62fb87a000 rw-p 0000b000 00:00 420318 /usr/lib/x86_64-linux-gnu/libavahi-common.so.3.5.3 -7f62fb87a000-7f62fb89f000 r-xp 00000000 00:00 420145 /usr/lib/x86_64-linux-gnu/libdbus-glib-1.so.2.2.2 -7f62fb89f000-7f62fba9f000 ---p 00025000 00:00 420145 /usr/lib/x86_64-linux-gnu/libdbus-glib-1.so.2.2.2 -7f62fba9f000-7f62fbaa0000 r--p 00025000 00:00 420145 /usr/lib/x86_64-linux-gnu/libdbus-glib-1.so.2.2.2 -7f62fbaa0000-7f62fbaa1000 rw-p 00026000 00:00 420145 /usr/lib/x86_64-linux-gnu/libdbus-glib-1.so.2.2.2 -7f62fbaa1000-7f62fbaa9000 r-xp 00000000 00:00 401299 /usr/lib/x86_64-linux-gnu/libxcb-render.so.0.0.0 -7f62fbaa9000-7f62fbca9000 ---p 00008000 00:00 401299 /usr/lib/x86_64-linux-gnu/libxcb-render.so.0.0.0 -7f62fbca9000-7f62fbcaa000 r--p 00008000 00:00 401299 /usr/lib/x86_64-linux-gnu/libxcb-render.so.0.0.0 -7f62fbcaa000-7f62fbcab000 rw-p 00009000 00:00 401299 /usr/lib/x86_64-linux-gnu/libxcb-render.so.0.0.0 -7f62fbcab000-7f62fbcad000 r-xp 00000000 00:00 396366 /usr/lib/x86_64-linux-gnu/libxcb-shm.so.0.0.0 -7f62fbcad000-7f62fbeac000 ---p 00002000 00:00 396366 /usr/lib/x86_64-linux-gnu/libxcb-shm.so.0.0.0 -7f62fbeac000-7f62fbead000 r--p 00001000 00:00 396366 /usr/lib/x86_64-linux-gnu/libxcb-shm.so.0.0.0 -7f62fbead000-7f62fbeae000 rw-p 00002000 00:00 396366 /usr/lib/x86_64-linux-gnu/libxcb-shm.so.0.0.0 -7f62fbeae000-7f62fbed4000 r-xp 00000000 00:00 262376 /lib/x86_64-linux-gnu/libpng12.so.0.46.0 -7f62fbed4000-7f62fc0d4000 ---p 00026000 00:00 262376 /lib/x86_64-linux-gnu/libpng12.so.0.46.0 -7f62fc0d4000-7f62fc0d5000 r--p 00026000 00:00 262376 /lib/x86_64-linux-gnu/libpng12.so.0.46.0 -7f62fc0d5000-7f62fc0d6000 rw-p 00027000 00:00 262376 /lib/x86_64-linux-gnu/libpng12.so.0.46.0 -7f62fc0d6000-7f62fc157000 r-xp 00000000 00:00 419692 /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.24.4 -7f62fc157000-7f62fc356000 ---p 00081000 00:00 419692 /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.24.4 -7f62fc356000-7f62fc35c000 r--p 00080000 00:00 419692 /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.24.4 -7f62fc35c000-7f62fc35d000 rw-p 00086000 00:00 419692 /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.24.4 -7f62fc35d000-7f62fc37a000 r-xp 00000000 00:00 262459 /lib/x86_64-linux-gnu/libselinux.so.1 -7f62fc37a000-7f62fc579000 ---p 0001d000 00:00 262459 /lib/x86_64-linux-gnu/libselinux.so.1 -7f62fc579000-7f62fc57a000 r--p 0001c000 00:00 262459 /lib/x86_64-linux-gnu/libselinux.so.1 -7f62fc57a000-7f62fc57b000 rw-p 0001d000 00:00 262459 /lib/x86_64-linux-gnu/libselinux.so.1 -7f62fc57b000-7f62fc57c000 rw-p 00000000 00:00 0 -7f62fc57c000-7f62fc57e000 r-xp 00000000 00:00 419344 /usr/lib/x86_64-linux-gnu/libXinerama.so.1.0.0 -7f62fc57e000-7f62fc77d000 ---p 00002000 00:00 419344 /usr/lib/x86_64-linux-gnu/libXinerama.so.1.0.0 -7f62fc77d000-7f62fc77e000 r--p 00001000 00:00 419344 /usr/lib/x86_64-linux-gnu/libXinerama.so.1.0.0 -7f62fc77e000-7f62fc77f000 rw-p 00002000 00:00 419344 /usr/lib/x86_64-linux-gnu/libXinerama.so.1.0.0 -7f62fc77f000-7f62fc7bb000 r-xp 00000000 00:00 262390 /lib/x86_64-linux-gnu/libpcre.so.3.12.1 -7f62fc7bb000-7f62fc9ba000 ---p 0003c000 00:00 262390 /lib/x86_64-linux-gnu/libpcre.so.3.12.1 -7f62fc9ba000-7f62fc9bb000 r--p 0003b000 00:00 262390 /lib/x86_64-linux-gnu/libpcre.so.3.12.1 -7f62fc9bb000-7f62fc9bc000 rw-p 0003c000 00:00 262390 /lib/x86_64-linux-gnu/libpcre.so.3.12.1 -7f62fc9bc000-7f62fc9c3000 r-xp 00000000 00:00 419528 /usr/lib/x86_64-linux-gnu/libffi.so.6.0.0 -7f62fc9c3000-7f62fcbc2000 ---p 00007000 00:00 419528 /usr/lib/x86_64-linux-gnu/libffi.so.6.0.0 -7f62fcbc2000-7f62fcbc3000 r--p 00006000 00:00 419528 /usr/lib/x86_64-linux-gnu/libffi.so.6.0.0 -7f62fcbc3000-7f62fcbc4000 rw-p 00007000 00:00 419528 /usr/lib/x86_64-linux-gnu/libffi.so.6.0.0 -7f62fcbc4000-7f62fcbe1000 r-xp 00000000 00:00 400302 /usr/lib/x86_64-linux-gnu/libxcb.so.1.1.0 -7f62fcbe1000-7f62fcde0000 ---p 0001d000 00:00 400302 /usr/lib/x86_64-linux-gnu/libxcb.so.1.1.0 -7f62fcde0000-7f62fcde1000 r--p 0001c000 00:00 400302 /usr/lib/x86_64-linux-gnu/libxcb.so.1.1.0 -7f62fcde1000-7f62fcde2000 rw-p 0001d000 00:00 400302 /usr/lib/x86_64-linux-gnu/libxcb.so.1.1.0 -7f62fcde2000-7f62fcf97000 r-xp 00000000 00:00 263480 /lib/x86_64-linux-gnu/libc-2.15.so -7f62fcf97000-7f62fd196000 ---p 001b5000 00:00 263480 /lib/x86_64-linux-gnu/libc-2.15.so -7f62fd196000-7f62fd19a000 r--p 001b4000 00:00 263480 /lib/x86_64-linux-gnu/libc-2.15.so -7f62fd19a000-7f62fd19c000 rw-p 001b8000 00:00 263480 /lib/x86_64-linux-gnu/libc-2.15.so -7f62fd19c000-7f62fd1a1000 rw-p 00000000 00:00 0 -7f62fd1a1000-7f62fd1b6000 r-xp 00000000 00:00 262366 /lib/x86_64-linux-gnu/libgcc_s.so.1 -7f62fd1b6000-7f62fd3b5000 ---p 00015000 00:00 262366 /lib/x86_64-linux-gnu/libgcc_s.so.1 -7f62fd3b5000-7f62fd3b6000 r--p 00014000 00:00 262366 /lib/x86_64-linux-gnu/libgcc_s.so.1 -7f62fd3b6000-7f62fd3b7000 rw-p 00015000 00:00 262366 /lib/x86_64-linux-gnu/libgcc_s.so.1 -7f62fd3b7000-7f62fd499000 r-xp 00000000 00:00 419083 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16 -7f62fd499000-7f62fd698000 ---p 000e2000 00:00 419083 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16 -7f62fd698000-7f62fd6a0000 r--p 000e1000 00:00 419083 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16 -7f62fd6a0000-7f62fd6a2000 rw-p 000e9000 00:00 419083 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16 -7f62fd6a2000-7f62fd6b7000 rw-p 00000000 00:00 0 -7f62fd6b7000-7f62fd6c3000 r-xp 00000000 00:00 262197 /lib/x86_64-linux-gnu/libudev.so.0.13.0 -7f62fd6c3000-7f62fd8c2000 ---p 0000c000 00:00 262197 /lib/x86_64-linux-gnu/libudev.so.0.13.0 -7f62fd8c2000-7f62fd8c3000 r--p 0000b000 00:00 262197 /lib/x86_64-linux-gnu/libudev.so.0.13.0 -7f62fd8c3000-7f62fd8c4000 rw-p 0000c000 00:00 262197 /lib/x86_64-linux-gnu/libudev.so.0.13.0 -7f62fd8c4000-7f62fd8eb000 r-xp 00000000 00:00 262435 /lib/x86_64-linux-gnu/libexpat.so.1.5.2 -7f62fd8eb000-7f62fdaeb000 ---p 00027000 00:00 262435 /lib/x86_64-linux-gnu/libexpat.so.1.5.2 -7f62fdaeb000-7f62fdaed000 r--p 00027000 00:00 262435 /lib/x86_64-linux-gnu/libexpat.so.1.5.2 -7f62fdaed000-7f62fdaee000 rw-p 00029000 00:00 262435 /lib/x86_64-linux-gnu/libexpat.so.1.5.2 -7f62fdaee000-7f62fdafd000 r-xp 00000000 00:00 262446 /lib/x86_64-linux-gnu/libbz2.so.1.0.4 -7f62fdafd000-7f62fdcfc000 ---p 0000f000 00:00 262446 /lib/x86_64-linux-gnu/libbz2.so.1.0.4 -7f62fdcfc000-7f62fdcfd000 r--p 0000e000 00:00 262446 /lib/x86_64-linux-gnu/libbz2.so.1.0.4 -7f62fdcfd000-7f62fdcfe000 rw-p 0000f000 00:00 262446 /lib/x86_64-linux-gnu/libbz2.so.1.0.4 -7f62fdcfe000-7f62fddf9000 r-xp 00000000 00:00 296562 /lib/x86_64-linux-gnu/libm-2.15.so -7f62fddf9000-7f62fdff8000 ---p 000fb000 00:00 296562 /lib/x86_64-linux-gnu/libm-2.15.so -7f62fdff8000-7f62fdff9000 r--p 000fa000 00:00 296562 /lib/x86_64-linux-gnu/libm-2.15.so -7f62fdff9000-7f62fdffa000 rw-p 000fb000 00:00 296562 /lib/x86_64-linux-gnu/libm-2.15.so -7f62fdffa000-7f62fe003000 r-xp 00000000 00:00 296563 /lib/x86_64-linux-gnu/libcrypt-2.15.so -7f62fe003000-7f62fe203000 ---p 00009000 00:00 296563 /lib/x86_64-linux-gnu/libcrypt-2.15.so -7f62fe203000-7f62fe204000 r--p 00009000 00:00 296563 /lib/x86_64-linux-gnu/libcrypt-2.15.so -7f62fe204000-7f62fe205000 rw-p 0000a000 00:00 296563 /lib/x86_64-linux-gnu/libcrypt-2.15.so -7f62fe205000-7f62fe233000 rw-p 00000000 00:00 0 -7f62fe233000-7f62fe249000 r-xp 00000000 00:00 262537 /lib/x86_64-linux-gnu/libz.so.1.2.3.4 -7f62fe249000-7f62fe448000 ---p 00016000 00:00 262537 /lib/x86_64-linux-gnu/libz.so.1.2.3.4 -7f62fe448000-7f62fe449000 r--p 00015000 00:00 262537 /lib/x86_64-linux-gnu/libz.so.1.2.3.4 -7f62fe449000-7f62fe44a000 rw-p 00016000 00:00 262537 /lib/x86_64-linux-gnu/libz.so.1.2.3.4 -7f62fe44a000-7f62fe4c4000 r-xp 00000000 00:00 262361 /lib/x86_64-linux-gnu/libgcrypt.so.11.7.0 -7f62fe4c4000-7f62fe6c4000 ---p 0007a000 00:00 262361 /lib/x86_64-linux-gnu/libgcrypt.so.11.7.0 -7f62fe6c4000-7f62fe6c5000 r--p 0007a000 00:00 262361 /lib/x86_64-linux-gnu/libgcrypt.so.11.7.0 -7f62fe6c5000-7f62fe6c8000 rw-p 0007b000 00:00 262361 /lib/x86_64-linux-gnu/libgcrypt.so.11.7.0 -7f62fe6c8000-7f62fe77c000 r-xp 00000000 00:00 419320 /usr/lib/x86_64-linux-gnu/libgnutls.so.26.21.8 -7f62fe77c000-7f62fe97c000 ---p 000b4000 00:00 419320 /usr/lib/x86_64-linux-gnu/libgnutls.so.26.21.8 -7f62fe97c000-7f62fe982000 r--p 000b4000 00:00 419320 /usr/lib/x86_64-linux-gnu/libgnutls.so.26.21.8 -7f62fe982000-7f62fe983000 rw-p 000ba000 00:00 419320 /usr/lib/x86_64-linux-gnu/libgnutls.so.26.21.8 -7f62fe983000-7f62fe984000 rw-p 00000000 00:00 0 -7f62fe984000-7f62fe987000 r-xp 00000000 00:00 262402 /lib/x86_64-linux-gnu/libcom_err.so.2.1 -7f62fe987000-7f62feb86000 ---p 00003000 00:00 262402 /lib/x86_64-linux-gnu/libcom_err.so.2.1 -7f62feb86000-7f62feb87000 r--p 00002000 00:00 262402 /lib/x86_64-linux-gnu/libcom_err.so.2.1 -7f62feb87000-7f62feb88000 rw-p 00003000 00:00 262402 /lib/x86_64-linux-gnu/libcom_err.so.2.1 -7f62feb88000-7f62febad000 r-xp 00000000 00:00 419096 /usr/lib/x86_64-linux-gnu/libk5crypto.so.3.1 -7f62febad000-7f62fedad000 ---p 00025000 00:00 419096 /usr/lib/x86_64-linux-gnu/libk5crypto.so.3.1 -7f62fedad000-7f62fedae000 r--p 00025000 00:00 419096 /usr/lib/x86_64-linux-gnu/libk5crypto.so.3.1 -7f62fedae000-7f62fedaf000 rw-p 00026000 00:00 419096 /usr/lib/x86_64-linux-gnu/libk5crypto.so.3.1 -7f62fedaf000-7f62fedb0000 rw-p 00000000 00:00 0 -7f62fedb0000-7f62fee74000 r-xp 00000000 00:00 420204 /usr/lib/x86_64-linux-gnu/libkrb5.so.3.3 -7f62fee74000-7f62ff073000 ---p 000c4000 00:00 420204 /usr/lib/x86_64-linux-gnu/libkrb5.so.3.3 -7f62ff073000-7f62ff07d000 r--p 000c3000 00:00 420204 /usr/lib/x86_64-linux-gnu/libkrb5.so.3.3 -7f62ff07d000-7f62ff07e000 rw-p 000cd000 00:00 420204 /usr/lib/x86_64-linux-gnu/libkrb5.so.3.3 -7f62ff07e000-7f62ff0b9000 r-xp 00000000 00:00 420086 /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2 -7f62ff0b9000-7f62ff2b9000 ---p 0003b000 00:00 420086 /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2 -7f62ff2b9000-7f62ff2ba000 r--p 0003b000 00:00 420086 /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2 -7f62ff2ba000-7f62ff2bc000 rw-p 0003c000 00:00 420086 /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2 -7f62ff2bc000-7f62ff30c000 r-xp 00000000 00:00 444357 /usr/lib/x86_64-linux-gnu/libcups.so.2 -7f62ff30c000-7f62ff50b000 ---p 00050000 00:00 444357 /usr/lib/x86_64-linux-gnu/libcups.so.2 -7f62ff50b000-7f62ff50f000 r--p 0004f000 00:00 444357 /usr/lib/x86_64-linux-gnu/libcups.so.2 -7f62ff50f000-7f62ff510000 rw-p 00053000 00:00 444357 /usr/lib/x86_64-linux-gnu/libcups.so.2 -7f62ff510000-7f62ff515000 r-xp 00000000 00:00 419317 /usr/lib/x86_64-linux-gnu/libXfixes.so.3.1.0 -7f62ff515000-7f62ff714000 ---p 00005000 00:00 419317 /usr/lib/x86_64-linux-gnu/libXfixes.so.3.1.0 -7f62ff714000-7f62ff715000 r--p 00004000 00:00 419317 /usr/lib/x86_64-linux-gnu/libXfixes.so.3.1.0 -7f62ff715000-7f62ff716000 rw-p 00005000 00:00 419317 /usr/lib/x86_64-linux-gnu/libXfixes.so.3.1.0 -7f62ff716000-7f62ff718000 r-xp 00000000 00:00 419868 /usr/lib/x86_64-linux-gnu/libXdamage.so.1.1.0 -7f62ff718000-7f62ff917000 ---p 00002000 00:00 419868 /usr/lib/x86_64-linux-gnu/libXdamage.so.1.1.0 -7f62ff917000-7f62ff918000 r--p 00001000 00:00 419868 /usr/lib/x86_64-linux-gnu/libXdamage.so.1.1.0 -7f62ff918000-7f62ff919000 rw-p 00002000 00:00 419868 /usr/lib/x86_64-linux-gnu/libXdamage.so.1.1.0 -7f62ff919000-7f62ff9ff000 r-xp 00000000 00:00 419887 /usr/lib/x86_64-linux-gnu/libasound.so.2.0.0 -7f62ff9ff000-7f62ffbff000 ---p 000e6000 00:00 419887 /usr/lib/x86_64-linux-gnu/libasound.so.2.0.0 -7f62ffbff000-7f62ffc05000 r--p 000e6000 00:00 419887 /usr/lib/x86_64-linux-gnu/libasound.so.2.0.0 -7f62ffc05000-7f62ffc06000 rw-p 000ec000 00:00 419887 /usr/lib/x86_64-linux-gnu/libasound.so.2.0.0 -7f62ffc06000-7f62ffc08000 r-xp 00000000 00:00 419816 /usr/lib/x86_64-linux-gnu/libXcomposite.so.1.0.0 -7f62ffc08000-7f62ffe07000 ---p 00002000 00:00 419816 /usr/lib/x86_64-linux-gnu/libXcomposite.so.1.0.0 -7f62ffe07000-7f62ffe08000 r--p 00001000 00:00 419816 /usr/lib/x86_64-linux-gnu/libXcomposite.so.1.0.0 -7f62ffe08000-7f62ffe09000 rw-p 00002000 00:00 419816 /usr/lib/x86_64-linux-gnu/libXcomposite.so.1.0.0 -7f62ffe09000-7f62ffe21000 r-xp 00000000 00:00 263482 /lib/x86_64-linux-gnu/libpthread-2.15.so -7f62ffe21000-7f6300020000 ---p 00018000 00:00 263482 /lib/x86_64-linux-gnu/libpthread-2.15.so -7f6300020000-7f6300021000 r--p 00017000 00:00 263482 /lib/x86_64-linux-gnu/libpthread-2.15.so -7f6300021000-7f6300022000 rw-p 00018000 00:00 263482 /lib/x86_64-linux-gnu/libpthread-2.15.so -7f6300022000-7f6300026000 rw-p 00000000 00:00 0 -7f6300026000-7f6300068000 r-xp 00000000 00:00 262204 /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8 -7f6300068000-7f6300268000 ---p 00042000 00:00 262204 /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8 -7f6300268000-7f6300269000 r--p 00042000 00:00 262204 /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8 -7f6300269000-7f630026a000 rw-p 00043000 00:00 262204 /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8 -7f630026a000-7f6300282000 r-xp 00000000 00:00 289099 /lib/x86_64-linux-gnu/libresolv-2.15.so -7f6300282000-7f6300482000 ---p 00018000 00:00 289099 /lib/x86_64-linux-gnu/libresolv-2.15.so -7f6300482000-7f6300483000 r--p 00018000 00:00 289099 /lib/x86_64-linux-gnu/libresolv-2.15.so -7f6300483000-7f6300484000 rw-p 00019000 00:00 289099 /lib/x86_64-linux-gnu/libresolv-2.15.so -7f6300484000-7f6300486000 rw-p 00000000 00:00 0 -7f6300486000-7f63004b3000 r-xp 00000000 00:00 419655 /usr/lib/x86_64-linux-gnu/libgconf-2.so.4.1.5 -7f63004b3000-7f63006b2000 ---p 0002d000 00:00 419655 /usr/lib/x86_64-linux-gnu/libgconf-2.so.4.1.5 -7f63006b2000-7f63006b3000 r--p 0002c000 00:00 419655 /usr/lib/x86_64-linux-gnu/libgconf-2.so.4.1.5 -7f63006b3000-7f63006b4000 rw-p 0002d000 00:00 419655 /usr/lib/x86_64-linux-gnu/libgconf-2.so.4.1.5 -7f63006b4000-7f63006ee000 r-xp 00000000 00:00 422225 /usr/lib/x86_64-linux-gnu/libnspr4.so -7f63006ee000-7f63008ee000 ---p 0003a000 00:00 422225 /usr/lib/x86_64-linux-gnu/libnspr4.so -7f63008ee000-7f63008ef000 r--p 0003a000 00:00 422225 /usr/lib/x86_64-linux-gnu/libnspr4.so -7f63008ef000-7f63008f1000 rw-p 0003b000 00:00 422225 /usr/lib/x86_64-linux-gnu/libnspr4.so -7f63008f1000-7f63008f3000 rw-p 00000000 00:00 0 -7f63008f3000-7f63008f7000 r-xp 00000000 00:00 422220 /usr/lib/x86_64-linux-gnu/libplc4.so -7f63008f7000-7f6300af6000 ---p 00004000 00:00 422220 /usr/lib/x86_64-linux-gnu/libplc4.so -7f6300af6000-7f6300af7000 r--p 00003000 00:00 422220 /usr/lib/x86_64-linux-gnu/libplc4.so -7f6300af7000-7f6300af8000 rw-p 00004000 00:00 422220 /usr/lib/x86_64-linux-gnu/libplc4.so -7f6300af8000-7f6300afb000 r-xp 00000000 00:00 422218 /usr/lib/x86_64-linux-gnu/libplds4.so -7f6300afb000-7f6300cfa000 ---p 00003000 00:00 422218 /usr/lib/x86_64-linux-gnu/libplds4.so -7f6300cfa000-7f6300cfb000 r--p 00002000 00:00 422218 /usr/lib/x86_64-linux-gnu/libplds4.so -7f6300cfb000-7f6300cfc000 rw-p 00003000 00:00 422218 /usr/lib/x86_64-linux-gnu/libplds4.so -7f6300cfc000-7f6300d1f000 r-xp 00000000 00:00 422231 /usr/lib/x86_64-linux-gnu/libsmime3.so -7f6300d1f000-7f6300f1f000 ---p 00023000 00:00 422231 /usr/lib/x86_64-linux-gnu/libsmime3.so -7f6300f1f000-7f6300f22000 r--p 00023000 00:00 422231 /usr/lib/x86_64-linux-gnu/libsmime3.so -7f6300f22000-7f6300f23000 rw-p 00026000 00:00 422231 /usr/lib/x86_64-linux-gnu/libsmime3.so -7f6300f23000-7f6300f44000 r-xp 00000000 00:00 420737 /usr/lib/x86_64-linux-gnu/libnssutil3.so -7f6300f44000-7f6301143000 ---p 00021000 00:00 420737 /usr/lib/x86_64-linux-gnu/libnssutil3.so -7f6301143000-7f6301149000 r--p 00020000 00:00 420737 /usr/lib/x86_64-linux-gnu/libnssutil3.so -7f6301149000-7f630114a000 rw-p 00026000 00:00 420737 /usr/lib/x86_64-linux-gnu/libnssutil3.so -7f630114a000-7f6301249000 r-xp 00000000 00:00 420704 /usr/lib/x86_64-linux-gnu/libnss3.so -7f6301249000-7f6301448000 ---p 000ff000 00:00 420704 /usr/lib/x86_64-linux-gnu/libnss3.so -7f6301448000-7f630144d000 r--p 000fe000 00:00 420704 /usr/lib/x86_64-linux-gnu/libnss3.so -7f630144d000-7f630144f000 rw-p 00103000 00:00 420704 /usr/lib/x86_64-linux-gnu/libnss3.so -7f630144f000-7f6301451000 rw-p 00000000 00:00 0 -7f6301451000-7f6301485000 r-xp 00000000 00:00 419748 /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4 -7f6301485000-7f6301685000 ---p 00034000 00:00 419748 /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4 -7f6301685000-7f6301686000 r--p 00034000 00:00 419748 /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4 -7f6301686000-7f6301687000 rw-p 00035000 00:00 419748 /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4 -7f6301687000-7f630171d000 r-xp 00000000 00:00 420767 /usr/lib/x86_64-linux-gnu/libfreetype.so.6.8.0 -7f630171d000-7f630191c000 ---p 00096000 00:00 420767 /usr/lib/x86_64-linux-gnu/libfreetype.so.6.8.0 -7f630191c000-7f6301922000 r--p 00095000 00:00 420767 /usr/lib/x86_64-linux-gnu/libfreetype.so.6.8.0 -7f6301922000-7f6301923000 rw-p 0009b000 00:00 420767 /usr/lib/x86_64-linux-gnu/libfreetype.so.6.8.0 -7f6301923000-7f6301969000 r-xp 00000000 00:00 419045 /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0 -7f6301969000-7f6301b69000 ---p 00046000 00:00 419045 /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0 -7f6301b69000-7f6301b6b000 r--p 00046000 00:00 419045 /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0 -7f6301b6b000-7f6301b6c000 rw-p 00048000 00:00 419045 /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.3000.0 -7f6301b6c000-7f6301c25000 r-xp 00000000 00:00 418996 /usr/lib/x86_64-linux-gnu/libcairo.so.2.11000.2 -7f6301c25000-7f6301e24000 ---p 000b9000 00:00 418996 /usr/lib/x86_64-linux-gnu/libcairo.so.2.11000.2 -7f6301e24000-7f6301e26000 r--p 000b8000 00:00 418996 /usr/lib/x86_64-linux-gnu/libcairo.so.2.11000.2 -7f6301e26000-7f6301e27000 rw-p 000ba000 00:00 418996 /usr/lib/x86_64-linux-gnu/libcairo.so.2.11000.2 -7f6301e27000-7f6301e2a000 rw-p 00000000 00:00 0 -7f6301e2a000-7f6301e48000 r-xp 00000000 00:00 419133 /usr/lib/x86_64-linux-gnu/libgdk_pixbuf-2.0.so.0.2600.1 -7f6301e48000-7f6302048000 ---p 0001e000 00:00 419133 /usr/lib/x86_64-linux-gnu/libgdk_pixbuf-2.0.so.0.2600.1 -7f6302048000-7f6302049000 r--p 0001e000 00:00 419133 /usr/lib/x86_64-linux-gnu/libgdk_pixbuf-2.0.so.0.2600.1 -7f6302049000-7f630204a000 rw-p 0001f000 00:00 419133 /usr/lib/x86_64-linux-gnu/libgdk_pixbuf-2.0.so.0.2600.1 -7f630204a000-7f6302055000 r-xp 00000000 00:00 419820 /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0.3000.0 -7f6302055000-7f6302254000 ---p 0000b000 00:00 419820 /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0.3000.0 -7f6302254000-7f6302255000 r--p 0000a000 00:00 419820 /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0.3000.0 -7f6302255000-7f6302256000 rw-p 0000b000 00:00 419820 /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0.3000.0 -7f6302256000-7f630227f000 r-xp 00000000 00:00 419157 /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0 -7f630227f000-7f630247e000 ---p 00029000 00:00 419157 /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0 -7f630247e000-7f630247f000 r--p 00028000 00:00 419157 /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0 -7f630247f000-7f6302480000 rw-p 00029000 00:00 419157 /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.3000.0 -7f6302480000-7f63025c8000 r-xp 00000000 00:00 419294 /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.3200.3 -7f63025c8000-7f63027c7000 ---p 00148000 00:00 419294 /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.3200.3 -7f63027c7000-7f63027cb000 r--p 00147000 00:00 419294 /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.3200.3 -7f63027cb000-7f63027cd000 rw-p 0014b000 00:00 419294 /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.3200.3 -7f63027cd000-7f63027cf000 rw-p 00000000 00:00 0 -7f63027cf000-7f63027ee000 r-xp 00000000 00:00 420188 /usr/lib/x86_64-linux-gnu/libatk-1.0.so.0.20409.1 -7f63027ee000-7f63029ee000 ---p 0001f000 00:00 420188 /usr/lib/x86_64-linux-gnu/libatk-1.0.so.0.20409.1 -7f63029ee000-7f63029f0000 r--p 0001f000 00:00 420188 /usr/lib/x86_64-linux-gnu/libatk-1.0.so.0.20409.1 -7f63029f0000-7f63029f1000 rw-p 00021000 00:00 420188 /usr/lib/x86_64-linux-gnu/libatk-1.0.so.0.20409.1 -7f63029f1000-7f6302a9e000 r-xp 00000000 00:00 419013 /usr/lib/x86_64-linux-gnu/libgdk-x11-2.0.so.0.2400.10 -7f6302a9e000-7f6302c9d000 ---p 000ad000 00:00 419013 /usr/lib/x86_64-linux-gnu/libgdk-x11-2.0.so.0.2400.10 -7f6302c9d000-7f6302ca1000 r--p 000ac000 00:00 419013 /usr/lib/x86_64-linux-gnu/libgdk-x11-2.0.so.0.2400.10 -7f6302ca1000-7f6302ca3000 rw-p 000b0000 00:00 419013 /usr/lib/x86_64-linux-gnu/libgdk-x11-2.0.so.0.2400.10 -7f6302ca3000-7f63030d0000 r-xp 00000000 00:00 419385 /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.10 -7f63030d0000-7f63032d0000 ---p 0042d000 00:00 419385 /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.10 -7f63032d0000-7f63032d7000 r--p 0042d000 00:00 419385 /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.10 -7f63032d7000-7f63032db000 rw-p 00434000 00:00 419385 /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.10 -7f63032db000-7f63032dd000 rw-p 00000000 00:00 0 -7f63032dd000-7f63032eb000 r-xp 00000000 00:00 419600 /usr/lib/x86_64-linux-gnu/libXi.so.6.1.0 -7f63032eb000-7f63034ea000 ---p 0000e000 00:00 419600 /usr/lib/x86_64-linux-gnu/libXi.so.6.1.0 -7f63034ea000-7f63034eb000 r--p 0000d000 00:00 419600 /usr/lib/x86_64-linux-gnu/libXi.so.6.1.0 -7f63034eb000-7f63034ec000 rw-p 0000e000 00:00 419600 /usr/lib/x86_64-linux-gnu/libXi.so.6.1.0 -7f63034ec000-7f63035de000 r-xp 00000000 00:00 262368 /lib/x86_64-linux-gnu/libglib-2.0.so.0.3200.3 -7f63035de000-7f63037de000 ---p 000f2000 00:00 262368 /lib/x86_64-linux-gnu/libglib-2.0.so.0.3200.3 -7f63037de000-7f63037df000 r--p 000f2000 00:00 262368 /lib/x86_64-linux-gnu/libglib-2.0.so.0.3200.3 -7f63037df000-7f63037e0000 rw-p 000f3000 00:00 262368 /lib/x86_64-linux-gnu/libglib-2.0.so.0.3200.3 -7f63037e0000-7f63037e1000 rw-p 00000000 00:00 0 -7f63037e1000-7f63037e2000 r-xp 00000000 00:00 419135 /usr/lib/x86_64-linux-gnu/libgthread-2.0.so.0.3200.3 -7f63037e2000-7f63039e1000 ---p 00001000 00:00 419135 /usr/lib/x86_64-linux-gnu/libgthread-2.0.so.0.3200.3 -7f63039e1000-7f63039e2000 r--p 00000000 00:00 419135 /usr/lib/x86_64-linux-gnu/libgthread-2.0.so.0.3200.3 -7f63039e2000-7f63039e3000 rw-p 00001000 00:00 419135 /usr/lib/x86_64-linux-gnu/libgthread-2.0.so.0.3200.3 -7f63039e3000-7f6303a30000 r-xp 00000000 00:00 419601 /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3200.3 -7f6303a30000-7f6303c30000 ---p 0004d000 00:00 419601 /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3200.3 -7f6303c30000-7f6303c31000 r--p 0004d000 00:00 419601 /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3200.3 -7f6303c31000-7f6303c32000 rw-p 0004e000 00:00 419601 /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3200.3 -7f6303c32000-7f6303c35000 r-xp 00000000 00:00 420150 /usr/lib/x86_64-linux-gnu/libgmodule-2.0.so.0.3200.3 -7f6303c35000-7f6303e34000 ---p 00003000 00:00 420150 /usr/lib/x86_64-linux-gnu/libgmodule-2.0.so.0.3200.3 -7f6303e34000-7f6303e35000 r--p 00002000 00:00 420150 /usr/lib/x86_64-linux-gnu/libgmodule-2.0.so.0.3200.3 -7f6303e35000-7f6303e36000 rw-p 00003000 00:00 420150 /usr/lib/x86_64-linux-gnu/libgmodule-2.0.so.0.3200.3 -7f6303e36000-7f6303e38000 r-xp 00000000 00:00 263479 /lib/x86_64-linux-gnu/libdl-2.15.so -7f6303e38000-7f6304038000 ---p 00002000 00:00 263479 /lib/x86_64-linux-gnu/libdl-2.15.so -7f6304038000-7f6304039000 r--p 00002000 00:00 263479 /lib/x86_64-linux-gnu/libdl-2.15.so -7f6304039000-7f630403a000 rw-p 00003000 00:00 263479 /lib/x86_64-linux-gnu/libdl-2.15.so -7f630403a000-7f6304041000 r-xp 00000000 00:00 265235 /lib/x86_64-linux-gnu/librt-2.15.so -7f6304041000-7f6304240000 ---p 00007000 00:00 265235 /lib/x86_64-linux-gnu/librt-2.15.so -7f6304240000-7f6304241000 r--p 00006000 00:00 265235 /lib/x86_64-linux-gnu/librt-2.15.so -7f6304241000-7f6304242000 rw-p 00007000 00:00 265235 /lib/x86_64-linux-gnu/librt-2.15.so -7f6304242000-7f6304252000 r-xp 00000000 00:00 419652 /usr/lib/x86_64-linux-gnu/libXext.so.6.4.0 -7f6304252000-7f6304451000 ---p 00010000 00:00 419652 /usr/lib/x86_64-linux-gnu/libXext.so.6.4.0 -7f6304451000-7f6304452000 r--p 0000f000 00:00 419652 /usr/lib/x86_64-linux-gnu/libXext.so.6.4.0 -7f6304452000-7f6304453000 rw-p 00010000 00:00 419652 /usr/lib/x86_64-linux-gnu/libXext.so.6.4.0 -7f6304453000-7f6304455000 r-xp 00000000 00:00 420132 /usr/lib/x86_64-linux-gnu/libXss.so.1.0.0 -7f6304455000-7f6304655000 ---p 00002000 00:00 420132 /usr/lib/x86_64-linux-gnu/libXss.so.1.0.0 -7f6304655000-7f6304656000 r--p 00002000 00:00 420132 /usr/lib/x86_64-linux-gnu/libXss.so.1.0.0 -7f6304656000-7f6304657000 rw-p 00003000 00:00 420132 /usr/lib/x86_64-linux-gnu/libXss.so.1.0.0 -7f6304657000-7f6304660000 r-xp 00000000 00:00 420211 /usr/lib/x86_64-linux-gnu/libXrender.so.1.3.0 -7f6304660000-7f630485f000 ---p 00009000 00:00 420211 /usr/lib/x86_64-linux-gnu/libXrender.so.1.3.0 -7f630485f000-7f6304860000 r--p 00008000 00:00 420211 /usr/lib/x86_64-linux-gnu/libXrender.so.1.3.0 -7f6304860000-7f6304861000 rw-p 00009000 00:00 420211 /usr/lib/x86_64-linux-gnu/libXrender.so.1.3.0 -7f6304861000-7f6304869000 r-xp 00000000 00:00 419998 /usr/lib/x86_64-linux-gnu/libXrandr.so.2.2.0 -7f6304869000-7f6304a68000 ---p 00008000 00:00 419998 /usr/lib/x86_64-linux-gnu/libXrandr.so.2.2.0 -7f6304a68000-7f6304a69000 r--p 00007000 00:00 419998 /usr/lib/x86_64-linux-gnu/libXrandr.so.2.2.0 -7f6304a69000-7f6304a6a000 rw-p 00008000 00:00 419998 /usr/lib/x86_64-linux-gnu/libXrandr.so.2.2.0 -7f6304a6a000-7f6304a73000 r-xp 00000000 00:00 419293 /usr/lib/x86_64-linux-gnu/libXcursor.so.1.0.2 -7f6304a73000-7f6304c72000 ---p 00009000 00:00 419293 /usr/lib/x86_64-linux-gnu/libXcursor.so.1.0.2 -7f6304c72000-7f6304c73000 r--p 00008000 00:00 419293 /usr/lib/x86_64-linux-gnu/libXcursor.so.1.0.2 -7f6304c73000-7f6304c74000 rw-p 00009000 00:00 419293 /usr/lib/x86_64-linux-gnu/libXcursor.so.1.0.2 -7f6304c74000-7f6304da3000 r-xp 00000000 00:00 419233 /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0 -7f6304da3000-7f6304fa3000 ---p 0012f000 00:00 419233 /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0 -7f6304fa3000-7f6304fa4000 r--p 0012f000 00:00 419233 /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0 -7f6304fa4000-7f6304fa8000 rw-p 00130000 00:00 419233 /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0 -7f6304fa8000-7f6304fca000 r-xp 00000000 00:00 297771 /lib/x86_64-linux-gnu/ld-2.15.so -7f6304fcd000-7f6304fce000 r--- 00000000 00:00 14846136 /run/shm/.org.chromium.Chromium.zsFhgx (deleted) -7f6304fce000-7f6304fdf000 rw-p 00000000 00:00 0 -7f6304fdf000-7f6305107000 rw-p 00000000 00:00 0 -7f6305107000-7f6305108000 ---p 00000000 00:00 0 -7f6305108000-7f6305127000 rw-p 00000000 00:00 0 -7f6305127000-7f6305128000 ---p 00000000 00:00 0 -7f6305128000-7f6305147000 rw-p 00000000 00:00 0 -7f6305147000-7f6305148000 ---p 00000000 00:00 0 -7f6305148000-7f6305167000 rw-p 00000000 00:00 0 -7f6305167000-7f6305168000 ---p 00000000 00:00 0 -7f6305168000-7f63051b1000 rw-p 00000000 00:00 0 -7f63051b1000-7f63051ca000 rw-p 00000000 00:00 0 -7f63051ca000-7f63051cb000 r--p 00022000 00:00 297771 /lib/x86_64-linux-gnu/ld-2.15.so -7f63051cb000-7f63051cd000 rw-p 00023000 00:00 297771 /lib/x86_64-linux-gnu/ld-2.15.so -7f63051cd000-7f630fd06000 r-xp 00000000 00:00 6308662 /home/user/chromium/src/out/Debug/chrome -7f630fd06000-7f631010d000 r--p 0ab38000 00:00 6308662 /home/user/chromium/src/out/Debug/chrome -7f631010d000-7f631014a000 rw-p 0af3f000 00:00 6308662 /home/user/chromium/src/out/Debug/chrome -7f631014a000-7f63101c2000 rw-p 00000000 00:00 0 -7fff9437f000-7fff943a1000 rw-p 00000000 00:00 0 [stack] -7fff943ff000-7fff94400000 r-xp 00000000 00:00 0 [vdso] -ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] diff --git a/tools/deep_memory_profiler/tests/dmprof_test.py b/tools/deep_memory_profiler/tests/dmprof_test.py deleted file mode 100755 index 68d19256ae..0000000000 --- a/tools/deep_memory_profiler/tests/dmprof_test.py +++ /dev/null @@ -1,220 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import cStringIO -import logging -import os -import sys -import textwrap -import unittest - -BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) -sys.path.append(BASE_PATH) - -from lib.bucket import Bucket -from lib.ordered_dict import OrderedDict -from lib.policy import Policy -from lib.symbol import SymbolMappingCache -from lib.symbol import FUNCTION_SYMBOLS, SOURCEFILE_SYMBOLS, TYPEINFO_SYMBOLS - -import subcommands - - -class SymbolMappingCacheTest(unittest.TestCase): - class MockBucketSet(object): - def __init__(self, addresses): - self._addresses = addresses - - def iter_addresses(self, symbol_type): # pylint: disable=W0613 - for address in self._addresses: - yield address - - class MockSymbolFinder(object): - def __init__(self, mapping): - self._mapping = mapping - - def find(self, address_list): - result = OrderedDict() - for address in address_list: - result[address] = self._mapping[address] - return result - - _TEST_FUNCTION_CACHE = textwrap.dedent("""\ - 1 0x0000000000000001 - 7fc33eebcaa4 __gnu_cxx::new_allocator::allocate - 7fc33ef69242 void DispatchToMethod - """) - - _EXPECTED_TEST_FUNCTION_CACHE = textwrap.dedent("""\ - 1 0x0000000000000001 - 7fc33eebcaa4 __gnu_cxx::new_allocator::allocate - 7fc33ef69242 void DispatchToMethod - 2 0x0000000000000002 - 7fc33ef7bc3e std::map::operator[] - 7fc34411f9d5 WTF::RefCounted::operator new - """) - - _TEST_FUNCTION_ADDRESS_LIST1 = [ - 0x1, 0x7fc33eebcaa4, 0x7fc33ef69242] - - _TEST_FUNCTION_ADDRESS_LIST2 = [ - 0x1, 0x2, 0x7fc33eebcaa4, 0x7fc33ef69242, 0x7fc33ef7bc3e, 0x7fc34411f9d5] - - _TEST_FUNCTION_DICT = { - 0x1: '0x0000000000000001', - 0x2: '0x0000000000000002', - 0x7fc33eebcaa4: '__gnu_cxx::new_allocator::allocate', - 0x7fc33ef69242: 'void DispatchToMethod', - 0x7fc33ef7bc3e: 'std::map::operator[]', - 0x7fc34411f9d5: 'WTF::RefCounted::operator new', - } - - def test_update(self): - symbol_mapping_cache = SymbolMappingCache() - cache_f = cStringIO.StringIO() - cache_f.write(self._TEST_FUNCTION_CACHE) - - # No update from self._TEST_FUNCTION_CACHE - symbol_mapping_cache.update( - FUNCTION_SYMBOLS, - self.MockBucketSet(self._TEST_FUNCTION_ADDRESS_LIST1), - self.MockSymbolFinder(self._TEST_FUNCTION_DICT), cache_f) - for address in self._TEST_FUNCTION_ADDRESS_LIST1: - self.assertEqual(self._TEST_FUNCTION_DICT[address], - symbol_mapping_cache.lookup(FUNCTION_SYMBOLS, address)) - self.assertEqual(self._TEST_FUNCTION_CACHE, cache_f.getvalue()) - - # Update to self._TEST_FUNCTION_ADDRESS_LIST2 - symbol_mapping_cache.update( - FUNCTION_SYMBOLS, - self.MockBucketSet(self._TEST_FUNCTION_ADDRESS_LIST2), - self.MockSymbolFinder(self._TEST_FUNCTION_DICT), cache_f) - for address in self._TEST_FUNCTION_ADDRESS_LIST2: - self.assertEqual(self._TEST_FUNCTION_DICT[address], - symbol_mapping_cache.lookup(FUNCTION_SYMBOLS, address)) - self.assertEqual(self._EXPECTED_TEST_FUNCTION_CACHE, cache_f.getvalue()) - - -class PolicyTest(unittest.TestCase): - class MockSymbolMappingCache(object): - def __init__(self): - self._symbol_caches = { - FUNCTION_SYMBOLS: {}, - SOURCEFILE_SYMBOLS: {}, - TYPEINFO_SYMBOLS: {}, - } - - def add(self, symbol_type, address, symbol): - self._symbol_caches[symbol_type][address] = symbol - - def lookup(self, symbol_type, address): - symbol = self._symbol_caches[symbol_type].get(address) - return symbol if symbol else '0x%016x' % address - - _TEST_POLICY = textwrap.dedent("""\ - { - "components": [ - "second", - "mmap-v8", - "malloc-v8", - "malloc-WebKit", - "mmap-catch-all", - "malloc-catch-all" - ], - "rules": [ - { - "name": "second", - "stacktrace": "optional", - "allocator": "optional" - }, - { - "name": "mmap-v8", - "stacktrace": ".*v8::.*", - "allocator": "mmap" - }, - { - "name": "malloc-v8", - "stacktrace": ".*v8::.*", - "allocator": "malloc" - }, - { - "name": "malloc-WebKit", - "stacktrace": ".*WebKit::.*", - "allocator": "malloc" - }, - { - "name": "mmap-catch-all", - "stacktrace": ".*", - "allocator": "mmap" - }, - { - "name": "malloc-catch-all", - "stacktrace": ".*", - "allocator": "malloc" - } - ], - "version": "POLICY_DEEP_3" - } - """) - - def test_load(self): - policy = Policy.parse(cStringIO.StringIO(self._TEST_POLICY), 'json') - self.assertTrue(policy) - self.assertEqual('POLICY_DEEP_3', policy.version) - - def test_find(self): - policy = Policy.parse(cStringIO.StringIO(self._TEST_POLICY), 'json') - self.assertTrue(policy) - - symbol_mapping_cache = self.MockSymbolMappingCache() - symbol_mapping_cache.add(FUNCTION_SYMBOLS, 0x1212, 'v8::create') - symbol_mapping_cache.add(FUNCTION_SYMBOLS, 0x1381, 'WebKit::create') - - bucket1 = Bucket([0x1212, 0x013], 'malloc', 0x29492, '_Z') - bucket1.symbolize(symbol_mapping_cache) - bucket2 = Bucket([0x18242, 0x1381], 'malloc', 0x9492, '_Z') - bucket2.symbolize(symbol_mapping_cache) - bucket3 = Bucket([0x18242, 0x181], 'malloc', 0x949, '_Z') - bucket3.symbolize(symbol_mapping_cache) - - self.assertEqual('malloc-v8', policy.find_malloc(bucket1)) - self.assertEqual('malloc-WebKit', policy.find_malloc(bucket2)) - self.assertEqual('malloc-catch-all', policy.find_malloc(bucket3)) - - -class BucketsCommandTest(unittest.TestCase): - def test(self): - BUCKETS_PATH = os.path.join(BASE_PATH, 'tests', 'output', 'buckets') - with open(BUCKETS_PATH) as output_f: - expected = output_f.read() - - out = cStringIO.StringIO() - - HEAP_PATH = os.path.join(BASE_PATH, 'tests', 'data', 'heap.01234.0001.heap') - subcommand = subcommands.BucketsCommand() - returncode = subcommand.do(['buckets', HEAP_PATH], out) - self.assertEqual(0, returncode) - self.assertEqual(expected, out.getvalue()) - - -class UploadCommandTest(unittest.TestCase): - def test(self): - MOCK_GSUTIL_PATH = os.path.join(BASE_PATH, 'tests', 'mock_gsutil.py') - HEAP_PATH = os.path.join(BASE_PATH, 'tests', 'data', 'heap.01234.0001.heap') - subcommand = subcommands.UploadCommand() - returncode = subcommand.do([ - 'upload', - '--gsutil', - MOCK_GSUTIL_PATH, - HEAP_PATH, - 'gs://test-storage/']) - self.assertEqual(0, returncode) - - -if __name__ == '__main__': - logging.basicConfig( - level=logging.DEBUG if '-v' in sys.argv else logging.ERROR, - format='%(levelname)5s %(filename)15s(%(lineno)3d): %(message)s') - unittest.main() diff --git a/tools/deep_memory_profiler/tests/mock_gsutil.py b/tools/deep_memory_profiler/tests/mock_gsutil.py deleted file mode 100755 index acacdcff3b..0000000000 --- a/tools/deep_memory_profiler/tests/mock_gsutil.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import os -import re -import sys -import zipfile - - -def main(): - ZIP_PATTERN = re.compile('dmprof......\.zip') - - assert len(sys.argv) == 6 - assert sys.argv[1] == 'cp' - assert sys.argv[2] == '-a' - assert sys.argv[3] == 'public-read' - assert ZIP_PATTERN.match(os.path.basename(sys.argv[4])) - assert sys.argv[5] == 'gs://test-storage/' - - zip_file = zipfile.ZipFile(sys.argv[4], 'r') - - expected_nameset = set(['heap.01234.0001.heap', - 'heap.01234.0002.heap', - 'heap.01234.0001.buckets', - 'heap.01234.0002.buckets', - 'heap.01234.symmap/maps', - 'heap.01234.symmap/chrome.uvwxyz.readelf-e', - 'heap.01234.symmap/chrome.abcdef.nm', - 'heap.01234.symmap/files.json']) - assert set(zip_file.namelist()) == expected_nameset - - heap_1 = zip_file.getinfo('heap.01234.0001.heap') - assert heap_1.CRC == 763099253 - assert heap_1.file_size == 1107 - - buckets_1 = zip_file.getinfo('heap.01234.0001.buckets') - assert buckets_1.CRC == 2632528901 - assert buckets_1.file_size == 2146 - - nm_chrome = zip_file.getinfo('heap.01234.symmap/chrome.abcdef.nm') - assert nm_chrome.CRC == 2717882373 - assert nm_chrome.file_size == 131049 - - zip_file.close() - return 0 - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/tools/deep_memory_profiler/tests/output/buckets b/tools/deep_memory_profiler/tests/output/buckets deleted file mode 100644 index 7f18ffee01..0000000000 --- a/tools/deep_memory_profiler/tests/output/buckets +++ /dev/null @@ -1,7 +0,0 @@ -1: malloc tno_typeinfo nno_typeinfo std::_Rb_tree::_M_insert_unique_(@?) std::_Rb_tree::_M_insert_unique_(@?) std::_Rb_tree::_M_insert_unique_(@?) std::_Rb_tree::_M_insert_unique_(@?) std::_Rb_tree::_M_insert_unique_(@?) std::map::insert(@?) std::map::operator[](@?) tracked_objects::ThreadData::TallyADeath(@?) tracked_objects::ThreadData::TallyRunInAScopedRegionIfTracking(@?) tracked_objects::ScopedProfile::StopClockAndTally(@?) tracked_objects::ScopedProfile::~ScopedProfile(@?) content::ResourceDispatcher::FlushDeferredMessages(@?) content::ChildThread::OnMessageReceived(@?) content::ChildThread::OnMessageReceived(@?) IPC::ChannelProxy::Context::OnDispatchMessage(@?) base::internal::RunnableAdapter::Run(@?) base::internal::InvokeHelper::MakeItSo(@?) base::internal::Invoker::Run(@?) base::Callback::Run(@?) MessageLoop::ProcessNextDelayedNonNestableTask(@?) MessageLoop::DeferOrRunPendingTask(@?) MessageLoop::DeferOrRunPendingTask(@?) base::MessagePumpDefault::Run(@?) MessageLoop::QuitWhenIdleClosure(@?) MessageLoop::QuitWhenIdleClosure(@?) base::RunLoop::Run(@?) MessageLoop::Run(@?) content::RenderViewImpl::GetPluginInfo(@?) content::SetupSignalHandlers(@?) content::RunNamedProcessTypeMain(@?) content::ContentMainRunnerImpl::Run(@?) content::ContentMain(@?) -2: malloc t0x00007f630ff7e718 nN7WebCore8RuleDataE WTF::fastMalloc(@?) WTF::Vector::shrinkCapacity(@?) WTF::Vector::shrinkCapacity(@?) WTF::Vector::shrinkToFit(@?) WebCore::shrinkMapVectorsToFit(@?) WebCore::RuleSet::shrinkToFit(@?) WebCore::RuleSet::addRulesFromSheet(@?) WebCore::CSSDefaultStyleSheets::loadFullDefaultStyle(@?) WebCore::CSSDefaultStyleSheets::loadFullDefaultStyle(@?) WebCore::StyleResolver::StyleResolver(@?) WebCore::Document::styleForElementIgnoringPendingStylesheets(@?) WebCore::Element::computedStyle(@?) WebCore::HTMLTitleElement::textWithDirection(@?) WebCore::HTMLTitleElement::childrenChanged(@?) WTF::Vector::shrinkCapacity(@?) WebCore::executeTask(@?) WebCore::HTMLConstructionSite::setCompatibilityModeFromDoctype(@?) WebCore::HTMLTreeBuilder::processEndOfFile(@?) WebCore::HTMLTreeBuilder::processCharacter(@?) WebCore::HTMLTreeBuilder::processToken(@?) WebCore::HTMLTreeBuilder::constructTree(@?) WebCore::HTMLDocumentParser::constructTreeFromHTMLToken(@?) WebCore::HTMLDocumentParser::processingData(@?) WebCore::HTMLDocumentParser::pumpTokenizerIfPossible(@?) WebCore::HTMLDocumentParser::insert(@?) WebCore::DecodedDataDocumentParser::appendBytes(@?) WebCore::DocumentWriter::addData(@?) WebCore::DocumentLoader::commitData(@?) WebKit::WebFrameImpl::commitDocumentData(@?) WebKit::FrameLoaderClientImpl::committedLoad(@?) WebCore::DocumentLoader::commitLoad(@?) WebCore::DocumentLoader::reportMemoryUsage(@?) -3: malloc t0x00007f630feeb3a0 nN7WebCore17CSSPrimitiveValueE WTF::fastMalloc(@?) WTF::RefCounted::operator new(@?) WebCore::CSSPrimitiveValue::createIdentifier(@?) WebCore::CSSValuePool::createIdentifierValue(@?) WebCore::CSSParser::parseValue(@?) WebCore::NodeV8Internal::lookupNamespaceURIMethod(@?) WebCore::CSSParser::parseSheet(@?) WebCore::StyleSheetContents::parseStringAtLine(@?) WebCore::StyleSheetContents::parseString(@?) WebCore::CSSDefaultStyleSheets::loadFullDefaultStyle(@?) WebCore::CSSDefaultStyleSheets::loadFullDefaultStyle(@?) WebCore::CSSDefaultStyleSheets::loadSimpleDefaultStyle(@?) WebCore::CSSDefaultStyleSheets::initDefaultStyle(@?) WebCore::StyleResolver::StyleResolver(@?) WebCore::Document::createStyleResolver(@?) WebCore::Document::styleResolver(@?) WebCore::Element::styleForRenderer(@?) WebCore::NodeRenderingContext::createRendererForElementIfNeeded(@?) WebCore::Element::createRendererIfNeeded(@?) WebCore::Element::attach(@?) WebCore::executeTask(@?) WebCore::HTMLConstructionSite::executeQueuedTasks(@?) WebCore::HTMLConstructionSite::HTMLConstructionSite(@?) WebCore::HTMLTreeBuilder::defaultForBeforeHTML(@?) WebCore::HTMLTreeBuilder::processEndOfFile(@?) WebCore::HTMLTreeBuilder::processToken(@?) WebCore::HTMLTreeBuilder::constructTree(@?) WebCore::HTMLDocumentParser::constructTreeFromHTMLToken(@?) WebCore::HTMLDocumentParser::processingData(@?) WebCore::HTMLDocumentParser::pumpTokenizerIfPossible(@?) WebCore::HTMLDocumentParser::prepareToStopParsing(@?) WebCore::HTMLDocumentParser::attemptToEnd(@?) -4: mmap tno_typeinfo nno_typeinfo DoAllocWithArena(@?) LowLevelAlloc::AllocWithArena(@?) ProfilerMalloc(@?) HeapProfileTable::GetBucket(@?) HeapProfileTable::RecordAlloc(@?) RecordAlloc(@?) NewHook(@?) MallocHook::InvokeNewHookSlow(@?) MallocHook::InvokeNewHook(@?) tc_new_nothrow(@?) WTF::fastMalloc(@?) WTF::HashTable::fullLookupForWriting(@?) WTF::HashTable::fullLookupForWriting(@?) WTF::HashTable::fullLookupForWriting(@?) WTF::HashTable::fullLookupForWriting(@?) WTF::HashTable::addPassingHashCode(@?) WebCore::nullQName(@?) WebCore::QualifiedName::QualifiedName(@?) WebCore::nullQName(@?) WebCore::NodeV8Internal::lookupNamespaceURIMethod(@?) WebCore::Frame::Frame(@?) WebCore::Frame::Frame(@?) WebCore::Frame::create(@?) WebKit::WebFrameImpl::initializeAsMainFrame(@?) WebKit::WebViewImpl::initializeMainFrame(@?) base::internal::scoped_ptr_impl::reset(@?) content::RenderViewImpl::Create(@?) content::RenderThreadImpl::OnCreateNewView(@?) base::internal::scoped_ptr_impl::reset(@?) ViewMsg_New::Dispatch(@?) base::internal::scoped_ptr_impl::reset(@?) content::RenderThreadImpl::OnCreateNewView(@?) -5: malloc tno_typeinfo nno_typeinfo 0x00007f62fd455a89(@?) 0x00007f62fd4575e3(@?) 0x00007fff9439ce50(@?) -6: malloc tno_typeinfo nno_typeinfo WTF::fastMalloc(@?) WTF::fastZeroedMalloc(@?) WTF::HashTable::allocateTable(@?) WTF::HashTable::rehash(@?) WTF::HashTable::add(@?) WTF::HashTable::add(@?) WTF::HashMap::inlineAdd(@?) WTF::HashMap::set(@?) WebCore::eventTargetDataMap(@?) WebCore::EventTarget::addEventListener(@?) WebCore::tryAddEventListener(@?) WebCore::Node::addEventListener(@?) WebCore::NodeV8Internal::removeEventListenerMethod(@?) WebCore::NodeV8Internal::addEventListenerMethodCallback(@?) 0x000012e93499fa0f(@?) 0x000012e93499f038(@?) 0x000012e93499ee28(@?) 0x000012e934925d44(@?) 0x000012e934907177(@?) v8::internal::Invoke(@?) v8::internal::Execution::Call(@?) v8::Function::Call(@?) WebCore::ScriptController::callFunctionWithInstrumentation(@?) WebCore::ScriptController::callFunction(@?) WebCore::resourceInfo(@?) WebCore::V8AbstractEventListener::invokeEventHandler(@?) WebCore::V8AbstractEventListener::handleEvent(@?) WebCore::EventTarget::fireEventListeners(@?) WebCore::EventTarget::clearAttributeEventListener(@?) WebCore::Node::handleLocalEvents(@?) WebCore::EventContext::handleLocalEvents(@?) WebCore::MouseOrFocusEventContext::handleLocalEvents(@?) -7: mmap tno_typeinfo nno_typeinfo DoAllocWithArena(@?) LowLevelAlloc::AllocWithArena(@?) EraseType(@?) EraseType(@?) AddressMap::Insert(@?) InsertType(@?) base::type_profiler::NewInterceptForTCMalloc(@?) __op_new_intercept__(@?) v8::internal::AstNodeFactory::NewVariableProxy(@?) v8::internal::Scope::NewUnresolved(@?) v8::internal::Parser::ParseLeftHandSideExpression(@?) v8::internal::Parser::ParseLeftHandSideExpression(@?) v8::internal::Parser::ParseLeftHandSideExpression(@?) v8::internal::Parser::ParseLeftHandSideExpression(@?) v8::internal::Parser::ParsePostfixExpression(@?) v8::internal::Parser::ParseBinaryExpression(@?) v8::internal::Parser::ParseBinaryExpression(@?) v8::internal::Parser::ParseConditionalExpression(@?) v8::internal::Parser::ParseAssignmentExpression(@?) v8::internal::Parser::ParseAssignmentExpression(@?) v8::internal::Parser::ParseLeftHandSideExpression(@?) v8::internal::Parser::ParseLeftHandSideExpression(@?) v8::internal::Parser::ParseLeftHandSideExpression(@?) v8::internal::Parser::ParseLeftHandSideExpression(@?) v8::internal::Parser::ParsePostfixExpression(@?) v8::internal::Parser::ParseBinaryExpression(@?) v8::internal::Parser::ParseBinaryExpression(@?) v8::internal::Parser::ParseConditionalExpression(@?) v8::internal::Parser::ParseAssignmentExpression(@?) v8::internal::Parser::ParseStatement(@?) v8::internal::Parser::ParseVariableStatement(@?) v8::internal::Parser::ParseStatement(@?) diff --git a/tools/deep_memory_profiler/tests/range_dict_tests.py b/tools/deep_memory_profiler/tests/range_dict_tests.py deleted file mode 100755 index 3bc2c139ac..0000000000 --- a/tools/deep_memory_profiler/tests/range_dict_tests.py +++ /dev/null @@ -1,131 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import logging -import os -import sys -import unittest - -BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) -sys.path.append(BASE_PATH) - -from lib.range_dict import ExclusiveRangeDict - - -class ExclusiveRangeDictTest(unittest.TestCase): - class TestAttribute(ExclusiveRangeDict.RangeAttribute): - def __init__(self): - super(ExclusiveRangeDictTest.TestAttribute, self).__init__() - self._value = 0 - - def __str__(self): - return str(self._value) - - def __repr__(self): - return '' % self._value - - def get(self): - return self._value - - def set(self, new_value): - self._value = new_value - - def copy(self): # pylint: disable=R0201 - new_attr = ExclusiveRangeDictTest.TestAttribute() - new_attr.set(self._value) - return new_attr - - def test_init(self): - ranges = ExclusiveRangeDict(self.TestAttribute) - - result = [] - for begin, end, attr in ranges.iter_range(20, 40): - result.append({'begin': begin, 'end':end, 'attr':attr.get()}) - expected = [ - {'begin': 20, 'end': 40, 'attr': 0}, - ] - self.assertEqual(expected, result) - - def test_norange(self): - ranges = ExclusiveRangeDict(self.TestAttribute) - - result = [] - for begin, end, attr in ranges.iter_range(20, 20): - result.append({'begin': begin, 'end':end, 'attr':attr.get()}) - expected = [] - self.assertEqual(expected, result) - - def test_set(self): - ranges = ExclusiveRangeDict(self.TestAttribute) - for begin, end, attr in ranges.iter_range(20, 30): - attr.set(12) - for begin, end, attr in ranges.iter_range(30, 40): - attr.set(52) - - result = [] - for begin, end, attr in ranges.iter_range(20, 40): - result.append({'begin': begin, 'end':end, 'attr':attr.get()}) - expected = [ - {'begin': 20, 'end': 30, 'attr': 12}, - {'begin': 30, 'end': 40, 'attr': 52}, - ] - self.assertEqual(expected, result) - - def test_split(self): - ranges = ExclusiveRangeDict(self.TestAttribute) - for begin, end, attr in ranges.iter_range(20, 30): - attr.set(1000) - for begin, end, attr in ranges.iter_range(30, 40): - attr.set(2345) - for begin, end, attr in ranges.iter_range(40, 50): - attr.set(3579) - - result1 = [] - for begin, end, attr in ranges.iter_range(25, 45): - result1.append({'begin': begin, 'end':end, 'attr':attr.get()}) - expected1 = [ - {'begin': 25, 'end': 30, 'attr': 1000}, - {'begin': 30, 'end': 40, 'attr': 2345}, - {'begin': 40, 'end': 45, 'attr': 3579}, - ] - self.assertEqual(expected1, result1) - - result2 = [] - for begin, end, attr in ranges.iter_range(20, 50): - result2.append({'begin': begin, 'end':end, 'attr':attr.get()}) - expected2 = [ - {'begin': 20, 'end': 25, 'attr': 1000}, - {'begin': 25, 'end': 30, 'attr': 1000}, - {'begin': 30, 'end': 40, 'attr': 2345}, - {'begin': 40, 'end': 45, 'attr': 3579}, - {'begin': 45, 'end': 50, 'attr': 3579}, - ] - self.assertEqual(expected2, result2) - - def test_fill(self): - ranges = ExclusiveRangeDict(self.TestAttribute) - for begin, end, attr in ranges.iter_range(30, 35): - attr.set(12345) - for begin, end, attr in ranges.iter_range(40, 45): - attr.set(97531) - - result = [] - for begin, end, attr in ranges.iter_range(25, 50): - result.append({'begin': begin, 'end':end, 'attr':attr.get()}) - expected = [ - {'begin': 25, 'end': 30, 'attr': 0}, - {'begin': 30, 'end': 35, 'attr': 12345}, - {'begin': 35, 'end': 40, 'attr': 0}, - {'begin': 40, 'end': 45, 'attr': 97531}, - {'begin': 45, 'end': 50, 'attr': 0}, - ] - self.assertEqual(expected, result) - - -if __name__ == '__main__': - logging.basicConfig( - level=logging.DEBUG if '-v' in sys.argv else logging.ERROR, - format='%(levelname)5s %(filename)15s(%(lineno)3d): %(message)s') - unittest.main() diff --git a/tools/deep_memory_profiler/visualizer/main.css b/tools/deep_memory_profiler/visualizer/main.css deleted file mode 100644 index 5d9ed53f48..0000000000 --- a/tools/deep_memory_profiler/visualizer/main.css +++ /dev/null @@ -1,9 +0,0 @@ -/* Copyright 2013 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. */ - -.plot-container { - width: 1240px; - height: 720px; - margin: 30px auto 30px auto; -} \ No newline at end of file diff --git a/tools/deep_memory_profiler/visualizer/main.html b/tools/deep_memory_profiler/visualizer/main.html deleted file mode 100644 index fdd7874591..0000000000 --- a/tools/deep_memory_profiler/visualizer/main.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - -

Deep Memory Profiler Visulaizer

-
- diff --git a/tools/deep_memory_profiler/visualizer/main.js b/tools/deep_memory_profiler/visualizer/main.js deleted file mode 100644 index 8c4dff84c4..0000000000 --- a/tools/deep_memory_profiler/visualizer/main.js +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * This class provides data access interface for dump file profiler - * @constructor - */ -var Profiler = function(jsonData) { - this._jsonData = jsonData; -}; - -/** - * Get units of a snapshot in a world. - * Exception will be thrown when no world of given name exists. - * @param {string} worldName - * @param {number} snapshotIndex - * @return {Object.} - */ -Profiler.prototype.getUnits = function(worldName, snapshotIndex) { - var snapshot = this._jsonData.snapshots[snapshotIndex]; - if (!snapshot.worlds[worldName]) - throw 'no world ' + worldName + ' in snapshot ' + index; - - // Return units. - var world = snapshot.worlds[worldName]; - var units = {}; - for (var unitName in world.units) - units[unitName] = world.units[unitName][0]; - return units; -}; - -/** - * Get first-level breakdowns of a snapshot in a world. - * Exception will be thrown when no world of given name exists. - * @param {string} worldName - * @param {number} snapshotIndex - * @return {Object.} - */ -Profiler.prototype.getBreakdowns = function(worldName, snapshotIndex) { - var snapshot = this._jsonData.snapshots[snapshotIndex]; - if (!snapshot.worlds[worldName]) - throw 'no world ' + worldName + ' in snapshot ' + index; - - // Return breakdowns. - // TODO(junjianx): handle breakdown with arbitrary-level structure. - return snapshot.worlds[worldName].breakdown; -}; - -/** - * Get categories from fixed hard-coded worlds and breakdowns temporarily. - * TODO(junjianx): remove the hard-code and support general cases. - * @return {Array.} - */ -Profiler.prototype.getCategories = function() { - var categories = []; - var snapshotNum = this._jsonData.snapshots.length; - - for (var snapshotIndex = 0; snapshotIndex < snapshotNum; ++snapshotIndex) { - // Initial categories object for one snapshot. - categories.push({}); - - // Handle breakdowns in malloc world. - var mallocBreakdown = this.getBreakdowns('malloc', snapshotIndex); - var mallocUnits = this.getUnits('malloc', snapshotIndex); - if (!mallocBreakdown['component']) - throw 'no breakdown ' + 'component' + ' in snapshot ' + snapshotIndex; - - var componentBreakdown = mallocBreakdown['component']; - var componentMemory = 0; - Object.keys(componentBreakdown).forEach(function(breakdownName) { - var breakdown = componentBreakdown[breakdownName]; - var memory = breakdown.units.reduce(function(previous, current) { - return previous + mallocUnits[current]; - }, 0); - componentMemory += memory; - - if (componentBreakdown['hidden'] === true) - return; - else - categories[snapshotIndex][breakdownName] = memory; - }); - - // Handle breakdowns in vm world. - var vmBreakdown = this.getBreakdowns('vm', snapshotIndex); - var vmUnits = this.getUnits('vm', snapshotIndex); - if (!vmBreakdown['map']) - throw 'no breakdown ' + 'map' + ' in snapshot ' + snapshotIndex; - - var mapBreakdown = vmBreakdown['map']; - - Object.keys(mapBreakdown).forEach(function(breakdownName) { - var breakdown = mapBreakdown[breakdownName]; - var memory = breakdown.units.reduce(function(previous, current) { - return previous + vmUnits[current]; - }, 0); - - if (vmBreakdown['hidden'] === true) - return; - else if (breakdownName === 'mmap-tcmalloc') - categories[snapshotIndex]['tc-unused'] = memory - componentMemory; - else - categories[snapshotIndex][breakdownName] = memory; - }); - } - - return categories; -}; - -/** - * Generate lines for flot plotting. - * @param {Array.} categories - * @return {Array.} - */ -var generateLines = function(categories) { - var lines = {}; - var snapshotNum = categories.length; - - // Initialize lines with all zero. - categories.forEach(function(categories) { - Object.keys(categories).forEach(function(breakdownName) { - if (lines[breakdownName]) - return; - lines[breakdownName] = []; - for (var i = 0; i < snapshotNum; ++i) - lines[breakdownName].push([i, 0]); - }); - }); - - // Assignment lines with values of categories. - categories.forEach(function(categories, index) { - Object.keys(categories).forEach(function(breakdownName) { - lines[breakdownName][index] = [index, categories[breakdownName]]; - }); - }); - - return Object.keys(lines).map(function(breakdownName) { - return { - label: breakdownName, - data: lines[breakdownName] - }; - }); -}; - -$(function() { - // Read original data and plot. - $.getJSON('data/result.json', function(jsonData) { - var profiler = new Profiler(jsonData); - var categories = profiler.getCategories(); - var lines = generateLines(categories); - - // Plot stack graph. - $.plot('#plot', lines, { - series: { - stack: true, - lines: { show: true, fill: true } - } - }); - }); -}); \ No newline at end of file diff --git a/tools/deps2git b/tools/deps2git deleted file mode 160000 index 92b6fca498..0000000000 --- a/tools/deps2git +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 92b6fca498aa9d9cca70e80b25a4c41313a537f0 diff --git a/tools/diagnose-me.py b/tools/diagnose-me.py deleted file mode 100755 index bbd9429cb1..0000000000 --- a/tools/diagnose-me.py +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/python -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Diagnose some common system configuration problems on Linux, and -suggest fixes.""" - -import os -import subprocess -import sys - -all_checks = [] - -def Check(name): - """Decorator that defines a diagnostic check.""" - def wrap(func): - all_checks.append((name, func)) - return func - return wrap - - -@Check("/usr/bin/ld is not gold") -def CheckSystemLd(): - proc = subprocess.Popen(['/usr/bin/ld', '-v'], stdout=subprocess.PIPE) - stdout = proc.communicate()[0] - if 'GNU gold' in stdout: - return ("When /usr/bin/ld is gold, system updates can silently\n" - "corrupt your graphics drivers.\n" - "Try 'sudo apt-get remove binutils-gold'.\n") - return None - - -@Check("random lds are not in the $PATH") -def CheckPathLd(): - proc = subprocess.Popen(['which', '-a', 'ld'], stdout=subprocess.PIPE) - stdout = proc.communicate()[0] - instances = stdout.split() - if len(instances) > 1: - return ("You have multiple 'ld' binaries in your $PATH:\n" - + '\n'.join(' - ' + i for i in instances) + "\n" - "You should delete all of them but your system one.\n" - "gold is hooked into your build via gyp.\n") - return None - - -@Check("/usr/bin/ld doesn't point to gold") -def CheckLocalGold(): - # Check /usr/bin/ld* symlinks. - for path in ('ld.bfd', 'ld'): - path = '/usr/bin/' + path - try: - target = os.readlink(path) - except OSError, e: - if e.errno == 2: - continue # No such file - if e.errno == 22: - continue # Not a symlink - raise - if '/usr/local/gold' in target: - return ("%s is a symlink into /usr/local/gold.\n" - "It's difficult to make a recommendation, because you\n" - "probably set this up yourself. But you should make\n" - "/usr/bin/ld be the standard linker, which you likely\n" - "renamed /usr/bin/ld.bfd or something like that.\n" % path) - - return None - - -@Check("random ninja binaries are not in the $PATH") -def CheckPathNinja(): - proc = subprocess.Popen(['which', 'ninja'], stdout=subprocess.PIPE) - stdout = proc.communicate()[0] - if not 'depot_tools' in stdout: - return ("The ninja binary in your path isn't from depot_tools:\n" - + " " + stdout + - "Remove custom ninjas from your path so that the one\n" - "in depot_tools is used.\n") - return None - - -def RunChecks(): - for name, check in all_checks: - sys.stdout.write("* Checking %s: " % name) - sys.stdout.flush() - error = check() - if not error: - print "ok" - else: - print "FAIL" - print error - - -if __name__ == '__main__': - RunChecks() diff --git a/tools/dromaeo_benchmark_runner/dromaeo_benchmark_runner.py b/tools/dromaeo_benchmark_runner/dromaeo_benchmark_runner.py deleted file mode 100755 index 5c4be81c37..0000000000 --- a/tools/dromaeo_benchmark_runner/dromaeo_benchmark_runner.py +++ /dev/null @@ -1,266 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2011 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Dromaeo benchmark automation script. - -Script runs dromaeo tests in browsers specified by --browser switch and saves -results to a spreadsheet on docs.google.com. - -Prerequisites: -1. Install Google Data APIs Python Client Library from - http://code.google.com/p/gdata-python-client. -2. Checkout Dromaeo benchmark from - http://src.chromium.org/svn/trunk/src/chrome/test/data/dromaeo and provide - local path to it in --dromaeo_home switch. -3. Create a spreadsheet at http://docs.google.com and specify its name in - --spreadsheet switch - -Benchmark results are presented in the following format: -browser | date time -test 1 name|m11|...|m1n|test 1 average mean| |e11|...|e1n|test 1 average error -test 2 name|m21|...|m2n|test 2 average mean| |e21|...|e2n|test 2 average error -... - -Here mij is mean run/s in individual dromaeo test i during benchmark run j, -eij is error in individual dromaeo test i during benchmark run j. - -Example usage: -dromaeo_benchmark_runner.py -b "E:\chromium\src\chrome\Release\chrome.exe" - -b "C:\Program Files (x86)\Safari\safari.exe" - -b "C:\Program Files (x86)\Opera 10.50 pre-alpha\opera.exe" -n 1 - -d "E:\chromium\src\chrome\test\data\dromaeo" -f dom -e example@gmail.com - -""" - -import getpass -import json -import os -import re -import subprocess -import time -import urlparse -from optparse import OptionParser -from BaseHTTPServer import HTTPServer -import SimpleHTTPServer -import gdata.spreadsheet.service - -max_spreadsheet_columns = 20 -test_props = ['mean', 'error'] - - -def ParseArguments(): - parser = OptionParser() - parser.add_option("-b", "--browser", - action="append", dest="browsers", - help="list of browsers to test") - parser.add_option("-n", "--run_count", dest="run_count", type="int", - default=5, help="number of runs") - parser.add_option("-d", "--dromaeo_home", dest="dromaeo_home", - help="directory with your dromaeo files") - parser.add_option("-p", "--port", dest="port", type="int", - default=8080, help="http server port") - parser.add_option("-f", "--filter", dest="filter", - default="dom", help="dromaeo suite filter") - parser.add_option("-e", "--email", dest="email", - help="your google docs account") - parser.add_option("-s", "--spreadsheet", dest="spreadsheet_title", - default="dromaeo", - help="your google docs spreadsheet name") - - options = parser.parse_args()[0] - - if not options.dromaeo_home: - raise Exception('please specify dromaeo_home') - - return options - - -def KillProcessByName(process_name): - process = subprocess.Popen('wmic process get processid, executablepath', - stdout=subprocess.PIPE) - stdout = str(process.communicate()[0]) - match = re.search(re.escape(process_name) + '\s+(\d+)', stdout) - if match: - pid = match.group(1) - subprocess.call('taskkill /pid %s' % pid) - - -class SpreadsheetWriter(object): - "Utility class for storing benchmarking results in Google spreadsheets." - - def __init__(self, email, spreadsheet_title): - '''Login to google docs and search for spreadsheet''' - - self.token_file = os.path.expanduser("~/.dromaeo_bot_auth_token") - self.gd_client = gdata.spreadsheet.service.SpreadsheetsService() - - authenticated = False - if os.path.exists(self.token_file): - token = '' - try: - file = open(self.token_file, 'r') - token = file.read() - file.close() - self.gd_client.SetClientLoginToken(token) - self.gd_client.GetSpreadsheetsFeed() - authenticated = True - except (IOError, gdata.service.RequestError): - pass - if not authenticated: - self.gd_client.email = email - self.gd_client.password = getpass.getpass('Password for %s: ' % email) - self.gd_client.source = 'python robot for dromaeo' - self.gd_client.ProgrammaticLogin() - token = self.gd_client.GetClientLoginToken() - try: - file = open(self.token_file, 'w') - file.write(token) - file.close() - except (IOError): - pass - os.chmod(self.token_file, 0600) - - # Search for the spreadsheet with title = spreadsheet_title. - spreadsheet_feed = self.gd_client.GetSpreadsheetsFeed() - for spreadsheet in spreadsheet_feed.entry: - if spreadsheet.title.text == spreadsheet_title: - self.spreadsheet_key = spreadsheet.id.text.rsplit('/', 1)[1] - if not self.spreadsheet_key: - raise Exception('Spreadsheet %s not found' % spreadsheet_title) - - # Get the key of the first worksheet in spreadsheet. - worksheet_feed = self.gd_client.GetWorksheetsFeed(self.spreadsheet_key) - self.worksheet_key = worksheet_feed.entry[0].id.text.rsplit('/', 1)[1] - - def _InsertRow(self, row): - row = dict([('c' + str(i), row[i]) for i in xrange(len(row))]) - self.gd_client.InsertRow(row, self.spreadsheet_key, self.worksheet_key) - - def _InsertBlankRow(self): - self._InsertRow('-' * self.columns_count) - - def PrepareSpreadsheet(self, run_count): - """Update cells in worksheet topmost row with service information. - - Calculate column count corresponding to run_count and create worksheet - column titles [c0, c1, ...] in the topmost row to speed up spreadsheet - updates (it allows to insert a whole row with a single request) - """ - - # Calculate the number of columns we need to present all test results. - self.columns_count = (run_count + 2) * len(test_props) - if self.columns_count > max_spreadsheet_columns: - # Google spreadsheet has just max_spreadsheet_columns columns. - max_run_count = max_spreadsheet_columns / len(test_props) - 2 - raise Exception('maximum run count is %i' % max_run_count) - # Create worksheet column titles [c0, c1, ..., cn]. - for i in xrange(self.columns_count): - self.gd_client.UpdateCell(1, i + 1, 'c' + str(i), self.spreadsheet_key, - self.worksheet_key) - - def WriteColumnTitles(self, run_count): - "Create titles for test results (mean 1, mean 2, ..., average mean, ...)" - row = [] - for prop in test_props: - row.append('') - for i in xrange(run_count): - row.append('%s %i' % (prop, i + 1)) - row.append('average ' + prop) - self._InsertRow(row) - - def WriteBrowserBenchmarkTitle(self, browser_name): - "Create browser benchmark title (browser name, date time)" - self._InsertBlankRow() - self._InsertRow([browser_name, time.strftime('%d.%m.%Y %H:%M:%S')]) - - def WriteBrowserBenchmarkResults(self, test_name, test_data): - "Insert a row with single test results" - row = [] - for prop in test_props: - if not row: - row.append(test_name) - else: - row.append('') - row.extend([str(x) for x in test_data[prop]]) - row.append(str(sum(test_data[prop]) / len(test_data[prop]))) - self._InsertRow(row) - - -class DromaeoHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): - - def do_POST(self): - self.send_response(200) - self.end_headers() - self.wfile.write("POST OK.

"); - length = int(self.headers.getheader('content-length')) - parameters = urlparse.parse_qs(self.rfile.read(length)) - self.server.got_post = True - self.server.post_data = parameters['data'] - - -class BenchmarkResults(object): - "Storage class for dromaeo benchmark results" - - def __init__(self): - self.data = {} - - def ProcessBrowserPostData(self, data): - "Convert dromaeo test results in internal format" - tests = json.loads(data[0]) - for test in tests: - test_name = test['name'] - if test_name not in self.data: - # Test is encountered for the first time. - self.data[test_name] = dict([(prop, []) for prop in test_props]) - # Append current run results. - for prop in test_props: - value = -1 - if prop in test: value = test[prop] # workaround for Opera 10.5 - self.data[test_name][prop].append(value) - - -def main(): - options = ParseArguments() - - # Start sever with dromaeo. - os.chdir(options.dromaeo_home) - server = HTTPServer(('', options.port), DromaeoHandler) - - # Open and prepare spreadsheet on google docs. - spreadsheet_writer = SpreadsheetWriter(options.email, - options.spreadsheet_title) - spreadsheet_writer.PrepareSpreadsheet(options.run_count) - spreadsheet_writer.WriteColumnTitles(options.run_count) - - for browser in options.browsers: - browser_name = os.path.splitext(os.path.basename(browser))[0] - spreadsheet_writer.WriteBrowserBenchmarkTitle(browser_name) - benchmark_results = BenchmarkResults() - for run_number in xrange(options.run_count): - print '%s run %i' % (browser_name, run_number + 1) - # Run browser. - test_page = 'http://localhost:%i/index.html?%s&automated&post_json' % ( - options.port, options.filter) - browser_process = subprocess.Popen('%s "%s"' % (browser, test_page)) - server.got_post = False - server.post_data = None - # Wait until POST request from browser. - while not server.got_post: - server.handle_request() - benchmark_results.ProcessBrowserPostData(server.post_data) - # Kill browser. - KillProcessByName(browser) - browser_process.wait() - - # Insert test results into spreadsheet. - for (test_name, test_data) in benchmark_results.data.iteritems(): - spreadsheet_writer.WriteBrowserBenchmarkResults(test_name, test_data) - - server.socket.close() - return 0 - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/tools/export_tarball/export_tarball.py b/tools/export_tarball/export_tarball.py deleted file mode 100755 index 36a98268ff..0000000000 --- a/tools/export_tarball/export_tarball.py +++ /dev/null @@ -1,172 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -""" -This tool creates a tarball with all the sources, but without .svn directories. - -It can also remove files which are not strictly required for build, so that -the resulting tarball can be reasonably small (last time it was ~110 MB). - -Example usage: - -export_tarball.py /foo/bar - -The above will create file /foo/bar.tar.bz2. -""" - -import optparse -import os -import subprocess -import sys -import tarfile - - -NONESSENTIAL_DIRS = ( - 'breakpad/src/processor/testdata', - 'chrome/browser/resources/tracing/tests', - 'chrome/common/extensions/docs', - 'chrome/tools/test/reference_build', - 'courgette/testdata', - 'data', - 'native_client/src/trusted/service_runtime/testdata', - 'src/chrome/test/data', - 'o3d/documentation', - 'o3d/samples', - 'o3d/tests', - 'ppapi/examples', - 'ppapi/native_client/tests', - 'third_party/angle/samples/gles2_book', - 'third_party/findbugs', - 'third_party/hunspell_dictionaries', - 'third_party/hunspell/tests', - 'third_party/lighttpd', - 'third_party/sqlite/src/test', - 'third_party/sqlite/test', - 'third_party/vc_80', - 'third_party/xdg-utils/tests', - 'third_party/yasm/source/patched-yasm/modules/arch/x86/tests', - 'third_party/yasm/source/patched-yasm/modules/dbgfmts/dwarf2/tests', - 'third_party/yasm/source/patched-yasm/modules/objfmts/bin/tests', - 'third_party/yasm/source/patched-yasm/modules/objfmts/coff/tests', - 'third_party/yasm/source/patched-yasm/modules/objfmts/elf/tests', - 'third_party/yasm/source/patched-yasm/modules/objfmts/macho/tests', - 'third_party/yasm/source/patched-yasm/modules/objfmts/rdf/tests', - 'third_party/yasm/source/patched-yasm/modules/objfmts/win32/tests', - 'third_party/yasm/source/patched-yasm/modules/objfmts/win64/tests', - 'third_party/yasm/source/patched-yasm/modules/objfmts/xdf/tests', - 'third_party/WebKit/LayoutTests', - 'third_party/WebKit/Source/JavaScriptCore/tests', - 'third_party/WebKit/Source/WebCore/ChangeLog', - 'third_party/WebKit/Source/WebKit2', - 'third_party/WebKit/Tools/Scripts', - 'tools/gyp/test', - 'v8/test', - 'webkit/data/layout_tests', - 'webkit/tools/test/reference_build', -) - -TESTDIRS = ( - 'chrome/test/data', - 'content/test/data', - 'media/test/data', - 'net/data', -) - -PRUNEDDIRS = ( - 'courgette', -) - - -def GetSourceDirectory(): - return os.path.realpath( - os.path.join(os.path.dirname(__file__), '..', '..', '..', 'src')) - - -# Workaround lack of the exclude parameter in add method in python-2.4. -# TODO(phajdan.jr): remove the workaround when it's not needed on the bot. -class MyTarFile(tarfile.TarFile): - def set_remove_nonessential_files(self, remove): - self.__remove_nonessential_files = remove - - def add(self, name, arcname=None, recursive=True, exclude=None, filter=None): - head, tail = os.path.split(name) - if tail in ('.svn', '.git'): - return - - if self.__remove_nonessential_files: - # WebKit change logs take quite a lot of space. This saves ~10 MB - # in a bzip2-compressed tarball. - if 'ChangeLog' in name: - return - - # Remove contents of non-essential directories, but preserve gyp files, - # so that build/gyp_chromium can work. - for nonessential_dir in (NONESSENTIAL_DIRS + TESTDIRS + PRUNEDDIRS): - dir_path = os.path.join(GetSourceDirectory(), nonessential_dir) - if (name.startswith(dir_path) and - os.path.isfile(name) and - 'gyp' not in name): - return - - tarfile.TarFile.add(self, name, arcname=arcname, recursive=recursive) - - -def main(argv): - parser = optparse.OptionParser() - parser.add_option("--basename") - parser.add_option("--remove-nonessential-files", - dest="remove_nonessential_files", - action="store_true", default=False) - parser.add_option("--test-data", action="store_true") - # TODO(phajdan.jr): Remove --xz option when it's not needed for compatibility. - parser.add_option("--xz", action="store_true") - - options, args = parser.parse_args(argv) - - if len(args) != 1: - print 'You must provide only one argument: output file name' - print '(without .tar.xz extension).' - return 1 - - if not os.path.exists(GetSourceDirectory()): - print 'Cannot find the src directory ' + GetSourceDirectory() - return 1 - - # These two commands are from src/DEPS; please keep them in sync. - if subprocess.call(['python', 'build/util/lastchange.py', '-o', - 'build/util/LASTCHANGE'], cwd=GetSourceDirectory()) != 0: - print 'Could not run build/util/lastchange.py to update LASTCHANGE.' - return 1 - if subprocess.call(['python', 'build/util/lastchange.py', '-s', - 'third_party/WebKit', '-o', - 'build/util/LASTCHANGE.blink'], - cwd=GetSourceDirectory()) != 0: - print 'Could not run build/util/lastchange.py to update LASTCHANGE.blink.' - return 1 - - output_fullname = args[0] + '.tar' - output_basename = options.basename or os.path.basename(args[0]) - - archive = MyTarFile.open(output_fullname, 'w') - archive.set_remove_nonessential_files(options.remove_nonessential_files) - try: - if options.test_data: - for directory in TESTDIRS: - archive.add(os.path.join(GetSourceDirectory(), directory), - arcname=os.path.join(output_basename, directory)) - else: - archive.add(GetSourceDirectory(), arcname=output_basename) - finally: - archive.close() - - if subprocess.call(['xz', '-9', output_fullname]) != 0: - print 'xz -9 failed!' - return 1 - - return 0 - - -if __name__ == "__main__": - sys.exit(main(sys.argv[1:])) diff --git a/tools/export_tarball/export_v8_tarball.py b/tools/export_tarball/export_v8_tarball.py deleted file mode 100755 index 30767b6287..0000000000 --- a/tools/export_tarball/export_v8_tarball.py +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2011 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Creates a tarball with V8 sources, but without .svn directories. - -This allows easy packaging of V8, synchronized with browser releases. - -Example usage: - -export_v8_tarball.py /foo/bar - -The above will create file /foo/bar/v8-VERSION.tar.bz2 if it doesn't exist. -""" - -import optparse -import os -import re -import subprocess -import sys -import tarfile - -_V8_MAJOR_VERSION_PATTERN = re.compile(r'#define\s+MAJOR_VERSION\s+(.*)') -_V8_MINOR_VERSION_PATTERN = re.compile(r'#define\s+MINOR_VERSION\s+(.*)') -_V8_BUILD_NUMBER_PATTERN = re.compile(r'#define\s+BUILD_NUMBER\s+(.*)') -_V8_PATCH_LEVEL_PATTERN = re.compile(r'#define\s+PATCH_LEVEL\s+(.*)') - -_V8_PATTERNS = [ - _V8_MAJOR_VERSION_PATTERN, - _V8_MINOR_VERSION_PATTERN, - _V8_BUILD_NUMBER_PATTERN, - _V8_PATCH_LEVEL_PATTERN] - - -def GetV8Version(v8_directory): - """ - Returns version number as string based on the string - contents of version.cc file. - """ - with open(os.path.join(v8_directory, 'src', 'version.cc')) as version_file: - version_contents = version_file.read() - - version_components = [] - for pattern in _V8_PATTERNS: - version_components.append(pattern.search(version_contents).group(1).strip()) - - if version_components[len(version_components) - 1] == '0': - version_components.pop() - - return '.'.join(version_components) - - -def GetSourceDirectory(): - return os.path.realpath( - os.path.join(os.path.dirname(__file__), '..', '..', '..', 'src')) - - -def GetV8Directory(): - return os.path.join(GetSourceDirectory(), 'v8') - - -# Workaround lack of the exclude parameter in add method in python-2.4. -# TODO(phajdan.jr): remove the workaround when it's not needed on the bot. -class MyTarFile(tarfile.TarFile): - def add(self, name, arcname=None, recursive=True, exclude=None, filter=None): - head, tail = os.path.split(name) - if tail in ('.svn', '.git'): - return - - tarfile.TarFile.add(self, name, arcname=arcname, recursive=recursive) - - -def main(argv): - parser = optparse.OptionParser() - options, args = parser.parse_args(argv) - - if len(args) != 1: - print 'You must provide only one argument: output file directory' - return 1 - - v8_directory = GetV8Directory() - if not os.path.exists(v8_directory): - print 'Cannot find the v8 directory.' - return 1 - - v8_version = GetV8Version(v8_directory) - print 'Packaging V8 version %s...' % v8_version - output_basename = 'v8-%s' % v8_version - output_fullname = os.path.join(args[0], output_basename + '.tar.bz2') - - if os.path.exists(output_fullname): - print 'Already packaged, exiting.' - return 0 - - subprocess.check_call(["make", "dependencies"], cwd=v8_directory) - - archive = MyTarFile.open(output_fullname, 'w:bz2') - try: - archive.add(v8_directory, arcname=output_basename) - finally: - archive.close() - - return 0 - - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) diff --git a/tools/find_depot_tools.py b/tools/find_depot_tools.py deleted file mode 100644 index 0fa151b162..0000000000 --- a/tools/find_depot_tools.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright (c) 2011 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -"""Small utility function to find depot_tools and add it to the python path. - -Will throw an ImportError exception if depot_tools can't be found since it -imports breakpad. -""" - -import os -import sys - -def add_depot_tools_to_path(): - """Search for depot_tools and add it to sys.path.""" - # First look if depot_tools is already in PYTHONPATH. - for i in sys.path: - if i.rstrip(os.sep).endswith('depot_tools'): - return i - # Then look if depot_tools is in PATH, common case. - for i in os.environ['PATH'].split(os.pathsep): - if i.rstrip(os.sep).endswith('depot_tools'): - sys.path.append(i.rstrip(os.sep)) - return i - # Rare case, it's not even in PATH, look upward up to root. - root_dir = os.path.dirname(os.path.abspath(__file__)) - previous_dir = os.path.abspath(__file__) - while root_dir and root_dir != previous_dir: - if os.path.isfile(os.path.join(root_dir, 'depot_tools', 'breakpad.py')): - i = os.path.join(root_dir, 'depot_tools') - sys.path.append(i) - return i - previous_dir = root_dir - root_dir = os.path.dirname(root_dir) - print >> sys.stderr, 'Failed to find depot_tools' - return None - -add_depot_tools_to_path() - -# pylint: disable=W0611 -import breakpad diff --git a/tools/find_runtime_symbols/OWNERS b/tools/find_runtime_symbols/OWNERS deleted file mode 100644 index aeea00ec3e..0000000000 --- a/tools/find_runtime_symbols/OWNERS +++ /dev/null @@ -1 +0,0 @@ -dmikurube@chromium.org diff --git a/tools/find_runtime_symbols/PRESUBMIT.py b/tools/find_runtime_symbols/PRESUBMIT.py deleted file mode 100644 index 8d6889ce3f..0000000000 --- a/tools/find_runtime_symbols/PRESUBMIT.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Top-level presubmit script for find_runtime_symbols. - -See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for -details on the presubmit API built into gcl. -""" - - -def CommonChecks(input_api, output_api): - import sys - def join(*args): - return input_api.os_path.join(input_api.PresubmitLocalPath(), *args) - - output = [] - sys_path_backup = sys.path - try: - sys.path = [ - join('..', 'find_runtime_symbols'), - ] + sys.path - output.extend(input_api.canned_checks.RunPylint(input_api, output_api)) - finally: - sys.path = sys_path_backup - - output.extend( - input_api.canned_checks.RunUnitTestsInDirectory( - input_api, output_api, - input_api.os_path.join(input_api.PresubmitLocalPath(), 'tests'), - whitelist=[r'.+_test\.py$'])) - - if input_api.is_committing: - output.extend(input_api.canned_checks.PanProjectChecks(input_api, - output_api, - owners_check=False)) - return output - - -def CheckChangeOnUpload(input_api, output_api): - return CommonChecks(input_api, output_api) - - -def CheckChangeOnCommit(input_api, output_api): - return CommonChecks(input_api, output_api) diff --git a/tools/find_runtime_symbols/README b/tools/find_runtime_symbols/README deleted file mode 100644 index ee5c2ac88c..0000000000 --- a/tools/find_runtime_symbols/README +++ /dev/null @@ -1,24 +0,0 @@ -This script maps runtime addresses to symbol names. It is robust over -Address Space Layout Randomization (ASLR) since it uses runtime addresses with -runtime mapping information (/proc/.../maps). -Like 'pprof --symbols' in gperftools . - - -Step 1: Prepare symbol information. - -It is required to collect symbol information before mapping runtime addresses -to symbol names. - -./prepare_symbol_info.py /path/to/maps [/another/path/to/symbol_info_dir] - -The required 'maps' file is /proc/.../maps of the process at runtime. - - -Step 2: Find symbols. - -./find_runtime_symbols.py /path/to/symbol_info_dir < addresses.txt - -'symbol_info_dir' is the result of the Step 1. -The stdin should be a list of hex addresses to map, one per line. - -The results will be printed to stdout like 'pprof --symbols'. diff --git a/tools/find_runtime_symbols/find_runtime_symbols.py b/tools/find_runtime_symbols/find_runtime_symbols.py deleted file mode 100755 index bed9e800b1..0000000000 --- a/tools/find_runtime_symbols/find_runtime_symbols.py +++ /dev/null @@ -1,207 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -"""Find symbols in a binary corresponding to given runtime virtual addresses. - -Note that source file names are treated as symbols in this script while they -are actually not. -""" - -import json -import logging -import os -import sys - -from static_symbols import StaticSymbolsInFile -from proc_maps import ProcMaps - -try: - from collections import OrderedDict # pylint: disable=E0611 -except ImportError: - BASE_PATH = os.path.dirname(os.path.abspath(__file__)) - SIMPLEJSON_PATH = os.path.join(BASE_PATH, os.pardir, os.pardir, 'third_party') - sys.path.insert(0, SIMPLEJSON_PATH) - from simplejson import OrderedDict - - -FUNCTION_SYMBOLS = 0 -SOURCEFILE_SYMBOLS = 1 -TYPEINFO_SYMBOLS = 2 - -_MAPS_FILENAME = 'maps' -_FILES_FILENAME = 'files.json' - - -class RuntimeSymbolsInProcess(object): - def __init__(self): - self._maps = None - self._static_symbols_in_filse = {} - - def find_procedure(self, runtime_address): - for vma in self._maps.iter(ProcMaps.executable): - if vma.begin <= runtime_address < vma.end: - static_symbols = self._static_symbols_in_filse.get(vma.name) - if static_symbols: - return static_symbols.find_procedure_by_runtime_address( - runtime_address, vma) - else: - return None - return None - - def find_sourcefile(self, runtime_address): - for vma in self._maps.iter(ProcMaps.executable): - if vma.begin <= runtime_address < vma.end: - static_symbols = self._static_symbols_in_filse.get(vma.name) - if static_symbols: - return static_symbols.find_sourcefile_by_runtime_address( - runtime_address, vma) - else: - return None - return None - - def find_typeinfo(self, runtime_address): - for vma in self._maps.iter(ProcMaps.constants): - if vma.begin <= runtime_address < vma.end: - static_symbols = self._static_symbols_in_filse.get(vma.name) - if static_symbols: - return static_symbols.find_typeinfo_by_runtime_address( - runtime_address, vma) - else: - return None - return None - - @staticmethod - def load(prepared_data_dir): - symbols_in_process = RuntimeSymbolsInProcess() - - with open(os.path.join(prepared_data_dir, _MAPS_FILENAME), mode='r') as f: - symbols_in_process._maps = ProcMaps.load(f) - with open(os.path.join(prepared_data_dir, _FILES_FILENAME), mode='r') as f: - files = json.load(f) - - # pylint: disable=W0212 - for vma in symbols_in_process._maps.iter(ProcMaps.executable_and_constants): - file_entry = files.get(vma.name) - if not file_entry: - continue - - static_symbols = StaticSymbolsInFile(vma.name) - - nm_entry = file_entry.get('nm') - if nm_entry and nm_entry['format'] == 'bsd': - with open(os.path.join(prepared_data_dir, nm_entry['file']), 'r') as f: - static_symbols.load_nm_bsd(f, nm_entry['mangled']) - - readelf_entry = file_entry.get('readelf-e') - if readelf_entry: - with open(os.path.join(prepared_data_dir, readelf_entry['file']), - 'r') as f: - static_symbols.load_readelf_ew(f) - - decodedline_file_entry = file_entry.get('readelf-debug-decodedline-file') - if decodedline_file_entry: - with open(os.path.join(prepared_data_dir, - decodedline_file_entry['file']), 'r') as f: - static_symbols.load_readelf_debug_decodedline_file(f) - - symbols_in_process._static_symbols_in_filse[vma.name] = static_symbols - - return symbols_in_process - - -def _find_runtime_function_symbols(symbols_in_process, addresses): - result = OrderedDict() - for address in addresses: - if isinstance(address, basestring): - address = int(address, 16) - found = symbols_in_process.find_procedure(address) - if found: - result[address] = found.name - else: - result[address] = '0x%016x' % address - return result - - -def _find_runtime_sourcefile_symbols(symbols_in_process, addresses): - result = OrderedDict() - for address in addresses: - if isinstance(address, basestring): - address = int(address, 16) - found = symbols_in_process.find_sourcefile(address) - if found: - result[address] = found - else: - result[address] = '' - return result - - -def _find_runtime_typeinfo_symbols(symbols_in_process, addresses): - result = OrderedDict() - for address in addresses: - if isinstance(address, basestring): - address = int(address, 16) - if address == 0: - result[address] = 'no typeinfo' - else: - found = symbols_in_process.find_typeinfo(address) - if found: - if found.startswith('typeinfo for '): - result[address] = found[13:] - else: - result[address] = found - else: - result[address] = '0x%016x' % address - return result - - -_INTERNAL_FINDERS = { - FUNCTION_SYMBOLS: _find_runtime_function_symbols, - SOURCEFILE_SYMBOLS: _find_runtime_sourcefile_symbols, - TYPEINFO_SYMBOLS: _find_runtime_typeinfo_symbols, - } - - -def find_runtime_symbols(symbol_type, symbols_in_process, addresses): - return _INTERNAL_FINDERS[symbol_type](symbols_in_process, addresses) - - -def main(): - # FIX: Accept only .pre data - if len(sys.argv) < 2: - sys.stderr.write("""Usage: -%s /path/to/prepared_data_dir/ < addresses.txt -""" % sys.argv[0]) - return 1 - - log = logging.getLogger('find_runtime_symbols') - log.setLevel(logging.WARN) - handler = logging.StreamHandler() - handler.setLevel(logging.WARN) - formatter = logging.Formatter('%(message)s') - handler.setFormatter(formatter) - log.addHandler(handler) - - prepared_data_dir = sys.argv[1] - if not os.path.exists(prepared_data_dir): - log.warn("Nothing found: %s" % prepared_data_dir) - return 1 - if not os.path.isdir(prepared_data_dir): - log.warn("Not a directory: %s" % prepared_data_dir) - return 1 - - symbols_in_process = RuntimeSymbolsInProcess.load(prepared_data_dir) - symbols_dict = find_runtime_symbols(FUNCTION_SYMBOLS, - symbols_in_process, - sys.stdin) - for address, symbol in symbols_dict: - if symbol: - print '%016x %s' % (address, symbol) - else: - print '%016x' % address - - return 0 - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/tools/find_runtime_symbols/prepare_symbol_info.py b/tools/find_runtime_symbols/prepare_symbol_info.py deleted file mode 100755 index d5503881a1..0000000000 --- a/tools/find_runtime_symbols/prepare_symbol_info.py +++ /dev/null @@ -1,226 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import hashlib -import json -import logging -import os -import re -import shutil -import subprocess -import sys -import tempfile - -from proc_maps import ProcMaps - - -BASE_PATH = os.path.dirname(os.path.abspath(__file__)) -REDUCE_DEBUGLINE_PATH = os.path.join(BASE_PATH, 'reduce_debugline.py') -LOGGER = logging.getLogger('prepare_symbol_info') - - -def _dump_command_result(command, output_dir_path, basename, suffix): - handle_out, filename_out = tempfile.mkstemp( - suffix=suffix, prefix=basename + '.', dir=output_dir_path) - handle_err, filename_err = tempfile.mkstemp( - suffix=suffix + '.err', prefix=basename + '.', dir=output_dir_path) - error = False - try: - subprocess.check_call( - command, stdout=handle_out, stderr=handle_err, shell=True) - except (OSError, subprocess.CalledProcessError): - error = True - finally: - os.close(handle_err) - os.close(handle_out) - - if os.path.exists(filename_err): - if LOGGER.getEffectiveLevel() <= logging.DEBUG: - with open(filename_err, 'r') as f: - for line in f: - LOGGER.debug(line.rstrip()) - os.remove(filename_err) - - if os.path.exists(filename_out) and ( - os.path.getsize(filename_out) == 0 or error): - os.remove(filename_out) - return None - - if not os.path.exists(filename_out): - return None - - return filename_out - - -def prepare_symbol_info(maps_path, - output_dir_path=None, - alternative_dirs=None, - use_tempdir=False, - use_source_file_name=False): - """Prepares (collects) symbol information files for find_runtime_symbols. - - 1) If |output_dir_path| is specified, it tries collecting symbol information - files in the given directory |output_dir_path|. - 1-a) If |output_dir_path| doesn't exist, create the directory and use it. - 1-b) If |output_dir_path| is an empty directory, use it. - 1-c) If |output_dir_path| is a directory which has 'files.json', assumes that - files are already collected and just ignores it. - 1-d) Otherwise, depends on |use_tempdir|. - - 2) If |output_dir_path| is not specified, it tries to create a new directory - depending on 'maps_path'. - - If it cannot create a new directory, creates a temporary directory depending - on |use_tempdir|. If |use_tempdir| is False, returns None. - - Args: - maps_path: A path to a file which contains '/proc//maps'. - alternative_dirs: A mapping from a directory '/path/on/target' where the - target process runs to a directory '/path/on/host' where the script - reads the binary. Considered to be used for Android binaries. - output_dir_path: A path to a directory where files are prepared. - use_tempdir: If True, it creates a temporary directory when it cannot - create a new directory. - use_source_file_name: If True, it adds reduced result of 'readelf -wL' - to find source file names. - - Returns: - A pair of a path to the prepared directory and a boolean representing - if it created a temporary directory or not. - """ - alternative_dirs = alternative_dirs or {} - if not output_dir_path: - matched = re.match('^(.*)\.maps$', os.path.basename(maps_path)) - if matched: - output_dir_path = matched.group(1) + '.pre' - if not output_dir_path: - matched = re.match('^/proc/(.*)/maps$', os.path.realpath(maps_path)) - if matched: - output_dir_path = matched.group(1) + '.pre' - if not output_dir_path: - output_dir_path = os.path.basename(maps_path) + '.pre' - # TODO(dmikurube): Find another candidate for output_dir_path. - - used_tempdir = False - LOGGER.info('Data for profiling will be collected in "%s".' % output_dir_path) - if os.path.exists(output_dir_path): - if os.path.isdir(output_dir_path) and not os.listdir(output_dir_path): - LOGGER.warn('Using an empty existing directory "%s".' % output_dir_path) - else: - LOGGER.warn('A file or a directory exists at "%s".' % output_dir_path) - if os.path.exists(os.path.join(output_dir_path, 'files.json')): - LOGGER.warn('Using the existing directory "%s".' % output_dir_path) - return output_dir_path, used_tempdir - else: - if use_tempdir: - output_dir_path = tempfile.mkdtemp() - used_tempdir = True - LOGGER.warn('Using a temporary directory "%s".' % output_dir_path) - else: - LOGGER.warn('The directory "%s" is not available.' % output_dir_path) - return None, used_tempdir - else: - LOGGER.info('Creating a new directory "%s".' % output_dir_path) - try: - os.mkdir(output_dir_path) - except OSError: - LOGGER.warn('A directory "%s" cannot be created.' % output_dir_path) - if use_tempdir: - output_dir_path = tempfile.mkdtemp() - used_tempdir = True - LOGGER.warn('Using a temporary directory "%s".' % output_dir_path) - else: - LOGGER.warn('The directory "%s" is not available.' % output_dir_path) - return None, used_tempdir - - shutil.copyfile(maps_path, os.path.join(output_dir_path, 'maps')) - - with open(maps_path, mode='r') as f: - maps = ProcMaps.load(f) - - LOGGER.debug('Listing up symbols.') - files = {} - for entry in maps.iter(ProcMaps.executable): - LOGGER.debug(' %016x-%016x +%06x %s' % ( - entry.begin, entry.end, entry.offset, entry.name)) - binary_path = entry.name - for target_path, host_path in alternative_dirs.iteritems(): - if entry.name.startswith(target_path): - binary_path = entry.name.replace(target_path, host_path, 1) - nm_filename = _dump_command_result( - 'nm -n --format bsd %s | c++filt' % binary_path, - output_dir_path, os.path.basename(binary_path), '.nm') - if not nm_filename: - continue - readelf_e_filename = _dump_command_result( - 'readelf -eW %s' % binary_path, - output_dir_path, os.path.basename(binary_path), '.readelf-e') - if not readelf_e_filename: - continue - readelf_debug_decodedline_file = None - if use_source_file_name: - readelf_debug_decodedline_file = _dump_command_result( - 'readelf -wL %s | %s' % (binary_path, REDUCE_DEBUGLINE_PATH), - output_dir_path, os.path.basename(binary_path), '.readelf-wL') - - files[entry.name] = {} - files[entry.name]['nm'] = { - 'file': os.path.basename(nm_filename), - 'format': 'bsd', - 'mangled': False} - files[entry.name]['readelf-e'] = { - 'file': os.path.basename(readelf_e_filename)} - if readelf_debug_decodedline_file: - files[entry.name]['readelf-debug-decodedline-file'] = { - 'file': os.path.basename(readelf_debug_decodedline_file)} - - files[entry.name]['size'] = os.stat(binary_path).st_size - - with open(binary_path, 'rb') as entry_f: - md5 = hashlib.md5() - sha1 = hashlib.sha1() - chunk = entry_f.read(1024 * 1024) - while chunk: - md5.update(chunk) - sha1.update(chunk) - chunk = entry_f.read(1024 * 1024) - files[entry.name]['sha1'] = sha1.hexdigest() - files[entry.name]['md5'] = md5.hexdigest() - - with open(os.path.join(output_dir_path, 'files.json'), 'w') as f: - json.dump(files, f, indent=2, sort_keys=True) - - LOGGER.info('Collected symbol information at "%s".' % output_dir_path) - return output_dir_path, used_tempdir - - -def main(): - if not sys.platform.startswith('linux'): - sys.stderr.write('This script work only on Linux.') - return 1 - - LOGGER.setLevel(logging.DEBUG) - handler = logging.StreamHandler() - handler.setLevel(logging.INFO) - formatter = logging.Formatter('%(message)s') - handler.setFormatter(formatter) - LOGGER.addHandler(handler) - - # TODO(dmikurube): Specify |alternative_dirs| from command line. - if len(sys.argv) < 2: - sys.stderr.write("""Usage: -%s /path/to/maps [/path/to/output_data_dir/] -""" % sys.argv[0]) - return 1 - elif len(sys.argv) == 2: - result, _ = prepare_symbol_info(sys.argv[1]) - else: - result, _ = prepare_symbol_info(sys.argv[1], sys.argv[2]) - - return not result - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/tools/find_runtime_symbols/proc_maps.py b/tools/find_runtime_symbols/proc_maps.py deleted file mode 100644 index 2d917b3212..0000000000 --- a/tools/find_runtime_symbols/proc_maps.py +++ /dev/null @@ -1,125 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import re - - -_MAPS_PATTERN = re.compile( - r'^([a-f0-9]+)-([a-f0-9]+)\s+(.)(.)(.)(.)\s+([a-f0-9]+)\s+(\S+):(\S+)\s+' - r'(\d+)\s*(.*)$', re.IGNORECASE) - - -class ProcMapsEntry(object): - """A class representing one line in /proc/.../maps.""" - - def __init__( - self, begin, end, readable, writable, executable, private, offset, - major, minor, inode, name): - self.begin = begin - self.end = end - self.readable = readable - self.writable = writable - self.executable = executable - self.private = private - self.offset = offset - self.major = major - self.minor = minor - self.inode = inode - self.name = name - - def as_dict(self): - return { - 'begin': self.begin, - 'end': self.end, - 'readable': self.readable, - 'writable': self.writable, - 'executable': self.executable, - 'private': self.private, - 'offset': self.offset, - 'major': self.major, - 'minor': self.minor, - 'inode': self.inode, - 'name': self.name, - } - - -class ProcMaps(object): - """A class representing contents in /proc/.../maps.""" - - def __init__(self): - self._sorted_indexes = [] - self._dictionary = {} - self._sorted = True - - def iter(self, condition): - if not self._sorted: - self._sorted_indexes.sort() - self._sorted = True - for index in self._sorted_indexes: - if not condition or condition(self._dictionary[index]): - yield self._dictionary[index] - - def __iter__(self): - if not self._sorted: - self._sorted_indexes.sort() - self._sorted = True - for index in self._sorted_indexes: - yield self._dictionary[index] - - @staticmethod - def load(f): - table = ProcMaps() - for line in f: - table.append_line(line) - return table - - def append_line(self, line): - entry = self.parse_line(line) - if entry: - self._append_entry(entry) - - @staticmethod - def parse_line(line): - matched = _MAPS_PATTERN.match(line) - if matched: - return ProcMapsEntry( # pylint: disable=W0212 - int(matched.group(1), 16), # begin - int(matched.group(2), 16), # end - matched.group(3), # readable - matched.group(4), # writable - matched.group(5), # executable - matched.group(6), # private - int(matched.group(7), 16), # offset - matched.group(8), # major - matched.group(9), # minor - int(matched.group(10), 10), # inode - matched.group(11) # name - ) - else: - return None - - @staticmethod - def constants(entry): - return (entry.writable == '-' and entry.executable == '-' and re.match( - '\S+(\.(so|dll|dylib|bundle)|chrome)((\.\d+)+\w*(\.\d+){0,3})?', - entry.name)) - - @staticmethod - def executable(entry): - return (entry.executable == 'x' and re.match( - '\S+(\.(so|dll|dylib|bundle)|chrome)((\.\d+)+\w*(\.\d+){0,3})?', - entry.name)) - - @staticmethod - def executable_and_constants(entry): - return (((entry.writable == '-' and entry.executable == '-') or - entry.executable == 'x') and re.match( - '\S+(\.(so|dll|dylib|bundle)|chrome)((\.\d+)+\w*(\.\d+){0,3})?', - entry.name)) - - def _append_entry(self, entry): - if self._sorted_indexes and self._sorted_indexes[-1] > entry.begin: - self._sorted = False - self._sorted_indexes.append(entry.begin) - self._dictionary[entry.begin] = entry diff --git a/tools/find_runtime_symbols/reduce_debugline.py b/tools/find_runtime_symbols/reduce_debugline.py deleted file mode 100755 index 75c8c8578d..0000000000 --- a/tools/find_runtime_symbols/reduce_debugline.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -"""Reduces result of 'readelf -wL' to just a list of starting addresses. - -It lists up all addresses where the corresponding source files change. The -list is sorted in ascending order. See tests/reduce_debugline_test.py for -examples. - -This script assumes that the result of 'readelf -wL' ends with an empty line. - -Note: the option '-wL' has the same meaning with '--debug-dump=decodedline'. -""" - -import re -import sys - - -_FILENAME_PATTERN = re.compile('(CU: |)(.+)\:') - - -def reduce_decoded_debugline(input_file): - filename = '' - starting_dict = {} - started = False - - for line in input_file: - line = line.strip() - unpacked = line.split(None, 2) - - if len(unpacked) == 3 and unpacked[2].startswith('0x'): - if not started and filename: - started = True - starting_dict[int(unpacked[2], 16)] = filename - else: - started = False - if line.endswith(':'): - matched = _FILENAME_PATTERN.match(line) - if matched: - filename = matched.group(2) - - starting_list = [] - prev_filename = '' - for address in sorted(starting_dict): - curr_filename = starting_dict[address] - if prev_filename != curr_filename: - starting_list.append((address, starting_dict[address])) - prev_filename = curr_filename - return starting_list - - -def main(): - if len(sys.argv) != 1: - print >> sys.stderr, 'Unsupported arguments' - return 1 - - starting_list = reduce_decoded_debugline(sys.stdin) - bits64 = starting_list[-1][0] > 0xffffffff - for address, filename in starting_list: - if bits64: - print '%016x %s' % (address, filename) - else: - print '%08x %s' % (address, filename) - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/tools/find_runtime_symbols/static_symbols.py b/tools/find_runtime_symbols/static_symbols.py deleted file mode 100644 index cd57bacd99..0000000000 --- a/tools/find_runtime_symbols/static_symbols.py +++ /dev/null @@ -1,277 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import bisect -import re - - -_ARGUMENT_TYPE_PATTERN = re.compile('\([^()]*\)(\s*const)?') -_TEMPLATE_ARGUMENT_PATTERN = re.compile('<[^<>]*>') -_LEADING_TYPE_PATTERN = re.compile('^.*\s+(\w+::)') -_READELF_SECTION_HEADER_PATTER = re.compile( - '^\s*\[\s*(Nr|\d+)\]\s+(|\S+)\s+([A-Z_]+)\s+([0-9a-f]+)\s+' - '([0-9a-f]+)\s+([0-9a-f]+)\s+([0-9]+)\s+([WAXMSILGxOop]*)\s+' - '([0-9]+)\s+([0-9]+)\s+([0-9]+)') - - -class ParsingException(Exception): - def __str__(self): - return repr(self.args[0]) - - -class AddressMapping(object): - def __init__(self): - self._symbol_map = {} - - def append(self, start, entry): - self._symbol_map[start] = entry - - def find(self, address): - return self._symbol_map.get(address) - - -class RangeAddressMapping(AddressMapping): - def __init__(self): - super(RangeAddressMapping, self).__init__() - self._sorted_start_list = [] - self._is_sorted = True - - def append(self, start, entry): - if self._sorted_start_list: - if self._sorted_start_list[-1] > start: - self._is_sorted = False - elif self._sorted_start_list[-1] == start: - return - self._sorted_start_list.append(start) - self._symbol_map[start] = entry - - def find(self, address): - if not self._sorted_start_list: - return None - if not self._is_sorted: - self._sorted_start_list.sort() - self._is_sorted = True - found_index = bisect.bisect_left(self._sorted_start_list, address) - found_start_address = self._sorted_start_list[found_index - 1] - return self._symbol_map[found_start_address] - - -class Procedure(object): - """A class for a procedure symbol and an address range for the symbol.""" - - def __init__(self, start, end, name): - self.start = start - self.end = end - self.name = name - - def __eq__(self, other): - return (self.start == other.start and - self.end == other.end and - self.name == other.name) - - def __ne__(self, other): - return not self.__eq__(other) - - def __str__(self): - return '%x-%x: %s' % (self.start, self.end, self.name) - - -class ElfSection(object): - """A class for an elf section header.""" - - def __init__( - self, number, name, stype, address, offset, size, es, flg, lk, inf, al): - self.number = number - self.name = name - self.stype = stype - self.address = address - self.offset = offset - self.size = size - self.es = es - self.flg = flg - self.lk = lk - self.inf = inf - self.al = al - - def __eq__(self, other): - return (self.number == other.number and - self.name == other.name and - self.stype == other.stype and - self.address == other.address and - self.offset == other.offset and - self.size == other.size and - self.es == other.es and - self.flg == other.flg and - self.lk == other.lk and - self.inf == other.inf and - self.al == other.al) - - def __ne__(self, other): - return not self.__eq__(other) - - def __str__(self): - return '%x+%x(%x) %s' % (self.address, self.size, self.offset, self.name) - - -class StaticSymbolsInFile(object): - """Represents static symbol information in a binary file.""" - - def __init__(self, my_name): - self.my_name = my_name - self._elf_sections = [] - self._procedures = RangeAddressMapping() - self._sourcefiles = RangeAddressMapping() - self._typeinfos = AddressMapping() - - def _append_elf_section(self, elf_section): - self._elf_sections.append(elf_section) - - def _append_procedure(self, start, procedure): - self._procedures.append(start, procedure) - - def _append_sourcefile(self, start, sourcefile): - self._sourcefiles.append(start, sourcefile) - - def _append_typeinfo(self, start, typeinfo): - self._typeinfos.append(start, typeinfo) - - def _find_symbol_by_runtime_address(self, address, vma, target): - if not (vma.begin <= address < vma.end): - return None - - if vma.name != self.my_name: - return None - - file_offset = address - (vma.begin - vma.offset) - elf_address = None - for section in self._elf_sections: - if section.offset <= file_offset < (section.offset + section.size): - elf_address = section.address + file_offset - section.offset - if not elf_address: - return None - - return target.find(elf_address) - - def find_procedure_by_runtime_address(self, address, vma): - return self._find_symbol_by_runtime_address(address, vma, self._procedures) - - def find_sourcefile_by_runtime_address(self, address, vma): - return self._find_symbol_by_runtime_address(address, vma, self._sourcefiles) - - def find_typeinfo_by_runtime_address(self, address, vma): - return self._find_symbol_by_runtime_address(address, vma, self._typeinfos) - - def load_readelf_ew(self, f): - found_header = False - for line in f: - if line.rstrip() == 'Section Headers:': - found_header = True - break - if not found_header: - return None - - for line in f: - line = line.rstrip() - matched = _READELF_SECTION_HEADER_PATTER.match(line) - if matched: - self._append_elf_section(ElfSection( - int(matched.group(1), 10), # number - matched.group(2), # name - matched.group(3), # stype - int(matched.group(4), 16), # address - int(matched.group(5), 16), # offset - int(matched.group(6), 16), # size - matched.group(7), # es - matched.group(8), # flg - matched.group(9), # lk - matched.group(10), # inf - matched.group(11) # al - )) - else: - if line in ('Key to Flags:', 'Program Headers:'): - break - - def load_readelf_debug_decodedline_file(self, input_file): - for line in input_file: - splitted = line.rstrip().split(None, 2) - self._append_sourcefile(int(splitted[0], 16), splitted[1]) - - @staticmethod - def _parse_nm_bsd_line(line): - if line[8] == ' ': - return line[0:8], line[9], line[11:] - elif line[16] == ' ': - return line[0:16], line[17], line[19:] - raise ParsingException('Invalid nm output.') - - @staticmethod - def _get_short_function_name(function): - while True: - function, number = _ARGUMENT_TYPE_PATTERN.subn('', function) - if not number: - break - while True: - function, number = _TEMPLATE_ARGUMENT_PATTERN.subn('', function) - if not number: - break - return _LEADING_TYPE_PATTERN.sub('\g<1>', function) - - def load_nm_bsd(self, f, mangled=False): - last_start = 0 - routine = '' - - for line in f: - line = line.rstrip() - sym_value, sym_type, sym_name = self._parse_nm_bsd_line(line) - - if sym_value[0] == ' ': - continue - - start_val = int(sym_value, 16) - - if (sym_type in ('r', 'R', 'D', 'U', 'd', 'V') and - (not mangled and sym_name.startswith('typeinfo'))): - self._append_typeinfo(start_val, sym_name) - - # It's possible for two symbols to share the same address, if - # one is a zero-length variable (like __start_google_malloc) or - # one symbol is a weak alias to another (like __libc_malloc). - # In such cases, we want to ignore all values except for the - # actual symbol, which in nm-speak has type "T". The logic - # below does this, though it's a bit tricky: what happens when - # we have a series of lines with the same address, is the first - # one gets queued up to be processed. However, it won't - # *actually* be processed until later, when we read a line with - # a different address. That means that as long as we're reading - # lines with the same address, we have a chance to replace that - # item in the queue, which we do whenever we see a 'T' entry -- - # that is, a line with type 'T'. If we never see a 'T' entry, - # we'll just go ahead and process the first entry (which never - # got touched in the queue), and ignore the others. - if start_val == last_start and (sym_type == 't' or sym_type == 'T'): - # We are the 'T' symbol at this address, replace previous symbol. - routine = sym_name - continue - elif start_val == last_start: - # We're not the 'T' symbol at this address, so ignore us. - continue - - # Tag this routine with the starting address in case the image - # has multiple occurrences of this routine. We use a syntax - # that resembles template paramters that are automatically - # stripped out by ShortFunctionName() - sym_name += "<%016x>" % start_val - - if not mangled: - routine = self._get_short_function_name(routine) - self._append_procedure( - last_start, Procedure(last_start, start_val, routine)) - - last_start = start_val - routine = sym_name - - if not mangled: - routine = self._get_short_function_name(routine) - self._append_procedure( - last_start, Procedure(last_start, last_start, routine)) diff --git a/tools/find_runtime_symbols/tests/proc_maps_test.py b/tools/find_runtime_symbols/tests/proc_maps_test.py deleted file mode 100755 index 502f252c55..0000000000 --- a/tools/find_runtime_symbols/tests/proc_maps_test.py +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import cStringIO -import logging -import os -import sys -import unittest - -ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) -sys.path.insert(0, ROOT_DIR) - -from proc_maps import ProcMaps - - -class ProcMapsTest(unittest.TestCase): - _TEST_PROCMAPS = '\n'.join([ - '00000000-00001000 r--p 00000000 fc:00 0', - '0080b000-0080c000 r-xp 0020b000 fc:00 2231329' - ' /usr/bin/some', - '0080c000-0080f000 ---p 0020c000 fc:00 2231329' - ' /usr/bin/some', - '0100a000-0100c000 r-xp 0120a000 fc:00 22381' - ' /usr/bin/chrome', - '0100c000-0100f000 ---p 0120c000 fc:00 22381' - ' /usr/bin/chrome', - '0237d000-02a9b000 rw-p 00000000 00:00 0' - ' [heap]', - '7fb920e6d000-7fb920e85000 r-xp 00000000 fc:00 263482' - ' /lib/x86_64-linux-gnu/libpthread-2.15.so', - '7fb920e85000-7fb921084000 ---p 00018000 fc:00 263482' - ' /lib/x86_64-linux-gnu/libpthread-2.15.so', - '7fb9225f4000-7fb922654000 rw-s 00000000 00:04 19660808' - ' /SYSV00000000 (deleted)', - 'ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0' - ' [vsyscall]', - ]) - - _EXPECTED = [ - (0x0, 0x1000, 'r', '-', '-', 'p', 0x0, 'fc', '00', 0, ''), - (0x80b000, 0x80c000, 'r', '-', 'x', 'p', 0x20b000, - 'fc', '00', 2231329, '/usr/bin/some'), - (0x80c000, 0x80f000, '-', '-', '-', 'p', 0x20c000, - 'fc', '00', 2231329, '/usr/bin/some'), - (0x100a000, 0x100c000, 'r', '-', 'x', 'p', 0x120a000, - 'fc', '00', 22381, '/usr/bin/chrome'), - (0x100c000, 0x100f000, '-', '-', '-', 'p', 0x120c000, - 'fc', '00', 22381, '/usr/bin/chrome'), - (0x237d000, 0x2a9b000, 'r', 'w', '-', 'p', 0x0, - '00', '00', 0, '[heap]'), - (0x7fb920e6d000, 0x7fb920e85000, 'r', '-', 'x', 'p', 0x0, - 'fc', '00', 263482, '/lib/x86_64-linux-gnu/libpthread-2.15.so'), - (0x7fb920e85000, 0x7fb921084000, '-', '-', '-', 'p', 0x18000, - 'fc', '00', 263482, '/lib/x86_64-linux-gnu/libpthread-2.15.so'), - (0x7fb9225f4000, 0x7fb922654000, 'r', 'w', '-', 's', 0x0, - '00', '04', 19660808, '/SYSV00000000 (deleted)'), - (0xffffffffff600000, 0xffffffffff601000, 'r', '-', 'x', 'p', 0x0, - '00', '00', 0, '[vsyscall]'), - ] - - @staticmethod - def _expected_as_dict(index): - return { - 'begin': ProcMapsTest._EXPECTED[index][0], - 'end': ProcMapsTest._EXPECTED[index][1], - 'readable': ProcMapsTest._EXPECTED[index][2], - 'writable': ProcMapsTest._EXPECTED[index][3], - 'executable': ProcMapsTest._EXPECTED[index][4], - 'private': ProcMapsTest._EXPECTED[index][5], - 'offset': ProcMapsTest._EXPECTED[index][6], - 'major': ProcMapsTest._EXPECTED[index][7], - 'minor': ProcMapsTest._EXPECTED[index][8], - 'inode': ProcMapsTest._EXPECTED[index][9], - 'name': ProcMapsTest._EXPECTED[index][10], - } - - def test_load(self): - maps = ProcMaps.load(cStringIO.StringIO(self._TEST_PROCMAPS)) - for index, entry in enumerate(maps): - self.assertEqual(entry.as_dict(), self._expected_as_dict(index)) - - def test_constants(self): - maps = ProcMaps.load(cStringIO.StringIO(self._TEST_PROCMAPS)) - selected = [4, 7] - for index, entry in enumerate(maps.iter(ProcMaps.constants)): - self.assertEqual(entry.as_dict(), - self._expected_as_dict(selected[index])) - - def test_executable(self): - maps = ProcMaps.load(cStringIO.StringIO(self._TEST_PROCMAPS)) - selected = [3, 6] - for index, entry in enumerate(maps.iter(ProcMaps.executable)): - self.assertEqual(entry.as_dict(), - self._expected_as_dict(selected[index])) - - def test_executable_and_constants(self): - maps = ProcMaps.load(cStringIO.StringIO(self._TEST_PROCMAPS)) - selected = [3, 4, 6, 7] - for index, entry in enumerate(maps.iter(ProcMaps.executable_and_constants)): - self.assertEqual(entry.as_dict(), - self._expected_as_dict(selected[index])) - - -if __name__ == '__main__': - logging.basicConfig( - level=logging.DEBUG if '-v' in sys.argv else logging.ERROR, - format='%(levelname)5s %(filename)15s(%(lineno)3d): %(message)s') - unittest.main() diff --git a/tools/find_runtime_symbols/tests/reduce_debugline_test.py b/tools/find_runtime_symbols/tests/reduce_debugline_test.py deleted file mode 100755 index 1e3a21afc2..0000000000 --- a/tools/find_runtime_symbols/tests/reduce_debugline_test.py +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import cStringIO -import logging -import os -import sys -import textwrap -import unittest - -ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) -sys.path.insert(0, ROOT_DIR) - -import reduce_debugline - - -class ReduceDebuglineTest(unittest.TestCase): - _DECODED_DEBUGLINE = textwrap.dedent("""\ - Decoded dump of debug contents of section .debug_line: - - CU: ../../chrome/service/service_main.cc: - File name Line number Starting address - service_main.cc 21 0xa41210 - - service_main.cc 24 0xa4141f - service_main.cc 30 0xa4142b - service_main.cc 31 0xa4143e - - ../../base/message_loop.h: - message_loop.h 550 0xa41300 - - message_loop.h 551 0xa41310 - - ../../base/logging.h: - logging.h 246 0xa41710 - - logging.h 247 0xa41726 - - ../../base/logging.h: - logging.h 846 0xa3fd90 - - logging.h 846 0xa3fda0 - - """) - - _EXPECTED_REDUCED_DEBUGLINE = [ - (0xa3fd90, '../../base/logging.h'), - (0xa41210, '../../chrome/service/service_main.cc'), - (0xa41300, '../../base/message_loop.h'), - (0xa4141f, '../../chrome/service/service_main.cc'), - (0xa41710, '../../base/logging.h'), - ] - - def test(self): - ranges_dict = reduce_debugline.reduce_decoded_debugline( - cStringIO.StringIO(self._DECODED_DEBUGLINE)) - self.assertEqual(self._EXPECTED_REDUCED_DEBUGLINE, ranges_dict) - - -if __name__ == '__main__': - logging.basicConfig( - level=logging.DEBUG if '-v' in sys.argv else logging.ERROR, - format='%(levelname)5s %(filename)15s(%(lineno)3d): %(message)s') - unittest.main() diff --git a/tools/flakiness/find_flakiness.py b/tools/flakiness/find_flakiness.py deleted file mode 100755 index 21629e4a7a..0000000000 --- a/tools/flakiness/find_flakiness.py +++ /dev/null @@ -1,179 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2011 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Contains two functions that run different test cases and the same test -case in parallel repeatedly to identify flaky tests. -""" - - -import os -import re -import subprocess -import time - - -# Defaults for FindShardingFlakiness(). -FF_DATA_SUFFIX = '_flakies' -FF_SLEEP_INTERVAL = 10.0 -FF_NUM_ITERATIONS = 100 -FF_SUPERVISOR_ARGS = ['-r3', '--random-seed'] - -# Defaults for FindUnaryFlakiness(). -FF_OUTPUT_SUFFIX = '_purges' -FF_NUM_PROCS = 20 -FF_NUM_REPEATS = 10 -FF_TIMEOUT = 600 - - -def FindShardingFlakiness(test_path, data_path, supervisor_args): - """Finds flaky test cases by sharding and running a test for the specified - number of times. The data file is read at the beginning of each run to find - the last known counts and is overwritten at the end of each run with the new - counts. There is an optional sleep interval between each run so the script can - be killed without losing the data, useful for overnight (or weekend!) runs. - """ - - failed_tests = {} - # Read a previously written data file. - if os.path.exists(data_path): - data_file = open(data_path, 'r') - num_runs = int(data_file.readline().split(' ')[0]) - num_passes = int(data_file.readline().split(' ')[0]) - for line in data_file: - if line: - split_line = line.split(' -> ') - failed_tests[split_line[0]] = int(split_line[1]) - data_file.close() - # No data file found. - else: - num_runs = 0 - num_passes = 0 - - log_lines = False - args = ['python', '../sharding_supervisor/sharding_supervisor.py'] - args.extend(supervisor_args + [test_path]) - proc = subprocess.Popen(args, stderr=subprocess.PIPE) - - # Shard the test and collect failures. - while True: - line = proc.stderr.readline() - if not line: - if proc.poll() is not None: - break - continue - print line.rstrip() - if log_lines: - line = line.rstrip() - if line in failed_tests: - failed_tests[line] += 1 - else: - failed_tests[line] = 1 - elif line.find('FAILED TESTS:') >= 0: - log_lines = True - num_runs += 1 - if proc.returncode == 0: - num_passes += 1 - - # Write the data file and print results. - data_file = open(data_path, 'w') - print '%i runs' % num_runs - data_file.write('%i runs\n' % num_runs) - print '%i passes' % num_passes - data_file.write('%i passes\n' % num_passes) - for (test, count) in failed_tests.iteritems(): - print '%s -> %i' % (test, count) - data_file.write('%s -> %i\n' % (test, count)) - data_file.close() - - -def FindUnaryFlakiness(test_path, output_path, num_procs, num_repeats, timeout): - """Runs all the test cases in a given test in parallel with itself, to get at - those that hold on to shared resources. The idea is that if a test uses a - unary resource, then running many instances of this test will purge out some - of them as failures or timeouts. - """ - - test_name_regex = r'((\w+/)?\w+\.\w+(/\d+)?)' - test_start = re.compile('\[\s+RUN\s+\] ' + test_name_regex) - test_list = [] - - # Run the test to discover all the test cases. - proc = subprocess.Popen([test_path], stdout=subprocess.PIPE) - while True: - line = proc.stdout.readline() - if not line: - if proc.poll() is not None: - break - continue - print line.rstrip() - results = test_start.search(line) - if results: - test_list.append(results.group(1)) - - failures = [] - index = 0 - total = len(test_list) - - # Run each test case in parallel with itself. - for test_name in test_list: - num_fails = 0 - num_terminated = 0 - procs = [] - args = [test_path, '--gtest_filter=' + test_name, - '--gtest_repeat=%i' % num_repeats] - while len(procs) < num_procs: - procs.append(subprocess.Popen(args)) - seconds = 0 - while procs: - for proc in procs: - if proc.poll() is not None: - if proc.returncode != 0: - ++num_fails - procs.remove(proc) - # Timeout exceeded, kill the remaining processes and make a note. - if seconds > timeout: - num_fails += len(procs) - num_terminated = len(procs) - while procs: - procs.pop().terminate() - time.sleep(1.0) - seconds += 1 - if num_fails: - line = '%s: %i failed' % (test_name, num_fails) - if num_terminated: - line += ' (%i terminated)' % num_terminated - failures.append(line) - print '%s (%i / %i): %i failed' % (test_name, index, total, num_fails) - index += 1 - time.sleep(1.0) - - # Print the results and write the data file. - print failures - data_file = open(output_path, 'w') - for line in failures: - data_file.write(line + '\n') - data_file.close() - - -def main(): - if not args: - parser.error('You must specify a path to test!') - if not os.path.exists(args[0]): - parser.error('%s does not exist!' % args[0]) - - data_path = os.path.basename(args[0]) + FF_DATA_SUFFIX - output_path = os.path.basename(args[0]) + FF_OUTPUT_SUFFIX - - for i in range(FF_NUM_ITERATIONS): - FindShardingFlakiness(args[0], data_path, FF_SUPERVISOR_ARGS) - print 'That was just iteration %i of %i.' % (i + 1, FF_NUM_ITERATIONS) - time.sleep(FF_SLEEP_INTERVAL) - - FindUnaryFlakiness( - args[0], output_path, FF_NUM_PROCS, FF_NUM_REPEATS, FF_TIMEOUT) - - -if __name__ == '__main__': - main() diff --git a/tools/gdb/gdb_chrome.py b/tools/gdb/gdb_chrome.py deleted file mode 100644 index 8173fa15a5..0000000000 --- a/tools/gdb/gdb_chrome.py +++ /dev/null @@ -1,296 +0,0 @@ -# Copyright (c) 2011 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""GDB support for Chrome types. - -Add this to your gdb by amending your ~/.gdbinit as follows: - python - import sys - sys.path.insert(0, "/path/to/tools/gdb/") - import gdb_chrome - end - -This module relies on the WebKit gdb module already existing in -your Python path. - -Use - (gdb) p /r any_variable -to print |any_variable| without using any printers. -""" - -import datetime -import gdb -import webkit - -# When debugging this module, set the below variable to True, and then use -# (gdb) python del sys.modules['gdb_chrome'] -# (gdb) python import gdb_chrome -# to reload. -_DEBUGGING = False - - -pp_set = gdb.printing.RegexpCollectionPrettyPrinter("chromium") - - -def typed_ptr(ptr): - """Prints a pointer along with its exact type. - - By default, gdb would print just the address, which takes more - steps to interpret. - """ - # Returning this as a cast expression surrounded by parentheses - # makes it easier to cut+paste inside of gdb. - return '((%s)%s)' % (ptr.dynamic_type, ptr) - - -class Printer(object): - def __init__(self, val): - self.val = val - - -class StringPrinter(Printer): - def display_hint(self): - return 'string' - - -class String16Printer(StringPrinter): - def to_string(self): - return webkit.ustring_to_string(self.val['_M_dataplus']['_M_p']) -pp_set.add_printer( - 'string16', - '^string16|std::basic_string<(unsigned short|char16|base::char16).*>$', - String16Printer); - - -class GURLPrinter(StringPrinter): - def to_string(self): - return self.val['spec_'] -pp_set.add_printer('GURL', '^GURL$', GURLPrinter) - - -class FilePathPrinter(StringPrinter): - def to_string(self): - return self.val['path_']['_M_dataplus']['_M_p'] -pp_set.add_printer('FilePath', '^FilePath$', FilePathPrinter) - - -class SizePrinter(Printer): - def to_string(self): - return '%sx%s' % (self.val['width_'], self.val['height_']) -pp_set.add_printer('gfx::Size', '^gfx::(Size|SizeF|SizeBase<.*>)$', SizePrinter) - - -class PointPrinter(Printer): - def to_string(self): - return '%s,%s' % (self.val['x_'], self.val['y_']) -pp_set.add_printer('gfx::Point', '^gfx::(Point|PointF|PointBase<.*>)$', - PointPrinter) - - -class RectPrinter(Printer): - def to_string(self): - return '%s %s' % (self.val['origin_'], self.val['size_']) -pp_set.add_printer('gfx::Rect', '^gfx::(Rect|RectF|RectBase<.*>)$', - RectPrinter) - - -class SmartPtrPrinter(Printer): - def to_string(self): - return '%s%s' % (self.typename, typed_ptr(self.ptr())) - - -class ScopedRefPtrPrinter(SmartPtrPrinter): - typename = 'scoped_refptr' - def ptr(self): - return self.val['ptr_'] -pp_set.add_printer('scoped_refptr', '^scoped_refptr<.*>$', ScopedRefPtrPrinter) - - -class LinkedPtrPrinter(SmartPtrPrinter): - typename = 'linked_ptr' - def ptr(self): - return self.val['value_'] -pp_set.add_printer('linked_ptr', '^linked_ptr<.*>$', LinkedPtrPrinter) - - -class WeakPtrPrinter(SmartPtrPrinter): - typename = 'base::WeakPtr' - def ptr(self): - flag = ScopedRefPtrPrinter(self.val['ref_']['flag_']).ptr() - if flag and flag['is_valid_']: - return self.val['ptr_'] - return gdb.Value(0).cast(self.val['ptr_'].type) -pp_set.add_printer('base::WeakPtr', '^base::WeakPtr<.*>$', WeakPtrPrinter) - - -class CallbackPrinter(Printer): - """Callbacks provide no usable information so reduce the space they take.""" - def to_string(self): - return '...' -pp_set.add_printer('base::Callback', '^base::Callback<.*>$', CallbackPrinter) - - -class LocationPrinter(Printer): - def to_string(self): - return '%s()@%s:%s' % (self.val['function_name_'].string(), - self.val['file_name_'].string(), - self.val['line_number_']) -pp_set.add_printer('tracked_objects::Location', '^tracked_objects::Location$', - LocationPrinter) - - -class LockPrinter(Printer): - def to_string(self): - try: - if self.val['owned_by_thread_']: - return 'Locked by thread %s' % self.val['owning_thread_id_'] - else: - return 'Unlocked' - except gdb.error: - return 'Unknown state' -pp_set.add_printer('base::Lock', '^base::Lock$', LockPrinter) - - -class TimeDeltaPrinter(object): - def __init__(self, val): - self._timedelta = datetime.timedelta(microseconds=int(val['delta_'])) - - def timedelta(self): - return self._timedelta - - def to_string(self): - return str(self._timedelta) -pp_set.add_printer('base::TimeDelta', '^base::TimeDelta$', TimeDeltaPrinter) - - -class TimeTicksPrinter(TimeDeltaPrinter): - def __init__(self, val): - self._timedelta = datetime.timedelta(microseconds=int(val['ticks_'])) -pp_set.add_printer('base::TimeTicks', '^base::TimeTicks$', TimeTicksPrinter) - - -class TimePrinter(object): - def __init__(self, val): - timet_offset = gdb.parse_and_eval( - 'base::Time::kTimeTToMicrosecondsOffset') - self._datetime = (datetime.datetime.fromtimestamp(0) + - datetime.timedelta(microseconds= - int(val['us_'] - timet_offset))) - - def datetime(self): - return self._datetime - - def to_string(self): - return str(self._datetime) -pp_set.add_printer('base::Time', '^base::Time$', TimePrinter) - - -class IpcMessagePrinter(Printer): - def header(self): - return self.val['header_'].cast( - gdb.lookup_type('IPC::Message::Header').pointer()) - - def to_string(self): - message_type = self.header()['type'] - return '%s of kind %s line %s' % ( - self.val.dynamic_type, - (message_type >> 16).cast(gdb.lookup_type('IPCMessageStart')), - message_type & 0xffff) - - def children(self): - yield ('header_', self.header().dereference()) - yield ('capacity_', self.val['capacity_']) - yield ('variable_buffer_offset_', self.val['variable_buffer_offset_']) - for field in self.val.type.fields(): - if field.is_base_class: - continue - yield (field.name, self.val[field.name]) -pp_set.add_printer('IPC::Message', '^IPC::Message$', IpcMessagePrinter) - - -class NotificationRegistrarPrinter(Printer): - def to_string(self): - try: - registrations = self.val['registered_'] - vector_finish = registrations['_M_impl']['_M_finish'] - vector_start = registrations['_M_impl']['_M_start'] - if vector_start == vector_finish: - return 'Not watching notifications' - if vector_start.dereference().type.sizeof == 0: - # Incomplete type: b/8242773 - return 'Watching some notifications' - return ('Watching %s notifications; ' - 'print %s->registered_ for details') % ( - int(vector_finish - vector_start), - typed_ptr(self.val.address)) - except gdb.error: - return 'NotificationRegistrar' -pp_set.add_printer('content::NotificationRegistrar', - '^content::NotificationRegistrar$', - NotificationRegistrarPrinter) - - -class SiteInstanceImplPrinter(object): - def __init__(self, val): - self.val = val.cast(val.dynamic_type) - - def to_string(self): - return 'SiteInstanceImpl@%s for %s' % ( - self.val.address, self.val['site_']) - - def children(self): - yield ('id_', self.val['id_']) - yield ('has_site_', self.val['has_site_']) - if self.val['browsing_instance_']['ptr_']: - yield ('browsing_instance_', self.val['browsing_instance_']['ptr_']) - if self.val['process_']: - yield ('process_', typed_ptr(self.val['process_'])) - if self.val['render_process_host_factory_']: - yield ('render_process_host_factory_', - self.val['render_process_host_factory_']) -pp_set.add_printer('content::SiteInstanceImpl', '^content::SiteInstanceImpl$', - SiteInstanceImplPrinter) - - -class RenderProcessHostImplPrinter(object): - def __init__(self, val): - self.val = val.cast(val.dynamic_type) - - def to_string(self): - pid = '' - try: - child_process_launcher_ptr = ( - self.val['child_process_launcher_']['impl_']['data_']['ptr']) - if child_process_launcher_ptr: - context = (child_process_launcher_ptr['context_']['ptr_']) - if context: - pid = ' PID %s' % str(context['process_']['process_']) - except gdb.error: - # The definition of the Context type may not be available. - # b/8242773 - pass - return 'RenderProcessHostImpl@%s%s' % (self.val.address, pid) - - def children(self): - yield ('id_', self.val['id_']) - yield ('render_widget_hosts_', - self.val['render_widget_hosts_']['data_']) - yield ('fast_shutdown_started_', self.val['fast_shutdown_started_']) - yield ('deleting_soon_', self.val['deleting_soon_']) - yield ('pending_views_', self.val['pending_views_']) - yield ('visible_widgets_', self.val['visible_widgets_']) - yield ('backgrounded_', self.val['backgrounded_']) - yield ('widget_helper_', self.val['widget_helper_']) - yield ('is_initialized_', self.val['is_initialized_']) - yield ('browser_context_', typed_ptr(self.val['browser_context_'])) - yield ('sudden_termination_allowed_', - self.val['sudden_termination_allowed_']) - yield ('ignore_input_events_', self.val['ignore_input_events_']) - yield ('is_guest_', self.val['is_guest_']) -pp_set.add_printer('content::RenderProcessHostImpl', - '^content::RenderProcessHostImpl$', - RenderProcessHostImplPrinter) - - -gdb.printing.register_pretty_printer(gdb, pp_set, replace=_DEBUGGING) diff --git a/tools/gen_keyboard_overlay_data/gen_keyboard_overlay_data.py b/tools/gen_keyboard_overlay_data/gen_keyboard_overlay_data.py deleted file mode 100755 index 8531241f28..0000000000 --- a/tools/gen_keyboard_overlay_data/gen_keyboard_overlay_data.py +++ /dev/null @@ -1,529 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Generate keyboard layout and hotkey data for the keyboard overlay. - -This script fetches data from the keyboard layout and hotkey data spreadsheet, -and output the data depending on the option. - - --cc: Rewrites a part of C++ code in - chrome/browser/chromeos/webui/keyboard_overlay_ui.cc - - --grd: Rewrites a part of grd messages in - chrome/app/generated_resources.grd - - --js: Rewrites the entire JavaScript code in - chrome/browser/resources/keyboard_overlay/keyboard_overlay_data.js - -These options can be specified at the same time. - -e.g. -python gen_keyboard_overlay_data.py --cc --grd --js - -The output directory of the generated files can be changed with --outdir. - -e.g. (This will generate tmp/keyboard_overlay.js) -python gen_keyboard_overlay_data.py --outdir=tmp --js -""" - -import cStringIO -import datetime -import gdata.spreadsheet.service -import getpass -import json -import optparse -import os -import re -import sys - -MODIFIER_SHIFT = 1 << 0 -MODIFIER_CTRL = 1 << 1 -MODIFIER_ALT = 1 << 2 - -KEYBOARD_GLYPH_SPREADSHEET_KEY = '0Ao3KldW9piwEdExLbGR6TmZ2RU9aUjFCMmVxWkVqVmc' -HOTKEY_SPREADSHEET_KEY = '0AqzoqbAMLyEPdE1RQXdodk1qVkFyTWtQbUxROVM1cXc' -CC_OUTDIR = 'chrome/browser/ui/webui/chromeos' -CC_FILENAME = 'keyboard_overlay_ui.cc' -GRD_OUTDIR = 'chrome/app' -GRD_FILENAME = 'chromeos_strings.grdp' -JS_OUTDIR = 'chrome/browser/resources/chromeos' -JS_FILENAME = 'keyboard_overlay_data.js' -CC_START = r'IDS_KEYBOARD_OVERLAY_INSTRUCTIONS_HIDE },' -CC_END = r'};' -GRD_START = r' ' -GRD_END = r' ' - -LABEL_MAP = { - 'glyph_arrow_down': 'down', - 'glyph_arrow_left': 'left', - 'glyph_arrow_right': 'right', - 'glyph_arrow_up': 'up', - 'glyph_back': 'back', - 'glyph_backspace': 'backspace', - 'glyph_brightness_down': 'bright down', - 'glyph_brightness_up': 'bright up', - 'glyph_enter': 'enter', - 'glyph_forward': 'forward', - 'glyph_fullscreen': 'full screen', - # Kana/Eisu key on Japanese keyboard - 'glyph_ime': u'\u304b\u306a\u0020\u002f\u0020\u82f1\u6570', - 'glyph_lock': 'lock', - 'glyph_overview': 'switch window', - 'glyph_power': 'power', - 'glyph_right': 'right', - 'glyph_reload': 'reload', - 'glyph_search': 'search', - 'glyph_shift': 'shift', - 'glyph_tab': 'tab', - 'glyph_tools': 'tools', - 'glyph_volume_down': 'vol. down', - 'glyph_volume_mute': 'mute', - 'glyph_volume_up': 'vol. up', -}; - -INPUT_METHOD_ID_TO_OVERLAY_ID = { - 'm17n:ar:kbd': 'ar', - 'm17n:fa:isiri': 'ar', - 'm17n:hi:itrans': 'hi', - 'm17n:th:kesmanee': 'th', - 'm17n:th:pattachote': 'th', - 'm17n:th:tis820': 'th', - 'm17n:vi:tcvn': 'vi', - 'm17n:vi:telex': 'vi', - 'm17n:vi:viqr': 'vi', - 'm17n:vi:vni': 'vi', - 'm17n:zh:cangjie': 'zh_TW', - 'm17n:zh:quick': 'zh_TW', - 'mozc': 'en_US', - 'mozc-chewing': 'zh_TW', - 'mozc-dv': 'en_US_dvorak', - 'mozc-hangul': 'ko', - 'mozc-jp': 'ja', - 'pinyin': 'zh_CN', - 'pinyin-dv': 'en_US_dvorak', - 'xkb:be::fra': 'fr', - 'xkb:be::ger': 'de', - 'xkb:be::nld': 'nl', - 'xkb:bg::bul': 'bg', - 'xkb:bg:phonetic:bul': 'bg', - 'xkb:br::por': 'pt_BR', - 'xkb:ca::fra': 'fr_CA', - 'xkb:ca:eng:eng': 'ca', - 'xkb:ch::ger': 'de', - 'xkb:ch:fr:fra': 'fr', - 'xkb:cz::cze': 'cs', - 'xkb:de::ger': 'de', - 'xkb:de:neo:ger': 'de_neo', - 'xkb:dk::dan': 'da', - 'xkb:ee::est': 'et', - 'xkb:es::spa': 'es', - 'xkb:es:cat:cat': 'ca', - 'xkb:fi::fin': 'fi', - 'xkb:fr::fra': 'fr', - 'xkb:gb:dvorak:eng': 'en_GB_dvorak', - 'xkb:gb:extd:eng': 'en_GB', - 'xkb:gr::gre': 'el', - 'xkb:hr::scr': 'hr', - 'xkb:hu::hun': 'hu', - 'xkb:il::heb': 'iw', - 'xkb:it::ita': 'it', - 'xkb:jp::jpn': 'ja', - 'xkb:kr:kr104:kor': 'ko', - 'xkb:latam::spa': 'es_419', - 'xkb:lt::lit': 'lt', - 'xkb:lv:apostrophe:lav': 'lv', - 'xkb:no::nob': 'no', - 'xkb:pl::pol': 'pl', - 'xkb:pt::por': 'pt_PT', - 'xkb:ro::rum': 'ro', - 'xkb:rs::srp': 'sr', - 'xkb:ru::rus': 'ru', - 'xkb:ru:phonetic:rus': 'ru', - 'xkb:se::swe': 'sv', - 'xkb:si::slv': 'sl', - 'xkb:sk::slo': 'sk', - 'xkb:tr::tur': 'tr', - 'xkb:ua::ukr': 'uk', - 'xkb:us::eng': 'en_US', - 'xkb:us:altgr-intl:eng': 'en_US_altgr_intl', - 'xkb:us:colemak:eng': 'en_US_colemak', - 'xkb:us:dvorak:eng': 'en_US_dvorak', - 'xkb:us:intl:eng': 'en_US_intl', - 'zinnia-japanese': 'ja', -} - -# The file was first generated in 2012 and we have a policy of not updating -# copyright dates. -COPYRIGHT_HEADER=\ -"""// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This is a generated file but may contain local modifications. See -// src/tools/gen_keyboard_overlay_data/gen_keyboard_overlay_data.py --help -""" - -# A snippet for grd file -GRD_SNIPPET_TEMPLATE=""" - %s - -""" - -# A snippet for C++ file -CC_SNIPPET_TEMPLATE=""" { "%s", %s }, -""" - - -def SplitBehavior(behavior): - """Splits the behavior to compose a message or i18n-content value. - - Examples: - 'Activate last tab' => ['Activate', 'last', 'tab'] - 'Close tab' => ['Close', 'tab'] - """ - return [x for x in re.split('[ ()"-.,]', behavior) if len(x) > 0] - - -def ToMessageName(behavior): - """Composes a message name for grd file. - - Examples: - 'Activate last tab' => IDS_KEYBOARD_OVERLAY_ACTIVATE_LAST_TAB - 'Close tab' => IDS_KEYBOARD_OVERLAY_CLOSE_TAB - """ - segments = [segment.upper() for segment in SplitBehavior(behavior)] - return 'IDS_KEYBOARD_OVERLAY_' + ('_'.join(segments)) - - -def ToMessageDesc(description): - """Composes a message description for grd file.""" - message_desc = 'The text in the keyboard overlay to explain the shortcut' - if description: - message_desc = '%s (%s).' % (message_desc, description) - else: - message_desc += '.' - return message_desc - - -def Toi18nContent(behavior): - """Composes a i18n-content value for HTML/JavaScript files. - - Examples: - 'Activate last tab' => keyboardOverlayActivateLastTab - 'Close tab' => keyboardOverlayCloseTab - """ - segments = [segment.lower() for segment in SplitBehavior(behavior)] - result = 'keyboardOverlay' - for segment in segments: - result += segment[0].upper() + segment[1:] - return result - - -def ToKeys(hotkey): - """Converts the action value to shortcut keys used from JavaScript. - - Examples: - 'Ctrl - 9' => '9<>CTRL' - 'Ctrl - Shift - Tab' => 'tab<>CTRL<>SHIFT' - """ - values = hotkey.split(' - ') - modifiers = sorted(value.upper() for value in values - if value in ['Shift', 'Ctrl', 'Alt', 'Search']) - keycode = [value.lower() for value in values - if value not in ['Shift', 'Ctrl', 'Alt', 'Search']] - # The keys which are highlighted even without modifier keys. - base_keys = ['backspace', 'power'] - if not modifiers and (keycode and keycode[0] not in base_keys): - return None - return '<>'.join(keycode + modifiers) - - -def ParseOptions(): - """Parses the input arguemnts and returns options.""" - # default_username = os.getusername() + '@google.com'; - default_username = '%s@google.com' % os.environ.get('USER') - parser = optparse.OptionParser() - parser.add_option('--key', dest='key', - help='The key of the spreadsheet (required).') - parser.add_option('--username', dest='username', - default=default_username, - help='Your user name (default: %s).' % default_username) - parser.add_option('--password', dest='password', - help='Your password.') - parser.add_option('--account_type', default='GOOGLE', dest='account_type', - help='Account type used for gdata login (default: GOOGLE)') - parser.add_option('--js', dest='js', default=False, action='store_true', - help='Output js file.') - parser.add_option('--grd', dest='grd', default=False, action='store_true', - help='Output resource file.') - parser.add_option('--cc', dest='cc', default=False, action='store_true', - help='Output cc file.') - parser.add_option('--outdir', dest='outdir', default=None, - help='Specify the directory files are generated.') - (options, unused_args) = parser.parse_args() - - if not options.username.endswith('google.com'): - print 'google.com account is necessary to use this script.' - sys.exit(-1) - - if (not (options.js or options.grd or options.cc)): - print 'Either --js, --grd, or --cc needs to be specified.' - sys.exit(-1) - - # Get the password from the terminal, if needed. - if not options.password: - options.password = getpass.getpass( - 'Application specific password for %s: ' % options.username) - return options - - -def InitClient(options): - """Initializes the spreadsheet client.""" - client = gdata.spreadsheet.service.SpreadsheetsService() - client.email = options.username - client.password = options.password - client.source = 'Spread Sheet' - client.account_type = options.account_type - print 'Logging in as %s (%s)' % (client.email, client.account_type) - client.ProgrammaticLogin() - return client - - -def PrintDiffs(message, lhs, rhs): - """Prints the differences between |lhs| and |rhs|.""" - dif = set(lhs).difference(rhs) - if dif: - print message, ', '.join(dif) - - -def FetchSpreadsheetFeeds(client, key, sheets, cols): - """Fetch feeds from the spreadsheet. - - Args: - client: A spreadsheet client to be used for fetching data. - key: A key string of the spreadsheet to be fetched. - sheets: A list of the sheet names to read data from. - cols: A list of columns to read data from. - """ - worksheets_feed = client.GetWorksheetsFeed(key) - print 'Fetching data from the worksheet: %s' % worksheets_feed.title.text - worksheets_data = {} - titles = [] - for entry in worksheets_feed.entry: - worksheet_id = entry.id.text.split('/')[-1] - list_feed = client.GetListFeed(key, worksheet_id) - list_data = [] - # Hack to deal with sheet names like 'sv (Copy of fl)' - title = list_feed.title.text.split('(')[0].strip() - titles.append(title) - if title not in sheets: - continue - print 'Reading data from the sheet: %s' % list_feed.title.text - for i, entry in enumerate(list_feed.entry): - line_data = {} - for k in entry.custom: - if (k not in cols) or (not entry.custom[k].text): - continue - line_data[k] = entry.custom[k].text - list_data.append(line_data) - worksheets_data[title] = list_data - PrintDiffs('Exist only on the spreadsheet: ', titles, sheets) - PrintDiffs('Specified but do not exist on the spreadsheet: ', sheets, titles) - return worksheets_data - - -def FetchKeyboardGlyphData(client): - """Fetches the keyboard glyph data from the spreadsheet.""" - glyph_cols = ['scancode', 'p0', 'p1', 'p2', 'p3', 'p4', 'p5', 'p6', 'p7', - 'p8', 'p9', 'label', 'format', 'notes'] - keyboard_glyph_data = FetchSpreadsheetFeeds( - client, KEYBOARD_GLYPH_SPREADSHEET_KEY, - INPUT_METHOD_ID_TO_OVERLAY_ID.values(), glyph_cols) - ret = {} - for lang in keyboard_glyph_data: - ret[lang] = {} - keys = {} - for line in keyboard_glyph_data[lang]: - scancode = line.get('scancode') - if (not scancode) and line.get('notes'): - ret[lang]['layoutName'] = line['notes'] - continue - del line['scancode'] - if 'notes' in line: - del line['notes'] - if 'label' in line: - line['label'] = LABEL_MAP.get(line['label'], line['label']) - keys[scancode] = line - # Add a label to space key - if '39' not in keys: - keys['39'] = {'label': 'space'} - ret[lang]['keys'] = keys - return ret - - -def FetchLayoutsData(client): - """Fetches the keyboard glyph data from the spreadsheet.""" - layout_names = ['U_layout', 'J_layout', 'E_layout', 'B_layout'] - cols = ['scancode', 'x', 'y', 'w', 'h'] - layouts = FetchSpreadsheetFeeds(client, KEYBOARD_GLYPH_SPREADSHEET_KEY, - layout_names, cols) - ret = {} - for layout_name, layout in layouts.items(): - ret[layout_name[0]] = [] - for row in layout: - line = [] - for col in cols: - value = row.get(col) - if not value: - line.append('') - else: - if col != 'scancode': - value = float(value) - line.append(value) - ret[layout_name[0]].append(line) - return ret - - -def FetchHotkeyData(client): - """Fetches the hotkey data from the spreadsheet.""" - hotkey_sheet = ['Cross Platform Behaviors'] - hotkey_cols = ['behavior', 'context', 'kind', 'actionctrlctrlcmdonmac', - 'chromeos', 'descriptionfortranslation'] - hotkey_data = FetchSpreadsheetFeeds(client, HOTKEY_SPREADSHEET_KEY, - hotkey_sheet, hotkey_cols) - action_to_id = {} - id_to_behavior = {} - # (behavior, action) - result = [] - for line in hotkey_data['Cross Platform Behaviors']: - if (not line.get('chromeos')) or (line.get('kind') != 'Key'): - continue - action = ToKeys(line['actionctrlctrlcmdonmac']) - if not action: - continue - behavior = line['behavior'].strip() - description = line.get('descriptionfortranslation') - result.append((behavior, action, description)) - return result - - -def UniqueBehaviors(hotkey_data): - """Retrieves a sorted list of unique behaviors from |hotkey_data|.""" - return sorted(set((behavior, description) for (behavior, _, description) - in hotkey_data), - cmp=lambda x, y: cmp(ToMessageName(x[0]), ToMessageName(y[0]))) - - -def GetPath(path_from_src): - """Returns the absolute path of the specified path.""" - path = os.path.join(os.path.dirname(__file__), '../..', path_from_src) - if not os.path.isfile(path): - print 'WARNING: %s does not exist. Maybe moved or renamed?' % path - return path - - -def OutputFile(outpath, snippet): - """Output the snippet into the specified path.""" - out = file(outpath, 'w') - out.write(COPYRIGHT_HEADER + '\n') - out.write(snippet) - print 'Output ' + os.path.normpath(outpath) - - -def RewriteFile(start, end, original_dir, original_filename, snippet, - outdir=None): - """Replaces a part of the specified file with snippet and outputs it.""" - original_path = GetPath(os.path.join(original_dir, original_filename)) - original = file(original_path, 'r') - original_content = original.read() - original.close() - if outdir: - outpath = os.path.join(outdir, original_filename) - else: - outpath = original_path - out = file(outpath, 'w') - rx = re.compile(r'%s\n.*?%s\n' % (re.escape(start), re.escape(end)), - re.DOTALL) - new_content = re.sub(rx, '%s\n%s%s\n' % (start, snippet, end), - original_content) - out.write(new_content) - out.close() - print 'Output ' + os.path.normpath(outpath) - - -def OutputJson(keyboard_glyph_data, hotkey_data, layouts, var_name, outdir): - """Outputs the keyboard overlay data as a JSON file.""" - action_to_id = {} - for (behavior, action, _) in hotkey_data: - i18nContent = Toi18nContent(behavior) - action_to_id[action] = i18nContent - data = {'keyboardGlyph': keyboard_glyph_data, - 'shortcut': action_to_id, - 'layouts': layouts, - 'inputMethodIdToOverlayId': INPUT_METHOD_ID_TO_OVERLAY_ID} - - if not outdir: - outdir = JS_OUTDIR - outpath = GetPath(os.path.join(outdir, JS_FILENAME)) - json_data = json.dumps(data, sort_keys=True, indent=2) - # Remove redundant spaces after ',' - json_data = json_data.replace(', \n', ',\n') - # Replace double quotes with single quotes to avoid lint warnings. - json_data = json_data.replace('\"', '\'') - snippet = 'var %s = %s;\n' % (var_name, json_data) - OutputFile(outpath, snippet) - - -def OutputGrd(hotkey_data, outdir): - """Outputs a part of messages in the grd file.""" - snippet = cStringIO.StringIO() - for (behavior, description) in UniqueBehaviors(hotkey_data): - # Do not generate message for 'Show wrench menu'. It is handled manually - # based on branding. - if behavior == 'Show wrench menu': - continue - snippet.write(GRD_SNIPPET_TEMPLATE % - (ToMessageName(behavior), ToMessageDesc(description), - behavior)) - - RewriteFile(GRD_START, GRD_END, GRD_OUTDIR, GRD_FILENAME, snippet.getvalue(), - outdir) - - -def OutputCC(hotkey_data, outdir): - """Outputs a part of code in the C++ file.""" - snippet = cStringIO.StringIO() - for (behavior, _) in UniqueBehaviors(hotkey_data): - message_name = ToMessageName(behavior) - output = CC_SNIPPET_TEMPLATE % (Toi18nContent(behavior), message_name) - # Break the line if the line is longer than 80 characters - if len(output) > 80: - output = output.replace(' ' + message_name, '\n %s' % message_name) - snippet.write(output) - - RewriteFile(CC_START, CC_END, CC_OUTDIR, CC_FILENAME, snippet.getvalue(), - outdir) - - -def main(): - options = ParseOptions() - client = InitClient(options) - hotkey_data = FetchHotkeyData(client) - - if options.js: - keyboard_glyph_data = FetchKeyboardGlyphData(client) - - if options.js: - layouts = FetchLayoutsData(client) - OutputJson(keyboard_glyph_data, hotkey_data, layouts, 'keyboardOverlayData', - options.outdir) - if options.grd: - OutputGrd(hotkey_data, options.outdir) - if options.cc: - OutputCC(hotkey_data, options.outdir) - - -if __name__ == '__main__': - main() diff --git a/tools/generate_library_loader/generate_library_loader.py b/tools/generate_library_loader/generate_library_loader.py deleted file mode 100755 index 866e005547..0000000000 --- a/tools/generate_library_loader/generate_library_loader.py +++ /dev/null @@ -1,256 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -""" -Creates a library loader (a header and implementation file), -which is a wrapper for dlopen or direct linking with given library. - -The loader makes it possible to have the same client code for both cases, -and also makes it easier to write code using dlopen (and also provides -a standard way to do so, and limits the ugliness just to generated files). - -For more info refer to http://crbug.com/162733 . -""" - - -import optparse -import os.path -import re -import sys - - -HEADER_TEMPLATE = """// This is generated file. Do not modify directly. -// Path to the code generator: %(generator_path)s . - -#ifndef %(unique_prefix)s -#define %(unique_prefix)s - -%(wrapped_header_include)s - -#include - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#if defined(%(unique_prefix)s_DLOPEN) -#include "base/native_library.h" -#endif - -class %(class_name)s { - public: - %(class_name)s(); - ~%(class_name)s(); - - bool Load(const std::string& library_name) WARN_UNUSED_RESULT; - - bool loaded() const { return loaded_; } - -%(member_decls)s - - private: - void CleanUp(bool unload); - -#if defined(%(unique_prefix)s_DLOPEN) - base::NativeLibrary library_; -#endif - - bool loaded_; - - DISALLOW_COPY_AND_ASSIGN(%(class_name)s); -}; - -#endif // %(unique_prefix)s -""" - - -HEADER_MEMBER_TEMPLATE = """ typeof(&::%(function_name)s) %(function_name)s; -""" - - -IMPL_TEMPLATE = """// This is generated file. Do not modify directly. -// Path to the code generator: %(generator_path)s . - -#include "%(generated_header_name)s" - -// Put these sanity checks here so that they fire at most once -// (to avoid cluttering the build output). -#if !defined(%(unique_prefix)s_DLOPEN) && !defined(%(unique_prefix)s_DT_NEEDED) -#error neither %(unique_prefix)s_DLOPEN nor %(unique_prefix)s_DT_NEEDED defined -#endif -#if defined(%(unique_prefix)s_DLOPEN) && defined(%(unique_prefix)s_DT_NEEDED) -#error both %(unique_prefix)s_DLOPEN and %(unique_prefix)s_DT_NEEDED defined -#endif - -#include "base/files/file_path.h" -#include "base/logging.h" - -%(class_name)s::%(class_name)s() : loaded_(false) { -} - -%(class_name)s::~%(class_name)s() { - CleanUp(loaded_); -} - -bool %(class_name)s::Load(const std::string& library_name) { - if (loaded_) { - NOTREACHED(); - return false; - } - -#if defined(%(unique_prefix)s_DLOPEN) - library_ = base::LoadNativeLibrary(base::FilePath(library_name), NULL); - if (!library_) - return false; -#endif - -%(member_init)s - - loaded_ = true; - return true; -} - -void %(class_name)s::CleanUp(bool unload) { -#if defined(%(unique_prefix)s_DLOPEN) - if (unload) { - base::UnloadNativeLibrary(library_); - library_ = NULL; - } -#endif - loaded_ = false; -%(member_cleanup)s -} -""" - -IMPL_MEMBER_INIT_TEMPLATE = """ -#if defined(%(unique_prefix)s_DLOPEN) - %(function_name)s = - reinterpret_cast%(function_name)s)>( - base::GetFunctionPointerFromNativeLibrary( - library_, "%(function_name)s")); -#endif -#if defined(%(unique_prefix)s_DT_NEEDED) - %(function_name)s = &::%(function_name)s; -#endif - if (!%(function_name)s) { - CleanUp(true); - return false; - } -""" - -IMPL_MEMBER_CLEANUP_TEMPLATE = """ %(function_name)s = NULL; -""" - -def main(): - parser = optparse.OptionParser() - parser.add_option('--name') - parser.add_option('--output-cc') - parser.add_option('--output-h') - parser.add_option('--header') - - parser.add_option('--bundled-header') - parser.add_option('--use-extern-c', action='store_true', default=False) - parser.add_option('--link-directly', type=int, default=0) - - options, args = parser.parse_args() - - if not options.name: - parser.error('Missing --name parameter') - if not options.output_cc: - parser.error('Missing --output-cc parameter') - if not options.output_h: - parser.error('Missing --output-h parameter') - if not options.header: - parser.error('Missing --header paramater') - if not args: - parser.error('No function names specified') - - # Make sure we are always dealing with paths relative to source tree root - # to avoid issues caused by different relative path roots. - source_tree_root = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..', '..')) - options.output_cc = os.path.relpath(options.output_cc, source_tree_root) - options.output_h = os.path.relpath(options.output_h, source_tree_root) - - # Create a unique prefix, e.g. for header guards. - # Stick a known string at the beginning to ensure this doesn't begin - # with an underscore, which is reserved for the C++ implementation. - unique_prefix = ('LIBRARY_LOADER_' + - re.sub(r'[\W]', '_', options.output_h).upper()) - - member_decls = [] - member_init = [] - member_cleanup = [] - for fn in args: - member_decls.append(HEADER_MEMBER_TEMPLATE % { - 'function_name': fn, - 'unique_prefix': unique_prefix - }) - member_init.append(IMPL_MEMBER_INIT_TEMPLATE % { - 'function_name': fn, - 'unique_prefix': unique_prefix - }) - member_cleanup.append(IMPL_MEMBER_CLEANUP_TEMPLATE % { - 'function_name': fn, - 'unique_prefix': unique_prefix - }) - - header = options.header - if options.link_directly == 0 and options.bundled_header: - header = options.bundled_header - wrapped_header_include = '#include %s\n' % header - - # Some libraries (e.g. libpci) have headers that cannot be included - # without extern "C", otherwise they cause the link to fail. - # TODO(phajdan.jr): This is a workaround for broken headers. Remove it. - if options.use_extern_c: - wrapped_header_include = 'extern "C" {\n%s\n}\n' % wrapped_header_include - - # It seems cleaner just to have a single #define here and #ifdefs in bunch - # of places, rather than having a different set of templates, duplicating - # or complicating more code. - if options.link_directly == 0: - wrapped_header_include += '#define %s_DLOPEN\n' % unique_prefix - elif options.link_directly == 1: - wrapped_header_include += '#define %s_DT_NEEDED\n' % unique_prefix - else: - parser.error('Invalid value for --link-directly. Should be 0 or 1.') - - # Make it easier for people to find the code generator just in case. - # Doing it this way is more maintainable, because it's going to work - # even if file gets moved without updating the contents. - generator_path = os.path.relpath(__file__, source_tree_root) - - header_contents = HEADER_TEMPLATE % { - 'generator_path': generator_path, - 'unique_prefix': unique_prefix, - 'wrapped_header_include': wrapped_header_include, - 'class_name': options.name, - 'member_decls': ''.join(member_decls), - } - - impl_contents = IMPL_TEMPLATE % { - 'generator_path': generator_path, - 'unique_prefix': unique_prefix, - 'generated_header_name': options.output_h, - 'class_name': options.name, - 'member_init': ''.join(member_init), - 'member_cleanup': ''.join(member_cleanup), - } - - header_file = open(os.path.join(source_tree_root, options.output_h), 'w') - try: - header_file.write(header_contents) - finally: - header_file.close() - - impl_file = open(os.path.join(source_tree_root, options.output_cc), 'w') - try: - impl_file.write(impl_contents) - finally: - impl_file.close() - - return 0 - -if __name__ == '__main__': - sys.exit(main()) diff --git a/tools/generate_shim_headers/generate_shim_headers.py b/tools/generate_shim_headers/generate_shim_headers.py deleted file mode 100755 index 81c531b2e6..0000000000 --- a/tools/generate_shim_headers/generate_shim_headers.py +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -""" -Generates shim headers that mirror the directory structure of bundled headers, -but just forward to the system ones. - -This allows seamless compilation against system headers with no changes -to our source code. -""" - - -import optparse -import os.path -import sys - - -SHIM_TEMPLATE = """ -#if defined(OFFICIAL_BUILD) -#error shim headers must not be used in official builds! -#endif -""" - - -def GeneratorMain(argv): - parser = optparse.OptionParser() - parser.add_option('--headers-root', action='append') - parser.add_option('--define', action='append') - parser.add_option('--output-directory') - parser.add_option('--prefix', default='') - parser.add_option('--use-include-next', action='store_true') - parser.add_option('--outputs', action='store_true') - parser.add_option('--generate', action='store_true') - - options, args = parser.parse_args(argv) - - if not options.headers_root: - parser.error('Missing --headers-root parameter.') - if not options.output_directory: - parser.error('Missing --output-directory parameter.') - if not args: - parser.error('Missing arguments - header file names.') - - source_tree_root = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..', '..')) - - for root in options.headers_root: - target_directory = os.path.join( - options.output_directory, - os.path.relpath(root, source_tree_root)) - if options.generate and not os.path.exists(target_directory): - os.makedirs(target_directory) - - for header_spec in args: - if ';' in header_spec: - (header_filename, - include_before, - include_after) = header_spec.split(';', 2) - else: - header_filename = header_spec - include_before = '' - include_after = '' - if options.outputs: - yield os.path.join(target_directory, header_filename) - if options.generate: - with open(os.path.join(target_directory, header_filename), 'w') as f: - f.write(SHIM_TEMPLATE) - - if options.define: - for define in options.define: - key, value = define.split('=', 1) - # This non-standard push_macro extension is supported - # by compilers we support (GCC, clang). - f.write('#pragma push_macro("%s")\n' % key) - f.write('#undef %s\n' % key) - f.write('#define %s %s\n' % (key, value)) - - if include_before: - for header in include_before.split(':'): - f.write('#include %s\n' % header) - - include_target = options.prefix + header_filename - if options.use_include_next: - f.write('#include_next <%s>\n' % include_target) - else: - f.write('#include <%s>\n' % include_target) - - if include_after: - for header in include_after.split(':'): - f.write('#include %s\n' % header) - - if options.define: - for define in options.define: - key, value = define.split('=', 1) - # This non-standard pop_macro extension is supported - # by compilers we support (GCC, clang). - f.write('#pragma pop_macro("%s")\n' % key) - - -def DoMain(argv): - return '\n'.join(GeneratorMain(argv)) - - -if __name__ == '__main__': - DoMain(sys.argv[1:]) diff --git a/tools/generate_stubs/generate_stubs.py b/tools/generate_stubs/generate_stubs.py deleted file mode 100755 index 27f8d5a05d..0000000000 --- a/tools/generate_stubs/generate_stubs.py +++ /dev/null @@ -1,1131 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Creates windows and posix stub files for a given set of signatures. - -For libraries that need to be loaded outside of the standard executable startup -path mechanism, stub files need to be generated for the wanted functions. In -windows, this is done via "def" files and the delay load mechanism. On a posix -system, a set of stub functions need to be generated that dispatch to functions -found via dlsym. - -This script takes a set of files, where each file is a list of C-style -signatures (one signature per line). The output is either a windows def file, -or a header + implementation file of stubs suitable for use in a posix system. - -This script also handles varidiac functions, e.g. -void printf(const char* s, ...); - -TODO(hclam): Fix the situation for varidiac functions. -Stub for the above function will be generated and inside the stub function it -is translated to: -void printf(const char* s, ...) { - printf_ptr(s, (void*)arg1); -} - -Only one argument from the varidiac arguments is used and it will be used as -type void*. -""" - -__author__ = 'ajwong@chromium.org (Albert J. Wong)' - -import optparse -import os -import re -import string -import subprocess -import sys - - -class Error(Exception): - pass - - -class BadSignatureError(Error): - pass - - -class SubprocessError(Error): - def __init__(self, message, error_code): - Error.__init__(self) - self.message = message - self.error_code = error_code - - def __str__(self): - return 'Failed with code %s: %s' % (self.message, repr(self.error_code)) - - -# Regular expression used to parse function signatures in the input files. -# The regex is built around identifying the "identifier" for the function name. -# We consider the identifier to be the string that follows these constraints: -# -# 1) Starts with [_a-ZA-Z] (C++ spec 2.10). -# 2) Continues with [_a-ZA-Z0-9] (C++ spec 2.10). -# 3) Preceeds an opening parenthesis by 0 or more whitespace chars. -# -# From that, all preceeding characters are considered the return value. -# Trailing characters should have a substring matching the form (.*). That -# is considered the arguments. -SIGNATURE_REGEX = re.compile('(?P.+?)' - '(?P[_a-zA-Z][_a-zA-Z0-9]+)\s*' - '\((?P.*?)\)') - -# Used for generating C++ identifiers. -INVALID_C_IDENT_CHARS = re.compile('[^_a-zA-Z0-9]') - -# Constants defning the supported file types options. -FILE_TYPE_WIN_X86 = 'windows_lib' -FILE_TYPE_WIN_X64 = 'windows_lib_x64' -FILE_TYPE_POSIX_STUB = 'posix_stubs' -FILE_TYPE_WIN_DEF = 'windows_def' - -# Template for generating a stub function definition. Includes a forward -# declaration marking the symbol as weak. This template takes the following -# named parameters. -# return_type: The return type. -# name: The name of the function. -# params: The parameters to the function. -# return_prefix: 'return ' if this function is not void. '' otherwise. -# arg_list: The arguments used to call the stub function. -STUB_FUNCTION_DEFINITION = ( - """extern %(return_type)s %(name)s(%(params)s) __attribute__((weak)); -%(return_type)s %(name)s(%(params)s) { - %(return_prefix)s%(name)s_ptr(%(arg_list)s); -}""") - -# Template for generating a variadic stub function definition with return -# value. -# Includes a forward declaration marking the symbol as weak. -# This template takes the following named parameters. -# return_type: The return type. -# name: The name of the function. -# params: The parameters to the function. -# arg_list: The arguments used to call the stub function without the -# variadic argument. -# last_named_arg: Name of the last named argument before the variadic -# argument. -VARIADIC_STUB_FUNCTION_DEFINITION = ( - """extern %(return_type)s %(name)s(%(params)s) __attribute__((weak)); -%(return_type)s %(name)s(%(params)s) { - va_list args___; - va_start(args___, %(last_named_arg)s); - %(return_type)s ret___ = %(name)s_ptr(%(arg_list)s, va_arg(args___, void*)); - va_end(args___); - return ret___; -}""") - -# Template for generating a variadic stub function definition without -# return value. -# Includes a forward declaration marking the symbol as weak. -# This template takes the following named parameters. -# name: The name of the function. -# params: The parameters to the function. -# arg_list: The arguments used to call the stub function without the -# variadic argument. -# last_named_arg: Name of the last named argument before the variadic -# argument. -VOID_VARIADIC_STUB_FUNCTION_DEFINITION = ( - """extern void %(name)s(%(params)s) __attribute__((weak)); -void %(name)s(%(params)s) { - va_list args___; - va_start(args___, %(last_named_arg)s); - %(name)s_ptr(%(arg_list)s, va_arg(args___, void*)); - va_end(args___); -}""") - -# Template for the preamble for the stub header file with the header guards, -# standard set of includes, and namespace opener. This template takes the -# following named parameters: -# guard_name: The macro to use as the header guard. -# namespace: The namespace for the stub functions. -STUB_HEADER_PREAMBLE = """// This is generated file. Do not modify directly. - -#ifndef %(guard_name)s -#define %(guard_name)s - -#include -#include -#include - -#include "base/logging.h" - -namespace %(namespace)s { -""" - -# Template for the end of the stub header. This closes the namespace and the -# header guards. This template takes the following named parameters: -# guard_name: The macro to use as the header guard. -# namespace: The namespace for the stub functions. -STUB_HEADER_CLOSER = """} // namespace %(namespace)s - -#endif // %(guard_name)s -""" - -# The standard includes needed for the stub implementation file. Takes one -# string substition with the path to the associated stub header file. -IMPLEMENTATION_PREAMBLE = """// This is generated file. Do not modify directly. - -#include "%s" - -#include // For NULL. -#include // For dysym, dlopen. - -#include -#include -""" - -# The start and end templates for the enum definitions used by the Umbrella -# initializer. -UMBRELLA_ENUM_START = """// Enum and typedef for umbrella initializer. -enum StubModules { -""" -UMBRELLA_ENUM_END = """ kNumStubModules -}; - -""" - -# Start and end of the extern "C" section for the implementation contents. -IMPLEMENTATION_CONTENTS_C_START = """extern "C" { - -""" -IMPLEMENTATION_CONTENTS_C_END = """ -} // extern "C" - - -""" - -# Templates for the start and end of a namespace. Takes one parameter, the -# namespace name. -NAMESPACE_START = """namespace %s { - -""" -NAMESPACE_END = """} // namespace %s - -""" - -# Comment to include before the section declaring all the function pointers -# used by the stub functions. -FUNCTION_POINTER_SECTION_COMMENT = ( - """// Static pointers that will hold the location of the real function -// implementations after the module has been loaded. -""") - -# Template for the module initialization check function. This template -# takes two parameteres: the function name, and the conditional used to -# verify the module's initialization. -MODULE_INITIALIZATION_CHECK_FUNCTION = ( - """// Returns true if all stubs have been properly initialized. -bool %s() { - if (%s) { - return true; - } else { - return false; - } -} - -""") - -# Template for the line that initialize the stub pointer. This template takes -# the following named parameters: -# name: The name of the function. -# return_type: The return type. -# params: The parameters to the function. -STUB_POINTER_INITIALIZER = """ %(name)s_ptr = - reinterpret_cast<%(return_type)s (*)(%(parameters)s)>( - dlsym(module, "%(name)s")); - VLOG_IF(1, !%(name)s_ptr) << "Couldn't load %(name)s, dlerror() says:\\n" - << dlerror(); -""" - -# Template for module initializer function start and end. This template takes -# one parameter which is the initializer function name. -MODULE_INITIALIZE_START = """// Initializes the module stubs. -void %s(void* module) { -""" -MODULE_INITIALIZE_END = """} - -""" - -# Template for module uninitializer function start and end. This template -# takes one parameter which is the initializer function name. -MODULE_UNINITIALIZE_START = ( - """// Uninitialize the module stubs. Reset pointers to NULL. -void %s() { -""") -MODULE_UNINITIALIZE_END = """} - -""" - - -# Open namespace and add typedef for internal data structures used by the -# umbrella initializer. -UMBRELLA_INITIALIZER_START = """namespace %s { -typedef std::map StubHandleMap; -""" - -# Function close DSOs on error and clean up dangling references. -UMBRELLA_INITIALIZER_CLEANUP_FUNCTION = ( - """static void CloseLibraries(StubHandleMap* stub_handles) { - for (StubHandleMap::const_iterator it = stub_handles->begin(); - it != stub_handles->end(); - ++it) { - dlclose(it->second); - } - - stub_handles->clear(); -} -""") - -# Function to initialize each DSO for the given paths. -UMBRELLA_INITIALIZER_INITIALIZE_FUNCTION_START = ( - """bool InitializeStubs(const StubPathMap& path_map) { - StubHandleMap opened_libraries; - for (int i = 0; i < kNumStubModules; ++i) { - StubModules cur_module = static_cast(i); - // If a module is missing, we fail. - StubPathMap::const_iterator it = path_map.find(cur_module); - if (it == path_map.end()) { - CloseLibraries(&opened_libraries); - return false; - } - - // Otherwise, attempt to dlopen the library. - const std::vector& paths = it->second; - bool module_opened = false; - for (std::vector::const_iterator dso_path = paths.begin(); - !module_opened && dso_path != paths.end(); - ++dso_path) { - void* handle = dlopen(dso_path->c_str(), RTLD_LAZY); - if (handle != NULL) { - module_opened = true; - opened_libraries[cur_module] = handle; - } else { - VLOG(1) << "dlopen(" << dso_path->c_str() << ") failed, " - << "dlerror() says:\\n" << dlerror(); - } - } - - if (!module_opened) { - CloseLibraries(&opened_libraries); - return false; - } - } -""") - -# Template to generate code to check if each module initializer correctly -# completed, and cleanup on failures. This template takes the following -# named parameters. -# conditional: The conditional expression for successful initialization. -# uninitializers: The statements needed to uninitialize the modules. -UMBRELLA_INITIALIZER_CHECK_AND_CLEANUP = ( - """ // Check that each module is initialized correctly. - // Close all previously opened libraries on failure. - if (%(conditional)s) { - %(uninitializers)s; - CloseLibraries(&opened_libraries); - return false; - } - - return true; -} -""") - -# Template for Initialize, Unininitialize, and IsInitialized functions for each -# module. This template takes the following named parameters: -# initialize: Name of the Initialize function. -# uninitialize: Name of the Uninitialize function. -# is_initialized: Name of the IsInitialized function. -MODULE_FUNCTION_PROTOTYPES = """bool %(is_initialized)s(); -void %(initialize)s(void* module); -void %(uninitialize)s(); - -""" - -# Template for umbrella initializer declaration and associated datatypes. -UMBRELLA_INITIALIZER_PROTOTYPE = ( - """typedef std::map > StubPathMap; - -// Umbrella initializer for all the modules in this stub file. -bool InitializeStubs(const StubPathMap& path_map); -""") - - -def ExtractModuleName(infile_path): - """Infers the module name from the input file path. - - The input filename is supposed to be in the form "ModuleName.sigs". - This function splits the filename from the extention on that basename of - the path and returns that as the module name. - - Args: - infile_path: String holding the path to the input file. - - Returns: - The module name as a string. - """ - basename = os.path.basename(infile_path) - - # This loop continously removes suffixes of the filename separated by a "." - # character. - while 1: - new_basename = os.path.splitext(basename)[0] - if basename == new_basename: - break - else: - basename = new_basename - return basename - - -def ParseSignatures(infile): - """Parses function signatures in the input file. - - This function parses a file of signatures into a list of dictionaries that - represent the function signatures in the input file. Each dictionary has - the following keys: - return_type: A string with the return type. - name: A string with the name of the function. - params: A list of each function parameter declaration (type + name) - - The format of the input file is one C-style function signature per line, no - trailing semicolon. Empty lines are allowed. An empty line is a line that - consists purely of whitespace. Lines that begin with a # are considered - comment lines and are ignored. - - We assume that "int foo(void)" is the same as "int foo()", which is not - true in C where "int foo()" is equivalent to "int foo(...)". Our generated - code is C++, and we do not handle varargs, so this is a case that can be - ignored for now. - - Args: - infile: File object holding a text file of function signatures. - - Returns: - A list of dictionaries, where each dictionary represents one function - signature. - - Raises: - BadSignatureError: A line could not be parsed as a signature. - """ - signatures = [] - for line in infile: - line = line.strip() - if line and line[0] != '#': - m = SIGNATURE_REGEX.match(line) - if m is None: - raise BadSignatureError('Unparsable line: %s' % line) - signatures.append( - {'return_type': m.group('return_type').strip(), - 'name': m.group('name').strip(), - 'params': [arg.strip() for arg in m.group('params').split(',')]}) - return signatures - - -def WriteWindowsDefFile(module_name, signatures, outfile): - """Writes a windows def file to the given output file object. - - The def file format is basically a list of function names. Generation is - simple. After outputting the LIBRARY and EXPORTS lines, print out each - function name, one to a line, preceeded by 2 spaces. - - Args: - module_name: The name of the module we are writing a stub for. - signatures: The list of signature hashes, as produced by ParseSignatures, - to create stubs for. - outfile: File handle to populate with definitions. - """ - outfile.write('LIBRARY %s\n' % module_name) - outfile.write('EXPORTS\n') - - for sig in signatures: - outfile.write(' %s\n' % sig['name']) - - -def QuietRun(args, filter=None, write_to=sys.stdout): - """Invoke |args| as command via subprocess.Popen, filtering lines starting - with |filter|.""" - popen = subprocess.Popen(args, stdout=subprocess.PIPE) - out, _ = popen.communicate() - for line in out.splitlines(): - if not filter or not line.startswith(filter): - write_to.write(line + '\n') - return popen.returncode - - -def CreateWindowsLib(module_name, signatures, intermediate_dir, outdir_path, - machine): - """Creates a windows library file. - - Calling this function will create a lib file in the outdir_path that exports - the signatures passed into the object. A temporary def file will be created - in the intermediate_dir. - - Args: - module_name: The name of the module we are writing a stub for. - signatures: The list of signature hashes, as produced by ParseSignatures, - to create stubs for. - intermediate_dir: The directory where the generated .def files should go. - outdir_path: The directory where generated .lib files should go. - machine: String holding the machine type, 'X86' or 'X64'. - - Raises: - SubprocessError: If invoking the windows "lib" tool fails, this is raised - with the error code. - """ - def_file_path = os.path.join(intermediate_dir, - module_name + '.def') - lib_file_path = os.path.join(outdir_path, - module_name + '.lib') - outfile = open(def_file_path, 'w') - try: - WriteWindowsDefFile(module_name, signatures, outfile) - finally: - outfile.close() - - # Invoke the "lib" program on Windows to create stub .lib files for the - # generated definitions. These .lib files can then be used during - # delayloading of the dynamic libraries. - ret = QuietRun(['lib', '/nologo', - '/machine:' + machine, - '/def:' + def_file_path, - '/out:' + lib_file_path], - filter=' Creating library') - if ret != 0: - raise SubprocessError( - 'Failed creating %s for %s' % (lib_file_path, def_file_path), - ret) - - -class PosixStubWriter(object): - """Creates a file of stub functions for a library that is opened via dlopen. - - Windows provides a function in their compiler known as delay loading, which - effectively generates a set of stub functions for a dynamic library that - delays loading of the dynamic library/resolution of the symbols until one of - the needed functions are accessed. - - In posix, RTLD_LAZY does something similar with DSOs. This is the default - link mode for DSOs. However, even though the symbol is not resolved until - first usage, the DSO must be present at load time of the main binary. - - To simulate the windows delay load procedure, we need to create a set of - stub functions that allow for correct linkage of the main binary, but - dispatch to the dynamically resolved symbol when the module is initialized. - - This class takes a list of function signatures, and generates a set of stub - functions plus initialization code for them. - """ - - def __init__(self, module_name, signatures): - """Initializes PosixStubWriter for this set of signatures and module_name. - - Args: - module_name: The name of the module we are writing a stub for. - signatures: The list of signature hashes, as produced by ParseSignatures, - to create stubs for. - """ - self.signatures = signatures - self.module_name = module_name - - @classmethod - def CStyleIdentifier(cls, identifier): - """Generates a C style identifier. - - The module_name has all invalid identifier characters removed (anything - that's not [_a-zA-Z0-9]) and is run through string.capwords to try - and approximate camel case. - - Args: - identifier: The string with the module name to turn to C-style. - - Returns: - A string that can be used as part of a C identifier. - """ - return string.capwords(re.sub(INVALID_C_IDENT_CHARS, '', identifier)) - - @classmethod - def EnumName(cls, module_name): - """Gets the enum name for the module. - - Takes the module name and creates a suitable enum name. The module_name - is munged to be a valid C identifier then prefixed with the string - "kModule" to generate a Google style enum name. - - Args: - module_name: The name of the module to generate an enum name for. - - Returns: - A string with the name of the enum value representing this module. - """ - return 'kModule%s' % PosixStubWriter.CStyleIdentifier(module_name) - - @classmethod - def IsInitializedName(cls, module_name): - """Gets the name of function that checks initialization of this module. - - The name is in the format IsModuleInitialized. Where "Module" is replaced - with the module name, munged to be a valid C identifier. - - Args: - module_name: The name of the module to generate the function name for. - - Returns: - A string with the name of the initialization check function. - """ - return 'Is%sInitialized' % PosixStubWriter.CStyleIdentifier(module_name) - - @classmethod - def InitializeModuleName(cls, module_name): - """Gets the name of the function that initializes this module. - - The name is in the format InitializeModule. Where "Module" is replaced - with the module name, munged to be a valid C identifier. - - Args: - module_name: The name of the module to generate the function name for. - - Returns: - A string with the name of the initialization function. - """ - return 'Initialize%s' % PosixStubWriter.CStyleIdentifier(module_name) - - @classmethod - def UninitializeModuleName(cls, module_name): - """Gets the name of the function that uninitializes this module. - - The name is in the format UninitializeModule. Where "Module" is replaced - with the module name, munged to be a valid C identifier. - - Args: - module_name: The name of the module to generate the function name for. - - Returns: - A string with the name of the uninitialization function. - """ - return 'Uninitialize%s' % PosixStubWriter.CStyleIdentifier(module_name) - - @classmethod - def StubFunctionPointer(cls, signature): - """Generates a function pointer declaration for the given signature. - - Args: - signature: A signature hash, as produced by ParseSignatures, - representating the function signature. - - Returns: - A string with the declaration of the function pointer for the signature. - """ - return 'static %s (*%s_ptr)(%s) = NULL;' % (signature['return_type'], - signature['name'], - ', '.join(signature['params'])) - - @classmethod - def StubFunction(cls, signature): - """Generates a stub function definition for the given signature. - - The function definitions are created with __attribute__((weak)) so that - they may be overridden by a real static link or mock versions to be used - when testing. - - Args: - signature: A signature hash, as produced by ParseSignatures, - representating the function signature. - - Returns: - A string with the stub function definition. - """ - return_prefix = '' - if signature['return_type'] != 'void': - return_prefix = 'return ' - - # Generate the argument list. - arguments = [re.split('[\*& ]', arg)[-1].strip() for arg in - signature['params']] - arg_list = ', '.join(arguments) - if arg_list == 'void': - arg_list = '' - - if arg_list != '' and len(arguments) > 1 and arguments[-1] == '...': - # If the last argment is ... then this is a variadic function. - if return_prefix != '': - return VARIADIC_STUB_FUNCTION_DEFINITION % { - 'return_type': signature['return_type'], - 'name': signature['name'], - 'params': ', '.join(signature['params']), - 'arg_list': ', '.join(arguments[0:-1]), - 'last_named_arg': arguments[-2]} - else: - return VOID_VARIADIC_STUB_FUNCTION_DEFINITION % { - 'name': signature['name'], - 'params': ', '.join(signature['params']), - 'arg_list': ', '.join(arguments[0:-1]), - 'last_named_arg': arguments[-2]} - else: - # This is a regular function. - return STUB_FUNCTION_DEFINITION % { - 'return_type': signature['return_type'], - 'name': signature['name'], - 'params': ', '.join(signature['params']), - 'return_prefix': return_prefix, - 'arg_list': arg_list} - - @classmethod - def WriteImplementationPreamble(cls, header_path, outfile): - """Write the necessary includes for the implementation file. - - Args: - header_path: The path to the header file. - outfile: The file handle to populate. - """ - outfile.write(IMPLEMENTATION_PREAMBLE % header_path) - - @classmethod - def WriteUmbrellaInitializer(cls, module_names, namespace, outfile): - """Writes a single function that will open + initialize each module. - - This intializer will take in an stl map of that lists the correct - dlopen target for each module. The map type is - std::map> which matches one module - to a list of paths to try in dlopen. - - This function is an all-or-nothing function. If any module fails to load, - all other modules are dlclosed, and the function returns. Though it is - not enforced, this function should only be called once. - - Args: - module_names: A list with the names of the modules in this stub file. - namespace: The namespace these functions should be in. - outfile: The file handle to populate with pointer definitions. - """ - outfile.write(UMBRELLA_INITIALIZER_START % namespace) - outfile.write(UMBRELLA_INITIALIZER_CLEANUP_FUNCTION) - - # Create the initializaiton function that calls all module initializers, - # checks if they succeeded, and backs out module loads on an error. - outfile.write(UMBRELLA_INITIALIZER_INITIALIZE_FUNCTION_START) - outfile.write( - '\n // Initialize each module if we have not already failed.\n') - for module in module_names: - outfile.write(' %s(opened_libraries[%s]);\n' % - (PosixStubWriter.InitializeModuleName(module), - PosixStubWriter.EnumName(module))) - outfile.write('\n') - - # Output code to check the initialization status, clean up on error. - initializer_checks = ['!%s()' % PosixStubWriter.IsInitializedName(name) - for name in module_names] - uninitializers = ['%s()' % PosixStubWriter.UninitializeModuleName(name) - for name in module_names] - outfile.write(UMBRELLA_INITIALIZER_CHECK_AND_CLEANUP % { - 'conditional': ' ||\n '.join(initializer_checks), - 'uninitializers': ';\n '.join(uninitializers)}) - outfile.write('\n} // namespace %s\n' % namespace) - - @classmethod - def WriteHeaderContents(cls, module_names, namespace, header_guard, outfile): - """Writes a header file for the stub file generated for module_names. - - The header file exposes the following: - 1) An enum, StubModules, listing with an entry for each enum. - 2) A typedef for a StubPathMap allowing for specification of paths to - search for each module. - 3) The IsInitialized/Initialize/Uninitialize functions for each module. - 4) An umbrella initialize function for all modules. - - Args: - module_names: A list with the names of each module in this stub file. - namespace: The namespace these functions should be in. - header_guard: The macro to use as our header guard. - outfile: The output handle to populate. - """ - outfile.write(STUB_HEADER_PREAMBLE % - {'guard_name': header_guard, 'namespace': namespace}) - - # Generate the Initializer protoypes for each module. - outfile.write('// Individual module initializer functions.\n') - for name in module_names: - outfile.write(MODULE_FUNCTION_PROTOTYPES % { - 'is_initialized': PosixStubWriter.IsInitializedName(name), - 'initialize': PosixStubWriter.InitializeModuleName(name), - 'uninitialize': PosixStubWriter.UninitializeModuleName(name)}) - - # Generate the enum for umbrella initializer. - outfile.write(UMBRELLA_ENUM_START) - outfile.write(' %s = 0,\n' % PosixStubWriter.EnumName(module_names[0])) - for name in module_names[1:]: - outfile.write(' %s,\n' % PosixStubWriter.EnumName(name)) - outfile.write(UMBRELLA_ENUM_END) - - outfile.write(UMBRELLA_INITIALIZER_PROTOTYPE) - outfile.write(STUB_HEADER_CLOSER % { - 'namespace': namespace, 'guard_name': - header_guard}) - - def WriteImplementationContents(self, namespace, outfile): - """Given a file handle, write out the stub definitions for this module. - - Args: - namespace: The namespace these functions should be in. - outfile: The file handle to populate. - """ - outfile.write(IMPLEMENTATION_CONTENTS_C_START) - self.WriteFunctionPointers(outfile) - self.WriteStubFunctions(outfile) - outfile.write(IMPLEMENTATION_CONTENTS_C_END) - - outfile.write(NAMESPACE_START % namespace) - self.WriteModuleInitializeFunctions(outfile) - outfile.write(NAMESPACE_END % namespace) - - def WriteFunctionPointers(self, outfile): - """Write the function pointer declarations needed by the stubs. - - We need function pointers to hold the actual location of the function - implementation returned by dlsym. This function outputs a pointer - definition for each signature in the module. - - Pointers will be named with the following pattern "FuntionName_ptr". - - Args: - outfile: The file handle to populate with pointer definitions. - """ - outfile.write(FUNCTION_POINTER_SECTION_COMMENT) - - for sig in self.signatures: - outfile.write('%s\n' % PosixStubWriter.StubFunctionPointer(sig)) - outfile.write('\n') - - def WriteStubFunctions(self, outfile): - """Write the function stubs to handle dispatching to real implementations. - - Functions that have a return type other than void will look as follows: - - ReturnType FunctionName(A a) { - return FunctionName_ptr(a); - } - - Functions with a return type of void will look as follows: - - void FunctionName(A a) { - FunctionName_ptr(a); - } - - Args: - outfile: The file handle to populate. - """ - outfile.write('// Stubs that dispatch to the real implementations.\n') - for sig in self.signatures: - outfile.write('%s\n' % PosixStubWriter.StubFunction(sig)) - - def WriteModuleInitializeFunctions(self, outfile): - """Write functions to initialize/query initlialization of the module. - - This creates 2 functions IsModuleInitialized and InitializeModule where - "Module" is replaced with the module name, first letter capitalized. - - The InitializeModule function takes a handle that is retrieved from dlopen - and attempts to assign each function pointer above via dlsym. - - The IsModuleInitialized returns true if none of the required functions - pointers are NULL. - - Args: - outfile: The file handle to populate. - """ - ptr_names = ['%s_ptr' % sig['name'] for sig in self.signatures] - - # Construct the conditional expression to check the initialization of - # all the function pointers above. It should generate a conjuntion - # with each pointer on its own line, indented by six spaces to match - # the indentation level of MODULE_INITIALIZATION_CHECK_FUNCTION. - initialization_conditional = ' &&\n '.join(ptr_names) - - outfile.write(MODULE_INITIALIZATION_CHECK_FUNCTION % ( - PosixStubWriter.IsInitializedName(self.module_name), - initialization_conditional)) - - # Create function that initializes the module. - outfile.write(MODULE_INITIALIZE_START % - PosixStubWriter.InitializeModuleName(self.module_name)) - for sig in self.signatures: - outfile.write(STUB_POINTER_INITIALIZER % { - 'name': sig['name'], - 'return_type': sig['return_type'], - 'parameters': ', '.join(sig['params'])}) - outfile.write(MODULE_INITIALIZE_END) - - # Create function that uninitializes the module (sets all pointers to - # NULL). - outfile.write(MODULE_UNINITIALIZE_START % - PosixStubWriter.UninitializeModuleName(self.module_name)) - for sig in self.signatures: - outfile.write(' %s_ptr = NULL;\n' % sig['name']) - outfile.write(MODULE_UNINITIALIZE_END) - - -def CreateOptionParser(): - """Creates an OptionParser for the configuration options of script. - - Returns: - A OptionParser object. - """ - parser = optparse.OptionParser(usage='usage: %prog [options] input') - parser.add_option('-o', - '--output', - dest='out_dir', - default=None, - help='Output location.') - parser.add_option('-i', - '--intermediate_dir', - dest='intermediate_dir', - default=None, - help=('Location of intermediate files. Ignored for %s type' - % FILE_TYPE_WIN_DEF)) - parser.add_option('-t', - '--type', - dest='type', - default=None, - help=('Type of file. Valid types are "%s" or "%s" or "%s" ' - 'or "%s"' % - (FILE_TYPE_POSIX_STUB, FILE_TYPE_WIN_X86, - FILE_TYPE_WIN_X64, FILE_TYPE_WIN_DEF))) - parser.add_option('-s', - '--stubfile_name', - dest='stubfile_name', - default=None, - help=('Name of posix_stubs output file. Only valid with ' - '%s type.' % FILE_TYPE_POSIX_STUB)) - parser.add_option('-p', - '--path_from_source', - dest='path_from_source', - default=None, - help=('The relative path from the project root that the ' - 'generated file should consider itself part of (eg. ' - 'third_party/ffmpeg). This is used to generate the ' - 'header guard and namespace for our initializer ' - 'functions and does NOT affect the physical output ' - 'location of the file like -o does. Ignored for ' - '%s and %s types.' % - (FILE_TYPE_WIN_X86, FILE_TYPE_WIN_X64))) - parser.add_option('-e', - '--extra_stub_header', - dest='extra_stub_header', - default=None, - help=('File to insert after the system includes in the ' - 'generated stub implemenation file. Ignored for ' - '%s and %s types.' % - (FILE_TYPE_WIN_X86, FILE_TYPE_WIN_X64))) - parser.add_option('-m', - '--module_name', - dest='module_name', - default=None, - help=('Name of output DLL or LIB for DEF creation using ' - '%s type.' % FILE_TYPE_WIN_DEF)) - - return parser - - -def ParseOptions(): - """Parses the options and terminates program if they are not sane. - - Returns: - The pair (optparse.OptionValues, [string]), that is the output of - a successful call to parser.parse_args(). - """ - parser = CreateOptionParser() - options, args = parser.parse_args() - - if not args: - parser.error('No inputs specified') - - if options.out_dir is None: - parser.error('Output location not specified') - - if (options.type not in - [FILE_TYPE_WIN_X86, FILE_TYPE_WIN_X64, FILE_TYPE_POSIX_STUB, - FILE_TYPE_WIN_DEF]): - parser.error('Invalid output file type: %s' % options.type) - - if options.type == FILE_TYPE_POSIX_STUB: - if options.stubfile_name is None: - parser.error('Output file name needed for %s' % FILE_TYPE_POSIX_STUB) - if options.path_from_source is None: - parser.error('Path from source needed for %s' % FILE_TYPE_POSIX_STUB) - - if options.type == FILE_TYPE_WIN_DEF: - if options.module_name is None: - parser.error('Module name needed for %s' % FILE_TYPE_WIN_DEF) - - return options, args - - -def EnsureDirExists(dir): - """Creates a directory. Does not use the more obvious 'if not exists: create' - to avoid race with other invocations of the same code, which will error out - on makedirs if another invocation has succeeded in creating the directory - since the existence check.""" - try: - os.makedirs(dir) - except: - if not os.path.isdir(dir): - raise - - -def CreateOutputDirectories(options): - """Creates the intermediate and final output directories. - - Given the parsed options, create the intermediate and final output - directories if they do not exist. Returns the paths to both directories - as a pair. - - Args: - options: An OptionParser.OptionValues object with the parsed options. - - Returns: - The pair (out_dir, intermediate_dir), both of which are strings. - """ - out_dir = os.path.normpath(options.out_dir) - intermediate_dir = os.path.normpath(options.intermediate_dir) - if intermediate_dir is None: - intermediate_dir = out_dir - - EnsureDirExists(out_dir) - EnsureDirExists(intermediate_dir) - - return out_dir, intermediate_dir - - -def CreateWindowsLibForSigFiles(sig_files, out_dir, intermediate_dir, machine): - """For each signature file, create a windows lib. - - Args: - sig_files: Array of strings with the paths to each signature file. - out_dir: String holding path to directory where the generated libs go. - intermediate_dir: String holding path to directory generated intermdiate - artifacts. - machine: String holding the machine type, 'X86' or 'X64'. - """ - for input_path in sig_files: - infile = open(input_path, 'r') - try: - signatures = ParseSignatures(infile) - module_name = ExtractModuleName(os.path.basename(input_path)) - CreateWindowsLib(module_name, signatures, intermediate_dir, out_dir, - machine) - finally: - infile.close() - - -def CreateWindowsDefForSigFiles(sig_files, out_dir, module_name): - """For all signature files, create a single windows def file. - - Args: - sig_files: Array of strings with the paths to each signature file. - out_dir: String holding path to directory where the generated def goes. - module_name: Name of the output DLL or LIB which will link in the def file. - """ - signatures = [] - for input_path in sig_files: - infile = open(input_path, 'r') - try: - signatures += ParseSignatures(infile) - finally: - infile.close() - - def_file_path = os.path.join( - out_dir, os.path.splitext(os.path.basename(module_name))[0] + '.def') - outfile = open(def_file_path, 'w') - - try: - WriteWindowsDefFile(module_name, signatures, outfile) - finally: - outfile.close() - - -def CreatePosixStubsForSigFiles(sig_files, stub_name, out_dir, - intermediate_dir, path_from_source, - extra_stub_header): - """Create a posix stub library with a module for each signature file. - - Args: - sig_files: Array of strings with the paths to each signature file. - stub_name: String with the basename of the generated stub file. - out_dir: String holding path to directory for the .h files. - intermediate_dir: String holding path to directory for the .cc files. - path_from_source: String with relative path of generated files from the - project root. - extra_stub_header: String with path to file of extra lines to insert - into the generated header for the stub library. - """ - header_base_name = stub_name + '.h' - header_path = os.path.join(out_dir, header_base_name) - impl_path = os.path.join(intermediate_dir, stub_name + '.cc') - - module_names = [ExtractModuleName(path) for path in sig_files] - namespace = path_from_source.replace('/', '_').lower() - header_guard = '%s_' % namespace.upper() - header_include_path = os.path.join(path_from_source, header_base_name) - - # First create the implementation file. - impl_file = open(impl_path, 'w') - try: - # Open the file, and create the preamble which consists of a file - # header plus any necessary includes. - PosixStubWriter.WriteImplementationPreamble(header_include_path, - impl_file) - if extra_stub_header is not None: - extra_header_file = open(extra_stub_header, 'r') - try: - impl_file.write('\n') - for line in extra_header_file: - impl_file.write(line) - impl_file.write('\n') - finally: - extra_header_file.close() - - # For each signature file, generate the stub population functions - # for that file. Each file represents one module. - for input_path in sig_files: - name = ExtractModuleName(input_path) - infile = open(input_path, 'r') - try: - signatures = ParseSignatures(infile) - finally: - infile.close() - writer = PosixStubWriter(name, signatures) - writer.WriteImplementationContents(namespace, impl_file) - - # Lastly, output the umbrella function for the file. - PosixStubWriter.WriteUmbrellaInitializer(module_names, namespace, - impl_file) - finally: - impl_file.close() - - # Then create the associated header file. - header_file = open(header_path, 'w') - try: - PosixStubWriter.WriteHeaderContents(module_names, namespace, - header_guard, header_file) - finally: - header_file.close() - - -def main(): - options, args = ParseOptions() - out_dir, intermediate_dir = CreateOutputDirectories(options) - - if options.type == FILE_TYPE_WIN_X86: - CreateWindowsLibForSigFiles(args, out_dir, intermediate_dir, 'X86') - elif options.type == FILE_TYPE_WIN_X64: - CreateWindowsLibForSigFiles(args, out_dir, intermediate_dir, 'X64') - elif options.type == FILE_TYPE_POSIX_STUB: - CreatePosixStubsForSigFiles(args, options.stubfile_name, out_dir, - intermediate_dir, options.path_from_source, - options.extra_stub_header) - elif options.type == FILE_TYPE_WIN_DEF: - CreateWindowsDefForSigFiles(args, out_dir, options.module_name) - - -if __name__ == '__main__': - main() diff --git a/tools/generate_stubs/generate_stubs_unittest.py b/tools/generate_stubs/generate_stubs_unittest.py deleted file mode 100755 index 13a2bc15e5..0000000000 --- a/tools/generate_stubs/generate_stubs_unittest.py +++ /dev/null @@ -1,297 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Unittest for the generate_stubs.py. - -Since generate_stubs.py is a code generator, it is hard to do a very good -test. Instead of creating a golden-file test, which might be flakey, this -test elects instead to verify that various components "exist" within the -generated file as a sanity check. In particular, there is a simple hit -test to make sure that umbrella functions, etc., do try and include every -function they are responsible for invoking. Missing an invocation is quite -easily missed. - -There is no attempt to verify ordering of different components, or whether -or not those components are going to parse incorrectly because of prior -errors or positioning. Most of that should be caught really fast anyways -during any attempt to use a badly behaving script. -""" - -import generate_stubs as gs -import re -import StringIO -import sys -import unittest - - -def _MakeSignature(return_type, name, params): - return {'return_type': return_type, - 'name': name, - 'params': params} - - -SIMPLE_SIGNATURES = [ - ('int foo(int a)', _MakeSignature('int', 'foo', ['int a'])), - ('int bar(int a, double b)', _MakeSignature('int', 'bar', - ['int a', 'double b'])), - ('int baz(void)', _MakeSignature('int', 'baz', ['void'])), - ('void quux(void)', _MakeSignature('void', 'quux', ['void'])), - ('void waldo(void);', _MakeSignature('void', 'waldo', ['void'])), - ('int corge(void);', _MakeSignature('int', 'corge', ['void'])), - ] - -TRICKY_SIGNATURES = [ - ('const struct name *foo(int a, struct Test* b); ', - _MakeSignature('const struct name *', - 'foo', - ['int a', 'struct Test* b'])), - ('const struct name &foo(int a, struct Test* b);', - _MakeSignature('const struct name &', - 'foo', - ['int a', 'struct Test* b'])), - ('const struct name &_foo(int a, struct Test* b);', - _MakeSignature('const struct name &', - '_foo', - ['int a', 'struct Test* b'])), - ('struct name const * const _foo(int a, struct Test* b) ' - '__attribute__((inline));', - _MakeSignature('struct name const * const', - '_foo', - ['int a', 'struct Test* b'])) - ] - -INVALID_SIGNATURES = ['I am bad', 'Seriously bad(', ';;;'] - - -class GenerateStubModuleFunctionsUnittest(unittest.TestCase): - def testExtractModuleName(self): - self.assertEqual('somefile-2', gs.ExtractModuleName('somefile-2.ext')) - - def testParseSignatures_EmptyFile(self): - # Empty file just generates empty signatures. - infile = StringIO.StringIO() - signatures = gs.ParseSignatures(infile) - self.assertEqual(0, len(signatures)) - - def testParseSignatures_SimpleSignatures(self): - file_contents = '\n'.join([x[0] for x in SIMPLE_SIGNATURES]) - infile = StringIO.StringIO(file_contents) - signatures = gs.ParseSignatures(infile) - self.assertEqual(len(SIMPLE_SIGNATURES), len(signatures)) - - # We assume signatures are in order. - for i in xrange(len(SIMPLE_SIGNATURES)): - self.assertEqual(SIMPLE_SIGNATURES[i][1], signatures[i], - msg='Expected %s\nActual %s\nFor %s' % - (SIMPLE_SIGNATURES[i][1], - signatures[i], - SIMPLE_SIGNATURES[i][0])) - - def testParseSignatures_TrickySignatures(self): - file_contents = '\n'.join([x[0] for x in TRICKY_SIGNATURES]) - infile = StringIO.StringIO(file_contents) - signatures = gs.ParseSignatures(infile) - self.assertEqual(len(TRICKY_SIGNATURES), len(signatures)) - - # We assume signatures are in order. - for i in xrange(len(TRICKY_SIGNATURES)): - self.assertEqual(TRICKY_SIGNATURES[i][1], signatures[i], - msg='Expected %s\nActual %s\nFor %s' % - (TRICKY_SIGNATURES[i][1], - signatures[i], - TRICKY_SIGNATURES[i][0])) - - def testParseSignatures_InvalidSignatures(self): - for i in INVALID_SIGNATURES: - infile = StringIO.StringIO(i) - self.assertRaises(gs.BadSignatureError, gs.ParseSignatures, infile) - - def testParseSignatures_CommentsIgnored(self): - my_sigs = [] - my_sigs.append('# a comment') - my_sigs.append(SIMPLE_SIGNATURES[0][0]) - my_sigs.append('# another comment') - my_sigs.append(SIMPLE_SIGNATURES[0][0]) - my_sigs.append('# a third comment') - my_sigs.append(SIMPLE_SIGNATURES[0][0]) - - file_contents = '\n'.join(my_sigs) - infile = StringIO.StringIO(file_contents) - signatures = gs.ParseSignatures(infile) - self.assertEqual(3, len(signatures)) - - -class WindowsLibUnittest(unittest.TestCase): - def testWriteWindowsDefFile(self): - module_name = 'my_module-1' - signatures = [sig[1] for sig in SIMPLE_SIGNATURES] - outfile = StringIO.StringIO() - gs.WriteWindowsDefFile(module_name, signatures, outfile) - contents = outfile.getvalue() - - # Check that the file header is correct. - self.assertTrue(contents.startswith("""LIBRARY %s -EXPORTS -""" % module_name)) - - # Check that the signatures were exported. - for sig in signatures: - pattern = '\n %s\n' % sig['name'] - self.assertTrue(re.search(pattern, contents), - msg='Expected match of "%s" in %s' % (pattern, contents)) - - def testQuietRun(self): - output = StringIO.StringIO() - gs.QuietRun([sys.executable, - '-c', 'print "line 1 and suffix\\nline 2"'], - write_to=output) - self.assertEqual('line 1 and suffix\nline 2\n', output.getvalue()) - - output = StringIO.StringIO() - gs.QuietRun([sys.executable, - '-c', 'print "line 1 and suffix\\nline 2"'], - filter='line 1', write_to=output) - self.assertEqual('line 2\n', output.getvalue()) - - -class PosixStubWriterUnittest(unittest.TestCase): - def setUp(self): - self.module_name = 'my_module-1' - self.signatures = [sig[1] for sig in SIMPLE_SIGNATURES] - self.out_dir = 'out_dir' - self.writer = gs.PosixStubWriter(self.module_name, self.signatures) - - def testEnumName(self): - self.assertEqual('kModuleMy_module1', - gs.PosixStubWriter.EnumName(self.module_name)) - - def testIsInitializedName(self): - self.assertEqual('IsMy_module1Initialized', - gs.PosixStubWriter.IsInitializedName(self.module_name)) - - def testInitializeModuleName(self): - self.assertEqual( - 'InitializeMy_module1', - gs.PosixStubWriter.InitializeModuleName(self.module_name)) - - def testUninitializeModuleName(self): - self.assertEqual( - 'UninitializeMy_module1', - gs.PosixStubWriter.UninitializeModuleName(self.module_name)) - - def testStubFunctionPointer(self): - self.assertEqual( - 'static int (*foo_ptr)(int a) = NULL;', - gs.PosixStubWriter.StubFunctionPointer(SIMPLE_SIGNATURES[0][1])) - - def testStubFunction(self): - # Test for a signature with a return value and a parameter. - self.assertEqual("""extern int foo(int a) __attribute__((weak)); -int foo(int a) { - return foo_ptr(a); -}""", gs.PosixStubWriter.StubFunction(SIMPLE_SIGNATURES[0][1])) - - # Test for a signature with a void return value and no parameters. - self.assertEqual("""extern void waldo(void) __attribute__((weak)); -void waldo(void) { - waldo_ptr(); -}""", gs.PosixStubWriter.StubFunction(SIMPLE_SIGNATURES[4][1])) - - def testWriteImplemenationContents(self): - outfile = StringIO.StringIO() - self.writer.WriteImplementationContents('my_namespace', outfile) - contents = outfile.getvalue() - - # Verify namespace exists somewhere. - self.assertTrue(contents.find('namespace my_namespace {') != -1) - - # Verify that each signature has an _ptr and a function call in the file. - # Check that the signatures were exported. - for sig in self.signatures: - decl = gs.PosixStubWriter.StubFunctionPointer(sig) - self.assertTrue(contents.find(decl) != -1, - msg='Expected "%s" in %s' % (decl, contents)) - - # Verify that each signature has an stub function generated for it. - for sig in self.signatures: - decl = gs.PosixStubWriter.StubFunction(sig) - self.assertTrue(contents.find(decl) != -1, - msg='Expected "%s" in %s' % (decl, contents)) - - # Find module initializer functions. Make sure all 3 exist. - decl = gs.PosixStubWriter.InitializeModuleName(self.module_name) - self.assertTrue(contents.find(decl) != -1, - msg='Expected "%s" in %s' % (decl, contents)) - decl = gs.PosixStubWriter.UninitializeModuleName(self.module_name) - self.assertTrue(contents.find(decl) != -1, - msg='Expected "%s" in %s' % (decl, contents)) - decl = gs.PosixStubWriter.IsInitializedName(self.module_name) - self.assertTrue(contents.find(decl) != -1, - msg='Expected "%s" in %s' % (decl, contents)) - - def testWriteHeaderContents(self): - # Data for header generation. - module_names = ['oneModule', 'twoModule'] - - # Make the header. - outfile = StringIO.StringIO() - self.writer.WriteHeaderContents(module_names, 'my_namespace', 'GUARD_', - outfile) - contents = outfile.getvalue() - - # Check for namespace and header guard. - self.assertTrue(contents.find('namespace my_namespace {') != -1) - self.assertTrue(contents.find('#ifndef GUARD_') != -1) - - # Check for umbrella initializer. - self.assertTrue(contents.find('InitializeStubs(') != -1) - - # Check per-module declarations. - for name in module_names: - # Check for enums. - decl = gs.PosixStubWriter.EnumName(name) - self.assertTrue(contents.find(decl) != -1, - msg='Expected "%s" in %s' % (decl, contents)) - - # Check for module initializer functions. - decl = gs.PosixStubWriter.IsInitializedName(name) - self.assertTrue(contents.find(decl) != -1, - msg='Expected "%s" in %s' % (decl, contents)) - decl = gs.PosixStubWriter.InitializeModuleName(name) - self.assertTrue(contents.find(decl) != -1, - msg='Expected "%s" in %s' % (decl, contents)) - decl = gs.PosixStubWriter.UninitializeModuleName(name) - self.assertTrue(contents.find(decl) != -1, - msg='Expected "%s" in %s' % (decl, contents)) - - def testWriteUmbrellaInitializer(self): - # Data for header generation. - module_names = ['oneModule', 'twoModule'] - - # Make the header. - outfile = StringIO.StringIO() - self.writer.WriteUmbrellaInitializer(module_names, 'my_namespace', outfile) - contents = outfile.getvalue() - - # Check for umbrella initializer declaration. - self.assertTrue(contents.find('bool InitializeStubs(') != -1) - - # If the umbrella initializer is correctly written, each module will have - # its initializer called, checked, and uninitialized on failure. Sanity - # check that here. - for name in module_names: - # Check for module initializer functions. - decl = gs.PosixStubWriter.IsInitializedName(name) - self.assertTrue(contents.find(decl) != -1, - msg='Expected "%s" in %s' % (decl, contents)) - decl = gs.PosixStubWriter.InitializeModuleName(name) - self.assertTrue(contents.find(decl) != -1, - msg='Expected "%s" in %s' % (decl, contents)) - decl = gs.PosixStubWriter.UninitializeModuleName(name) - self.assertTrue(contents.find(decl) != -1, - msg='Expected "%s" in %s' % (decl, contents)) - -if __name__ == '__main__': - unittest.main() diff --git a/tools/gn/BUILD.gn b/tools/gn/BUILD.gn deleted file mode 100644 index 17be36c0f4..0000000000 --- a/tools/gn/BUILD.gn +++ /dev/null @@ -1,174 +0,0 @@ -static_library("gn_lib") { - sources = [ - "binary_target_generator.cc", - "binary_target_generator.h", - "build_settings.cc", - "build_settings.h", - "command_desc.cc", - "command_gen.cc", - "command_help.cc", - "commands.cc", - "commands.h", - "config.cc", - "config.h", - "config_values.cc", - "config_values.h", - "config_values_extractors.cc", - "config_values_extractors.h", - "config_values_generator.cc", - "config_values_generator.h", - "copy_target_generator.cc", - "copy_target_generator.h", - "err.cc", - "err.h", - "escape.cc", - "escape.h", - "file_template.cc", - "file_template.h", - "filesystem_utils.cc", - "filesystem_utils.h", - "functions.cc", - "functions.h", - "functions_target.cc", - "function_exec_script.cc", - "function_process_file_template.cc", - "function_read_file.cc", - "function_set_default_toolchain.cc", - "function_template.cc", - "function_toolchain.cc", - "function_write_file.cc", - "group_target_generator.cc", - "group_target_generator.h", - "import_manager.cc", - "import_manager.h", - "input_conversion.cc", - "input_conversion.h", - "input_file.cc", - "input_file.h", - "input_file_manager.cc", - "input_file_manager.h", - "item.cc", - "item.h", - "item_node.cc", - "item_node.h", - "item_tree.cc", - "item_tree.h", - "label.cc", - "label.h", - "location.h", - "ninja_binary_target_writer.cc", - "ninja_binary_target_writer.h", - "ninja_build_writer.cc", - "ninja_build_writer.h", - "ninja_copy_target_writer.cc", - "ninja_copy_target_writer.h", - "ninja_group_target_writer.cc", - "ninja_group_target_writer.h", - "ninja_helper.cc", - "ninja_helper.h", - "ninja_script_target_writer.cc", - "ninja_script_target_writer.h", - "ninja_target_writer.cc", - "ninja_target_writer.h", - "ninja_toolchain_writer.cc", - "ninja_toolchain_writer.h", - "ninja_writer.cc", - "ninja_writer.h", - "operators.cc", - "operators.h", - "output_file.h", - "parse_tree.cc", - "parse_tree.h", - "parser.cc", - "parser.h", - "path_output.cc", - "path_output.h", - "pattern.cc", - "pattern.h", - "scheduler.cc", - "scheduler.h", - "scope.cc", - "scope.h", - "scope_per_file_provider.cc", - "scope_per_file_provider.h", - "script_target_generator.cc", - "script_target_generator.h", - "script_values.cc", - "script_values.h", - "settings.cc", - "settings.h", - "setup.cc", - "setup.h", - "source_dir.cc", - "source_dir.h", - "source_file.cc", - "source_file.h", - "standard_out.cc", - "standard_out.h", - "string_utils.cc", - "string_utils.h", - "target.cc", - "target.h", - "target_generator.cc", - "target_generator.h", - "target_manager.cc", - "target_manager.h", - "token.cc", - "token.h", - "tokenizer.cc", - "tokenizer.h", - "toolchain.cc", - "toolchain.h", - "toolchain_manager.cc", - "toolchain_manager.h", - "value.cc", - "value.h", - "value_extractors.cc", - "value_extractors.h", - "variables.cc", - "variables.h", - ] - deps = [ - "//base", - "//base/third_party/dynamic_annotations", - ] -} - -executable("gn") { - sources = [ - "gn_main.cc", - ] - deps = [ - ":gn_lib", - ] -} - -test("gn_unittests") { - sources = [ - "escape_unittest.cc", - "file_template_unittest.cc", - "filesystem_utils_unittest.cc", - "input_conversion_unittest.cc", - "label_unittest.cc", - "ninja_helper_unittest.cc", - "parser_unittest.cc", - "path_output_unittest.cc", - "pattern_unittest.cc", - "source_dir_unittest.cc", - "string_utils_unittest.cc", - "target_generator_unittest.cc", - "target_manager_unittest.cc", - "tokenizer_unittest.cc", - ] - deps = [ - ":gn_lib", - "//base:run_all_unittests", - "//base:test_support_base", - "//testing:gtest", - ] -} - -executable("generate_test_gn_data") { - sources = [ "generate_test_gn_data.cc" ] - deps = [ "//base" ] -} diff --git a/tools/gn/OWNERS b/tools/gn/OWNERS deleted file mode 100644 index 06fefbf4ec..0000000000 --- a/tools/gn/OWNERS +++ /dev/null @@ -1 +0,0 @@ -brettw@chromium.org diff --git a/tools/gn/README.txt b/tools/gn/README.txt deleted file mode 100644 index 0a637bf477..0000000000 --- a/tools/gn/README.txt +++ /dev/null @@ -1,7 +0,0 @@ -GN "Generate Ninja" - -This tool is an experimental metabuildsystem. It is not currently in a state -where it is ready for public consumption. - -It is not currently used in the build and there are currently no plans to -replace GYP. diff --git a/tools/gn/binary_target_generator.cc b/tools/gn/binary_target_generator.cc deleted file mode 100644 index d7e488a5a6..0000000000 --- a/tools/gn/binary_target_generator.cc +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/gn/binary_target_generator.h" - -#include "tools/gn/config_values_generator.h" -#include "tools/gn/err.h" - -BinaryTargetGenerator::BinaryTargetGenerator(Target* target, - Scope* scope, - const Token& function_token, - Target::OutputType type, - Err* err) - : TargetGenerator(target, scope, function_token, err), - output_type_(type) { -} - -BinaryTargetGenerator::~BinaryTargetGenerator() { -} - -void BinaryTargetGenerator::DoRun() { - target_->set_output_type(output_type_); - - FillSources(); - FillConfigs(); - - // Config values (compiler flags, etc.) set directly on this target. - ConfigValuesGenerator gen(&target_->config_values(), scope_, - function_token_, input_directory_, err_); - gen.Run(); - if (err_->has_error()) - return; - - SetToolchainDependency(); -} diff --git a/tools/gn/binary_target_generator.h b/tools/gn/binary_target_generator.h deleted file mode 100644 index dacb4974bd..0000000000 --- a/tools/gn/binary_target_generator.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef TOOLS_GN_BINARY_TARGET_GENERATOR_H_ -#define TOOLS_GN_BINARY_TARGET_GENERATOR_H_ - -#include "base/compiler_specific.h" -#include "tools/gn/target_generator.h" - -// Populates a Target with the values from a binary rule (executable, shared -// library, or static library). -class BinaryTargetGenerator : public TargetGenerator { - public: - BinaryTargetGenerator(Target* target, - Scope* scope, - const Token& function_token, - Target::OutputType type, - Err* err); - virtual ~BinaryTargetGenerator(); - - protected: - virtual void DoRun() OVERRIDE; - - private: - Target::OutputType output_type_; - - DISALLOW_COPY_AND_ASSIGN(BinaryTargetGenerator); -}; - -#endif // TOOLS_GN_BINARY_TARGET_GENERATOR_H_ - diff --git a/tools/gn/build_settings.cc b/tools/gn/build_settings.cc deleted file mode 100644 index 09b4c99589..0000000000 --- a/tools/gn/build_settings.cc +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/gn/build_settings.h" - -#include "tools/gn/filesystem_utils.h" - -BuildSettings::BuildSettings() - : item_tree_(), - target_manager_(this), - toolchain_manager_(this) { -} - -BuildSettings::~BuildSettings() { -} - -void BuildSettings::SetSecondarySourcePath(const SourceDir& d) { - secondary_source_path_ = GetFullPath(d); -} - -void BuildSettings::SetBuildDir(const SourceDir& d) { - build_dir_ = d; - build_to_source_dir_string_ = InvertDir(d); -} - -base::FilePath BuildSettings::GetFullPath(const SourceFile& file) const { - return file.Resolve(root_path_); -} - -base::FilePath BuildSettings::GetFullPath(const SourceDir& dir) const { - return dir.Resolve(root_path_); -} - -base::FilePath BuildSettings::GetFullPathSecondary( - const SourceFile& file) const { - return file.Resolve(secondary_source_path_); -} - -base::FilePath BuildSettings::GetFullPathSecondary( - const SourceDir& dir) const { - return dir.Resolve(secondary_source_path_); -} - diff --git a/tools/gn/build_settings.h b/tools/gn/build_settings.h deleted file mode 100644 index fe0426674b..0000000000 --- a/tools/gn/build_settings.h +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef TOOLS_GN_BUILD_SETTINGS_H_ -#define TOOLS_GN_BUILD_SETTINGS_H_ - -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/files/file_path.h" -#include "tools/gn/item_tree.h" -#include "tools/gn/scope.h" -#include "tools/gn/source_dir.h" -#include "tools/gn/source_file.h" -#include "tools/gn/target_manager.h" -#include "tools/gn/toolchain_manager.h" - -// Settings for one build, which is one toplevel output directory. There -// may be multiple Settings objects that refer to this, one for each toolchain. -class BuildSettings { - public: - typedef base::Callback TargetResolvedCallback; - - BuildSettings(); - ~BuildSettings(); - - // Absolute path of the source root on the local system. Everything is - // relative to this. - const base::FilePath& root_path() const { return root_path_; } - void set_root_path(const base::FilePath& r) { root_path_ = r; } - - // When nonempty, specifies a parallel directory higherarchy in which to - // search for buildfiles if they're not found in the root higherarchy. This - // allows us to keep buildfiles in a separate tree during development. - const base::FilePath& secondary_source_path() const { - return secondary_source_path_; - } - void SetSecondarySourcePath(const SourceDir& d); - - // Path of the python executable to run scripts with. - base::FilePath python_path() const { return python_path_; } - void set_python_path(const base::FilePath& p) { python_path_ = p; } - - const SourceFile& build_config_file() const { return build_config_file_; } - void set_build_config_file(const SourceFile& f) { build_config_file_ = f; } - - // The build directory is the root of all output files. The default toolchain - // files go into here, and non-default toolchains will have separate - // toolchain-specific root directories inside this. - const SourceDir& build_dir() const { return build_dir_; } - void SetBuildDir(const SourceDir& dir); - - // The inverse of relative_build_dir, ending with a separator. - // Example: relative_build_dir_ = "out/Debug/" this will be "../../" - const std::string& build_to_source_dir_string() const { - return build_to_source_dir_string_; - } - - // These accessors do not return const objects since the resulting objects - // are threadsafe. In this setting, we use constness primarily to ensure - // that the Settings object is used in a threadsafe manner. Although this - // violates the concept of logical constness, that's less important in our - // application, and actually implementing this in a way that preserves - // logical constness is cumbersome. - ItemTree& item_tree() const { return item_tree_; } - TargetManager& target_manager() const { return target_manager_; } - ToolchainManager& toolchain_manager() const { return toolchain_manager_; } - - // Returns the full absolute OS path cooresponding to the given file in the - // root source tree. - base::FilePath GetFullPath(const SourceFile& file) const; - base::FilePath GetFullPath(const SourceDir& dir) const; - - // Returns the absolute OS path inside the secondary source path. Will return - // an empty FilePath if the secondary source path is empty. When loading a - // buildfile, the GetFullPath should always be consulted first. - base::FilePath GetFullPathSecondary(const SourceFile& file) const; - base::FilePath GetFullPathSecondary(const SourceDir& dir) const; - - // This is the callback to execute when a target is marked resolved. If we - // don't need to do anything, this will be null. When a target is resolved, - // this callback should be posted to the scheduler pool so the work is - // distributed properly. - const TargetResolvedCallback& target_resolved_callback() const { - return target_resolved_callback_; - } - void set_target_resolved_callback(const TargetResolvedCallback& cb) { - target_resolved_callback_ = cb; - } - - private: - base::FilePath root_path_; - base::FilePath secondary_source_path_; - base::FilePath python_path_; - - SourceFile build_config_file_; - SourceDir build_dir_; - std::string build_to_source_dir_string_; - - TargetResolvedCallback target_resolved_callback_; - - // See getters above. - mutable ItemTree item_tree_; - mutable TargetManager target_manager_; - mutable ToolchainManager toolchain_manager_; - - DISALLOW_COPY_AND_ASSIGN(BuildSettings); -}; - -#endif // TOOLS_GN_BUILD_SETTINGS_H_ diff --git a/tools/gn/command_desc.cc b/tools/gn/command_desc.cc deleted file mode 100644 index dd78b84b7e..0000000000 --- a/tools/gn/command_desc.cc +++ /dev/null @@ -1,344 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include -#include -#include - -#include "base/command_line.h" -#include "tools/gn/commands.h" -#include "tools/gn/config.h" -#include "tools/gn/config_values_extractors.h" -#include "tools/gn/item.h" -#include "tools/gn/item_node.h" -#include "tools/gn/label.h" -#include "tools/gn/setup.h" -#include "tools/gn/standard_out.h" -#include "tools/gn/target.h" - -namespace commands { - -namespace { - -struct CompareTargetLabel { - bool operator()(const Target* a, const Target* b) const { - return a->label() < b->label(); - } -}; - -void RecursiveCollectDeps(const Target* target, std::set