Merge "trusty: keymaster: set_attestation_key: Change wrapped key"
diff --git a/Android.bp b/Android.bp
deleted file mode 100644
index 0b4a925..0000000
--- a/Android.bp
+++ /dev/null
@@ -1,4 +0,0 @@
-filegroup {
- name: "android_filesystem_config_header",
- srcs: ["include/private/android_filesystem_config.h"],
-}
diff --git a/fastboot/Android.bp b/fastboot/Android.bp
index e6f9ffa..fe05553 100644
--- a/fastboot/Android.bp
+++ b/fastboot/Android.bp
@@ -126,7 +126,7 @@
shared_libs: [
"android.hardware.boot@1.0",
"android.hardware.boot@1.1",
- "android.hardware.fastboot@1.0",
+ "android.hardware.fastboot@1.1",
"android.hardware.health@2.0",
"libasyncio",
"libbase",
@@ -147,7 +147,6 @@
static_libs: [
"libgtest_prod",
"libhealthhalutils",
- "libsnapshot_cow",
"libsnapshot_nobinder",
"update_metadata-protos",
],
diff --git a/fastboot/device/commands.cpp b/fastboot/device/commands.cpp
index 2553353..4601960 100644
--- a/fastboot/device/commands.cpp
+++ b/fastboot/device/commands.cpp
@@ -164,6 +164,28 @@
return device->WriteOkay(message);
}
+bool OemPostWipeData(FastbootDevice* device) {
+ auto fastboot_hal = device->fastboot_hal();
+ if (!fastboot_hal) {
+ return false;
+ }
+
+ Result ret;
+ auto ret_val = fastboot_hal->doOemSpecificErase([&](Result result) { ret = result; });
+ if (!ret_val.isOk()) {
+ return false;
+ }
+ if (ret.status == Status::NOT_SUPPORTED) {
+ return false;
+ } else if (ret.status != Status::SUCCESS) {
+ device->WriteStatus(FastbootResult::FAIL, ret.message);
+ } else {
+ device->WriteStatus(FastbootResult::OKAY, "Erasing succeeded");
+ }
+
+ return true;
+}
+
bool EraseHandler(FastbootDevice* device, const std::vector<std::string>& args) {
if (args.size() < 2) {
return device->WriteStatus(FastbootResult::FAIL, "Invalid arguments");
@@ -184,7 +206,18 @@
return device->WriteStatus(FastbootResult::FAIL, "Partition doesn't exist");
}
if (wipe_block_device(handle.fd(), get_block_device_size(handle.fd())) == 0) {
- return device->WriteStatus(FastbootResult::OKAY, "Erasing succeeded");
+ //Perform oem PostWipeData if Android userdata partition has been erased
+ bool support_oem_postwipedata = false;
+ if (partition_name == "userdata") {
+ support_oem_postwipedata = OemPostWipeData(device);
+ }
+
+ if (!support_oem_postwipedata) {
+ return device->WriteStatus(FastbootResult::OKAY, "Erasing succeeded");
+ } else {
+ //Write device status in OemPostWipeData(), so just return true
+ return true;
+ }
}
return device->WriteStatus(FastbootResult::FAIL, "Erasing failed");
}
diff --git a/fastboot/device/fastboot_device.cpp b/fastboot/device/fastboot_device.cpp
index 1b0859f..52ea9f0 100644
--- a/fastboot/device/fastboot_device.cpp
+++ b/fastboot/device/fastboot_device.cpp
@@ -22,7 +22,7 @@
#include <android-base/properties.h>
#include <android-base/strings.h>
#include <android/hardware/boot/1.0/IBootControl.h>
-#include <android/hardware/fastboot/1.0/IFastboot.h>
+#include <android/hardware/fastboot/1.1/IFastboot.h>
#include <fs_mgr.h>
#include <fs_mgr/roots.h>
#include <healthhalutils/HealthHalUtils.h>
@@ -37,7 +37,7 @@
using ::android::hardware::hidl_string;
using ::android::hardware::boot::V1_0::IBootControl;
using ::android::hardware::boot::V1_0::Slot;
-using ::android::hardware::fastboot::V1_0::IFastboot;
+using ::android::hardware::fastboot::V1_1::IFastboot;
using ::android::hardware::health::V2_0::get_health_service;
namespace sph = std::placeholders;
diff --git a/fastboot/device/fastboot_device.h b/fastboot/device/fastboot_device.h
index bbe8172..23be721 100644
--- a/fastboot/device/fastboot_device.h
+++ b/fastboot/device/fastboot_device.h
@@ -24,7 +24,7 @@
#include <android/hardware/boot/1.0/IBootControl.h>
#include <android/hardware/boot/1.1/IBootControl.h>
-#include <android/hardware/fastboot/1.0/IFastboot.h>
+#include <android/hardware/fastboot/1.1/IFastboot.h>
#include <android/hardware/health/2.0/IHealth.h>
#include "commands.h"
@@ -53,7 +53,7 @@
return boot_control_hal_;
}
android::sp<android::hardware::boot::V1_1::IBootControl> boot1_1() { return boot1_1_; }
- android::sp<android::hardware::fastboot::V1_0::IFastboot> fastboot_hal() {
+ android::sp<android::hardware::fastboot::V1_1::IFastboot> fastboot_hal() {
return fastboot_hal_;
}
android::sp<android::hardware::health::V2_0::IHealth> health_hal() { return health_hal_; }
@@ -67,7 +67,7 @@
android::sp<android::hardware::boot::V1_0::IBootControl> boot_control_hal_;
android::sp<android::hardware::boot::V1_1::IBootControl> boot1_1_;
android::sp<android::hardware::health::V2_0::IHealth> health_hal_;
- android::sp<android::hardware::fastboot::V1_0::IFastboot> fastboot_hal_;
+ android::sp<android::hardware::fastboot::V1_1::IFastboot> fastboot_hal_;
std::vector<char> download_data_;
std::string active_slot_;
};
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index ddffef2..db2e16c 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -74,11 +74,9 @@
"android/snapshot/snapshot.proto",
"device_info.cpp",
"snapshot.cpp",
- "snapshot_reader.cpp",
"snapshot_stats.cpp",
"snapshot_stub.cpp",
"snapshot_metadata_updater.cpp",
- "snapshot_writer.cpp",
"partition_cow_creator.cpp",
"return.cpp",
"utility.cpp",
@@ -249,7 +247,6 @@
"libgmock",
"liblp",
"libsnapshot",
- "libsnapshot_cow",
"libsnapshot_test_helpers",
"libsparse",
],
@@ -284,7 +281,6 @@
static_libs: [
"libfstab",
"libsnapshot",
- "libsnapshot_cow",
"update_metadata-protos",
],
shared_libs: [
@@ -348,7 +344,6 @@
"libgmock", // from libsnapshot_test_helpers
"liblog",
"liblp",
- "libsnapshot_cow",
"libsnapshot_test_helpers",
"libprotobuf-mutator",
],
diff --git a/fs_mgr/libsnapshot/cow_writer.cpp b/fs_mgr/libsnapshot/cow_writer.cpp
index f96f174..70fdac1 100644
--- a/fs_mgr/libsnapshot/cow_writer.cpp
+++ b/fs_mgr/libsnapshot/cow_writer.cpp
@@ -32,9 +32,6 @@
static_assert(sizeof(off_t) == sizeof(uint64_t));
-using android::base::borrowed_fd;
-using android::base::unique_fd;
-
bool ICowWriter::AddCopy(uint64_t new_block, uint64_t old_block) {
if (!ValidateNewBlock(new_block)) {
return false;
@@ -101,12 +98,12 @@
return true;
}
-bool CowWriter::Initialize(unique_fd&& fd, OpenMode mode) {
+bool CowWriter::Initialize(android::base::unique_fd&& fd, OpenMode mode) {
owned_fd_ = std::move(fd);
- return Initialize(borrowed_fd{owned_fd_}, mode);
+ return Initialize(android::base::borrowed_fd{owned_fd_}, mode);
}
-bool CowWriter::Initialize(borrowed_fd fd, OpenMode mode) {
+bool CowWriter::Initialize(android::base::borrowed_fd fd, OpenMode mode) {
fd_ = fd;
if (!ParseOptions()) {
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
index 2bc0171..245da0c 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
@@ -58,9 +58,6 @@
// Return number of bytes the cow image occupies on disk.
virtual uint64_t GetCowSize() = 0;
- // Returns true if AddCopy() operations are supported.
- virtual bool SupportsCopyOperation() const { return true; }
-
const CowOptions& options() { return options_; }
protected:
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h
index 13f19aa..eb6ad05 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h
@@ -38,7 +38,9 @@
(const android::fs_mgr::CreateLogicalPartitionParams& params,
std::string* snapshot_path),
(override));
- MOCK_METHOD(std::unique_ptr<ISnapshotWriter>, OpenSnapshotWriter,
+ MOCK_METHOD(std::unique_ptr<ICowWriter>, OpenSnapshotWriter,
+ (const android::fs_mgr::CreateLogicalPartitionParams& params), (override));
+ MOCK_METHOD(std::unique_ptr<FileDescriptor>, OpenSnapshotReader,
(const android::fs_mgr::CreateLogicalPartitionParams& params), (override));
MOCK_METHOD(bool, UnmapUpdateSnapshot, (const std::string& target_partition_name), (override));
MOCK_METHOD(bool, NeedSnapshotsInFirstStageMount, (), (override));
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index 1bc972e..6fef58a 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -35,8 +35,8 @@
#include <update_engine/update_metadata.pb.h>
#include <libsnapshot/auto_device.h>
+#include <libsnapshot/cow_writer.h>
#include <libsnapshot/return.h>
-#include <libsnapshot/snapshot_writer.h>
#ifndef FRIEND_TEST
#define FRIEND_TEST(test_set_name, individual_test) \
@@ -44,6 +44,10 @@
#define DEFINED_FRIEND_TEST
#endif
+namespace chromeos_update_engine {
+class FileDescriptor;
+} // namespace chromeos_update_engine
+
namespace android {
namespace fiemap {
@@ -106,6 +110,8 @@
};
virtual ~ISnapshotManager() = default;
+ using FileDescriptor = chromeos_update_engine::FileDescriptor;
+
// Begin an update. This must be called before creating any snapshots. It
// will fail if GetUpdateState() != None.
virtual bool BeginUpdate() = 0;
@@ -181,14 +187,19 @@
virtual bool MapUpdateSnapshot(const android::fs_mgr::CreateLogicalPartitionParams& params,
std::string* snapshot_path) = 0;
- // Create an ISnapshotWriter to build a snapshot against a target partition. The partition name
- // must be suffixed.
- virtual std::unique_ptr<ISnapshotWriter> OpenSnapshotWriter(
+ // Create an ICowWriter to build a snapshot against a target partition. The partition name must
+ // be suffixed.
+ virtual std::unique_ptr<ICowWriter> OpenSnapshotWriter(
+ const android::fs_mgr::CreateLogicalPartitionParams& params) = 0;
+
+ // Open a snapshot for reading. A file-like interface is provided through the FileDescriptor.
+ // In this mode, writes are not supported. The partition name must be suffixed.
+ virtual std::unique_ptr<FileDescriptor> OpenSnapshotReader(
const android::fs_mgr::CreateLogicalPartitionParams& params) = 0;
// Unmap a snapshot device or CowWriter that was previously opened with MapUpdateSnapshot,
- // OpenSnapshotWriter. All outstanding open descriptors, writers, or
- // readers must be deleted before this is called.
+ // OpenSnapshotWriter, or OpenSnapshotReader. All outstanding open descriptors, writers,
+ // or readers must be deleted before this is called.
virtual bool UnmapUpdateSnapshot(const std::string& target_partition_name) = 0;
// If this returns true, first-stage mount must call
@@ -299,7 +310,9 @@
Return CreateUpdateSnapshots(const DeltaArchiveManifest& manifest) override;
bool MapUpdateSnapshot(const CreateLogicalPartitionParams& params,
std::string* snapshot_path) override;
- std::unique_ptr<ISnapshotWriter> OpenSnapshotWriter(
+ std::unique_ptr<ICowWriter> OpenSnapshotWriter(
+ const android::fs_mgr::CreateLogicalPartitionParams& params) override;
+ std::unique_ptr<FileDescriptor> OpenSnapshotReader(
const android::fs_mgr::CreateLogicalPartitionParams& params) override;
bool UnmapUpdateSnapshot(const std::string& target_partition_name) override;
bool NeedSnapshotsInFirstStageMount() override;
@@ -519,39 +532,9 @@
std::string GetSnapshotDeviceName(const std::string& snapshot_name,
const SnapshotStatus& status);
- // Reason for calling MapPartitionWithSnapshot.
- enum class SnapshotContext {
- // For writing or verification (during update_engine).
- Update,
-
- // For mounting a full readable device.
- Mount,
- };
-
- struct SnapshotPaths {
- // Target/base device (eg system_b), always present.
- std::string target_device;
-
- // COW path (eg system_cow). Not present if no COW is needed.
- std::string cow_device;
-
- // dm-snapshot instance. Not present in Update mode for VABC.
- std::string snapshot_device;
- };
-
- // Helpers for OpenSnapshotWriter.
- std::unique_ptr<ISnapshotWriter> OpenCompressedSnapshotWriter(LockedFile* lock,
- const std::string& partition_name,
- const SnapshotStatus& status,
- const SnapshotPaths& paths);
- std::unique_ptr<ISnapshotWriter> OpenKernelSnapshotWriter(LockedFile* lock,
- const std::string& partition_name,
- const SnapshotStatus& status,
- const SnapshotPaths& paths);
-
// Map the base device, COW devices, and snapshot device.
bool MapPartitionWithSnapshot(LockedFile* lock, CreateLogicalPartitionParams params,
- SnapshotContext context, SnapshotPaths* paths);
+ std::string* path);
// Map the COW devices, including the partition in super and the images.
// |params|:
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h
index cda2bee..149f463 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h
@@ -36,7 +36,9 @@
const chromeos_update_engine::DeltaArchiveManifest& manifest) override;
bool MapUpdateSnapshot(const android::fs_mgr::CreateLogicalPartitionParams& params,
std::string* snapshot_path) override;
- std::unique_ptr<ISnapshotWriter> OpenSnapshotWriter(
+ std::unique_ptr<ICowWriter> OpenSnapshotWriter(
+ const android::fs_mgr::CreateLogicalPartitionParams& params) override;
+ std::unique_ptr<FileDescriptor> OpenSnapshotReader(
const android::fs_mgr::CreateLogicalPartitionParams& params) override;
bool UnmapUpdateSnapshot(const std::string& target_partition_name) override;
bool NeedSnapshotsInFirstStageMount() override;
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h
deleted file mode 100644
index bf57a00..0000000
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#pragma once
-
-#include <android-base/unique_fd.h>
-
-#include <libsnapshot/cow_writer.h>
-
-namespace chromeos_update_engine {
-class FileDescriptor;
-} // namespace chromeos_update_engine
-
-namespace android {
-namespace snapshot {
-
-class ISnapshotWriter : public ICowWriter {
- public:
- using FileDescriptor = chromeos_update_engine::FileDescriptor;
-
- explicit ISnapshotWriter(const CowOptions& options);
-
- // Set the source device. This is used for AddCopy() operations, if the
- // underlying writer needs the original bytes (for example if backed by
- // dm-snapshot or if writing directly to an unsnapshotted region).
- void SetSourceDevice(android::base::unique_fd&& source_fd);
-
- virtual std::unique_ptr<FileDescriptor> OpenReader() = 0;
-
- protected:
- android::base::unique_fd source_fd_;
-};
-
-// Write directly to a dm-snapshot device.
-class OnlineKernelSnapshotWriter : public ISnapshotWriter {
- public:
- OnlineKernelSnapshotWriter(const CowOptions& options);
-
- // Set the device used for all writes.
- void SetSnapshotDevice(android::base::unique_fd&& snapshot_fd, uint64_t cow_size);
-
- bool Flush() override;
- uint64_t GetCowSize() override { return cow_size_; }
- virtual std::unique_ptr<FileDescriptor> OpenReader() override;
-
- protected:
- bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override;
- bool EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) override;
- bool EmitCopy(uint64_t new_block, uint64_t old_block) override;
-
- private:
- android::base::unique_fd snapshot_fd_;
- uint64_t cow_size_ = 0;
-};
-
-} // namespace snapshot
-} // namespace android
diff --git a/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h b/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h
index 197aeaa..8e369b0 100644
--- a/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h
+++ b/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h
@@ -144,7 +144,6 @@
// Expect space of |path| is multiple of 4K.
bool WriteRandomData(const std::string& path, std::optional<size_t> expect_size = std::nullopt,
std::string* hash = nullptr);
-bool WriteRandomData(ICowWriter* writer, std::string* hash = nullptr);
std::optional<std::string> GetHash(const std::string& path);
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index b672d0e..0904fc7 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -15,7 +15,6 @@
#include <libsnapshot/snapshot.h>
#include <dirent.h>
-#include <fcntl.h>
#include <math.h>
#include <sys/file.h>
#include <sys/types.h>
@@ -44,7 +43,6 @@
#include "device_info.h"
#include "partition_cow_creator.h"
#include "snapshot_metadata_updater.h"
-#include "snapshot_reader.h"
#include "utility.h"
namespace android {
@@ -1572,8 +1570,7 @@
.timeout_ms = timeout_ms,
};
std::string ignore_path;
- if (!MapPartitionWithSnapshot(lock.get(), std::move(params), SnapshotContext::Mount,
- nullptr)) {
+ if (!MapPartitionWithSnapshot(lock.get(), std::move(params), &ignore_path)) {
return false;
}
}
@@ -1601,10 +1598,11 @@
bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock,
CreateLogicalPartitionParams params,
- SnapshotContext context, SnapshotPaths* paths) {
+ std::string* path) {
auto begin = std::chrono::steady_clock::now();
CHECK(lock);
+ path->clear();
if (params.GetPartitionName() != params.GetDeviceName()) {
LOG(ERROR) << "Mapping snapshot with a different name is unsupported: partition_name = "
@@ -1685,11 +1683,8 @@
}
created_devices.EmplaceBack<AutoUnmapDevice>(&dm, params.GetDeviceName());
- if (paths) {
- paths->target_device = base_path;
- }
-
if (!live_snapshot_status.has_value()) {
+ *path = base_path;
created_devices.Release();
return true;
}
@@ -1716,33 +1711,21 @@
LOG(ERROR) << "Could not determine major/minor for: " << cow_name;
return false;
}
- if (paths) {
- paths->cow_device = cow_device;
- }
remaining_time = GetRemainingTime(params.timeout_ms, begin);
if (remaining_time.count() < 0) return false;
- if (context == SnapshotContext::Update && IsCompressionEnabled()) {
- // Stop here, we can't run dm-user yet, the COW isn't built.
- return true;
- }
-
- std::string path;
if (!MapSnapshot(lock, params.GetPartitionName(), base_device, cow_device, remaining_time,
- &path)) {
+ path)) {
LOG(ERROR) << "Could not map snapshot for partition: " << params.GetPartitionName();
return false;
}
// No need to add params.GetPartitionName() to created_devices since it is immediately released.
- if (paths) {
- paths->snapshot_device = path;
- }
-
created_devices.Release();
- LOG(INFO) << "Mapped " << params.GetPartitionName() << " as snapshot device at " << path;
+ LOG(INFO) << "Mapped " << params.GetPartitionName() << " as snapshot device at " << *path;
+
return true;
}
@@ -2455,86 +2438,23 @@
<< params.GetPartitionName();
return false;
}
-
- SnapshotPaths paths;
- if (!MapPartitionWithSnapshot(lock.get(), params, SnapshotContext::Update, &paths)) {
- return false;
- }
-
- if (paths.snapshot_device.empty()) {
- *snapshot_path = paths.snapshot_device;
- } else {
- *snapshot_path = paths.target_device;
- }
- return true;
+ return MapPartitionWithSnapshot(lock.get(), params, snapshot_path);
}
-std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenSnapshotWriter(
+std::unique_ptr<ICowWriter> SnapshotManager::OpenSnapshotWriter(
const android::fs_mgr::CreateLogicalPartitionParams& params) {
- // First unmap any existing mapping.
- auto lock = LockShared();
- if (!lock) return nullptr;
- if (!UnmapPartitionWithSnapshot(lock.get(), params.GetPartitionName())) {
- LOG(ERROR) << "Cannot unmap existing snapshot before re-mapping it: "
- << params.GetPartitionName();
- return nullptr;
- }
+ (void)params;
- SnapshotPaths paths;
- if (!MapPartitionWithSnapshot(lock.get(), params, SnapshotContext::Update, &paths)) {
- return nullptr;
- }
-
- SnapshotStatus status;
- if (!paths.cow_device.empty()) {
- if (!ReadSnapshotStatus(lock.get(), params.GetPartitionName(), &status)) {
- return nullptr;
- }
- } else {
- // Currently, partition_cow_creator always creates snapshots. The
- // reason is that if partition X shrinks while partition Y grows, we
- // cannot bindly write to the newly freed extents in X. This would
- // make the old slot unusable. So, the entire size of the target
- // partition is currently considered snapshottable.
- LOG(ERROR) << "No snapshot available for partition " << params.GetPartitionName();
- return nullptr;
- }
-
- if (IsCompressionEnabled()) {
- return OpenCompressedSnapshotWriter(lock.get(), params.GetPartitionName(), status, paths);
- } else {
- return OpenKernelSnapshotWriter(lock.get(), params.GetPartitionName(), status, paths);
- }
-}
-
-std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenCompressedSnapshotWriter(
- LockedFile*, const std::string&, const SnapshotStatus&, const SnapshotPaths&) {
- LOG(ERROR) << "OpenSnapshotWriter not yet implemented for compression";
+ LOG(ERROR) << "OpenSnapshotWriter not yet implemented";
return nullptr;
}
-std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenKernelSnapshotWriter(
- LockedFile* lock, [[maybe_unused]] const std::string& partition_name,
- const SnapshotStatus& status, const SnapshotPaths& paths) {
- CHECK(lock);
+std::unique_ptr<FileDescriptor> SnapshotManager::OpenSnapshotReader(
+ const android::fs_mgr::CreateLogicalPartitionParams& params) {
+ (void)params;
- CowOptions cow_options;
- cow_options.max_blocks = {status.device_size() / cow_options.block_size};
-
- auto writer = std::make_unique<OnlineKernelSnapshotWriter>(cow_options);
-
- std::string_view path =
- paths.snapshot_device.empty() ? paths.target_device : paths.snapshot_device;
- unique_fd fd(open(path.data(), O_RDWR | O_CLOEXEC));
- if (fd < 0) {
- PLOG(ERROR) << "open failed: " << path;
- return nullptr;
- }
-
- uint64_t cow_size = status.cow_partition_size() + status.cow_file_size();
- writer->SetSnapshotDevice(std::move(fd), cow_size);
-
- return writer;
+ LOG(ERROR) << "OpenSnapshotReader not yet implemented";
+ return nullptr;
}
bool SnapshotManager::UnmapUpdateSnapshot(const std::string& target_partition_name) {
diff --git a/fs_mgr/libsnapshot/snapshot_reader.cpp b/fs_mgr/libsnapshot/snapshot_reader.cpp
deleted file mode 100644
index 0d47468..0000000
--- a/fs_mgr/libsnapshot/snapshot_reader.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-//
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#include <ext4_utils/ext4_utils.h>
-
-#include "snapshot_reader.h"
-
-namespace android {
-namespace snapshot {
-
-// Not supported.
-bool ReadOnlyFileDescriptor::Open(const char*, int, mode_t) {
- errno = EINVAL;
- return false;
-}
-
-bool ReadOnlyFileDescriptor::Open(const char*, int) {
- errno = EINVAL;
- return false;
-}
-
-ssize_t ReadOnlyFileDescriptor::Write(const void*, size_t) {
- errno = EINVAL;
- return false;
-}
-
-bool ReadOnlyFileDescriptor::BlkIoctl(int, uint64_t, uint64_t, int*) {
- errno = EINVAL;
- return false;
-}
-
-ReadFdFileDescriptor::ReadFdFileDescriptor(android::base::unique_fd&& fd) : fd_(std::move(fd)) {}
-
-ssize_t ReadFdFileDescriptor::Read(void* buf, size_t count) {
- return read(fd_.get(), buf, count);
-}
-
-off64_t ReadFdFileDescriptor::Seek(off64_t offset, int whence) {
- return lseek(fd_.get(), offset, whence);
-}
-
-uint64_t ReadFdFileDescriptor::BlockDevSize() {
- return get_block_device_size(fd_.get());
-}
-
-bool ReadFdFileDescriptor::Close() {
- fd_ = {};
- return true;
-}
-
-bool ReadFdFileDescriptor::IsSettingErrno() {
- return true;
-}
-
-bool ReadFdFileDescriptor::IsOpen() {
- return fd_ >= 0;
-}
-
-bool ReadFdFileDescriptor::Flush() {
- return true;
-}
-
-} // namespace snapshot
-} // namespace android
diff --git a/fs_mgr/libsnapshot/snapshot_reader.h b/fs_mgr/libsnapshot/snapshot_reader.h
deleted file mode 100644
index 1f2ffe2..0000000
--- a/fs_mgr/libsnapshot/snapshot_reader.h
+++ /dev/null
@@ -1,50 +0,0 @@
-//
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#pragma once
-
-#include <android-base/file.h>
-#include <payload_consumer/file_descriptor.h>
-
-namespace android {
-namespace snapshot {
-
-class ReadOnlyFileDescriptor : public chromeos_update_engine::FileDescriptor {
- public:
- bool Open(const char* path, int flags, mode_t mode) override;
- bool Open(const char* path, int flags) override;
- ssize_t Write(const void* buf, size_t count) override;
- bool BlkIoctl(int request, uint64_t start, uint64_t length, int* result) override;
-};
-
-class ReadFdFileDescriptor : public ReadOnlyFileDescriptor {
- public:
- explicit ReadFdFileDescriptor(android::base::unique_fd&& fd);
-
- ssize_t Read(void* buf, size_t count) override;
- off64_t Seek(off64_t offset, int whence) override;
- uint64_t BlockDevSize() override;
- bool Close() override;
- bool IsSettingErrno() override;
- bool IsOpen() override;
- bool Flush() override;
-
- private:
- android::base::unique_fd fd_;
-};
-
-} // namespace snapshot
-} // namespace android
diff --git a/fs_mgr/libsnapshot/snapshot_stub.cpp b/fs_mgr/libsnapshot/snapshot_stub.cpp
index 41f5da4..8ae6305 100644
--- a/fs_mgr/libsnapshot/snapshot_stub.cpp
+++ b/fs_mgr/libsnapshot/snapshot_stub.cpp
@@ -130,7 +130,13 @@
return &snapshot_merge_stats;
}
-std::unique_ptr<ISnapshotWriter> SnapshotManagerStub::OpenSnapshotWriter(
+std::unique_ptr<ICowWriter> SnapshotManagerStub::OpenSnapshotWriter(
+ const CreateLogicalPartitionParams&) {
+ LOG(ERROR) << __FUNCTION__ << " should never be called.";
+ return nullptr;
+}
+
+std::unique_ptr<FileDescriptor> SnapshotManagerStub::OpenSnapshotReader(
const CreateLogicalPartitionParams&) {
LOG(ERROR) << __FUNCTION__ << " should never be called.";
return nullptr;
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index f2caaa4..6ff935b 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -80,7 +80,6 @@
std::string fake_super;
void MountMetadata();
-bool IsCompressionEnabled();
class SnapshotTest : public ::testing::Test {
public:
@@ -893,39 +892,42 @@
return AssertionSuccess();
}
- AssertionResult MapUpdateSnapshot(const std::string& name,
- std::unique_ptr<ICowWriter>* writer = nullptr) {
- CreateLogicalPartitionParams params{
- .block_device = fake_super,
- .metadata_slot = 1,
- .partition_name = name,
- .timeout_ms = 10s,
- .partition_opener = opener_.get(),
- };
-
- auto result = sm->OpenSnapshotWriter(params);
- if (!result) {
- return AssertionFailure() << "Cannot open snapshot for writing: " << name;
+ AssertionResult MapUpdateSnapshot(const std::string& name, std::string* path = nullptr) {
+ std::string real_path;
+ if (!sm->MapUpdateSnapshot(
+ CreateLogicalPartitionParams{
+ .block_device = fake_super,
+ .metadata_slot = 1,
+ .partition_name = name,
+ .timeout_ms = 10s,
+ .partition_opener = opener_.get(),
+ },
+ &real_path)) {
+ return AssertionFailure() << "Unable to map snapshot " << name;
}
-
- if (writer) {
- *writer = std::move(result);
+ if (path) {
+ *path = real_path;
}
- return AssertionSuccess();
+ return AssertionSuccess() << "Mapped snapshot " << name << " to " << real_path;
}
- AssertionResult WriteSnapshotAndHash(const std::string& name) {
- std::unique_ptr<ICowWriter> writer;
- auto res = MapUpdateSnapshot(name, &writer);
+ AssertionResult WriteSnapshotAndHash(const std::string& name,
+ std::optional<size_t> size = std::nullopt) {
+ std::string path;
+ auto res = MapUpdateSnapshot(name, &path);
if (!res) {
return res;
}
- if (!WriteRandomData(writer.get(), &hashes_[name])) {
- return AssertionFailure() << "Unable to write random data to snapshot " << name;
+ std::string size_string = size ? (std::to_string(*size) + " bytes") : "";
+
+ if (!WriteRandomData(path, size, &hashes_[name])) {
+ return AssertionFailure() << "Unable to write " << size_string << " to " << path
+ << " for partition " << name;
}
- return AssertionSuccess() << "Written random data to snapshot " << name
+ return AssertionSuccess() << "Written " << size_string << " to " << path
+ << " for snapshot partition " << name
<< ", hash: " << hashes_[name];
}
@@ -1001,7 +1003,7 @@
// Write some data to target partitions.
for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
- ASSERT_TRUE(WriteSnapshotAndHash(name));
+ ASSERT_TRUE(WriteSnapshotAndHash(name, partition_size));
}
// Assert that source partitions aren't affected.
@@ -1404,10 +1406,6 @@
MetadataMountedTest().TearDown();
}
-bool IsCompressionEnabled() {
- return android::base::GetBoolProperty("ro.virtual_ab.compression.enabled", false);
-}
-
TEST_F(MetadataMountedTest, Android) {
auto device = sm->EnsureMetadataMounted();
EXPECT_NE(nullptr, device);
@@ -1625,7 +1623,7 @@
// Map and write some data to target partition.
ASSERT_TRUE(MapUpdateSnapshots({"vnd_b", "prd_b"}));
- ASSERT_TRUE(WriteSnapshotAndHash("sys_b"));
+ ASSERT_TRUE(WriteSnapshotAndHash("sys_b", partition_size));
// Finish update.
ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
@@ -1657,7 +1655,7 @@
// Map and write some data to target partitions.
ASSERT_TRUE(MapUpdateSnapshots({"vnd_b", "prd_b"}));
- ASSERT_TRUE(WriteSnapshotAndHash("sys_b"));
+ ASSERT_TRUE(WriteSnapshotAndHash("sys_b", actual_write_size));
std::vector<android::dm::DeviceMapper::TargetInfo> table;
ASSERT_TRUE(DeviceMapper::Instance().GetTableStatus("sys_b", &table));
diff --git a/fs_mgr/libsnapshot/snapshot_writer.cpp b/fs_mgr/libsnapshot/snapshot_writer.cpp
deleted file mode 100644
index 584f15e..0000000
--- a/fs_mgr/libsnapshot/snapshot_writer.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-//
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#include <libsnapshot/snapshot_writer.h>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <payload_consumer/file_descriptor.h>
-#include "snapshot_reader.h"
-
-namespace android {
-namespace snapshot {
-
-using android::base::unique_fd;
-using chromeos_update_engine::FileDescriptor;
-
-ISnapshotWriter::ISnapshotWriter(const CowOptions& options) : ICowWriter(options) {}
-
-void ISnapshotWriter::SetSourceDevice(android::base::unique_fd&& source_fd) {
- source_fd_ = std::move(source_fd);
-}
-
-OnlineKernelSnapshotWriter::OnlineKernelSnapshotWriter(const CowOptions& options)
- : ISnapshotWriter(options) {}
-
-void OnlineKernelSnapshotWriter::SetSnapshotDevice(android::base::unique_fd&& snapshot_fd,
- uint64_t cow_size) {
- snapshot_fd_ = std::move(snapshot_fd);
- cow_size_ = cow_size;
-}
-
-bool OnlineKernelSnapshotWriter::Flush() {
- if (fsync(snapshot_fd_.get()) < 0) {
- PLOG(ERROR) << "fsync";
- return false;
- }
- return true;
-}
-
-bool OnlineKernelSnapshotWriter::EmitRawBlocks(uint64_t new_block_start, const void* data,
- size_t size) {
- uint64_t offset = new_block_start * options_.block_size;
- if (lseek(snapshot_fd_.get(), offset, SEEK_SET) < 0) {
- PLOG(ERROR) << "EmitRawBlocks lseek to offset " << offset;
- return false;
- }
- if (!android::base::WriteFully(snapshot_fd_, data, size)) {
- PLOG(ERROR) << "EmitRawBlocks write";
- return false;
- }
- return true;
-}
-
-bool OnlineKernelSnapshotWriter::EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) {
- std::string zeroes(options_.block_size, 0);
- for (uint64_t i = 0; i < num_blocks; i++) {
- if (!EmitRawBlocks(new_block_start + i, zeroes.data(), zeroes.size())) {
- return false;
- }
- }
- return true;
-}
-
-bool OnlineKernelSnapshotWriter::EmitCopy(uint64_t new_block, uint64_t old_block) {
- std::string buffer(options_.block_size, 0);
- uint64_t offset = old_block * options_.block_size;
- if (!android::base::ReadFullyAtOffset(source_fd_, buffer.data(), buffer.size(), offset)) {
- PLOG(ERROR) << "EmitCopy read";
- return false;
- }
- return EmitRawBlocks(new_block, buffer.data(), buffer.size());
-}
-
-std::unique_ptr<FileDescriptor> OnlineKernelSnapshotWriter::OpenReader() {
- unique_fd fd(dup(snapshot_fd_.get()));
- if (fd < 0) {
- PLOG(ERROR) << "dup2 failed in OpenReader";
- return nullptr;
- }
- return std::make_unique<ReadFdFileDescriptor>(std::move(fd));
-}
-
-} // namespace snapshot
-} // namespace android
diff --git a/fs_mgr/libsnapshot/test_helpers.cpp b/fs_mgr/libsnapshot/test_helpers.cpp
index 6104c82..b07bf91 100644
--- a/fs_mgr/libsnapshot/test_helpers.cpp
+++ b/fs_mgr/libsnapshot/test_helpers.cpp
@@ -127,48 +127,6 @@
return true;
}
-bool WriteRandomData(ICowWriter* writer, std::string* hash) {
- unique_fd rand(open("/dev/urandom", O_RDONLY));
- if (rand < 0) {
- PLOG(ERROR) << "open /dev/urandom";
- return false;
- }
-
- SHA256_CTX ctx;
- if (hash) {
- SHA256_Init(&ctx);
- }
-
- if (!writer->options().max_blocks) {
- LOG(ERROR) << "CowWriter must specify maximum number of blocks";
- return false;
- }
- uint64_t num_blocks = writer->options().max_blocks.value();
-
- size_t block_size = writer->options().block_size;
- std::string block(block_size, '\0');
- for (uint64_t i = 0; i < num_blocks; i++) {
- if (!ReadFully(rand, block.data(), block.size())) {
- PLOG(ERROR) << "read /dev/urandom";
- return false;
- }
- if (!writer->AddRawBlocks(i, block.data(), block.size())) {
- LOG(ERROR) << "Failed to add raw block " << i;
- return false;
- }
- if (hash) {
- SHA256_Update(&ctx, block.data(), block.size());
- }
- }
-
- if (hash) {
- uint8_t out[32];
- SHA256_Final(out, &ctx);
- *hash = ToHexString(out, sizeof(out));
- }
- return true;
-}
-
std::optional<std::string> GetHash(const std::string& path) {
std::string content;
if (!android::base::ReadFileToString(path, &content, true)) {
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
deleted file mode 120000
index f28a564..0000000
--- a/include/private/android_filesystem_config.h
+++ /dev/null
@@ -1 +0,0 @@
-../../libcutils/include/private/android_filesystem_config.h
\ No newline at end of file
diff --git a/init/Android.bp b/init/Android.bp
index c3dd7f6..3f2cd07 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -129,7 +129,6 @@
"libprotobuf-cpp-lite",
"libpropertyinfoserializer",
"libpropertyinfoparser",
- "libsnapshot_cow",
"libsnapshot_init",
"libxml2",
"lib_apex_manifest_proto_lite",
diff --git a/init/Android.mk b/init/Android.mk
index 998e0fd..da94daf 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -112,7 +112,6 @@
libmodprobe \
libext2_uuid \
libprotobuf-cpp-lite \
- libsnapshot_cow \
libsnapshot_init \
update_metadata-protos \
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index 1f775db..b749d87 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -14,6 +14,11 @@
// limitations under the License.
//
+filegroup {
+ name: "android_filesystem_config_header",
+ srcs: ["include/private/android_filesystem_config.h"],
+}
+
// some files must not be compiled when building against Mingw
// they correspond to features not used by our host development tools
// which are also hard or even impossible to port to native Win32
diff --git a/liblog/include_vndk/log/log.h b/liblog/include_vndk/log/log.h
index ab4adc4..fee18c6 100644
--- a/liblog/include_vndk/log/log.h
+++ b/liblog/include_vndk/log/log.h
@@ -1,10 +1,11 @@
/*Special log.h file for VNDK linking modules*/
-#ifndef _LIBS_LOG_LOG_H
-#define _LIBS_LOG_LOG_H
+#pragma once
-/* Historically vendors have depended on this header being included. */
+/* Historically vendors have depended on these headers being included. */
#include <fcntl.h>
+#include <pthread.h>
+#include <unistd.h>
#include <android/log.h>
#include <log/log_id.h>
@@ -24,5 +25,3 @@
#ifndef LOG_TAG
#define LOG_TAG NULL
#endif
-
-#endif /*_LIBS_LOG_LOG_H*/
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index 75a419c..7770b13 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -296,6 +296,8 @@
"tests/files/offline/shared_lib_in_apk_memory_only_arm64/*",
"tests/files/offline/shared_lib_in_apk_single_map_arm64/*",
"tests/files/offline/signal_load_bias_arm/*",
+ "tests/files/offline/signal_fde_x86/*",
+ "tests/files/offline/signal_fde_x86_64/*",
"tests/files/offline/straddle_arm/*",
"tests/files/offline/straddle_arm64/*",
],
diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp
index bf86e6e..ad25e80 100644
--- a/libunwindstack/DwarfSection.cpp
+++ b/libunwindstack/DwarfSection.cpp
@@ -37,7 +37,8 @@
DwarfSection::DwarfSection(Memory* memory) : memory_(memory) {}
-bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) {
+bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished,
+ bool* is_signal_frame) {
// Lookup the pc in the cache.
auto it = loc_regs_.upper_bound(pc);
if (it == loc_regs_.end() || pc < it->second.pc_start) {
@@ -59,6 +60,8 @@
it = loc_regs_.emplace(loc_regs.pc_end, std::move(loc_regs)).first;
}
+ *is_signal_frame = it->second.cie->is_signal_frame;
+
// Now eval the actual registers.
return Eval(it->second.cie, process_memory, it->second, regs, finished);
}
@@ -241,6 +244,9 @@
return false;
}
break;
+ case 'S':
+ cie->is_signal_frame = true;
+ break;
}
}
return true;
@@ -558,8 +564,10 @@
cur_regs->set_pc((*cur_regs)[cie->return_address_register]);
}
- // If the pc was set to zero, consider this the final frame.
- *finished = (cur_regs->pc() == 0) ? true : false;
+ // If the pc was set to zero, consider this the final frame. Exception: if
+ // this is the sigreturn frame, then we want to try to recover the real PC
+ // using the return address (from LR or the stack), so keep going.
+ *finished = (cur_regs->pc() == 0 && !cie->is_signal_frame) ? true : false;
cur_regs->set_sp(eval_info.cfa);
diff --git a/libunwindstack/Elf.cpp b/libunwindstack/Elf.cpp
index 286febc..e098a58 100644
--- a/libunwindstack/Elf.cpp
+++ b/libunwindstack/Elf.cpp
@@ -188,14 +188,15 @@
}
// The relative pc is always relative to the start of the map from which it comes.
-bool Elf::Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished) {
+bool Elf::Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished,
+ bool* is_signal_frame) {
if (!valid_) {
return false;
}
// Lock during the step which can update information in the object.
std::lock_guard<std::mutex> guard(lock_);
- return interface_->Step(rel_pc, regs, process_memory, finished);
+ return interface_->Step(rel_pc, regs, process_memory, finished, is_signal_frame);
}
bool Elf::IsValidElf(Memory* memory) {
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
index 17470fd..0188def 100644
--- a/libunwindstack/ElfInterface.cpp
+++ b/libunwindstack/ElfInterface.cpp
@@ -499,25 +499,27 @@
return false;
}
-bool ElfInterface::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) {
+bool ElfInterface::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished,
+ bool* is_signal_frame) {
last_error_.code = ERROR_NONE;
last_error_.address = 0;
// Try the debug_frame first since it contains the most specific unwind
// information.
DwarfSection* debug_frame = debug_frame_.get();
- if (debug_frame != nullptr && debug_frame->Step(pc, regs, process_memory, finished)) {
+ if (debug_frame != nullptr &&
+ debug_frame->Step(pc, regs, process_memory, finished, is_signal_frame)) {
return true;
}
// Try the eh_frame next.
DwarfSection* eh_frame = eh_frame_.get();
- if (eh_frame != nullptr && eh_frame->Step(pc, regs, process_memory, finished)) {
+ if (eh_frame != nullptr && eh_frame->Step(pc, regs, process_memory, finished, is_signal_frame)) {
return true;
}
if (gnu_debugdata_interface_ != nullptr &&
- gnu_debugdata_interface_->Step(pc, regs, process_memory, finished)) {
+ gnu_debugdata_interface_->Step(pc, regs, process_memory, finished, is_signal_frame)) {
return true;
}
diff --git a/libunwindstack/ElfInterfaceArm.cpp b/libunwindstack/ElfInterfaceArm.cpp
index 76f2dc8..9352a5d 100644
--- a/libunwindstack/ElfInterfaceArm.cpp
+++ b/libunwindstack/ElfInterfaceArm.cpp
@@ -100,12 +100,13 @@
total_entries_ = ph_filesz / 8;
}
-bool ElfInterfaceArm::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) {
+bool ElfInterfaceArm::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished,
+ bool* is_signal_frame) {
// Dwarf unwind information is precise about whether a pc is covered or not,
// but arm unwind information only has ranges of pc. In order to avoid
// incorrectly doing a bad unwind using arm unwind information for a
// different function, always try and unwind with the dwarf information first.
- return ElfInterface32::Step(pc, regs, process_memory, finished) ||
+ return ElfInterface32::Step(pc, regs, process_memory, finished, is_signal_frame) ||
StepExidx(pc, regs, process_memory, finished);
}
diff --git a/libunwindstack/ElfInterfaceArm.h b/libunwindstack/ElfInterfaceArm.h
index 1d71cac..fd824f8 100644
--- a/libunwindstack/ElfInterfaceArm.h
+++ b/libunwindstack/ElfInterfaceArm.h
@@ -72,7 +72,8 @@
void HandleUnknownType(uint32_t type, uint64_t ph_offset, uint64_t ph_filesz) override;
- bool Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) override;
+ bool Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished,
+ bool* is_signal_frame) override;
bool StepExidx(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished);
diff --git a/libunwindstack/LocalUnwinder.cpp b/libunwindstack/LocalUnwinder.cpp
index 05650fb..5f51a73 100644
--- a/libunwindstack/LocalUnwinder.cpp
+++ b/libunwindstack/LocalUnwinder.cpp
@@ -113,9 +113,11 @@
step_pc -= pc_adjustment;
bool finished = false;
+ bool is_signal_frame = false;
if (elf->StepIfSignalHandler(rel_pc, regs.get(), process_memory_.get())) {
step_pc = rel_pc;
- } else if (!elf->Step(step_pc, regs.get(), process_memory_.get(), &finished)) {
+ } else if (!elf->Step(step_pc, regs.get(), process_memory_.get(), &finished,
+ &is_signal_frame)) {
finished = true;
}
diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp
index bcdbde8..9ffc0f7 100644
--- a/libunwindstack/Unwinder.cpp
+++ b/libunwindstack/Unwinder.cpp
@@ -242,18 +242,21 @@
// some of the speculative frames.
in_device_map = true;
} else {
+ bool is_signal_frame = false;
if (elf->StepIfSignalHandler(rel_pc, regs_, process_memory_.get())) {
stepped = true;
- if (frame != nullptr) {
- // Need to adjust the relative pc because the signal handler
- // pc should not be adjusted.
- frame->rel_pc = rel_pc;
- frame->pc += pc_adjustment;
- step_pc = rel_pc;
- }
- } else if (elf->Step(step_pc, regs_, process_memory_.get(), &finished)) {
+ is_signal_frame = true;
+ } else if (elf->Step(step_pc, regs_, process_memory_.get(), &finished,
+ &is_signal_frame)) {
stepped = true;
}
+ if (is_signal_frame && frame != nullptr) {
+ // Need to adjust the relative pc because the signal handler
+ // pc should not be adjusted.
+ frame->rel_pc = rel_pc;
+ frame->pc += pc_adjustment;
+ step_pc = rel_pc;
+ }
elf->GetLastError(&last_error_);
}
}
diff --git a/libunwindstack/include/unwindstack/DwarfSection.h b/libunwindstack/include/unwindstack/DwarfSection.h
index af823da..f28cf25 100644
--- a/libunwindstack/include/unwindstack/DwarfSection.h
+++ b/libunwindstack/include/unwindstack/DwarfSection.h
@@ -106,7 +106,7 @@
virtual uint64_t AdjustPcFromFde(uint64_t pc) = 0;
- bool Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished);
+ bool Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished, bool* is_signal_frame);
protected:
DwarfMemory memory_;
diff --git a/libunwindstack/include/unwindstack/DwarfStructs.h b/libunwindstack/include/unwindstack/DwarfStructs.h
index 4b481f0..3d8c2db 100644
--- a/libunwindstack/include/unwindstack/DwarfStructs.h
+++ b/libunwindstack/include/unwindstack/DwarfStructs.h
@@ -35,6 +35,7 @@
uint64_t code_alignment_factor = 0;
int64_t data_alignment_factor = 0;
uint64_t return_address_register = 0;
+ bool is_signal_frame = false;
};
struct DwarfFde {
diff --git a/libunwindstack/include/unwindstack/Elf.h b/libunwindstack/include/unwindstack/Elf.h
index 97614b1..e15b221 100644
--- a/libunwindstack/include/unwindstack/Elf.h
+++ b/libunwindstack/include/unwindstack/Elf.h
@@ -60,7 +60,8 @@
bool StepIfSignalHandler(uint64_t rel_pc, Regs* regs, Memory* process_memory);
- bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished);
+ bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished,
+ bool* is_signal_frame);
ElfInterface* CreateInterfaceFromMemory(Memory* memory);
diff --git a/libunwindstack/include/unwindstack/ElfInterface.h b/libunwindstack/include/unwindstack/ElfInterface.h
index 0c39b23..5df7ddf 100644
--- a/libunwindstack/include/unwindstack/ElfInterface.h
+++ b/libunwindstack/include/unwindstack/ElfInterface.h
@@ -64,7 +64,8 @@
virtual std::string GetBuildID() = 0;
- virtual bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished);
+ virtual bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished,
+ bool* is_signal_frame);
virtual bool IsValidPc(uint64_t pc);
diff --git a/libunwindstack/tests/DwarfSectionTest.cpp b/libunwindstack/tests/DwarfSectionTest.cpp
index febd6d3..e5a1aed 100644
--- a/libunwindstack/tests/DwarfSectionTest.cpp
+++ b/libunwindstack/tests/DwarfSectionTest.cpp
@@ -68,7 +68,8 @@
EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(nullptr));
bool finished;
- ASSERT_FALSE(section_->Step(0x1000, nullptr, nullptr, &finished));
+ bool is_signal_frame;
+ ASSERT_FALSE(section_->Step(0x1000, nullptr, nullptr, &finished, &is_signal_frame));
}
TEST_F(DwarfSectionTest, Step_fail_cie_null) {
@@ -79,7 +80,8 @@
EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde));
bool finished;
- ASSERT_FALSE(section_->Step(0x1000, ®s_, nullptr, &finished));
+ bool is_signal_frame;
+ ASSERT_FALSE(section_->Step(0x1000, ®s_, nullptr, &finished, &is_signal_frame));
}
TEST_F(DwarfSectionTest, Step_fail_cfa_location) {
@@ -93,7 +95,8 @@
.WillOnce(::testing::Return(false));
bool finished;
- ASSERT_FALSE(section_->Step(0x1000, ®s_, nullptr, &finished));
+ bool is_signal_frame;
+ ASSERT_FALSE(section_->Step(0x1000, ®s_, nullptr, &finished, &is_signal_frame));
}
TEST_F(DwarfSectionTest, Step_pass) {
@@ -111,7 +114,8 @@
.WillOnce(::testing::Return(true));
bool finished;
- ASSERT_TRUE(section_->Step(0x1000, ®s_, &process, &finished));
+ bool is_signal_frame;
+ ASSERT_TRUE(section_->Step(0x1000, ®s_, &process, &finished, &is_signal_frame));
}
static bool MockGetCfaLocationInfo(::testing::Unused, const DwarfFde* fde,
@@ -137,9 +141,10 @@
.WillRepeatedly(::testing::Return(true));
bool finished;
- ASSERT_TRUE(section_->Step(0x1000, ®s_, &process, &finished));
- ASSERT_TRUE(section_->Step(0x1000, ®s_, &process, &finished));
- ASSERT_TRUE(section_->Step(0x1500, ®s_, &process, &finished));
+ bool is_signal_frame;
+ ASSERT_TRUE(section_->Step(0x1000, ®s_, &process, &finished, &is_signal_frame));
+ ASSERT_TRUE(section_->Step(0x1000, ®s_, &process, &finished, &is_signal_frame));
+ ASSERT_TRUE(section_->Step(0x1500, ®s_, &process, &finished, &is_signal_frame));
}
TEST_F(DwarfSectionTest, Step_cache_not_in_pc) {
@@ -157,7 +162,8 @@
.WillRepeatedly(::testing::Return(true));
bool finished;
- ASSERT_TRUE(section_->Step(0x1000, ®s_, &process, &finished));
+ bool is_signal_frame;
+ ASSERT_TRUE(section_->Step(0x1000, ®s_, &process, &finished, &is_signal_frame));
DwarfFde fde1{};
fde1.pc_start = 0x500;
@@ -167,8 +173,8 @@
EXPECT_CALL(*section_, GetCfaLocationInfo(0x600, &fde1, ::testing::_, ::testing::_))
.WillOnce(::testing::Invoke(MockGetCfaLocationInfo));
- ASSERT_TRUE(section_->Step(0x600, ®s_, &process, &finished));
- ASSERT_TRUE(section_->Step(0x700, ®s_, &process, &finished));
+ ASSERT_TRUE(section_->Step(0x600, ®s_, &process, &finished, &is_signal_frame));
+ ASSERT_TRUE(section_->Step(0x700, ®s_, &process, &finished, &is_signal_frame));
}
} // namespace unwindstack
diff --git a/libunwindstack/tests/ElfFake.cpp b/libunwindstack/tests/ElfFake.cpp
index 3d5ddd6..b16cd53 100644
--- a/libunwindstack/tests/ElfFake.cpp
+++ b/libunwindstack/tests/ElfFake.cpp
@@ -52,7 +52,7 @@
return true;
}
-bool ElfInterfaceFake::Step(uint64_t, Regs* regs, Memory*, bool* finished) {
+bool ElfInterfaceFake::Step(uint64_t, Regs* regs, Memory*, bool* finished, bool* is_signal_frame) {
if (steps_.empty()) {
return false;
}
@@ -68,6 +68,7 @@
fake_regs->set_pc(entry.pc);
fake_regs->set_sp(entry.sp);
*finished = entry.finished;
+ *is_signal_frame = false;
return true;
}
diff --git a/libunwindstack/tests/ElfFake.h b/libunwindstack/tests/ElfFake.h
index 3b6cb80..abda7b8 100644
--- a/libunwindstack/tests/ElfFake.h
+++ b/libunwindstack/tests/ElfFake.h
@@ -76,7 +76,7 @@
bool GetGlobalVariable(const std::string&, uint64_t*) override;
std::string GetBuildID() override { return fake_build_id_; }
- bool Step(uint64_t, Regs*, Memory*, bool*) override;
+ bool Step(uint64_t, Regs*, Memory*, bool*, bool*) override;
void FakeSetGlobalVariable(const std::string& global, uint64_t offset) {
globals_[global] = offset;
diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp
index f0852a4..d81edbf 100644
--- a/libunwindstack/tests/ElfTest.cpp
+++ b/libunwindstack/tests/ElfTest.cpp
@@ -138,7 +138,8 @@
EXPECT_EQ(ERROR_INVALID_ELF, elf.GetLastErrorCode());
bool finished;
- ASSERT_FALSE(elf.Step(0, nullptr, nullptr, &finished));
+ bool is_signal_frame;
+ ASSERT_FALSE(elf.Step(0, nullptr, nullptr, &finished, &is_signal_frame));
EXPECT_EQ(ERROR_INVALID_ELF, elf.GetLastErrorCode());
}
@@ -327,7 +328,7 @@
bool GetFunctionName(uint64_t, std::string*, uint64_t*) override { return false; }
std::string GetBuildID() override { return ""; }
- MOCK_METHOD(bool, Step, (uint64_t, Regs*, Memory*, bool*), (override));
+ MOCK_METHOD(bool, Step, (uint64_t, Regs*, Memory*, bool*, bool*), (override));
MOCK_METHOD(bool, GetGlobalVariable, (const std::string&, uint64_t*), (override));
MOCK_METHOD(bool, IsValidPc, (uint64_t), (override));
@@ -351,10 +352,11 @@
MemoryFake process_memory;
bool finished;
- EXPECT_CALL(*interface, Step(0x1000, ®s, &process_memory, &finished))
+ bool is_signal_frame;
+ EXPECT_CALL(*interface, Step(0x1000, ®s, &process_memory, &finished, &is_signal_frame))
.WillOnce(::testing::Return(true));
- ASSERT_TRUE(elf.Step(0x1000, ®s, &process_memory, &finished));
+ ASSERT_TRUE(elf.Step(0x1000, ®s, &process_memory, &finished, &is_signal_frame));
}
TEST_F(ElfTest, get_global_invalid_elf) {
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp
index 0c6f9f8..ab427b5 100644
--- a/libunwindstack/tests/UnwindOfflineTest.cpp
+++ b/libunwindstack/tests/UnwindOfflineTest.cpp
@@ -1736,4 +1736,158 @@
EXPECT_EQ(0x7ffb6c0f30U, unwinder.frames()[6].sp);
}
+// This test has a libc.so where the __restore has been changed so
+// that the signal handler match does not occur and it uses the
+// fde to do the unwind.
+TEST_F(UnwindOfflineTest, signal_fde_x86) {
+ ASSERT_NO_FATAL_FAILURE(Init("signal_fde_x86/", ARCH_X86));
+
+ Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
+ unwinder.Unwind();
+
+ std::string frame_info(DumpFrames(unwinder));
+ ASSERT_EQ(20U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+ EXPECT_EQ(
+ " #00 pc 007914d9 libunwindstack_test (SignalInnerFunction+25)\n"
+ " #01 pc 007914fc libunwindstack_test (SignalMiddleFunction+28)\n"
+ " #02 pc 0079152c libunwindstack_test (SignalOuterFunction+28)\n"
+ " #03 pc 0079af62 libunwindstack_test (unwindstack::SignalCallerHandler(int, siginfo*, "
+ "void*)+50)\n"
+ " #04 pc 00058fb0 libc.so (__restore)\n"
+ " #05 pc 00000000 <unknown>\n"
+ " #06 pc 0079161a libunwindstack_test (InnerFunction+218)\n"
+ " #07 pc 007923aa libunwindstack_test (MiddleFunction+42)\n"
+ " #08 pc 007923ea libunwindstack_test (OuterFunction+42)\n"
+ " #09 pc 00797444 libunwindstack_test (unwindstack::RemoteThroughSignal(int, unsigned "
+ "int)+868)\n"
+ " #10 pc 007985b8 libunwindstack_test "
+ "(unwindstack::UnwindTest_remote_through_signal_with_invalid_func_Test::TestBody()+56)\n"
+ " #11 pc 00817a19 libunwindstack_test\n"
+ " #12 pc 008178c5 libunwindstack_test (testing::Test::Run()+277)\n"
+ " #13 pc 00818d3e libunwindstack_test (testing::TestInfo::Run()+318)\n"
+ " #14 pc 008198b4 libunwindstack_test (testing::TestSuite::Run()+436)\n"
+ " #15 pc 00828cb0 libunwindstack_test "
+ "(testing::internal::UnitTestImpl::RunAllTests()+1216)\n"
+ " #16 pc 0082870f libunwindstack_test (testing::UnitTest::Run()+367)\n"
+ " #17 pc 0084031e libunwindstack_test (IsolateMain+2334)\n"
+ " #18 pc 0083f9e9 libunwindstack_test (main+41)\n"
+ " #19 pc 00050646 libc.so (__libc_init+118)\n",
+ frame_info);
+
+ EXPECT_EQ(0x5ae0d4d9U, unwinder.frames()[0].pc);
+ EXPECT_EQ(0xecb37188U, unwinder.frames()[0].sp);
+ EXPECT_EQ(0x5ae0d4fcU, unwinder.frames()[1].pc);
+ EXPECT_EQ(0xecb37190U, unwinder.frames()[1].sp);
+ EXPECT_EQ(0x5ae0d52cU, unwinder.frames()[2].pc);
+ EXPECT_EQ(0xecb371b0U, unwinder.frames()[2].sp);
+ EXPECT_EQ(0x5ae16f62U, unwinder.frames()[3].pc);
+ EXPECT_EQ(0xecb371d0U, unwinder.frames()[3].sp);
+ EXPECT_EQ(0xec169fb0U, unwinder.frames()[4].pc);
+ EXPECT_EQ(0xecb371f0U, unwinder.frames()[4].sp);
+ EXPECT_EQ(0x0U, unwinder.frames()[5].pc);
+ EXPECT_EQ(0xffcfac6cU, unwinder.frames()[5].sp);
+ EXPECT_EQ(0x5ae0d61aU, unwinder.frames()[6].pc);
+ EXPECT_EQ(0xffcfac6cU, unwinder.frames()[6].sp);
+ EXPECT_EQ(0x5ae0e3aaU, unwinder.frames()[7].pc);
+ EXPECT_EQ(0xffcfad60U, unwinder.frames()[7].sp);
+ EXPECT_EQ(0x5ae0e3eaU, unwinder.frames()[8].pc);
+ EXPECT_EQ(0xffcfad90U, unwinder.frames()[8].sp);
+ EXPECT_EQ(0x5ae13444U, unwinder.frames()[9].pc);
+ EXPECT_EQ(0xffcfadc0U, unwinder.frames()[9].sp);
+ EXPECT_EQ(0x5ae145b8U, unwinder.frames()[10].pc);
+ EXPECT_EQ(0xffcfb020U, unwinder.frames()[10].sp);
+ EXPECT_EQ(0x5ae93a19U, unwinder.frames()[11].pc);
+ EXPECT_EQ(0xffcfb050U, unwinder.frames()[11].sp);
+ EXPECT_EQ(0x5ae938c5U, unwinder.frames()[12].pc);
+ EXPECT_EQ(0xffcfb090U, unwinder.frames()[12].sp);
+ EXPECT_EQ(0x5ae94d3eU, unwinder.frames()[13].pc);
+ EXPECT_EQ(0xffcfb0f0U, unwinder.frames()[13].sp);
+ EXPECT_EQ(0x5ae958b4U, unwinder.frames()[14].pc);
+ EXPECT_EQ(0xffcfb160U, unwinder.frames()[14].sp);
+ EXPECT_EQ(0x5aea4cb0U, unwinder.frames()[15].pc);
+ EXPECT_EQ(0xffcfb1d0U, unwinder.frames()[15].sp);
+ EXPECT_EQ(0x5aea470fU, unwinder.frames()[16].pc);
+ EXPECT_EQ(0xffcfb270U, unwinder.frames()[16].sp);
+ EXPECT_EQ(0x5aebc31eU, unwinder.frames()[17].pc);
+ EXPECT_EQ(0xffcfb2c0U, unwinder.frames()[17].sp);
+ EXPECT_EQ(0x5aebb9e9U, unwinder.frames()[18].pc);
+ EXPECT_EQ(0xffcfc3c0U, unwinder.frames()[18].sp);
+ EXPECT_EQ(0xec161646U, unwinder.frames()[19].pc);
+ EXPECT_EQ(0xffcfc3f0U, unwinder.frames()[19].sp);
+}
+
+// This test has a libc.so where the __restore_rt has been changed so
+// that the signal handler match does not occur and it uses the
+// fde to do the unwind.
+TEST_F(UnwindOfflineTest, signal_fde_x86_64) {
+ ASSERT_NO_FATAL_FAILURE(Init("signal_fde_x86_64/", ARCH_X86_64));
+
+ Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
+ unwinder.Unwind();
+
+ std::string frame_info(DumpFrames(unwinder));
+ ASSERT_EQ(18U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+ EXPECT_EQ(
+ " #00 pc 000000000058415b libunwindstack_test (SignalInnerFunction+11)\n"
+ " #01 pc 0000000000584168 libunwindstack_test (SignalMiddleFunction+8)\n"
+ " #02 pc 0000000000584178 libunwindstack_test (SignalOuterFunction+8)\n"
+ " #03 pc 000000000058ac77 libunwindstack_test (unwindstack::SignalCallerHandler(int, "
+ "siginfo*, void*)+23)\n"
+ " #04 pc 0000000000057d10 libc.so (__restore_rt)\n"
+ " #05 pc 0000000000000000 <unknown>\n"
+ " #06 pc 0000000000584244 libunwindstack_test (InnerFunction+196)\n"
+ " #07 pc 0000000000584b44 libunwindstack_test (MiddleFunction+20)\n"
+ " #08 pc 0000000000584b64 libunwindstack_test (OuterFunction+20)\n"
+ " #09 pc 0000000000588457 libunwindstack_test (unwindstack::RemoteThroughSignal(int, "
+ "unsigned int)+583)\n"
+ " #10 pc 0000000000588f67 libunwindstack_test "
+ "(unwindstack::UnwindTest_remote_through_signal_with_invalid_func_Test::TestBody()+23)\n"
+ " #11 pc 00000000005d9c38 libunwindstack_test (testing::Test::Run()+216)\n"
+ " #12 pc 00000000005daf9a libunwindstack_test (testing::TestInfo::Run()+266)\n"
+ " #13 pc 00000000005dba46 libunwindstack_test (testing::TestSuite::Run()+390)\n"
+ " #14 pc 00000000005ea4c6 libunwindstack_test "
+ "(testing::internal::UnitTestImpl::RunAllTests()+1190)\n"
+ " #15 pc 00000000005e9f61 libunwindstack_test (testing::UnitTest::Run()+337)\n"
+ " #16 pc 0000000000600155 libunwindstack_test (IsolateMain+2037)\n"
+ " #17 pc 000000000004e405 libc.so (__libc_init+101)\n",
+ frame_info);
+
+ EXPECT_EQ(0x5bb41271e15bU, unwinder.frames()[0].pc);
+ EXPECT_EQ(0x707eb5aa8320U, unwinder.frames()[0].sp);
+ EXPECT_EQ(0x5bb41271e168U, unwinder.frames()[1].pc);
+ EXPECT_EQ(0x707eb5aa8330U, unwinder.frames()[1].sp);
+ EXPECT_EQ(0x5bb41271e178U, unwinder.frames()[2].pc);
+ EXPECT_EQ(0x707eb5aa8340U, unwinder.frames()[2].sp);
+ EXPECT_EQ(0x5bb412724c77U, unwinder.frames()[3].pc);
+ EXPECT_EQ(0x707eb5aa8350U, unwinder.frames()[3].sp);
+ EXPECT_EQ(0x707eb2ca5d10U, unwinder.frames()[4].pc);
+ EXPECT_EQ(0x707eb5aa8380U, unwinder.frames()[4].sp);
+ EXPECT_EQ(0x0U, unwinder.frames()[5].pc);
+ EXPECT_EQ(0x7ffcaadde078U, unwinder.frames()[5].sp);
+ EXPECT_EQ(0x5bb41271e244U, unwinder.frames()[6].pc);
+ EXPECT_EQ(0x7ffcaadde078U, unwinder.frames()[6].sp);
+ EXPECT_EQ(0x5bb41271eb44U, unwinder.frames()[7].pc);
+ EXPECT_EQ(0x7ffcaadde1a0U, unwinder.frames()[7].sp);
+ EXPECT_EQ(0x5bb41271eb64U, unwinder.frames()[8].pc);
+ EXPECT_EQ(0x7ffcaadde1c0U, unwinder.frames()[8].sp);
+ EXPECT_EQ(0x5bb412722457U, unwinder.frames()[9].pc);
+ EXPECT_EQ(0x7ffcaadde1e0U, unwinder.frames()[9].sp);
+ EXPECT_EQ(0x5bb412722f67U, unwinder.frames()[10].pc);
+ EXPECT_EQ(0x7ffcaadde510U, unwinder.frames()[10].sp);
+ EXPECT_EQ(0x5bb412773c38U, unwinder.frames()[11].pc);
+ EXPECT_EQ(0x7ffcaadde530U, unwinder.frames()[11].sp);
+ EXPECT_EQ(0x5bb412774f9aU, unwinder.frames()[12].pc);
+ EXPECT_EQ(0x7ffcaadde560U, unwinder.frames()[12].sp);
+ EXPECT_EQ(0x5bb412775a46U, unwinder.frames()[13].pc);
+ EXPECT_EQ(0x7ffcaadde5b0U, unwinder.frames()[13].sp);
+ EXPECT_EQ(0x5bb4127844c6U, unwinder.frames()[14].pc);
+ EXPECT_EQ(0x7ffcaadde5f0U, unwinder.frames()[14].sp);
+ EXPECT_EQ(0x5bb412783f61U, unwinder.frames()[15].pc);
+ EXPECT_EQ(0x7ffcaadde6c0U, unwinder.frames()[15].sp);
+ EXPECT_EQ(0x5bb41279a155U, unwinder.frames()[16].pc);
+ EXPECT_EQ(0x7ffcaadde720U, unwinder.frames()[16].sp);
+ EXPECT_EQ(0x707eb2c9c405U, unwinder.frames()[17].pc);
+ EXPECT_EQ(0x7ffcaaddf870U, unwinder.frames()[17].sp);
+}
+
} // namespace unwindstack
diff --git a/libunwindstack/tests/files/offline/signal_fde_x86/libc.so b/libunwindstack/tests/files/offline/signal_fde_x86/libc.so
new file mode 100644
index 0000000..5c882e4
--- /dev/null
+++ b/libunwindstack/tests/files/offline/signal_fde_x86/libc.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/signal_fde_x86/libunwindstack_test b/libunwindstack/tests/files/offline/signal_fde_x86/libunwindstack_test
new file mode 100644
index 0000000..8dcff67
--- /dev/null
+++ b/libunwindstack/tests/files/offline/signal_fde_x86/libunwindstack_test
Binary files differ
diff --git a/libunwindstack/tests/files/offline/signal_fde_x86/maps.txt b/libunwindstack/tests/files/offline/signal_fde_x86/maps.txt
new file mode 100644
index 0000000..6166a9d
--- /dev/null
+++ b/libunwindstack/tests/files/offline/signal_fde_x86/maps.txt
@@ -0,0 +1,4 @@
+5a67c000-5a7ba000 r--p 0 00:00 0 libunwindstack_test
+5a7ba000-5aedd000 r-xp 13d000 00:00 0 libunwindstack_test
+ec111000-ec153000 r--p 0 00:00 0 libc.so
+ec153000-ec200000 r-xp 41000 00:00 0 libc.so
diff --git a/libunwindstack/tests/files/offline/signal_fde_x86/regs.txt b/libunwindstack/tests/files/offline/signal_fde_x86/regs.txt
new file mode 100644
index 0000000..456b212
--- /dev/null
+++ b/libunwindstack/tests/files/offline/signal_fde_x86/regs.txt
@@ -0,0 +1,9 @@
+eax: 5aeec4ac
+ebx: 5aeec4ac
+ecx: 0
+edx: 6b
+ebp: ecb37188
+edi: ebecda30
+esi: b
+esp: ecb37188
+eip: 5ae0d4d9
diff --git a/libunwindstack/tests/files/offline/signal_fde_x86/stack0.data b/libunwindstack/tests/files/offline/signal_fde_x86/stack0.data
new file mode 100644
index 0000000..0bbbe22
--- /dev/null
+++ b/libunwindstack/tests/files/offline/signal_fde_x86/stack0.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/signal_fde_x86/stack1.data b/libunwindstack/tests/files/offline/signal_fde_x86/stack1.data
new file mode 100644
index 0000000..0873046
--- /dev/null
+++ b/libunwindstack/tests/files/offline/signal_fde_x86/stack1.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/signal_fde_x86_64/libc.so b/libunwindstack/tests/files/offline/signal_fde_x86_64/libc.so
new file mode 100644
index 0000000..cea7336
--- /dev/null
+++ b/libunwindstack/tests/files/offline/signal_fde_x86_64/libc.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/signal_fde_x86_64/libunwindstack_test b/libunwindstack/tests/files/offline/signal_fde_x86_64/libunwindstack_test
new file mode 100644
index 0000000..c48e84e
--- /dev/null
+++ b/libunwindstack/tests/files/offline/signal_fde_x86_64/libunwindstack_test
Binary files differ
diff --git a/libunwindstack/tests/files/offline/signal_fde_x86_64/maps.txt b/libunwindstack/tests/files/offline/signal_fde_x86_64/maps.txt
new file mode 100644
index 0000000..514aa71
--- /dev/null
+++ b/libunwindstack/tests/files/offline/signal_fde_x86_64/maps.txt
@@ -0,0 +1,4 @@
+5bb41219a000-5bb4122cd000 r--p 0 00:00 0 libunwindstack_test
+5bb4122cd000-5bb4127b9000 r-xp 132000 00:00 0 libunwindstack_test
+707eb2c4e000-707eb2c91000 r--p 0 00:00 0 libc.so
+707eb2c91000-707eb2d1b000 r-xp 42000 00:00 0 libc.so
diff --git a/libunwindstack/tests/files/offline/signal_fde_x86_64/regs.txt b/libunwindstack/tests/files/offline/signal_fde_x86_64/regs.txt
new file mode 100644
index 0000000..8da7b4e
--- /dev/null
+++ b/libunwindstack/tests/files/offline/signal_fde_x86_64/regs.txt
@@ -0,0 +1,17 @@
+rax: 0
+rbx: 707d82c59c60
+rcx: 4
+rdx: 707eb5aa8380
+r8: 7ffcaadde470
+r9: 7ffcaadde478
+r10: 8
+r11: 206
+r12: 707cb2c64330
+r13: 0
+r14: 174e9096a8f
+r15: 707d52c96cb0
+rdi: b
+rsi: 707eb5aa84b0
+rbp: 707eb5aa8320
+rsp: 707eb5aa8320
+rip: 5bb41271e15b
diff --git a/libunwindstack/tests/files/offline/signal_fde_x86_64/stack0.data b/libunwindstack/tests/files/offline/signal_fde_x86_64/stack0.data
new file mode 100644
index 0000000..e19a016
--- /dev/null
+++ b/libunwindstack/tests/files/offline/signal_fde_x86_64/stack0.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/signal_fde_x86_64/stack1.data b/libunwindstack/tests/files/offline/signal_fde_x86_64/stack1.data
new file mode 100644
index 0000000..3435f7c
--- /dev/null
+++ b/libunwindstack/tests/files/offline/signal_fde_x86_64/stack1.data
Binary files differ
diff --git a/libutils/String8.cpp b/libutils/String8.cpp
index c837891..3dc2026 100644
--- a/libutils/String8.cpp
+++ b/libutils/String8.cpp
@@ -309,8 +309,14 @@
n = vsnprintf(nullptr, 0, fmt, tmp_args);
va_end(tmp_args);
- if (n != 0) {
+ if (n < 0) return UNKNOWN_ERROR;
+
+ if (n > 0) {
size_t oldLength = length();
+ if ((size_t)n > SIZE_MAX - 1 ||
+ oldLength > SIZE_MAX - (size_t)n - 1) {
+ return NO_MEMORY;
+ }
char* buf = lockBuffer(oldLength + n);
if (buf) {
vsnprintf(buf + oldLength, n + 1, fmt, args);
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index a98c4b9..0259266 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -19,6 +19,7 @@
#include <sys/types.h>
#include <functional>
+#include <memory>
#include <log/log.h>
#include <log/log_read.h>
@@ -62,6 +63,7 @@
const char* msg, uint16_t len) = 0;
virtual std::unique_ptr<FlushToState> CreateFlushToState(uint64_t start, LogMask log_mask) = 0;
+ virtual void DeleteFlushToState(std::unique_ptr<FlushToState>) {}
virtual bool FlushTo(
LogWriter* writer, FlushToState& state,
const std::function<FilterResult(log_id_t log_id, pid_t pid, uint64_t sequence,
diff --git a/logd/LogReaderThread.cpp b/logd/LogReaderThread.cpp
index 4a8be01..6ac9741 100644
--- a/logd/LogReaderThread.cpp
+++ b/logd/LogReaderThread.cpp
@@ -72,6 +72,7 @@
[this](log_id_t log_id, pid_t pid, uint64_t sequence, log_time realtime) {
return FilterFirstPass(log_id, pid, sequence, realtime);
});
+ log_buffer_->DeleteFlushToState(std::move(first_pass_state));
}
bool flush_success = log_buffer_->FlushTo(
writer_.get(), *flush_to_state_,
@@ -105,6 +106,10 @@
}
}
+ lock.unlock();
+ log_buffer_->DeleteFlushToState(std::move(flush_to_state_));
+ lock.lock();
+
writer_->Release();
auto& log_reader_threads = reader_list_->reader_threads();
diff --git a/logd/LogReaderThread.h b/logd/LogReaderThread.h
index 20624f2..f1b673f 100644
--- a/logd/LogReaderThread.h
+++ b/logd/LogReaderThread.h
@@ -53,7 +53,7 @@
bool IsWatching(log_id_t id) const { return flush_to_state_->log_mask() & (1 << id); }
bool IsWatchingMultiple(LogMask log_mask) const {
- return flush_to_state_->log_mask() & log_mask;
+ return flush_to_state_ && flush_to_state_->log_mask() & log_mask;
}
std::string name() const { return writer_->name(); }
diff --git a/logd/SerializedLogBuffer.cpp b/logd/SerializedLogBuffer.cpp
index fa90878..6d1576f 100644
--- a/logd/SerializedLogBuffer.cpp
+++ b/logd/SerializedLogBuffer.cpp
@@ -201,6 +201,11 @@
return std::make_unique<SerializedFlushToState>(start, log_mask);
}
+void SerializedLogBuffer::DeleteFlushToState(std::unique_ptr<FlushToState> state) {
+ auto lock = std::unique_lock{lock_};
+ state.reset();
+}
+
bool SerializedLogBuffer::FlushTo(
LogWriter* writer, FlushToState& abstract_state,
const std::function<FilterResult(log_id_t log_id, pid_t pid, uint64_t sequence,
diff --git a/logd/SerializedLogBuffer.h b/logd/SerializedLogBuffer.h
index 294cfe6..9164526 100644
--- a/logd/SerializedLogBuffer.h
+++ b/logd/SerializedLogBuffer.h
@@ -42,6 +42,7 @@
int Log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid, const char* msg,
uint16_t len) override;
std::unique_ptr<FlushToState> CreateFlushToState(uint64_t start, LogMask log_mask) override;
+ void DeleteFlushToState(std::unique_ptr<FlushToState> state) override;
bool FlushTo(LogWriter* writer, FlushToState& state,
const std::function<FilterResult(log_id_t log_id, pid_t pid, uint64_t sequence,
log_time realtime)>& filter) override;
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 108f003..6e6aa1f 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -573,7 +573,7 @@
mkdir /data/apex/backup 0700 root system
mkdir /data/apex/hashtree 0700 root system
mkdir /data/apex/sessions 0700 root system
- mkdir /data/app-staging 0750 system system encryption=None
+ mkdir /data/app-staging 0750 system system encryption=DeleteIfNecessary
start apexd
# Avoid predictable entropy pool. Carry over entropy from previous boot.
diff --git a/trusty/utils/rpmb_dev/rpmb_dev.c b/trusty/utils/rpmb_dev/rpmb_dev.c
index 5de1efa..2025621 100644
--- a/trusty/utils/rpmb_dev/rpmb_dev.c
+++ b/trusty/utils/rpmb_dev/rpmb_dev.c
@@ -283,6 +283,7 @@
{
.func = rpmb_dev_data_read,
.resp = RPMB_RESP_DATA_READ,
+ .check_key_programmed = true,
.check_addr = true,
.multi_packet_res = true,
.res_mac = true,