summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-11-12 15:45:40 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-11-12 15:45:40 +0000
commitb10151f531375fc1f25199c16334c4446c24a23b (patch)
treedd72a84514306c5cc0c9025a1fb9e9e3976ced32
parentf3076ee9f11bdfd75fec983c15b0c3fbe5ba6afe (diff)
parent3b739c8720db08d5b34e8a547a5b2f6305fe37b6 (diff)
downloadextras-android12-mainline-neuralnetworks-release.tar.gz
Snap for 7910331 from 3b739c8720db08d5b34e8a547a5b2f6305fe37b6 to mainline-neuralnetworks-releaseandroid-mainline-12.0.0_r92android-mainline-12.0.0_r78android-mainline-12.0.0_r50android12-mainline-neuralnetworks-release
Change-Id: I37da9ab80b1cf86d4ebb8f3c2ca8e44e8efc2db8
-rw-r--r--profcollectd/libprofcollectd/bindings/libbase/Android.bp17
-rw-r--r--profcollectd/libprofcollectd/bindings/libbase/lib.rs31
-rw-r--r--profcollectd/libprofcollectd/bindings/libbase/properties.cpp7
-rw-r--r--profcollectd/libprofcollectd/bindings/libbase/properties.hpp9
-rw-r--r--profcollectd/libprofcollectd/bindings/libflags/Android.bp15
-rw-r--r--profcollectd/libprofcollectd/bindings/libflags/get_flags.cpp13
-rw-r--r--profcollectd/libprofcollectd/bindings/libflags/get_flags.hpp7
-rw-r--r--profcollectd/libprofcollectd/bindings/libflags/lib.rs37
-rw-r--r--profcollectd/libprofcollectd/config.rs8
-rw-r--r--profcollectd/libprofcollectd/report.rs11
-rw-r--r--profcollectd/libprofcollectd/service.rs31
-rw-r--r--simpleperf/dso_test.cpp36
-rw-r--r--simpleperf/get_test_data.h28
-rw-r--r--simpleperf/read_dex_file_test.cpp24
-rw-r--r--simpleperf/test_util.cpp41
-rw-r--r--simpleperf/testdata/base.vdex (renamed from simpleperf/testdata/base_with_cdex_v1.vdex)bin2046136 -> 2046136 bytes
-rw-r--r--simpleperf/testdata/base_with_cdex_v2.vdexbin2626976 -> 0 bytes
-rw-r--r--toolchain-extras/Android.bp3
-rw-r--r--toolchain-extras/profile-clang-extras.cpp21
19 files changed, 157 insertions, 182 deletions
diff --git a/profcollectd/libprofcollectd/bindings/libbase/Android.bp b/profcollectd/libprofcollectd/bindings/libbase/Android.bp
index b99d41d8..8e5fb1e0 100644
--- a/profcollectd/libprofcollectd/bindings/libbase/Android.bp
+++ b/profcollectd/libprofcollectd/bindings/libbase/Android.bp
@@ -26,20 +26,25 @@ package {
cc_library_static {
name: "libprofcollect_libbase",
srcs: ["properties.cpp"],
+ generated_headers: ["cxx-bridge-header"],
+ generated_sources: ["libprofcollect_libbase_bridge_code"],
}
-rust_bindgen {
- name: "libprofcollect_libbase_bindgen",
- wrapper_src: "properties.hpp",
- crate_name: "profcollect_libbase_bindgen",
- source_stem: "bindings",
+genrule {
+ name: "libprofcollect_libbase_bridge_code",
+ tools: ["cxxbridge"],
+ cmd: "$(location cxxbridge) $(in) >> $(out)",
+ srcs: ["lib.rs"],
+ out: ["libprofcollect_libbase_cxx_generated.cc"],
}
rust_library {
name: "libprofcollect_libbase_rust",
crate_name: "profcollect_libbase_rust",
srcs: ["lib.rs"],
- rlibs: ["libprofcollect_libbase_bindgen"],
+ rustlibs: [
+ "libcxx",
+ ],
static_libs: ["libprofcollect_libbase"],
shared_libs: [
"libc++",
diff --git a/profcollectd/libprofcollectd/bindings/libbase/lib.rs b/profcollectd/libprofcollectd/bindings/libbase/lib.rs
index 6ac34d58..bdd99a02 100644
--- a/profcollectd/libprofcollectd/bindings/libbase/lib.rs
+++ b/profcollectd/libprofcollectd/bindings/libbase/lib.rs
@@ -14,26 +14,21 @@
// limitations under the License.
//
-//! This module implements safe wrappers for GetProperty method from libbase.
+//! This module implements safe wrappers for GetProperty and SetProperty from libbase.
-use std::ffi::{CStr, CString};
+pub use ffi::{GetProperty, SetProperty};
-/// Returns the current value of the system property `key`,
-/// or `default_value` if the property is empty or doesn't exist.
-pub fn get_property<'a>(key: &str, default_value: &'a str) -> &'a str {
- let key = CString::new(key).unwrap();
- let default_value = CString::new(default_value).unwrap();
- unsafe {
- let cstr = profcollect_libbase_bindgen::GetProperty(key.as_ptr(), default_value.as_ptr());
- CStr::from_ptr(cstr).to_str().unwrap()
- }
-}
+/// Safe wrappers for the GetProperty and SetProperty methods from libbase.
+#[cxx::bridge]
+mod ffi {
+ unsafe extern "C++" {
+ include!("properties.hpp");
+
+ /// Returns the current value of the system property `key`,
+ /// or `default_value` if the property is empty or doesn't exist.
+ fn GetProperty(key: &str, default_value: &str) -> String;
-/// Sets the system property `key` to `value`.
-pub fn set_property(key: &str, value: &str) {
- let key = CString::new(key).unwrap();
- let value = CString::new(value).unwrap();
- unsafe {
- profcollect_libbase_bindgen::SetProperty(key.as_ptr(), value.as_ptr());
+ /// Sets the system property `key` to `value`.
+ fn SetProperty(key: &str, value: &str);
}
}
diff --git a/profcollectd/libprofcollectd/bindings/libbase/properties.cpp b/profcollectd/libprofcollectd/bindings/libbase/properties.cpp
index 01be7c73..908f19d0 100644
--- a/profcollectd/libprofcollectd/bindings/libbase/properties.cpp
+++ b/profcollectd/libprofcollectd/bindings/libbase/properties.cpp
@@ -17,11 +17,10 @@
#include "../../../../../libbase/include/android-base/properties.h"
#include "properties.hpp"
-const char* GetProperty(const char* key, const char* default_value) {
- auto v = android::base::GetProperty(std::string(key), std::string(default_value));
- return strdup(v.c_str());
+rust::String GetProperty(rust::Str key, rust::Str default_value) {
+ return android::base::GetProperty(std::string(key), std::string(default_value));
}
-void SetProperty(const char* key, const char* value) {
+void SetProperty(rust::Str key, rust::Str value) {
android::base::SetProperty(std::string(key), std::string(value));
}
diff --git a/profcollectd/libprofcollectd/bindings/libbase/properties.hpp b/profcollectd/libprofcollectd/bindings/libbase/properties.hpp
index d6785a28..c8ef1f64 100644
--- a/profcollectd/libprofcollectd/bindings/libbase/properties.hpp
+++ b/profcollectd/libprofcollectd/bindings/libbase/properties.hpp
@@ -14,6 +14,9 @@
* limitations under the License.
*/
-// C declaration for bindgen.
-const char* GetProperty(const char*, const char*);
-void SetProperty(const char*, const char*);
+#pragma once
+
+#include "rust/cxx.h"
+
+rust::String GetProperty(rust::Str, rust::Str);
+void SetProperty(rust::Str, rust::Str);
diff --git a/profcollectd/libprofcollectd/bindings/libflags/Android.bp b/profcollectd/libprofcollectd/bindings/libflags/Android.bp
index 102a6c05..fb846678 100644
--- a/profcollectd/libprofcollectd/bindings/libflags/Android.bp
+++ b/profcollectd/libprofcollectd/bindings/libflags/Android.bp
@@ -26,20 +26,23 @@ package {
cc_library_static {
name: "libprofcollect_libflags",
srcs: ["get_flags.cpp"],
+ generated_headers: ["cxx-bridge-header"],
+ generated_sources: ["libprofcollect_libflags_bridge_code"],
}
-rust_bindgen {
- name: "libprofcollect_libflags_bindgen",
- wrapper_src: "get_flags.hpp",
- crate_name: "profcollect_libflags_bindgen",
- source_stem: "bindings",
+genrule {
+ name: "libprofcollect_libflags_bridge_code",
+ tools: ["cxxbridge"],
+ cmd: "$(location cxxbridge) $(in) >> $(out)",
+ srcs: ["lib.rs"],
+ out: ["libprofcollect_libflags_cxx_generated.cc"],
}
rust_library {
name: "libprofcollect_libflags_rust",
crate_name: "profcollect_libflags_rust",
srcs: ["lib.rs"],
- rlibs: ["libprofcollect_libflags_bindgen"],
+ rustlibs: ["libcxx"],
static_libs: ["libprofcollect_libflags"],
shared_libs: [
"libc++",
diff --git a/profcollectd/libprofcollectd/bindings/libflags/get_flags.cpp b/profcollectd/libprofcollectd/bindings/libflags/get_flags.cpp
index e5ce65a1..d8bab841 100644
--- a/profcollectd/libprofcollectd/bindings/libflags/get_flags.cpp
+++ b/profcollectd/libprofcollectd/bindings/libflags/get_flags.cpp
@@ -17,12 +17,9 @@
#include "../../../../../server_configurable_flags/libflags/include/server_configurable_flags/get_flags.h"
#include "get_flags.hpp"
-const char* GetServerConfigurableFlag(const char* experiment_category_name,
- const char* experiment_flag_name,
- const char* default_value) {
- auto v = server_configurable_flags::GetServerConfigurableFlag(
- std::string(experiment_category_name),
- std::string(experiment_flag_name),
- std::string(default_value));
- return strdup(v.c_str());
+rust::String GetServerConfigurableFlag(rust::Str experiment_category_name,
+ rust::Str experiment_flag_name, rust::Str default_value) {
+ return server_configurable_flags::GetServerConfigurableFlag(std::string(experiment_category_name),
+ std::string(experiment_flag_name),
+ std::string(default_value));
}
diff --git a/profcollectd/libprofcollectd/bindings/libflags/get_flags.hpp b/profcollectd/libprofcollectd/bindings/libflags/get_flags.hpp
index ab3be989..a42c52e8 100644
--- a/profcollectd/libprofcollectd/bindings/libflags/get_flags.hpp
+++ b/profcollectd/libprofcollectd/bindings/libflags/get_flags.hpp
@@ -14,5 +14,8 @@
* limitations under the License.
*/
-// C declaration for bindgen.
-const char* GetServerConfigurableFlag(const char*, const char*, const char*);
+#pragma once
+
+#include "rust/cxx.h"
+
+rust::String GetServerConfigurableFlag(rust::Str, rust::Str, rust::Str);
diff --git a/profcollectd/libprofcollectd/bindings/libflags/lib.rs b/profcollectd/libprofcollectd/bindings/libflags/lib.rs
index c8875cb1..c6435bbd 100644
--- a/profcollectd/libprofcollectd/bindings/libflags/lib.rs
+++ b/profcollectd/libprofcollectd/bindings/libflags/lib.rs
@@ -17,27 +17,22 @@
//! This module implements safe wrappers for GetServerConfigurableFlag method
//! from libflags.
-use std::ffi::{CStr, CString};
+pub use ffi::GetServerConfigurableFlag;
-/// Use the category name and flag name registered in SettingsToPropertiesMapper.java
-/// to query the experiment flag value. This method will return default_value if
-/// querying fails.
-/// Note that for flags from Settings.Global, experiment_category_name should
-/// always be global_settings.
-pub fn get_server_configurable_flag<'a>(
- experiment_category_name: &str,
- experiment_flag_name: &str,
- default_value: &'a str,
-) -> &'a str {
- let experiment_category_name = CString::new(experiment_category_name).unwrap();
- let experiment_flag_name = CString::new(experiment_flag_name).unwrap();
- let default_value = CString::new(default_value).unwrap();
- unsafe {
- let cstr = profcollect_libflags_bindgen::GetServerConfigurableFlag(
- experiment_category_name.as_ptr(),
- experiment_flag_name.as_ptr(),
- default_value.as_ptr(),
- );
- CStr::from_ptr(cstr).to_str().unwrap()
+#[cxx::bridge]
+mod ffi {
+ unsafe extern "C++" {
+ include!("get_flags.hpp");
+
+ /// Use the category name and flag name registered in SettingsToPropertiesMapper.java
+ /// to query the experiment flag value. This method will return default_value if
+ /// querying fails.
+ /// Note that for flags from Settings.Global, experiment_category_name should
+ /// always be global_settings.
+ fn GetServerConfigurableFlag(
+ experiment_category_name: &str,
+ experiment_flag_name: &str,
+ default_value: &str,
+ ) -> String;
}
}
diff --git a/profcollectd/libprofcollectd/config.rs b/profcollectd/libprofcollectd/config.rs
index d2850e82..e8afb37f 100644
--- a/profcollectd/libprofcollectd/config.rs
+++ b/profcollectd/libprofcollectd/config.rs
@@ -29,6 +29,8 @@ use std::time::Duration;
const PROFCOLLECT_CONFIG_NAMESPACE: &str = "profcollect_native_boot";
const PROFCOLLECT_NODE_ID_PROPERTY: &str = "persist.profcollectd.node_id";
+pub const REPORT_RETENTION_SECS: u64 = 14 * 24 * 60 * 60; // 14 days.
+
lazy_static! {
pub static ref TRACE_OUTPUT_DIR: &'static Path = Path::new("/data/misc/profcollectd/trace/");
pub static ref PROFILE_OUTPUT_DIR: &'static Path = Path::new("/data/misc/profcollectd/output/");
@@ -105,7 +107,7 @@ where
T::Err: Error + Send + Sync + 'static,
{
let default_value = default_value.to_string();
- let config = profcollect_libflags_rust::get_server_configurable_flag(
+ let config = profcollect_libflags_rust::GetServerConfigurableFlag(
&PROFCOLLECT_CONFIG_NAMESPACE,
&key,
&default_value,
@@ -119,7 +121,7 @@ where
T::Err: Error + Send + Sync + 'static,
{
let default_value = default_value.to_string();
- let value = profcollect_libbase_rust::get_property(&key, &default_value);
+ let value = profcollect_libbase_rust::GetProperty(&key, &default_value);
Ok(T::from_str(&value)?)
}
@@ -128,7 +130,7 @@ where
T: ToString,
{
let value = value.to_string();
- profcollect_libbase_rust::set_property(&key, &value);
+ profcollect_libbase_rust::SetProperty(&key, &value);
}
fn generate_random_node_id() -> MacAddr6 {
diff --git a/profcollectd/libprofcollectd/report.rs b/profcollectd/libprofcollectd/report.rs
index c37993b7..a67d500b 100644
--- a/profcollectd/libprofcollectd/report.rs
+++ b/profcollectd/libprofcollectd/report.rs
@@ -23,7 +23,7 @@ use std::fs::{self, File, Permissions};
use std::io::{Read, Write};
use std::os::unix::fs::PermissionsExt;
use std::path::{Path, PathBuf};
-use std::time::SystemTime;
+use std::time::{Duration, SystemTime};
use uuid::v1::{Context, Timestamp};
use uuid::Uuid;
use zip::write::FileOptions;
@@ -82,3 +82,12 @@ fn get_report_filename(node_id: &MacAddr6) -> Result<String> {
let uuid = Uuid::new_v1(ts, &node_id.as_bytes())?;
Ok(uuid.to_string())
}
+
+/// Get report creation timestamp through its filename (version 1 UUID).
+pub fn get_report_ts(filename: &str) -> Result<SystemTime> {
+ let uuid_ts = Uuid::parse_str(filename)?
+ .to_timestamp()
+ .ok_or_else(|| anyhow!("filename is not a valid V1 UUID."))?
+ .to_unix();
+ Ok(SystemTime::UNIX_EPOCH + Duration::new(uuid_ts.0, uuid_ts.1))
+}
diff --git a/profcollectd/libprofcollectd/service.rs b/profcollectd/libprofcollectd/service.rs
index 0b9cca1e..04f30f89 100644
--- a/profcollectd/libprofcollectd/service.rs
+++ b/profcollectd/libprofcollectd/service.rs
@@ -21,16 +21,17 @@ use binder::public_api::Result as BinderResult;
use binder::Status;
use profcollectd_aidl_interface::aidl::com::android::server::profcollect::IProfCollectd::IProfCollectd;
use std::ffi::CString;
-use std::fs::{copy, create_dir, read_to_string, remove_dir_all, remove_file, write};
+use std::fs::{copy, create_dir, read_dir, read_to_string, remove_dir_all, remove_file, write};
use std::path::PathBuf;
use std::str::FromStr;
use std::sync::{Mutex, MutexGuard};
+use std::time::Duration;
use crate::config::{
Config, BETTERBUG_CACHE_DIR_PREFIX, BETTERBUG_CACHE_DIR_SUFFIX, CONFIG_FILE,
- PROFILE_OUTPUT_DIR, REPORT_OUTPUT_DIR, TRACE_OUTPUT_DIR,
+ PROFILE_OUTPUT_DIR, REPORT_OUTPUT_DIR, REPORT_RETENTION_SECS, TRACE_OUTPUT_DIR,
};
-use crate::report::pack_report;
+use crate::report::{get_report_ts, pack_report};
use crate::scheduler::Scheduler;
fn err_to_binder_status(msg: Error) -> Status {
@@ -155,6 +156,30 @@ impl ProfcollectdBinderService {
write(*CONFIG_FILE, &new_config.to_string())?;
}
+ // Clear profile reports out of rentention period.
+ for report in read_dir(*REPORT_OUTPUT_DIR)? {
+ let report = report?.path();
+ let report_name = report
+ .file_stem()
+ .and_then(|f| f.to_str())
+ .ok_or_else(|| anyhow!("Malformed path {}", report.display()))?;
+ let report_ts = get_report_ts(report_name);
+ if let Err(e) = report_ts {
+ log::error!(
+ "Cannot decode creation timestamp for report {}, caused by {}, deleting",
+ report_name,
+ e
+ );
+ remove_file(report)?;
+ continue;
+ }
+ let report_age = report_ts.unwrap().elapsed()?;
+ if report_age > Duration::from_secs(REPORT_RETENTION_SECS) {
+ log::info!("Report {} past rentention period, deleting", report_name);
+ remove_file(report)?;
+ }
+ }
+
Ok(ProfcollectdBinderService {
lock: Mutex::new(Lock { scheduler: new_scheduler, config: new_config }),
})
diff --git a/simpleperf/dso_test.cpp b/simpleperf/dso_test.cpp
index c8618036..02958ce6 100644
--- a/simpleperf/dso_test.cpp
+++ b/simpleperf/dso_test.cpp
@@ -152,28 +152,24 @@ TEST(DebugElfFileFinder, build_id_mismatch) {
TEST(dso, dex_file_dso) {
#if defined(__linux__)
for (DsoType dso_type : {DSO_DEX_FILE, DSO_ELF_FILE}) {
- for (const DexFileTestData& entry : dex_file_test_data) {
- if (entry.filename == "base_with_cdex_v1.vdex") {
- continue; // TODO: reenable it.
- }
- std::unique_ptr<Dso> dso = Dso::CreateDso(dso_type, GetTestData(entry.filename));
- ASSERT_TRUE(dso);
- dso->AddDexFileOffset(entry.dexfile_offset);
- ASSERT_EQ(DSO_DEX_FILE, dso->type());
- const Symbol* symbol = dso->FindSymbol(entry.symbol_addr);
- ASSERT_NE(symbol, nullptr);
- ASSERT_EQ(symbol->addr, entry.symbol_addr);
- ASSERT_EQ(symbol->len, entry.symbol_len);
- ASSERT_STREQ(symbol->DemangledName(), entry.symbol_name.c_str());
- uint64_t min_vaddr;
- uint64_t file_offset_of_min_vaddr;
- dso->GetMinExecutableVaddr(&min_vaddr, &file_offset_of_min_vaddr);
- ASSERT_EQ(min_vaddr, 0);
- ASSERT_EQ(file_offset_of_min_vaddr, 0);
- }
+ std::unique_ptr<Dso> dso = Dso::CreateDso(dso_type, GetTestData("base.vdex"));
+ ASSERT_TRUE(dso);
+ dso->AddDexFileOffset(0x28);
+ ASSERT_EQ(DSO_DEX_FILE, dso->type());
+ const Symbol* symbol = dso->FindSymbol(0x6c77e);
+ ASSERT_NE(symbol, nullptr);
+ ASSERT_EQ(symbol->addr, static_cast<uint64_t>(0x6c77e));
+ ASSERT_EQ(symbol->len, static_cast<uint64_t>(0x16));
+ ASSERT_STREQ(symbol->DemangledName(),
+ "com.example.simpleperf.simpleperfexamplewithnative.MixActivity$1.run");
+ uint64_t min_vaddr;
+ uint64_t file_offset_of_min_vaddr;
+ dso->GetMinExecutableVaddr(&min_vaddr, &file_offset_of_min_vaddr);
+ ASSERT_EQ(min_vaddr, 0);
+ ASSERT_EQ(file_offset_of_min_vaddr, 0);
// Don't crash on not exist zip entry.
- std::unique_ptr<Dso> dso = Dso::CreateDso(dso_type, GetTestData("base.zip!/not_exist_entry"));
+ dso = Dso::CreateDso(dso_type, GetTestData("base.zip!/not_exist_entry"));
ASSERT_TRUE(dso);
ASSERT_EQ(nullptr, dso->FindSymbol(0));
}
diff --git a/simpleperf/get_test_data.h b/simpleperf/get_test_data.h
index b6a7999e..1ef663b9 100644
--- a/simpleperf/get_test_data.h
+++ b/simpleperf/get_test_data.h
@@ -149,32 +149,4 @@ static const std::string PERF_DATA_WITH_IP_ZERO_IN_CALLCHAIN =
// generated by `simpleperf record -e cs-etm:u ./etm_test_loop`
static const std::string PERF_DATA_ETM_TEST_LOOP = "etm/perf.data";
-struct DexFileTestData {
- std::string filename;
- uint64_t dexfile_offset;
- size_t symbol_count;
- // One symbol in the dex file.
- uint64_t symbol_addr;
- uint64_t symbol_len;
- std::string symbol_name;
-};
-
-static DexFileTestData dex_file_test_data[] = {
- DexFileTestData{
- "base_with_cdex_v1.vdex",
- 0x28,
- 12435,
- 0x6c77e,
- 0x16,
- "com.example.simpleperf.simpleperfexamplewithnative.MixActivity$1.run",
- },
- DexFileTestData{
- "base_with_cdex_v2.vdex",
- 0x40,
- 16891,
- 0x169b84,
- 0x25a,
- "com.android.calculator2.Calculator.onButtonClick",
- }};
-
#endif // SIMPLE_PERF_GET_TEST_DATA_H_
diff --git a/simpleperf/read_dex_file_test.cpp b/simpleperf/read_dex_file_test.cpp
index fc72ceda..843a964c 100644
--- a/simpleperf/read_dex_file_test.cpp
+++ b/simpleperf/read_dex_file_test.cpp
@@ -32,18 +32,12 @@ TEST(read_dex_file, smoke) {
auto symbol_callback = [&](DexFileSymbol* symbol) {
symbols.emplace_back(symbol->name, symbol->addr, symbol->size);
};
- for (DexFileTestData& entry : dex_file_test_data) {
- if (entry.filename == "base_with_cdex_v1.vdex") {
- continue; // TODO: reenable it.
- }
- ASSERT_TRUE(ReadSymbolsFromDexFile(GetTestData(entry.filename), {entry.dexfile_offset},
- symbol_callback));
- ASSERT_EQ(entry.symbol_count, symbols.size());
- auto it = std::find_if(symbols.begin(), symbols.end(),
- [&](const Symbol& symbol) { return symbol.addr == entry.symbol_addr; });
- ASSERT_NE(it, symbols.end());
- ASSERT_EQ(it->addr, entry.symbol_addr);
- ASSERT_EQ(it->len, entry.symbol_len);
- ASSERT_STREQ(it->Name(), entry.symbol_name.c_str());
- }
-} \ No newline at end of file
+ ASSERT_TRUE(ReadSymbolsFromDexFile(GetTestData("base.vdex"), {0x28}, symbol_callback));
+ ASSERT_EQ(12435u, symbols.size());
+ auto it = std::find_if(symbols.begin(), symbols.end(),
+ [](const Symbol& symbol) { return symbol.addr == 0x6c77e; });
+ ASSERT_NE(it, symbols.end());
+ ASSERT_EQ(it->addr, 0x6c77e);
+ ASSERT_EQ(it->len, 0x16);
+ ASSERT_STREQ(it->Name(), "com.example.simpleperf.simpleperfexamplewithnative.MixActivity$1.run");
+}
diff --git a/simpleperf/test_util.cpp b/simpleperf/test_util.cpp
index c2a21960..547eaf90 100644
--- a/simpleperf/test_util.cpp
+++ b/simpleperf/test_util.cpp
@@ -48,29 +48,6 @@ bool IsInNativeAbi() {
return in_native_abi == 1;
}
-static bool InCloudAndroid() {
-#if defined(__i386__) || defined(__x86_64__)
-#if defined(__ANDROID__)
- std::string prop_value = android::base::GetProperty("ro.build.flavor", "");
- if (android::base::StartsWith(prop_value, "cf_x86_phone") ||
- android::base::StartsWith(prop_value, "aosp_cf_x86_phone") ||
- android::base::StartsWith(prop_value, "cf_x86_64_phone") ||
- android::base::StartsWith(prop_value, "aosp_cf_x86_64_phone")) {
- return true;
- }
- // aosp_x86* builds may also run on cloud Android. Detect it by checking
- /// if cpu-cycles isn't supported.
- if (android::base::StartsWith(prop_value, "aosp_x86")) {
- const simpleperf::EventType* type = simpleperf::FindEventTypeByName("cpu-cycles", false);
- CHECK(type != nullptr);
- perf_event_attr attr = CreateDefaultPerfEventAttr(*type);
- return !IsEventAttrSupported(attr, "cpu-cycles");
- }
-#endif
-#endif
- return false;
-}
-
#if defined(__arm__)
// Check if we can get a non-zero instruction event count by monitoring current thread.
static bool HasNonZeroInstructionEventCount() {
@@ -96,18 +73,28 @@ static bool HasNonZeroInstructionEventCount() {
#endif // defined(__arm__)
bool HasHardwareCounter() {
+#if defined(__linux__)
static int has_hw_counter = -1;
if (has_hw_counter == -1) {
- // Cloud Android doesn't have hardware counters.
- has_hw_counter = InCloudAndroid() ? 0 : 1;
-#if defined(__arm__)
+ has_hw_counter = 1;
+#if defined(__x86__) || defined(__x86_64__)
+ // On x86 and x86_64, it's likely to run on an emulator or vm without hardware perf counters.
+ // It's hard to enumerate them all. So check the support at runtime.
+ const simpleperf::EventType* type = simpleperf::FindEventTypeByName("cpu-cycles", false);
+ CHECK(type != nullptr);
+ perf_event_attr attr = CreateDefaultPerfEventAttr(*type);
+ has_hw_counter = IsEventAttrSupported(attr, "cpu-cycles") ? 1 : 0;
+#elif defined(__arm__)
// For arm32 devices, external non-invasive debug signal controls PMU counters. Once it is
// disabled for security reason, we always get zero values for PMU counters. And we want to
// skip hardware counter tests once we detect it.
has_hw_counter &= HasNonZeroInstructionEventCount() ? 1 : 0;
-#endif
+#endif // defined(__arm__)
}
return has_hw_counter == 1;
+#else // defined(__linux__)
+ return false;
+#endif // defined(__linux__)
}
bool HasPmuCounter() {
diff --git a/simpleperf/testdata/base_with_cdex_v1.vdex b/simpleperf/testdata/base.vdex
index b0ea0184..b0ea0184 100644
--- a/simpleperf/testdata/base_with_cdex_v1.vdex
+++ b/simpleperf/testdata/base.vdex
Binary files differ
diff --git a/simpleperf/testdata/base_with_cdex_v2.vdex b/simpleperf/testdata/base_with_cdex_v2.vdex
deleted file mode 100644
index 16ecc6fd..00000000
--- a/simpleperf/testdata/base_with_cdex_v2.vdex
+++ /dev/null
Binary files differ
diff --git a/toolchain-extras/Android.bp b/toolchain-extras/Android.bp
index 007817ec..220f3e34 100644
--- a/toolchain-extras/Android.bp
+++ b/toolchain-extras/Android.bp
@@ -129,11 +129,10 @@ cc_test {
srcs: [
"profile-clang-extras-test.cpp",
],
- static_libs: [
+ whole_static_libs: [
"libprofile-clang-extras",
],
ldflags: [
- "-uinit_profile_extras",
"-Wl,--wrap,open",
],
native_coverage: false,
diff --git a/toolchain-extras/profile-clang-extras.cpp b/toolchain-extras/profile-clang-extras.cpp
index 89c18b2a..bb713e18 100644
--- a/toolchain-extras/profile-clang-extras.cpp
+++ b/toolchain-extras/profile-clang-extras.cpp
@@ -36,24 +36,15 @@ static void llvm_signal_handler(__unused int signum) {
}
}
-__attribute__((weak)) int init_profile_extras_once = 0;
-
// Initialize libprofile-extras:
-// - Install a signal handler that triggers __llvm_profile_write_file on <COVERAGE_FLUSH_SIGNAL>.
-//
-// We want this initializer to run during load time.
//
-// Just marking init_profile_extras() with __attribute__((constructor)) isn't
-// enough since the linker drops it from its output since no other symbol from
-// this static library is referenced.
+// - Install a signal handler that triggers __llvm_profile_write_file on
+// <COVERAGE_FLUSH_SIGNAL>.
//
-// We force the linker to include init_profile_extras() by passing
-// '-uinit_profile_extras' to the linker (in build/soong).
-__attribute__((constructor)) int init_profile_extras(void) {
- if (init_profile_extras_once)
- return 0;
- init_profile_extras_once = 1;
-
+// We want this initializer to run during load time. In addition to marking
+// this function as a constructor, we link this library with `--whole-archive`
+// to force this function to be included in the output.
+static __attribute__((constructor)) int init_profile_extras(void) {
if (chained_signal_handler != SIG_ERR) {
return -1;
}