1# Copyright (C) 2018 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15import("../../../gn/fuzzer.gni") 16import("../../../gn/perfetto.gni") 17import("../../../gn/test.gni") 18 19assert(enable_perfetto_heapprofd) 20 21# The Android heap profiling daemon. 22executable("heapprofd") { 23 deps = [ 24 ":heapprofd_main", 25 "../../../gn:default_deps", 26 ] 27 sources = [ "main.cc" ] 28} 29 30source_set("heapprofd_main") { 31 deps = [ 32 "../../../gn:default_deps", 33 "../../../protos/perfetto/trace:zero", 34 "../../../src/base", 35 "../../../src/base:unix_socket", 36 "../../../src/profiling/memory:daemon", 37 "../../../src/profiling/memory:wire_protocol", 38 "../../../src/tracing/ipc/producer", 39 ] 40 sources = [ 41 "heapprofd.cc", 42 "heapprofd.h", 43 ] 44} 45 46# This library gets loaded into (and executes in) arbitrary android processes. 47# Logging must be non-allocating. This is achieved by defining 48# PERFETTO_ANDROID_ASYNC_SAFE_LOG, which needs to be set for all perfetto code 49# being compiled for this library. When generating Android.bp, the |cflags| 50# entry on this target is sufficient (as all sources are flattened into a 51# single bp target). However this is not correctly reflected in the gn 52# structure (which is a tree of targets) as the dependencies would not pick 53# up the flag (and thus use the wrong logging macro). 54# 55# This builds only in the Android tree, when using the generated Android.bp. 56if (perfetto_build_with_android) { 57 shared_library("heapprofd_client") { 58 configs -= [ "//gn/standalone:android_liblog" ] 59 cflags = [ "-DPERFETTO_ANDROID_ASYNC_SAFE_LOG" ] 60 deps = [ 61 ":heapprofd_client_api", 62 ":malloc_interceptor_bionic_hooks", 63 ] 64 } 65 66 # This will export publicly visible symbols for the 67 # malloc_interceptor_bionic_hooks. 68 source_set("malloc_interceptor_bionic_hooks") { 69 deps = [ 70 ":bionic_libc_platform_headers_on_android", 71 ":wrap_allocators", 72 "../../../gn:default_deps", 73 "../../base", 74 ] 75 cflags = [ 76 "-isystem", 77 rebase_path("../../../buildtools/bionic/libc", root_build_dir), 78 ] 79 sources = [ "malloc_interceptor_bionic_hooks.cc" ] 80 } 81} # if (perfetto_build_with_android) 82 83executable("heapprofd_standalone_client_example") { 84 deps = [ 85 ":heapprofd_standalone_client", 86 "../../../gn:default_deps", 87 ] 88 sources = [ "heapprofd_standalone_client_example.cc" ] 89} 90 91source_set("client_api_standalone") { 92 deps = [ 93 ":client", 94 ":client_api", 95 ":daemon", 96 "../../../gn:default_deps", 97 "../../../include/perfetto/ext/tracing/ipc", 98 "../../base", 99 "../common:proc_utils", 100 ] 101 sources = [ "client_api_factory_standalone.cc" ] 102} 103 104# This can be used to instrument custom allocators to report their allocations 105# to Perfetto. This bundles a copy of heapprofd in the library, in contrast to 106# heapprofd_client_api (see below), which expects one to be present in the 107# Android platform. 108shared_library("heapprofd_standalone_client") { 109 deps = [ 110 ":client_api_standalone", 111 "../../../gn:default_deps", 112 ] 113 ldflags = [ 114 "-Wl,--version-script", 115 rebase_path("heapprofd_client_api.map.txt", root_build_dir), 116 ] 117} 118 119shared_library("heapprofd_api_noop") { 120 deps = [ "../../../gn:default_deps" ] 121 ldflags = [ 122 "-Wl,--version-script", 123 rebase_path("heapprofd_client_api.map.txt", root_build_dir), 124 ] 125 126 # This target does absolutely nothing, so we do not want to depend on 127 # liblog. 128 configs -= [ "//gn/standalone:android_liblog" ] 129 sources = [ "client_api_noop.cc" ] 130} 131 132shared_library("heapprofd_client_api") { 133 configs -= [ "//gn/standalone:android_liblog" ] 134 if (perfetto_build_with_android) { 135 cflags = [ "-DPERFETTO_ANDROID_ASYNC_SAFE_LOG" ] 136 } else { 137 # We don't have async safe logging for non-Android, so disable all 138 # logging in the client. 139 # TODO(fmayer): Add async-safe logging for non-Android. 140 cflags = [ "-DPERFETTO_DISABLE_LOG" ] 141 } 142 deps = [ ":client_api" ] 143 if (perfetto_build_with_android) { 144 sources = [ "client_api_factory_android.cc" ] 145 } 146} 147 148# On GLibc Linux, this can be used to override the allocators using 149# LD_PRELOAD. On non-GLibc, this will probably fail to link. 150shared_library("heapprofd_glibc_preload") { 151 deps = [ 152 ":client_api_standalone", 153 ":wrap_allocators", 154 "../../../gn:default_deps", 155 "../../base", 156 ] 157 ldflags = [ 158 "-Wl,--version-script", 159 rebase_path("heapprofd_preload.map.txt", root_build_dir), 160 ] 161 sources = [ "malloc_interceptor_glibc_preload.cc" ] 162} 163 164# On Android builds, this is converted to 165# header_libs: ["bionic_libc_platform_headers"]. 166source_set("bionic_libc_platform_headers_on_android") { 167} 168 169source_set("client_api") { 170 if (perfetto_build_with_android) { 171 cflags = [ "-DPERFETTO_ANDROID_ASYNC_SAFE_LOG" ] 172 } else { 173 # We don't have async safe logging for non-Android, so disable all 174 # logging in the client. 175 # TODO(fmayer): Add async-safe logging for non-Android. 176 cflags = [ "-DPERFETTO_DISABLE_LOG" ] 177 } 178 deps = [ 179 ":client", 180 ":scoped_spinlock", 181 ":wire_protocol", 182 "../../../gn:default_deps", 183 "../../base", 184 ] 185 sources = [ "client_api.cc" ] 186} 187 188source_set("wrap_allocators") { 189 deps = [ 190 "../../../gn:default_deps", 191 "../../base", 192 ] 193 sources = [ "wrap_allocators.cc" ] 194} 195 196source_set("wire_protocol") { 197 public_deps = [ "../../../gn:libunwindstack" ] 198 deps = [ 199 ":bionic_libc_platform_headers_on_android", 200 ":ring_buffer", 201 "../../../gn:default_deps", 202 "../../base", 203 "../../base:unix_socket", 204 ] 205 sources = [ 206 "wire_protocol.cc", 207 "wire_protocol.h", 208 ] 209} 210 211source_set("scoped_spinlock") { 212 deps = [ 213 "../../../gn:default_deps", 214 "../../base", 215 ] 216 sources = [ 217 "scoped_spinlock.cc", 218 "scoped_spinlock.h", 219 ] 220} 221 222source_set("ring_buffer") { 223 deps = [ 224 ":scoped_spinlock", 225 "../../../gn:default_deps", 226 "../../base", 227 ] 228 sources = [ 229 "shared_ring_buffer.cc", 230 "shared_ring_buffer.h", 231 ] 232} 233 234source_set("ring_buffer_unittests") { 235 testonly = true 236 deps = [ 237 ":ring_buffer", 238 "../../../gn:default_deps", 239 "../../../gn:gtest_and_gmock", 240 "../../base", 241 ] 242 sources = [ "shared_ring_buffer_unittest.cc" ] 243} 244 245source_set("daemon") { 246 deps = [ 247 ":ring_buffer", 248 ":scoped_spinlock", 249 ":wire_protocol", 250 "../../../gn:default_deps", 251 "../../../protos/perfetto/config/profiling:cpp", 252 "../../base", 253 "../../base:unix_socket", 254 "../../tracing/core", 255 "../../tracing/ipc/producer", 256 "../common:callstack_trie", 257 "../common:interner", 258 "../common:interning_output", 259 "../common:proc_cmdline", 260 "../common:proc_utils", 261 "../common:producer_support", 262 "../common:profiler_guardrails", 263 "../common:unwind_support", 264 ] 265 public_deps = [ 266 "../../../gn:libunwindstack", 267 "../../../protos/perfetto/config/profiling:cpp", 268 "../../../protos/perfetto/trace:zero", 269 "../../../protos/perfetto/trace/interned_data:zero", 270 "../../../protos/perfetto/trace/profiling:zero", 271 ] 272 sources = [ 273 "bookkeeping.cc", 274 "bookkeeping.h", 275 "bookkeeping_dump.cc", 276 "bookkeeping_dump.h", 277 "heapprofd_producer.cc", 278 "heapprofd_producer.h", 279 "java_hprof_producer.cc", 280 "java_hprof_producer.h", 281 "log_histogram.cc", 282 "log_histogram.h", 283 "system_property.cc", 284 "system_property.h", 285 "unwinding.cc", 286 "unwinding.h", 287 "unwound_messages.h", 288 ] 289} 290 291source_set("client") { 292 deps = [ 293 ":ring_buffer", 294 ":scoped_spinlock", 295 ":wire_protocol", 296 "../../../gn:default_deps", 297 "../../base", 298 "../../base:unix_socket", 299 ] 300 public_deps = [ "../../../gn:libunwindstack" ] 301 sources = [ 302 "client.cc", 303 "client.h", 304 "sampler.cc", 305 "sampler.h", 306 ] 307} 308 309perfetto_unittest_source_set("unittests") { 310 testonly = true 311 deps = [ 312 ":client", 313 ":daemon", 314 ":ring_buffer", 315 ":wire_protocol", 316 "../../../gn:default_deps", 317 "../../../gn:gtest_and_gmock", 318 "../../../gn:libunwindstack", 319 "../../base", 320 "../../base:test_support", 321 "../../tracing/core", 322 "../../tracing/test:test_support", 323 "../common:proc_utils", 324 "../common:unwind_support", 325 ] 326 sources = [ 327 "bookkeeping_unittest.cc", 328 "client_unittest.cc", 329 "heapprofd_producer_unittest.cc", 330 "parse_smaps_unittest.cc", 331 "sampler_unittest.cc", 332 "system_property_unittest.cc", 333 "unwinding_unittest.cc", 334 "wire_protocol_unittest.cc", 335 ] 336 337 # Do not build with Android to avoid applying PERFETTO_ANDROID_ASYNC_SAFE_LOG 338 # to the whole perfetto_unittests target. 339 if (!perfetto_build_with_android) { 340 sources += [ "client_api_unittest.cc" ] 341 deps += [ ":client_api" ] 342 } 343} 344 345source_set("end_to_end_tests") { 346 testonly = true 347 deps = [ 348 ":client", 349 ":daemon", 350 ":wire_protocol", 351 "../../../gn:default_deps", 352 "../../../gn:gtest_and_gmock", 353 "../../../gn:libunwindstack", 354 "../../../protos/perfetto/config/profiling:cpp", 355 "../../../protos/perfetto/trace/interned_data:cpp", 356 "../../../protos/perfetto/trace/profiling:cpp", 357 "../../../test:test_helper", 358 "../../base", 359 "../../base:test_support", 360 "../../trace_processor:lib", 361 "../../tracing/test:test_support", 362 ] 363 sources = [ 364 "heapprofd_end_to_end_test.cc", 365 "heapprofd_producer_integrationtest.cc", 366 ] 367 if (perfetto_build_with_android) { 368 deps += [ ":heapprofd_client_api" ] 369 } else { 370 deps += [ ":heapprofd_standalone_client" ] 371 } 372} 373 374perfetto_fuzzer_test("unwinding_fuzzer") { 375 testonly = true 376 sources = [ "unwinding_fuzzer.cc" ] 377 deps = [ 378 ":daemon", 379 ":ring_buffer", 380 ":wire_protocol", 381 "../../../gn:default_deps", 382 "../../base", 383 "../../tracing/core", 384 "../common:unwind_support", 385 ] 386} 387 388perfetto_fuzzer_test("shared_ring_buffer_fuzzer") { 389 testonly = true 390 sources = [ "shared_ring_buffer_fuzzer.cc" ] 391 deps = [ 392 ":ring_buffer", 393 "../../../gn:default_deps", 394 "../../base", 395 ] 396} 397 398perfetto_fuzzer_test("shared_ring_buffer_write_fuzzer") { 399 testonly = true 400 sources = [ "shared_ring_buffer_write_fuzzer.cc" ] 401 deps = [ 402 ":ring_buffer", 403 "../../../gn:default_deps", 404 "../../base", 405 ] 406} 407 408if (enable_perfetto_benchmarks) { 409 source_set("benchmarks") { 410 testonly = true 411 deps = [ 412 ":client", 413 ":client_api", 414 "../../../gn:benchmark", 415 "../../../gn:default_deps", 416 "../../base", 417 "../../base:test_support", 418 ] 419 sources = [ "client_api_benchmark.cc" ] 420 } 421} 422