summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pagecache/pagecache.py50
-rw-r--r--profcollectd/README.md11
-rw-r--r--profcollectd/libprofcollectd/config.rs19
-rw-r--r--profcollectd/libprofcollectd/lib.rs2
-rw-r--r--profcollectd/profcollectd.rc4
-rw-r--r--simpleperf/cmd_inject.cpp76
-rw-r--r--simpleperf/cmd_record.cpp2
-rwxr-xr-xtools/check_elf_alignment.sh18
8 files changed, 104 insertions, 78 deletions
diff --git a/pagecache/pagecache.py b/pagecache/pagecache.py
index 3f96a5d1..808812c5 100644
--- a/pagecache/pagecache.py
+++ b/pagecache/pagecache.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
import curses
import operator
@@ -8,7 +8,7 @@ import re
import subprocess
import sys
import threading
-import Queue
+import queue
STATS_UPDATE_INTERVAL = 0.2
PAGE_SIZE = 4096
@@ -68,21 +68,21 @@ class PagecacheStats():
def print_stats(self):
# Create new merged dict
- sorted_added = sorted(self._file_pages.items(), key=operator.itemgetter(1), reverse=True)
+ sorted_added = sorted(list(self._file_pages.items()), key=operator.itemgetter(1), reverse=True)
row_format = "{:<70}{:<12}{:<14}{:<9}"
- print row_format.format('NAME', 'ADDED (MB)', 'REMOVED (MB)', 'SIZE (MB)')
+ print(row_format.format('NAME', 'ADDED (MB)', 'REMOVED (MB)', 'SIZE (MB)'))
for filename, added in sorted_added:
filesize = self._file_size[filename]
added = self._file_pages[filename][0]
removed = self._file_pages[filename][1]
- if (filename > 64):
+ if (len(filename) > 64):
filename = filename[-64:]
- print row_format.format(filename, self.pages_to_mb(added), self.pages_to_mb(removed), self.bytes_to_mb(filesize))
+ print(row_format.format(filename, self.pages_to_mb(added), self.pages_to_mb(removed), self.bytes_to_mb(filesize)))
- print row_format.format('TOTAL', self.pages_to_mb(self._total_pages_added), self.pages_to_mb(self._total_pages_removed), '')
+ print(row_format.format('TOTAL', self.pages_to_mb(self._total_pages_added), self.pages_to_mb(self._total_pages_removed), ''))
def print_stats_curses(self, pad):
- sorted_added = sorted(self._file_pages.items(), key=operator.itemgetter(1), reverse=True)
+ sorted_added = sorted(list(self._file_pages.items()), key=operator.itemgetter(1), reverse=True)
height, width = pad.getmaxyx()
pad.clear()
pad.addstr(0, 2, 'NAME'.ljust(68), curses.A_REVERSE)
@@ -94,7 +94,7 @@ class PagecacheStats():
filesize = self._file_size[filename]
added = self._file_pages[filename][0]
removed = self._file_pages[filename][1]
- if (filename > 64):
+ if (len(filename) > 64):
filename = filename[-64:]
pad.addstr(y, 2, filename)
pad.addstr(y, 70, self.pages_to_mb(added).rjust(10))
@@ -122,7 +122,7 @@ class FileReaderThread(threading.Thread):
Args:
file_object: The file or pipe to read from.
- output_queue: A Queue.Queue object that will receive the data
+ output_queue: A queue.Queue object that will receive the data
text_file: If True, the file will be read one line at a time, and
chunk_size will be ignored. If False, line breaks are ignored and
chunk_size must be set to a positive integer.
@@ -204,10 +204,10 @@ class AdbUtils():
shell=False, universal_newlines=True)
except OSError as error:
# This usually means that the adb executable was not found in the path.
- print >> sys.stderr, ('\nThe command "%s" failed with the following error:'
- % ' '.join(adb_command))
- print >> sys.stderr, ' %s' % str(error)
- print >> sys.stderr, 'Is adb in your path?'
+ print('\nThe command "%s" failed with the following error:'
+ % ' '.join(adb_command), file=sys.stderr)
+ print(' %s' % str(error), file=sys.stderr)
+ print('Is adb in your path?', file=sys.stderr)
adb_return_code = error.errno
adb_output = error
except subprocess.CalledProcessError as error:
@@ -265,11 +265,11 @@ def get_inode_data(datafile, dumpfile, adb_serial):
'find /apex /system /system_ext /product /data /vendor ' +
'-exec stat -c "%d %i %s %n" {} \;', adb_serial)
if stat_dump is None:
- print 'Could not retrieve inode data from device.'
+ print('Could not retrieve inode data from device.')
sys.exit(1)
if dumpfile is not None:
- print 'Storing inode data in ' + dumpfile
+ print('Storing inode data in ' + dumpfile)
f = open(dumpfile, 'w')
f.write(stat_dump)
f.close()
@@ -285,8 +285,8 @@ def read_and_parse_trace_file(trace_file, pagecache_stats, app_name):
def read_and_parse_trace_data_live(stdout, stderr, pagecache_stats, app_name):
# Start reading trace data
- stdout_queue = Queue.Queue(maxsize=128)
- stderr_queue = Queue.Queue()
+ stdout_queue = queue.Queue(maxsize=128)
+ stderr_queue = queue.Queue()
stdout_thread = FileReaderThread(stdout, stdout_queue,
text_file=True, chunk_size=64)
@@ -316,13 +316,13 @@ def read_and_parse_trace_data_live(stdout, stderr, pagecache_stats, app_name):
not stdout_queue.empty() or not stderr_queue.empty()):
while not stderr_queue.empty():
# Pass along errors from adb.
- line = stderr_queue.get()
+ line = stderr_queue.get().decode("utf-8")
sys.stderr.write(line)
while True:
try:
- line = stdout_queue.get(True, STATS_UPDATE_INTERVAL)
+ line = stdout_queue.get(True, STATS_UPDATE_INTERVAL).decode("utf-8")
parse_atrace_line(line, pagecache_stats, app_name)
- except Queue.Empty:
+ except (queue.Empty, KeyboardInterrupt):
break
key = ''
@@ -335,9 +335,9 @@ def read_and_parse_trace_data_live(stdout, stderr, pagecache_stats, app_name):
pagecache_stats.reset_stats()
pagecache_stats.print_stats_curses(pagecache_pad)
- except Exception, e:
+ except Exception as e:
curses.endwin()
- print e
+ print(e)
finally:
curses.endwin()
# The threads should already have stopped, so this is just for cleanup.
@@ -383,7 +383,7 @@ def main():
if options.trace_file is not None:
if not os.path.isfile(options.trace_file):
- print >> sys.stderr, ('Couldn\'t load trace file.')
+ print('Couldn\'t load trace file.', file=sys.stderr)
sys.exit(1)
trace_file = open(options.trace_file, 'r')
read_and_parse_trace_file(trace_file, pagecache_stats, options.app_name)
@@ -396,7 +396,7 @@ def main():
atrace = subprocess.Popen(trace_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
except OSError as error:
- print >> sys.stderr, ('The command failed')
+ print('The command failed', file=sys.stderr)
sys.exit(1)
read_and_parse_trace_data_live(atrace.stdout, atrace.stderr, pagecache_stats, options.app_name)
diff --git a/profcollectd/README.md b/profcollectd/README.md
index e9066000..1017e7e4 100644
--- a/profcollectd/README.md
+++ b/profcollectd/README.md
@@ -39,21 +39,18 @@ Setting the frequency value to `0` disables collection for the corresponding eve
#### Custom configuration
-In adb root:
+Under adb root:
```
# Record every 60s (By default, record every 10m). The actual interval will be longer than the
# set value if the device goes to hibernation.
-oriole:/ # setprop persist.device_config.profcollect_native_boot.collection_interval 60
+oriole:/ # device_config put profcollect_native_boot collection_interval 60
# Each time recording, record ETM data for 1s (By default, it's 0.5s).
-oriole:/ # setprop persist.device_config.profcollect_native_boot.sampling_period 1000
+oriole:/ # device_config put profcollect_native_boot sampling_period 1000
# Set ETM data storage limit to 50G (By default, it is 512M).
-oriole:/ # setprop persist.device_config.profcollect_native_boot.max_trace_limit 53687091200
-
-# Enable ETM data collection (By default, it's decided by the server).
-oriole:/ # setprop persist.device_config.profcollect_native_boot.enabled true
+oriole:/ # device_config put profcollect_native_boot max_trace_limit 53687091200
# After adjusting configuration, need to restart profcollectd
oriole:/ # setprop ctl.stop profcollectd
diff --git a/profcollectd/libprofcollectd/config.rs b/profcollectd/libprofcollectd/config.rs
index 8a6c9e4f..0a1a9ad9 100644
--- a/profcollectd/libprofcollectd/config.rs
+++ b/profcollectd/libprofcollectd/config.rs
@@ -24,6 +24,7 @@ use serde::{Deserialize, Serialize};
use std::error::Error;
use std::fs::{read_dir, remove_file};
use std::path::Path;
+use std::process::Command;
use std::str::FromStr;
use std::time::Duration;
@@ -61,6 +62,8 @@ pub struct Config {
pub binary_filter: String,
/// Maximum size of the trace directory.
pub max_trace_limit: u64,
+ /// The kernel release version
+ pub kernel_release: String,
}
impl Config {
@@ -78,13 +81,14 @@ impl Config {
"max_trace_limit",
/* 512MB */ 512 * 1024 * 1024,
)?,
+ kernel_release: get_kernel_release(),
})
}
}
-impl ToString for Config {
- fn to_string(&self) -> String {
- serde_json::to_string(self).expect("Failed to deserialise configuration.")
+impl std::fmt::Display for Config {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{}", serde_json::to_string(self).expect("Failed to deserialise configuration."))
}
}
@@ -151,6 +155,15 @@ fn generate_random_node_id() -> MacAddr6 {
MacAddr6::from(node_id)
}
+fn get_kernel_release() -> String {
+ match Command::new("uname").args(["-r"]).output() {
+ Ok(output) if output.status.success() => {
+ String::from_utf8_lossy(&output.stdout).trim().to_string()
+ }
+ _ => String::new(),
+ }
+}
+
pub fn clear_data() -> Result<()> {
fn remove_files(path: &Path) -> Result<()> {
read_dir(path)?
diff --git a/profcollectd/libprofcollectd/lib.rs b/profcollectd/libprofcollectd/lib.rs
index c8e39753..f0d32a8b 100644
--- a/profcollectd/libprofcollectd/lib.rs
+++ b/profcollectd/libprofcollectd/lib.rs
@@ -85,7 +85,7 @@ pub fn init_service(schedule_now: bool) -> Result<()> {
}
fn get_profcollectd_service() -> Result<binder::Strong<dyn IProfCollectd::IProfCollectd>> {
- binder::get_interface(PROFCOLLECTD_SERVICE_NAME)
+ binder::wait_for_interface(PROFCOLLECTD_SERVICE_NAME)
.context("Failed to get profcollectd binder service, is profcollectd running?")
}
diff --git a/profcollectd/profcollectd.rc b/profcollectd/profcollectd.rc
index 312c7003..faeb4124 100644
--- a/profcollectd/profcollectd.rc
+++ b/profcollectd/profcollectd.rc
@@ -13,8 +13,8 @@ on post-fs-data
mkdir /data/misc/profcollectd/output 0770 shell shell
mkdir /data/misc/profcollectd/report 0770 shell shell
-on boot && property:persist.device_config.profcollect_native_boot.enabled=true
+on boot && property:persist.device_config.aconfig_flags.profcollect_native_boot.enabled=true
start profcollectd
-on boot && property:persist.device_config.profcollect_native_boot.enabled=
+on boot && property:persist.device_config.aconfig_flags.profcollect_native_boot.enabled=
exec_background - root shell -- /system/bin/profcollectctl reset
diff --git a/simpleperf/cmd_inject.cpp b/simpleperf/cmd_inject.cpp
index 182f4fd2..6798a32a 100644
--- a/simpleperf/cmd_inject.cpp
+++ b/simpleperf/cmd_inject.cpp
@@ -683,46 +683,52 @@ class AutoFDOWriter {
const AutoFDOBinaryInfo& binary = binary_map_[key];
// AutoFDO text format needs file_offsets instead of virtual addrs in a binary. And it uses
// below formula: vaddr = file_offset + GetFirstLoadSegmentVaddr().
- uint64_t first_load_segment_addr = binary.first_load_segment_addr;
-
- auto to_offset = [&](uint64_t vaddr) -> uint64_t {
- if (vaddr == 0) {
- return 0;
+ uint64_t base_addr = binary.first_load_segment_addr;
+
+ // Write range_count_map. Sort the output by addrs.
+ std::vector<std::pair<AddrPair, uint64_t>> range_counts;
+ for (std::pair<AddrPair, uint64_t> p : binary.range_count_map) {
+ if (p.first.first >= base_addr && p.first.second >= base_addr) {
+ p.first.first -= base_addr;
+ p.first.second -= base_addr;
+ range_counts.emplace_back(p);
}
- CHECK_GE(vaddr, first_load_segment_addr);
- return vaddr - first_load_segment_addr;
- };
-
- // Write range_count_map.
- std::map<AddrPair, uint64_t> range_count_map(binary.range_count_map.begin(),
- binary.range_count_map.end());
- fprintf(output_fp.get(), "%zu\n", range_count_map.size());
- for (const auto& pair2 : range_count_map) {
- const AddrPair& addr_range = pair2.first;
- uint64_t count = pair2.second;
-
- fprintf(output_fp.get(), "%" PRIx64 "-%" PRIx64 ":%" PRIu64 "\n",
- to_offset(addr_range.first), to_offset(addr_range.second), count);
}
-
- // Write addr_count_map.
- std::map<uint64_t, uint64_t> address_count_map(binary.address_count_map.begin(),
- binary.address_count_map.end());
- fprintf(output_fp.get(), "%zu\n", address_count_map.size());
- for (const auto& [addr, count] : address_count_map) {
- fprintf(output_fp.get(), "%" PRIx64 ":%" PRIu64 "\n", to_offset(addr), count);
+ std::sort(range_counts.begin(), range_counts.end());
+ fprintf(output_fp.get(), "%zu\n", range_counts.size());
+ for (const auto& p : range_counts) {
+ fprintf(output_fp.get(), "%" PRIx64 "-%" PRIx64 ":%" PRIu64 "\n", p.first.first,
+ p.first.second, p.second);
}
- // Write branch_count_map.
- std::map<AddrPair, uint64_t> branch_count_map(binary.branch_count_map.begin(),
- binary.branch_count_map.end());
- fprintf(output_fp.get(), "%zu\n", branch_count_map.size());
- for (const auto& pair2 : branch_count_map) {
- const AddrPair& branch = pair2.first;
- uint64_t count = pair2.second;
+ // Write addr_count_map. Sort the output by addrs.
+ std::vector<std::pair<uint64_t, uint64_t>> address_counts;
+ for (std::pair<uint64_t, uint64_t> p : binary.address_count_map) {
+ if (p.first >= base_addr) {
+ p.first -= base_addr;
+ address_counts.emplace_back(p);
+ }
+ }
+ std::sort(address_counts.begin(), address_counts.end());
+ fprintf(output_fp.get(), "%zu\n", address_counts.size());
+ for (const auto& p : address_counts) {
+ fprintf(output_fp.get(), "%" PRIx64 ":%" PRIu64 "\n", p.first, p.second);
+ }
- fprintf(output_fp.get(), "%" PRIx64 "->%" PRIx64 ":%" PRIu64 "\n", to_offset(branch.first),
- to_offset(branch.second), count);
+ // Write branch_count_map. Sort the output by addrs.
+ std::vector<std::pair<AddrPair, uint64_t>> branch_counts;
+ for (std::pair<AddrPair, uint64_t> p : binary.branch_count_map) {
+ if (p.first.first >= base_addr) {
+ p.first.first -= base_addr;
+ p.first.second = (p.first.second >= base_addr) ? (p.first.second - base_addr) : 0;
+ branch_counts.emplace_back(p);
+ }
+ }
+ std::sort(branch_counts.begin(), branch_counts.end());
+ fprintf(output_fp.get(), "%zu\n", branch_counts.size());
+ for (const auto& p : branch_counts) {
+ fprintf(output_fp.get(), "%" PRIx64 "->%" PRIx64 ":%" PRIu64 "\n", p.first.first,
+ p.first.second, p.second);
}
// Write the binary path in comment.
diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp
index e08b153b..cb9ad884 100644
--- a/simpleperf/cmd_record.cpp
+++ b/simpleperf/cmd_record.cpp
@@ -1057,7 +1057,7 @@ bool RecordCommand::ParseOptions(const std::vector<std::string>& args,
etm_branch_list_generator_ = ETMBranchListGenerator::Create(system_wide_collection_);
}
uint32_t interval = 0;
- if (options.PullUintValue("--etm-flush-interval", &interval)) {
+ if (options.PullUintValue("--etm-flush-interval", &interval) && interval != 0) {
etm_flush_interval_ = std::chrono::milliseconds(interval);
}
diff --git a/tools/check_elf_alignment.sh b/tools/check_elf_alignment.sh
index b74f34ae..6cf9f92b 100755
--- a/tools/check_elf_alignment.sh
+++ b/tools/check_elf_alignment.sh
@@ -16,7 +16,7 @@ usage() {
echo "Shared libraries are reported ALIGNED when their ELF regions are"
echo "16 KB or 64 KB aligned. Otherwise they are reported as UNALIGNED."
echo
- echo "Usage: ${progname} [input-path|input-APK]"
+ echo "Usage: ${progname} [input-path|input-APK|input-APEX]"
}
if [ ${#} -ne 1 ]; then
@@ -61,6 +61,15 @@ if [[ "${dir}" == *.apk ]]; then
dir="${tmp}"
fi
+if [[ "${dir}" == *.apex ]]; then
+ trap 'cleanup_trap' EXIT
+
+ dir_filename=$(basename "${dir}")
+ tmp=$(mktemp -d -t "${dir_filename%.apex}_out_XXXXX")
+ deapexer extract "${dir}" "${tmp}" >/dev/null 2>&1
+ dir="${tmp}"
+fi
+
RED="\e[31m"
GREEN="\e[32m"
ENDCOLOR="\e[0m"
@@ -70,11 +79,12 @@ unaligned_libs=()
echo
echo "=== ELF alignment ==="
-matches="$(find "${dir}" -name "*.so" -type f)"
+matches="$(find "${dir}" -type f \( -name "*.so" -or -executable \))"
IFS=$'\n'
for match in $matches; do
- res="$(objdump -p ${match} | grep LOAD | awk '{ print $NF }' | head -1)"
- if [[ $res =~ "2**14" ]] || [[ $res =~ "2**16" ]]; then
+ [[ $(file "${match}") == *"ELF"* ]] || continue
+ res="$(objdump -p "${match}" | grep LOAD | awk '{ print $NF }' | head -1)"
+ if [[ $res =~ 2**(1[4-9]|[2-9][0-9]|[1-9][0-9]{2,}) ]]; then
echo -e "${match}: ${GREEN}ALIGNED${ENDCOLOR} ($res)"
else
echo -e "${match}: ${RED}UNALIGNED${ENDCOLOR} ($res)"