Merge "Allow configuration of the number of tombstones."
diff --git a/adb/transport_usb.cpp b/adb/transport_usb.cpp
index 47094b8..2f46920 100644
--- a/adb/transport_usb.cpp
+++ b/adb/transport_usb.cpp
@@ -192,7 +192,7 @@
#if defined(_WIN32) || !ADB_HOST
return false;
#else
- static bool disable = getenv("ADB_LIBUSB") && strcmp(getenv("ADB_LIBUSB"), "0") == 0;
- return !disable;
+ static bool enable = getenv("ADB_LIBUSB") && strcmp(getenv("ADB_LIBUSB"), "1") == 0;
+ return enable;
#endif
}
diff --git a/debuggerd/client/debuggerd_client_test.cpp b/debuggerd/client/debuggerd_client_test.cpp
index 8420f03..9c2f0d6 100644
--- a/debuggerd/client/debuggerd_client_test.cpp
+++ b/debuggerd/client/debuggerd_client_test.cpp
@@ -27,6 +27,7 @@
#include <gtest/gtest.h>
#include <android-base/file.h>
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
@@ -36,8 +37,20 @@
using namespace std::chrono_literals;
using android::base::unique_fd;
+static int getThreadCount() {
+ int threadCount = 1024;
+ std::vector<std::string> characteristics =
+ android::base::Split(android::base::GetProperty("ro.build.characteristics", ""), ",");
+ if (std::find(characteristics.begin(), characteristics.end(), "embedded")
+ != characteristics.end()) {
+ // 128 is the realistic number for iot devices.
+ threadCount = 128;
+ }
+ return threadCount;
+}
+
TEST(debuggerd_client, race) {
- static constexpr int THREAD_COUNT = 1024;
+ static int THREAD_COUNT = getThreadCount();
pid_t forkpid = fork();
ASSERT_NE(-1, forkpid);
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index df7201d..4b1e51d 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -282,7 +282,10 @@
ATRACE_NAME("after reparent");
// Die if we take too long.
- alarm(2);
+ //
+ // Note: processes with many threads and minidebug-info can take a bit to
+ // unwind, do not make this too small. b/62828735
+ alarm(5);
std::string attach_error;
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 4660f3d..b51fc66 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -311,7 +311,7 @@
std::string result;
ConsumeFd(std::move(output_fd), &result);
- ASSERT_BACKTRACE_FRAME(result, "tgkill");
+ ASSERT_BACKTRACE_FRAME(result, "abort");
}
TEST_F(CrasherTest, signal) {
@@ -458,7 +458,7 @@
FinishIntercept(&intercept_result);
ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
ConsumeFd(std::move(output_fd), &result);
- ASSERT_BACKTRACE_FRAME(result, "tgkill");
+ ASSERT_BACKTRACE_FRAME(result, "abort");
}
TEST_F(CrasherTest, PR_SET_DUMPABLE_0_crash) {
@@ -478,7 +478,7 @@
std::string result;
ConsumeFd(std::move(output_fd), &result);
- ASSERT_BACKTRACE_FRAME(result, "tgkill");
+ ASSERT_BACKTRACE_FRAME(result, "abort");
}
TEST_F(CrasherTest, capabilities) {
diff --git a/debuggerd/tombstoned/tombstoned.cpp b/debuggerd/tombstoned/tombstoned.cpp
index 1840dd5..93c7fb5 100644
--- a/debuggerd/tombstoned/tombstoned.cpp
+++ b/debuggerd/tombstoned/tombstoned.cpp
@@ -343,7 +343,14 @@
}
if (!crash->crash_path.empty()) {
- LOG(ERROR) << "Tombstone written to: " << crash->crash_path;
+ if (crash->crash_type == kDebuggerdJavaBacktrace) {
+ LOG(ERROR) << "Traces for pid " << crash->crash_pid << " written to: " << crash->crash_path;
+ } else {
+ // NOTE: Several tools parse this log message to figure out where the
+ // tombstone associated with a given native crash was written. Any changes
+ // to this message must be carefully considered.
+ LOG(ERROR) << "Tombstone written to: " << crash->crash_path;
+ }
}
fail:
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 5e0bfe4..8c19a81 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -839,7 +839,8 @@
return FS_MGR_MNTALL_FAIL;
}
}
- if (!avb_handle->SetUpAvb(&fstab->recs[i], true /* wait_for_verity_dev */)) {
+ if (avb_handle->SetUpAvbHashtree(&fstab->recs[i], true /* wait_for_verity_dev */) ==
+ SetUpAvbHashtreeResult::kFail) {
LERROR << "Failed to set up AVB on partition: "
<< fstab->recs[i].mount_point << ", skipping!";
/* Skips mounting the device. */
@@ -1055,7 +1056,8 @@
return FS_MGR_DOMNT_FAILED;
}
}
- if (!avb_handle->SetUpAvb(&fstab->recs[i], true /* wait_for_verity_dev */)) {
+ if (avb_handle->SetUpAvbHashtree(&fstab->recs[i], true /* wait_for_verity_dev */) ==
+ SetUpAvbHashtreeResult::kFail) {
LERROR << "Failed to set up AVB on partition: "
<< fstab->recs[i].mount_point << ", skipping!";
/* Skips mounting the device. */
diff --git a/fs_mgr/fs_mgr_avb.cpp b/fs_mgr/fs_mgr_avb.cpp
index 6618003..2c99aa7 100644
--- a/fs_mgr/fs_mgr_avb.cpp
+++ b/fs_mgr/fs_mgr_avb.cpp
@@ -114,7 +114,6 @@
// Reads the following values from kernel cmdline and provides the
// VerifyVbmetaImages() to verify AvbSlotVerifyData.
-// - androidboot.vbmeta.device_state
// - androidboot.vbmeta.hash_alg
// - androidboot.vbmeta.size
// - androidboot.vbmeta.digest
@@ -123,7 +122,6 @@
// The factory method to return a unique_ptr<FsManagerAvbVerifier>
static std::unique_ptr<FsManagerAvbVerifier> Create();
bool VerifyVbmetaImages(const AvbSlotVerifyData& verify_data);
- bool IsDeviceUnlocked() { return is_device_unlocked_; }
protected:
FsManagerAvbVerifier() = default;
@@ -138,7 +136,6 @@
HashAlgorithm hash_alg_;
uint8_t digest_[SHA512_DIGEST_LENGTH];
size_t vbmeta_size_;
- bool is_device_unlocked_;
};
std::unique_ptr<FsManagerAvbVerifier> FsManagerAvbVerifier::Create() {
@@ -161,9 +158,7 @@
const std::string& key = pieces[0];
const std::string& value = pieces[1];
- if (key == "androidboot.vbmeta.device_state") {
- avb_verifier->is_device_unlocked_ = (value == "unlocked");
- } else if (key == "androidboot.vbmeta.hash_alg") {
+ if (key == "androidboot.vbmeta.hash_alg") {
hash_alg = value;
} else if (key == "androidboot.vbmeta.size") {
if (!android::base::ParseUint(value.c_str(), &avb_verifier->vbmeta_size_)) {
@@ -478,6 +473,16 @@
return true;
}
+// Orange state means the device is unlocked, see the following link for details.
+// https://source.android.com/security/verifiedboot/verified-boot#device_state
+static inline bool IsDeviceUnlocked() {
+ std::string verified_boot_state;
+ if (fs_mgr_get_boot_config("verifiedbootstate", &verified_boot_state)) {
+ return verified_boot_state == "orange";
+ }
+ return false;
+}
+
FsManagerAvbUniquePtr FsManagerAvbHandle::Open(const fstab& fstab) {
FsManagerAvbOps avb_ops(fstab);
return DoOpen(&avb_ops);
@@ -493,12 +498,7 @@
}
FsManagerAvbUniquePtr FsManagerAvbHandle::DoOpen(FsManagerAvbOps* avb_ops) {
- // Gets the expected hash value of vbmeta images from kernel cmdline.
- std::unique_ptr<FsManagerAvbVerifier> avb_verifier = FsManagerAvbVerifier::Create();
- if (!avb_verifier) {
- LERROR << "Failed to create FsManagerAvbVerifier";
- return nullptr;
- }
+ bool is_device_unlocked = IsDeviceUnlocked();
FsManagerAvbUniquePtr avb_handle(new FsManagerAvbHandle());
if (!avb_handle) {
@@ -506,9 +506,8 @@
return nullptr;
}
- AvbSlotVerifyFlags flags = avb_verifier->IsDeviceUnlocked()
- ? AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
- : AVB_SLOT_VERIFY_FLAGS_NONE;
+ AvbSlotVerifyFlags flags = is_device_unlocked ? AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
+ : AVB_SLOT_VERIFY_FLAGS_NONE;
AvbSlotVerifyResult verify_result =
avb_ops->AvbSlotVerify(fs_mgr_get_slot_suffix(), flags, &avb_handle->avb_slot_data_);
@@ -526,62 +525,81 @@
// for more details.
switch (verify_result) {
case AVB_SLOT_VERIFY_RESULT_OK:
- avb_handle->status_ = kFsManagerAvbHandleSuccess;
+ avb_handle->status_ = kAvbHandleSuccess;
break;
case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
- if (!avb_verifier->IsDeviceUnlocked()) {
+ if (!is_device_unlocked) {
LERROR << "ERROR_VERIFICATION isn't allowed when the device is LOCKED";
return nullptr;
}
- avb_handle->status_ = kFsManagerAvbHandleErrorVerification;
+ avb_handle->status_ = kAvbHandleVerificationError;
break;
default:
LERROR << "avb_slot_verify failed, result: " << verify_result;
return nullptr;
}
- // Verifies vbmeta images against the digest passed from bootloader.
- if (!avb_verifier->VerifyVbmetaImages(*avb_handle->avb_slot_data_)) {
- LERROR << "VerifyVbmetaImages failed";
- return nullptr;
- }
-
// Sets the MAJOR.MINOR for init to set it into "ro.boot.avb_version".
avb_handle->avb_version_ =
android::base::StringPrintf("%d.%d", AVB_VERSION_MAJOR, AVB_VERSION_MINOR);
- // Checks whether FLAGS_HASHTREE_DISABLED is set.
+ // Checks whether FLAGS_VERIFICATION_DISABLED is set:
+ // - Only the top-level vbmeta struct is read.
+ // - vbmeta struct in other partitions are NOT processed, including AVB HASH descriptor(s)
+ // and AVB HASHTREE descriptor(s).
AvbVBMetaImageHeader vbmeta_header;
avb_vbmeta_image_header_to_host_byte_order(
(AvbVBMetaImageHeader*)avb_handle->avb_slot_data_->vbmeta_images[0].vbmeta_data,
&vbmeta_header);
+ bool verification_disabled =
+ ((AvbVBMetaImageFlags)vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED);
- bool hashtree_disabled =
- ((AvbVBMetaImageFlags)vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED);
- if (hashtree_disabled) {
- avb_handle->status_ = kFsManagerAvbHandleHashtreeDisabled;
+ if (verification_disabled) {
+ avb_handle->status_ = kAvbHandleVerificationDisabled;
+ } else {
+ // Verifies vbmeta structs against the digest passed from bootloader in kernel cmdline.
+ std::unique_ptr<FsManagerAvbVerifier> avb_verifier = FsManagerAvbVerifier::Create();
+ if (!avb_verifier) {
+ LERROR << "Failed to create FsManagerAvbVerifier";
+ return nullptr;
+ }
+ if (!avb_verifier->VerifyVbmetaImages(*avb_handle->avb_slot_data_)) {
+ LERROR << "VerifyVbmetaImages failed";
+ return nullptr;
+ }
+
+ // Checks whether FLAGS_HASHTREE_DISABLED is set.
+ bool hashtree_disabled =
+ ((AvbVBMetaImageFlags)vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED);
+ if (hashtree_disabled) {
+ avb_handle->status_ = kAvbHandleHashtreeDisabled;
+ }
}
LINFO << "Returning avb_handle with status: " << avb_handle->status_;
return avb_handle;
}
-bool FsManagerAvbHandle::SetUpAvb(struct fstab_rec* fstab_entry, bool wait_for_verity_dev) {
- if (!fstab_entry) return false;
- if (!avb_slot_data_ || avb_slot_data_->num_vbmeta_images < 1) {
- return false;
+SetUpAvbHashtreeResult FsManagerAvbHandle::SetUpAvbHashtree(struct fstab_rec* fstab_entry,
+ bool wait_for_verity_dev) {
+ if (!fstab_entry || status_ == kAvbHandleUninitialized || !avb_slot_data_ ||
+ avb_slot_data_->num_vbmeta_images < 1) {
+ return SetUpAvbHashtreeResult::kFail;
}
- if (status_ == kFsManagerAvbHandleUninitialized) return false;
- if (status_ == kFsManagerAvbHandleHashtreeDisabled) {
- LINFO << "AVB HASHTREE disabled on:" << fstab_entry->mount_point;
- return true;
+ if (status_ == kAvbHandleHashtreeDisabled || status_ == kAvbHandleVerificationDisabled) {
+ LINFO << "AVB HASHTREE disabled on: " << fstab_entry->mount_point;
+ return SetUpAvbHashtreeResult::kDisabled;
}
- std::string partition_name(basename(fstab_entry->mount_point));
- if (!avb_validate_utf8((const uint8_t*)partition_name.c_str(), partition_name.length())) {
- LERROR << "Partition name: " << partition_name.c_str() << " is not valid UTF-8.";
- return false;
+ // Derives partition_name from blk_device to query the corresponding AVB HASHTREE descriptor
+ // to setup dm-verity. The partition_names in AVB descriptors are without A/B suffix.
+ std::string partition_name(basename(fstab_entry->blk_device));
+ if (fstab_entry->fs_mgr_flags & MF_SLOTSELECT) {
+ auto ab_suffix = partition_name.rfind(fs_mgr_get_slot_suffix());
+ if (ab_suffix != std::string::npos) {
+ partition_name.erase(ab_suffix);
+ }
}
AvbHashtreeDescriptor hashtree_descriptor;
@@ -589,13 +607,14 @@
std::string root_digest;
if (!get_hashtree_descriptor(partition_name, *avb_slot_data_, &hashtree_descriptor, &salt,
&root_digest)) {
- return false;
+ return SetUpAvbHashtreeResult::kFail;
}
// Converts HASHTREE descriptor to verity_table_params.
if (!hashtree_dm_verity_setup(fstab_entry, hashtree_descriptor, salt, root_digest,
wait_for_verity_dev)) {
- return false;
+ return SetUpAvbHashtreeResult::kFail;
}
- return true;
+
+ return SetUpAvbHashtreeResult::kSuccess;
}
diff --git a/fs_mgr/fs_mgr_avb_ops.cpp b/fs_mgr/fs_mgr_avb_ops.cpp
index 512839b..ba1262f 100644
--- a/fs_mgr/fs_mgr_avb_ops.cpp
+++ b/fs_mgr/fs_mgr_avb_ops.cpp
@@ -89,6 +89,15 @@
return AVB_IO_RESULT_OK;
}
+static AvbIOResult dummy_get_size_of_partition(AvbOps* ops ATTRIBUTE_UNUSED,
+ const char* partition ATTRIBUTE_UNUSED,
+ uint64_t* out_size_num_byte) {
+ // The function is for bootloader to load entire content of AVB HASH partitions.
+ // In user-space, returns 0 as we only need to set up AVB HASHTHREE partitions.
+ *out_size_num_byte = 0;
+ return AVB_IO_RESULT_OK;
+}
+
void FsManagerAvbOps::InitializeAvbOps() {
// We only need to provide the implementation of read_from_partition()
// operation since that's all what is being used by the avb_slot_verify().
@@ -101,6 +110,7 @@
avb_ops_.validate_vbmeta_public_key = dummy_validate_vbmeta_public_key;
avb_ops_.read_is_device_unlocked = dummy_read_is_device_unlocked;
avb_ops_.get_unique_guid_for_partition = dummy_get_unique_guid_for_partition;
+ avb_ops_.get_size_of_partition = dummy_get_size_of_partition;
// Sets user_data for GetInstanceFromAvbOps() to convert it back to FsManagerAvbOps.
avb_ops_.user_data = this;
diff --git a/fs_mgr/include/fs_mgr_avb.h b/fs_mgr/include/fs_mgr_avb.h
index bbafe1a..73a22c8 100644
--- a/fs_mgr/include/fs_mgr_avb.h
+++ b/fs_mgr/include/fs_mgr_avb.h
@@ -25,11 +25,10 @@
#include "fs_mgr.h"
-enum FsManagerAvbHandleStatus {
- kFsManagerAvbHandleUninitialized = -1,
- kFsManagerAvbHandleSuccess = 0,
- kFsManagerAvbHandleHashtreeDisabled = 1,
- kFsManagerAvbHandleErrorVerification = 2,
+enum class SetUpAvbHashtreeResult {
+ kSuccess = 0,
+ kFail,
+ kDisabled,
};
class FsManagerAvbOps;
@@ -40,8 +39,8 @@
using ByNameSymlinkMap = std::map<std::string, std::string>;
// Provides a factory method to return a unique_ptr pointing to itself and the
-// SetUpAvb() function to extract dm-verity parameters from AVB metadata to
-// load verity table into kernel through ioctl.
+// SetUpAvbHashtree() function to extract dm-verity parameters from AVB HASHTREE
+// descriptors to load verity table into kernel through ioctl.
class FsManagerAvbHandle {
public:
// The factory method to return a FsManagerAvbUniquePtr that holds
@@ -65,12 +64,22 @@
// - nullptr: any error when reading and verifying the metadata,
// e.g., I/O error, digest value mismatch, size mismatch, etc.
//
- // - a valid unique_ptr with status kFsMgrAvbHandleHashtreeDisabled:
+ // - a valid unique_ptr with status kAvbHandleHashtreeDisabled:
// to support the existing 'adb disable-verity' feature in Android.
// It's very helpful for developers to make the filesystem writable to
// allow replacing binaries on the device.
//
- // - a valid unique_ptr with status kFsMgrAvbHandleSuccess: the metadata
+ // - a valid unique_ptr with status kAvbHandleVerificationDisabled:
+ // to support 'avbctl disable-verification': only the top-level
+ // vbmeta is read, vbmeta structs in other partitions are not processed.
+ // It's needed to bypass AVB when using the generic system.img to run
+ // VTS for project Treble.
+ //
+ // - a valid unique_ptr with status kAvbHandleVerificationError:
+ // there is verification error when libavb loads vbmeta from each
+ // partition. This is only allowed when the device is unlocked.
+ //
+ // - a valid unique_ptr with status kAvbHandleSuccess: the metadata
// is verified and can be trusted.
//
static FsManagerAvbUniquePtr Open(const fstab& fstab);
@@ -79,14 +88,15 @@
// Sets up dm-verity on the given fstab entry.
// The 'wait_for_verity_dev' parameter makes this function wait for the
// verity device to get created before return.
- // Returns true if the mount point is eligible to mount, it includes:
- // - status_ is kFsMgrAvbHandleHashtreeDisabled or
- // - status_ is kFsMgrAvbHandleSuccess and sending ioctl DM_TABLE_LOAD
- // to load verity table is success.
- // Otherwise, returns false.
- bool SetUpAvb(fstab_rec* fstab_entry, bool wait_for_verity_dev);
+ //
+ // Return value:
+ // - kSuccess: successfully loads dm-verity table into kernel.
+ // - kFailed: failed to setup dm-verity, e.g., vbmeta verification error,
+ // failed to get the HASHTREE descriptor, runtime error when set up
+ // device-mapper, etc.
+ // - kDisabled: hashtree is disabled.
+ SetUpAvbHashtreeResult SetUpAvbHashtree(fstab_rec* fstab_entry, bool wait_for_verity_dev);
- bool hashtree_disabled() const { return status_ == kFsManagerAvbHandleHashtreeDisabled; }
const std::string& avb_version() const { return avb_version_; }
FsManagerAvbHandle(const FsManagerAvbHandle&) = delete; // no copy
@@ -102,11 +112,19 @@
};
private:
- FsManagerAvbHandle() : avb_slot_data_(nullptr), status_(kFsManagerAvbHandleUninitialized) {}
+ enum AvbHandleStatus {
+ kAvbHandleSuccess = 0,
+ kAvbHandleUninitialized,
+ kAvbHandleHashtreeDisabled,
+ kAvbHandleVerificationDisabled,
+ kAvbHandleVerificationError,
+ };
+
+ FsManagerAvbHandle() : avb_slot_data_(nullptr), status_(kAvbHandleUninitialized) {}
static FsManagerAvbUniquePtr DoOpen(FsManagerAvbOps* avb_ops);
AvbSlotVerifyData* avb_slot_data_;
- FsManagerAvbHandleStatus status_;
+ AvbHandleStatus status_;
std::string avb_version_;
};
diff --git a/init/action.cpp b/init/action.cpp
index 21abe02..6900391 100644
--- a/init/action.cpp
+++ b/init/action.cpp
@@ -18,13 +18,14 @@
#include <android-base/logging.h>
#include <android-base/properties.h>
-#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include "util.h"
using android::base::Join;
-using android::base::StringPrintf;
+
+namespace android {
+namespace init {
Command::Command(BuiltinFunction f, const std::vector<std::string>& args, int line)
: func_(f), args_(args), line_(line) {}
@@ -98,10 +99,10 @@
android::base::GetMinimumLogSeverity() <= android::base::DEBUG) {
std::string trigger_name = BuildTriggersString();
std::string cmd_str = command.BuildCommandString();
- std::string source = StringPrintf(" (%s:%d)", filename_.c_str(), command.line());
- LOG(INFO) << "Command '" << cmd_str << "' action=" << trigger_name << source
- << " returned " << result << " took " << duration_ms << "ms.";
+ LOG(INFO) << "Command '" << cmd_str << "' action=" << trigger_name << " (" << filename_
+ << ":" << command.line() << ") returned " << result << " took " << duration_ms
+ << "ms.";
}
}
@@ -351,3 +352,6 @@
action_manager_->AddAction(std::move(action_));
}
}
+
+} // namespace init
+} // namespace android
diff --git a/init/action.h b/init/action.h
index d006c50..5cb50a7 100644
--- a/init/action.h
+++ b/init/action.h
@@ -27,6 +27,9 @@
#include "init_parser.h"
#include "keyword_map.h"
+namespace android {
+namespace init {
+
class Command {
public:
Command(BuiltinFunction f, const std::vector<std::string>& args, int line);
@@ -126,4 +129,7 @@
std::unique_ptr<Action> action_;
};
+} // namespace init
+} // namespace android
+
#endif
diff --git a/init/bootchart.cpp b/init/bootchart.cpp
index 825603a..4727f92 100644
--- a/init/bootchart.cpp
+++ b/init/bootchart.cpp
@@ -40,6 +40,9 @@
using android::base::StringPrintf;
using namespace std::chrono_literals;
+namespace android {
+namespace init {
+
static std::thread* g_bootcharting_thread;
static std::mutex g_bootcharting_finished_mutex;
@@ -192,3 +195,6 @@
if (args[1] == "start") return do_bootchart_start();
return do_bootchart_stop();
}
+
+} // namespace init
+} // namespace android
diff --git a/init/bootchart.h b/init/bootchart.h
index 0e3593d..e4f7b59 100644
--- a/init/bootchart.h
+++ b/init/bootchart.h
@@ -20,6 +20,12 @@
#include <string>
#include <vector>
+namespace android {
+namespace init {
+
int do_bootchart(const std::vector<std::string>& args);
+} // namespace init
+} // namespace android
+
#endif /* _BOOTCHART_H */
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 1eacb36..00ffbc3 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -43,7 +43,6 @@
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/properties.h>
-#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <bootloader_message/bootloader_message.h>
#include <cutils/android_reboot.h>
@@ -68,6 +67,9 @@
#define chmod DO_NOT_USE_CHMOD_USE_FCHMODAT_SYMLINK_NOFOLLOW
+namespace android {
+namespace init {
+
static constexpr std::chrono::nanoseconds kCommandRetryTimeout = 5s;
static int insmod(const char *filename, const char *options, int flags) {
@@ -535,11 +537,10 @@
}
}
- std::string prop_name = android::base::StringPrintf("ro.boottime.init.mount_all.%s",
- prop_post_fix);
+ std::string prop_name = "ro.boottime.init.mount_all."s + prop_post_fix;
Timer t;
int ret = mount_fstab(fstabfile, mount_mode);
- property_set(prop_name.c_str(), std::to_string(t.duration_ms()).c_str());
+ property_set(prop_name, std::to_string(t.duration_ms()));
if (import_rc) {
/* Paths of .rc files are specified at the 2nd argument and beyond */
@@ -567,9 +568,7 @@
}
static int do_setprop(const std::vector<std::string>& args) {
- const char* name = args[1].c_str();
- const char* value = args[2].c_str();
- property_set(name, value);
+ property_set(args[1], args[2]);
return 0;
}
@@ -652,8 +651,7 @@
static void verity_update_property(fstab_rec *fstab, const char *mount_point,
int mode, int status) {
- property_set(android::base::StringPrintf("partition.%s.verified", mount_point).c_str(),
- android::base::StringPrintf("%d", mode).c_str());
+ property_set("partition."s + mount_point + ".verified", std::to_string(mode));
}
static int do_verity_update_state(const std::vector<std::string>& args) {
@@ -929,3 +927,6 @@
// clang-format on
return builtin_functions;
}
+
+} // namespace init
+} // namespace android
diff --git a/init/builtins.h b/init/builtins.h
index e1f0567..b110f61 100644
--- a/init/builtins.h
+++ b/init/builtins.h
@@ -24,6 +24,9 @@
#include "keyword_map.h"
+namespace android {
+namespace init {
+
using BuiltinFunction = std::function<int(const std::vector<std::string>&)>;
class BuiltinFunctionMap : public KeywordMap<BuiltinFunction> {
public:
@@ -33,4 +36,7 @@
const Map& map() const override;
};
+} // namespace init
+} // namespace android
+
#endif
diff --git a/init/capabilities.cpp b/init/capabilities.cpp
index b8a9ec0..53832a4 100644
--- a/init/capabilities.cpp
+++ b/init/capabilities.cpp
@@ -25,6 +25,9 @@
#define CAP_MAP_ENTRY(cap) { #cap, CAP_##cap }
+namespace android {
+namespace init {
+
static const std::map<std::string, int> cap_map = {
CAP_MAP_ENTRY(CHOWN),
CAP_MAP_ENTRY(DAC_OVERRIDE),
@@ -192,3 +195,6 @@
// See http://man7.org/linux/man-pages/man7/capabilities.7.html.
return SetAmbientCaps(to_keep);
}
+
+} // namespace init
+} // namespace android
diff --git a/init/capabilities.h b/init/capabilities.h
index abd7fb2..ef507a6 100644
--- a/init/capabilities.h
+++ b/init/capabilities.h
@@ -20,6 +20,9 @@
#include <bitset>
#include <string>
+namespace android {
+namespace init {
+
using CapSet = std::bitset<CAP_LAST_CAP + 1>;
int LookupCap(const std::string& cap_name);
@@ -27,4 +30,7 @@
unsigned int GetLastValidCap();
bool SetCapsForExec(const CapSet& to_keep);
+} // namespace init
+} // namespace android
+
#endif // _INIT_CAPABILITIES_H
diff --git a/init/descriptors.cpp b/init/descriptors.cpp
index 6f729a3..0cb639a 100644
--- a/init/descriptors.cpp
+++ b/init/descriptors.cpp
@@ -31,6 +31,9 @@
#include "init.h"
#include "util.h"
+namespace android {
+namespace init {
+
DescriptorInfo::DescriptorInfo(const std::string& name, const std::string& type, uid_t uid,
gid_t gid, int perm, const std::string& context)
: name_(name), type_(type), uid_(uid), gid_(gid), perm_(perm), context_(context) {
@@ -58,7 +61,7 @@
std::for_each(publishedName.begin(), publishedName.end(),
[] (char& c) { c = isalnum(c) ? c : '_'; });
- std::string val = android::base::StringPrintf("%d", fd);
+ std::string val = std::to_string(fd);
add_environment(publishedName.c_str(), val.c_str());
// make sure we don't close on exec
@@ -74,7 +77,8 @@
}
void SocketInfo::Clean() const {
- unlink(android::base::StringPrintf(ANDROID_SOCKET_DIR "/%s", name().c_str()).c_str());
+ std::string path = android::base::StringPrintf("%s/%s", ANDROID_SOCKET_DIR, name().c_str());
+ unlink(path.c_str());
}
int SocketInfo::Create(const std::string& context) const {
@@ -125,3 +129,6 @@
const std::string FileInfo::key() const {
return ANDROID_FILE_ENV_PREFIX;
}
+
+} // namespace init
+} // namespace android
diff --git a/init/descriptors.h b/init/descriptors.h
index ff276fb..3bdddfe 100644
--- a/init/descriptors.h
+++ b/init/descriptors.h
@@ -22,6 +22,9 @@
#include <string>
+namespace android {
+namespace init {
+
class DescriptorInfo {
public:
DescriptorInfo(const std::string& name, const std::string& type, uid_t uid,
@@ -75,4 +78,7 @@
virtual const std::string key() const override;
};
+} // namespace init
+} // namespace android
+
#endif
diff --git a/init/devices.cpp b/init/devices.cpp
index 2943fb7..215d2ea 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -37,13 +37,23 @@
#error "Do not include init.h in files used by ueventd or watchdogd; it will expose init's globals"
#endif
+using android::base::Basename;
+using android::base::Dirname;
+using android::base::Readlink;
+using android::base::Realpath;
+using android::base::StartsWith;
+using android::base::StringPrintf;
+
+namespace android {
+namespace init {
+
/* Given a path that may start with a PCI device, populate the supplied buffer
* with the PCI domain/bus number and the peripheral ID and return 0.
* If it doesn't start with a PCI device, or there is some error, return -1 */
static bool FindPciDevicePrefix(const std::string& path, std::string* result) {
result->clear();
- if (!android::base::StartsWith(path, "/devices/pci")) return false;
+ if (!StartsWith(path, "/devices/pci")) return false;
/* Beginning of the prefix is the initial "pci" after "/devices/" */
std::string::size_type start = 9;
@@ -74,7 +84,7 @@
static bool FindVbdDevicePrefix(const std::string& path, std::string* result) {
result->clear();
- if (!android::base::StartsWith(path, "/devices/vbd-")) return false;
+ if (!StartsWith(path, "/devices/vbd-")) return false;
/* Beginning of the prefix is the initial "vbd-" after "/devices/" */
std::string::size_type start = 13;
@@ -116,14 +126,14 @@
}
bool Permissions::Match(const std::string& path) const {
- if (prefix_) return android::base::StartsWith(path, name_.c_str());
+ if (prefix_) return StartsWith(path, name_.c_str());
if (wildcard_) return fnmatch(name_.c_str(), path.c_str(), FNM_PATHNAME) == 0;
return path == name_;
}
bool SysfsPermissions::MatchWithSubsystem(const std::string& path,
const std::string& subsystem) const {
- std::string path_basename = android::base::Basename(path);
+ std::string path_basename = Basename(path);
if (name().find(subsystem) != std::string::npos) {
if (Match("/sys/class/" + subsystem + "/" + path_basename)) return true;
if (Match("/sys/bus/" + subsystem + "/devices/" + path_basename)) return true;
@@ -156,11 +166,11 @@
// Uevents don't contain the mount point, so we need to add it here.
path.insert(0, sysfs_mount_point_);
- std::string directory = android::base::Dirname(path);
+ std::string directory = Dirname(path);
while (directory != "/" && directory != ".") {
std::string subsystem_link_path;
- if (android::base::Realpath(directory + "/subsystem", &subsystem_link_path) &&
+ if (Realpath(directory + "/subsystem", &subsystem_link_path) &&
subsystem_link_path == sysfs_mount_point_ + "/bus/platform") {
// We need to remove the mount point that we added above before returning.
directory.erase(0, sysfs_mount_point_.size());
@@ -172,7 +182,7 @@
if (last_slash == std::string::npos) return false;
path.erase(last_slash);
- directory = android::base::Dirname(path);
+ directory = Dirname(path);
}
return false;
@@ -276,7 +286,7 @@
// skip path to the parent driver
std::string path = uevent.path.substr(parent_device.length());
- if (!android::base::StartsWith(path, "/usb")) return {};
+ if (!StartsWith(path, "/usb")) return {};
// skip root hub name and device. use device interface
// skip 3 slashes, including the first / by starting the search at the 1st character, not 0th.
@@ -334,9 +344,9 @@
static const std::string devices_platform_prefix = "/devices/platform/";
static const std::string devices_prefix = "/devices/";
- if (android::base::StartsWith(device, devices_platform_prefix.c_str())) {
+ if (StartsWith(device, devices_platform_prefix.c_str())) {
device = device.substr(devices_platform_prefix.length());
- } else if (android::base::StartsWith(device, devices_prefix.c_str())) {
+ } else if (StartsWith(device, devices_prefix.c_str())) {
device = device.substr(devices_prefix.length());
}
@@ -380,8 +390,8 @@
if (action == "add") {
MakeDevice(devpath, block, major, minor, links);
for (const auto& link : links) {
- if (mkdir_recursive(android::base::Dirname(link), 0755, sehandle_)) {
- PLOG(ERROR) << "Failed to create directory " << android::base::Dirname(link);
+ if (mkdir_recursive(Dirname(link), 0755, sehandle_)) {
+ PLOG(ERROR) << "Failed to create directory " << Dirname(link);
}
if (symlink(devpath.c_str(), link.c_str()) && errno != EEXIST) {
@@ -393,7 +403,7 @@
if (action == "remove") {
for (const auto& link : links) {
std::string link_path;
- if (android::base::Readlink(link, &link_path) && link_path == devpath) {
+ if (Readlink(link, &link_path) && link_path == devpath) {
unlink(link.c_str());
}
}
@@ -408,11 +418,11 @@
const char* base = "/dev/block/";
make_dir(base, 0755, sehandle_);
- std::string name = android::base::Basename(uevent.path);
+ std::string name = Basename(uevent.path);
std::string devpath = base + name;
std::vector<std::string> links;
- if (android::base::StartsWith(uevent.path, "/devices")) {
+ if (StartsWith(uevent.path, "/devices")) {
links = GetBlockDeviceSymlinks(uevent);
}
@@ -425,7 +435,7 @@
std::string devpath;
- if (android::base::StartsWith(uevent.subsystem, "usb")) {
+ if (StartsWith(uevent.subsystem, "usb")) {
if (uevent.subsystem == "usb") {
if (!uevent.device_name.empty()) {
devpath = "/dev/" + uevent.device_name;
@@ -435,7 +445,7 @@
// Minors are broken up into groups of 128, starting at "001"
int bus_id = uevent.minor / 128 + 1;
int device_id = uevent.minor % 128 + 1;
- devpath = android::base::StringPrintf("/dev/bus/usb/%03d/%03d", bus_id, device_id);
+ devpath = StringPrintf("/dev/bus/usb/%03d/%03d", bus_id, device_id);
}
} else {
// ignore other USB events
@@ -446,10 +456,10 @@
subsystem != subsystems_.cend()) {
devpath = subsystem->ParseDevPath(uevent);
} else {
- devpath = "/dev/" + android::base::Basename(uevent.path);
+ devpath = "/dev/" + Basename(uevent.path);
}
- mkdir_recursive(android::base::Dirname(devpath), 0755, sehandle_);
+ mkdir_recursive(Dirname(devpath), 0755, sehandle_);
auto links = GetCharacterDeviceSymlinks(uevent);
@@ -481,3 +491,6 @@
DeviceHandler::DeviceHandler()
: DeviceHandler(std::vector<Permissions>{}, std::vector<SysfsPermissions>{},
std::vector<Subsystem>{}, false) {}
+
+} // namespace init
+} // namespace android
diff --git a/init/devices.h b/init/devices.h
index 362c38c..5105ad7 100644
--- a/init/devices.h
+++ b/init/devices.h
@@ -29,6 +29,9 @@
#include "uevent.h"
+namespace android {
+namespace init {
+
class Permissions {
public:
Permissions(const std::string& name, mode_t perm, uid_t uid, gid_t gid);
@@ -133,4 +136,7 @@
// Exposed for testing
void SanitizePartitionName(std::string* string);
+} // namespace init
+} // namespace android
+
#endif
diff --git a/init/devices_test.cpp b/init/devices_test.cpp
index e1e4e49..57d8e0f 100644
--- a/init/devices_test.cpp
+++ b/init/devices_test.cpp
@@ -24,6 +24,9 @@
using namespace std::string_literals;
+namespace android {
+namespace init {
+
class DeviceHandlerTester {
public:
void TestGetSymlinks(const std::string& platform_device, const Uevent& uevent,
@@ -400,3 +403,6 @@
EXPECT_EQ(0U, permissions.uid());
EXPECT_EQ(1001U, permissions.gid());
}
+
+} // namespace init
+} // namespace android
diff --git a/init/firmware_handler.cpp b/init/firmware_handler.cpp
index 844c605..8cd5cc5 100644
--- a/init/firmware_handler.cpp
+++ b/init/firmware_handler.cpp
@@ -30,10 +30,16 @@
#include "util.h"
+using android::base::unique_fd;
+using android::base::WriteFully;
+
+namespace android {
+namespace init {
+
static void LoadFirmware(const Uevent& uevent, const std::string& root, int fw_fd, size_t fw_size,
int loading_fd, int data_fd) {
// Start transfer.
- android::base::WriteFully(loading_fd, "1", 1);
+ WriteFully(loading_fd, "1", 1);
// Copy the firmware.
int rc = sendfile(data_fd, fw_fd, nullptr, fw_size);
@@ -44,7 +50,7 @@
// Tell the firmware whether to abort or commit.
const char* response = (rc != -1) ? "0" : "-1";
- android::base::WriteFully(loading_fd, response, strlen(response));
+ WriteFully(loading_fd, response, strlen(response));
}
static bool IsBooting() {
@@ -60,13 +66,13 @@
std::string loading = root + "/loading";
std::string data = root + "/data";
- android::base::unique_fd loading_fd(open(loading.c_str(), O_WRONLY | O_CLOEXEC));
+ unique_fd loading_fd(open(loading.c_str(), O_WRONLY | O_CLOEXEC));
if (loading_fd == -1) {
PLOG(ERROR) << "couldn't open firmware loading fd for " << uevent.firmware;
return;
}
- android::base::unique_fd data_fd(open(data.c_str(), O_WRONLY | O_CLOEXEC));
+ unique_fd data_fd(open(data.c_str(), O_WRONLY | O_CLOEXEC));
if (data_fd == -1) {
PLOG(ERROR) << "couldn't open firmware data fd for " << uevent.firmware;
return;
@@ -78,7 +84,7 @@
try_loading_again:
for (size_t i = 0; i < arraysize(firmware_dirs); i++) {
std::string file = firmware_dirs[i] + uevent.firmware;
- android::base::unique_fd fw_fd(open(file.c_str(), O_RDONLY | O_CLOEXEC));
+ unique_fd fw_fd(open(file.c_str(), O_RDONLY | O_CLOEXEC));
struct stat sb;
if (fw_fd != -1 && fstat(fw_fd, &sb) != -1) {
LoadFirmware(uevent, root, fw_fd, sb.st_size, loading_fd, data_fd);
@@ -130,3 +136,6 @@
waitpid(pid, nullptr, 0);
}
+
+} // namespace init
+} // namespace android
diff --git a/init/firmware_handler.h b/init/firmware_handler.h
index be9daae..e456ac4 100644
--- a/init/firmware_handler.h
+++ b/init/firmware_handler.h
@@ -19,6 +19,12 @@
#include "uevent.h"
+namespace android {
+namespace init {
+
void HandleFirmwareEvent(const Uevent& uevent);
+} // namespace init
+} // namespace android
+
#endif
diff --git a/init/import_parser.cpp b/init/import_parser.cpp
index 99275e5..b9fa2ce 100644
--- a/init/import_parser.cpp
+++ b/init/import_parser.cpp
@@ -20,6 +20,9 @@
#include "util.h"
+namespace android {
+namespace init {
+
bool ImportParser::ParseSection(std::vector<std::string>&& args, const std::string& filename,
int line, std::string* err) {
if (args.size() != 2) {
@@ -50,3 +53,6 @@
}
}
}
+
+} // namespace init
+} // namespace android
diff --git a/init/import_parser.h b/init/import_parser.h
index 45cbfad..b774c57 100644
--- a/init/import_parser.h
+++ b/init/import_parser.h
@@ -22,6 +22,9 @@
#include <string>
#include <vector>
+namespace android {
+namespace init {
+
class ImportParser : public SectionParser {
public:
ImportParser(Parser* parser) : parser_(parser) {}
@@ -37,4 +40,7 @@
std::vector<std::pair<std::string, int>> imports_;
};
+} // namespace init
+} // namespace android
+
#endif
diff --git a/init/init.cpp b/init/init.cpp
index 999fada..0562dad 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -42,14 +42,12 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
-#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <keyutils.h>
#include <libavb/libavb.h>
#include <private/android_filesystem_config.h>
#include <selinux/android.h>
-#include <selinux/label.h>
#include <selinux/selinux.h>
#include <fstream>
@@ -71,9 +69,13 @@
#include "util.h"
#include "watchdogd.h"
+using namespace std::string_literals;
+
using android::base::boot_clock;
using android::base::GetProperty;
-using android::base::StringPrintf;
+
+namespace android {
+namespace init {
struct selabel_handle *sehandle;
struct selabel_handle *sehandle_prop;
@@ -219,7 +221,7 @@
panic();
}
- property_set("ro.boottime.init.cold_boot_wait", std::to_string(t.duration_ms()).c_str());
+ property_set("ro.boottime.init.cold_boot_wait", std::to_string(t.duration_ms()));
return 0;
}
@@ -449,14 +451,14 @@
if (for_emulator) {
// In the emulator, export any kernel option with the "ro.kernel." prefix.
- property_set(StringPrintf("ro.kernel.%s", key.c_str()).c_str(), value.c_str());
+ property_set("ro.kernel." + key, value);
return;
}
if (key == "qemu") {
strlcpy(qemu, value.c_str(), sizeof(qemu));
} else if (android::base::StartsWith(key, "androidboot.")) {
- property_set(StringPrintf("ro.boot.%s", key.c_str() + 12).c_str(), value.c_str());
+ property_set("ro.boot." + key.substr(12), value);
}
}
@@ -487,7 +489,7 @@
};
for (size_t i = 0; i < arraysize(prop_map); i++) {
std::string value = GetProperty(prop_map[i].src_prop, "");
- property_set(prop_map[i].dst_prop, (!value.empty()) ? value.c_str() : prop_map[i].default_value);
+ property_set(prop_map[i].dst_prop, (!value.empty()) ? value : prop_map[i].default_value);
}
}
@@ -511,8 +513,7 @@
android::base::ReadFileToString(file_name, &dt_file);
std::replace(dt_file.begin(), dt_file.end(), ',', '.');
- std::string property_name = StringPrintf("ro.boot.%s", dp->d_name);
- property_set(property_name.c_str(), dt_file.c_str());
+ property_set("ro.boot."s + dp->d_name, dt_file);
}
}
@@ -1002,7 +1003,7 @@
static constexpr uint32_t kNanosecondsPerMillisecond = 1e6;
uint64_t start_ms = start_time.time_since_epoch().count() / kNanosecondsPerMillisecond;
- setenv("INIT_STARTED_AT", StringPrintf("%" PRIu64, start_ms).c_str(), 1);
+ setenv("INIT_STARTED_AT", std::to_string(start_ms).c_str(), 1);
char* path = argv[0];
char* args[] = { path, nullptr };
@@ -1157,3 +1158,10 @@
return 0;
}
+
+} // namespace init
+} // namespace android
+
+int main(int argc, char** argv) {
+ android::init::main(argc, argv);
+}
diff --git a/init/init.h b/init/init.h
index 6725a70..479b771 100644
--- a/init/init.h
+++ b/init/init.h
@@ -19,6 +19,11 @@
#include <string>
+#include <selinux/label.h>
+
+namespace android {
+namespace init {
+
// Note: These globals are *only* valid in init, so they should not be used in ueventd,
// watchdogd, or any files that may be included in those, such as devices.cpp and util.cpp.
// TODO: Have an Init class and remove all globals.
@@ -39,4 +44,7 @@
void DumpState();
+} // namespace init
+} // namespace android
+
#endif /* _INIT_INIT_H */
diff --git a/init/init_first_stage.cpp b/init/init_first_stage.cpp
index 4faca89..e10c3b2 100644
--- a/init/init_first_stage.cpp
+++ b/init/init_first_stage.cpp
@@ -38,6 +38,9 @@
using namespace std::chrono_literals;
+namespace android {
+namespace init {
+
// Class Declarations
// ------------------
class FirstStageMount {
@@ -307,17 +310,17 @@
if (fs_mgr_is_verified(fstab_rec)) {
int ret = fs_mgr_setup_verity(fstab_rec, false /* wait_for_verity_dev */);
switch (ret) {
- case FS_MGR_SETUP_VERITY_SKIPPED:
- case FS_MGR_SETUP_VERITY_DISABLED:
- LOG(INFO) << "Verity disabled/skipped for '" << fstab_rec->mount_point << "'";
- break;
- case FS_MGR_SETUP_VERITY_SUCCESS:
- // The exact block device name (fstab_rec->blk_device) is changed to "/dev/block/dm-XX".
- // Needs to create it because ueventd isn't started in init first stage.
- return InitVerityDevice(fstab_rec->blk_device);
- break;
- default:
- return false;
+ case FS_MGR_SETUP_VERITY_SKIPPED:
+ case FS_MGR_SETUP_VERITY_DISABLED:
+ LOG(INFO) << "Verity disabled/skipped for '" << fstab_rec->mount_point << "'";
+ return true;
+ case FS_MGR_SETUP_VERITY_SUCCESS:
+ // The exact block device name (fstab_rec->blk_device) is changed to
+ // "/dev/block/dm-XX". Needs to create it because ueventd isn't started in init
+ // first stage.
+ return InitVerityDevice(fstab_rec->blk_device);
+ default:
+ return false;
}
}
return true; // Returns true to mount the partition.
@@ -406,14 +409,18 @@
bool FirstStageMountVBootV2::SetUpDmVerity(fstab_rec* fstab_rec) {
if (fs_mgr_is_avb(fstab_rec)) {
if (!InitAvbHandle()) return false;
- if (avb_handle_->hashtree_disabled()) {
- LOG(INFO) << "avb hashtree disabled for '" << fstab_rec->mount_point << "'";
- } else if (avb_handle_->SetUpAvb(fstab_rec, false /* wait_for_verity_dev */)) {
- // The exact block device name (fstab_rec->blk_device) is changed to "/dev/block/dm-XX".
- // Needs to create it because ueventd isn't started in init first stage.
- InitVerityDevice(fstab_rec->blk_device);
- } else {
- return false;
+ SetUpAvbHashtreeResult hashtree_result =
+ avb_handle_->SetUpAvbHashtree(fstab_rec, false /* wait_for_verity_dev */);
+ switch (hashtree_result) {
+ case SetUpAvbHashtreeResult::kDisabled:
+ return true; // Returns true to mount the partition.
+ case SetUpAvbHashtreeResult::kSuccess:
+ // The exact block device name (fstab_rec->blk_device) is changed to
+ // "/dev/block/dm-XX". Needs to create it because ueventd isn't started in init
+ // first stage.
+ return InitVerityDevice(fstab_rec->blk_device);
+ default:
+ return false;
}
}
return true; // Returns true to mount the partition.
@@ -493,3 +500,6 @@
}
setenv("INIT_AVB_VERSION", avb_handle->avb_version().c_str(), 1);
}
+
+} // namespace init
+} // namespace android
diff --git a/init/init_first_stage.h b/init/init_first_stage.h
index 170a24c..c7a3867 100644
--- a/init/init_first_stage.h
+++ b/init/init_first_stage.h
@@ -17,7 +17,13 @@
#ifndef _INIT_FIRST_STAGE_H
#define _INIT_FIRST_STAGE_H
+namespace android {
+namespace init {
+
bool DoFirstStageMount();
void SetInitAvbVersionInRecovery();
+} // namespace init
+} // namespace android
+
#endif
diff --git a/init/init_parser.cpp b/init/init_parser.cpp
index 1b31cf2..e76d589 100644
--- a/init/init_parser.cpp
+++ b/init/init_parser.cpp
@@ -25,6 +25,9 @@
#include "parser.h"
#include "util.h"
+namespace android {
+namespace init {
+
Parser::Parser() {
}
@@ -159,3 +162,6 @@
}
return ParseConfigFile(path);
}
+
+} // namespace init
+} // namespace android
diff --git a/init/init_parser.h b/init/init_parser.h
index 722ebb2..c07a699 100644
--- a/init/init_parser.h
+++ b/init/init_parser.h
@@ -45,6 +45,9 @@
// This function is called at the end of the file.
// It indicates that the parsing has completed and any relevant objects should be committed.
+namespace android {
+namespace init {
+
class SectionParser {
public:
virtual ~SectionParser() {}
@@ -93,4 +96,7 @@
bool is_odm_etc_init_loaded_ = false;
};
+} // namespace init
+} // namespace android
+
#endif
diff --git a/init/init_parser_test.cpp b/init/init_parser_test.cpp
index 86d60d0..38b8275 100644
--- a/init/init_parser_test.cpp
+++ b/init/init_parser_test.cpp
@@ -24,6 +24,9 @@
#include <string>
#include <vector>
+namespace android {
+namespace init {
+
TEST(init_parser, make_exec_oneshot_service_invalid_syntax) {
ServiceManager& sm = ServiceManager::GetInstance();
std::vector<std::string> args;
@@ -141,3 +144,6 @@
TEST(init_parser, make_exec_oneshot_service_with_just_command_no_dash) {
Test_make_exec_oneshot_service(false, false, false, false, false);
}
+
+} // namespace init
+} // namespace android
diff --git a/init/init_test.cpp b/init/init_test.cpp
index 7093ba9..0a4071b 100644
--- a/init/init_test.cpp
+++ b/init/init_test.cpp
@@ -27,6 +27,9 @@
#include "keyword_map.h"
#include "util.h"
+namespace android {
+namespace init {
+
class TestFunctionMap : public KeywordMap<BuiltinFunction> {
public:
// Helper for argument-less functions
@@ -185,3 +188,6 @@
EXPECT_EQ(6, num_executed);
}
+
+} // namespace init
+} // namespace android
diff --git a/init/keychords.cpp b/init/keychords.cpp
index c572cee..a0d7cc5 100644
--- a/init/keychords.cpp
+++ b/init/keychords.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "keychords.h"
+
#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
@@ -25,7 +27,9 @@
#include <android-base/properties.h>
#include "init.h"
-#include "service.h"
+
+namespace android {
+namespace init {
static struct input_keychord *keychords = 0;
static int keychords_count = 0;
@@ -112,3 +116,6 @@
register_epoll_handler(keychord_fd, handle_keychord);
}
+
+} // namespace init
+} // namespace android
diff --git a/init/keychords.h b/init/keychords.h
index d2723b7..1c34098 100644
--- a/init/keychords.h
+++ b/init/keychords.h
@@ -17,9 +17,15 @@
#ifndef _INIT_KEYCHORDS_H_
#define _INIT_KEYCHORDS_H_
-struct service;
+#include "service.h"
-void add_service_keycodes(service*);
+namespace android {
+namespace init {
+
+void add_service_keycodes(Service* svc);
void keychord_init();
+} // namespace init
+} // namespace android
+
#endif
diff --git a/init/keyword_map.h b/init/keyword_map.h
index 88bad01..481d637 100644
--- a/init/keyword_map.h
+++ b/init/keyword_map.h
@@ -22,6 +22,9 @@
#include <android-base/stringprintf.h>
+namespace android {
+namespace init {
+
template <typename Function>
class KeywordMap {
public:
@@ -79,4 +82,7 @@
virtual const Map& map() const = 0;
};
+} // namespace init
+} // namespace android
+
#endif
diff --git a/init/log.cpp b/init/log.cpp
index 0615730..1830077 100644
--- a/init/log.cpp
+++ b/init/log.cpp
@@ -23,6 +23,9 @@
#include <android-base/logging.h>
#include <selinux/selinux.h>
+namespace android {
+namespace init {
+
void InitKernelLogging(char* argv[]) {
// Make stdin/stdout/stderr all point to /dev/null.
int fd = open("/sys/fs/selinux/null", O_RDWR);
@@ -55,3 +58,6 @@
android::base::KernelLogger(android::base::MAIN, severity, "selinux", nullptr, 0, buf);
return 0;
}
+
+} // namespace init
+} // namespace android
diff --git a/init/log.h b/init/log.h
index 29a27af..5a4eba6 100644
--- a/init/log.h
+++ b/init/log.h
@@ -19,8 +19,14 @@
#include <sys/cdefs.h>
+namespace android {
+namespace init {
+
void InitKernelLogging(char* argv[]);
int selinux_klog_callback(int level, const char* fmt, ...) __printflike(2, 3);
+} // namespace init
+} // namespace android
+
#endif
diff --git a/init/parser.cpp b/init/parser.cpp
index 0d13cfe..c0fa6d9 100644
--- a/init/parser.cpp
+++ b/init/parser.cpp
@@ -1,5 +1,8 @@
#include "parser.h"
+namespace android {
+namespace init {
+
int next_token(struct parse_state *state)
{
char *x = state->ptr;
@@ -116,3 +119,6 @@
}
return T_EOF;
}
+
+} // namespace init
+} // namespace android
diff --git a/init/parser.h b/init/parser.h
index 3dcc566..86e4c57 100644
--- a/init/parser.h
+++ b/init/parser.h
@@ -21,6 +21,9 @@
#define T_TEXT 1
#define T_NEWLINE 2
+namespace android {
+namespace init {
+
struct parse_state
{
char *ptr;
@@ -31,4 +34,7 @@
int next_token(struct parse_state *state);
+} // namespace init
+} // namespace android
+
#endif /* PARSER_H_ */
diff --git a/init/property_service.cpp b/init/property_service.cpp
index b43da4e..0af6c21 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -45,7 +45,6 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
-#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <bootimg.h>
#include <fs_mgr.h>
@@ -56,11 +55,12 @@
#include "init.h"
#include "util.h"
-using android::base::StringPrintf;
-
#define PERSISTENT_PROPERTY_DIR "/data/property"
#define RECOVERY_MOUNT_POINT "/recovery"
+namespace android {
+namespace init {
+
static int persistent_properties_loaded = 0;
static int property_set_fd = -1;
@@ -714,7 +714,7 @@
boot_img_hdr hdr;
if (android::base::ReadFully(fd, &hdr, sizeof(hdr))) {
std::string hex = bytes_to_hex(reinterpret_cast<uint8_t*>(hdr.id), sizeof(hdr.id));
- property_set("ro.recovery_id", hex.c_str());
+ property_set("ro.recovery_id", hex);
} else {
PLOG(ERROR) << "error reading /recovery";
}
@@ -744,3 +744,6 @@
register_epoll_handler(property_set_fd, handle_property_set_fd);
}
+
+} // namespace init
+} // namespace android
diff --git a/init/property_service.h b/init/property_service.h
index 9251722..a55e79c 100644
--- a/init/property_service.h
+++ b/init/property_service.h
@@ -21,6 +21,9 @@
#include <string>
+namespace android {
+namespace init {
+
struct property_audit_data {
ucred *cr;
const char* name;
@@ -36,5 +39,7 @@
uint32_t property_set(const std::string& name, const std::string& value);
bool is_legal_property_name(const std::string& name);
+} // namespace init
+} // namespace android
#endif /* _INIT_PROPERTY_H */
diff --git a/init/property_service_test.cpp b/init/property_service_test.cpp
index 4d784aa..3a64e02 100644
--- a/init/property_service_test.cpp
+++ b/init/property_service_test.cpp
@@ -23,6 +23,9 @@
#include <gtest/gtest.h>
+namespace android {
+namespace init {
+
TEST(property_service, very_long_name_35166374) {
// Connect to the property service directly...
int fd = socket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
@@ -46,3 +49,6 @@
ASSERT_EQ(static_cast<ssize_t>(sizeof(data)), send(fd, &data, sizeof(data), 0));
ASSERT_EQ(0, close(fd));
}
+
+} // namespace init
+} // namespace android
diff --git a/init/reboot.cpp b/init/reboot.cpp
index cdfc698..df7912f 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -53,6 +53,9 @@
using android::base::StringPrintf;
+namespace android {
+namespace init {
+
// represents umount status during reboot / shutdown.
enum UmountStat {
/* umount succeeded. */
@@ -468,3 +471,6 @@
DoReboot(cmd, command, reboot_target, run_fsck);
return true;
}
+
+} // namespace init
+} // namespace android
diff --git a/init/reboot.h b/init/reboot.h
index b304b3c..e559540 100644
--- a/init/reboot.h
+++ b/init/reboot.h
@@ -19,6 +19,9 @@
#include <string>
+namespace android {
+namespace init {
+
/* Reboot / shutdown the system.
* cmd ANDROID_RB_* as defined in android_reboot.h
* reason Reason string like "reboot", "userrequested"
@@ -32,4 +35,7 @@
// Parses and handles a setprop sys.powerctl message.
bool HandlePowerctlMessage(const std::string& command);
+} // namespace init
+} // namespace android
+
#endif
diff --git a/init/service.cpp b/init/service.cpp
index b73ddfb..f9a452b 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -45,10 +45,16 @@
#include "util.h"
using android::base::boot_clock;
+using android::base::GetProperty;
+using android::base::Join;
using android::base::ParseInt;
+using android::base::StartsWith;
using android::base::StringPrintf;
using android::base::WriteStringToFile;
+namespace android {
+namespace init {
+
static std::string ComputeContextFromExecutable(std::string& service_name,
const std::string& service_path) {
std::string computed_context;
@@ -198,13 +204,12 @@
return;
}
- std::string prop_name = StringPrintf("init.svc.%s", name_.c_str());
- property_set(prop_name.c_str(), new_state.c_str());
+ std::string prop_name = "init.svc." + name_;
+ property_set(prop_name, new_state);
if (new_state == "running") {
uint64_t start_ns = time_started_.time_since_epoch().count();
- property_set(StringPrintf("ro.boottime.%s", name_.c_str()).c_str(),
- StringPrintf("%" PRIu64, start_ns).c_str());
+ property_set("ro.boottime." + name_, std::to_string(start_ns));
}
}
@@ -322,8 +327,8 @@
void Service::DumpState() const {
LOG(INFO) << "service " << name_;
- LOG(INFO) << " class '" << android::base::Join(classnames_, " ") << "'";
- LOG(INFO) << " exec "<< android::base::Join(args_, " ");
+ LOG(INFO) << " class '" << Join(classnames_, " ") << "'";
+ LOG(INFO) << " exec " << Join(args_, " ");
std::for_each(descriptors_.begin(), descriptors_.end(),
[] (const auto& info) { LOG(INFO) << *info; });
}
@@ -526,9 +531,8 @@
// name type perm [ uid gid context ]
bool Service::ParseSocket(const std::vector<std::string>& args, std::string* err) {
- if (!android::base::StartsWith(args[2], "dgram") &&
- !android::base::StartsWith(args[2], "stream") &&
- !android::base::StartsWith(args[2], "seqpacket")) {
+ if (!StartsWith(args[2], "dgram") && !StartsWith(args[2], "stream") &&
+ !StartsWith(args[2], "seqpacket")) {
*err = "socket type must be 'dgram', 'stream' or 'seqpacket'";
return false;
}
@@ -696,13 +700,13 @@
// See if there were "writepid" instructions to write to files under /dev/cpuset/.
auto cpuset_predicate = [](const std::string& path) {
- return android::base::StartsWith(path, "/dev/cpuset/");
+ return StartsWith(path, "/dev/cpuset/");
};
auto iter = std::find_if(writepid_files_.begin(), writepid_files_.end(), cpuset_predicate);
if (iter == writepid_files_.end()) {
// There were no "writepid" instructions for cpusets, check if the system default
// cpuset is specified to be used for the process.
- std::string default_cpuset = android::base::GetProperty("ro.cpuset.default", "");
+ std::string default_cpuset = GetProperty("ro.cpuset.default", "");
if (!default_cpuset.empty()) {
// Make sure the cpuset name starts and ends with '/'.
// A single '/' means the 'root' cpuset.
@@ -716,7 +720,7 @@
StringPrintf("/dev/cpuset%stasks", default_cpuset.c_str()));
}
}
- std::string pid_str = StringPrintf("%d", getpid());
+ std::string pid_str = std::to_string(getpid());
for (const auto& file : writepid_files_) {
if (!WriteStringToFile(pid_str, file)) {
PLOG(ERROR) << "couldn't write " << pid_str << " to " << file;
@@ -757,7 +761,7 @@
}
if (oom_score_adjust_ != -1000) {
- std::string oom_str = StringPrintf("%d", oom_score_adjust_);
+ std::string oom_str = std::to_string(oom_score_adjust_);
std::string oom_file = StringPrintf("/proc/%d/oom_score_adj", pid);
if (!WriteStringToFile(oom_str, oom_file)) {
PLOG(ERROR) << "couldn't write oom_score_adj: " << strerror(errno);
@@ -776,9 +780,9 @@
}
if ((flags_ & SVC_EXEC) != 0) {
- LOG(INFO) << android::base::StringPrintf(
- "SVC_EXEC pid %d (uid %d gid %d+%zu context %s) started; waiting...", pid_, uid_, gid_,
- supp_gids_.size(), !seclabel_.empty() ? seclabel_.c_str() : "default");
+ LOG(INFO) << "SVC_EXEC pid " << pid_ << " (uid " << uid_ << " gid " << gid_ << "+"
+ << supp_gids_.size() << " context "
+ << (!seclabel_.empty() ? seclabel_ : "default") << ") started; waiting...";
}
NotifyStateChange("running");
@@ -955,8 +959,7 @@
std::vector<std::string> str_args(args.begin() + command_arg, args.end());
exec_count_++;
- std::string name =
- "exec " + std::to_string(exec_count_) + " (" + android::base::Join(str_args, " ") + ")";
+ std::string name = "exec " + std::to_string(exec_count_) + " (" + Join(str_args, " ") + ")";
unsigned flags = SVC_EXEC | SVC_ONESHOT | SVC_TEMPORARY;
CapSet no_capabilities;
@@ -1094,14 +1097,12 @@
std::string name;
std::string wait_string;
if (svc) {
- name = android::base::StringPrintf("Service '%s' (pid %d)",
- svc->name().c_str(), pid);
+ name = StringPrintf("Service '%s' (pid %d)", svc->name().c_str(), pid);
if (svc->flags() & SVC_EXEC) {
- wait_string =
- android::base::StringPrintf(" waiting took %f seconds", exec_waiter_->duration_s());
+ wait_string = StringPrintf(" waiting took %f seconds", exec_waiter_->duration_s());
}
} else {
- name = android::base::StringPrintf("Untracked pid %d", pid);
+ name = StringPrintf("Untracked pid %d", pid);
}
if (WIFEXITED(status)) {
@@ -1176,3 +1177,6 @@
// the service name to the "ctl.start" and "ctl.stop" properties.)
return is_legal_property_name("init.svc." + name) && name.size() <= PROP_VALUE_MAX;
}
+
+} // namespace init
+} // namespace android
diff --git a/init/service.h b/init/service.h
index b9c270a..3c7dc74 100644
--- a/init/service.h
+++ b/init/service.h
@@ -55,8 +55,8 @@
#define NR_SVC_SUPP_GIDS 12 // twelve supplementary groups
-class Action;
-class ServiceManager;
+namespace android {
+namespace init {
struct ServiceEnvironmentInfo {
ServiceEnvironmentInfo();
@@ -236,4 +236,7 @@
std::unique_ptr<Service> service_;
};
+} // namespace init
+} // namespace android
+
#endif
diff --git a/init/service_test.cpp b/init/service_test.cpp
index b9c4627..44f28a3 100644
--- a/init/service_test.cpp
+++ b/init/service_test.cpp
@@ -23,6 +23,9 @@
#include <gtest/gtest.h>
+namespace android {
+namespace init {
+
TEST(service, pod_initialized) {
constexpr auto memory_size = sizeof(Service);
alignas(alignof(Service)) char old_memory[memory_size];
@@ -67,3 +70,6 @@
EXPECT_EQ(-1000, service_in_old_memory2->oom_score_adjust());
EXPECT_FALSE(service_in_old_memory->process_cgroup_empty());
}
+
+} // namespace init
+} // namespace android
diff --git a/init/signal_handler.cpp b/init/signal_handler.cpp
index 4d56d84..db1bfcf 100644
--- a/init/signal_handler.cpp
+++ b/init/signal_handler.cpp
@@ -21,11 +21,13 @@
#include <unistd.h>
#include <android-base/logging.h>
-#include <android-base/stringprintf.h>
#include "init.h"
#include "service.h"
+namespace android {
+namespace init {
+
static int signal_write_fd = -1;
static int signal_read_fd = -1;
@@ -65,3 +67,6 @@
register_epoll_handler(signal_read_fd, handle_signal);
}
+
+} // namespace init
+} // namespace android
diff --git a/init/signal_handler.h b/init/signal_handler.h
index 449b4af..f7881ab 100644
--- a/init/signal_handler.h
+++ b/init/signal_handler.h
@@ -17,6 +17,12 @@
#ifndef _INIT_SIGNAL_HANDLER_H_
#define _INIT_SIGNAL_HANDLER_H_
+namespace android {
+namespace init {
+
void signal_handler_init(void);
+} // namespace init
+} // namespace android
+
#endif
diff --git a/init/uevent.h b/init/uevent.h
index 1095665..c4fd945 100644
--- a/init/uevent.h
+++ b/init/uevent.h
@@ -19,6 +19,9 @@
#include <string>
+namespace android {
+namespace init {
+
struct Uevent {
std::string action;
std::string path;
@@ -31,4 +34,7 @@
int minor;
};
+} // namespace init
+} // namespace android
+
#endif
diff --git a/init/uevent_listener.cpp b/init/uevent_listener.cpp
index c748984..ac1d7c7 100644
--- a/init/uevent_listener.cpp
+++ b/init/uevent_listener.cpp
@@ -26,6 +26,9 @@
#include <android-base/logging.h>
#include <cutils/uevent.h>
+namespace android {
+namespace init {
+
static void ParseEvent(const char* msg, Uevent* uevent) {
uevent->partition_num = -1;
uevent->major = -1;
@@ -212,3 +215,6 @@
}
}
}
+
+} // namespace init
+} // namespace android
diff --git a/init/uevent_listener.h b/init/uevent_listener.h
index 0dae102..5b453fe 100644
--- a/init/uevent_listener.h
+++ b/init/uevent_listener.h
@@ -29,6 +29,9 @@
#define UEVENT_MSG_LEN 2048
+namespace android {
+namespace init {
+
enum class ListenerAction {
kStop = 0, // Stop regenerating uevents as we've handled the one(s) we're interested in.
kContinue, // Continue regenerating uevents as we haven't seen the one(s) we're interested in.
@@ -53,4 +56,7 @@
android::base::unique_fd device_fd_;
};
+} // namespace init
+} // namespace android
+
#endif
diff --git a/init/ueventd.cpp b/init/ueventd.cpp
index 4982b77..81a0572 100644
--- a/init/ueventd.cpp
+++ b/init/ueventd.cpp
@@ -29,7 +29,6 @@
#include <android-base/logging.h>
#include <android-base/properties.h>
-#include <android-base/stringprintf.h>
#include <selinux/android.h>
#include <selinux/selinux.h>
@@ -100,6 +99,9 @@
// the uevent listener resumes in polling mode and will handle the uevents that occurred during
// coldboot.
+namespace android {
+namespace init {
+
class ColdBoot {
public:
ColdBoot(UeventListener& uevent_listener, DeviceHandler& device_handler)
@@ -274,3 +276,6 @@
return 0;
}
+
+} // namespace init
+} // namespace android
diff --git a/init/ueventd.h b/init/ueventd.h
index 1f424d3..51775ec 100644
--- a/init/ueventd.h
+++ b/init/ueventd.h
@@ -17,6 +17,12 @@
#ifndef _INIT_UEVENTD_H_
#define _INIT_UEVENTD_H_
+namespace android {
+namespace init {
+
int ueventd_main(int argc, char** argv);
+} // namespace init
+} // namespace android
+
#endif
diff --git a/init/ueventd_parser.cpp b/init/ueventd_parser.cpp
index 7156e76..02e0d42 100644
--- a/init/ueventd_parser.cpp
+++ b/init/ueventd_parser.cpp
@@ -21,6 +21,9 @@
#include "keyword_map.h"
+namespace android {
+namespace init {
+
bool ParsePermissionsLine(std::vector<std::string>&& args, std::string* err,
std::vector<SysfsPermissions>* out_sysfs_permissions,
std::vector<Permissions>* out_dev_permissions) {
@@ -143,3 +146,6 @@
void SubsystemParser::EndSection() {
subsystems_->emplace_back(std::move(subsystem_));
}
+
+} // namespace init
+} // namespace android
diff --git a/init/ueventd_parser.h b/init/ueventd_parser.h
index c1ce976..592df63 100644
--- a/init/ueventd_parser.h
+++ b/init/ueventd_parser.h
@@ -23,6 +23,9 @@
#include "devices.h"
#include "init_parser.h"
+namespace android {
+namespace init {
+
class SubsystemParser : public SectionParser {
public:
SubsystemParser(std::vector<Subsystem>* subsystems) : subsystems_(subsystems) {}
@@ -43,4 +46,7 @@
std::vector<SysfsPermissions>* out_sysfs_permissions,
std::vector<Permissions>* out_dev_permissions);
+} // namespace init
+} // namespace android
+
#endif
diff --git a/init/util.cpp b/init/util.cpp
index 75f81b9..4b1894f 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -50,6 +50,9 @@
using android::base::boot_clock;
using namespace std::literals::string_literals;
+namespace android {
+namespace init {
+
// DecodeUid() - decodes and returns the given string, which can be either the
// numeric or name representation, into the integer uid or gid. Returns
// UINT_MAX on error.
@@ -397,3 +400,6 @@
}
return false;
}
+
+} // namespace init
+} // namespace android
diff --git a/init/util.h b/init/util.h
index 1ad6b77..346953f 100644
--- a/init/util.h
+++ b/init/util.h
@@ -35,6 +35,9 @@
using android::base::boot_clock;
using namespace std::chrono_literals;
+namespace android {
+namespace init {
+
int CreateSocket(const char* name, int type, bool passcred, mode_t perm, uid_t uid, gid_t gid,
const char* socketcon, selabel_handle* sehandle);
@@ -78,4 +81,7 @@
bool read_android_dt_file(const std::string& sub_path, std::string* dt_content);
bool is_android_dt_value_expected(const std::string& sub_path, const std::string& expected_content);
+} // namespace init
+} // namespace android
+
#endif
diff --git a/init/util_test.cpp b/init/util_test.cpp
index 4bb8a83..c16ab74 100644
--- a/init/util_test.cpp
+++ b/init/util_test.cpp
@@ -26,6 +26,9 @@
using namespace std::literals::string_literals;
+namespace android {
+namespace init {
+
TEST(util, ReadFile_ENOENT) {
std::string s("hello");
std::string err;
@@ -187,3 +190,6 @@
std::string path3 = android::base::StringPrintf("%s/three/directories/deep", test_dir.path);
EXPECT_TRUE(is_dir(path1.c_str()));
}
+
+} // namespace init
+} // namespace android
diff --git a/init/watchdogd.cpp b/init/watchdogd.cpp
index 7baa487..e0164b4 100644
--- a/init/watchdogd.cpp
+++ b/init/watchdogd.cpp
@@ -31,6 +31,9 @@
#define DEV_NAME "/dev/watchdog"
+namespace android {
+namespace init {
+
int watchdogd_main(int argc, char **argv) {
InitKernelLogging(argv);
@@ -73,3 +76,6 @@
sleep(interval);
}
}
+
+} // namespace init
+} // namespace android
diff --git a/init/watchdogd.h b/init/watchdogd.h
index 8b48ab8..73f77d5 100644
--- a/init/watchdogd.h
+++ b/init/watchdogd.h
@@ -17,6 +17,12 @@
#ifndef _INIT_WATCHDOGD_H_
#define _INIT_WATCHDOGD_H_
+namespace android {
+namespace init {
+
int watchdogd_main(int argc, char **argv);
+} // namespace init
+} // namespace android
+
#endif
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index 919b65b..13c4abf 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -266,14 +266,27 @@
return false;
}
+static inline bool prefix_cmp(bool partial, const char* prefix, size_t len, const char* path,
+ size_t plen) {
+ return ((partial && plen >= len) || (plen == len)) && !strncmp(prefix, path, len);
+}
+
// alias prefixes of "<partition>/<stuff>" to "system/<partition>/<stuff>" or
// "system/<partition>/<stuff>" to "<partition>/<stuff>"
-static bool prefix_cmp(const char* prefix, const char* path, size_t len) {
- if (!strncmp(prefix, path, len)) return true;
+static bool fs_config_cmp(bool partial, const char* prefix, size_t len, const char* path,
+ size_t plen) {
+ // If name ends in * then allow partial matches.
+ if (!partial && prefix[len - 1] == '*') {
+ len--;
+ partial = true;
+ }
+
+ if (prefix_cmp(partial, prefix, len, path, plen)) return true;
static const char system[] = "system/";
if (!strncmp(path, system, strlen(system))) {
path += strlen(system);
+ plen -= strlen(system);
} else if (len <= strlen(system)) {
return false;
} else if (strncmp(prefix, system, strlen(system))) {
@@ -282,25 +295,11 @@
prefix += strlen(system);
len -= strlen(system);
}
- return is_partition(prefix, len) && !strncmp(prefix, path, len);
+ return is_partition(prefix, len) && prefix_cmp(partial, prefix, len, path, plen);
}
-
-static bool fs_config_cmp(bool dir, const char* prefix, size_t len, const char* path, size_t plen) {
- if (dir) {
- if (plen < len) {
- return false;
- }
- } else {
- // If name ends in * then allow partial matches.
- if (prefix[len - 1] == '*') {
- return prefix_cmp(prefix, path, len - 1);
- }
- if (plen != len) {
- return false;
- }
- }
- return prefix_cmp(prefix, path, len);
-}
+#ifndef __ANDROID_VNDK__
+auto __for_testing_only__fs_config_cmp = fs_config_cmp;
+#endif
void fs_config(const char* path, int dir, const char* target_out_path, unsigned* uid, unsigned* gid,
unsigned* mode, uint64_t* capabilities) {
diff --git a/libcutils/tests/fs_config.cpp b/libcutils/tests/fs_config.cpp
index a62cd51..391adb6 100644
--- a/libcutils/tests/fs_config.cpp
+++ b/libcutils/tests/fs_config.cpp
@@ -29,12 +29,39 @@
extern const fs_path_config* __for_testing_only__android_dirs;
extern const fs_path_config* __for_testing_only__android_files;
+extern bool (*__for_testing_only__fs_config_cmp)(bool, const char*, size_t, const char*, size_t);
// Maximum entries in system/core/libcutils/fs_config.cpp:android_* before we
// hit a nullptr termination, before we declare the list is just too big or
// could be missing the nullptr.
static constexpr size_t max_idx = 4096;
+static const struct fs_config_cmp_test {
+ bool dir;
+ const char* prefix;
+ const char* path;
+ bool match;
+} fs_config_cmp_tests[] = {
+ // clang-format off
+ { true, "system/lib", "system/lib/hw", true },
+ { true, "vendor/lib", "system/vendor/lib/hw", true },
+ { true, "system/vendor/lib", "vendor/lib/hw", true },
+ { true, "system/vendor/lib", "system/vendor/lib/hw", true },
+ { false, "vendor/bin/wifi", "system/vendor/bin/w", false },
+ { false, "vendor/bin/wifi", "system/vendor/bin/wifi", true },
+ { false, "vendor/bin/wifi", "system/vendor/bin/wifi2", false },
+ { false, "system/vendor/bin/wifi", "system/vendor/bin/wifi", true, },
+ { false, "odm/bin/wifi", "system/odm/bin/wifi", true },
+ { false, "oem/bin/wifi", "system/oem/bin/wifi", true },
+ { false, "data/bin/wifi", "system/data/bin/wifi", false },
+ { false, "system/bin/*", "system/bin/wifi", true },
+ { false, "vendor/bin/*", "system/vendor/bin/wifi", true },
+ { false, "system/bin/*", "system/bin", false },
+ { false, "system/vendor/bin/*", "vendor/bin/wifi", true },
+ { false, NULL, NULL, false },
+ // clang-format on
+};
+
static bool check_unique(std::vector<const char*>& paths, const std::string& config_name,
const std::string& prefix) {
bool retval = false;
@@ -106,6 +133,22 @@
return check_unique(paths_tmp, config, prefix) || retval;
}
+static bool check_fs_config_cmp(const fs_config_cmp_test* tests) {
+ bool match, retval = false;
+ for (size_t idx = 0; tests[idx].prefix; ++idx) {
+ match = __for_testing_only__fs_config_cmp(tests[idx].dir, tests[idx].prefix,
+ strlen(tests[idx].prefix), tests[idx].path,
+ strlen(tests[idx].path));
+ if (match != tests[idx].match) {
+ GTEST_LOG_(ERROR) << tests[idx].path << (match ? " matched " : " didn't match ")
+ << tests[idx].prefix;
+ retval = true;
+ break;
+ }
+ }
+ return retval;
+}
+
#define endof(pointer, field) (offsetof(typeof(*(pointer)), field) + sizeof((pointer)->field))
static bool check_unique(const std::string& config, const std::string& prefix) {
@@ -199,3 +242,7 @@
TEST(fs_config, odm_files_alias) {
check_two(__for_testing_only__android_files, "files", "odm/");
}
+
+TEST(fs_config, system_alias) {
+ EXPECT_FALSE(check_fs_config_cmp(fs_config_cmp_tests));
+}
diff --git a/libmemunreachable/Allocator.cpp b/libmemunreachable/Allocator.cpp
index 6fe67a4..213be17 100644
--- a/libmemunreachable/Allocator.cpp
+++ b/libmemunreachable/Allocator.cpp
@@ -33,9 +33,11 @@
#include "android-base/macros.h"
-#include "anon_vma_naming.h"
#include "Allocator.h"
#include "LinkedList.h"
+#include "anon_vma_naming.h"
+
+namespace android {
// runtime interfaces used:
// abort
@@ -57,10 +59,9 @@
static constexpr size_t kUsableChunkSize = kChunkSize - kPageSize;
static constexpr size_t kMaxBucketAllocationSize = kChunkSize / 4;
static constexpr size_t kMinBucketAllocationSize = 8;
-static constexpr unsigned int kNumBuckets = const_log2(kMaxBucketAllocationSize)
- - const_log2(kMinBucketAllocationSize) + 1;
-static constexpr unsigned int kUsablePagesPerChunk = kUsableChunkSize
- / kPageSize;
+static constexpr unsigned int kNumBuckets =
+ const_log2(kMaxBucketAllocationSize) - const_log2(kMinBucketAllocationSize) + 1;
+static constexpr unsigned int kUsablePagesPerChunk = kUsableChunkSize / kPageSize;
std::atomic<int> heap_count;
@@ -93,7 +94,7 @@
void FreeLocked(void* ptr);
struct MapAllocation {
- void *ptr;
+ void* ptr;
size_t size;
MapAllocation* next;
};
@@ -107,8 +108,7 @@
}
static inline unsigned int size_to_bucket(size_t size) {
- if (size < kMinBucketAllocationSize)
- return kMinBucketAllocationSize;
+ if (size < kMinBucketAllocationSize) return kMinBucketAllocationSize;
return log2(size - 1) + 1 - const_log2(kMinBucketAllocationSize);
}
@@ -140,8 +140,7 @@
// Trim beginning
if (aligned_ptr != ptr) {
- ptrdiff_t extra = reinterpret_cast<uintptr_t>(aligned_ptr)
- - reinterpret_cast<uintptr_t>(ptr);
+ ptrdiff_t extra = reinterpret_cast<uintptr_t>(aligned_ptr) - reinterpret_cast<uintptr_t>(ptr);
munmap(ptr, extra);
map_size -= extra;
ptr = aligned_ptr;
@@ -151,14 +150,13 @@
if (map_size != size) {
assert(map_size > size);
assert(ptr != NULL);
- munmap(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(ptr) + size),
- map_size - size);
+ munmap(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(ptr) + size), map_size - size);
}
-#define PR_SET_VMA 0x53564d41
-#define PR_SET_VMA_ANON_NAME 0
- prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME,
- reinterpret_cast<uintptr_t>(ptr), size, "leak_detector_malloc");
+#define PR_SET_VMA 0x53564d41
+#define PR_SET_VMA_ANON_NAME 0
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, reinterpret_cast<uintptr_t>(ptr), size,
+ "leak_detector_malloc");
return ptr;
}
@@ -170,36 +168,31 @@
Chunk(HeapImpl* heap, int bucket);
~Chunk() {}
- void *Alloc();
+ void* Alloc();
void Free(void* ptr);
void Purge();
bool Empty();
static Chunk* ptr_to_chunk(void* ptr) {
- return reinterpret_cast<Chunk*>(reinterpret_cast<uintptr_t>(ptr)
- & ~(kChunkSize - 1));
+ return reinterpret_cast<Chunk*>(reinterpret_cast<uintptr_t>(ptr) & ~(kChunkSize - 1));
}
static bool is_chunk(void* ptr) {
return (reinterpret_cast<uintptr_t>(ptr) & (kChunkSize - 1)) != 0;
}
- unsigned int free_count() {
- return free_count_;
- }
- HeapImpl* heap() {
- return heap_;
- }
- LinkedList<Chunk*> node_; // linked list sorted by minimum free count
+ unsigned int free_count() { return free_count_; }
+ HeapImpl* heap() { return heap_; }
+ LinkedList<Chunk*> node_; // linked list sorted by minimum free count
private:
DISALLOW_COPY_AND_ASSIGN(Chunk);
HeapImpl* heap_;
unsigned int bucket_;
- unsigned int allocation_size_; // size of allocations in chunk, min 8 bytes
- unsigned int max_allocations_; // maximum number of allocations in the chunk
- unsigned int first_free_bitmap_; // index into bitmap for first non-full entry
- unsigned int free_count_; // number of available allocations
- unsigned int frees_since_purge_; // number of calls to Free since last Purge
+ unsigned int allocation_size_; // size of allocations in chunk, min 8 bytes
+ unsigned int max_allocations_; // maximum number of allocations in the chunk
+ unsigned int first_free_bitmap_; // index into bitmap for first non-full entry
+ unsigned int free_count_; // number of available allocations
+ unsigned int frees_since_purge_; // number of calls to Free since last Purge
// bitmap of pages that have been dirtied
uint32_t dirty_pages_[div_round_up(kUsablePagesPerChunk, 32)];
@@ -210,13 +203,10 @@
char data_[0];
unsigned int ptr_to_n(void* ptr) {
- ptrdiff_t offset = reinterpret_cast<uintptr_t>(ptr)
- - reinterpret_cast<uintptr_t>(data_);
+ ptrdiff_t offset = reinterpret_cast<uintptr_t>(ptr) - reinterpret_cast<uintptr_t>(data_);
return offset / allocation_size_;
}
- void* n_to_ptr(unsigned int n) {
- return data_ + n * allocation_size_;
- }
+ void* n_to_ptr(unsigned int n) { return data_ + n * allocation_size_; }
};
static_assert(sizeof(Chunk) <= kPageSize, "header must fit in page");
@@ -225,23 +215,27 @@
assert(count == sizeof(Chunk));
void* mem = MapAligned(kChunkSize, kChunkSize);
if (!mem) {
- abort(); //throw std::bad_alloc;
+ abort(); // throw std::bad_alloc;
}
return mem;
}
// Override new operator on chunk to use mmap to allocate kChunkSize
-void Chunk::operator delete(void *ptr) {
+void Chunk::operator delete(void* ptr) {
assert(reinterpret_cast<Chunk*>(ptr) == ptr_to_chunk(ptr));
munmap(ptr, kChunkSize);
}
-Chunk::Chunk(HeapImpl* heap, int bucket) :
- node_(this), heap_(heap), bucket_(bucket), allocation_size_(
- bucket_to_size(bucket)), max_allocations_(
- kUsableChunkSize / allocation_size_), first_free_bitmap_(0), free_count_(
- max_allocations_), frees_since_purge_(0) {
+Chunk::Chunk(HeapImpl* heap, int bucket)
+ : node_(this),
+ heap_(heap),
+ bucket_(bucket),
+ allocation_size_(bucket_to_size(bucket)),
+ max_allocations_(kUsableChunkSize / allocation_size_),
+ first_free_bitmap_(0),
+ free_count_(max_allocations_),
+ frees_since_purge_(0) {
memset(dirty_pages_, 0, sizeof(dirty_pages_));
memset(free_bitmap_, 0xff, sizeof(free_bitmap_));
}
@@ -254,8 +248,7 @@
assert(free_count_ > 0);
unsigned int i = first_free_bitmap_;
- while (free_bitmap_[i] == 0)
- i++;
+ while (free_bitmap_[i] == 0) i++;
assert(i < arraysize(free_bitmap_));
unsigned int bit = __builtin_ffs(free_bitmap_[i]) - 1;
assert(free_bitmap_[i] & (1U << bit));
@@ -306,38 +299,35 @@
void Chunk::Purge() {
frees_since_purge_ = 0;
- //unsigned int allocsPerPage = kPageSize / allocation_size_;
+ // unsigned int allocsPerPage = kPageSize / allocation_size_;
}
// Override new operator on HeapImpl to use mmap to allocate a page
-void* HeapImpl::operator new(std::size_t count __attribute__((unused)))
- noexcept {
+void* HeapImpl::operator new(std::size_t count __attribute__((unused))) noexcept {
assert(count == sizeof(HeapImpl));
void* mem = MapAligned(kPageSize, kPageSize);
if (!mem) {
- abort(); //throw std::bad_alloc;
+ abort(); // throw std::bad_alloc;
}
heap_count++;
return mem;
}
-void HeapImpl::operator delete(void *ptr) {
+void HeapImpl::operator delete(void* ptr) {
munmap(ptr, kPageSize);
}
-HeapImpl::HeapImpl() :
- free_chunks_(), full_chunks_(), map_allocation_list_(NULL) {
-}
+HeapImpl::HeapImpl() : free_chunks_(), full_chunks_(), map_allocation_list_(NULL) {}
bool HeapImpl::Empty() {
for (unsigned int i = 0; i < kNumBuckets; i++) {
- for (LinkedList<Chunk*> *it = free_chunks_[i].next(); it->data() != NULL; it = it->next()) {
+ for (LinkedList<Chunk*>* it = free_chunks_[i].next(); it->data() != NULL; it = it->next()) {
if (!it->data()->Empty()) {
return false;
}
}
- for (LinkedList<Chunk*> *it = full_chunks_[i].next(); it->data() != NULL; it = it->next()) {
+ for (LinkedList<Chunk*>* it = full_chunks_[i].next(); it->data() != NULL; it = it->next()) {
if (!it->data()->Empty()) {
return false;
}
@@ -350,12 +340,12 @@
HeapImpl::~HeapImpl() {
for (unsigned int i = 0; i < kNumBuckets; i++) {
while (!free_chunks_[i].empty()) {
- Chunk *chunk = free_chunks_[i].next()->data();
+ Chunk* chunk = free_chunks_[i].next()->data();
chunk->node_.remove();
delete chunk;
}
while (!full_chunks_[i].empty()) {
- Chunk *chunk = full_chunks_[i].next()->data();
+ Chunk* chunk = full_chunks_[i].next()->data();
chunk->node_.remove();
delete chunk;
}
@@ -373,18 +363,18 @@
}
int bucket = size_to_bucket(size);
if (free_chunks_[bucket].empty()) {
- Chunk *chunk = new Chunk(this, bucket);
+ Chunk* chunk = new Chunk(this, bucket);
free_chunks_[bucket].insert(chunk->node_);
}
return free_chunks_[bucket].next()->data()->Alloc();
}
-void HeapImpl::Free(void *ptr) {
+void HeapImpl::Free(void* ptr) {
std::lock_guard<std::mutex> lk(m_);
FreeLocked(ptr);
}
-void HeapImpl::FreeLocked(void *ptr) {
+void HeapImpl::FreeLocked(void* ptr) {
if (!Chunk::is_chunk(ptr)) {
HeapImpl::MapFree(ptr);
} else {
@@ -397,12 +387,11 @@
void* HeapImpl::MapAlloc(size_t size) {
size = (size + kPageSize - 1) & ~(kPageSize - 1);
- MapAllocation* allocation = reinterpret_cast<MapAllocation*>(AllocLocked(
- sizeof(MapAllocation)));
+ MapAllocation* allocation = reinterpret_cast<MapAllocation*>(AllocLocked(sizeof(MapAllocation)));
void* ptr = MapAligned(size, kChunkSize);
if (!ptr) {
FreeLocked(allocation);
- abort(); //throw std::bad_alloc;
+ abort(); // throw std::bad_alloc;
}
allocation->ptr = ptr;
allocation->size = size;
@@ -412,10 +401,9 @@
return ptr;
}
-void HeapImpl::MapFree(void *ptr) {
- MapAllocation **allocation = &map_allocation_list_;
- while (*allocation && (*allocation)->ptr != ptr)
- allocation = &(*allocation)->next;
+void HeapImpl::MapFree(void* ptr) {
+ MapAllocation** allocation = &map_allocation_list_;
+ while (*allocation && (*allocation)->ptr != ptr) allocation = &(*allocation)->next;
assert(*allocation != nullptr);
@@ -425,22 +413,22 @@
*allocation = (*allocation)->next;
}
-void HeapImpl::MoveToFreeList(Chunk *chunk, int bucket) {
+void HeapImpl::MoveToFreeList(Chunk* chunk, int bucket) {
MoveToList(chunk, &free_chunks_[bucket]);
}
-void HeapImpl::MoveToFullList(Chunk *chunk, int bucket) {
+void HeapImpl::MoveToFullList(Chunk* chunk, int bucket) {
MoveToList(chunk, &full_chunks_[bucket]);
}
-void HeapImpl::MoveToList(Chunk *chunk, LinkedList<Chunk*>* head) {
+void HeapImpl::MoveToList(Chunk* chunk, LinkedList<Chunk*>* head) {
// Remove from old list
chunk->node_.remove();
- LinkedList<Chunk*> *node = head;
+ LinkedList<Chunk*>* node = head;
// Insert into new list, sorted by lowest free count
- while (node->next() != head && node->data() != nullptr
- && node->data()->free_count() < chunk->free_count())
+ while (node->next() != head && node->data() != nullptr &&
+ node->data()->free_count() < chunk->free_count())
node = node->next();
node->insert(chunk->node_);
@@ -469,10 +457,12 @@
impl_->Free(ptr);
}
-void Heap::deallocate(HeapImpl*impl, void* ptr) {
+void Heap::deallocate(HeapImpl* impl, void* ptr) {
impl->Free(ptr);
}
bool Heap::empty() {
return impl_->Empty();
}
+
+} // namespace android
diff --git a/libmemunreachable/Allocator.h b/libmemunreachable/Allocator.h
index 5390739..837a12b 100644
--- a/libmemunreachable/Allocator.h
+++ b/libmemunreachable/Allocator.h
@@ -27,18 +27,20 @@
#include <unordered_map>
#include <unordered_set>
#include <vector>
+
+namespace android {
+
extern std::atomic<int> heap_count;
class HeapImpl;
-template<typename T>
+template <typename T>
class Allocator;
-
// Non-templated class that implements wraps HeapImpl to keep
// implementation out of the header file
class Heap {
-public:
+ public:
Heap();
~Heap();
@@ -59,110 +61,99 @@
static void deallocate(HeapImpl* impl, void* ptr);
// Allocate a class of type T
- template<class T>
+ template <class T>
T* allocate() {
return reinterpret_cast<T*>(allocate(sizeof(T)));
}
// Comparators, copied objects will be equal
- bool operator ==(const Heap& other) const {
- return impl_ == other.impl_;
- }
- bool operator !=(const Heap& other) const {
- return !(*this == other);
- }
+ bool operator==(const Heap& other) const { return impl_ == other.impl_; }
+ bool operator!=(const Heap& other) const { return !(*this == other); }
// std::unique_ptr wrapper that allocates using allocate and deletes using
// deallocate
- template<class T>
+ template <class T>
using unique_ptr = std::unique_ptr<T, std::function<void(void*)>>;
- template<class T, class... Args>
+ template <class T, class... Args>
unique_ptr<T> make_unique(Args&&... args) {
HeapImpl* impl = impl_;
- return unique_ptr<T>(new (allocate<T>()) T(std::forward<Args>(args)...),
- [impl](void* ptr) {
- reinterpret_cast<T*>(ptr)->~T();
- deallocate(impl, ptr);
- });
+ return unique_ptr<T>(new (allocate<T>()) T(std::forward<Args>(args)...), [impl](void* ptr) {
+ reinterpret_cast<T*>(ptr)->~T();
+ deallocate(impl, ptr);
+ });
}
// std::unique_ptr wrapper that allocates using allocate and deletes using
// deallocate
- template<class T>
+ template <class T>
using shared_ptr = std::shared_ptr<T>;
- template<class T, class... Args>
+ template <class T, class... Args>
shared_ptr<T> make_shared(Args&&... args);
-protected:
+ protected:
HeapImpl* impl_;
bool owns_impl_;
};
// STLAllocator implements the std allocator interface on top of a Heap
-template<typename T>
+template <typename T>
class STLAllocator {
-public:
+ public:
using value_type = T;
- ~STLAllocator() {
- }
+ ~STLAllocator() {}
// Construct an STLAllocator on top of a Heap
- STLAllocator(const Heap& heap) : // NOLINT, implicit
- heap_(heap) {
- }
+ STLAllocator(const Heap& heap)
+ : // NOLINT, implicit
+ heap_(heap) {}
// Rebind an STLAllocator from an another STLAllocator
- template<typename U>
- STLAllocator(const STLAllocator<U>& other) : // NOLINT, implicit
- heap_(other.heap_) {
- }
+ template <typename U>
+ STLAllocator(const STLAllocator<U>& other)
+ : // NOLINT, implicit
+ heap_(other.heap_) {}
STLAllocator(const STLAllocator&) = default;
STLAllocator<T>& operator=(const STLAllocator<T>&) = default;
- T* allocate(std::size_t n) {
- return reinterpret_cast<T*>(heap_.allocate(n * sizeof(T)));
- }
+ T* allocate(std::size_t n) { return reinterpret_cast<T*>(heap_.allocate(n * sizeof(T))); }
- void deallocate(T* ptr, std::size_t) {
- heap_.deallocate(ptr);
- }
+ void deallocate(T* ptr, std::size_t) { heap_.deallocate(ptr); }
- template<typename U>
- bool operator ==(const STLAllocator<U>& other) const {
+ template <typename U>
+ bool operator==(const STLAllocator<U>& other) const {
return heap_ == other.heap_;
}
- template<typename U>
- inline bool operator !=(const STLAllocator<U>& other) const {
+ template <typename U>
+ inline bool operator!=(const STLAllocator<U>& other) const {
return !(this == other);
}
- template<typename U>
+ template <typename U>
friend class STLAllocator;
-protected:
+ protected:
Heap heap_;
};
-
// Allocator extends STLAllocator with some convenience methods for allocating
// a single object and for constructing unique_ptr and shared_ptr objects with
// appropriate deleters.
-template<class T>
+template <class T>
class Allocator : public STLAllocator<T> {
public:
~Allocator() {}
- Allocator(const Heap& other) : // NOLINT, implicit
- STLAllocator<T>(other) {
- }
+ Allocator(const Heap& other)
+ : // NOLINT, implicit
+ STLAllocator<T>(other) {}
- template<typename U>
- Allocator(const STLAllocator<U>& other) : // NOLINT, implicit
- STLAllocator<T>(other) {
- }
+ template <typename U>
+ Allocator(const STLAllocator<U>& other)
+ : // NOLINT, implicit
+ STLAllocator<T>(other) {}
Allocator(const Allocator&) = default;
Allocator<T>& operator=(const Allocator<T>&) = default;
@@ -171,24 +162,20 @@
using STLAllocator<T>::deallocate;
using STLAllocator<T>::heap_;
- T* allocate() {
- return STLAllocator<T>::allocate(1);
- }
- void deallocate(void* ptr) {
- heap_.deallocate(ptr);
- }
+ T* allocate() { return STLAllocator<T>::allocate(1); }
+ void deallocate(void* ptr) { heap_.deallocate(ptr); }
using shared_ptr = Heap::shared_ptr<T>;
- template<class... Args>
- shared_ptr make_shared(Args&& ...args) {
+ template <class... Args>
+ shared_ptr make_shared(Args&&... args) {
return heap_.template make_shared<T>(std::forward<Args>(args)...);
}
using unique_ptr = Heap::unique_ptr<T>;
- template<class... Args>
- unique_ptr make_unique(Args&& ...args) {
+ template <class... Args>
+ unique_ptr make_unique(Args&&... args) {
return heap_.template make_unique<T>(std::forward<Args>(args)...);
}
};
@@ -196,33 +183,36 @@
// std::unique_ptr wrapper that allocates using allocate and deletes using
// deallocate. Implemented outside class definition in order to pass
// Allocator<T> to shared_ptr.
-template<class T, class... Args>
+template <class T, class... Args>
inline Heap::shared_ptr<T> Heap::make_shared(Args&&... args) {
return std::allocate_shared<T, Allocator<T>, Args...>(Allocator<T>(*this),
- std::forward<Args>(args)...);
+ std::forward<Args>(args)...);
}
namespace allocator {
-template<class T>
+template <class T>
using vector = std::vector<T, Allocator<T>>;
-template<class T>
+template <class T>
using list = std::list<T, Allocator<T>>;
-template<class Key, class T, class Compare = std::less<Key>>
+template <class Key, class T, class Compare = std::less<Key>>
using map = std::map<Key, T, Compare, Allocator<std::pair<const Key, T>>>;
-template<class Key, class T, class Hash = std::hash<Key>, class KeyEqual = std::equal_to<Key>>
-using unordered_map = std::unordered_map<Key, T, Hash, KeyEqual, Allocator<std::pair<const Key, T>>>;
+template <class Key, class T, class Hash = std::hash<Key>, class KeyEqual = std::equal_to<Key>>
+using unordered_map =
+ std::unordered_map<Key, T, Hash, KeyEqual, Allocator<std::pair<const Key, T>>>;
-template<class Key, class Hash = std::hash<Key>, class KeyEqual = std::equal_to<Key>>
+template <class Key, class Hash = std::hash<Key>, class KeyEqual = std::equal_to<Key>>
using unordered_set = std::unordered_set<Key, Hash, KeyEqual, Allocator<Key>>;
-template<class Key, class Compare = std::less<Key>>
+template <class Key, class Compare = std::less<Key>>
using set = std::set<Key, Compare, Allocator<Key>>;
using string = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
}
+} // namespace android
+
#endif
diff --git a/libmemunreachable/HeapWalker.cpp b/libmemunreachable/HeapWalker.cpp
index c365ae5..2403ad0 100644
--- a/libmemunreachable/HeapWalker.cpp
+++ b/libmemunreachable/HeapWalker.cpp
@@ -28,6 +28,8 @@
#include "ScopedSignalHandler.h"
#include "log.h"
+namespace android {
+
bool HeapWalker::Allocation(uintptr_t begin, uintptr_t end) {
if (end == begin) {
end = begin + 1;
@@ -114,8 +116,8 @@
return true;
}
-bool HeapWalker::Leaked(allocator::vector<Range>& leaked, size_t limit,
- size_t* num_leaks_out, size_t* leak_bytes_out) {
+bool HeapWalker::Leaked(allocator::vector<Range>& leaked, size_t limit, size_t* num_leaks_out,
+ size_t* leak_bytes_out) {
leaked.clear();
size_t num_leaks = 0;
@@ -148,9 +150,9 @@
static bool MapOverPage(void* addr) {
const size_t page_size = sysconf(_SC_PAGE_SIZE);
- void *page = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(addr) & ~(page_size-1));
+ void* page = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(addr) & ~(page_size - 1));
- void* ret = mmap(page, page_size, PROT_READ, MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED, -1, 0);
+ void* ret = mmap(page, page_size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
if (ret == MAP_FAILED) {
MEM_ALOGE("failed to map page at %p: %s", page, strerror(errno));
return false;
@@ -159,7 +161,8 @@
return true;
}
-void HeapWalker::HandleSegFault(ScopedSignalHandler& handler, int signal, siginfo_t* si, void* /*uctx*/) {
+void HeapWalker::HandleSegFault(ScopedSignalHandler& handler, int signal, siginfo_t* si,
+ void* /*uctx*/) {
uintptr_t addr = reinterpret_cast<uintptr_t>(si->si_addr);
if (addr != walking_ptr_) {
handler.reset();
@@ -172,3 +175,5 @@
}
ScopedSignalHandler::SignalFn ScopedSignalHandler::handler_;
+
+} // namespace android
diff --git a/libmemunreachable/HeapWalker.h b/libmemunreachable/HeapWalker.h
index b25696f..5c7ec13 100644
--- a/libmemunreachable/HeapWalker.h
+++ b/libmemunreachable/HeapWalker.h
@@ -25,6 +25,8 @@
#include "ScopedSignalHandler.h"
#include "Tarjan.h"
+namespace android {
+
// A range [begin, end)
struct Range {
uintptr_t begin;
@@ -34,31 +36,31 @@
bool operator==(const Range& other) const {
return this->begin == other.begin && this->end == other.end;
}
- bool operator!=(const Range& other) const {
- return !(*this == other);
- }
+ bool operator!=(const Range& other) const { return !(*this == other); }
};
// Comparator for Ranges that returns equivalence for overlapping ranges
struct compare_range {
- bool operator()(const Range& a, const Range& b) const {
- return a.end <= b.begin;
- }
+ bool operator()(const Range& a, const Range& b) const { return a.end <= b.begin; }
};
class HeapWalker {
public:
- explicit HeapWalker(Allocator<HeapWalker> allocator) : allocator_(allocator),
- allocations_(allocator), allocation_bytes_(0),
- roots_(allocator), root_vals_(allocator),
- segv_handler_(allocator), walking_ptr_(0) {
+ explicit HeapWalker(Allocator<HeapWalker> allocator)
+ : allocator_(allocator),
+ allocations_(allocator),
+ allocation_bytes_(0),
+ roots_(allocator),
+ root_vals_(allocator),
+ segv_handler_(allocator),
+ walking_ptr_(0) {
valid_allocations_range_.end = 0;
valid_allocations_range_.begin = ~valid_allocations_range_.end;
- segv_handler_.install(SIGSEGV,
- [=](ScopedSignalHandler& handler, int signal, siginfo_t* siginfo, void* uctx) {
+ segv_handler_.install(
+ SIGSEGV, [=](ScopedSignalHandler& handler, int signal, siginfo_t* siginfo, void* uctx) {
this->HandleSegFault(handler, signal, siginfo, uctx);
- });
+ });
}
~HeapWalker() {}
@@ -68,15 +70,14 @@
bool DetectLeaks();
- bool Leaked(allocator::vector<Range>&, size_t limit, size_t* num_leaks,
- size_t* leak_bytes);
+ bool Leaked(allocator::vector<Range>&, size_t limit, size_t* num_leaks, size_t* leak_bytes);
size_t Allocations();
size_t AllocationBytes();
- template<class F>
+ template <class F>
void ForEachPtrInRange(const Range& range, F&& f);
- template<class F>
+ template <class F>
void ForEachAllocation(F&& f);
struct AllocationInfo {
@@ -84,7 +85,6 @@
};
private:
-
void RecurseRoot(const Range& root);
bool WordContainsAllocationPtr(uintptr_t ptr, Range* range, AllocationInfo** info);
void HandleSegFault(ScopedSignalHandler&, int, siginfo_t*, void*);
@@ -103,7 +103,7 @@
uintptr_t walking_ptr_;
};
-template<class F>
+template <class F>
inline void HeapWalker::ForEachPtrInRange(const Range& range, F&& f) {
uintptr_t begin = (range.begin + (sizeof(uintptr_t) - 1)) & ~(sizeof(uintptr_t) - 1);
// TODO(ccross): we might need to consider a pointer to the end of a buffer
@@ -118,7 +118,7 @@
}
}
-template<class F>
+template <class F>
inline void HeapWalker::ForEachAllocation(F&& f) {
for (auto& it : allocations_) {
const Range& range = it.first;
@@ -127,4 +127,6 @@
}
}
+} // namespace android
+
#endif
diff --git a/libmemunreachable/Leak.h b/libmemunreachable/Leak.h
index eaeeea7..de64b64 100644
--- a/libmemunreachable/Leak.h
+++ b/libmemunreachable/Leak.h
@@ -26,9 +26,9 @@
// as a key in std::unordered_map.
namespace std {
-template<>
-struct hash<Leak::Backtrace> {
- std::size_t operator()(const Leak::Backtrace& key) const {
+template <>
+struct hash<android::Leak::Backtrace> {
+ std::size_t operator()(const android::Leak::Backtrace& key) const {
std::size_t seed = 0;
hash_combine(seed, key.num_frames);
@@ -40,7 +40,7 @@
}
private:
- template<typename T>
+ template <typename T>
inline void hash_combine(std::size_t& seed, const T& v) const {
std::hash<T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
@@ -49,9 +49,12 @@
} // namespace std
+namespace android {
+
static bool operator==(const Leak::Backtrace& lhs, const Leak::Backtrace& rhs) {
return (lhs.num_frames == rhs.num_frames) &&
- memcmp(lhs.frames, rhs.frames, lhs.num_frames * sizeof(lhs.frames[0])) == 0;
+ memcmp(lhs.frames, rhs.frames, lhs.num_frames * sizeof(lhs.frames[0])) == 0;
+}
}
#endif
diff --git a/libmemunreachable/LeakFolding.cpp b/libmemunreachable/LeakFolding.cpp
index be4d20c..69f320c 100644
--- a/libmemunreachable/LeakFolding.cpp
+++ b/libmemunreachable/LeakFolding.cpp
@@ -22,6 +22,8 @@
#include "Tarjan.h"
#include "log.h"
+namespace android {
+
// Converts possibly cyclic graph of leaks to a DAG by combining
// strongly-connected components into a object, stored in the scc pointer
// of each node in the component.
@@ -31,11 +33,11 @@
Allocator<SCCInfo> scc_allocator = allocator_;
- for (auto& scc_nodes: scc_list) {
+ for (auto& scc_nodes : scc_list) {
Allocator<SCCInfo>::unique_ptr leak_scc;
leak_scc = scc_allocator.make_unique(scc_allocator);
- for (auto& node: scc_nodes) {
+ for (auto& node : scc_nodes) {
node->ptr->scc = leak_scc.get();
leak_scc->count++;
leak_scc->size += node->ptr->range.size();
@@ -46,7 +48,7 @@
for (auto& it : leak_map_) {
LeakInfo& leak = it.second;
- for (auto& ref: leak.node.references_out) {
+ for (auto& ref : leak.node.references_out) {
if (leak.scc != ref->ptr->scc) {
leak.scc->node.Edge(&ref->ptr->scc->node);
}
@@ -55,17 +57,14 @@
}
void LeakFolding::AccumulateLeaks(SCCInfo* dominator) {
- std::function<void(SCCInfo*)> walk(std::allocator_arg, allocator_,
- [&](SCCInfo* scc) {
- if (scc->accumulator != dominator) {
- scc->accumulator = dominator;
- dominator->cuumulative_size += scc->size;
- dominator->cuumulative_count += scc->count;
- scc->node.Foreach([&](SCCInfo* ref) {
- walk(ref);
- });
- }
- });
+ std::function<void(SCCInfo*)> walk(std::allocator_arg, allocator_, [&](SCCInfo* scc) {
+ if (scc->accumulator != dominator) {
+ scc->accumulator = dominator;
+ dominator->cuumulative_size += scc->size;
+ dominator->cuumulative_count += scc->count;
+ scc->node.Foreach([&](SCCInfo* ref) { walk(ref); });
+ }
+ });
walk(dominator);
}
@@ -73,27 +72,25 @@
Allocator<LeakInfo> leak_allocator = allocator_;
// Find all leaked allocations insert them into leak_map_ and leak_graph_
- heap_walker_.ForEachAllocation(
- [&](const Range& range, HeapWalker::AllocationInfo& allocation) {
- if (!allocation.referenced_from_root) {
- auto it = leak_map_.emplace(std::piecewise_construct,
- std::forward_as_tuple(range),
- std::forward_as_tuple(range, allocator_));
- LeakInfo& leak = it.first->second;
- leak_graph_.push_back(&leak.node);
- }
- });
+ heap_walker_.ForEachAllocation([&](const Range& range, HeapWalker::AllocationInfo& allocation) {
+ if (!allocation.referenced_from_root) {
+ auto it = leak_map_.emplace(std::piecewise_construct, std::forward_as_tuple(range),
+ std::forward_as_tuple(range, allocator_));
+ LeakInfo& leak = it.first->second;
+ leak_graph_.push_back(&leak.node);
+ }
+ });
// Find references between leaked allocations and connect them in leak_graph_
for (auto& it : leak_map_) {
LeakInfo& leak = it.second;
heap_walker_.ForEachPtrInRange(leak.range,
- [&](Range& ptr_range, HeapWalker::AllocationInfo* ptr_info) {
- if (!ptr_info->referenced_from_root) {
- LeakInfo* ptr_leak = &leak_map_.at(ptr_range);
- leak.node.Edge(&ptr_leak->node);
- }
- });
+ [&](Range& ptr_range, HeapWalker::AllocationInfo* ptr_info) {
+ if (!ptr_info->referenced_from_root) {
+ LeakInfo* ptr_leak = &leak_map_.at(ptr_range);
+ leak.node.Edge(&ptr_leak->node);
+ }
+ });
}
// Convert the cyclic graph to a DAG by grouping strongly connected components
@@ -110,8 +107,8 @@
return true;
}
-bool LeakFolding::Leaked(allocator::vector<LeakFolding::Leak>& leaked,
- size_t* num_leaks_out, size_t* leak_bytes_out) {
+bool LeakFolding::Leaked(allocator::vector<LeakFolding::Leak>& leaked, size_t* num_leaks_out,
+ size_t* leak_bytes_out) {
size_t num_leaks = 0;
size_t leak_bytes = 0;
for (auto& it : leak_map_) {
@@ -123,9 +120,8 @@
for (auto& it : leak_map_) {
const LeakInfo& leak = it.second;
if (leak.scc->dominator) {
- leaked.emplace_back(Leak{leak.range,
- leak.scc->cuumulative_count - 1,
- leak.scc->cuumulative_size - leak.range.size()});
+ leaked.emplace_back(Leak{leak.range, leak.scc->cuumulative_count - 1,
+ leak.scc->cuumulative_size - leak.range.size()});
}
}
@@ -138,3 +134,5 @@
return true;
}
+
+} // namespace android
diff --git a/libmemunreachable/LeakFolding.h b/libmemunreachable/LeakFolding.h
index 9c6a525..09affac 100644
--- a/libmemunreachable/LeakFolding.h
+++ b/libmemunreachable/LeakFolding.h
@@ -19,11 +19,16 @@
#include "HeapWalker.h"
+namespace android {
+
class LeakFolding {
public:
LeakFolding(Allocator<void> allocator, HeapWalker& heap_walker)
- : allocator_(allocator), heap_walker_(heap_walker),
- leak_map_(allocator), leak_graph_(allocator), leak_scc_(allocator) {}
+ : allocator_(allocator),
+ heap_walker_(heap_walker),
+ leak_map_(allocator),
+ leak_graph_(allocator),
+ leak_scc_(allocator) {}
bool FoldLeaks();
@@ -33,8 +38,7 @@
size_t referenced_size;
};
- bool Leaked(allocator::vector<Leak>& leaked,
- size_t* num_leaks_out, size_t* leak_bytes_out);
+ bool Leaked(allocator::vector<Leak>& leaked, size_t* num_leaks_out, size_t* leak_bytes_out);
private:
DISALLOW_COPY_AND_ASSIGN(LeakFolding);
@@ -54,9 +58,15 @@
bool dominator;
SCCInfo* accumulator;
- explicit SCCInfo(Allocator<SCCInfo> allocator) : node(this, allocator),
- count(0), size(0), cuumulative_count(0), cuumulative_size(0),
- dominator(false), accumulator(nullptr) {}
+ explicit SCCInfo(Allocator<SCCInfo> allocator)
+ : node(this, allocator),
+ count(0),
+ size(0),
+ cuumulative_count(0),
+ cuumulative_size(0),
+ dominator(false),
+ accumulator(nullptr) {}
+
private:
SCCInfo(SCCInfo&&) = delete;
DISALLOW_COPY_AND_ASSIGN(SCCInfo);
@@ -71,8 +81,7 @@
SCCInfo* scc;
LeakInfo(const Range& range, Allocator<LeakInfo> allocator)
- : node(this, allocator), range(range),
- scc(nullptr) {}
+ : node(this, allocator), range(range), scc(nullptr) {}
private:
DISALLOW_COPY_AND_ASSIGN(LeakInfo);
@@ -86,4 +95,6 @@
allocator::vector<Allocator<SCCInfo>::unique_ptr> leak_scc_;
};
-#endif // LIBMEMUNREACHABLE_LEAK_FOLDING_H_
+} // namespace android
+
+#endif // LIBMEMUNREACHABLE_LEAK_FOLDING_H_
diff --git a/libmemunreachable/LeakPipe.cpp b/libmemunreachable/LeakPipe.cpp
index 78117e2..8ea9ad6 100644
--- a/libmemunreachable/LeakPipe.cpp
+++ b/libmemunreachable/LeakPipe.cpp
@@ -21,9 +21,11 @@
#include "log.h"
+namespace android {
+
bool LeakPipe::SendFd(int sock, int fd) {
- struct msghdr hdr{};
- struct iovec iov{};
+ struct msghdr hdr {};
+ struct iovec iov {};
unsigned int data = 0xfdfdfdfd;
alignas(struct cmsghdr) char cmsgbuf[CMSG_SPACE(sizeof(int))];
@@ -56,8 +58,8 @@
}
int LeakPipe::ReceiveFd(int sock) {
- struct msghdr hdr{};
- struct iovec iov{};
+ struct msghdr hdr {};
+ struct iovec iov {};
unsigned int data;
alignas(struct cmsghdr) char cmsgbuf[CMSG_SPACE(sizeof(int))];
@@ -87,3 +89,5 @@
return *(int*)CMSG_DATA(cmsg);
}
+
+} // namespace android
diff --git a/libmemunreachable/LeakPipe.h b/libmemunreachable/LeakPipe.h
index 3ea2d8f..94d4aa4 100644
--- a/libmemunreachable/LeakPipe.h
+++ b/libmemunreachable/LeakPipe.h
@@ -26,6 +26,8 @@
#include "ScopedPipe.h"
#include "log.h"
+namespace android {
+
// LeakPipe implements a pipe that can transfer vectors of simple objects
// between processes. The pipe is created in the sending process and
// transferred over a socketpair that was created before forking. This ensures
@@ -34,15 +36,13 @@
class LeakPipe {
public:
LeakPipe() {
- int ret = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, sv_);
+ int ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sv_);
if (ret < 0) {
MEM_LOG_ALWAYS_FATAL("failed to create socketpair: %s", strerror(errno));
}
}
- ~LeakPipe() {
- Close();
- }
+ ~LeakPipe() { Close(); }
void Close() {
close(sv_[0]);
@@ -77,13 +77,9 @@
public:
LeakPipeBase() : fd_(-1) {}
- ~LeakPipeBase() {
- Close();
- }
+ ~LeakPipeBase() { Close(); }
- void SetFd(int fd) {
- fd_ = fd;
- }
+ void SetFd(int fd) { fd_ = fd; }
void Close() {
close(fd_);
@@ -101,7 +97,7 @@
public:
using LeakPipeBase::LeakPipeBase;
- template<typename T>
+ template <typename T>
bool Send(const T& value) {
ssize_t ret = TEMP_FAILURE_RETRY(write(fd_, &value, sizeof(T)));
if (ret < 0) {
@@ -115,7 +111,7 @@
return true;
}
- template<class T, class Alloc = std::allocator<T>>
+ template <class T, class Alloc = std::allocator<T>>
bool SendVector(const std::vector<T, Alloc>& vector) {
size_t size = vector.size() * sizeof(T);
if (!Send(size)) {
@@ -139,7 +135,7 @@
public:
using LeakPipeBase::LeakPipeBase;
- template<typename T>
+ template <typename T>
bool Receive(T* value) {
ssize_t ret = TEMP_FAILURE_RETRY(read(fd_, reinterpret_cast<void*>(value), sizeof(T)));
if (ret < 0) {
@@ -153,7 +149,7 @@
return true;
}
- template<class T, class Alloc = std::allocator<T>>
+ template <class T, class Alloc = std::allocator<T>>
bool ReceiveVector(std::vector<T, Alloc>& vector) {
size_t size = 0;
if (!Receive(&size)) {
@@ -178,16 +174,11 @@
return true;
}
-
};
- LeakPipeReceiver& Receiver() {
- return receiver_;
- }
+ LeakPipeReceiver& Receiver() { return receiver_; }
- LeakPipeSender& Sender() {
- return sender_;
- }
+ LeakPipeSender& Sender() { return sender_; }
private:
LeakPipeReceiver receiver_;
@@ -198,4 +189,6 @@
int sv_[2];
};
-#endif // LIBMEMUNREACHABLE_LEAK_PIPE_H_
+} // namespace android
+
+#endif // LIBMEMUNREACHABLE_LEAK_PIPE_H_
diff --git a/libmemunreachable/LineBuffer.cpp b/libmemunreachable/LineBuffer.cpp
index d3580c0..4ea0542 100644
--- a/libmemunreachable/LineBuffer.cpp
+++ b/libmemunreachable/LineBuffer.cpp
@@ -23,8 +23,10 @@
#include "LineBuffer.h"
-LineBuffer::LineBuffer(int fd, char* buffer, size_t buffer_len) : fd_(fd), buffer_(buffer), buffer_len_(buffer_len) {
-}
+namespace android {
+
+LineBuffer::LineBuffer(int fd, char* buffer, size_t buffer_len)
+ : fd_(fd), buffer_(buffer), buffer_len_(buffer_len) {}
bool LineBuffer::GetLine(char** line, size_t* line_len) {
while (true) {
@@ -60,3 +62,5 @@
bytes_ += bytes;
}
}
+
+} // namespace android
diff --git a/libmemunreachable/LineBuffer.h b/libmemunreachable/LineBuffer.h
index a015c46..cc6cd0c 100644
--- a/libmemunreachable/LineBuffer.h
+++ b/libmemunreachable/LineBuffer.h
@@ -19,6 +19,8 @@
#include <stdint.h>
+namespace android {
+
class LineBuffer {
public:
LineBuffer(int fd, char* buffer, size_t buffer_len);
@@ -33,4 +35,6 @@
size_t bytes_ = 0;
};
-#endif // _LIBMEMUNREACHABLE_LINE_BUFFER_H
+} // namespace android
+
+#endif // _LIBMEMUNREACHABLE_LINE_BUFFER_H
diff --git a/libmemunreachable/LinkedList.h b/libmemunreachable/LinkedList.h
index 132842d..36fe9fd 100644
--- a/libmemunreachable/LinkedList.h
+++ b/libmemunreachable/LinkedList.h
@@ -17,44 +17,47 @@
#ifndef LIBMEMUNREACHABLE_LINKED_LIST_H_
#define LIBMEMUNREACHABLE_LINKED_LIST_H_
-template<class T>
+namespace android {
+
+template <class T>
class LinkedList {
-public:
- LinkedList() : next_(this), prev_(this), data_() {}
- explicit LinkedList(T data) : LinkedList() {
- data_ = data;
- }
- ~LinkedList() {}
- void insert(LinkedList<T>& node) {
- assert(node.empty());
- node.next_ = this->next_;
- node.next_->prev_ = &node;
- this->next_ = &node;
- node.prev_ = this;
- }
- void remove() {
- this->next_->prev_ = this->prev_;
- this->prev_->next_ = this->next_;
- this->next_ = this;
- this->prev_ = this;
- }
- T data() { return data_; }
- bool empty() { return next_ == this && prev_ == this; }
- LinkedList<T> *next() { return next_; }
-private:
- LinkedList<T> *next_;
- LinkedList<T> *prev_;
- T data_;
+ public:
+ LinkedList() : next_(this), prev_(this), data_() {}
+ explicit LinkedList(T data) : LinkedList() { data_ = data; }
+ ~LinkedList() {}
+ void insert(LinkedList<T>& node) {
+ assert(node.empty());
+ node.next_ = this->next_;
+ node.next_->prev_ = &node;
+ this->next_ = &node;
+ node.prev_ = this;
+ }
+ void remove() {
+ this->next_->prev_ = this->prev_;
+ this->prev_->next_ = this->next_;
+ this->next_ = this;
+ this->prev_ = this;
+ }
+ T data() { return data_; }
+ bool empty() { return next_ == this && prev_ == this; }
+ LinkedList<T>* next() { return next_; }
+
+ private:
+ LinkedList<T>* next_;
+ LinkedList<T>* prev_;
+ T data_;
};
-template<class T>
+template <class T>
class LinkedListHead {
-public:
- LinkedListHead() : node_() {}
- ~LinkedListHead() {}
+ public:
+ LinkedListHead() : node_() {}
+ ~LinkedListHead() {}
-private:
- LinkedList<T> node_;
+ private:
+ LinkedList<T> node_;
};
+} // namespace android
+
#endif
diff --git a/libmemunreachable/MemUnreachable.cpp b/libmemunreachable/MemUnreachable.cpp
index 1c84744..a1f74c3 100644
--- a/libmemunreachable/MemUnreachable.cpp
+++ b/libmemunreachable/MemUnreachable.cpp
@@ -15,16 +15,17 @@
*/
#include <inttypes.h>
+#include <string.h>
#include <functional>
#include <iomanip>
#include <mutex>
-#include <string>
#include <sstream>
+#include <string>
#include <unordered_map>
-#include <backtrace.h>
#include <android-base/macros.h>
+#include <backtrace.h>
#include "Allocator.h"
#include "HeapWalker.h"
@@ -37,30 +38,33 @@
#include "Semaphore.h"
#include "ThreadCapture.h"
-#include "memunreachable/memunreachable.h"
#include "bionic.h"
#include "log.h"
-
-const size_t Leak::contents_length;
+#include "memunreachable/memunreachable.h"
using namespace std::chrono_literals;
+namespace android {
+
+const size_t Leak::contents_length;
+
class MemUnreachable {
public:
- MemUnreachable(pid_t pid, Allocator<void> allocator) : pid_(pid), allocator_(allocator),
- heap_walker_(allocator_) {}
+ MemUnreachable(pid_t pid, Allocator<void> allocator)
+ : pid_(pid), allocator_(allocator), heap_walker_(allocator_) {}
bool CollectAllocations(const allocator::vector<ThreadInfo>& threads,
- const allocator::vector<Mapping>& mappings);
- bool GetUnreachableMemory(allocator::vector<Leak>& leaks, size_t limit,
- size_t* num_leaks, size_t* leak_bytes);
+ const allocator::vector<Mapping>& mappings);
+ bool GetUnreachableMemory(allocator::vector<Leak>& leaks, size_t limit, size_t* num_leaks,
+ size_t* leak_bytes);
size_t Allocations() { return heap_walker_.Allocations(); }
size_t AllocationBytes() { return heap_walker_.AllocationBytes(); }
+
private:
bool ClassifyMappings(const allocator::vector<Mapping>& mappings,
- allocator::vector<Mapping>& heap_mappings,
- allocator::vector<Mapping>& anon_mappings,
- allocator::vector<Mapping>& globals_mappings,
- allocator::vector<Mapping>& stack_mappings);
+ allocator::vector<Mapping>& heap_mappings,
+ allocator::vector<Mapping>& anon_mappings,
+ allocator::vector<Mapping>& globals_mappings,
+ allocator::vector<Mapping>& stack_mappings);
DISALLOW_COPY_AND_ASSIGN(MemUnreachable);
pid_t pid_;
Allocator<void> allocator_;
@@ -68,16 +72,17 @@
};
static void HeapIterate(const Mapping& heap_mapping,
- const std::function<void(uintptr_t, size_t)>& func) {
+ const std::function<void(uintptr_t, size_t)>& func) {
malloc_iterate(heap_mapping.begin, heap_mapping.end - heap_mapping.begin,
- [](uintptr_t base, size_t size, void* arg) {
- auto f = reinterpret_cast<const std::function<void(uintptr_t, size_t)>*>(arg);
- (*f)(base, size);
- }, const_cast<void*>(reinterpret_cast<const void*>(&func)));
+ [](uintptr_t base, size_t size, void* arg) {
+ auto f = reinterpret_cast<const std::function<void(uintptr_t, size_t)>*>(arg);
+ (*f)(base, size);
+ },
+ const_cast<void*>(reinterpret_cast<const void*>(&func)));
}
bool MemUnreachable::CollectAllocations(const allocator::vector<ThreadInfo>& threads,
- const allocator::vector<Mapping>& mappings) {
+ const allocator::vector<Mapping>& mappings) {
MEM_ALOGI("searching process %d for allocations", pid_);
allocator::vector<Mapping> heap_mappings{mappings};
allocator::vector<Mapping> anon_mappings{mappings};
@@ -118,8 +123,8 @@
return true;
}
-bool MemUnreachable::GetUnreachableMemory(allocator::vector<Leak>& leaks,
- size_t limit, size_t* num_leaks, size_t* leak_bytes) {
+bool MemUnreachable::GetUnreachableMemory(allocator::vector<Leak>& leaks, size_t limit,
+ size_t* num_leaks, size_t* leak_bytes) {
MEM_ALOGI("sweeping process %d for unreachable memory", pid_);
leaks.clear();
@@ -127,7 +132,6 @@
return false;
}
-
allocator::vector<Range> leaked1{allocator_};
heap_walker_.Leaked(leaked1, 0, num_leaks, leak_bytes);
@@ -152,12 +156,12 @@
// in backtrace_map.
leaks.reserve(leaked.size());
- for (auto& it: leaked) {
+ for (auto& it : leaked) {
leaks.emplace_back();
Leak* leak = &leaks.back();
- ssize_t num_backtrace_frames = malloc_backtrace(reinterpret_cast<void*>(it.range.begin),
- leak->backtrace.frames, leak->backtrace.max_frames);
+ ssize_t num_backtrace_frames = malloc_backtrace(
+ reinterpret_cast<void*>(it.range.begin), leak->backtrace.frames, leak->backtrace.max_frames);
if (num_backtrace_frames > 0) {
leak->backtrace.num_frames = num_backtrace_frames;
@@ -183,14 +187,13 @@
leak->referenced_size = it.referenced_size;
leak->total_size = leak->size + leak->referenced_size;
memcpy(leak->contents, reinterpret_cast<void*>(it.range.begin),
- std::min(leak->size, Leak::contents_length));
+ std::min(leak->size, Leak::contents_length));
}
MEM_ALOGI("folding done");
- std::sort(leaks.begin(), leaks.end(), [](const Leak& a, const Leak& b) {
- return a.total_size > b.total_size;
- });
+ std::sort(leaks.begin(), leaks.end(),
+ [](const Leak& a, const Leak& b) { return a.total_size > b.total_size; });
if (leaks.size() > limit) {
leaks.resize(limit);
@@ -205,11 +208,10 @@
}
bool MemUnreachable::ClassifyMappings(const allocator::vector<Mapping>& mappings,
- allocator::vector<Mapping>& heap_mappings,
- allocator::vector<Mapping>& anon_mappings,
- allocator::vector<Mapping>& globals_mappings,
- allocator::vector<Mapping>& stack_mappings)
-{
+ allocator::vector<Mapping>& heap_mappings,
+ allocator::vector<Mapping>& anon_mappings,
+ allocator::vector<Mapping>& globals_mappings,
+ allocator::vector<Mapping>& stack_mappings) {
heap_mappings.clear();
anon_mappings.clear();
globals_mappings.clear();
@@ -245,7 +247,8 @@
stack_mappings.emplace_back(*it);
} else if (mapping_name.size() == 0) {
globals_mappings.emplace_back(*it);
- } else if (has_prefix(mapping_name, "[anon:") && mapping_name != "[anon:leak_detector_malloc]") {
+ } else if (has_prefix(mapping_name, "[anon:") &&
+ mapping_name != "[anon:leak_detector_malloc]") {
// TODO(ccross): it would be nice to treat named anonymous mappings as
// possible leaks, but naming something in a .bss or .data section makes
// it impossible to distinguish them from mmaped and then named mappings.
@@ -256,7 +259,7 @@
return true;
}
-template<typename T>
+template <typename T>
static inline const char* plural(T val) {
return (val == 1) ? "" : "s";
}
@@ -403,7 +406,6 @@
}
std::string Leak::ToString(bool log_contents) const {
-
std::ostringstream oss;
oss << " " << std::dec << size;
@@ -492,8 +494,8 @@
oss << std::endl;
for (auto it = leaks.begin(); it != leaks.end(); it++) {
- oss << it->ToString(log_contents);
- oss << std::endl;
+ oss << it->ToString(log_contents);
+ oss << std::endl;
}
return oss.str();
@@ -511,9 +513,11 @@
return info.ToString(log_contents);
}
+} // namespace android
+
bool LogUnreachableMemory(bool log_contents, size_t limit) {
- UnreachableMemoryInfo info;
- if (!GetUnreachableMemory(info, limit)) {
+ android::UnreachableMemoryInfo info;
+ if (!android::GetUnreachableMemory(info, limit)) {
return false;
}
@@ -523,10 +527,9 @@
return true;
}
-
bool NoLeaks() {
- UnreachableMemoryInfo info;
- if (!GetUnreachableMemory(info, 0)) {
+ android::UnreachableMemoryInfo info;
+ if (!android::GetUnreachableMemory(info, 0)) {
return false;
}
diff --git a/libmemunreachable/ProcessMappings.cpp b/libmemunreachable/ProcessMappings.cpp
index 57b2321..9a06870 100644
--- a/libmemunreachable/ProcessMappings.cpp
+++ b/libmemunreachable/ProcessMappings.cpp
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include <inttypes.h>
#include <fcntl.h>
+#include <inttypes.h>
#include <string.h>
#include <unistd.h>
@@ -25,6 +25,8 @@
#include "ProcessMappings.h"
#include "log.h"
+namespace android {
+
// This function is not re-entrant since it uses a static buffer for
// the line data.
bool ProcessMappings(pid_t pid, allocator::vector<Mapping>& mappings) {
@@ -42,8 +44,8 @@
int name_pos;
char perms[5];
Mapping mapping{};
- if (sscanf(line, "%" SCNxPTR "-%" SCNxPTR " %4s %*x %*x:%*x %*d %n",
- &mapping.begin, &mapping.end, perms, &name_pos) == 3) {
+ if (sscanf(line, "%" SCNxPTR "-%" SCNxPTR " %4s %*x %*x:%*x %*d %n", &mapping.begin,
+ &mapping.end, perms, &name_pos) == 3) {
if (perms[0] == 'r') {
mapping.read = true;
}
@@ -64,3 +66,5 @@
}
return true;
}
+
+} // namespace android
diff --git a/libmemunreachable/ProcessMappings.h b/libmemunreachable/ProcessMappings.h
index d3b7496..a0e97e9 100644
--- a/libmemunreachable/ProcessMappings.h
+++ b/libmemunreachable/ProcessMappings.h
@@ -19,6 +19,8 @@
#include "Allocator.h"
+namespace android {
+
struct Mapping {
uintptr_t begin;
uintptr_t end;
@@ -33,4 +35,6 @@
// the line data.
bool ProcessMappings(pid_t pid, allocator::vector<Mapping>& mappings);
-#endif // LIBMEMUNREACHABLE_PROCESS_MAPPING_H_
+} // namespace android
+
+#endif // LIBMEMUNREACHABLE_PROCESS_MAPPING_H_
diff --git a/libmemunreachable/PtracerThread.cpp b/libmemunreachable/PtracerThread.cpp
index 73b0493..aca2a82 100644
--- a/libmemunreachable/PtracerThread.cpp
+++ b/libmemunreachable/PtracerThread.cpp
@@ -23,17 +23,19 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <unistd.h>
#include "android-base/macros.h"
+#include "PtracerThread.h"
#include "anon_vma_naming.h"
#include "log.h"
-#include "PtracerThread.h"
+
+namespace android {
class Stack {
public:
@@ -41,7 +43,7 @@
int prot = PROT_READ | PROT_WRITE;
int flags = MAP_PRIVATE | MAP_ANONYMOUS;
page_size_ = sysconf(_SC_PAGE_SIZE);
- size_ += page_size_*2; // guard pages
+ size_ += page_size_ * 2; // guard pages
base_ = mmap(NULL, size_, prot, flags, -1, 0);
if (base_ == MAP_FAILED) {
base_ = NULL;
@@ -52,22 +54,20 @@
mprotect(base_, page_size_, PROT_NONE);
mprotect(top(), page_size_, PROT_NONE);
};
- ~Stack() {
- munmap(base_, size_);
- };
+ ~Stack() { munmap(base_, size_); };
void* top() {
return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(base_) + size_ - page_size_);
};
+
private:
DISALLOW_COPY_AND_ASSIGN(Stack);
- void *base_;
+ void* base_;
size_t size_;
size_t page_size_;
};
-PtracerThread::PtracerThread(const std::function<int()>& func) :
- child_pid_(0) {
+PtracerThread::PtracerThread(const std::function<int()>& func) : child_pid_(0) {
stack_ = std::make_unique<Stack>(PTHREAD_STACK_MIN);
if (stack_->top() == nullptr) {
MEM_LOG_ALWAYS_FATAL("failed to mmap child stack: %s", strerror(errno));
@@ -93,14 +93,13 @@
std::unique_lock<std::mutex> lk(m_);
// Convert from void(*)(void*) to lambda with captures
- auto proxy = [](void *arg) -> int {
+ auto proxy = [](void* arg) -> int {
prctl(PR_SET_NAME, "libmemunreachable ptrace thread");
return (*reinterpret_cast<std::function<int()>*>(arg))();
};
- child_pid_ = clone(proxy, stack_->top(),
- CLONE_VM|CLONE_FS|CLONE_FILES/*|CLONE_UNTRACED*/,
- reinterpret_cast<void*>(&func_));
+ child_pid_ = clone(proxy, stack_->top(), CLONE_VM | CLONE_FS | CLONE_FILES /*|CLONE_UNTRACED*/,
+ reinterpret_cast<void*>(&func_));
if (child_pid_ < 0) {
MEM_ALOGE("failed to clone child: %s", strerror(errno));
return false;
@@ -151,3 +150,5 @@
void PtracerThread::ClearTracer() {
prctl(PR_SET_PTRACER, 0);
}
+
+} // namespace android
diff --git a/libmemunreachable/PtracerThread.h b/libmemunreachable/PtracerThread.h
index f88b599..4f9c420 100644
--- a/libmemunreachable/PtracerThread.h
+++ b/libmemunreachable/PtracerThread.h
@@ -24,6 +24,8 @@
#include "Allocator.h"
+namespace android {
+
class Stack;
// PtracerThread is similar to std::thread, except that it creates a "thread"
@@ -36,6 +38,7 @@
~PtracerThread();
bool Start();
int Join();
+
private:
void SetTracer(pid_t);
void ClearTracer();
@@ -47,4 +50,6 @@
pid_t child_pid_;
};
-#endif // LIBMEMUNREACHABLE_PTRACER_THREAD_H_
+} // namespace android
+
+#endif // LIBMEMUNREACHABLE_PTRACER_THREAD_H_
diff --git a/libmemunreachable/ScopedAlarm.h b/libmemunreachable/ScopedAlarm.h
index 287f479..bb50b9e 100644
--- a/libmemunreachable/ScopedAlarm.h
+++ b/libmemunreachable/ScopedAlarm.h
@@ -23,15 +23,15 @@
#include <chrono>
#include <functional>
+namespace android {
+
class ScopedAlarm {
public:
ScopedAlarm(std::chrono::microseconds us, std::function<void()> func) {
func_ = func;
- struct sigaction oldact{};
- struct sigaction act{};
- act.sa_handler = [](int) {
- ScopedAlarm::func_();
- };
+ struct sigaction oldact {};
+ struct sigaction act {};
+ act.sa_handler = [](int) { ScopedAlarm::func_(); };
sigaction(SIGALRM, &act, &oldact);
std::chrono::seconds s = std::chrono::duration_cast<std::chrono::seconds>(us);
@@ -43,11 +43,15 @@
~ScopedAlarm() {
itimerval t = itimerval{};
setitimer(ITIMER_REAL, &t, NULL);
- struct sigaction act{};
+ struct sigaction act {};
act.sa_handler = SIG_DFL;
sigaction(SIGALRM, &act, NULL);
}
+
private:
static std::function<void()> func_;
};
+
+} // namespace android
+
#endif
diff --git a/libmemunreachable/ScopedDisableMalloc.h b/libmemunreachable/ScopedDisableMalloc.h
index 758d317..655e826 100644
--- a/libmemunreachable/ScopedDisableMalloc.h
+++ b/libmemunreachable/ScopedDisableMalloc.h
@@ -21,16 +21,16 @@
#include "android-base/macros.h"
+#include "ScopedAlarm.h"
#include "bionic.h"
#include "log.h"
-#include "ScopedAlarm.h"
-class DisableMallocGuard{
+namespace android {
+
+class DisableMallocGuard {
public:
- DisableMallocGuard() : disabled_(false){}
- ~DisableMallocGuard() {
- Enable();
- }
+ DisableMallocGuard() : disabled_(false) {}
+ ~DisableMallocGuard() { Enable(); }
void Disable() {
if (!disabled_) {
@@ -45,6 +45,7 @@
disabled_ = false;
}
}
+
private:
DISALLOW_COPY_AND_ASSIGN(DisableMallocGuard);
bool disabled_;
@@ -59,13 +60,9 @@
// here.
class ScopedDisableMalloc {
public:
- ScopedDisableMalloc() {
- disable_malloc_.Disable();
- }
+ ScopedDisableMalloc() { disable_malloc_.Disable(); }
- ~ScopedDisableMalloc() {
- disable_malloc_.Enable();
- }
+ ~ScopedDisableMalloc() { disable_malloc_.Enable(); }
private:
DISALLOW_COPY_AND_ASSIGN(ScopedDisableMalloc);
@@ -74,18 +71,15 @@
class ScopedDisableMallocTimeout {
public:
- explicit ScopedDisableMallocTimeout(std::chrono::milliseconds timeout = std::chrono::milliseconds(2000)) :
- timeout_(timeout), timed_out_(false), disable_malloc_() {
+ explicit ScopedDisableMallocTimeout(
+ std::chrono::milliseconds timeout = std::chrono::milliseconds(2000))
+ : timeout_(timeout), timed_out_(false), disable_malloc_() {
Disable();
}
- ~ScopedDisableMallocTimeout() {
- Enable();
- }
+ ~ScopedDisableMallocTimeout() { Enable(); }
- bool timed_out() {
- return timed_out_;
- }
+ bool timed_out() { return timed_out_; }
void Enable() {
disable_malloc_.Enable();
@@ -110,4 +104,6 @@
DisableMallocGuard disable_malloc_;
};
-#endif // LIBMEMUNREACHABLE_SCOPED_DISABLE_MALLOC_H_
+} // namespace android
+
+#endif // LIBMEMUNREACHABLE_SCOPED_DISABLE_MALLOC_H_
diff --git a/libmemunreachable/ScopedPipe.h b/libmemunreachable/ScopedPipe.h
index 7f44953..adabfd8 100644
--- a/libmemunreachable/ScopedPipe.h
+++ b/libmemunreachable/ScopedPipe.h
@@ -21,6 +21,8 @@
#include "log.h"
+namespace android {
+
class ScopedPipe {
public:
ScopedPipe() : pipefd_{-1, -1} {
@@ -29,28 +31,22 @@
MEM_LOG_ALWAYS_FATAL("failed to open pipe");
}
}
- ~ScopedPipe() {
- Close();
- }
+ ~ScopedPipe() { Close(); }
ScopedPipe(ScopedPipe&& other) {
SetReceiver(other.ReleaseReceiver());
SetSender(other.ReleaseSender());
}
- ScopedPipe& operator = (ScopedPipe&& other) {
+ ScopedPipe& operator=(ScopedPipe&& other) {
SetReceiver(other.ReleaseReceiver());
SetSender(other.ReleaseSender());
return *this;
}
- void CloseReceiver() {
- close(ReleaseReceiver());
- }
+ void CloseReceiver() { close(ReleaseReceiver()); }
- void CloseSender() {
- close(ReleaseSender());
- }
+ void CloseSender() { close(ReleaseSender()); }
void Close() {
CloseReceiver();
@@ -78,4 +74,7 @@
int pipefd_[2];
};
+
+} // namespace android
+
#endif
diff --git a/libmemunreachable/ScopedSignalHandler.h b/libmemunreachable/ScopedSignalHandler.h
index fab38ed..f62f368 100644
--- a/libmemunreachable/ScopedSignalHandler.h
+++ b/libmemunreachable/ScopedSignalHandler.h
@@ -26,14 +26,14 @@
#include "log.h"
+namespace android {
+
class ScopedSignalHandler {
public:
using Fn = std::function<void(ScopedSignalHandler&, int, siginfo_t*, void*)>;
explicit ScopedSignalHandler(Allocator<Fn> allocator) : allocator_(allocator), signal_(-1) {}
- ~ScopedSignalHandler() {
- reset();
- }
+ ~ScopedSignalHandler() { reset(); }
template <class F>
void install(int signal, F&& f) {
@@ -65,7 +65,6 @@
}
}
-
private:
using SignalFn = std::function<void(int, siginfo_t*, void*)>;
DISALLOW_COPY_AND_ASSIGN(ScopedSignalHandler);
@@ -77,4 +76,6 @@
static SignalFn handler_;
};
-#endif // LIBMEMUNREACHABLE_SCOPED_SIGNAL_HANDLER_H_
+} // namespace android
+
+#endif // LIBMEMUNREACHABLE_SCOPED_SIGNAL_HANDLER_H_
diff --git a/libmemunreachable/Semaphore.h b/libmemunreachable/Semaphore.h
index 6bcf4ea..cd73972 100644
--- a/libmemunreachable/Semaphore.h
+++ b/libmemunreachable/Semaphore.h
@@ -22,6 +22,8 @@
#include "android-base/macros.h"
+namespace android {
+
class Semaphore {
public:
explicit Semaphore(int count = 0) : count_(count) {}
@@ -29,7 +31,7 @@
void Wait(std::chrono::milliseconds ms) {
std::unique_lock<std::mutex> lk(m_);
- cv_.wait_for(lk, ms, [&]{
+ cv_.wait_for(lk, ms, [&] {
if (count_ > 0) {
count_--;
return true;
@@ -44,6 +46,7 @@
}
cv_.notify_one();
}
+
private:
DISALLOW_COPY_AND_ASSIGN(Semaphore);
@@ -52,5 +55,6 @@
std::condition_variable cv_;
};
+} // namespace android
-#endif // LIBMEMUNREACHABLE_SEMAPHORE_H_
+#endif // LIBMEMUNREACHABLE_SEMAPHORE_H_
diff --git a/libmemunreachable/Tarjan.h b/libmemunreachable/Tarjan.h
index 2546341..355679f 100644
--- a/libmemunreachable/Tarjan.h
+++ b/libmemunreachable/Tarjan.h
@@ -24,7 +24,9 @@
#include "Allocator.h"
-template<class T>
+namespace android {
+
+template <class T>
class Node {
public:
allocator::set<Node<T>*> references_in;
@@ -34,39 +36,41 @@
T* ptr;
- Node(T* ptr, Allocator<Node> allocator) : references_in(allocator), references_out(allocator),
- ptr(ptr) {};
+ Node(T* ptr, Allocator<Node> allocator)
+ : references_in(allocator), references_out(allocator), ptr(ptr){};
Node(Node&& rhs) = default;
void Edge(Node<T>* ref) {
references_out.emplace(ref);
ref->references_in.emplace(this);
}
- template<class F>
+ template <class F>
void Foreach(F&& f) {
- for (auto& node: references_out) {
+ for (auto& node : references_out) {
f(node->ptr);
}
}
+
private:
DISALLOW_COPY_AND_ASSIGN(Node<T>);
};
-template<class T>
+template <class T>
using Graph = allocator::vector<Node<T>*>;
-template<class T>
+template <class T>
using SCC = allocator::vector<Node<T>*>;
-template<class T>
+template <class T>
using SCCList = allocator::vector<SCC<T>>;
-template<class T>
+template <class T>
class TarjanAlgorithm {
public:
- explicit TarjanAlgorithm(Allocator<void> allocator) : index_(0),
- stack_(allocator), components_(allocator) {}
+ explicit TarjanAlgorithm(Allocator<void> allocator)
+ : index_(0), stack_(allocator), components_(allocator) {}
void Execute(Graph<T>& graph, SCCList<T>& out);
+
private:
static constexpr size_t UNDEFINED_INDEX = static_cast<size_t>(-1);
void Tarjan(Node<T>* vertex, Graph<T>& graph);
@@ -76,17 +80,17 @@
SCCList<T> components_;
};
-template<class T>
+template <class T>
void TarjanAlgorithm<T>::Execute(Graph<T>& graph, SCCList<T>& out) {
stack_.clear();
components_.clear();
index_ = 0;
- for (auto& it: graph) {
+ for (auto& it : graph) {
it->index = UNDEFINED_INDEX;
it->lowlink = UNDEFINED_INDEX;
}
- for (auto& it: graph) {
+ for (auto& it : graph) {
if (it->index == UNDEFINED_INDEX) {
Tarjan(it, graph);
}
@@ -94,14 +98,14 @@
out.swap(components_);
}
-template<class T>
+template <class T>
void TarjanAlgorithm<T>::Tarjan(Node<T>* vertex, Graph<T>& graph) {
assert(vertex->index == UNDEFINED_INDEX);
vertex->index = index_;
vertex->lowlink = index_;
index_++;
stack_.push_back(vertex);
- for (auto& it: vertex->references_out) {
+ for (auto& it : vertex->references_out) {
Node<T>* vertex_next = it;
if (vertex_next->index == UNDEFINED_INDEX) {
Tarjan(vertex_next, graph);
@@ -123,10 +127,12 @@
}
}
-template<class T>
+template <class T>
void Tarjan(Graph<T>& graph, SCCList<T>& out) {
TarjanAlgorithm<T> tarjan{graph.get_allocator()};
tarjan.Execute(graph, out);
}
-#endif // LIBMEMUNREACHABLE_TARJAN_H_
+} // namespace android
+
+#endif // LIBMEMUNREACHABLE_TARJAN_H_
diff --git a/libmemunreachable/ThreadCapture.cpp b/libmemunreachable/ThreadCapture.cpp
index 3891f2d..45eb55d 100644
--- a/libmemunreachable/ThreadCapture.cpp
+++ b/libmemunreachable/ThreadCapture.cpp
@@ -21,13 +21,13 @@
#include <fcntl.h>
#include <limits.h>
#include <stdlib.h>
-#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/wait.h>
+#include <unistd.h>
#include <map>
#include <memory>
@@ -39,6 +39,8 @@
#include "Allocator.h"
#include "log.h"
+namespace android {
+
// bionic interfaces used:
// atoi
// strlcat
@@ -50,12 +52,12 @@
// Convert a pid > 0 to a string. sprintf might allocate, so we can't use it.
// Returns a pointer somewhere in buf to a null terminated string, or NULL
// on error.
-static char *pid_to_str(char *buf, size_t len, pid_t pid) {
+static char* pid_to_str(char* buf, size_t len, pid_t pid) {
if (pid <= 0) {
return nullptr;
}
- char *ptr = buf + len - 1;
+ char* ptr = buf + len - 1;
*ptr = 0;
while (pid > 0) {
ptr--;
@@ -79,6 +81,7 @@
bool ReleaseThread(pid_t tid);
bool CapturedThreadInfo(ThreadInfoList& threads);
void InjectTestFunc(std::function<void(pid_t)>&& f) { inject_test_func_ = f; }
+
private:
int CaptureThread(pid_t tid);
bool ReleaseThread(pid_t tid, unsigned int signal);
@@ -92,9 +95,8 @@
std::function<void(pid_t)> inject_test_func_;
};
-ThreadCaptureImpl::ThreadCaptureImpl(pid_t pid, Allocator<ThreadCaptureImpl>& allocator) :
- captured_threads_(allocator), allocator_(allocator), pid_(pid) {
-}
+ThreadCaptureImpl::ThreadCaptureImpl(pid_t pid, Allocator<ThreadCaptureImpl>& allocator)
+ : captured_threads_(allocator), allocator_(allocator), pid_(pid) {}
bool ThreadCaptureImpl::ListThreads(TidList& tids) {
tids.clear();
@@ -115,11 +117,11 @@
}
struct linux_dirent64 {
- uint64_t d_ino;
- int64_t d_off;
- uint16_t d_reclen;
- char d_type;
- char d_name[];
+ uint64_t d_ino;
+ int64_t d_off;
+ uint16_t d_reclen;
+ char d_type;
+ char d_name[];
} __attribute((packed));
char dirent_buf[4096];
ssize_t nread;
@@ -209,7 +211,7 @@
bool ThreadCaptureImpl::PtraceThreadInfo(pid_t tid, ThreadInfo& thread_info) {
thread_info.tid = tid;
- const unsigned int max_num_regs = 128; // larger than number of registers on any device
+ const unsigned int max_num_regs = 128; // larger than number of registers on any device
uintptr_t regs[max_num_regs];
struct iovec iovec;
iovec.iov_base = ®s;
@@ -243,7 +245,7 @@
thread_info.stack = std::pair<uintptr_t, uintptr_t>(regs[sp], 0);
- return true;
+ return true;
}
int ThreadCaptureImpl::CaptureThread(pid_t tid) {
@@ -266,7 +268,7 @@
unsigned int resume_signal = 0;
- unsigned int signal = WSTOPSIG(status);
+ unsigned int signal = WSTOPSIG(status);
if ((status >> 16) == PTRACE_EVENT_STOP) {
switch (signal) {
case SIGSTOP:
@@ -307,7 +309,7 @@
bool ThreadCaptureImpl::ReleaseThreads() {
bool ret = true;
- for (auto it = captured_threads_.begin(); it != captured_threads_.end(); ) {
+ for (auto it = captured_threads_.begin(); it != captured_threads_.end();) {
if (ReleaseThread(it->first, it->second)) {
it = captured_threads_.erase(it);
} else {
@@ -361,3 +363,5 @@
void ThreadCapture::InjectTestFunc(std::function<void(pid_t)>&& f) {
impl_->InjectTestFunc(std::forward<std::function<void(pid_t)>>(f));
}
+
+} // namespace android
diff --git a/libmemunreachable/ThreadCapture.h b/libmemunreachable/ThreadCapture.h
index 1022cad..961cb60 100644
--- a/libmemunreachable/ThreadCapture.h
+++ b/libmemunreachable/ThreadCapture.h
@@ -21,6 +21,8 @@
#include "Allocator.h"
+namespace android {
+
struct ThreadInfo {
pid_t tid;
allocator::vector<uintptr_t> regs;
@@ -33,7 +35,7 @@
class ThreadCaptureImpl;
class ThreadCapture {
-public:
+ public:
ThreadCapture(pid_t pid, Allocator<ThreadCapture> allocator);
~ThreadCapture();
@@ -44,11 +46,13 @@
bool CapturedThreadInfo(ThreadInfoList& threads);
void InjectTestFunc(std::function<void(pid_t)>&& f);
-private:
+ private:
ThreadCapture(const ThreadCapture&) = delete;
void operator=(const ThreadCapture&) = delete;
Allocator<ThreadCaptureImpl>::unique_ptr impl_;
};
+} // namespace android
+
#endif
diff --git a/libmemunreachable/anon_vma_naming.h b/libmemunreachable/anon_vma_naming.h
index 1e4ade1..fb31e41 100644
--- a/libmemunreachable/anon_vma_naming.h
+++ b/libmemunreachable/anon_vma_naming.h
@@ -19,7 +19,7 @@
#include <sys/prctl.h>
-#define PR_SET_VMA 0x53564d41
-#define PR_SET_VMA_ANON_NAME 0
+#define PR_SET_VMA 0x53564d41
+#define PR_SET_VMA_ANON_NAME 0
-#endif // LIBMEMUNREACHABLE_ANON_VMA_NAMING_H_
+#endif // LIBMEMUNREACHABLE_ANON_VMA_NAMING_H_
diff --git a/libmemunreachable/bionic.h b/libmemunreachable/bionic.h
index 83d07a8..dd1ec79 100644
--- a/libmemunreachable/bionic.h
+++ b/libmemunreachable/bionic.h
@@ -17,9 +17,9 @@
#ifndef LIBMEMUNREACHABLE_BIONIC_H_
#define LIBMEMUNREACHABLE_BIONIC_H_
-#include <sys/cdefs.h>
#include <stdint.h>
#include <stdlib.h>
+#include <sys/cdefs.h>
__BEGIN_DECLS
@@ -27,9 +27,9 @@
extern void malloc_disable();
extern void malloc_enable();
extern int malloc_iterate(uintptr_t base, size_t size,
- void (*callback)(uintptr_t base, size_t size, void* arg), void* arg);
+ void (*callback)(uintptr_t base, size_t size, void* arg), void* arg);
extern ssize_t malloc_backtrace(void* pointer, uintptr_t* frames, size_t frame_count);
__END_DECLS
-#endif // LIBMEMUNREACHABLE_BIONIC_H_
+#endif // LIBMEMUNREACHABLE_BIONIC_H_
diff --git a/libmemunreachable/include/memunreachable/memunreachable.h b/libmemunreachable/include/memunreachable/memunreachable.h
index 9b227fd..438fcaf 100644
--- a/libmemunreachable/include/memunreachable/memunreachable.h
+++ b/libmemunreachable/include/memunreachable/memunreachable.h
@@ -17,12 +17,15 @@
#ifndef LIBMEMUNREACHABLE_MEMUNREACHABLE_H_
#define LIBMEMUNREACHABLE_MEMUNREACHABLE_H_
+#include <string.h>
#include <sys/cdefs.h>
#ifdef __cplusplus
-#include <vector>
#include <string>
+#include <vector>
+
+namespace android {
struct Leak {
uintptr_t begin;
@@ -73,6 +76,8 @@
std::string GetUnreachableMemoryString(bool log_contents = false, size_t limit = 100);
+} // namespace android
+
#endif
__BEGIN_DECLS
@@ -83,4 +88,4 @@
__END_DECLS
-#endif // LIBMEMUNREACHABLE_MEMUNREACHABLE_H_
+#endif // LIBMEMUNREACHABLE_MEMUNREACHABLE_H_
diff --git a/libmemunreachable/log.h b/libmemunreachable/log.h
index 10b83db..44c5f85 100644
--- a/libmemunreachable/log.h
+++ b/libmemunreachable/log.h
@@ -26,7 +26,18 @@
#define MEM_ALOGE(...) async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, ##__VA_ARGS__)
#define MEM_ALOGW(...) async_safe_format_log(ANDROID_LOG_WARN, LOG_TAG, ##__VA_ARGS__)
#define MEM_ALOGI(...) async_safe_format_log(ANDROID_LOG_INFO, LOG_TAG, ##__VA_ARGS__)
-#define MEM_ALOGV(...) async_safe_format_log(ANDROID_LOG_VERBOSE, LOG_TAG, ##__VA_ARGS__)
+#define MEM_ALOGV_IMPL(...) async_safe_format_log(ANDROID_LOG_VERBOSE, LOG_TAG, ##__VA_ARGS__)
+
+#ifdef NDEBUG
+#define MEM_ALOGV(...) \
+ do { \
+ if (0) { \
+ MEM_ALOGV_IMPL(__VA_ARGS__); \
+ } \
+ } while (0)
+#else
+#define MEM_ALOGV(...) MEM_ALOGV_IMPL(__VA_ARGS__)
+#endif
#define MEM_LOG_ALWAYS_FATAL(...) async_safe_fatal(__VA_ARGS__)
@@ -43,4 +54,4 @@
#endif
-#endif // LIBMEMUNREACHABLE_LOG_H_
+#endif // LIBMEMUNREACHABLE_LOG_H_
diff --git a/libmemunreachable/tests/Allocator_test.cpp b/libmemunreachable/tests/Allocator_test.cpp
index 21c8218..8991a7b 100644
--- a/libmemunreachable/tests/Allocator_test.cpp
+++ b/libmemunreachable/tests/Allocator_test.cpp
@@ -16,44 +16,44 @@
#include <Allocator.h>
-#include <gtest/gtest.h>
#include <ScopedDisableMalloc.h>
+#include <gtest/gtest.h>
+namespace android {
std::function<void()> ScopedAlarm::func_;
class AllocatorTest : public testing::Test {
protected:
AllocatorTest() : heap(), disable_malloc_() {}
- virtual void SetUp() {
- heap_count = 0;
- }
+ virtual void SetUp() { heap_count = 0; }
virtual void TearDown() {
ASSERT_EQ(heap_count, 0);
ASSERT_TRUE(heap.empty());
ASSERT_FALSE(disable_malloc_.timed_out());
}
Heap heap;
+
private:
ScopedDisableMallocTimeout disable_malloc_;
};
TEST_F(AllocatorTest, simple) {
Allocator<char[100]> allocator(heap);
- void *ptr = allocator.allocate();
+ void* ptr = allocator.allocate();
ASSERT_TRUE(ptr != NULL);
allocator.deallocate(ptr);
}
TEST_F(AllocatorTest, multiple) {
Allocator<char[100]> allocator(heap);
- void *ptr1 = allocator.allocate();
+ void* ptr1 = allocator.allocate();
ASSERT_TRUE(ptr1 != NULL);
- void *ptr2 = allocator.allocate();
+ void* ptr2 = allocator.allocate();
ASSERT_TRUE(ptr2 != NULL);
ASSERT_NE(ptr1, ptr2);
allocator.deallocate(ptr1);
- void *ptr3 = allocator.allocate();
+ void* ptr3 = allocator.allocate();
ASSERT_EQ(ptr1, ptr3);
allocator.deallocate(ptr3);
allocator.deallocate(ptr2);
@@ -63,7 +63,7 @@
const int num = 4096;
const int size = 128;
Allocator<char[size]> allocator(heap);
- void *ptr[num];
+ void* ptr[num];
for (int i = 0; i < num; i++) {
ptr[i] = allocator.allocate();
memset(ptr[i], 0xaa, size);
@@ -87,7 +87,7 @@
TEST_F(AllocatorTest, large) {
const size_t size = 1024 * 1024;
Allocator<char[size]> allocator(heap);
- void *ptr = allocator.allocate();
+ void* ptr = allocator.allocate();
memset(ptr, 0xaa, size);
allocator.deallocate(ptr);
}
@@ -96,7 +96,7 @@
const int num = 128;
const int size = 1024 * 1024;
Allocator<char[size]> allocator(heap);
- void *ptr[num];
+ void* ptr[num];
for (int i = 0; i < num; i++) {
ptr[i] = allocator.allocate();
memset(ptr[i], 0xaa, size);
@@ -172,3 +172,5 @@
ASSERT_NE(ptr, nullptr);
}
+
+} // namespace android
diff --git a/libmemunreachable/tests/DisableMalloc_test.cpp b/libmemunreachable/tests/DisableMalloc_test.cpp
index 4e6155b..c630049 100644
--- a/libmemunreachable/tests/DisableMalloc_test.cpp
+++ b/libmemunreachable/tests/DisableMalloc_test.cpp
@@ -19,11 +19,13 @@
#include <chrono>
#include <functional>
-#include <gtest/gtest.h>
#include <ScopedDisableMalloc.h>
+#include <gtest/gtest.h>
using namespace std::chrono_literals;
+namespace android {
+
class DisableMallocTest : public ::testing::Test {
protected:
void alarm(std::chrono::microseconds us) {
@@ -36,75 +38,83 @@
};
TEST_F(DisableMallocTest, reenable) {
- ASSERT_EXIT({
- alarm(100ms);
- void *ptr1 = malloc(128);
- ASSERT_NE(ptr1, nullptr);
- free(ptr1);
- {
- ScopedDisableMalloc disable_malloc;
- }
- void *ptr2 = malloc(128);
- ASSERT_NE(ptr2, nullptr);
- free(ptr2);
- _exit(1);
- }, ::testing::ExitedWithCode(1), "");
+ ASSERT_EXIT(
+ {
+ alarm(100ms);
+ void* ptr1 = malloc(128);
+ ASSERT_NE(ptr1, nullptr);
+ free(ptr1);
+ { ScopedDisableMalloc disable_malloc; }
+ void* ptr2 = malloc(128);
+ ASSERT_NE(ptr2, nullptr);
+ free(ptr2);
+ _exit(1);
+ },
+ ::testing::ExitedWithCode(1), "");
}
TEST_F(DisableMallocTest, deadlock_allocate) {
- ASSERT_DEATH({
- void *ptr = malloc(128);
- ASSERT_NE(ptr, nullptr);
- free(ptr);
- {
- alarm(100ms);
- ScopedDisableMalloc disable_malloc;
- void* ptr = malloc(128);
- ASSERT_NE(ptr, nullptr);
- free(ptr);
- }
- }, "");
+ ASSERT_DEATH(
+ {
+ void* ptr = malloc(128);
+ ASSERT_NE(ptr, nullptr);
+ free(ptr);
+ {
+ alarm(100ms);
+ ScopedDisableMalloc disable_malloc;
+ void* ptr = malloc(128);
+ ASSERT_NE(ptr, nullptr);
+ free(ptr);
+ }
+ },
+ "");
}
TEST_F(DisableMallocTest, deadlock_new) {
- ASSERT_DEATH({
- char* ptr = new(char);
- ASSERT_NE(ptr, nullptr);
- delete(ptr);
- {
- alarm(100ms);
- ScopedDisableMalloc disable_malloc;
- char* ptr = new (std::nothrow)(char);
- ASSERT_NE(ptr, nullptr);
- delete(ptr);
- }
- }, "");
+ ASSERT_DEATH(
+ {
+ char* ptr = new (char);
+ ASSERT_NE(ptr, nullptr);
+ delete (ptr);
+ {
+ alarm(100ms);
+ ScopedDisableMalloc disable_malloc;
+ char* ptr = new (std::nothrow)(char);
+ ASSERT_NE(ptr, nullptr);
+ delete (ptr);
+ }
+ },
+ "");
}
TEST_F(DisableMallocTest, deadlock_delete) {
- ASSERT_DEATH({
- char* ptr = new(char);
- ASSERT_NE(ptr, nullptr);
- {
- alarm(250ms);
- ScopedDisableMalloc disable_malloc;
- delete(ptr);
- // Force ptr usage or this code gets optimized away by the arm64 compiler.
- ASSERT_NE(ptr, nullptr);
- }
- }, "");
+ ASSERT_DEATH(
+ {
+ char* ptr = new (char);
+ ASSERT_NE(ptr, nullptr);
+ {
+ alarm(250ms);
+ ScopedDisableMalloc disable_malloc;
+ delete (ptr);
+ // Force ptr usage or this code gets optimized away by the arm64 compiler.
+ ASSERT_NE(ptr, nullptr);
+ }
+ },
+ "");
}
TEST_F(DisableMallocTest, deadlock_free) {
- ASSERT_DEATH({
- void *ptr = malloc(128);
- ASSERT_NE(ptr, nullptr);
- {
- alarm(100ms);
- ScopedDisableMalloc disable_malloc;
- free(ptr);
- }
- }, "");
+ ASSERT_DEATH(
+ {
+ void* ptr = malloc(128);
+ ASSERT_NE(ptr, nullptr);
+ {
+ alarm(100ms);
+ ScopedDisableMalloc disable_malloc;
+ free(ptr);
+ }
+ },
+ "");
}
TEST_F(DisableMallocTest, deadlock_fork) {
@@ -113,6 +123,8 @@
alarm(100ms);
ScopedDisableMalloc disable_malloc;
fork();
- }
- }, "");
}
+}, "");
+}
+
+} // namespace android
diff --git a/libmemunreachable/tests/HeapWalker_test.cpp b/libmemunreachable/tests/HeapWalker_test.cpp
index 98e4aa1..84a0ec6 100644
--- a/libmemunreachable/tests/HeapWalker_test.cpp
+++ b/libmemunreachable/tests/HeapWalker_test.cpp
@@ -19,10 +19,12 @@
#include "HeapWalker.h"
-#include <gtest/gtest.h>
#include <ScopedDisableMalloc.h>
+#include <gtest/gtest.h>
#include "Allocator.h"
+namespace android {
+
class HeapWalkerTest : public ::testing::Test {
public:
HeapWalkerTest() : disable_malloc_(), heap_() {}
@@ -172,20 +174,20 @@
ASSERT_EQ(true, heap_walker.Leaked(leaked, 100, &num_leaks, &leaked_bytes));
EXPECT_EQ(2U, num_leaks);
- EXPECT_EQ(2*sizeof(uintptr_t), leaked_bytes);
+ EXPECT_EQ(2 * sizeof(uintptr_t), leaked_bytes);
ASSERT_EQ(2U, leaked.size());
}
TEST_F(HeapWalkerTest, segv) {
const size_t page_size = sysconf(_SC_PAGE_SIZE);
- void* buffer1 = mmap(NULL, page_size, PROT_NONE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+ void* buffer1 = mmap(NULL, page_size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
ASSERT_NE(buffer1, nullptr);
void* buffer2;
buffer2 = &buffer1;
HeapWalker heap_walker(heap_);
- heap_walker.Allocation(buffer_begin(buffer1), buffer_begin(buffer1)+page_size);
+ heap_walker.Allocation(buffer_begin(buffer1), buffer_begin(buffer1) + page_size);
heap_walker.Root(buffer_begin(buffer2), buffer_end(buffer2));
ASSERT_EQ(true, heap_walker.DetectLeaks());
@@ -199,3 +201,5 @@
EXPECT_EQ(0U, leaked_bytes);
ASSERT_EQ(0U, leaked.size());
}
+
+} // namespace android
diff --git a/libmemunreachable/tests/HostMallocStub.cpp b/libmemunreachable/tests/HostMallocStub.cpp
index a7e3f07..0ef0487 100644
--- a/libmemunreachable/tests/HostMallocStub.cpp
+++ b/libmemunreachable/tests/HostMallocStub.cpp
@@ -16,8 +16,6 @@
#include "bionic.h"
-void malloc_disable() {
-}
+void malloc_disable() {}
-void malloc_enable() {
-}
+void malloc_enable() {}
diff --git a/libmemunreachable/tests/LeakFolding_test.cpp b/libmemunreachable/tests/LeakFolding_test.cpp
index e85df5f..f5b3631 100644
--- a/libmemunreachable/tests/LeakFolding_test.cpp
+++ b/libmemunreachable/tests/LeakFolding_test.cpp
@@ -14,13 +14,15 @@
* limitations under the License.
*/
-#include "HeapWalker.h"
#include "LeakFolding.h"
+#include "HeapWalker.h"
-#include <gtest/gtest.h>
#include <ScopedDisableMalloc.h>
+#include <gtest/gtest.h>
#include "Allocator.h"
+namespace android {
+
class LeakFoldingTest : public ::testing::Test {
public:
LeakFoldingTest() : disable_malloc_(), heap_() {}
@@ -84,7 +86,7 @@
ASSERT_EQ(true, folding.Leaked(leaked, &num_leaks, &leaked_bytes));
EXPECT_EQ(2U, num_leaks);
- EXPECT_EQ(2*sizeof(uintptr_t), leaked_bytes);
+ EXPECT_EQ(2 * sizeof(uintptr_t), leaked_bytes);
ASSERT_EQ(2U, leaked.size());
EXPECT_EQ(0U, leaked[0].referenced_count);
EXPECT_EQ(0U, leaked[0].referenced_size);
@@ -113,7 +115,7 @@
ASSERT_EQ(true, folding.Leaked(leaked, &num_leaks, &leaked_bytes));
EXPECT_EQ(2U, num_leaks);
- EXPECT_EQ(2*sizeof(uintptr_t), leaked_bytes);
+ EXPECT_EQ(2 * sizeof(uintptr_t), leaked_bytes);
ASSERT_EQ(1U, leaked.size());
EXPECT_EQ(1U, leaked[0].referenced_count);
EXPECT_EQ(sizeof(uintptr_t), leaked[0].referenced_size);
@@ -144,10 +146,10 @@
ASSERT_EQ(true, folding.Leaked(leaked, &num_leaks, &leaked_bytes));
EXPECT_EQ(3U, num_leaks);
- EXPECT_EQ(3*sizeof(uintptr_t), leaked_bytes);
+ EXPECT_EQ(3 * sizeof(uintptr_t), leaked_bytes);
ASSERT_EQ(1U, leaked.size());
EXPECT_EQ(2U, leaked[0].referenced_count);
- EXPECT_EQ(2*sizeof(uintptr_t), leaked[0].referenced_size);
+ EXPECT_EQ(2 * sizeof(uintptr_t), leaked[0].referenced_size);
}
TEST_F(LeakFoldingTest, dominator_cycle) {
@@ -175,13 +177,13 @@
ASSERT_EQ(true, folding.Leaked(leaked, &num_leaks, &leaked_bytes));
EXPECT_EQ(3U, num_leaks);
- EXPECT_EQ(5*sizeof(uintptr_t), leaked_bytes);
+ EXPECT_EQ(5 * sizeof(uintptr_t), leaked_bytes);
ASSERT_EQ(2U, leaked.size());
EXPECT_EQ(2U, leaked[0].referenced_count);
- EXPECT_EQ(3*sizeof(uintptr_t), leaked[0].referenced_size);
+ EXPECT_EQ(3 * sizeof(uintptr_t), leaked[0].referenced_size);
EXPECT_EQ(2U, leaked[1].referenced_count);
- EXPECT_EQ(3*sizeof(uintptr_t), leaked[1].referenced_size);
+ EXPECT_EQ(3 * sizeof(uintptr_t), leaked[1].referenced_size);
}
TEST_F(LeakFoldingTest, two_cycles) {
@@ -218,12 +220,12 @@
ASSERT_EQ(true, folding.Leaked(leaked, &num_leaks, &leaked_bytes));
EXPECT_EQ(6U, num_leaks);
- EXPECT_EQ(6*sizeof(uintptr_t), leaked_bytes);
+ EXPECT_EQ(6 * sizeof(uintptr_t), leaked_bytes);
ASSERT_EQ(2U, leaked.size());
EXPECT_EQ(2U, leaked[0].referenced_count);
- EXPECT_EQ(2*sizeof(uintptr_t), leaked[0].referenced_size);
+ EXPECT_EQ(2 * sizeof(uintptr_t), leaked[0].referenced_size);
EXPECT_EQ(2U, leaked[1].referenced_count);
- EXPECT_EQ(2*sizeof(uintptr_t), leaked[1].referenced_size);
+ EXPECT_EQ(2 * sizeof(uintptr_t), leaked[1].referenced_size);
}
TEST_F(LeakFoldingTest, two_dominator_cycles) {
@@ -254,7 +256,7 @@
ASSERT_EQ(true, folding.Leaked(leaked, &num_leaks, &leaked_bytes));
EXPECT_EQ(4U, num_leaks);
- EXPECT_EQ(4*sizeof(uintptr_t), leaked_bytes);
+ EXPECT_EQ(4 * sizeof(uintptr_t), leaked_bytes);
ASSERT_EQ(4U, leaked.size());
EXPECT_EQ(1U, leaked[0].referenced_count);
EXPECT_EQ(sizeof(uintptr_t), leaked[0].referenced_size);
@@ -272,13 +274,13 @@
HeapWalker heap_walker(heap_);
- for (size_t i = 0; i < n; i ++) {
+ for (size_t i = 0; i < n; i++) {
ASSERT_TRUE(heap_walker.Allocation(reinterpret_cast<uintptr_t>(&buffer[i]),
- reinterpret_cast<uintptr_t>(&buffer[i+1])));
+ reinterpret_cast<uintptr_t>(&buffer[i + 1])));
}
for (size_t i = 0; i < n - 1; i++) {
- buffer[i] = &buffer[i+1];
+ buffer[i] = &buffer[i + 1];
}
buffer[n - 1] = &buffer[0];
@@ -306,15 +308,15 @@
HeapWalker heap_walker(heap_);
for (size_t i = 0; i < n - 1; i++) {
- buffer[i] = &buffer[i+1];
+ buffer[i] = &buffer[i + 1];
}
buffer[n - 1] = &buffer[0];
buffer1[0] = &buffer[0];
- for (size_t i = 0; i < n; i ++) {
+ for (size_t i = 0; i < n; i++) {
ASSERT_TRUE(heap_walker.Allocation(reinterpret_cast<uintptr_t>(&buffer[i]),
- reinterpret_cast<uintptr_t>(&buffer[i+1])));
+ reinterpret_cast<uintptr_t>(&buffer[i + 1])));
}
ALLOCATION(heap_walker, buffer1);
@@ -425,3 +427,5 @@
EXPECT_EQ(3U, leaked[3].referenced_count);
EXPECT_EQ(6 * sizeof(uintptr_t), leaked[3].referenced_size);
}
+
+} // namespace android
diff --git a/libmemunreachable/tests/MemUnreachable_test.cpp b/libmemunreachable/tests/MemUnreachable_test.cpp
index 71da365..ec89388 100644
--- a/libmemunreachable/tests/MemUnreachable_test.cpp
+++ b/libmemunreachable/tests/MemUnreachable_test.cpp
@@ -16,36 +16,32 @@
#include <fcntl.h>
#include <stdlib.h>
-#include <unistd.h>
#include <sys/prctl.h>
+#include <unistd.h>
#include <gtest/gtest.h>
#include <memunreachable/memunreachable.h>
+namespace android {
+
class HiddenPointer {
public:
- explicit HiddenPointer(size_t size = 256) {
- Set(malloc(size));
- }
- ~HiddenPointer() {
- Free();
- }
- void* Get() {
- return reinterpret_cast<void*>(~ptr_);
- }
+ explicit HiddenPointer(size_t size = 256) { Set(malloc(size)); }
+ ~HiddenPointer() { Free(); }
+ void* Get() { return reinterpret_cast<void*>(~ptr_); }
void Free() {
free(Get());
Set(nullptr);
}
+
private:
- void Set(void* ptr) {
- ptr_ = ~reinterpret_cast<uintptr_t>(ptr);
- }
+ void Set(void* ptr) { ptr_ = ~reinterpret_cast<uintptr_t>(ptr); }
volatile uintptr_t ptr_;
};
-static void Ref(void* ptr) {
+// Trick the compiler into thinking a value on the stack is still referenced.
+static void Ref(void** ptr) {
write(0, ptr, 0);
}
@@ -63,14 +59,14 @@
{
void* ptr = hidden_ptr.Get();
- Ref(ptr);
+ Ref(&ptr);
UnreachableMemoryInfo info;
ASSERT_TRUE(GetUnreachableMemory(info));
ASSERT_EQ(0U, info.leaks.size());
- Ref(ptr);
+ ptr = nullptr;
}
{
@@ -216,3 +212,5 @@
ASSERT_TRUE(LogUnreachableMemory(true, 100));
}
+
+} // namespace android
diff --git a/libmemunreachable/tests/ThreadCapture_test.cpp b/libmemunreachable/tests/ThreadCapture_test.cpp
index 44aabd7..4fbf729 100644
--- a/libmemunreachable/tests/ThreadCapture_test.cpp
+++ b/libmemunreachable/tests/ThreadCapture_test.cpp
@@ -34,6 +34,8 @@
using namespace std::chrono_literals;
+namespace android {
+
class ThreadListTest : public ::testing::TestWithParam<int> {
public:
ThreadListTest() : stop_(false) {}
@@ -45,12 +47,10 @@
WaitForThreads();
}
- virtual void TearDown() {
- ASSERT_TRUE(heap.empty());
- }
+ virtual void TearDown() { ASSERT_TRUE(heap.empty()); }
protected:
- template<class Function>
+ template <class Function>
void StartThreads(unsigned int threads, Function&& func) {
threads_.reserve(threads);
tids_.reserve(threads);
@@ -68,14 +68,14 @@
{
std::unique_lock<std::mutex> lk(m_);
- cv_stop_.wait(lk, [&] {return stop_;});
+ cv_stop_.wait(lk, [&] { return stop_; });
}
});
}
{
std::unique_lock<std::mutex> lk(m_);
- cv_start_.wait(lk, [&]{ return tids_.size() == threads; });
+ cv_start_.wait(lk, [&] { return tids_.size() == threads; });
}
}
@@ -93,9 +93,7 @@
tids_.clear();
}
- std::vector<pid_t>& tids() {
- return tids_;
- }
+ std::vector<pid_t>& tids() { return tids_; }
Heap heap;
@@ -143,7 +141,7 @@
TEST_P(ThreadListTest, list_some) {
const unsigned int threads = GetParam() - 1;
- StartThreads(threads, [](){});
+ StartThreads(threads, []() {});
std::vector<pid_t> expected_tids = tids();
expected_tids.push_back(getpid());
@@ -176,10 +174,8 @@
public:
ThreadCaptureTest() {}
~ThreadCaptureTest() {}
- void Fork(std::function<void()>&& child_init,
- std::function<void()>&& child_cleanup,
- std::function<void(pid_t)>&& parent) {
-
+ void Fork(std::function<void()>&& child_init, std::function<void()>&& child_cleanup,
+ std::function<void(pid_t)>&& parent) {
ScopedPipe start_pipe;
ScopedPipe stop_pipe;
@@ -211,39 +207,40 @@
TEST_P(ThreadCaptureTest, capture_some) {
const unsigned int threads = GetParam();
- Fork([&](){
- // child init
- StartThreads(threads - 1, [](){});
- },
- [&](){
- // child cleanup
- StopThreads();
- },
- [&](pid_t child){
- // parent
- ASSERT_GT(child, 0);
+ Fork(
+ [&]() {
+ // child init
+ StartThreads(threads - 1, []() {});
+ },
+ [&]() {
+ // child cleanup
+ StopThreads();
+ },
+ [&](pid_t child) {
+ // parent
+ ASSERT_GT(child, 0);
- {
- ScopedDisableMallocTimeout disable_malloc;
+ {
+ ScopedDisableMallocTimeout disable_malloc;
- ThreadCapture thread_capture(child, heap);
- auto list_tids = allocator::vector<pid_t>(heap);
+ ThreadCapture thread_capture(child, heap);
+ auto list_tids = allocator::vector<pid_t>(heap);
- ASSERT_TRUE(thread_capture.ListThreads(list_tids));
- ASSERT_EQ(threads, list_tids.size());
+ ASSERT_TRUE(thread_capture.ListThreads(list_tids));
+ ASSERT_EQ(threads, list_tids.size());
- ASSERT_TRUE(thread_capture.CaptureThreads());
+ ASSERT_TRUE(thread_capture.CaptureThreads());
- auto thread_info = allocator::vector<ThreadInfo>(heap);
- ASSERT_TRUE(thread_capture.CapturedThreadInfo(thread_info));
- ASSERT_EQ(threads, thread_info.size());
- ASSERT_TRUE(thread_capture.ReleaseThreads());
+ auto thread_info = allocator::vector<ThreadInfo>(heap);
+ ASSERT_TRUE(thread_capture.CapturedThreadInfo(thread_info));
+ ASSERT_EQ(threads, thread_info.size());
+ ASSERT_TRUE(thread_capture.ReleaseThreads());
- if (!HasFailure()) {
- ASSERT_FALSE(disable_malloc.timed_out());
- }
-}
- });
+ if (!HasFailure()) {
+ ASSERT_FALSE(disable_malloc.timed_out());
+ }
+ }
+ });
}
INSTANTIATE_TEST_CASE_P(ThreadCaptureTest, ThreadCaptureTest, ::testing::Values(1, 2, 10, 1024));
@@ -262,7 +259,7 @@
ScopedDisableMallocTimeout disable_malloc;
ThreadCapture thread_capture(ret, heap);
- thread_capture.InjectTestFunc([&](pid_t tid){
+ thread_capture.InjectTestFunc([&](pid_t tid) {
syscall(SYS_tgkill, ret, tid, SIGKILL);
usleep(10000);
});
@@ -288,62 +285,65 @@
// For signal handler
static ScopedPipe* g_pipe;
- Fork([&](){
- // child init
- pipe.CloseReceiver();
+ Fork(
+ [&]() {
+ // child init
+ pipe.CloseReceiver();
- g_pipe = &pipe;
+ g_pipe = &pipe;
- struct sigaction act{};
- act.sa_handler = [](int){
- char buf = '+';
- write(g_pipe->Sender(), &buf, 1);
- g_pipe->CloseSender();
- };
- sigaction(sig, &act, NULL);
- sigset_t set;
- sigemptyset(&set);
- sigaddset(&set, sig);
- pthread_sigmask(SIG_UNBLOCK, &set, NULL);
- },
- [&](){
- // child cleanup
- g_pipe = nullptr;
- pipe.Close();
- },
- [&](pid_t child){
- // parent
- ASSERT_GT(child, 0);
- pipe.CloseSender();
+ struct sigaction act {};
+ act.sa_handler = [](int) {
+ char buf = '+';
+ write(g_pipe->Sender(), &buf, 1);
+ g_pipe->CloseSender();
+ };
+ sigaction(sig, &act, NULL);
+ sigset_t set;
+ sigemptyset(&set);
+ sigaddset(&set, sig);
+ pthread_sigmask(SIG_UNBLOCK, &set, NULL);
+ },
+ [&]() {
+ // child cleanup
+ g_pipe = nullptr;
+ pipe.Close();
+ },
+ [&](pid_t child) {
+ // parent
+ ASSERT_GT(child, 0);
+ pipe.CloseSender();
- {
- ScopedDisableMallocTimeout disable_malloc;
+ {
+ ScopedDisableMallocTimeout disable_malloc;
- ThreadCapture thread_capture(child, heap);
- thread_capture.InjectTestFunc([&](pid_t tid){
- syscall(SYS_tgkill, child, tid, sig);
- usleep(10000);
+ ThreadCapture thread_capture(child, heap);
+ thread_capture.InjectTestFunc([&](pid_t tid) {
+ syscall(SYS_tgkill, child, tid, sig);
+ usleep(10000);
+ });
+ auto list_tids = allocator::vector<pid_t>(heap);
+
+ ASSERT_TRUE(thread_capture.ListThreads(list_tids));
+ ASSERT_EQ(1U, list_tids.size());
+
+ ASSERT_TRUE(thread_capture.CaptureThreads());
+
+ auto thread_info = allocator::vector<ThreadInfo>(heap);
+ ASSERT_TRUE(thread_capture.CapturedThreadInfo(thread_info));
+ ASSERT_EQ(1U, thread_info.size());
+ ASSERT_TRUE(thread_capture.ReleaseThreads());
+
+ usleep(100000);
+ char buf;
+ ASSERT_EQ(1, TEMP_FAILURE_RETRY(read(pipe.Receiver(), &buf, 1)));
+ ASSERT_EQ(buf, '+');
+
+ if (!HasFailure()) {
+ ASSERT_FALSE(disable_malloc.timed_out());
+ }
+ }
});
- auto list_tids = allocator::vector<pid_t>(heap);
-
- ASSERT_TRUE(thread_capture.ListThreads(list_tids));
- ASSERT_EQ(1U, list_tids.size());
-
- ASSERT_TRUE(thread_capture.CaptureThreads());
-
- auto thread_info = allocator::vector<ThreadInfo>(heap);
- ASSERT_TRUE(thread_capture.CapturedThreadInfo(thread_info));
- ASSERT_EQ(1U, thread_info.size());
- ASSERT_TRUE(thread_capture.ReleaseThreads());
-
- usleep(100000);
- char buf;
- ASSERT_EQ(1, TEMP_FAILURE_RETRY(read(pipe.Receiver(), &buf, 1)));
- ASSERT_EQ(buf, '+');
-
- if (!HasFailure()) {
- ASSERT_FALSE(disable_malloc.timed_out());
- }
- }
- });
}
+
+} // namespace android
diff --git a/libsysutils/src/FrameworkListener.cpp b/libsysutils/src/FrameworkListener.cpp
index 1b6076f..6f76e76 100644
--- a/libsysutils/src/FrameworkListener.cpp
+++ b/libsysutils/src/FrameworkListener.cpp
@@ -68,7 +68,7 @@
android_errorWriteLog(0x534e4554, "29831647");
c->sendMsg(500, "Command too large for buffer", false);
mSkipToNextNullByte = true;
- return false;
+ return true;
}
int offset = 0;
diff --git a/libunwindstack/Elf.h b/libunwindstack/Elf.h
index 7bf45b8..f9db541 100644
--- a/libunwindstack/Elf.h
+++ b/libunwindstack/Elf.h
@@ -45,8 +45,8 @@
return valid_ && interface_->GetSoname(name);
}
- bool GetFunctionName(uint64_t, std::string*, uint64_t*) {
- return false;
+ bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) {
+ return valid_ && interface_->GetFunctionName(addr, name, func_offset);
}
bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory) {
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
index bfa7944..3a7f7cb 100644
--- a/libunwindstack/ElfInterface.cpp
+++ b/libunwindstack/ElfInterface.cpp
@@ -22,9 +22,18 @@
#include "DwarfDebugFrame.h"
#include "DwarfEhFrame.h"
+#include "DwarfSection.h"
#include "ElfInterface.h"
+#include "Log.h"
#include "Memory.h"
#include "Regs.h"
+#include "Symbols.h"
+
+ElfInterface::~ElfInterface() {
+ for (auto symbol : symbols_) {
+ delete symbol;
+ }
+}
template <typename AddressType>
void ElfInterface::InitHeadersWithTemplate() {
@@ -57,7 +66,13 @@
if (!ReadProgramHeaders<EhdrType, PhdrType>(ehdr)) {
return false;
}
- return ReadSectionHeaders<EhdrType, ShdrType>(ehdr);
+
+ // We could still potentially unwind without the section header
+ // information, so ignore any errors.
+ if (!ReadSectionHeaders<EhdrType, ShdrType>(ehdr)) {
+ log(0, "Malformed section header found, ignoring...");
+ }
+ return true;
}
template <typename EhdrType, typename PhdrType>
@@ -147,12 +162,39 @@
}
// Skip the first header, it's always going to be NULL.
+ offset += ehdr.e_shentsize;
for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) {
if (!memory_->ReadField(offset, &shdr, &shdr.sh_type, sizeof(shdr.sh_type))) {
return false;
}
- if (shdr.sh_type == SHT_PROGBITS) {
+ if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
+ if (!memory_->Read(offset, &shdr, sizeof(shdr))) {
+ return false;
+ }
+ // Need to go get the information about the section that contains
+ // the string terminated names.
+ ShdrType str_shdr;
+ if (shdr.sh_link >= ehdr.e_shnum) {
+ return false;
+ }
+ uint64_t str_offset = ehdr.e_shoff + shdr.sh_link * ehdr.e_shentsize;
+ if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_type, sizeof(str_shdr.sh_type))) {
+ return false;
+ }
+ if (str_shdr.sh_type != SHT_STRTAB) {
+ return false;
+ }
+ if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_offset,
+ sizeof(str_shdr.sh_offset))) {
+ return false;
+ }
+ if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_size, sizeof(str_shdr.sh_size))) {
+ return false;
+ }
+ symbols_.push_back(new Symbols(shdr.sh_offset, shdr.sh_size, shdr.sh_entsize,
+ str_shdr.sh_offset, str_shdr.sh_size));
+ } else if (shdr.sh_type == SHT_PROGBITS && sec_size != 0) {
// Look for the .debug_frame and .gnu_debugdata.
if (!memory_->ReadField(offset, &shdr, &shdr.sh_name, sizeof(shdr.sh_name))) {
return false;
@@ -160,18 +202,20 @@
if (shdr.sh_name < sec_size) {
std::string name;
if (memory_->ReadString(sec_offset + shdr.sh_name, &name)) {
+ uint64_t* offset_ptr = nullptr;
+ uint64_t* size_ptr = nullptr;
if (name == ".debug_frame") {
- if (memory_->ReadField(offset, &shdr, &shdr.sh_offset, sizeof(shdr.sh_offset)) &&
- memory_->ReadField(offset, &shdr, &shdr.sh_size, sizeof(shdr.sh_size))) {
- debug_frame_offset_ = shdr.sh_offset;
- debug_frame_size_ = shdr.sh_size;
- }
+ offset_ptr = &debug_frame_offset_;
+ size_ptr = &debug_frame_size_;
} else if (name == ".gnu_debugdata") {
- if (memory_->ReadField(offset, &shdr, &shdr.sh_offset, sizeof(shdr.sh_offset)) &&
- memory_->ReadField(offset, &shdr, &shdr.sh_size, sizeof(shdr.sh_size))) {
- gnu_debugdata_offset_ = shdr.sh_offset;
- gnu_debugdata_size_ = shdr.sh_size;
- }
+ offset_ptr = &gnu_debugdata_offset_;
+ size_ptr = &gnu_debugdata_size_;
+ }
+ if (offset_ptr != nullptr &&
+ memory_->ReadField(offset, &shdr, &shdr.sh_offset, sizeof(shdr.sh_offset)) &&
+ memory_->ReadField(offset, &shdr, &shdr.sh_size, sizeof(shdr.sh_size))) {
+ *offset_ptr = shdr.sh_offset;
+ *size_ptr = shdr.sh_size;
}
}
}
@@ -228,7 +272,40 @@
return true;
}
-bool ElfInterface::Step(uint64_t, Regs*, Memory*) {
+template <typename SymType>
+bool ElfInterface::GetFunctionNameWithTemplate(uint64_t addr, std::string* name,
+ uint64_t* func_offset) {
+ if (symbols_.empty()) {
+ return false;
+ }
+
+ for (const auto symbol : symbols_) {
+ if (symbol->GetName<SymType>(addr, load_bias_, memory_, name, func_offset)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool ElfInterface::Step(uint64_t pc, Regs* regs, Memory* process_memory) {
+ // Need to subtract off the load_bias to get the correct pc.
+ if (pc < load_bias_) {
+ return false;
+ }
+ pc -= load_bias_;
+
+ // Try the eh_frame first.
+ DwarfSection* eh_frame = eh_frame_.get();
+ if (eh_frame != nullptr && eh_frame->Step(pc, regs, process_memory)) {
+ return true;
+ }
+
+ // Try the debug_frame next.
+ DwarfSection* debug_frame = debug_frame_.get();
+ if (debug_frame != nullptr && debug_frame->Step(pc, regs, process_memory)) {
+ return true;
+ }
+
return false;
}
@@ -247,3 +324,8 @@
template bool ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(std::string*);
template bool ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(std::string*);
+
+template bool ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(uint64_t, std::string*,
+ uint64_t*);
+template bool ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(uint64_t, std::string*,
+ uint64_t*);
diff --git a/libunwindstack/ElfInterface.h b/libunwindstack/ElfInterface.h
index 1cc8aa0..d0d0d28 100644
--- a/libunwindstack/ElfInterface.h
+++ b/libunwindstack/ElfInterface.h
@@ -30,6 +30,7 @@
// Forward declarations.
class Memory;
class Regs;
+class Symbols;
struct LoadInfo {
uint64_t offset;
@@ -46,7 +47,7 @@
class ElfInterface {
public:
ElfInterface(Memory* memory) : memory_(memory) {}
- virtual ~ElfInterface() = default;
+ virtual ~ElfInterface();
virtual bool Init() = 0;
@@ -94,6 +95,9 @@
template <typename DynType>
bool GetSonameWithTemplate(std::string* soname);
+ template <typename SymType>
+ bool GetFunctionNameWithTemplate(uint64_t addr, std::string* name, uint64_t* func_offset);
+
virtual bool HandleType(uint64_t, uint32_t) { return false; }
Memory* memory_;
@@ -118,6 +122,8 @@
std::unique_ptr<DwarfSection> eh_frame_;
std::unique_ptr<DwarfSection> debug_frame_;
+
+ std::vector<Symbols*> symbols_;
};
class ElfInterface32 : public ElfInterface {
@@ -135,8 +141,8 @@
return ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(soname);
}
- bool GetFunctionName(uint64_t, std::string*, uint64_t*) override {
- return false;
+ bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) override {
+ return ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(addr, name, func_offset);
}
};
@@ -155,8 +161,8 @@
return ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(soname);
}
- bool GetFunctionName(uint64_t, std::string*, uint64_t*) override {
- return false;
+ bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) override {
+ return ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(addr, name, func_offset);
}
};
diff --git a/libunwindstack/tests/ElfInterfaceTest.cpp b/libunwindstack/tests/ElfInterfaceTest.cpp
index 81cdaf5..0f56ba8 100644
--- a/libunwindstack/tests/ElfInterfaceTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceTest.cpp
@@ -79,9 +79,37 @@
template <typename ElfType>
void InitHeadersDebugFrameFail();
+ template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
+ void InitSectionHeadersMalformed();
+
+ template <typename Ehdr, typename Shdr, typename Sym, typename ElfInterfaceType>
+ void InitSectionHeaders(uint64_t entry_size);
+
+ template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
+ void InitSectionHeadersOffsets();
+
+ template <typename Sym>
+ void InitSym(uint64_t offset, uint32_t value, uint32_t size, uint32_t name_offset,
+ uint64_t sym_offset, const char* name);
+
MemoryFake memory_;
};
+template <typename Sym>
+void ElfInterfaceTest::InitSym(uint64_t offset, uint32_t value, uint32_t size, uint32_t name_offset,
+ uint64_t sym_offset, const char* name) {
+ Sym sym;
+ memset(&sym, 0, sizeof(sym));
+ sym.st_info = STT_FUNC;
+ sym.st_value = value;
+ sym.st_size = size;
+ sym.st_name = name_offset;
+ sym.st_shndx = SHN_COMMON;
+
+ memory_.SetMemory(offset, &sym, sizeof(sym));
+ memory_.SetMemory(sym_offset + name_offset, name, strlen(name) + 1);
+}
+
template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
void ElfInterfaceTest::SinglePtLoad() {
std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
@@ -718,3 +746,178 @@
TEST_F(ElfInterfaceTest, init_headers_debug_frame64_fail) {
InitHeadersDebugFrameFail<MockElfInterface64>();
}
+
+template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
+void ElfInterfaceTest::InitSectionHeadersMalformed() {
+ std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
+
+ Ehdr ehdr;
+ memset(&ehdr, 0, sizeof(ehdr));
+ ehdr.e_shoff = 0x1000;
+ ehdr.e_shnum = 10;
+ ehdr.e_shentsize = sizeof(Shdr);
+ memory_.SetMemory(0, &ehdr, sizeof(ehdr));
+
+ ASSERT_TRUE(elf->Init());
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_malformed32) {
+ InitSectionHeadersMalformed<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>();
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_malformed64) {
+ InitSectionHeadersMalformed<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>();
+}
+
+template <typename Ehdr, typename Shdr, typename Sym, typename ElfInterfaceType>
+void ElfInterfaceTest::InitSectionHeaders(uint64_t entry_size) {
+ std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
+
+ uint64_t offset = 0x1000;
+
+ Ehdr ehdr;
+ memset(&ehdr, 0, sizeof(ehdr));
+ ehdr.e_shoff = offset;
+ ehdr.e_shnum = 10;
+ ehdr.e_shentsize = entry_size;
+ memory_.SetMemory(0, &ehdr, sizeof(ehdr));
+
+ offset += ehdr.e_shentsize;
+
+ Shdr shdr;
+ memset(&shdr, 0, sizeof(shdr));
+ shdr.sh_type = SHT_SYMTAB;
+ shdr.sh_link = 4;
+ shdr.sh_addr = 0x5000;
+ shdr.sh_offset = 0x5000;
+ shdr.sh_entsize = sizeof(Sym);
+ shdr.sh_size = shdr.sh_entsize * 10;
+ memory_.SetMemory(offset, &shdr, sizeof(shdr));
+ offset += ehdr.e_shentsize;
+
+ memset(&shdr, 0, sizeof(shdr));
+ shdr.sh_type = SHT_DYNSYM;
+ shdr.sh_link = 4;
+ shdr.sh_addr = 0x6000;
+ shdr.sh_offset = 0x6000;
+ shdr.sh_entsize = sizeof(Sym);
+ shdr.sh_size = shdr.sh_entsize * 10;
+ memory_.SetMemory(offset, &shdr, sizeof(shdr));
+ offset += ehdr.e_shentsize;
+
+ memset(&shdr, 0, sizeof(shdr));
+ shdr.sh_type = SHT_PROGBITS;
+ shdr.sh_name = 0xa000;
+ memory_.SetMemory(offset, &shdr, sizeof(shdr));
+ offset += ehdr.e_shentsize;
+
+ // The string data for the entries.
+ memset(&shdr, 0, sizeof(shdr));
+ shdr.sh_type = SHT_STRTAB;
+ shdr.sh_name = 0x20000;
+ shdr.sh_offset = 0xf000;
+ shdr.sh_size = 0x1000;
+ memory_.SetMemory(offset, &shdr, sizeof(shdr));
+ offset += ehdr.e_shentsize;
+
+ InitSym<Sym>(0x5000, 0x90000, 0x1000, 0x100, 0xf000, "function_one");
+ InitSym<Sym>(0x6000, 0xd0000, 0x1000, 0x300, 0xf000, "function_two");
+
+ ASSERT_TRUE(elf->Init());
+ EXPECT_EQ(0U, elf->debug_frame_offset());
+ EXPECT_EQ(0U, elf->debug_frame_size());
+ EXPECT_EQ(0U, elf->gnu_debugdata_offset());
+ EXPECT_EQ(0U, elf->gnu_debugdata_size());
+
+ // Look in the first symbol table.
+ std::string name;
+ uint64_t name_offset;
+ ASSERT_TRUE(elf->GetFunctionName(0x90010, &name, &name_offset));
+ EXPECT_EQ("function_one", name);
+ EXPECT_EQ(16U, name_offset);
+ ASSERT_TRUE(elf->GetFunctionName(0xd0020, &name, &name_offset));
+ EXPECT_EQ("function_two", name);
+ EXPECT_EQ(32U, name_offset);
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers32) {
+ InitSectionHeaders<Elf32_Ehdr, Elf32_Shdr, Elf32_Sym, ElfInterface32>(sizeof(Elf32_Shdr));
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers64) {
+ InitSectionHeaders<Elf64_Ehdr, Elf64_Shdr, Elf64_Sym, ElfInterface64>(sizeof(Elf64_Shdr));
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_non_std_entry_size32) {
+ InitSectionHeaders<Elf32_Ehdr, Elf32_Shdr, Elf32_Sym, ElfInterface32>(0x100);
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_non_std_entry_size64) {
+ InitSectionHeaders<Elf64_Ehdr, Elf64_Shdr, Elf64_Sym, ElfInterface64>(0x100);
+}
+
+template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
+void ElfInterfaceTest::InitSectionHeadersOffsets() {
+ std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
+
+ uint64_t offset = 0x2000;
+
+ Ehdr ehdr;
+ memset(&ehdr, 0, sizeof(ehdr));
+ ehdr.e_shoff = offset;
+ ehdr.e_shnum = 10;
+ ehdr.e_shentsize = sizeof(Shdr);
+ ehdr.e_shstrndx = 2;
+ memory_.SetMemory(0, &ehdr, sizeof(ehdr));
+
+ offset += ehdr.e_shentsize;
+
+ Shdr shdr;
+ memset(&shdr, 0, sizeof(shdr));
+ shdr.sh_type = SHT_PROGBITS;
+ shdr.sh_link = 2;
+ shdr.sh_name = 0x200;
+ shdr.sh_addr = 0x5000;
+ shdr.sh_offset = 0x5000;
+ shdr.sh_entsize = 0x100;
+ shdr.sh_size = 0x800;
+ memory_.SetMemory(offset, &shdr, sizeof(shdr));
+ offset += ehdr.e_shentsize;
+
+ // The string data for section header names.
+ memset(&shdr, 0, sizeof(shdr));
+ shdr.sh_type = SHT_STRTAB;
+ shdr.sh_name = 0x20000;
+ shdr.sh_offset = 0xf000;
+ shdr.sh_size = 0x1000;
+ memory_.SetMemory(offset, &shdr, sizeof(shdr));
+ offset += ehdr.e_shentsize;
+
+ memset(&shdr, 0, sizeof(shdr));
+ shdr.sh_type = SHT_PROGBITS;
+ shdr.sh_link = 2;
+ shdr.sh_name = 0x100;
+ shdr.sh_addr = 0x6000;
+ shdr.sh_offset = 0x6000;
+ shdr.sh_entsize = 0x100;
+ shdr.sh_size = 0x500;
+ memory_.SetMemory(offset, &shdr, sizeof(shdr));
+ offset += ehdr.e_shentsize;
+
+ memory_.SetMemory(0xf100, ".debug_frame", sizeof(".debug_frame"));
+ memory_.SetMemory(0xf200, ".gnu_debugdata", sizeof(".gnu_debugdata"));
+
+ ASSERT_TRUE(elf->Init());
+ EXPECT_EQ(0x6000U, elf->debug_frame_offset());
+ EXPECT_EQ(0x500U, elf->debug_frame_size());
+ EXPECT_EQ(0x5000U, elf->gnu_debugdata_offset());
+ EXPECT_EQ(0x800U, elf->gnu_debugdata_size());
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_offsets32) {
+ InitSectionHeadersOffsets<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>();
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_offsets64) {
+ InitSectionHeadersOffsets<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>();
+}