Merge "libsnapshot: Implement OnlineKernelSnapshotWriter::OpenReader."
diff --git a/OWNERS b/OWNERS
index 4f8e433..682a067 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,2 +1 @@
enh@google.com
-baligh@google.com
diff --git a/adb/Android.bp b/adb/Android.bp
index 5c1e1fe..c361a14 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -293,8 +293,9 @@
export_include_dirs: ["."],
visibility: [
- "//system/core/adb:__subpackages__",
"//bootable/recovery/minadbd:__subpackages__",
+ "//packages/modules/adb:__subpackages__",
+ "//system/core/adb:__subpackages__",
],
apex_available: [
@@ -499,6 +500,7 @@
],
visibility: [
"//bootable/recovery/minadbd",
+ "//packages/modules/adb:__subpackages__",
"//system/core/adb",
],
}
@@ -578,6 +580,7 @@
"com.android.adbd",
],
visibility: [
+ "//packages/modules/adb",
"//system/core/adb",
],
@@ -636,6 +639,7 @@
visibility: [
"//bootable/recovery/minadbd",
+ "//packages/modules/adb",
"//system/core/adb",
],
}
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 43772ba..d9e69f7 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -1149,7 +1149,7 @@
// If we were using a specific transport ID, there's nothing we can wait for.
if (previous_id == 0) {
adb_set_transport(previous_type, previous_serial, 0);
- wait_for_device("wait-for-device", 6000ms);
+ wait_for_device("wait-for-device", 12000ms);
}
return true;
diff --git a/adb/crypto/Android.bp b/adb/crypto/Android.bp
index e2c27f1..c4052c3 100644
--- a/adb/crypto/Android.bp
+++ b/adb/crypto/Android.bp
@@ -39,8 +39,9 @@
export_include_dirs: ["include"],
visibility: [
- "//system/core/adb:__subpackages__",
"//bootable/recovery/minadbd:__subpackages__",
+ "//packages/modules/adb:__subpackages__",
+ "//system/core/adb:__subpackages__",
],
host_supported: true,
diff --git a/adb/libs/adbconnection/Android.bp b/adb/libs/adbconnection/Android.bp
index f7d2dc1..29ae060 100644
--- a/adb/libs/adbconnection/Android.bp
+++ b/adb/libs/adbconnection/Android.bp
@@ -39,6 +39,7 @@
defaults: ["adbd_defaults"],
visibility: [
"//art:__subpackages__",
+ "//packages/modules/adb/apex:__subpackages__",
"//system/core/adb/apex:__subpackages__",
],
apex_available: [
diff --git a/adb/pairing_auth/Android.bp b/adb/pairing_auth/Android.bp
index a43f4d0..806879d 100644
--- a/adb/pairing_auth/Android.bp
+++ b/adb/pairing_auth/Android.bp
@@ -40,6 +40,7 @@
visibility: [
"//art:__subpackages__",
+ "//packages/modules/adb:__subpackages__",
"//system/core/adb:__subpackages__",
],
diff --git a/adb/pairing_connection/Android.bp b/adb/pairing_connection/Android.bp
index 9595511..1886885 100644
--- a/adb/pairing_connection/Android.bp
+++ b/adb/pairing_connection/Android.bp
@@ -39,8 +39,9 @@
visibility: [
"//art:__subpackages__",
- "//system/core/adb:__subpackages__",
"//frameworks/base/services:__subpackages__",
+ "//packages/modules/adb:__subpackages__",
+ "//system/core/adb:__subpackages__",
// This needs to be visible to minadbd, even though it's removed via exclude_shared_libs.
"//bootable/recovery/minadbd:__subpackages__",
@@ -129,8 +130,9 @@
visibility: [
"//art:__subpackages__",
- "//system/core/adb:__subpackages__",
"//frameworks/base/services:__subpackages__",
+ "//packages/modules/adb:__subpackages__",
+ "//system/core/adb:__subpackages__",
],
recovery_available: false,
diff --git a/adb/proto/Android.bp b/adb/proto/Android.bp
index 086d10e..ef97208 100644
--- a/adb/proto/Android.bp
+++ b/adb/proto/Android.bp
@@ -40,6 +40,7 @@
},
visibility: [
+ "//packages/modules/adb:__subpackages__",
"//system/core/adb:__subpackages__",
// This needs to be visible to minadbd, even though it's removed via exclude_shared_libs.
@@ -94,6 +95,7 @@
},
visibility: [
+ "//packages/modules/adb:__subpackages__",
"//system/core/adb:__subpackages__",
// This needs to be visible to minadbd, even though it's removed via exclude_shared_libs.
diff --git a/adb/tls/Android.bp b/adb/tls/Android.bp
index e5204f3..1e00548 100644
--- a/adb/tls/Android.bp
+++ b/adb/tls/Android.bp
@@ -40,6 +40,7 @@
visibility: [
"//bootable/recovery/minadbd:__subpackages__",
+ "//packages/modules/adb:__subpackages__",
"//system/core/adb:__subpackages__",
],
diff --git a/adb/transport.cpp b/adb/transport.cpp
index c33d5af..93b4618 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -129,8 +129,8 @@
};
// Only retry for up to one minute.
- static constexpr const std::chrono::seconds kDefaultTimeout = 10s;
- static constexpr const size_t kMaxAttempts = 6;
+ static constexpr const std::chrono::seconds kDefaultTimeout = 3s;
+ static constexpr const size_t kMaxAttempts = 20;
// Protects all members.
std::mutex reconnect_mutex_;
diff --git a/fs_mgr/libdm/dm_target.cpp b/fs_mgr/libdm/dm_target.cpp
index 8788b5a..ef46eb9 100644
--- a/fs_mgr/libdm/dm_target.cpp
+++ b/fs_mgr/libdm/dm_target.cpp
@@ -284,6 +284,7 @@
std::vector<std::string> argv;
argv.push_back(std::to_string(start()));
argv.push_back(std::to_string(size()));
+ argv.push_back(control_device());
return android::base::Join(argv, " ");
}
diff --git a/fs_mgr/libdm/include/libdm/dm_target.h b/fs_mgr/libdm/include/libdm/dm_target.h
index 57e3884..478a3c6 100644
--- a/fs_mgr/libdm/include/libdm/dm_target.h
+++ b/fs_mgr/libdm/include/libdm/dm_target.h
@@ -311,10 +311,15 @@
class DmTargetUser final : public DmTarget {
public:
- DmTargetUser(uint64_t start, uint64_t length) : DmTarget(start, length) {}
+ DmTargetUser(uint64_t start, uint64_t length, std::string control_device)
+ : DmTarget(start, length), control_device_(control_device) {}
std::string name() const override { return "user"; }
+ std::string control_device() const { return control_device_; }
std::string GetParameterString() const override;
+
+ private:
+ std::string control_device_;
};
} // namespace dm
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index 7985fcd..b373d99 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -545,9 +545,11 @@
"libsnapshot_snapuserd",
"libcutils_sockets",
"libz",
+ "libdm",
],
header_libs: [
"libstorage_literals_headers",
+ "libfiemap_headers",
],
test_min_api_level: 30,
auto_gen_config: true,
diff --git a/fs_mgr/libsnapshot/cow_snapuserd_test.cpp b/fs_mgr/libsnapshot/cow_snapuserd_test.cpp
index 75e54f7..1d6c104 100644
--- a/fs_mgr/libsnapshot/cow_snapuserd_test.cpp
+++ b/fs_mgr/libsnapshot/cow_snapuserd_test.cpp
@@ -12,12 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include <fcntl.h>
#include <linux/fs.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <chrono>
#include <iostream>
#include <memory>
#include <string_view>
@@ -25,6 +25,7 @@
#include <android-base/file.h>
#include <android-base/unique_fd.h>
#include <gtest/gtest.h>
+#include <libdm/loop_control.h>
#include <libsnapshot/cow_writer.h>
#include <libsnapshot/snapuserd_client.h>
#include <storage_literals/storage_literals.h>
@@ -34,6 +35,8 @@
using namespace android::storage_literals;
using android::base::unique_fd;
+using LoopDevice = android::dm::LoopDevice;
+using namespace std::chrono_literals;
class SnapuserdTest : public ::testing::Test {
protected:
@@ -50,6 +53,18 @@
cow_product_1_ = std::make_unique<TemporaryFile>();
ASSERT_GE(cow_product_1_->fd, 0) << strerror(errno);
+ // Create temp files in the PWD as selinux
+ // allows kernel domin to read from that directory only
+ // on userdebug/eng builds. Creating files under /data/local/tmp
+ // will have selinux denials.
+ std::string path = android::base::GetExecutableDirectory();
+
+ system_a_ = std::make_unique<TemporaryFile>(path);
+ ASSERT_GE(system_a_->fd, 0) << strerror(errno);
+
+ product_a_ = std::make_unique<TemporaryFile>(path);
+ ASSERT_GE(product_a_->fd, 0) << strerror(errno);
+
size_ = 100_MiB;
}
@@ -61,6 +76,12 @@
cow_product_1_ = nullptr;
}
+ std::unique_ptr<TemporaryFile> system_a_;
+ std::unique_ptr<TemporaryFile> product_a_;
+
+ std::unique_ptr<LoopDevice> system_a_loop_;
+ std::unique_ptr<LoopDevice> product_a_loop_;
+
std::unique_ptr<TemporaryFile> cow_system_;
std::unique_ptr<TemporaryFile> cow_product_;
@@ -76,6 +97,9 @@
std::string system_device_name_;
std::string product_device_name_;
+ std::string system_device_ctrl_name_;
+ std::string product_device_ctrl_name_;
+
std::unique_ptr<uint8_t[]> random_buffer_1_;
std::unique_ptr<uint8_t[]> random_buffer_2_;
std::unique_ptr<uint8_t[]> zero_buffer_;
@@ -86,10 +110,18 @@
void CreateCowDevice(std::unique_ptr<TemporaryFile>& cow);
void CreateSystemDmUser(std::unique_ptr<TemporaryFile>& cow);
void CreateProductDmUser(std::unique_ptr<TemporaryFile>& cow);
+ void DeleteDmUser(std::unique_ptr<TemporaryFile>& cow, std::string snapshot_device);
void StartSnapuserdDaemon();
void CreateSnapshotDevices();
void SwitchSnapshotDevices();
+ std::string GetSystemControlPath() {
+ return std::string("/dev/dm-user-") + system_device_ctrl_name_;
+ }
+ std::string GetProductControlPath() {
+ return std::string("/dev/dm-user-") + product_device_ctrl_name_;
+ }
+
void TestIO(unique_fd& snapshot_fd, std::unique_ptr<uint8_t[]>& buffer);
SnapuserdClient client_;
};
@@ -97,6 +129,7 @@
void SnapuserdTest::Init() {
unique_fd rnd_fd;
loff_t offset = 0;
+ std::unique_ptr<uint8_t[]> random_buffer = std::make_unique<uint8_t[]>(1_MiB);
rnd_fd.reset(open("/dev/random", O_RDONLY));
ASSERT_TRUE(rnd_fd > 0);
@@ -118,10 +151,27 @@
offset += 1_MiB;
}
- sys_fd_.reset(open("/dev/block/mapper/system_a", O_RDONLY));
+ for (size_t j = 0; j < (800_MiB / 1_MiB); j++) {
+ ASSERT_EQ(ReadFullyAtOffset(rnd_fd, (char*)random_buffer.get(), 1_MiB, 0), true);
+ ASSERT_EQ(android::base::WriteFully(system_a_->fd, random_buffer.get(), 1_MiB), true);
+ }
+
+ for (size_t j = 0; j < (800_MiB / 1_MiB); j++) {
+ ASSERT_EQ(ReadFullyAtOffset(rnd_fd, (char*)random_buffer.get(), 1_MiB, 0), true);
+ ASSERT_EQ(android::base::WriteFully(product_a_->fd, random_buffer.get(), 1_MiB), true);
+ }
+
+ // Create loopback devices
+ system_a_loop_ = std::make_unique<LoopDevice>(std::string(system_a_->path), 10s);
+ ASSERT_TRUE(system_a_loop_->valid());
+
+ product_a_loop_ = std::make_unique<LoopDevice>(std::string(product_a_->path), 10s);
+ ASSERT_TRUE(product_a_loop_->valid());
+
+ sys_fd_.reset(open(system_a_loop_->device().c_str(), O_RDONLY));
ASSERT_TRUE(sys_fd_ > 0);
- product_fd_.reset(open("/dev/block/mapper/product_a", O_RDONLY));
+ product_fd_.reset(open(product_a_loop_->device().c_str(), O_RDONLY));
ASSERT_TRUE(product_fd_ > 0);
// Read from system partition from offset 0 of size 100MB
@@ -183,47 +233,65 @@
}
void SnapuserdTest::CreateSystemDmUser(std::unique_ptr<TemporaryFile>& cow) {
- unique_fd system_a_fd;
std::string cmd;
system_device_name_.clear();
+ system_device_ctrl_name_.clear();
// Create a COW device. Number of sectors is chosen random which can
// hold at least 400MB of data
- system_a_fd.reset(open("/dev/block/mapper/system_a", O_RDONLY));
- ASSERT_TRUE(system_a_fd > 0);
-
- int err = ioctl(system_a_fd.get(), BLKGETSIZE, &system_blksize_);
+ int err = ioctl(sys_fd_.get(), BLKGETSIZE, &system_blksize_);
ASSERT_GE(err, 0);
std::string str(cow->path);
std::size_t found = str.find_last_of("/\\");
ASSERT_NE(found, std::string::npos);
system_device_name_ = str.substr(found + 1);
+
+ // Create a control device
+ system_device_ctrl_name_ = system_device_name_ + "-ctrl";
cmd = "dmctl create " + system_device_name_ + " user 0 " + std::to_string(system_blksize_);
+ cmd += " " + system_device_ctrl_name_;
+
+ system(cmd.c_str());
+}
+
+void SnapuserdTest::DeleteDmUser(std::unique_ptr<TemporaryFile>& cow, std::string snapshot_device) {
+ std::string cmd;
+
+ cmd = "dmctl delete " + snapshot_device;
+ system(cmd.c_str());
+
+ cmd.clear();
+
+ std::string str(cow->path);
+ std::size_t found = str.find_last_of("/\\");
+ ASSERT_NE(found, std::string::npos);
+ std::string device_name = str.substr(found + 1);
+
+ cmd = "dmctl delete " + device_name;
system(cmd.c_str());
}
void SnapuserdTest::CreateProductDmUser(std::unique_ptr<TemporaryFile>& cow) {
- unique_fd product_a_fd;
std::string cmd;
product_device_name_.clear();
+ product_device_ctrl_name_.clear();
// Create a COW device. Number of sectors is chosen random which can
// hold at least 400MB of data
- product_a_fd.reset(open("/dev/block/mapper/product_a", O_RDONLY));
- ASSERT_TRUE(product_a_fd > 0);
-
- int err = ioctl(product_a_fd.get(), BLKGETSIZE, &product_blksize_);
+ int err = ioctl(product_fd_.get(), BLKGETSIZE, &product_blksize_);
ASSERT_GE(err, 0);
std::string str(cow->path);
std::size_t found = str.find_last_of("/\\");
ASSERT_NE(found, std::string::npos);
product_device_name_ = str.substr(found + 1);
+ product_device_ctrl_name_ = product_device_name_ + "-ctrl";
cmd = "dmctl create " + product_device_name_ + " user 0 " + std::to_string(product_blksize_);
+ cmd += " " + product_device_ctrl_name_;
system(cmd.c_str());
}
@@ -234,10 +302,12 @@
ret = client_.StartSnapuserd();
ASSERT_EQ(ret, 0);
- ret = client_.InitializeSnapuserd(cow_system_->path, "/dev/block/mapper/system_a");
+ ret = client_.InitializeSnapuserd(cow_system_->path, system_a_loop_->device(),
+ GetSystemControlPath());
ASSERT_EQ(ret, 0);
- ret = client_.InitializeSnapuserd(cow_product_->path, "/dev/block/mapper/product_a");
+ ret = client_.InitializeSnapuserd(cow_product_->path, product_a_loop_->device(),
+ GetProductControlPath());
ASSERT_EQ(ret, 0);
}
@@ -245,7 +315,7 @@
std::string cmd;
cmd = "dmctl create system-snapshot -ro snapshot 0 " + std::to_string(system_blksize_);
- cmd += " /dev/block/mapper/system_a";
+ cmd += " " + system_a_loop_->device();
cmd += " /dev/block/mapper/" + system_device_name_;
cmd += " P 8";
@@ -254,7 +324,7 @@
cmd.clear();
cmd = "dmctl create product-snapshot -ro snapshot 0 " + std::to_string(product_blksize_);
- cmd += " /dev/block/mapper/product_a";
+ cmd += " " + product_a_loop_->device();
cmd += " /dev/block/mapper/" + product_device_name_;
cmd += " P 8";
@@ -265,7 +335,7 @@
std::string cmd;
cmd = "dmctl create system-snapshot-1 -ro snapshot 0 " + std::to_string(system_blksize_);
- cmd += " /dev/block/mapper/system_a";
+ cmd += " " + system_a_loop_->device();
cmd += " /dev/block/mapper/" + system_device_name_;
cmd += " P 8";
@@ -274,7 +344,7 @@
cmd.clear();
cmd = "dmctl create product-snapshot-1 -ro snapshot 0 " + std::to_string(product_blksize_);
- cmd += " /dev/block/mapper/product_a";
+ cmd += " " + product_a_loop_->device();
cmd += " /dev/block/mapper/" + product_device_name_;
cmd += " P 8";
@@ -318,7 +388,7 @@
//
// IO path:
//
- // dm-snap->dm-snap-persistent->dm-user->snapuserd->read_from_system_a_partition
+ // dm-snap->dm-snap-persistent->dm-user->snapuserd->read_from_(system_a/product_a) partition
// (copy op) -> return
ASSERT_EQ(ReadFullyAtOffset(snapshot_fd, snapuserd_buffer.get(), size_, offset), true);
@@ -379,24 +449,33 @@
ASSERT_TRUE(snapshot_fd > 0);
TestIO(snapshot_fd, product_buffer_);
+ snapshot_fd.reset(-1);
+
// Sequence of operations for transition
CreateCowDevice(cow_system_1_);
CreateCowDevice(cow_product_1_);
+ // Create dm-user which creates new control devices
CreateSystemDmUser(cow_system_1_);
CreateProductDmUser(cow_product_1_);
- std::vector<std::pair<std::string, std::string>> vec;
- vec.push_back(std::make_pair(cow_system_1_->path, "/dev/block/mapper/system_a"));
- vec.push_back(std::make_pair(cow_product_1_->path, "/dev/block/mapper/product_a"));
+ // Send the path information to second stage daemon through vector
+ std::vector<std::vector<std::string>> vec{
+ {cow_system_1_->path, system_a_loop_->device(), GetSystemControlPath()},
+ {cow_product_1_->path, product_a_loop_->device(), GetProductControlPath()}};
- // Start the second stage deamon and send the devices
+ // Start the second stage deamon and send the devices information through
+ // vector.
ASSERT_EQ(client_.RestartSnapuserd(vec), 0);
// TODO: This is not switching snapshot device but creates a new table;
- // however, it should serve the testing purpose.
+ // Second stage daemon will be ready to serve the IO request. From now
+ // onwards, we can go ahead and shutdown the first stage daemon
SwitchSnapshotDevices();
+ DeleteDmUser(cow_system_, "system-snapshot");
+ DeleteDmUser(cow_product_, "product-snapshot");
+
// Stop the first stage daemon
ASSERT_EQ(client_.StopSnapuserd(true), 0);
@@ -409,6 +488,11 @@
ASSERT_TRUE(snapshot_fd > 0);
TestIO(snapshot_fd, product_buffer_);
+ snapshot_fd.reset(-1);
+
+ DeleteDmUser(cow_system_1_, "system-snapshot-1");
+ DeleteDmUser(cow_product_1_, "product-snapshot-1");
+
// Stop the second stage daemon
ASSERT_EQ(client_.StopSnapuserd(false), 0);
}
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd.h b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd.h
index d495014..2f727d6 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd.h
@@ -60,9 +60,11 @@
class Snapuserd final {
public:
- Snapuserd(const std::string& in_cow_device, const std::string& in_backing_store_device)
+ Snapuserd(const std::string& in_cow_device, const std::string& in_backing_store_device,
+ const std::string& in_control_device)
: cow_device_(in_cow_device),
backing_store_device_(in_backing_store_device),
+ control_device_(in_control_device),
metadata_read_done_(false) {}
bool Init();
@@ -75,6 +77,8 @@
int ReadDiskExceptions(chunk_t chunk, size_t size);
int ReadData(chunk_t chunk, size_t size);
+ std::string GetControlDevicePath() { return control_device_; }
+
private:
int ProcessReplaceOp(const CowOperation* cow_op);
int ProcessCopyOp(const CowOperation* cow_op);
@@ -82,6 +86,7 @@
std::string cow_device_;
std::string backing_store_device_;
+ std::string control_device_;
unique_fd cow_fd_;
unique_fd backing_store_fd_;
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_client.h b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_client.h
index 535e923..ab2149e 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_client.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_client.h
@@ -51,8 +51,9 @@
public:
int StartSnapuserd();
int StopSnapuserd(bool firstStageDaemon);
- int RestartSnapuserd(std::vector<std::pair<std::string, std::string>>& vec);
- int InitializeSnapuserd(std::string cow_device, std::string backing_device);
+ int RestartSnapuserd(std::vector<std::vector<std::string>>& vec);
+ int InitializeSnapuserd(std::string cow_device, std::string backing_device,
+ std::string control_device);
};
} // namespace snapshot
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_kernel.h b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_kernel.h
index 1a6ba8f..1037c12 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_kernel.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_kernel.h
@@ -80,7 +80,6 @@
__u64 flags;
__u64 sector;
__u64 len;
- __u64 io_in_progress;
} __attribute__((packed));
struct dm_user_payload {
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_server.h b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_server.h
index 584fe71..a1ebd3a 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_server.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_server.h
@@ -60,7 +60,8 @@
virtual ~Stoppable() {}
- virtual void ThreadStart(std::string cow_device, std::string backing_device) = 0;
+ virtual void ThreadStart(std::string cow_device, std::string backing_device,
+ std::string control_device) = 0;
bool StopRequested() {
// checks if value in future object is available
@@ -78,7 +79,8 @@
bool terminating_;
std::vector<std::unique_ptr<Client>> clients_vec_;
- void ThreadStart(std::string cow_device, std::string backing_device) override;
+ void ThreadStart(std::string cow_device, std::string backing_device,
+ std::string control_device) override;
void ShutdownThreads();
DaemonOperations Resolveop(std::string& input);
std::string GetDaemonStatus();
diff --git a/fs_mgr/libsnapshot/snapuserd.cpp b/fs_mgr/libsnapshot/snapuserd.cpp
index 3ed853f..62ef1b0 100644
--- a/fs_mgr/libsnapshot/snapuserd.cpp
+++ b/fs_mgr/libsnapshot/snapuserd.cpp
@@ -34,18 +34,6 @@
static_assert(PAYLOAD_SIZE >= BLOCK_SIZE);
-class Target {
- public:
- // Represents an already-created Target, which is referenced by UUID.
- Target(std::string uuid) : uuid_(uuid) {}
-
- const auto& uuid() { return uuid_; }
- std::string control_path() { return std::string("/dev/dm-user-") + uuid(); }
-
- private:
- const std::string uuid_;
-};
-
void BufferSink::Initialize(size_t size) {
buffer_size_ = size;
buffer_offset_ = 0;
@@ -498,26 +486,13 @@
return false;
}
- std::string str(cow_device_);
- std::size_t found = str.find_last_of("/\\");
- CHECK(found != std::string::npos);
- std::string device_name = str.substr(found + 1);
+ std::string control_path = GetControlDevicePath();
- LOG(DEBUG) << "Fetching UUID for: " << device_name;
+ LOG(DEBUG) << "Opening control device " << control_path;
- auto& dm = dm::DeviceMapper::Instance();
- std::string uuid;
- if (!dm.GetDmDeviceUuidByName(device_name, &uuid)) {
- LOG(ERROR) << "Unable to find UUID for " << cow_device_;
- return false;
- }
-
- LOG(DEBUG) << "UUID: " << uuid;
- Target t(uuid);
-
- ctrl_fd_.reset(open(t.control_path().c_str(), O_RDWR));
+ ctrl_fd_.reset(open(control_path.c_str(), O_RDWR));
if (ctrl_fd_ < 0) {
- LOG(ERROR) << "Unable to open " << t.control_path();
+ LOG(ERROR) << "Unable to open " << control_path;
return false;
}
@@ -553,7 +528,6 @@
case DM_USER_MAP_READ: {
size_t remaining_size = header->len;
loff_t offset = 0;
- header->io_in_progress = 0;
ret = 0;
do {
size_t read_size = std::min(PAYLOAD_SIZE, remaining_size);
@@ -619,7 +593,6 @@
if (remaining_size) {
LOG(DEBUG) << "Write done ret: " << ret
<< " remaining size: " << remaining_size;
- bufsink_.GetHeaderPtr()->io_in_progress = 1;
}
} while (remaining_size);
diff --git a/fs_mgr/libsnapshot/snapuserd_client.cpp b/fs_mgr/libsnapshot/snapuserd_client.cpp
index bef8f5c..78dbada 100644
--- a/fs_mgr/libsnapshot/snapuserd_client.cpp
+++ b/fs_mgr/libsnapshot/snapuserd_client.cpp
@@ -127,24 +127,6 @@
return msgStr;
}
-#if 0
-std::string SnapuserdClient::Receivemsg() {
- char msg[PACKET_SIZE];
- std::string msgStr("fail");
- int ret;
-
- ret = TEMP_FAILURE_RETRY(recv(sockfd_, msg, PACKET_SIZE, 0));
- if (ret <= 0) {
- LOG(ERROR) << "recv failed " << strerror(errno);
- return msgStr;
- }
-
- msgStr.clear();
- msgStr = msg;
- return msgStr;
-}
-#endif
-
int SnapuserdClient::StopSnapuserd(bool firstStageDaemon) {
if (firstStageDaemon) {
sockfd_ = socket_local_client(GetSocketNameFirstStage().c_str(),
@@ -209,7 +191,8 @@
return 0;
}
-int SnapuserdClient::InitializeSnapuserd(std::string cow_device, std::string backing_device) {
+int SnapuserdClient::InitializeSnapuserd(std::string cow_device, std::string backing_device,
+ std::string control_device) {
int ret = 0;
if (!ConnectToServer()) {
@@ -217,7 +200,7 @@
return -1;
}
- std::string msg = "start," + cow_device + "," + backing_device;
+ std::string msg = "start," + cow_device + "," + backing_device + "," + control_device;
ret = Sendmsg(msg.c_str(), msg.size());
if (ret < 0) {
@@ -270,7 +253,7 @@
* completely active to serve the IO and merging process.
*
*/
-int SnapuserdClient::RestartSnapuserd(std::vector<std::pair<std::string, std::string>>& vec) {
+int SnapuserdClient::RestartSnapuserd(std::vector<std::vector<std::string>>& vec) {
// Connect to first-stage daemon and send a terminate-request control
// message. This will not terminate the daemon but will mark the daemon as
// passive.
@@ -306,14 +289,19 @@
LOG(DEBUG) << "Second stage Snapuserd daemon created successfully at socket "
<< GetSocketNameSecondStage();
- CHECK(vec.size() % 2 == 0);
+ // Vector contains all the device information to be passed to the new
+ // daemon. Note that the caller can choose to initialize separately
+ // by calling InitializeSnapuserd() API as well. In that case, vector
+ // should be empty
for (int i = 0; i < vec.size(); i++) {
- std::string& cow_device = vec[i].first;
- std::string& base_device = vec[i].second;
+ std::string& cow_device = vec[i][0];
+ std::string& base_device = vec[i][1];
+ std::string& control_device = vec[i][2];
- InitializeSnapuserd(cow_device, base_device);
- LOG(DEBUG) << "Daemon initialized with " << cow_device << " and " << base_device;
+ InitializeSnapuserd(cow_device, base_device, control_device);
+ LOG(DEBUG) << "Daemon initialized with " << cow_device << ", " << base_device << " and "
+ << control_device;
}
return 0;
diff --git a/fs_mgr/libsnapshot/snapuserd_server.cpp b/fs_mgr/libsnapshot/snapuserd_server.cpp
index 1f8dd63..53101aa 100644
--- a/fs_mgr/libsnapshot/snapuserd_server.cpp
+++ b/fs_mgr/libsnapshot/snapuserd_server.cpp
@@ -63,8 +63,9 @@
}
// new thread
-void SnapuserdServer::ThreadStart(std::string cow_device, std::string backing_device) {
- Snapuserd snapd(cow_device, backing_device);
+void SnapuserdServer::ThreadStart(std::string cow_device, std::string backing_device,
+ std::string control_device) {
+ Snapuserd snapd(cow_device, backing_device, control_device);
if (!snapd.Init()) {
PLOG(ERROR) << "Snapuserd: Init failed";
return;
@@ -73,10 +74,9 @@
while (StopRequested() == false) {
int ret = snapd.Run();
- if (ret == -ETIMEDOUT) continue;
-
if (ret < 0) {
- PLOG(ERROR) << "snapd.Run() failed..." << ret;
+ LOG(ERROR) << "Snapuserd: Thread terminating as control device is de-registered";
+ break;
}
}
}
@@ -159,12 +159,12 @@
switch (op) {
case DaemonOperations::START: {
// Message format:
- // start,<cow_device_path>,<source_device_path>
+ // start,<cow_device_path>,<source_device_path>,<control_device>
//
// Start the new thread which binds to dm-user misc device
newClient = std::make_unique<Client>();
newClient->SetThreadHandler(
- std::bind(&SnapuserdServer::ThreadStart, this, out[1], out[2]));
+ std::bind(&SnapuserdServer::ThreadStart, this, out[1], out[2], out[3]));
clients_vec_.push_back(std::move(newClient));
sprintf(msg, "success");
Sendmsg(fd, msg, MAX_PACKET_SIZE);
diff --git a/fs_mgr/tools/dmctl.cpp b/fs_mgr/tools/dmctl.cpp
index 9edcda7..62ca162 100644
--- a/fs_mgr/tools/dmctl.cpp
+++ b/fs_mgr/tools/dmctl.cpp
@@ -177,7 +177,12 @@
return std::make_unique<DmTargetSnapshot>(start_sector, num_sectors, base_device,
cow_device, mode, chunk_size);
} else if (target_type == "user") {
- return std::make_unique<DmTargetUser>(start_sector, num_sectors);
+ if (!HasArgs(1)) {
+ std::cerr << "Expected \"user\" <control_device_name>" << std::endl;
+ return nullptr;
+ }
+ std::string control_device = NextArg();
+ return std::make_unique<DmTargetUser>(start_sector, num_sectors, control_device);
} else {
std::cerr << "Unrecognized target type: " << target_type << std::endl;
return nullptr;
diff --git a/healthd/android.hardware.health@2.0-service.rc b/healthd/android.hardware.health@2.0-service.rc
index 6960c5d..762771e 100644
--- a/healthd/android.hardware.health@2.0-service.rc
+++ b/healthd/android.hardware.health@2.0-service.rc
@@ -2,5 +2,5 @@
class hal
user system
group system
- capabilities WAKE_ALARM
+ capabilities WAKE_ALARM BLOCK_SUSPEND
file /dev/kmsg w
diff --git a/healthd/api/charger_sysprop-current.txt b/healthd/api/charger_sysprop-current.txt
index 678c847..e69de29 100644
--- a/healthd/api/charger_sysprop-current.txt
+++ b/healthd/api/charger_sysprop-current.txt
@@ -1,29 +0,0 @@
-props {
- module: "android.sysprop.ChargerProperties"
- prop {
- api_name: "disable_init_blank"
- scope: Internal
- prop_name: "ro.charger.disable_init_blank"
- }
- prop {
- api_name: "draw_split_offset"
- type: Long
- scope: Internal
- prop_name: "ro.charger.draw_split_offset"
- }
- prop {
- api_name: "draw_split_screen"
- scope: Internal
- prop_name: "ro.charger.draw_split_screen"
- }
- prop {
- api_name: "enable_suspend"
- scope: Internal
- prop_name: "ro.charger.enable_suspend"
- }
- prop {
- api_name: "no_ui"
- scope: Internal
- prop_name: "ro.charger.no_ui"
- }
-}
diff --git a/init/Android.mk b/init/Android.mk
index 998e0fd..ac31ef1 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -80,6 +80,7 @@
$(TARGET_RAMDISK_OUT)/dev \
$(TARGET_RAMDISK_OUT)/mnt \
$(TARGET_RAMDISK_OUT)/proc \
+ $(TARGET_RAMDISK_OUT)/second_stage_resources \
$(TARGET_RAMDISK_OUT)/sys \
LOCAL_STATIC_LIBRARIES := \
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index 0215576..554f301 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -41,6 +41,7 @@
#include "first_stage_console.h"
#include "first_stage_mount.h"
#include "reboot_utils.h"
+#include "second_stage_resources.h"
#include "switch_root.h"
#include "util.h"
@@ -235,6 +236,11 @@
// /debug_ramdisk is used to preserve additional files from the debug ramdisk
CHECKCALL(mount("tmpfs", "/debug_ramdisk", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
"mode=0755,uid=0,gid=0"));
+
+ // /second_stage_resources is used to preserve files from first to second
+ // stage init
+ CHECKCALL(mount("tmpfs", kSecondStageRes, "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
+ "mode=0755,uid=0,gid=0"))
#undef CHECKCALL
SetStdioToDevNull(argv);
@@ -276,6 +282,20 @@
StartConsole();
}
+ if (access(kBootImageRamdiskProp, F_OK) == 0) {
+ std::string dest = GetRamdiskPropForSecondStage();
+ std::string dir = android::base::Dirname(dest);
+ std::error_code ec;
+ if (!fs::create_directories(dir, ec)) {
+ LOG(FATAL) << "Can't mkdir " << dir << ": " << ec.message();
+ }
+ if (!fs::copy_file(kBootImageRamdiskProp, dest, ec)) {
+ LOG(FATAL) << "Can't copy " << kBootImageRamdiskProp << " to " << dest << ": "
+ << ec.message();
+ }
+ LOG(INFO) << "Copied ramdisk prop to " << dest;
+ }
+
if (ForceNormalBoot(cmdline)) {
mkdir("/first_stage_ramdisk", 0755);
// SwitchRoot() must be called with a mount point as the target, so we bind mount the
diff --git a/init/init.cpp b/init/init.cpp
index 7d00538..ea04494 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -71,6 +71,7 @@
#include "proto_utils.h"
#include "reboot.h"
#include "reboot_utils.h"
+#include "second_stage_resources.h"
#include "security.h"
#include "selabel.h"
#include "selinux.h"
@@ -668,6 +669,12 @@
}
}
+static void UmountSecondStageRes() {
+ if (umount(kSecondStageRes) != 0) {
+ PLOG(ERROR) << "Failed to umount " << kSecondStageRes;
+ }
+}
+
static void MountExtraFilesystems() {
#define CHECKCALL(x) \
if ((x) != 0) PLOG(FATAL) << #x " failed.";
@@ -776,6 +783,9 @@
PropertyInit();
+ // Umount second stage resources after property service has read the .prop files.
+ UmountSecondStageRes();
+
// Umount the debug ramdisk after property service has read the .prop files when it means to.
if (load_debug_prop) {
UmountDebugRamdisk();
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 57e82fa..e71c386 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -67,6 +67,7 @@
#include "persistent_properties.h"
#include "property_type.h"
#include "proto_utils.h"
+#include "second_stage_resources.h"
#include "selinux.h"
#include "subcontext.h"
#include "system/core/init/property_service.pb.h"
@@ -745,6 +746,15 @@
return true;
}
+static void LoadPropertiesFromSecondStageRes(std::map<std::string, std::string>* properties) {
+ std::string prop = GetRamdiskPropForSecondStage();
+ if (access(prop.c_str(), R_OK) != 0) {
+ CHECK(errno == ENOENT) << "Cannot access " << prop << ": " << strerror(errno);
+ return;
+ }
+ load_properties_from_file(prop.c_str(), nullptr, properties);
+}
+
// persist.sys.usb.config values can't be combined on build-time when property
// files are split into each partition.
// So we need to apply the same rule of build/make/tools/post_process_props.py
@@ -933,6 +943,7 @@
// Order matters here. The more the partition is specific to a product, the higher its
// precedence is.
+ LoadPropertiesFromSecondStageRes(&properties);
load_properties_from_file("/system/build.prop", nullptr, &properties);
load_properties_from_partition("system_ext", /* support_legacy_path_until */ 30);
// TODO(b/117892318): uncomment the following condition when vendor.imgs for aosp_* targets are
diff --git a/init/second_stage_resources.h b/init/second_stage_resources.h
new file mode 100644
index 0000000..544d16f
--- /dev/null
+++ b/init/second_stage_resources.h
@@ -0,0 +1,32 @@
+/*
+ * 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 <string>
+
+namespace android {
+namespace init {
+
+constexpr const char kSecondStageRes[] = "/second_stage_resources";
+constexpr const char kBootImageRamdiskProp[] = "/system/etc/ramdisk/build.prop";
+
+inline std::string GetRamdiskPropForSecondStage() {
+ return std::string(kSecondStageRes) + kBootImageRamdiskProp;
+}
+
+} // namespace init
+} // namespace android
diff --git a/libbacktrace b/libbacktrace
new file mode 120000
index 0000000..571194c
--- /dev/null
+++ b/libbacktrace
@@ -0,0 +1 @@
+../unwinding/libbacktrace
\ No newline at end of file
diff --git a/libbacktrace/.clang-format b/libbacktrace/.clang-format
deleted file mode 120000
index fd0645f..0000000
--- a/libbacktrace/.clang-format
+++ /dev/null
@@ -1 +0,0 @@
-../.clang-format-2
\ No newline at end of file
diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp
deleted file mode 100644
index c7969f2..0000000
--- a/libbacktrace/Android.bp
+++ /dev/null
@@ -1,233 +0,0 @@
-//
-// Copyright (C) 2014 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.
-//
-
-cc_defaults {
- name: "libbacktrace_common",
-
- cflags: [
- "-Wall",
- "-Werror",
- ],
-
- target: {
- darwin: {
- enabled: false,
- },
- },
-}
-
-libbacktrace_sources = [
- "Backtrace.cpp",
- "BacktraceCurrent.cpp",
- "BacktracePtrace.cpp",
- "ThreadEntry.cpp",
- "UnwindStack.cpp",
- "UnwindStackMap.cpp",
-]
-
-cc_library_headers {
- name: "libbacktrace_headers",
- vendor_available: true,
- recovery_available: true,
- native_bridge_supported: true,
- export_include_dirs: ["include"],
- apex_available: [
- "//apex_available:platform",
- "//apex_available:anyapex",
- ],
- min_sdk_version: "apex_inherit",
-}
-
-cc_defaults {
- name: "libbacktrace_defaults",
- defaults: ["libbacktrace_common"],
-
- cflags: [
- "-Wexit-time-destructors",
- ],
-
- srcs: [
- "BacktraceMap.cpp",
- ],
-
- export_include_dirs: ["include"],
-
- target: {
- darwin: {
- enabled: true,
- shared_libs: [
- "libbase",
- ],
- },
- linux: {
- srcs: libbacktrace_sources,
-
- shared_libs: [
- "libbase",
- "liblog",
- ],
-
- static_libs: [
- "libprocinfo",
- ],
- },
- android: {
- static_libs: ["libasync_safe"],
- static: {
- whole_static_libs: ["libasync_safe"],
- },
- },
- },
-}
-
-cc_library {
- name: "libbacktrace",
- vendor_available: false,
- // TODO(b/153609531): remove when no longer needed.
- native_bridge_supported: true,
- recovery_available: true,
- apex_available: [
- "//apex_available:platform",
- "//apex_available:anyapex",
- ],
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- host_supported: true,
- defaults: ["libbacktrace_defaults"],
-
- target: {
- linux: {
- shared_libs: [
- "libunwindstack",
- ],
- },
- vendor: {
- cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
- },
- recovery: {
- cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
- },
- native_bridge: {
- cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
- },
- },
-}
-
-// Static library without DEX support to avoid dependencies on the ART APEX.
-cc_library_static {
- name: "libbacktrace_no_dex",
- visibility: [
- "//system/core/debuggerd",
- "//system/core/init",
- ],
- defaults: ["libbacktrace_defaults"],
- cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
- target: {
- linux: {
- static_libs: [
- "libunwindstack_no_dex",
- ],
- },
- },
-}
-
-cc_test_library {
- name: "libbacktrace_test",
- defaults: ["libbacktrace_common"],
- host_supported: true,
- strip: {
- none: true,
- },
- cflags: ["-O0"],
- srcs: ["backtrace_testlib.cpp"],
-
- shared_libs: [
- "libunwindstack",
- ],
- relative_install_path: "backtrace_test_libs",
-
- target: {
- linux_glibc: {
- // This forces the creation of eh_frame with unwind information
- // for host.
- cflags: [
- "-fcxx-exceptions"
- ],
- },
- },
-}
-
-//-------------------------------------------------------------------------
-// The backtrace_test executable.
-//-------------------------------------------------------------------------
-cc_test {
- name: "backtrace_test",
- isolated: true,
- defaults: ["libbacktrace_common"],
- host_supported: true,
- srcs: [
- "backtrace_test.cpp",
- ],
-
- cflags: [
- "-fno-builtin",
- "-O0",
- "-g",
- ],
-
- shared_libs: [
- "libbacktrace",
- "libbase",
- "liblog",
- "libunwindstack",
- ],
-
- group_static_libs: true,
-
- // So that the dlopen can find the libbacktrace_test.so.
- ldflags: [
- "-Wl,--rpath,${ORIGIN}/../backtrace_test_libs",
- ],
-
- test_suites: ["device-tests"],
- data: [
- "testdata/arm/*",
- "testdata/arm64/*",
- "testdata/x86/*",
- "testdata/x86_64/*",
- ],
- required: [
- "libbacktrace_test",
- ],
-}
-
-cc_benchmark {
- name: "backtrace_benchmarks",
- defaults: ["libbacktrace_common"],
-
- srcs: [
- "backtrace_benchmarks.cpp",
- "backtrace_read_benchmarks.cpp",
- ],
-
- shared_libs: [
- "libbacktrace",
- "libbase",
- "libunwindstack",
- ],
-}
diff --git a/libbacktrace/Backtrace.cpp b/libbacktrace/Backtrace.cpp
deleted file mode 100644
index 3e050ab..0000000
--- a/libbacktrace/Backtrace.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 2013 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 <inttypes.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <ucontext.h>
-
-#include <string>
-
-#include <android-base/stringprintf.h>
-#include <android-base/threads.h>
-
-#include <backtrace/Backtrace.h>
-#include <backtrace/BacktraceMap.h>
-
-#include "BacktraceLog.h"
-#include "UnwindStack.h"
-
-using android::base::StringPrintf;
-
-extern "C" char* __cxa_demangle(const char*, char*, size_t*, int*);
-
-//-------------------------------------------------------------------------
-// Backtrace functions.
-//-------------------------------------------------------------------------
-Backtrace::Backtrace(pid_t pid, pid_t tid, BacktraceMap* map)
- : pid_(pid), tid_(tid), map_(map), map_shared_(true) {
- if (map_ == nullptr) {
- map_ = BacktraceMap::Create(pid);
- map_shared_ = false;
- }
-}
-
-Backtrace::~Backtrace() {
- if (map_ && !map_shared_) {
- delete map_;
- map_ = nullptr;
- }
-}
-
-std::string Backtrace::GetFunctionName(uint64_t pc, uint64_t* offset, const backtrace_map_t* map) {
- backtrace_map_t map_value;
- if (map == nullptr) {
- FillInMap(pc, &map_value);
- map = &map_value;
- }
- // If no map is found, or this map is backed by a device, then return nothing.
- if (map->start == 0 || (map->flags & PROT_DEVICE_MAP)) {
- return "";
- }
- std::string name(GetFunctionNameRaw(pc, offset));
- char* demangled_name = __cxa_demangle(name.c_str(), nullptr, nullptr, nullptr);
- if (demangled_name != nullptr) {
- name = demangled_name;
- free(demangled_name);
- return name;
- }
- return name;
-}
-
-bool Backtrace::VerifyReadWordArgs(uint64_t ptr, word_t* out_value) {
- if (ptr & (sizeof(word_t)-1)) {
- BACK_LOGW("invalid pointer %p", reinterpret_cast<void*>(ptr));
- *out_value = static_cast<word_t>(-1);
- return false;
- }
- return true;
-}
-
-std::string Backtrace::FormatFrameData(size_t frame_num) {
- if (frame_num >= frames_.size()) {
- return "";
- }
- return FormatFrameData(&frames_[frame_num]);
-}
-
-std::string Backtrace::FormatFrameData(const backtrace_frame_data_t* frame) {
- std::string map_name;
- if (BacktraceMap::IsValid(frame->map)) {
- map_name = frame->map.Name();
- if (!frame->map.name.empty()) {
- if (map_name[0] == '[' && map_name[map_name.size() - 1] == ']') {
- map_name.resize(map_name.size() - 1);
- map_name += StringPrintf(":%" PRIPTR "]", frame->map.start);
- }
- }
- } else {
- map_name = "<unknown>";
- }
-
- std::string line(StringPrintf("#%02zu pc %" PRIPTR " ", frame->num, frame->rel_pc));
- line += map_name;
- // Special handling for non-zero offset maps, we need to print that
- // information.
- if (frame->map.offset != 0) {
- line += " (offset " + StringPrintf("0x%" PRIx64, frame->map.offset) + ")";
- }
- if (!frame->func_name.empty()) {
- line += " (" + frame->func_name;
- if (frame->func_offset) {
- line += StringPrintf("+%" PRIu64, frame->func_offset);
- }
- line += ')';
- }
-
- return line;
-}
-
-void Backtrace::FillInMap(uint64_t pc, backtrace_map_t* map) {
- if (map_ != nullptr) {
- map_->FillIn(pc, map);
- }
-}
-
-Backtrace* Backtrace::Create(pid_t pid, pid_t tid, BacktraceMap* map) {
- if (pid == BACKTRACE_CURRENT_PROCESS) {
- pid = getpid();
- if (tid == BACKTRACE_CURRENT_THREAD) {
- tid = android::base::GetThreadId();
- }
- } else if (tid == BACKTRACE_CURRENT_THREAD) {
- tid = pid;
- }
-
- if (pid == getpid()) {
- return new UnwindStackCurrent(pid, tid, map);
- } else {
- return new UnwindStackPtrace(pid, tid, map);
- }
-}
-
-std::string Backtrace::GetErrorString(BacktraceUnwindError error) {
- switch (error.error_code) {
- case BACKTRACE_UNWIND_NO_ERROR:
- return "No error";
- case BACKTRACE_UNWIND_ERROR_SETUP_FAILED:
- return "Setup failed";
- case BACKTRACE_UNWIND_ERROR_MAP_MISSING:
- return "No map found";
- case BACKTRACE_UNWIND_ERROR_INTERNAL:
- return "Internal libbacktrace error, please submit a bugreport";
- case BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST:
- return "Thread doesn't exist";
- case BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT:
- return "Thread has not responded to signal in time";
- case BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION:
- return "Attempt to use an unsupported feature";
- case BACKTRACE_UNWIND_ERROR_NO_CONTEXT:
- return "Attempt to do an offline unwind without a context";
- case BACKTRACE_UNWIND_ERROR_EXCEED_MAX_FRAMES_LIMIT:
- return "Exceed MAX_BACKTRACE_FRAMES limit";
- case BACKTRACE_UNWIND_ERROR_ACCESS_MEM_FAILED:
- return android::base::StringPrintf("Failed to read memory at addr 0x%" PRIx64,
- error.error_info.addr);
- case BACKTRACE_UNWIND_ERROR_ACCESS_REG_FAILED:
- return android::base::StringPrintf("Failed to read register %" PRIu64, error.error_info.regno);
- case BACKTRACE_UNWIND_ERROR_FIND_PROC_INFO_FAILED:
- return "Failed to find a function in debug sections";
- case BACKTRACE_UNWIND_ERROR_EXECUTE_DWARF_INSTRUCTION_FAILED:
- return "Failed to execute dwarf instructions in debug sections";
- case BACKTRACE_UNWIND_ERROR_UNWIND_INFO:
- return "Failed to unwind due to invalid unwind information";
- case BACKTRACE_UNWIND_ERROR_REPEATED_FRAME:
- return "Failed to unwind due to same sp/pc repeating";
- case BACKTRACE_UNWIND_ERROR_INVALID_ELF:
- return "Failed to unwind due to invalid elf";
- }
-}
diff --git a/libbacktrace/BacktraceAsyncSafeLog.h b/libbacktrace/BacktraceAsyncSafeLog.h
deleted file mode 100644
index 14f51be..0000000
--- a/libbacktrace/BacktraceAsyncSafeLog.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#ifndef _LIBBACKTRACE_BACKTRACE_ASYNC_SAFE_LOG_H
-#define _LIBBACKTRACE_BACKTRACE_ASYNC_SAFE_LOG_H
-
-#if defined(__ANDROID__)
-
-#include <async_safe/log.h>
-
-// Logging macros for use in signal handler, only available on target.
-#define BACK_ASYNC_SAFE_LOGW(format, ...) \
- async_safe_format_log(ANDROID_LOG_WARN, "libbacktrace", "%s: " format, __PRETTY_FUNCTION__, \
- ##__VA_ARGS__)
-
-#define BACK_ASYNC_SAFE_LOGE(format, ...) \
- async_safe_format_log(ANDROID_LOG_ERROR, "libbacktrace", "%s: " format, __PRETTY_FUNCTION__, \
- ##__VA_ARGS__)
-
-#else
-
-#define BACK_ASYNC_SAFE_LOGW(format, ...)
-
-#define BACK_ASYNC_SAFE_LOGE(format, ...)
-
-#endif
-
-#endif // _LIBBACKTRACE_BACKTRACE_ASYNC_SAFE_LOG_H
diff --git a/libbacktrace/BacktraceCurrent.cpp b/libbacktrace/BacktraceCurrent.cpp
deleted file mode 100644
index a506575..0000000
--- a/libbacktrace/BacktraceCurrent.cpp
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#define _GNU_SOURCE 1
-#include <errno.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/param.h>
-#include <sys/ptrace.h>
-#include <sys/types.h>
-#include <ucontext.h>
-#include <unistd.h>
-
-#include <stdlib.h>
-
-#include <string>
-
-#include <android-base/threads.h>
-#include <backtrace/Backtrace.h>
-#include <backtrace/BacktraceMap.h>
-
-#include "BacktraceAsyncSafeLog.h"
-#include "BacktraceCurrent.h"
-#include "ThreadEntry.h"
-
-bool BacktraceCurrent::ReadWord(uint64_t ptr, word_t* out_value) {
-#if defined(__aarch64__)
- // Tagged pointer after Android R would lead top byte to have random values
- // https://source.android.com/devices/tech/debug/tagged-pointers
- ptr &= (1ULL << 56) - 1;
-#endif
-
- if (!VerifyReadWordArgs(ptr, out_value)) {
- return false;
- }
-
- backtrace_map_t map;
- FillInMap(ptr, &map);
- if (BacktraceMap::IsValid(map) && map.flags & PROT_READ) {
- *out_value = *reinterpret_cast<word_t*>(ptr);
- return true;
- } else {
- BACK_ASYNC_SAFE_LOGW("pointer %p not in a readable map", reinterpret_cast<void*>(ptr));
- *out_value = static_cast<word_t>(-1);
- return false;
- }
-}
-
-size_t BacktraceCurrent::Read(uint64_t addr, uint8_t* buffer, size_t bytes) {
-#if defined(__aarch64__)
- // Tagged pointer after Android R would lead top byte to have random values
- // https://source.android.com/devices/tech/debug/tagged-pointers
- addr &= (1ULL << 56) - 1;
-#endif
-
- backtrace_map_t map;
- FillInMap(addr, &map);
- if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) {
- return 0;
- }
- bytes = MIN(map.end - addr, bytes);
- memcpy(buffer, reinterpret_cast<uint8_t*>(addr), bytes);
- return bytes;
-}
-
-bool BacktraceCurrent::Unwind(size_t num_ignore_frames, void* ucontext) {
- if (GetMap() == nullptr) {
- // Without a map object, we can't do anything.
- error_.error_code = BACKTRACE_UNWIND_ERROR_MAP_MISSING;
- return false;
- }
-
- error_.error_code = BACKTRACE_UNWIND_NO_ERROR;
- if (ucontext) {
- return UnwindFromContext(num_ignore_frames, ucontext);
- }
-
- if (Tid() != static_cast<pid_t>(android::base::GetThreadId())) {
- return UnwindThread(num_ignore_frames);
- }
-
- return UnwindFromContext(num_ignore_frames, nullptr);
-}
-
-bool BacktraceCurrent::DiscardFrame(const backtrace_frame_data_t& frame) {
- if (BacktraceMap::IsValid(frame.map)) {
- const std::string library = basename(frame.map.name.c_str());
- if (library == "libunwind.so" || library == "libbacktrace.so") {
- return true;
- }
- }
- return false;
-}
-
-static pthread_mutex_t g_sigaction_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-// Since errno is stored per thread, changing it in the signal handler
-// modifies the value on the thread in which the signal handler executes.
-// If a signal occurs between a call and an errno check, it's possible
-// to get the errno set here. Always save and restore it just in case
-// code would modify it.
-class ErrnoRestorer {
- public:
- ErrnoRestorer() : saved_errno_(errno) {}
- ~ErrnoRestorer() {
- errno = saved_errno_;
- }
-
- private:
- int saved_errno_;
-};
-
-static void SignalLogOnly(int, siginfo_t*, void*) {
- ErrnoRestorer restore;
-
- BACK_ASYNC_SAFE_LOGE("pid %d, tid %d: Received a spurious signal %d\n", getpid(),
- static_cast<int>(android::base::GetThreadId()), THREAD_SIGNAL);
-}
-
-static void SignalHandler(int, siginfo_t*, void* sigcontext) {
- ErrnoRestorer restore;
-
- ThreadEntry* entry = ThreadEntry::Get(getpid(), android::base::GetThreadId(), false);
- if (!entry) {
- BACK_ASYNC_SAFE_LOGE("pid %d, tid %d entry not found", getpid(),
- static_cast<int>(android::base::GetThreadId()));
- return;
- }
-
- entry->CopyUcontextFromSigcontext(sigcontext);
-
- // Indicate the ucontext is now valid.
- entry->Wake();
-
- // Pause the thread until the unwind is complete. This avoids having
- // the thread run ahead causing problems.
- // The number indicates that we are waiting for the second Wake() call
- // overall which is made by the thread requesting an unwind.
- if (entry->Wait(2)) {
- // Do not remove the entry here because that can result in a deadlock
- // if the code cannot properly send a signal to the thread under test.
- entry->Wake();
- } else {
- // At this point, it is possible that entry has been freed, so just exit.
- BACK_ASYNC_SAFE_LOGE("Timed out waiting for unwind thread to indicate it completed.");
- }
-}
-
-bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) {
- // Prevent multiple threads trying to set the trigger action on different
- // threads at the same time.
- pthread_mutex_lock(&g_sigaction_mutex);
-
- ThreadEntry* entry = ThreadEntry::Get(Pid(), Tid());
- entry->Lock();
-
- struct sigaction act, oldact;
- memset(&act, 0, sizeof(act));
- act.sa_sigaction = SignalHandler;
- act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
- sigemptyset(&act.sa_mask);
- if (sigaction(THREAD_SIGNAL, &act, &oldact) != 0) {
- BACK_ASYNC_SAFE_LOGE("sigaction failed: %s", strerror(errno));
- ThreadEntry::Remove(entry);
- pthread_mutex_unlock(&g_sigaction_mutex);
- error_.error_code = BACKTRACE_UNWIND_ERROR_INTERNAL;
- return false;
- }
-
- if (tgkill(Pid(), Tid(), THREAD_SIGNAL) != 0) {
- // Do not emit an error message, this might be expected. Set the
- // error and let the caller decide.
- if (errno == ESRCH) {
- error_.error_code = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST;
- } else {
- error_.error_code = BACKTRACE_UNWIND_ERROR_INTERNAL;
- }
-
- sigaction(THREAD_SIGNAL, &oldact, nullptr);
- ThreadEntry::Remove(entry);
- pthread_mutex_unlock(&g_sigaction_mutex);
- return false;
- }
-
- // Wait for the thread to get the ucontext. The number indicates
- // that we are waiting for the first Wake() call made by the thread.
- bool wait_completed = entry->Wait(1);
-
- if (!wait_completed && oldact.sa_sigaction == nullptr) {
- // If the wait failed, it could be that the signal could not be delivered
- // within the timeout. Add a signal handler that's simply going to log
- // something so that we don't crash if the signal eventually gets
- // delivered. Only do this if there isn't already an action set up.
- memset(&act, 0, sizeof(act));
- act.sa_sigaction = SignalLogOnly;
- act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
- sigemptyset(&act.sa_mask);
- sigaction(THREAD_SIGNAL, &act, nullptr);
- } else {
- sigaction(THREAD_SIGNAL, &oldact, nullptr);
- }
- // After the thread has received the signal, allow other unwinders to
- // continue.
- pthread_mutex_unlock(&g_sigaction_mutex);
-
- bool unwind_done = false;
- if (wait_completed) {
- unwind_done = UnwindFromContext(num_ignore_frames, entry->GetUcontext());
-
- // Tell the signal handler to exit and release the entry.
- entry->Wake();
-
- // Wait for the thread to indicate it is done with the ThreadEntry.
- if (!entry->Wait(3)) {
- // Send a warning, but do not mark as a failure to unwind.
- BACK_ASYNC_SAFE_LOGW("Timed out waiting for signal handler to indicate it finished.");
- }
- } else {
- // Check to see if the thread has disappeared.
- if (tgkill(Pid(), Tid(), 0) == -1 && errno == ESRCH) {
- error_.error_code = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST;
- } else {
- error_.error_code = BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT;
- BACK_ASYNC_SAFE_LOGE("Timed out waiting for signal handler to get ucontext data.");
- }
- }
-
- ThreadEntry::Remove(entry);
-
- return unwind_done;
-}
diff --git a/libbacktrace/BacktraceCurrent.h b/libbacktrace/BacktraceCurrent.h
deleted file mode 100644
index 48c14ea..0000000
--- a/libbacktrace/BacktraceCurrent.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef _LIBBACKTRACE_BACKTRACE_CURRENT_H
-#define _LIBBACKTRACE_BACKTRACE_CURRENT_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <backtrace/Backtrace.h>
-
-// The signal used to cause a thread to dump the stack.
-#if defined(__GLIBC__)
-// In order to run the backtrace_tests on the host, we can't use
-// the internal real time signals used by GLIBC. To avoid this,
-// use SIGRTMIN for the signal to dump the stack.
-#define THREAD_SIGNAL SIGRTMIN
-#else
-#define THREAD_SIGNAL (__SIGRTMIN+1)
-#endif
-
-class BacktraceMap;
-
-class BacktraceCurrent : public Backtrace {
- public:
- BacktraceCurrent(pid_t pid, pid_t tid, BacktraceMap* map) : Backtrace(pid, tid, map) {}
- virtual ~BacktraceCurrent() {}
-
- size_t Read(uint64_t addr, uint8_t* buffer, size_t bytes) override;
-
- bool ReadWord(uint64_t ptr, word_t* out_value) override;
-
- bool Unwind(size_t num_ignore_frames, void* ucontext) override;
-
- protected:
- bool DiscardFrame(const backtrace_frame_data_t& frame);
-
- private:
- bool UnwindThread(size_t num_ignore_frames);
-
- virtual bool UnwindFromContext(size_t num_ignore_frames, void* ucontext) = 0;
-};
-
-#endif // _LIBBACKTRACE_BACKTRACE_CURRENT_H
diff --git a/libbacktrace/BacktraceLog.h b/libbacktrace/BacktraceLog.h
deleted file mode 100644
index 5c39f1c..0000000
--- a/libbacktrace/BacktraceLog.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#ifndef _LIBBACKTRACE_BACKTRACE_LOG_H
-#define _LIBBACKTRACE_BACKTRACE_LOG_H
-
-#define LOG_TAG "libbacktrace"
-
-#include <log/log.h>
-
-// Macro to log the function name along with the warning message.
-#define BACK_LOGW(format, ...) \
- ALOGW("%s: " format, __PRETTY_FUNCTION__, ##__VA_ARGS__)
-
-#define BACK_LOGE(format, ...) \
- ALOGE("%s: " format, __PRETTY_FUNCTION__, ##__VA_ARGS__)
-
-#endif // _LIBBACKTRACE_BACKTRACE_LOG_H
diff --git a/libbacktrace/BacktraceMap.cpp b/libbacktrace/BacktraceMap.cpp
deleted file mode 100644
index 781819a..0000000
--- a/libbacktrace/BacktraceMap.cpp
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#define LOG_TAG "backtrace-map"
-
-#include <ctype.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <log/log.h>
-
-#include <android-base/stringprintf.h>
-#include <backtrace/Backtrace.h>
-#include <backtrace/BacktraceMap.h>
-#include <backtrace/backtrace_constants.h>
-#if defined(__linux__)
-#include <procinfo/process_map.h>
-#endif
-
-using android::base::StringPrintf;
-
-std::string backtrace_map_t::Name() const {
- if (!name.empty()) return name;
- if (start == 0 && end == 0) return "";
- return StringPrintf("<anonymous:%" PRIPTR ">", start);
-}
-
-BacktraceMap::BacktraceMap(pid_t pid) : pid_(pid) {
- if (pid_ < 0) {
- pid_ = getpid();
- }
-}
-
-BacktraceMap::~BacktraceMap() {}
-
-void BacktraceMap::FillIn(uint64_t addr, backtrace_map_t* map) {
- ScopedBacktraceMapIteratorLock lock(this);
- for (auto it = begin(); it != end(); ++it) {
- const backtrace_map_t* entry = *it;
- if (addr >= entry->start && addr < entry->end) {
- *map = *entry;
- return;
- }
- }
- *map = {};
-}
-
-#if defined(__APPLE__)
-static bool ParseLine(const char* line, backtrace_map_t* map) {
- uint64_t start;
- uint64_t end;
- char permissions[5];
- int name_pos;
-
- // Mac OS vmmap(1) output:
- // __TEXT 0009f000-000a1000 [ 8K 8K] r-x/rwx SM=COW
- // /Volumes/android/dalvik-dev/out/host/darwin-x86/bin/libcorkscrew_test\n
- // 012345678901234567890123456789012345678901234567890123456789
- // 0 1 2 3 4 5
- if (sscanf(line, "%*21c %" SCNx64 "-%" SCNx64 " [%*13c] %3c/%*3c SM=%*3c %n", &start, &end,
- permissions, &name_pos) != 3) {
- return false;
- }
-
- map->start = start;
- map->end = end;
- map->flags = PROT_NONE;
- if (permissions[0] == 'r') {
- map->flags |= PROT_READ;
- }
- if (permissions[1] == 'w') {
- map->flags |= PROT_WRITE;
- }
- if (permissions[2] == 'x') {
- map->flags |= PROT_EXEC;
- }
-
- map->name = line + name_pos;
- if (!map->name.empty() && map->name[map->name.length() - 1] == '\n') {
- map->name.erase(map->name.length() - 1);
- }
-
- ALOGV("Parsed map: start=%p, end=%p, flags=%x, name=%s", reinterpret_cast<void*>(map->start),
- reinterpret_cast<void*>(map->end), map->flags, map->name.c_str());
- return true;
-}
-#endif // defined(__APPLE__)
-
-bool BacktraceMap::Build() {
-#if defined(__APPLE__)
- char
- cmd[sizeof(pid_t) * 3 + sizeof("vmmap -w -resident -submap -allSplitLibs -interleaved ") + 1];
- char line[1024];
- // cmd is guaranteed to always be big enough to hold this string.
- snprintf(cmd, sizeof(cmd), "vmmap -w -resident -submap -allSplitLibs -interleaved %d", pid_);
- FILE* fp = popen(cmd, "r");
- if (fp == nullptr) {
- return false;
- }
-
- while (fgets(line, sizeof(line), fp)) {
- backtrace_map_t map;
- if (ParseLine(line, &map)) {
- maps_.push_back(map);
- }
- }
- pclose(fp);
- return true;
-#else
- return android::procinfo::ReadProcessMaps(
- pid_, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t, ino_t, const char* name) {
- maps_.resize(maps_.size() + 1);
- backtrace_map_t& map = maps_.back();
- map.start = start;
- map.end = end;
- map.flags = flags;
- map.name = name;
- });
-#endif
-}
-
-#if defined(__APPLE__)
-// Corkscrew and libunwind don't compile on the mac, so create a generic
-// map object.
-BacktraceMap* BacktraceMap::Create(pid_t pid, bool /*uncached*/) {
- BacktraceMap* map = new BacktraceMap(pid);
- if (!map->Build()) {
- delete map;
- return nullptr;
- }
- return map;
-}
-#endif
diff --git a/libbacktrace/BacktracePtrace.cpp b/libbacktrace/BacktracePtrace.cpp
deleted file mode 100644
index 9da457d..0000000
--- a/libbacktrace/BacktracePtrace.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2013 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 <errno.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/param.h>
-#include <sys/ptrace.h>
-#include <sys/types.h>
-#include <ucontext.h>
-#include <unistd.h>
-
-#include <backtrace/Backtrace.h>
-#include <backtrace/BacktraceMap.h>
-
-#include "BacktraceLog.h"
-#include "BacktracePtrace.h"
-
-#if !defined(__APPLE__)
-static bool PtraceRead(pid_t tid, uint64_t addr, word_t* out_value) {
- // ptrace() returns -1 and sets errno when the operation fails.
- // To disambiguate -1 from a valid result, we clear errno beforehand.
- errno = 0;
- *out_value = ptrace(PTRACE_PEEKTEXT, tid, reinterpret_cast<void*>(addr), nullptr);
- if (*out_value == static_cast<word_t>(-1) && errno) {
- return false;
- }
- return true;
-}
-#endif
-
-bool BacktracePtrace::ReadWord(uint64_t ptr, word_t* out_value) {
-#if defined(__APPLE__)
- BACK_LOGW("MacOS does not support reading from another pid.");
- return false;
-#else
- if (!VerifyReadWordArgs(ptr, out_value)) {
- return false;
- }
-
- backtrace_map_t map;
- FillInMap(ptr, &map);
- if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) {
- return false;
- }
-
- return PtraceRead(Tid(), ptr, out_value);
-#endif
-}
-
-size_t BacktracePtrace::Read(uint64_t addr, uint8_t* buffer, size_t bytes) {
-#if defined(__APPLE__)
- BACK_LOGW("MacOS does not support reading from another pid.");
- return 0;
-#else
- backtrace_map_t map;
- FillInMap(addr, &map);
- if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) {
- return 0;
- }
-
- bytes = MIN(map.end - addr, bytes);
- size_t bytes_read = 0;
- word_t data_word;
- size_t align_bytes = addr & (sizeof(word_t) - 1);
- if (align_bytes != 0) {
- if (!PtraceRead(Tid(), addr & ~(sizeof(word_t) - 1), &data_word)) {
- return 0;
- }
- size_t copy_bytes = MIN(sizeof(word_t) - align_bytes, bytes);
- memcpy(buffer, reinterpret_cast<uint8_t*>(&data_word) + align_bytes, copy_bytes);
- addr += copy_bytes;
- buffer += copy_bytes;
- bytes -= copy_bytes;
- bytes_read += copy_bytes;
- }
-
- size_t num_words = bytes / sizeof(word_t);
- for (size_t i = 0; i < num_words; i++) {
- if (!PtraceRead(Tid(), addr, &data_word)) {
- return bytes_read;
- }
- memcpy(buffer, &data_word, sizeof(word_t));
- buffer += sizeof(word_t);
- addr += sizeof(word_t);
- bytes_read += sizeof(word_t);
- }
-
- size_t left_over = bytes & (sizeof(word_t) - 1);
- if (left_over) {
- if (!PtraceRead(Tid(), addr, &data_word)) {
- return bytes_read;
- }
- memcpy(buffer, &data_word, left_over);
- bytes_read += left_over;
- }
- return bytes_read;
-#endif
-}
diff --git a/libbacktrace/BacktracePtrace.h b/libbacktrace/BacktracePtrace.h
deleted file mode 100644
index 1ae3adf..0000000
--- a/libbacktrace/BacktracePtrace.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef _LIBBACKTRACE_BACKTRACE_PTRACE_H
-#define _LIBBACKTRACE_BACKTRACE_PTRACE_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <backtrace/Backtrace.h>
-
-class BacktraceMap;
-
-class BacktracePtrace : public Backtrace {
- public:
- BacktracePtrace(pid_t pid, pid_t tid, BacktraceMap* map) : Backtrace(pid, tid, map) {}
- virtual ~BacktracePtrace() {}
-
- size_t Read(uint64_t addr, uint8_t* buffer, size_t bytes) override;
-
- bool ReadWord(uint64_t ptr, word_t* out_value) override;
-};
-
-#endif // _LIBBACKTRACE_BACKTRACE_PTRACE_H
diff --git a/libbacktrace/BacktraceTest.h b/libbacktrace/BacktraceTest.h
deleted file mode 100644
index c38af04..0000000
--- a/libbacktrace/BacktraceTest.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef _LIBBACKTRACE_BACKTRACE_TEST_H
-#define _LIBBACKTRACE_BACKTRACE_TEST_H
-
-#include <dlfcn.h>
-
-#include <gtest/gtest.h>
-
-class BacktraceTest : public ::testing::Test {
- protected:
- static void SetUpTestCase() {
- dl_handle_ = dlopen("libbacktrace_test.so", RTLD_NOW | RTLD_LOCAL);
-
- test_level_one_ = reinterpret_cast<int (*)(int, int, int, int, void (*)(void*), void*)>(
- dlsym(dl_handle_, "test_level_one"));
-
- test_level_two_ = reinterpret_cast<int (*)(int, int, int, int, void (*)(void*), void*)>(
- dlsym(dl_handle_, "test_level_two"));
-
- test_level_three_ = reinterpret_cast<int (*)(int, int, int, int, void (*)(void*), void*)>(
- dlsym(dl_handle_, "test_level_three"));
-
- test_level_four_ = reinterpret_cast<int (*)(int, int, int, int, void (*)(void*), void*)>(
- dlsym(dl_handle_, "test_level_four"));
-
- test_recursive_call_ = reinterpret_cast<int (*)(int, void (*)(void*), void*)>(
- dlsym(dl_handle_, "test_recursive_call"));
-
- test_get_context_and_wait_ = reinterpret_cast<void (*)(void*, volatile int*)>(
- dlsym(dl_handle_, "test_get_context_and_wait"));
-
- test_signal_action_ =
- reinterpret_cast<void (*)(int, siginfo_t*, void*)>(dlsym(dl_handle_, "test_signal_action"));
-
- test_signal_handler_ =
- reinterpret_cast<void (*)(int)>(dlsym(dl_handle_, "test_signal_handler"));
- }
-
- void SetUp() override {
- ASSERT_TRUE(dl_handle_ != nullptr);
- ASSERT_TRUE(test_level_one_ != nullptr);
- ASSERT_TRUE(test_level_two_ != nullptr);
- ASSERT_TRUE(test_level_three_ != nullptr);
- ASSERT_TRUE(test_level_four_ != nullptr);
- ASSERT_TRUE(test_recursive_call_ != nullptr);
- ASSERT_TRUE(test_get_context_and_wait_ != nullptr);
- ASSERT_TRUE(test_signal_action_ != nullptr);
- ASSERT_TRUE(test_signal_handler_ != nullptr);
- }
-
- public:
- static void* dl_handle_;
- static int (*test_level_one_)(int, int, int, int, void (*)(void*), void*);
- static int (*test_level_two_)(int, int, int, int, void (*)(void*), void*);
- static int (*test_level_three_)(int, int, int, int, void (*)(void*), void*);
- static int (*test_level_four_)(int, int, int, int, void (*)(void*), void*);
- static int (*test_recursive_call_)(int, void (*)(void*), void*);
- static void (*test_get_context_and_wait_)(void*, volatile int*);
- static void (*test_signal_action_)(int, siginfo_t*, void*);
- static void (*test_signal_handler_)(int);
-};
-
-#endif // _LIBBACKTRACE_BACKTRACE_TEST_H
diff --git a/libbacktrace/OWNERS b/libbacktrace/OWNERS
deleted file mode 100644
index bfeedca..0000000
--- a/libbacktrace/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-cferris@google.com
-jmgao@google.com
diff --git a/libbacktrace/ThreadEntry.cpp b/libbacktrace/ThreadEntry.cpp
deleted file mode 100644
index 9bd59e4..0000000
--- a/libbacktrace/ThreadEntry.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2015 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 <pthread.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/types.h>
-#include <time.h>
-#include <ucontext.h>
-
-#include "BacktraceAsyncSafeLog.h"
-#include "ThreadEntry.h"
-
-// Initialize static member variables.
-ThreadEntry* ThreadEntry::list_ = nullptr;
-pthread_mutex_t ThreadEntry::list_mutex_ = PTHREAD_MUTEX_INITIALIZER;
-
-// Assumes that ThreadEntry::list_mutex_ has already been locked before
-// creating a ThreadEntry object.
-ThreadEntry::ThreadEntry(pid_t pid, pid_t tid)
- : pid_(pid), tid_(tid), ref_count_(1), mutex_(PTHREAD_MUTEX_INITIALIZER),
- wait_mutex_(PTHREAD_MUTEX_INITIALIZER), wait_value_(0),
- next_(ThreadEntry::list_), prev_(nullptr) {
- pthread_condattr_t attr;
- pthread_condattr_init(&attr);
- pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
- pthread_cond_init(&wait_cond_, &attr);
-
- // Add ourselves to the list.
- if (ThreadEntry::list_) {
- ThreadEntry::list_->prev_ = this;
- }
- ThreadEntry::list_ = this;
-}
-
-ThreadEntry* ThreadEntry::Get(pid_t pid, pid_t tid, bool create) {
- pthread_mutex_lock(&ThreadEntry::list_mutex_);
- ThreadEntry* entry = list_;
- while (entry != nullptr) {
- if (entry->Match(pid, tid)) {
- break;
- }
- entry = entry->next_;
- }
-
- if (!entry) {
- if (create) {
- entry = new ThreadEntry(pid, tid);
- }
- } else {
- entry->ref_count_++;
- }
- pthread_mutex_unlock(&ThreadEntry::list_mutex_);
-
- return entry;
-}
-
-void ThreadEntry::Remove(ThreadEntry* entry) {
- entry->Unlock();
-
- pthread_mutex_lock(&ThreadEntry::list_mutex_);
- if (--entry->ref_count_ == 0) {
- delete entry;
- }
- pthread_mutex_unlock(&ThreadEntry::list_mutex_);
-}
-
-// Assumes that ThreadEntry::list_mutex_ has already been locked before
-// deleting a ThreadEntry object.
-ThreadEntry::~ThreadEntry() {
- if (list_ == this) {
- list_ = next_;
- } else {
- if (next_) {
- next_->prev_ = prev_;
- }
- prev_->next_ = next_;
- }
-
- next_ = nullptr;
- prev_ = nullptr;
-
- pthread_cond_destroy(&wait_cond_);
-}
-
-bool ThreadEntry::Wait(int value) {
- timespec ts;
- clock_gettime(CLOCK_MONOTONIC, &ts);
- ts.tv_sec += 5;
-
- bool wait_completed = true;
- pthread_mutex_lock(&wait_mutex_);
- while (wait_value_ != value) {
- int ret = pthread_cond_timedwait(&wait_cond_, &wait_mutex_, &ts);
- if (ret != 0) {
- BACK_ASYNC_SAFE_LOGW("pthread_cond_timedwait for value %d failed: %s", value, strerror(ret));
- wait_completed = false;
- break;
- }
- }
- pthread_mutex_unlock(&wait_mutex_);
-
- return wait_completed;
-}
-
-void ThreadEntry::Wake() {
- pthread_mutex_lock(&wait_mutex_);
- wait_value_++;
- pthread_mutex_unlock(&wait_mutex_);
-
- pthread_cond_signal(&wait_cond_);
-}
-
-void ThreadEntry::CopyUcontextFromSigcontext(void* sigcontext) {
- ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(sigcontext);
- // The only thing the unwinder cares about is the mcontext data.
- memcpy(&ucontext_.uc_mcontext, &ucontext->uc_mcontext, sizeof(ucontext->uc_mcontext));
-}
diff --git a/libbacktrace/ThreadEntry.h b/libbacktrace/ThreadEntry.h
deleted file mode 100644
index caa5497..0000000
--- a/libbacktrace/ThreadEntry.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef _LIBBACKTRACE_THREAD_ENTRY_H
-#define _LIBBACKTRACE_THREAD_ENTRY_H
-
-#include <pthread.h>
-#include <sys/types.h>
-#include <ucontext.h>
-
-class ThreadEntry {
- public:
- static ThreadEntry* Get(pid_t pid, pid_t tid, bool create = true);
-
- static void Remove(ThreadEntry* entry);
-
- void Wake();
-
- bool Wait(int);
-
- void CopyUcontextFromSigcontext(void*);
-
- inline void Lock() {
- pthread_mutex_lock(&mutex_);
-
- // Always reset the wait value since this could be the first or nth
- // time this entry is locked.
- wait_value_ = 0;
- }
-
- inline void Unlock() {
- pthread_mutex_unlock(&mutex_);
- }
-
- inline ucontext_t* GetUcontext() { return &ucontext_; }
-
- private:
- ThreadEntry(pid_t pid, pid_t tid);
- ~ThreadEntry();
-
- bool Match(pid_t chk_pid, pid_t chk_tid) { return (chk_pid == pid_ && chk_tid == tid_); }
-
- pid_t pid_;
- pid_t tid_;
- int ref_count_;
- pthread_mutex_t mutex_;
- pthread_mutex_t wait_mutex_;
- pthread_cond_t wait_cond_;
- int wait_value_;
- ThreadEntry* next_;
- ThreadEntry* prev_;
- ucontext_t ucontext_;
-
- static ThreadEntry* list_;
- static pthread_mutex_t list_mutex_;
-};
-
-#endif // _LIBBACKTRACE_THREAD_ENTRY_H
diff --git a/libbacktrace/UnwindMap.cpp b/libbacktrace/UnwindMap.cpp
deleted file mode 100644
index 798c769..0000000
--- a/libbacktrace/UnwindMap.cpp
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2014 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 <pthread.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <backtrace/BacktraceMap.h>
-
-#include <libunwind.h>
-
-#include "BacktraceLog.h"
-#include "UnwindMap.h"
-
-//-------------------------------------------------------------------------
-// libunwind has a single shared address space for the current process
-// aka local. If multiple maps are created for the current pid, then
-// only update the local address space once, and keep a reference count
-// of maps using the same map cursor.
-//-------------------------------------------------------------------------
-UnwindMap::UnwindMap(pid_t pid) : BacktraceMap(pid) {
- unw_map_cursor_clear(&map_cursor_);
-}
-
-UnwindMapRemote::UnwindMapRemote(pid_t pid) : UnwindMap(pid) {
-}
-
-UnwindMapRemote::~UnwindMapRemote() {
- unw_map_cursor_destroy(&map_cursor_);
- unw_map_cursor_clear(&map_cursor_);
-}
-
-bool UnwindMapRemote::GenerateMap() {
- // Use the map_cursor information to construct the BacktraceMap data
- // rather than reparsing /proc/self/maps.
- unw_map_cursor_reset(&map_cursor_);
-
- unw_map_t unw_map;
- while (unw_map_cursor_get_next(&map_cursor_, &unw_map)) {
- backtrace_map_t map;
-
- map.start = unw_map.start;
- map.end = unw_map.end;
- map.offset = unw_map.offset;
- map.load_bias = unw_map.load_base;
- map.flags = unw_map.flags;
- map.name = unw_map.path;
-
- // The maps are in descending order, but we want them in ascending order.
- maps_.push_front(map);
- }
-
- return true;
-}
-
-bool UnwindMapRemote::Build() {
- return (unw_map_cursor_create(&map_cursor_, pid_) == 0) && GenerateMap();
-}
-
-UnwindMapLocal::UnwindMapLocal() : UnwindMap(getpid()), map_created_(false) {
- pthread_rwlock_init(&map_lock_, nullptr);
-}
-
-UnwindMapLocal::~UnwindMapLocal() {
- if (map_created_) {
- unw_map_local_destroy();
- unw_map_cursor_clear(&map_cursor_);
- }
-}
-
-bool UnwindMapLocal::GenerateMap() {
- // Lock so that multiple threads cannot modify the maps data at the
- // same time.
- pthread_rwlock_wrlock(&map_lock_);
-
- // It's possible for the map to be regenerated while this loop is occurring.
- // If that happens, get the map again, but only try at most three times
- // before giving up.
- bool generated = false;
- for (int i = 0; i < 3; i++) {
- maps_.clear();
-
- // Save the map data retrieved so we can tell if it changes.
- unw_map_local_cursor_get(&map_cursor_);
-
- unw_map_t unw_map;
- int ret;
- while ((ret = unw_map_local_cursor_get_next(&map_cursor_, &unw_map)) > 0) {
- backtrace_map_t map;
-
- map.start = unw_map.start;
- map.end = unw_map.end;
- map.offset = unw_map.offset;
- map.load_bias = unw_map.load_base;
- map.flags = unw_map.flags;
- map.name = unw_map.path;
-
- free(unw_map.path);
-
- // The maps are in descending order, but we want them in ascending order.
- maps_.push_front(map);
- }
- // Check to see if the map changed while getting the data.
- if (ret != -UNW_EINVAL) {
- generated = true;
- break;
- }
- }
-
- pthread_rwlock_unlock(&map_lock_);
-
- if (!generated) {
- BACK_LOGW("Unable to generate the map.");
- }
- return generated;
-}
-
-bool UnwindMapLocal::Build() {
- return (map_created_ = (unw_map_local_create() == 0)) && GenerateMap();;
-}
-
-void UnwindMapLocal::FillIn(uint64_t addr, backtrace_map_t* map) {
- BacktraceMap::FillIn(addr, map);
- if (!IsValid(*map)) {
- // Check to see if the underlying map changed and regenerate the map
- // if it did.
- if (unw_map_local_cursor_valid(&map_cursor_) < 0) {
- if (GenerateMap()) {
- BacktraceMap::FillIn(addr, map);
- }
- }
- }
-}
diff --git a/libbacktrace/UnwindMap.h b/libbacktrace/UnwindMap.h
deleted file mode 100644
index 15544e8..0000000
--- a/libbacktrace/UnwindMap.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#ifndef _LIBBACKTRACE_UNWIND_MAP_H
-#define _LIBBACKTRACE_UNWIND_MAP_H
-
-#include <pthread.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <backtrace/BacktraceMap.h>
-
-// The unw_map_cursor_t structure is different depending on whether it is
-// the local or remote version. In order to get the correct version, include
-// libunwind.h first then this header.
-
-class UnwindMap : public BacktraceMap {
- public:
- explicit UnwindMap(pid_t pid);
-
- unw_map_cursor_t* GetMapCursor() { return &map_cursor_; }
-
- protected:
- unw_map_cursor_t map_cursor_;
-};
-
-class UnwindMapRemote : public UnwindMap {
- public:
- explicit UnwindMapRemote(pid_t pid);
- virtual ~UnwindMapRemote();
-
- bool Build() override;
-
- private:
- bool GenerateMap();
-};
-
-class UnwindMapLocal : public UnwindMap {
- public:
- UnwindMapLocal();
- virtual ~UnwindMapLocal();
-
- bool Build() override;
-
- void FillIn(uint64_t addr, backtrace_map_t* map) override;
-
- void LockIterator() override { pthread_rwlock_rdlock(&map_lock_); }
- void UnlockIterator() override { pthread_rwlock_unlock(&map_lock_); }
-
- private:
- bool GenerateMap();
-
- bool map_created_;
-
- pthread_rwlock_t map_lock_;
-};
-
-#endif // _LIBBACKTRACE_UNWIND_MAP_H
diff --git a/libbacktrace/UnwindStack.cpp b/libbacktrace/UnwindStack.cpp
deleted file mode 100644
index 82ff21c..0000000
--- a/libbacktrace/UnwindStack.cpp
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#define _GNU_SOURCE 1
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <memory>
-#include <set>
-#include <string>
-
-#include <backtrace/Backtrace.h>
-#include <unwindstack/Elf.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/Regs.h>
-#include <unwindstack/RegsGetLocal.h>
-
-#if !defined(NO_LIBDEXFILE_SUPPORT)
-#include <unwindstack/DexFiles.h>
-#endif
-#include <unwindstack/Unwinder.h>
-
-#include "BacktraceLog.h"
-#include "UnwindStack.h"
-#include "UnwindStackMap.h"
-
-extern "C" char* __cxa_demangle(const char*, char*, size_t*, int*);
-
-bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map,
- std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames,
- std::vector<std::string>* skip_names, BacktraceUnwindError* error) {
- UnwindStackMap* stack_map = reinterpret_cast<UnwindStackMap*>(back_map);
- auto process_memory = stack_map->process_memory();
- unwindstack::Unwinder unwinder(MAX_BACKTRACE_FRAMES + num_ignore_frames, stack_map->stack_maps(),
- regs, stack_map->process_memory());
- unwinder.SetResolveNames(stack_map->ResolveNames());
- stack_map->SetArch(regs->Arch());
- if (stack_map->GetJitDebug() != nullptr) {
- unwinder.SetJitDebug(stack_map->GetJitDebug());
- }
-#if !defined(NO_LIBDEXFILE_SUPPORT)
- if (stack_map->GetDexFiles() != nullptr) {
- unwinder.SetDexFiles(stack_map->GetDexFiles());
- }
-#endif
- unwinder.Unwind(skip_names, &stack_map->GetSuffixesToIgnore());
- if (error != nullptr) {
- switch (unwinder.LastErrorCode()) {
- case unwindstack::ERROR_NONE:
- error->error_code = BACKTRACE_UNWIND_NO_ERROR;
- break;
-
- case unwindstack::ERROR_MEMORY_INVALID:
- error->error_code = BACKTRACE_UNWIND_ERROR_ACCESS_MEM_FAILED;
- error->error_info.addr = unwinder.LastErrorAddress();
- break;
-
- case unwindstack::ERROR_UNWIND_INFO:
- error->error_code = BACKTRACE_UNWIND_ERROR_UNWIND_INFO;
- break;
-
- case unwindstack::ERROR_UNSUPPORTED:
- error->error_code = BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION;
- break;
-
- case unwindstack::ERROR_INVALID_MAP:
- error->error_code = BACKTRACE_UNWIND_ERROR_MAP_MISSING;
- break;
-
- case unwindstack::ERROR_MAX_FRAMES_EXCEEDED:
- error->error_code = BACKTRACE_UNWIND_ERROR_EXCEED_MAX_FRAMES_LIMIT;
- break;
-
- case unwindstack::ERROR_REPEATED_FRAME:
- error->error_code = BACKTRACE_UNWIND_ERROR_REPEATED_FRAME;
- break;
-
- case unwindstack::ERROR_INVALID_ELF:
- error->error_code = BACKTRACE_UNWIND_ERROR_INVALID_ELF;
- break;
- }
- }
-
- if (num_ignore_frames >= unwinder.NumFrames()) {
- frames->resize(0);
- return true;
- }
-
- auto unwinder_frames = unwinder.frames();
- frames->resize(unwinder.NumFrames() - num_ignore_frames);
- size_t cur_frame = 0;
- for (size_t i = num_ignore_frames; i < unwinder.NumFrames(); i++) {
- auto frame = &unwinder_frames[i];
-
- backtrace_frame_data_t* back_frame = &frames->at(cur_frame);
-
- back_frame->num = cur_frame++;
-
- back_frame->rel_pc = frame->rel_pc;
- back_frame->pc = frame->pc;
- back_frame->sp = frame->sp;
-
- char* demangled_name = __cxa_demangle(frame->function_name.c_str(), nullptr, nullptr, nullptr);
- if (demangled_name != nullptr) {
- back_frame->func_name = demangled_name;
- free(demangled_name);
- } else {
- back_frame->func_name = frame->function_name;
- }
- back_frame->func_offset = frame->function_offset;
-
- back_frame->map.name = frame->map_name;
- back_frame->map.start = frame->map_start;
- back_frame->map.end = frame->map_end;
- back_frame->map.offset = frame->map_elf_start_offset;
- back_frame->map.load_bias = frame->map_load_bias;
- back_frame->map.flags = frame->map_flags;
- }
-
- return true;
-}
-
-UnwindStackCurrent::UnwindStackCurrent(pid_t pid, pid_t tid, BacktraceMap* map)
- : BacktraceCurrent(pid, tid, map) {}
-
-std::string UnwindStackCurrent::GetFunctionNameRaw(uint64_t pc, uint64_t* offset) {
- return GetMap()->GetFunctionName(pc, offset);
-}
-
-bool UnwindStackCurrent::UnwindFromContext(size_t num_ignore_frames, void* ucontext) {
- std::unique_ptr<unwindstack::Regs> regs;
- if (ucontext == nullptr) {
- regs.reset(unwindstack::Regs::CreateFromLocal());
- // Fill in the registers from this function. Do it here to avoid
- // one extra function call appearing in the unwind.
- unwindstack::RegsGetLocal(regs.get());
- } else {
- regs.reset(unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(), ucontext));
- }
-
- std::vector<std::string> skip_names{"libunwindstack.so", "libbacktrace.so"};
- if (!skip_frames_) {
- skip_names.clear();
- }
- return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames, &skip_names, &error_);
-}
-
-UnwindStackPtrace::UnwindStackPtrace(pid_t pid, pid_t tid, BacktraceMap* map)
- : BacktracePtrace(pid, tid, map), memory_(unwindstack::Memory::CreateProcessMemory(pid)) {}
-
-std::string UnwindStackPtrace::GetFunctionNameRaw(uint64_t pc, uint64_t* offset) {
- return GetMap()->GetFunctionName(pc, offset);
-}
-
-bool UnwindStackPtrace::Unwind(size_t num_ignore_frames, void* context) {
- std::unique_ptr<unwindstack::Regs> regs;
- if (context == nullptr) {
- regs.reset(unwindstack::Regs::RemoteGet(Tid()));
- } else {
- regs.reset(unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(), context));
- }
-
- return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames, nullptr, &error_);
-}
-
-size_t UnwindStackPtrace::Read(uint64_t addr, uint8_t* buffer, size_t bytes) {
-#if defined(__aarch64__)
- // Tagged pointer after Android R would lead top byte to have random values
- // https://source.android.com/devices/tech/debug/tagged-pointers
- addr &= (1ULL << 56) - 1;
-#endif
- return memory_->Read(addr, buffer, bytes);
-}
diff --git a/libbacktrace/UnwindStack.h b/libbacktrace/UnwindStack.h
deleted file mode 100644
index 47f6757..0000000
--- a/libbacktrace/UnwindStack.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef _LIBBACKTRACE_UNWIND_STACK_H
-#define _LIBBACKTRACE_UNWIND_STACK_H
-
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-
-#include <backtrace/BacktraceMap.h>
-#include <unwindstack/Memory.h>
-
-#include "BacktraceCurrent.h"
-#include "BacktracePtrace.h"
-
-class UnwindStackCurrent : public BacktraceCurrent {
- public:
- UnwindStackCurrent(pid_t pid, pid_t tid, BacktraceMap* map);
- virtual ~UnwindStackCurrent() = default;
-
- std::string GetFunctionNameRaw(uint64_t pc, uint64_t* offset) override;
-
- bool UnwindFromContext(size_t num_ignore_frames, void* ucontext) override;
-};
-
-class UnwindStackPtrace : public BacktracePtrace {
- public:
- UnwindStackPtrace(pid_t pid, pid_t tid, BacktraceMap* map);
- virtual ~UnwindStackPtrace() = default;
-
- bool Unwind(size_t num_ignore_frames, void* context) override;
-
- std::string GetFunctionNameRaw(uint64_t pc, uint64_t* offset) override;
-
- size_t Read(uint64_t addr, uint8_t* buffer, size_t bytes) override;
-
- private:
- std::shared_ptr<unwindstack::Memory> memory_;
-};
-
-#endif // _LIBBACKTRACE_UNWIND_STACK_H
diff --git a/libbacktrace/UnwindStackMap.cpp b/libbacktrace/UnwindStackMap.cpp
deleted file mode 100644
index aa0b17c..0000000
--- a/libbacktrace/UnwindStackMap.cpp
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (C) 2017 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 <stdint.h>
-#include <stdlib.h>
-#include <sys/types.h>
-
-#include <string>
-#include <vector>
-
-#include <backtrace/BacktraceMap.h>
-#include <unwindstack/Elf.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Regs.h>
-
-#include "UnwindStackMap.h"
-
-//-------------------------------------------------------------------------
-UnwindStackMap::UnwindStackMap(pid_t pid) : BacktraceMap(pid) {}
-
-bool UnwindStackMap::Build() {
- if (pid_ == 0) {
- pid_ = getpid();
- stack_maps_.reset(new unwindstack::LocalMaps);
- } else {
- stack_maps_.reset(new unwindstack::RemoteMaps(pid_));
- }
-
- // Create the process memory object.
- process_memory_ = unwindstack::Memory::CreateProcessMemory(pid_);
-
- // Create a JitDebug object for getting jit unwind information.
- std::vector<std::string> search_libs_{"libart.so", "libartd.so"};
- jit_debug_.reset(new unwindstack::JitDebug(process_memory_, search_libs_));
-#if !defined(NO_LIBDEXFILE_SUPPORT)
- dex_files_.reset(new unwindstack::DexFiles(process_memory_, search_libs_));
-#endif
-
- if (!stack_maps_->Parse()) {
- return false;
- }
-
- // Iterate through the maps and fill in the backtrace_map_t structure.
- for (const auto& map_info : *stack_maps_) {
- backtrace_map_t map;
- map.start = map_info->start;
- map.end = map_info->end;
- map.offset = map_info->offset;
- // Set to -1 so that it is demand loaded.
- map.load_bias = static_cast<uint64_t>(-1);
- map.flags = map_info->flags;
- map.name = map_info->name;
-
- maps_.push_back(map);
- }
-
- return true;
-}
-
-void UnwindStackMap::FillIn(uint64_t addr, backtrace_map_t* map) {
- BacktraceMap::FillIn(addr, map);
- if (map->load_bias != static_cast<uint64_t>(-1)) {
- return;
- }
-
- // Fill in the load_bias.
- unwindstack::MapInfo* map_info = stack_maps_->Find(addr);
- if (map_info == nullptr) {
- return;
- }
- map->load_bias = map_info->GetLoadBias(process_memory_);
-}
-
-uint64_t UnwindStackMap::GetLoadBias(size_t index) {
- if (index >= stack_maps_->Total()) {
- return 0;
- }
-
- unwindstack::MapInfo* map_info = stack_maps_->Get(index);
- if (map_info == nullptr) {
- return 0;
- }
- return map_info->GetLoadBias(process_memory_);
-}
-
-std::string UnwindStackMap::GetFunctionName(uint64_t pc, uint64_t* offset) {
- *offset = 0;
- unwindstack::Maps* maps = stack_maps();
-
- // Get the map for this
- unwindstack::MapInfo* map_info = maps->Find(pc);
- if (map_info == nullptr || map_info->flags & PROT_DEVICE_MAP) {
- return "";
- }
-
- if (arch_ == unwindstack::ARCH_UNKNOWN) {
- if (pid_ == getpid()) {
- arch_ = unwindstack::Regs::CurrentArch();
- } else {
- // Create a remote regs, to figure out the architecture.
- std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::RemoteGet(pid_));
- arch_ = regs->Arch();
- }
- }
-
- unwindstack::Elf* elf = map_info->GetElf(process_memory(), arch_);
-
- std::string name;
- uint64_t func_offset;
- if (!elf->GetFunctionName(elf->GetRelPc(pc, map_info), &name, &func_offset)) {
- return "";
- }
- *offset = func_offset;
- return name;
-}
-
-std::shared_ptr<unwindstack::Memory> UnwindStackMap::GetProcessMemory() {
- return process_memory_;
-}
-
-//-------------------------------------------------------------------------
-// BacktraceMap create function.
-//-------------------------------------------------------------------------
-BacktraceMap* BacktraceMap::Create(pid_t pid, bool uncached) {
- BacktraceMap* map;
-
- if (uncached) {
- // Force use of the base class to parse the maps when this call is made.
- map = new BacktraceMap(pid);
- } else if (pid == getpid()) {
- map = new UnwindStackMap(0);
- } else {
- map = new UnwindStackMap(pid);
- }
- if (!map->Build()) {
- delete map;
- return nullptr;
- }
- return map;
-}
diff --git a/libbacktrace/UnwindStackMap.h b/libbacktrace/UnwindStackMap.h
deleted file mode 100644
index f0e7d8b..0000000
--- a/libbacktrace/UnwindStackMap.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef _LIBBACKTRACE_UNWINDSTACK_MAP_H
-#define _LIBBACKTRACE_UNWINDSTACK_MAP_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <memory>
-#include <mutex>
-#include <unordered_map>
-#include <vector>
-
-#include <backtrace/Backtrace.h>
-#include <backtrace/BacktraceMap.h>
-#if !defined(NO_LIBDEXFILE_SUPPORT)
-#include <unwindstack/DexFiles.h>
-#endif
-#include <unwindstack/Elf.h>
-#include <unwindstack/JitDebug.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
-
-// Forward declarations.
-class UnwindDexFile;
-
-class UnwindStackMap : public BacktraceMap {
- public:
- explicit UnwindStackMap(pid_t pid);
- ~UnwindStackMap() = default;
-
- bool Build() override;
-
- void FillIn(uint64_t addr, backtrace_map_t* map) override;
-
- virtual std::string GetFunctionName(uint64_t pc, uint64_t* offset) override;
- virtual std::shared_ptr<unwindstack::Memory> GetProcessMemory() override final;
-
- unwindstack::Maps* stack_maps() { return stack_maps_.get(); }
-
- const std::shared_ptr<unwindstack::Memory>& process_memory() { return process_memory_; }
-
- unwindstack::JitDebug* GetJitDebug() { return jit_debug_.get(); }
-
-#if !defined(NO_LIBDEXFILE_SUPPORT)
- unwindstack::DexFiles* GetDexFiles() { return dex_files_.get(); }
-#endif
-
- void SetArch(unwindstack::ArchEnum arch) { arch_ = arch; }
-
- protected:
- uint64_t GetLoadBias(size_t index) override;
-
- std::unique_ptr<unwindstack::Maps> stack_maps_;
- std::shared_ptr<unwindstack::Memory> process_memory_;
- std::unique_ptr<unwindstack::JitDebug> jit_debug_;
-#if !defined(NO_LIBDEXFILE_SUPPORT)
- std::unique_ptr<unwindstack::DexFiles> dex_files_;
-#endif
-
- unwindstack::ArchEnum arch_ = unwindstack::ARCH_UNKNOWN;
-};
-
-#endif // _LIBBACKTRACE_UNWINDSTACK_MAP_H
diff --git a/libbacktrace/backtrace_benchmarks.cpp b/libbacktrace/backtrace_benchmarks.cpp
deleted file mode 100644
index a93a25e..0000000
--- a/libbacktrace/backtrace_benchmarks.cpp
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2017 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 <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/prctl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <string>
-
-#include <android-base/file.h>
-#include <android-base/threads.h>
-
-#include <benchmark/benchmark.h>
-
-#include <backtrace/Backtrace.h>
-#include <backtrace/BacktraceMap.h>
-#include <unwindstack/Memory.h>
-
-constexpr size_t kNumMaps = 2000;
-
-static bool CountMaps(pid_t pid, size_t* num_maps) {
- // Minimize the calls that might allocate memory. If too much memory
- // gets allocated, then this routine will add extra maps and the next
- // call will fail to get the same number of maps as before.
- int fd =
- open((std::string("/proc/") + std::to_string(pid) + "/maps").c_str(), O_RDONLY | O_CLOEXEC);
- if (fd == -1) {
- fprintf(stderr, "Cannot open map file for pid %d: %s\n", pid, strerror(errno));
- return false;
- }
- *num_maps = 0;
- while (true) {
- char buffer[2048];
- ssize_t bytes = read(fd, buffer, sizeof(buffer));
- if (bytes <= 0) {
- break;
- }
- // Count the '\n'.
- for (size_t i = 0; i < static_cast<size_t>(bytes); i++) {
- if (buffer[i] == '\n') {
- ++*num_maps;
- }
- }
- }
-
- close(fd);
- return true;
-}
-
-static void CreateMap(benchmark::State& state, BacktraceMap* (*map_func)(pid_t, bool)) {
- // Create a remote process so that the map data is exactly the same.
- // Also, so that we can create a set number of maps.
- pid_t pid;
- if ((pid = fork()) == 0) {
- size_t num_maps;
- if (!CountMaps(getpid(), &num_maps)) {
- exit(1);
- }
- // Create uniquely named maps.
- std::vector<void*> maps;
- for (size_t i = num_maps; i < kNumMaps; i++) {
- int flags = PROT_READ | PROT_WRITE;
- // Alternate page type to make sure a map entry is added for each call.
- if ((i % 2) == 0) {
- flags |= PROT_EXEC;
- }
- void* memory = mmap(nullptr, PAGE_SIZE, flags, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (memory == MAP_FAILED) {
- fprintf(stderr, "Failed to create map: %s\n", strerror(errno));
- exit(1);
- }
- memset(memory, 0x1, PAGE_SIZE);
-#if defined(PR_SET_VMA)
- if (prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, memory, PAGE_SIZE, "test_map") == -1) {
- fprintf(stderr, "Failed: %s\n", strerror(errno));
- }
-#endif
- maps.push_back(memory);
- }
-
- if (!CountMaps(getpid(), &num_maps)) {
- exit(1);
- }
-
- if (num_maps < kNumMaps) {
- fprintf(stderr, "Maps set incorrectly: %zu found, %zu expected at least.\n", num_maps,
- kNumMaps);
- std::string str;
- android::base::ReadFileToString("/proc/self/maps", &str);
- fprintf(stderr, "%s\n", str.c_str());
- exit(1);
- }
-
- // Wait for an hour at most.
- sleep(3600);
- exit(1);
- } else if (pid < 0) {
- fprintf(stderr, "Fork failed: %s\n", strerror(errno));
- return;
- }
-
- size_t num_maps = 0;
- for (size_t i = 0; i < 2000; i++) {
- if (CountMaps(pid, &num_maps) && num_maps >= kNumMaps) {
- break;
- }
- usleep(1000);
- }
- if (num_maps < kNumMaps) {
- fprintf(stderr, "Timed out waiting for the number of maps available: %zu\n", num_maps);
- return;
- }
-
- while (state.KeepRunning()) {
- BacktraceMap* map = map_func(pid, false);
- if (map == nullptr) {
- fprintf(stderr, "Failed to create map\n");
- return;
- }
- delete map;
- }
-
- kill(pid, SIGKILL);
- waitpid(pid, nullptr, 0);
-}
-
-static void BM_create_map(benchmark::State& state) {
- CreateMap(state, BacktraceMap::Create);
-}
-BENCHMARK(BM_create_map);
-
-using BacktraceCreateFn = decltype(Backtrace::Create);
-
-static void CreateBacktrace(benchmark::State& state, BacktraceMap* map, BacktraceCreateFn fn) {
- while (state.KeepRunning()) {
- std::unique_ptr<Backtrace> backtrace(fn(getpid(), android::base::GetThreadId(), map));
- backtrace->Unwind(0);
- }
-}
-
-static void BM_create_backtrace(benchmark::State& state) {
- std::unique_ptr<BacktraceMap> backtrace_map(BacktraceMap::Create(getpid()));
- CreateBacktrace(state, backtrace_map.get(), Backtrace::Create);
-}
-BENCHMARK(BM_create_backtrace);
-
-BENCHMARK_MAIN();
diff --git a/libbacktrace/backtrace_read_benchmarks.cpp b/libbacktrace/backtrace_read_benchmarks.cpp
deleted file mode 100644
index 6a688b0..0000000
--- a/libbacktrace/backtrace_read_benchmarks.cpp
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2017 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 <errno.h>
-#include <signal.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/ptrace.h>
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <memory>
-#include <vector>
-
-#include <benchmark/benchmark.h>
-
-#include <backtrace/Backtrace.h>
-
-#define AT_COMMON_SIZES Arg(1)->Arg(4)->Arg(8)->Arg(16)->Arg(100)->Arg(200)->Arg(500)->Arg(1024)
-
-static void Attach(pid_t pid) {
- if (ptrace(PTRACE_ATTACH, pid, 0, 0) == -1) {
- perror("Failed to attach");
- abort();
- }
-
- siginfo_t si;
- // Wait for up to 5 seconds.
- for (size_t i = 0; i < 5000; i++) {
- if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
- return;
- }
- usleep(1000);
- }
- printf("Remote process failed to stop in five seconds.\n");
- abort();
-}
-
-class ScopedPidReaper {
- public:
- ScopedPidReaper(pid_t pid) : pid_(pid) {}
- ~ScopedPidReaper() {
- kill(pid_, SIGKILL);
- waitpid(pid_, nullptr, 0);
- }
-
- private:
- pid_t pid_;
-};
-
-static size_t ProcessVmRead(pid_t pid, uint64_t remote_src, void* dst, size_t len) {
- struct iovec dst_iov = {
- .iov_base = dst, .iov_len = len,
- };
-
- struct iovec src_iov = {
- .iov_base = reinterpret_cast<void*>(remote_src), .iov_len = len,
- };
-
- ssize_t rc = process_vm_readv(pid, &dst_iov, 1, &src_iov, 1, 0);
- return rc == -1 ? 0 : rc;
-}
-
-static bool PtraceReadLong(pid_t pid, uint64_t addr, long* value) {
- // ptrace() returns -1 and sets errno when the operation fails.
- // To disambiguate -1 from a valid result, we clear errno beforehand.
- errno = 0;
- *value = ptrace(PTRACE_PEEKTEXT, pid, reinterpret_cast<void*>(addr), nullptr);
- if (*value == -1 && errno) {
- return false;
- }
- return true;
-}
-
-static size_t PtraceRead(pid_t pid, uint64_t addr, void* dst, size_t bytes) {
- size_t bytes_read = 0;
- long data;
- for (size_t i = 0; i < bytes / sizeof(long); i++) {
- if (!PtraceReadLong(pid, addr, &data)) {
- return bytes_read;
- }
- memcpy(dst, &data, sizeof(long));
- dst = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(dst) + sizeof(long));
- addr += sizeof(long);
- bytes_read += sizeof(long);
- }
-
- size_t left_over = bytes & (sizeof(long) - 1);
- if (left_over) {
- if (!PtraceReadLong(pid, addr, &data)) {
- return bytes_read;
- }
- memcpy(dst, &data, left_over);
- bytes_read += left_over;
- }
- return bytes_read;
-}
-
-static void CreateRemoteProcess(size_t size, void** map, pid_t* pid) {
- *map = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (*map == MAP_FAILED) {
- perror("Can't allocate memory");
- abort();
- }
- memset(*map, 0xaa, size);
-
- if ((*pid = fork()) == 0) {
- for (volatile int i = 0;; i++)
- ;
- exit(1);
- }
- if (*pid < 0) {
- perror("Failed to fork");
- abort();
- }
- Attach(*pid);
- // Don't need this map in the current process any more.
- munmap(*map, size);
-}
-
-static void BM_read_with_ptrace(benchmark::State& state) {
- void* map;
- pid_t pid;
- CreateRemoteProcess(state.range(0), &map, &pid);
- ScopedPidReaper reap(pid);
-
- std::vector<uint8_t> read_buffer(state.range(0));
- uint64_t addr = reinterpret_cast<uint64_t>(map);
- while (state.KeepRunning()) {
- if (PtraceRead(pid, addr, read_buffer.data(), read_buffer.size()) != read_buffer.size()) {
- printf("Unexpected bad read.\n");
- abort();
- }
- }
- ptrace(PTRACE_DETACH, pid, 0, 0);
-}
-BENCHMARK(BM_read_with_ptrace)->AT_COMMON_SIZES;
-
-static void BM_read_with_process_vm_read(benchmark::State& state) {
- void* map;
- pid_t pid;
- CreateRemoteProcess(state.range(0), &map, &pid);
- ScopedPidReaper reap(pid);
-
- std::vector<uint8_t> read_buffer(state.range(0));
- uint64_t addr = reinterpret_cast<uint64_t>(map);
- while (state.KeepRunning()) {
- if (ProcessVmRead(pid, addr, read_buffer.data(), read_buffer.size()) != read_buffer.size()) {
- printf("Unexpected bad read.\n");
- abort();
- }
- }
- ptrace(PTRACE_DETACH, pid, 0, 0);
-}
-BENCHMARK(BM_read_with_process_vm_read)->AT_COMMON_SIZES;
-
-static void BM_read_with_backtrace_object(benchmark::State& state) {
- void* map;
- pid_t pid;
- CreateRemoteProcess(state.range(0), &map, &pid);
- ScopedPidReaper reap(pid);
-
- std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, BACKTRACE_CURRENT_THREAD));
- if (backtrace.get() == nullptr) {
- printf("Failed to create backtrace.\n");
- abort();
- }
-
- uint64_t addr = reinterpret_cast<uint64_t>(map);
- std::vector<uint8_t> read_buffer(state.range(0));
- while (state.KeepRunning()) {
- if (backtrace->Read(addr, read_buffer.data(), read_buffer.size()) != read_buffer.size()) {
- printf("Unexpected bad read.\n");
- abort();
- }
- }
- ptrace(PTRACE_DETACH, pid, 0, 0);
-}
-BENCHMARK(BM_read_with_backtrace_object)->AT_COMMON_SIZES;
diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp
deleted file mode 100644
index cc32b6d..0000000
--- a/libbacktrace/backtrace_test.cpp
+++ /dev/null
@@ -1,1893 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#define _GNU_SOURCE 1
-#include <dirent.h>
-#include <dlfcn.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <malloc.h>
-#include <pthread.h>
-#include <signal.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ptrace.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <time.h>
-#include <ucontext.h>
-#include <unistd.h>
-
-#include <algorithm>
-#include <list>
-#include <memory>
-#include <ostream>
-#include <string>
-#include <vector>
-
-#include <backtrace/Backtrace.h>
-#include <backtrace/BacktraceMap.h>
-
-#include <android-base/macros.h>
-#include <android-base/stringprintf.h>
-#include <android-base/test_utils.h>
-#include <android-base/threads.h>
-#include <android-base/unique_fd.h>
-#include <cutils/atomic.h>
-
-#include <gtest/gtest.h>
-
-// For the THREAD_SIGNAL definition.
-#include "BacktraceCurrent.h"
-#include "BacktraceTest.h"
-#include "backtrace_testlib.h"
-
-// Number of microseconds per milliseconds.
-#define US_PER_MSEC 1000
-
-// Number of nanoseconds in a second.
-#define NS_PER_SEC 1000000000ULL
-
-// Number of simultaneous dumping operations to perform.
-#define NUM_THREADS 40
-
-// Number of simultaneous threads running in our forked process.
-#define NUM_PTRACE_THREADS 5
-
-// The list of shared libaries that make up the backtrace library.
-static std::vector<std::string> kBacktraceLibs{"libunwindstack.so", "libbacktrace.so"};
-
-struct thread_t {
- pid_t tid;
- int32_t state;
- pthread_t threadId;
- void* data;
-};
-
-struct dump_thread_t {
- thread_t thread;
- BacktraceMap* map;
- Backtrace* backtrace;
- int32_t* now;
- int32_t done;
-};
-
-typedef Backtrace* (*create_func_t)(pid_t, pid_t, BacktraceMap*);
-typedef BacktraceMap* (*map_create_func_t)(pid_t, bool);
-
-static void VerifyLevelDump(Backtrace* backtrace, create_func_t create_func = nullptr,
- map_create_func_t map_func = nullptr);
-static void VerifyMaxDump(Backtrace* backtrace, create_func_t create_func = nullptr,
- map_create_func_t map_func = nullptr);
-
-void* BacktraceTest::dl_handle_;
-int (*BacktraceTest::test_level_one_)(int, int, int, int, void (*)(void*), void*);
-int (*BacktraceTest::test_level_two_)(int, int, int, int, void (*)(void*), void*);
-int (*BacktraceTest::test_level_three_)(int, int, int, int, void (*)(void*), void*);
-int (*BacktraceTest::test_level_four_)(int, int, int, int, void (*)(void*), void*);
-int (*BacktraceTest::test_recursive_call_)(int, void (*)(void*), void*);
-void (*BacktraceTest::test_get_context_and_wait_)(void*, volatile int*);
-void (*BacktraceTest::test_signal_action_)(int, siginfo_t*, void*);
-void (*BacktraceTest::test_signal_handler_)(int);
-
-extern "C" bool GetInitialArgs(const char*** args, size_t* num_args) {
- static const char* initial_args[] = {"--slow_threshold_ms=8000", "--deadline_threshold_ms=15000"};
- *args = initial_args;
- *num_args = 2;
- return true;
-}
-
-static uint64_t NanoTime() {
- struct timespec t = { 0, 0 };
- clock_gettime(CLOCK_MONOTONIC, &t);
- return static_cast<uint64_t>(t.tv_sec * NS_PER_SEC + t.tv_nsec);
-}
-
-static std::string DumpFrames(Backtrace* backtrace) {
- if (backtrace->NumFrames() == 0) {
- return " No frames to dump.\n";
- }
-
- std::string frame;
- for (size_t i = 0; i < backtrace->NumFrames(); i++) {
- frame += " " + backtrace->FormatFrameData(i) + '\n';
- }
- return frame;
-}
-
-static void WaitForStop(pid_t pid) {
- uint64_t start = NanoTime();
-
- siginfo_t si;
- while (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) < 0 && (errno == EINTR || errno == ESRCH)) {
- if ((NanoTime() - start) > NS_PER_SEC) {
- printf("The process did not get to a stopping point in 1 second.\n");
- break;
- }
- usleep(US_PER_MSEC);
- }
-}
-
-static void CreateRemoteProcess(pid_t* pid) {
- if ((*pid = fork()) == 0) {
- while (true)
- ;
- _exit(0);
- }
- ASSERT_NE(-1, *pid);
-
- ASSERT_TRUE(ptrace(PTRACE_ATTACH, *pid, 0, 0) == 0);
-
- // Wait for the process to get to a stopping point.
- WaitForStop(*pid);
-}
-
-static void FinishRemoteProcess(pid_t pid) {
- ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0);
-
- kill(pid, SIGKILL);
- ASSERT_EQ(waitpid(pid, nullptr, 0), pid);
-}
-
-#if !defined(__ANDROID__) || defined(__arm__)
-// On host and arm target we aren't guaranteed that we will terminate cleanly.
-#define VERIFY_NO_ERROR(error_code) \
- ASSERT_TRUE(error_code == BACKTRACE_UNWIND_NO_ERROR || \
- error_code == BACKTRACE_UNWIND_ERROR_UNWIND_INFO || \
- error_code == BACKTRACE_UNWIND_ERROR_MAP_MISSING) \
- << "Unknown error code " << std::to_string(error_code);
-#else
-#define VERIFY_NO_ERROR(error_code) ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, error_code);
-#endif
-
-static bool ReadyLevelBacktrace(Backtrace* backtrace) {
- // See if test_level_four is in the backtrace.
- bool found = false;
- for (Backtrace::const_iterator it = backtrace->begin(); it != backtrace->end(); ++it) {
- if (it->func_name == "test_level_four") {
- found = true;
- break;
- }
- }
-
- return found;
-}
-
-static void VerifyLevelDump(Backtrace* backtrace, create_func_t, map_create_func_t) {
- ASSERT_GT(backtrace->NumFrames(), static_cast<size_t>(0))
- << DumpFrames(backtrace);
- ASSERT_LT(backtrace->NumFrames(), static_cast<size_t>(MAX_BACKTRACE_FRAMES))
- << DumpFrames(backtrace);
-
- // Look through the frames starting at the highest to find the
- // frame we want.
- size_t frame_num = 0;
- for (size_t i = backtrace->NumFrames()-1; i > 2; i--) {
- if (backtrace->GetFrame(i)->func_name == "test_level_one") {
- frame_num = i;
- break;
- }
- }
- ASSERT_LT(static_cast<size_t>(0), frame_num) << DumpFrames(backtrace);
- ASSERT_LE(static_cast<size_t>(3), frame_num) << DumpFrames(backtrace);
-
- ASSERT_EQ(backtrace->GetFrame(frame_num)->func_name, "test_level_one")
- << DumpFrames(backtrace);
- ASSERT_EQ(backtrace->GetFrame(frame_num-1)->func_name, "test_level_two")
- << DumpFrames(backtrace);
- ASSERT_EQ(backtrace->GetFrame(frame_num-2)->func_name, "test_level_three")
- << DumpFrames(backtrace);
- ASSERT_EQ(backtrace->GetFrame(frame_num-3)->func_name, "test_level_four")
- << DumpFrames(backtrace);
-}
-
-static void VerifyLevelBacktrace(void*) {
- std::unique_ptr<Backtrace> backtrace(
- Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
- ASSERT_TRUE(backtrace.get() != nullptr);
- ASSERT_TRUE(backtrace->Unwind(0));
- VERIFY_NO_ERROR(backtrace->GetError().error_code);
-
- VerifyLevelDump(backtrace.get());
-}
-
-static bool ReadyMaxBacktrace(Backtrace* backtrace) {
- return (backtrace->NumFrames() == MAX_BACKTRACE_FRAMES);
-}
-
-static void VerifyMaxDump(Backtrace* backtrace, create_func_t, map_create_func_t) {
- ASSERT_EQ(backtrace->NumFrames(), static_cast<size_t>(MAX_BACKTRACE_FRAMES))
- << DumpFrames(backtrace);
- // Verify that the last frame is our recursive call.
- ASSERT_EQ(backtrace->GetFrame(MAX_BACKTRACE_FRAMES-1)->func_name, "test_recursive_call")
- << DumpFrames(backtrace);
-}
-
-static void VerifyMaxBacktrace(void*) {
- std::unique_ptr<Backtrace> backtrace(
- Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
- ASSERT_TRUE(backtrace.get() != nullptr);
- ASSERT_TRUE(backtrace->Unwind(0));
- ASSERT_EQ(BACKTRACE_UNWIND_ERROR_EXCEED_MAX_FRAMES_LIMIT, backtrace->GetError().error_code);
-
- VerifyMaxDump(backtrace.get());
-}
-
-static void ThreadSetState(void* data) {
- thread_t* thread = reinterpret_cast<thread_t*>(data);
- android_atomic_acquire_store(1, &thread->state);
- volatile int i = 0;
- while (thread->state) {
- i++;
- }
-}
-
-static bool WaitForNonZero(int32_t* value, uint64_t seconds) {
- uint64_t start = NanoTime();
- do {
- if (android_atomic_acquire_load(value)) {
- return true;
- }
- } while ((NanoTime() - start) < seconds * NS_PER_SEC);
- return false;
-}
-
-TEST_F(BacktraceTest, local_no_unwind_frames) {
- // Verify that a local unwind does not include any frames within
- // libunwind or libbacktrace.
- std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), getpid()));
- ASSERT_TRUE(backtrace.get() != nullptr);
- ASSERT_TRUE(backtrace->Unwind(0));
- VERIFY_NO_ERROR(backtrace->GetError().error_code);
-
- ASSERT_TRUE(backtrace->NumFrames() != 0);
- // None of the frames should be in the backtrace libraries.
- for (const auto& frame : *backtrace ) {
- if (BacktraceMap::IsValid(frame.map)) {
- const std::string name = basename(frame.map.name.c_str());
- for (const auto& lib : kBacktraceLibs) {
- ASSERT_TRUE(name != lib) << DumpFrames(backtrace.get());
- }
- }
- }
-}
-
-TEST_F(BacktraceTest, local_unwind_frames) {
- // Verify that a local unwind with the skip frames disabled does include
- // frames within the backtrace libraries.
- std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), getpid()));
- ASSERT_TRUE(backtrace.get() != nullptr);
- backtrace->SetSkipFrames(false);
- ASSERT_TRUE(backtrace->Unwind(0));
- VERIFY_NO_ERROR(backtrace->GetError().error_code);
-
- ASSERT_TRUE(backtrace->NumFrames() != 0);
- size_t first_frame_non_backtrace_lib = 0;
- for (const auto& frame : *backtrace) {
- if (BacktraceMap::IsValid(frame.map)) {
- const std::string name = basename(frame.map.name.c_str());
- bool found = false;
- for (const auto& lib : kBacktraceLibs) {
- if (name == lib) {
- found = true;
- break;
- }
- }
- if (!found) {
- first_frame_non_backtrace_lib = frame.num;
- break;
- }
- }
- }
-
- ASSERT_NE(0U, first_frame_non_backtrace_lib) << "No frames found in backtrace libraries:\n"
- << DumpFrames(backtrace.get());
-}
-
-TEST_F(BacktraceTest, local_trace) {
- ASSERT_NE(test_level_one_(1, 2, 3, 4, VerifyLevelBacktrace, nullptr), 0);
-}
-
-static void VerifyIgnoreFrames(Backtrace* bt_all, Backtrace* bt_ign1, Backtrace* bt_ign2,
- const char* cur_proc) {
- ASSERT_EQ(bt_all->NumFrames(), bt_ign1->NumFrames() + 1) << "All backtrace:\n"
- << DumpFrames(bt_all)
- << "Ignore 1 backtrace:\n"
- << DumpFrames(bt_ign1);
- ASSERT_EQ(bt_all->NumFrames(), bt_ign2->NumFrames() + 2) << "All backtrace:\n"
- << DumpFrames(bt_all)
- << "Ignore 2 backtrace:\n"
- << DumpFrames(bt_ign2);
-
- // Check all of the frames are the same > the current frame.
- bool check = (cur_proc == nullptr);
- for (size_t i = 0; i < bt_ign2->NumFrames(); i++) {
- if (check) {
- EXPECT_EQ(bt_ign2->GetFrame(i)->pc, bt_ign1->GetFrame(i+1)->pc);
- EXPECT_EQ(bt_ign2->GetFrame(i)->sp, bt_ign1->GetFrame(i+1)->sp);
- EXPECT_EQ(bt_ign2->GetFrame(i)->stack_size, bt_ign1->GetFrame(i+1)->stack_size);
-
- EXPECT_EQ(bt_ign2->GetFrame(i)->pc, bt_all->GetFrame(i+2)->pc);
- EXPECT_EQ(bt_ign2->GetFrame(i)->sp, bt_all->GetFrame(i+2)->sp);
- EXPECT_EQ(bt_ign2->GetFrame(i)->stack_size, bt_all->GetFrame(i+2)->stack_size);
- }
- if (!check && bt_ign2->GetFrame(i)->func_name == cur_proc) {
- check = true;
- }
- }
-}
-
-static void VerifyLevelIgnoreFrames(void*) {
- std::unique_ptr<Backtrace> all(
- Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
- ASSERT_TRUE(all.get() != nullptr);
- ASSERT_TRUE(all->Unwind(0));
- VERIFY_NO_ERROR(all->GetError().error_code);
-
- std::unique_ptr<Backtrace> ign1(
- Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
- ASSERT_TRUE(ign1.get() != nullptr);
- ASSERT_TRUE(ign1->Unwind(1));
- VERIFY_NO_ERROR(ign1->GetError().error_code);
-
- std::unique_ptr<Backtrace> ign2(
- Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
- ASSERT_TRUE(ign2.get() != nullptr);
- ASSERT_TRUE(ign2->Unwind(2));
- VERIFY_NO_ERROR(ign2->GetError().error_code);
-
- VerifyIgnoreFrames(all.get(), ign1.get(), ign2.get(), "VerifyLevelIgnoreFrames");
-}
-
-TEST_F(BacktraceTest, local_trace_ignore_frames) {
- ASSERT_NE(test_level_one_(1, 2, 3, 4, VerifyLevelIgnoreFrames, nullptr), 0);
-}
-
-TEST_F(BacktraceTest, local_max_trace) {
- ASSERT_NE(test_recursive_call_(MAX_BACKTRACE_FRAMES + 10, VerifyMaxBacktrace, nullptr), 0);
-}
-
-static void VerifyProcTest(pid_t pid, pid_t tid, bool (*ReadyFunc)(Backtrace*),
- void (*VerifyFunc)(Backtrace*, create_func_t, map_create_func_t),
- create_func_t create_func, map_create_func_t map_create_func) {
- pid_t ptrace_tid;
- if (tid < 0) {
- ptrace_tid = pid;
- } else {
- ptrace_tid = tid;
- }
- uint64_t start = NanoTime();
- bool verified = false;
- std::string last_dump;
- do {
- usleep(US_PER_MSEC);
- if (ptrace(PTRACE_ATTACH, ptrace_tid, 0, 0) == 0) {
- // Wait for the process to get to a stopping point.
- WaitForStop(ptrace_tid);
-
- std::unique_ptr<BacktraceMap> map;
- map.reset(map_create_func(pid, false));
- std::unique_ptr<Backtrace> backtrace(create_func(pid, tid, map.get()));
- ASSERT_TRUE(backtrace.get() != nullptr);
- ASSERT_TRUE(backtrace->Unwind(0));
- if (ReadyFunc(backtrace.get())) {
- VerifyFunc(backtrace.get(), create_func, map_create_func);
- verified = true;
- } else {
- last_dump = DumpFrames(backtrace.get());
- }
-
- ASSERT_TRUE(ptrace(PTRACE_DETACH, ptrace_tid, 0, 0) == 0);
- }
- // If 5 seconds have passed, then we are done.
- } while (!verified && (NanoTime() - start) <= 5 * NS_PER_SEC);
- ASSERT_TRUE(verified) << "Last backtrace:\n" << last_dump;
-}
-
-TEST_F(BacktraceTest, ptrace_trace) {
- pid_t pid;
- if ((pid = fork()) == 0) {
- ASSERT_NE(test_level_one_(1, 2, 3, 4, nullptr, nullptr), 0);
- _exit(1);
- }
- VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, ReadyLevelBacktrace, VerifyLevelDump,
- Backtrace::Create, BacktraceMap::Create);
-
- kill(pid, SIGKILL);
- int status;
- ASSERT_EQ(waitpid(pid, &status, 0), pid);
-}
-
-TEST_F(BacktraceTest, ptrace_max_trace) {
- pid_t pid;
- if ((pid = fork()) == 0) {
- ASSERT_NE(test_recursive_call_(MAX_BACKTRACE_FRAMES + 10, nullptr, nullptr), 0);
- _exit(1);
- }
- VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, ReadyMaxBacktrace, VerifyMaxDump, Backtrace::Create,
- BacktraceMap::Create);
-
- kill(pid, SIGKILL);
- int status;
- ASSERT_EQ(waitpid(pid, &status, 0), pid);
-}
-
-static void VerifyProcessIgnoreFrames(Backtrace* bt_all, create_func_t create_func,
- map_create_func_t map_create_func) {
- std::unique_ptr<BacktraceMap> map(map_create_func(bt_all->Pid(), false));
- std::unique_ptr<Backtrace> ign1(create_func(bt_all->Pid(), BACKTRACE_CURRENT_THREAD, map.get()));
- ASSERT_TRUE(ign1.get() != nullptr);
- ASSERT_TRUE(ign1->Unwind(1));
- VERIFY_NO_ERROR(ign1->GetError().error_code);
-
- std::unique_ptr<Backtrace> ign2(create_func(bt_all->Pid(), BACKTRACE_CURRENT_THREAD, map.get()));
- ASSERT_TRUE(ign2.get() != nullptr);
- ASSERT_TRUE(ign2->Unwind(2));
- VERIFY_NO_ERROR(ign2->GetError().error_code);
-
- VerifyIgnoreFrames(bt_all, ign1.get(), ign2.get(), nullptr);
-}
-
-TEST_F(BacktraceTest, ptrace_ignore_frames) {
- pid_t pid;
- if ((pid = fork()) == 0) {
- ASSERT_NE(test_level_one_(1, 2, 3, 4, nullptr, nullptr), 0);
- _exit(1);
- }
- VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, ReadyLevelBacktrace, VerifyProcessIgnoreFrames,
- Backtrace::Create, BacktraceMap::Create);
-
- kill(pid, SIGKILL);
- int status;
- ASSERT_EQ(waitpid(pid, &status, 0), pid);
-}
-
-// Create a process with multiple threads and dump all of the threads.
-static void* PtraceThreadLevelRun(void*) {
- EXPECT_NE(BacktraceTest::test_level_one_(1, 2, 3, 4, nullptr, nullptr), 0);
- return nullptr;
-}
-
-static void GetThreads(pid_t pid, std::vector<pid_t>* threads) {
- // Get the list of tasks.
- char task_path[128];
- snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid);
-
- std::unique_ptr<DIR, decltype(&closedir)> tasks_dir(opendir(task_path), closedir);
- ASSERT_TRUE(tasks_dir != nullptr);
- struct dirent* entry;
- while ((entry = readdir(tasks_dir.get())) != nullptr) {
- char* end;
- pid_t tid = strtoul(entry->d_name, &end, 10);
- if (*end == '\0') {
- threads->push_back(tid);
- }
- }
-}
-
-TEST_F(BacktraceTest, ptrace_threads) {
- pid_t pid;
- if ((pid = fork()) == 0) {
- for (size_t i = 0; i < NUM_PTRACE_THREADS; i++) {
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
- pthread_t thread;
- ASSERT_TRUE(pthread_create(&thread, &attr, PtraceThreadLevelRun, nullptr) == 0);
- }
- ASSERT_NE(test_level_one_(1, 2, 3, 4, nullptr, nullptr), 0);
- _exit(1);
- }
-
- // Check to see that all of the threads are running before unwinding.
- std::vector<pid_t> threads;
- uint64_t start = NanoTime();
- do {
- usleep(US_PER_MSEC);
- threads.clear();
- GetThreads(pid, &threads);
- } while ((threads.size() != NUM_PTRACE_THREADS + 1) &&
- ((NanoTime() - start) <= 5 * NS_PER_SEC));
- ASSERT_EQ(threads.size(), static_cast<size_t>(NUM_PTRACE_THREADS + 1));
-
- ASSERT_TRUE(ptrace(PTRACE_ATTACH, pid, 0, 0) == 0);
- WaitForStop(pid);
- for (std::vector<int>::const_iterator it = threads.begin(); it != threads.end(); ++it) {
- // Skip the current forked process, we only care about the threads.
- if (pid == *it) {
- continue;
- }
- VerifyProcTest(pid, *it, ReadyLevelBacktrace, VerifyLevelDump, Backtrace::Create,
- BacktraceMap::Create);
- }
-
- FinishRemoteProcess(pid);
-}
-
-void VerifyLevelThread(void*) {
- std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), android::base::GetThreadId()));
- ASSERT_TRUE(backtrace.get() != nullptr);
- ASSERT_TRUE(backtrace->Unwind(0));
- VERIFY_NO_ERROR(backtrace->GetError().error_code);
-
- VerifyLevelDump(backtrace.get());
-}
-
-TEST_F(BacktraceTest, thread_current_level) {
- ASSERT_NE(test_level_one_(1, 2, 3, 4, VerifyLevelThread, nullptr), 0);
-}
-
-static void VerifyMaxThread(void*) {
- std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), android::base::GetThreadId()));
- ASSERT_TRUE(backtrace.get() != nullptr);
- ASSERT_TRUE(backtrace->Unwind(0));
- ASSERT_EQ(BACKTRACE_UNWIND_ERROR_EXCEED_MAX_FRAMES_LIMIT, backtrace->GetError().error_code);
-
- VerifyMaxDump(backtrace.get());
-}
-
-TEST_F(BacktraceTest, thread_current_max) {
- ASSERT_NE(test_recursive_call_(MAX_BACKTRACE_FRAMES + 10, VerifyMaxThread, nullptr), 0);
-}
-
-static void* ThreadLevelRun(void* data) {
- thread_t* thread = reinterpret_cast<thread_t*>(data);
-
- thread->tid = android::base::GetThreadId();
- EXPECT_NE(BacktraceTest::test_level_one_(1, 2, 3, 4, ThreadSetState, data), 0);
- return nullptr;
-}
-
-TEST_F(BacktraceTest, thread_level_trace) {
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
- thread_t thread_data = { 0, 0, 0, nullptr };
- pthread_t thread;
- ASSERT_TRUE(pthread_create(&thread, &attr, ThreadLevelRun, &thread_data) == 0);
-
- // Wait up to 2 seconds for the tid to be set.
- ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2));
-
- // Make sure that the thread signal used is not visible when compiled for
- // the target.
-#if !defined(__GLIBC__)
- ASSERT_LT(THREAD_SIGNAL, SIGRTMIN);
-#endif
-
- // Save the current signal action and make sure it is restored afterwards.
- struct sigaction cur_action;
- ASSERT_TRUE(sigaction(THREAD_SIGNAL, nullptr, &cur_action) == 0);
-
- std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid));
- ASSERT_TRUE(backtrace.get() != nullptr);
- ASSERT_TRUE(backtrace->Unwind(0));
- VERIFY_NO_ERROR(backtrace->GetError().error_code);
-
- VerifyLevelDump(backtrace.get());
-
- // Tell the thread to exit its infinite loop.
- android_atomic_acquire_store(0, &thread_data.state);
-
- // Verify that the old action was restored.
- struct sigaction new_action;
- ASSERT_TRUE(sigaction(THREAD_SIGNAL, nullptr, &new_action) == 0);
- EXPECT_EQ(cur_action.sa_sigaction, new_action.sa_sigaction);
- // The SA_RESTORER flag gets set behind our back, so a direct comparison
- // doesn't work unless we mask the value off. Mips doesn't have this
- // flag, so skip this on that platform.
-#if defined(SA_RESTORER)
- cur_action.sa_flags &= ~SA_RESTORER;
- new_action.sa_flags &= ~SA_RESTORER;
-#elif defined(__GLIBC__)
- // Our host compiler doesn't appear to define this flag for some reason.
- cur_action.sa_flags &= ~0x04000000;
- new_action.sa_flags &= ~0x04000000;
-#endif
- EXPECT_EQ(cur_action.sa_flags, new_action.sa_flags);
-}
-
-TEST_F(BacktraceTest, thread_ignore_frames) {
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
- thread_t thread_data = { 0, 0, 0, nullptr };
- pthread_t thread;
- ASSERT_TRUE(pthread_create(&thread, &attr, ThreadLevelRun, &thread_data) == 0);
-
- // Wait up to 2 seconds for the tid to be set.
- ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2));
-
- std::unique_ptr<Backtrace> all(Backtrace::Create(getpid(), thread_data.tid));
- ASSERT_TRUE(all.get() != nullptr);
- ASSERT_TRUE(all->Unwind(0));
- VERIFY_NO_ERROR(all->GetError().error_code);
-
- std::unique_ptr<Backtrace> ign1(Backtrace::Create(getpid(), thread_data.tid));
- ASSERT_TRUE(ign1.get() != nullptr);
- ASSERT_TRUE(ign1->Unwind(1));
- VERIFY_NO_ERROR(ign1->GetError().error_code);
-
- std::unique_ptr<Backtrace> ign2(Backtrace::Create(getpid(), thread_data.tid));
- ASSERT_TRUE(ign2.get() != nullptr);
- ASSERT_TRUE(ign2->Unwind(2));
- VERIFY_NO_ERROR(ign2->GetError().error_code);
-
- VerifyIgnoreFrames(all.get(), ign1.get(), ign2.get(), nullptr);
-
- // Tell the thread to exit its infinite loop.
- android_atomic_acquire_store(0, &thread_data.state);
-}
-
-static void* ThreadMaxRun(void* data) {
- thread_t* thread = reinterpret_cast<thread_t*>(data);
-
- thread->tid = android::base::GetThreadId();
- EXPECT_NE(BacktraceTest::test_recursive_call_(MAX_BACKTRACE_FRAMES + 10, ThreadSetState, data),
- 0);
- return nullptr;
-}
-
-TEST_F(BacktraceTest, thread_max_trace) {
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
- thread_t thread_data = { 0, 0, 0, nullptr };
- pthread_t thread;
- ASSERT_TRUE(pthread_create(&thread, &attr, ThreadMaxRun, &thread_data) == 0);
-
- // Wait for the tid to be set.
- ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2));
-
- std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid));
- ASSERT_TRUE(backtrace.get() != nullptr);
- ASSERT_TRUE(backtrace->Unwind(0));
- ASSERT_EQ(BACKTRACE_UNWIND_ERROR_EXCEED_MAX_FRAMES_LIMIT, backtrace->GetError().error_code);
-
- VerifyMaxDump(backtrace.get());
-
- // Tell the thread to exit its infinite loop.
- android_atomic_acquire_store(0, &thread_data.state);
-}
-
-static void* ThreadDump(void* data) {
- dump_thread_t* dump = reinterpret_cast<dump_thread_t*>(data);
- while (true) {
- if (android_atomic_acquire_load(dump->now)) {
- break;
- }
- }
-
- // The status of the actual unwind will be checked elsewhere.
- dump->backtrace = Backtrace::Create(getpid(), dump->thread.tid, dump->map);
- dump->backtrace->Unwind(0);
-
- android_atomic_acquire_store(1, &dump->done);
-
- return nullptr;
-}
-
-static void MultipleThreadDumpTest(bool share_map) {
- // Dump NUM_THREADS simultaneously using the same map.
- std::vector<thread_t> runners(NUM_THREADS);
- std::vector<dump_thread_t> dumpers(NUM_THREADS);
-
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- for (size_t i = 0; i < NUM_THREADS; i++) {
- // Launch the runners, they will spin in hard loops doing nothing.
- runners[i].tid = 0;
- runners[i].state = 0;
- ASSERT_TRUE(pthread_create(&runners[i].threadId, &attr, ThreadMaxRun, &runners[i]) == 0);
- }
-
- // Wait for tids to be set.
- for (std::vector<thread_t>::iterator it = runners.begin(); it != runners.end(); ++it) {
- ASSERT_TRUE(WaitForNonZero(&it->state, 30));
- }
-
- // Start all of the dumpers at once, they will spin until they are signalled
- // to begin their dump run.
- std::unique_ptr<BacktraceMap> map;
- if (share_map) {
- map.reset(BacktraceMap::Create(getpid()));
- }
- int32_t dump_now = 0;
- for (size_t i = 0; i < NUM_THREADS; i++) {
- dumpers[i].thread.tid = runners[i].tid;
- dumpers[i].thread.state = 0;
- dumpers[i].done = 0;
- dumpers[i].now = &dump_now;
- dumpers[i].map = map.get();
-
- ASSERT_TRUE(pthread_create(&dumpers[i].thread.threadId, &attr, ThreadDump, &dumpers[i]) == 0);
- }
-
- // Start all of the dumpers going at once.
- android_atomic_acquire_store(1, &dump_now);
-
- for (size_t i = 0; i < NUM_THREADS; i++) {
- ASSERT_TRUE(WaitForNonZero(&dumpers[i].done, 30));
-
- // Tell the runner thread to exit its infinite loop.
- android_atomic_acquire_store(0, &runners[i].state);
-
- ASSERT_TRUE(dumpers[i].backtrace != nullptr);
- VerifyMaxDump(dumpers[i].backtrace);
-
- delete dumpers[i].backtrace;
- dumpers[i].backtrace = nullptr;
- }
-}
-
-TEST_F(BacktraceTest, thread_multiple_dump) {
- MultipleThreadDumpTest(false);
-}
-
-TEST_F(BacktraceTest, thread_multiple_dump_same_map) {
- MultipleThreadDumpTest(true);
-}
-
-// This test is for UnwindMaps that should share the same map cursor when
-// multiple maps are created for the current process at the same time.
-TEST_F(BacktraceTest, simultaneous_maps) {
- BacktraceMap* map1 = BacktraceMap::Create(getpid());
- BacktraceMap* map2 = BacktraceMap::Create(getpid());
- BacktraceMap* map3 = BacktraceMap::Create(getpid());
-
- Backtrace* back1 = Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD, map1);
- ASSERT_TRUE(back1 != nullptr);
- EXPECT_TRUE(back1->Unwind(0));
- VERIFY_NO_ERROR(back1->GetError().error_code);
- delete back1;
- delete map1;
-
- Backtrace* back2 = Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD, map2);
- ASSERT_TRUE(back2 != nullptr);
- EXPECT_TRUE(back2->Unwind(0));
- VERIFY_NO_ERROR(back2->GetError().error_code);
- delete back2;
- delete map2;
-
- Backtrace* back3 = Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD, map3);
- ASSERT_TRUE(back3 != nullptr);
- EXPECT_TRUE(back3->Unwind(0));
- VERIFY_NO_ERROR(back3->GetError().error_code);
- delete back3;
- delete map3;
-}
-
-TEST_F(BacktraceTest, fillin_erases) {
- BacktraceMap* back_map = BacktraceMap::Create(getpid());
-
- backtrace_map_t map;
-
- map.start = 1;
- map.end = 3;
- map.flags = 1;
- map.name = "Initialized";
- back_map->FillIn(0, &map);
- delete back_map;
-
- ASSERT_FALSE(BacktraceMap::IsValid(map));
- ASSERT_EQ(static_cast<uint64_t>(0), map.start);
- ASSERT_EQ(static_cast<uint64_t>(0), map.end);
- ASSERT_EQ(0, map.flags);
- ASSERT_EQ("", map.name);
-}
-
-TEST_F(BacktraceTest, format_test) {
- std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD));
- ASSERT_TRUE(backtrace.get() != nullptr);
-
- backtrace_frame_data_t frame;
- frame.num = 1;
- frame.pc = 2;
- frame.rel_pc = 2;
- frame.sp = 0;
- frame.stack_size = 0;
- frame.func_offset = 0;
-
- // Check no map set.
- frame.num = 1;
-#if defined(__LP64__)
- EXPECT_EQ("#01 pc 0000000000000002 <unknown>",
-#else
- EXPECT_EQ("#01 pc 00000002 <unknown>",
-#endif
- backtrace->FormatFrameData(&frame));
-
- // Check map name empty, but exists.
- frame.pc = 0xb0020;
- frame.rel_pc = 0x20;
- frame.map.start = 0xb0000;
- frame.map.end = 0xbffff;
- frame.map.load_bias = 0;
-#if defined(__LP64__)
- EXPECT_EQ("#01 pc 0000000000000020 <anonymous:00000000000b0000>",
-#else
- EXPECT_EQ("#01 pc 00000020 <anonymous:000b0000>",
-#endif
- backtrace->FormatFrameData(&frame));
-
- // Check map name begins with a [.
- frame.pc = 0xc0020;
- frame.map.start = 0xc0000;
- frame.map.end = 0xcffff;
- frame.map.load_bias = 0;
- frame.map.name = "[anon:thread signal stack]";
-#if defined(__LP64__)
- EXPECT_EQ("#01 pc 0000000000000020 [anon:thread signal stack:00000000000c0000]",
-#else
- EXPECT_EQ("#01 pc 00000020 [anon:thread signal stack:000c0000]",
-#endif
- backtrace->FormatFrameData(&frame));
-
- // Check relative pc is set and map name is set.
- frame.pc = 0x12345679;
- frame.rel_pc = 0x12345678;
- frame.map.name = "MapFake";
- frame.map.start = 1;
- frame.map.end = 1;
-#if defined(__LP64__)
- EXPECT_EQ("#01 pc 0000000012345678 MapFake",
-#else
- EXPECT_EQ("#01 pc 12345678 MapFake",
-#endif
- backtrace->FormatFrameData(&frame));
-
- // Check func_name is set, but no func offset.
- frame.func_name = "ProcFake";
-#if defined(__LP64__)
- EXPECT_EQ("#01 pc 0000000012345678 MapFake (ProcFake)",
-#else
- EXPECT_EQ("#01 pc 12345678 MapFake (ProcFake)",
-#endif
- backtrace->FormatFrameData(&frame));
-
- // Check func_name is set, and func offset is non-zero.
- frame.func_offset = 645;
-#if defined(__LP64__)
- EXPECT_EQ("#01 pc 0000000012345678 MapFake (ProcFake+645)",
-#else
- EXPECT_EQ("#01 pc 12345678 MapFake (ProcFake+645)",
-#endif
- backtrace->FormatFrameData(&frame));
-
- // Check func_name is set, func offset is non-zero, and load_bias is non-zero.
- frame.rel_pc = 0x123456dc;
- frame.func_offset = 645;
- frame.map.load_bias = 100;
-#if defined(__LP64__)
- EXPECT_EQ("#01 pc 00000000123456dc MapFake (ProcFake+645)",
-#else
- EXPECT_EQ("#01 pc 123456dc MapFake (ProcFake+645)",
-#endif
- backtrace->FormatFrameData(&frame));
-
- // Check a non-zero map offset.
- frame.map.offset = 0x1000;
-#if defined(__LP64__)
- EXPECT_EQ("#01 pc 00000000123456dc MapFake (offset 0x1000) (ProcFake+645)",
-#else
- EXPECT_EQ("#01 pc 123456dc MapFake (offset 0x1000) (ProcFake+645)",
-#endif
- backtrace->FormatFrameData(&frame));
-}
-
-struct map_test_t {
- uint64_t start;
- uint64_t end;
-};
-
-static bool map_sort(map_test_t i, map_test_t j) { return i.start < j.start; }
-
-static std::string GetTestMapsAsString(const std::vector<map_test_t>& maps) {
- if (maps.size() == 0) {
- return "No test map entries\n";
- }
- std::string map_txt;
- for (auto map : maps) {
- map_txt += android::base::StringPrintf("%" PRIx64 "-%" PRIx64 "\n", map.start, map.end);
- }
- return map_txt;
-}
-
-static std::string GetMapsAsString(BacktraceMap* maps) {
- if (maps->size() == 0) {
- return "No map entries\n";
- }
- std::string map_txt;
- for (const backtrace_map_t* map : *maps) {
- map_txt += android::base::StringPrintf(
- "%" PRIx64 "-%" PRIx64 " flags: 0x%x offset: 0x%" PRIx64 " load_bias: 0x%" PRIx64,
- map->start, map->end, map->flags, map->offset, map->load_bias);
- if (!map->name.empty()) {
- map_txt += ' ' + map->name;
- }
- map_txt += '\n';
- }
- return map_txt;
-}
-
-static void VerifyMap(pid_t pid) {
- char buffer[4096];
- snprintf(buffer, sizeof(buffer), "/proc/%d/maps", pid);
-
- FILE* map_file = fopen(buffer, "r");
- ASSERT_TRUE(map_file != nullptr);
- std::vector<map_test_t> test_maps;
- while (fgets(buffer, sizeof(buffer), map_file)) {
- map_test_t map;
- ASSERT_EQ(2, sscanf(buffer, "%" SCNx64 "-%" SCNx64 " ", &map.start, &map.end));
- test_maps.push_back(map);
- }
- fclose(map_file);
- std::sort(test_maps.begin(), test_maps.end(), map_sort);
-
- std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(pid));
-
- // Basic test that verifies that the map is in the expected order.
- auto test_it = test_maps.begin();
- for (auto it = map->begin(); it != map->end(); ++it) {
- ASSERT_TRUE(test_it != test_maps.end()) << "Mismatch in number of maps, expected test maps:\n"
- << GetTestMapsAsString(test_maps) << "Actual maps:\n"
- << GetMapsAsString(map.get());
- ASSERT_EQ(test_it->start, (*it)->start) << "Mismatch in map data, expected test maps:\n"
- << GetTestMapsAsString(test_maps) << "Actual maps:\n"
- << GetMapsAsString(map.get());
- ASSERT_EQ(test_it->end, (*it)->end) << "Mismatch maps in map data, expected test maps:\n"
- << GetTestMapsAsString(test_maps) << "Actual maps:\n"
- << GetMapsAsString(map.get());
- // Make sure the load bias get set to a value.
- ASSERT_NE(static_cast<uint64_t>(-1), (*it)->load_bias) << "Found uninitialized load_bias\n"
- << GetMapsAsString(map.get());
- ++test_it;
- }
- ASSERT_TRUE(test_it == test_maps.end());
-}
-
-TEST_F(BacktraceTest, verify_map_remote) {
- pid_t pid;
- CreateRemoteProcess(&pid);
-
- // The maps should match exactly since the forked process has been paused.
- VerifyMap(pid);
-
- FinishRemoteProcess(pid);
-}
-
-static void InitMemory(uint8_t* memory, size_t bytes) {
- for (size_t i = 0; i < bytes; i++) {
- memory[i] = i;
- if (memory[i] == '\0') {
- // Don't use '\0' in our data so we can verify that an overread doesn't
- // occur by using a '\0' as the character after the read data.
- memory[i] = 23;
- }
- }
-}
-
-static void* ThreadReadTest(void* data) {
- thread_t* thread_data = reinterpret_cast<thread_t*>(data);
-
- thread_data->tid = android::base::GetThreadId();
-
- // Create two map pages.
- // Mark the second page as not-readable.
- size_t pagesize = static_cast<size_t>(sysconf(_SC_PAGE_SIZE));
- uint8_t* memory;
- if (posix_memalign(reinterpret_cast<void**>(&memory), pagesize, 2 * pagesize) != 0) {
- return reinterpret_cast<void*>(-1);
- }
-
- if (mprotect(&memory[pagesize], pagesize, PROT_NONE) != 0) {
- return reinterpret_cast<void*>(-1);
- }
-
- // Set up a simple pattern in memory.
- InitMemory(memory, pagesize);
-
- thread_data->data = memory;
-
- // Tell the caller it's okay to start reading memory.
- android_atomic_acquire_store(1, &thread_data->state);
-
- // Loop waiting for the caller to finish reading the memory.
- while (thread_data->state) {
- }
-
- // Re-enable read-write on the page so that we don't crash if we try
- // and access data on this page when freeing the memory.
- if (mprotect(&memory[pagesize], pagesize, PROT_READ | PROT_WRITE) != 0) {
- return reinterpret_cast<void*>(-1);
- }
- free(memory);
-
- android_atomic_acquire_store(1, &thread_data->state);
-
- return nullptr;
-}
-
-static void RunReadTest(Backtrace* backtrace, uint64_t read_addr) {
- size_t pagesize = static_cast<size_t>(sysconf(_SC_PAGE_SIZE));
-
- // Create a page of data to use to do quick compares.
- uint8_t* expected = new uint8_t[pagesize];
- InitMemory(expected, pagesize);
-
- uint8_t* data = new uint8_t[2 * pagesize];
- // Verify that we can only read one page worth of data.
- size_t bytes_read = backtrace->Read(read_addr, data, 2 * pagesize);
- ASSERT_EQ(pagesize, bytes_read);
- ASSERT_TRUE(memcmp(data, expected, pagesize) == 0);
-
- // Verify unaligned reads.
- for (size_t i = 1; i < sizeof(word_t); i++) {
- bytes_read = backtrace->Read(read_addr + i, data, 2 * sizeof(word_t));
- ASSERT_EQ(2 * sizeof(word_t), bytes_read);
- ASSERT_TRUE(memcmp(data, &expected[i], 2 * sizeof(word_t)) == 0)
- << "Offset at " << i << " failed";
- }
-
- // Verify small unaligned reads.
- for (size_t i = 1; i < sizeof(word_t); i++) {
- for (size_t j = 1; j < sizeof(word_t); j++) {
- // Set one byte past what we expect to read, to guarantee we don't overread.
- data[j] = '\0';
- bytes_read = backtrace->Read(read_addr + i, data, j);
- ASSERT_EQ(j, bytes_read);
- ASSERT_TRUE(memcmp(data, &expected[i], j) == 0)
- << "Offset at " << i << " length " << j << " miscompared";
- ASSERT_EQ('\0', data[j])
- << "Offset at " << i << " length " << j << " wrote too much data";
- }
- }
- delete[] data;
- delete[] expected;
-}
-
-TEST_F(BacktraceTest, thread_read) {
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- pthread_t thread;
- thread_t thread_data = { 0, 0, 0, nullptr };
- ASSERT_TRUE(pthread_create(&thread, &attr, ThreadReadTest, &thread_data) == 0);
-
- ASSERT_TRUE(WaitForNonZero(&thread_data.state, 10));
-
- std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid));
- ASSERT_TRUE(backtrace.get() != nullptr);
-
- RunReadTest(backtrace.get(), reinterpret_cast<uint64_t>(thread_data.data));
-
- android_atomic_acquire_store(0, &thread_data.state);
-
- ASSERT_TRUE(WaitForNonZero(&thread_data.state, 10));
-}
-
-// The code requires these variables are the same size.
-volatile uint64_t g_ready = 0;
-volatile uint64_t g_addr = 0;
-static_assert(sizeof(g_ready) == sizeof(g_addr), "g_ready/g_addr must be same size");
-
-static void ForkedReadTest() {
- // Create two map pages.
- size_t pagesize = static_cast<size_t>(sysconf(_SC_PAGE_SIZE));
- uint8_t* memory;
- if (posix_memalign(reinterpret_cast<void**>(&memory), pagesize, 2 * pagesize) != 0) {
- perror("Failed to allocate memory\n");
- exit(1);
- }
-
- // Mark the second page as not-readable.
- if (mprotect(&memory[pagesize], pagesize, PROT_NONE) != 0) {
- perror("Failed to mprotect memory\n");
- exit(1);
- }
-
- // Set up a simple pattern in memory.
- InitMemory(memory, pagesize);
-
- g_addr = reinterpret_cast<uint64_t>(memory);
- g_ready = 1;
-
- while (1) {
- usleep(US_PER_MSEC);
- }
-}
-
-TEST_F(BacktraceTest, process_read) {
- g_ready = 0;
- pid_t pid;
- if ((pid = fork()) == 0) {
- ForkedReadTest();
- exit(0);
- }
- ASSERT_NE(-1, pid);
-
- bool test_executed = false;
- uint64_t start = NanoTime();
- while (1) {
- if (ptrace(PTRACE_ATTACH, pid, 0, 0) == 0) {
- WaitForStop(pid);
-
- std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, pid));
- ASSERT_TRUE(backtrace.get() != nullptr);
-
- uint64_t read_addr;
- size_t bytes_read = backtrace->Read(reinterpret_cast<uint64_t>(&g_ready),
- reinterpret_cast<uint8_t*>(&read_addr), sizeof(g_ready));
- ASSERT_EQ(sizeof(g_ready), bytes_read);
- if (read_addr) {
- // The forked process is ready to be read.
- bytes_read = backtrace->Read(reinterpret_cast<uint64_t>(&g_addr),
- reinterpret_cast<uint8_t*>(&read_addr), sizeof(g_addr));
- ASSERT_EQ(sizeof(g_addr), bytes_read);
-
- RunReadTest(backtrace.get(), read_addr);
-
- test_executed = true;
- break;
- }
- ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0);
- }
- if ((NanoTime() - start) > 5 * NS_PER_SEC) {
- break;
- }
- usleep(US_PER_MSEC);
- }
- kill(pid, SIGKILL);
- ASSERT_EQ(waitpid(pid, nullptr, 0), pid);
-
- ASSERT_TRUE(test_executed);
-}
-
-static void VerifyFunctionsFound(const std::vector<std::string>& found_functions) {
- // We expect to find these functions in libbacktrace_test. If we don't
- // find them, that's a bug in the memory read handling code in libunwind.
- std::list<std::string> expected_functions;
- expected_functions.push_back("test_recursive_call");
- expected_functions.push_back("test_level_one");
- expected_functions.push_back("test_level_two");
- expected_functions.push_back("test_level_three");
- expected_functions.push_back("test_level_four");
- for (const auto& found_function : found_functions) {
- for (const auto& expected_function : expected_functions) {
- if (found_function == expected_function) {
- expected_functions.remove(found_function);
- break;
- }
- }
- }
- ASSERT_TRUE(expected_functions.empty()) << "Not all functions found in shared library.";
-}
-
-static void CopySharedLibrary(const char* tmp_dir, std::string* tmp_so_name) {
- std::string test_lib(testing::internal::GetArgvs()[0]);
- auto const value = test_lib.find_last_of('/');
- if (value == std::string::npos) {
- test_lib = "../backtrace_test_libs/";
- } else {
- test_lib = test_lib.substr(0, value + 1) + "../backtrace_test_libs/";
- }
- test_lib += "libbacktrace_test.so";
-
- *tmp_so_name = std::string(tmp_dir) + "/libbacktrace_test.so";
- std::string cp_cmd = android::base::StringPrintf("cp %s %s", test_lib.c_str(), tmp_dir);
-
- // Copy the shared so to a tempory directory.
- ASSERT_EQ(0, system(cp_cmd.c_str()));
-}
-
-TEST_F(BacktraceTest, check_unreadable_elf_local) {
- TemporaryDir td;
- std::string tmp_so_name;
- ASSERT_NO_FATAL_FAILURE(CopySharedLibrary(td.path, &tmp_so_name));
-
- struct stat buf;
- ASSERT_TRUE(stat(tmp_so_name.c_str(), &buf) != -1);
- uint64_t map_size = buf.st_size;
-
- int fd = open(tmp_so_name.c_str(), O_RDONLY);
- ASSERT_TRUE(fd != -1);
-
- void* map = mmap(nullptr, map_size, PROT_READ | PROT_EXEC, MAP_PRIVATE, fd, 0);
- ASSERT_TRUE(map != MAP_FAILED);
- close(fd);
- ASSERT_TRUE(unlink(tmp_so_name.c_str()) != -1);
-
- std::vector<std::string> found_functions;
- std::unique_ptr<Backtrace> backtrace(Backtrace::Create(BACKTRACE_CURRENT_PROCESS,
- BACKTRACE_CURRENT_THREAD));
- ASSERT_TRUE(backtrace.get() != nullptr);
-
- // Needed before GetFunctionName will work.
- backtrace->Unwind(0);
-
- // Loop through the entire map, and get every function we can find.
- map_size += reinterpret_cast<uint64_t>(map);
- std::string last_func;
- for (uint64_t read_addr = reinterpret_cast<uint64_t>(map); read_addr < map_size; read_addr += 4) {
- uint64_t offset;
- std::string func_name = backtrace->GetFunctionName(read_addr, &offset);
- if (!func_name.empty() && last_func != func_name) {
- found_functions.push_back(func_name);
- }
- last_func = func_name;
- }
-
- ASSERT_TRUE(munmap(map, map_size - reinterpret_cast<uint64_t>(map)) == 0);
-
- VerifyFunctionsFound(found_functions);
-}
-
-TEST_F(BacktraceTest, check_unreadable_elf_remote) {
- TemporaryDir td;
- std::string tmp_so_name;
- ASSERT_NO_FATAL_FAILURE(CopySharedLibrary(td.path, &tmp_so_name));
-
- g_ready = 0;
-
- struct stat buf;
- ASSERT_TRUE(stat(tmp_so_name.c_str(), &buf) != -1);
- uint64_t map_size = buf.st_size;
-
- pid_t pid;
- if ((pid = fork()) == 0) {
- int fd = open(tmp_so_name.c_str(), O_RDONLY);
- if (fd == -1) {
- fprintf(stderr, "Failed to open file %s: %s\n", tmp_so_name.c_str(), strerror(errno));
- unlink(tmp_so_name.c_str());
- exit(0);
- }
-
- void* map = mmap(nullptr, map_size, PROT_READ | PROT_EXEC, MAP_PRIVATE, fd, 0);
- if (map == MAP_FAILED) {
- fprintf(stderr, "Failed to map in memory: %s\n", strerror(errno));
- unlink(tmp_so_name.c_str());
- exit(0);
- }
- close(fd);
- if (unlink(tmp_so_name.c_str()) == -1) {
- fprintf(stderr, "Failed to unlink: %s\n", strerror(errno));
- exit(0);
- }
-
- g_addr = reinterpret_cast<uint64_t>(map);
- g_ready = 1;
- while (true) {
- usleep(US_PER_MSEC);
- }
- exit(0);
- }
- ASSERT_TRUE(pid > 0);
-
- std::vector<std::string> found_functions;
- uint64_t start = NanoTime();
- while (true) {
- ASSERT_TRUE(ptrace(PTRACE_ATTACH, pid, 0, 0) == 0);
-
- // Wait for the process to get to a stopping point.
- WaitForStop(pid);
-
- std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, BACKTRACE_CURRENT_THREAD));
- ASSERT_TRUE(backtrace.get() != nullptr);
-
- uint64_t read_addr;
- ASSERT_EQ(sizeof(g_ready),
- backtrace->Read(reinterpret_cast<uint64_t>(&g_ready),
- reinterpret_cast<uint8_t*>(&read_addr), sizeof(g_ready)));
- if (read_addr) {
- ASSERT_EQ(sizeof(g_addr),
- backtrace->Read(reinterpret_cast<uint64_t>(&g_addr),
- reinterpret_cast<uint8_t*>(&read_addr), sizeof(uint64_t)));
-
- // Needed before GetFunctionName will work.
- backtrace->Unwind(0);
-
- // Loop through the entire map, and get every function we can find.
- map_size += read_addr;
- std::string last_func;
- for (; read_addr < map_size; read_addr += 4) {
- uint64_t offset;
- std::string func_name = backtrace->GetFunctionName(read_addr, &offset);
- if (!func_name.empty() && last_func != func_name) {
- found_functions.push_back(func_name);
- }
- last_func = func_name;
- }
- break;
- }
- ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0);
-
- if ((NanoTime() - start) > 5 * NS_PER_SEC) {
- break;
- }
- usleep(US_PER_MSEC);
- }
-
- kill(pid, SIGKILL);
- ASSERT_EQ(waitpid(pid, nullptr, 0), pid);
-
- VerifyFunctionsFound(found_functions);
-}
-
-static bool FindFuncFrameInBacktrace(Backtrace* backtrace, uint64_t test_func, size_t* frame_num) {
- backtrace_map_t map;
- backtrace->FillInMap(test_func, &map);
- if (!BacktraceMap::IsValid(map)) {
- return false;
- }
-
- // Loop through the frames, and find the one that is in the map.
- *frame_num = 0;
- for (Backtrace::const_iterator it = backtrace->begin(); it != backtrace->end(); ++it) {
- if (BacktraceMap::IsValid(it->map) && map.start == it->map.start &&
- it->pc >= test_func) {
- *frame_num = it->num;
- return true;
- }
- }
- return false;
-}
-
-static void VerifyUnreadableElfFrame(Backtrace* backtrace, uint64_t test_func, size_t frame_num) {
- ASSERT_LT(backtrace->NumFrames(), static_cast<size_t>(MAX_BACKTRACE_FRAMES))
- << DumpFrames(backtrace);
-
- ASSERT_TRUE(frame_num != 0) << DumpFrames(backtrace);
- // Make sure that there is at least one more frame above the test func call.
- ASSERT_LT(frame_num, backtrace->NumFrames()) << DumpFrames(backtrace);
-
- uint64_t diff = backtrace->GetFrame(frame_num)->pc - test_func;
- ASSERT_LT(diff, 200U) << DumpFrames(backtrace);
-}
-
-static void VerifyUnreadableElfBacktrace(void* func) {
- std::unique_ptr<Backtrace> backtrace(Backtrace::Create(BACKTRACE_CURRENT_PROCESS,
- BACKTRACE_CURRENT_THREAD));
- ASSERT_TRUE(backtrace.get() != nullptr);
- ASSERT_TRUE(backtrace->Unwind(0));
- VERIFY_NO_ERROR(backtrace->GetError().error_code);
-
- size_t frame_num;
- uint64_t test_func = reinterpret_cast<uint64_t>(func);
- ASSERT_TRUE(FindFuncFrameInBacktrace(backtrace.get(), test_func, &frame_num))
- << DumpFrames(backtrace.get());
-
- VerifyUnreadableElfFrame(backtrace.get(), test_func, frame_num);
-}
-
-typedef int (*test_func_t)(int, int, int, int, void (*)(void*), void*);
-
-TEST_F(BacktraceTest, unwind_through_unreadable_elf_local) {
- TemporaryDir td;
- std::string tmp_so_name;
- ASSERT_NO_FATAL_FAILURE(CopySharedLibrary(td.path, &tmp_so_name));
-
- void* lib_handle = dlopen(tmp_so_name.c_str(), RTLD_NOW);
- ASSERT_TRUE(lib_handle != nullptr);
- ASSERT_TRUE(unlink(tmp_so_name.c_str()) != -1);
-
- test_func_t test_func;
- test_func = reinterpret_cast<test_func_t>(dlsym(lib_handle, "test_level_one"));
- ASSERT_TRUE(test_func != nullptr);
-
- ASSERT_NE(test_func(1, 2, 3, 4, VerifyUnreadableElfBacktrace, reinterpret_cast<void*>(test_func)),
- 0);
-}
-
-TEST_F(BacktraceTest, unwind_through_unreadable_elf_remote) {
- TemporaryDir td;
- std::string tmp_so_name;
- ASSERT_NO_FATAL_FAILURE(CopySharedLibrary(td.path, &tmp_so_name));
-
- void* lib_handle = dlopen(tmp_so_name.c_str(), RTLD_NOW);
- ASSERT_TRUE(lib_handle != nullptr);
- ASSERT_TRUE(unlink(tmp_so_name.c_str()) != -1);
-
- test_func_t test_func;
- test_func = reinterpret_cast<test_func_t>(dlsym(lib_handle, "test_level_one"));
- ASSERT_TRUE(test_func != nullptr);
-
- pid_t pid;
- if ((pid = fork()) == 0) {
- test_func(1, 2, 3, 4, 0, 0);
- exit(0);
- }
- ASSERT_TRUE(pid > 0);
-
- uint64_t start = NanoTime();
- bool done = false;
- while (!done) {
- ASSERT_TRUE(ptrace(PTRACE_ATTACH, pid, 0, 0) == 0);
-
- // Wait for the process to get to a stopping point.
- WaitForStop(pid);
-
- std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, BACKTRACE_CURRENT_THREAD));
- ASSERT_TRUE(backtrace.get() != nullptr);
- ASSERT_TRUE(backtrace->Unwind(0));
- VERIFY_NO_ERROR(backtrace->GetError().error_code);
-
- size_t frame_num;
- if (FindFuncFrameInBacktrace(backtrace.get(), reinterpret_cast<uint64_t>(test_func),
- &frame_num) &&
- frame_num != 0) {
- VerifyUnreadableElfFrame(backtrace.get(), reinterpret_cast<uint64_t>(test_func), frame_num);
- done = true;
- }
-
- ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0);
-
- if ((NanoTime() - start) > 5 * NS_PER_SEC) {
- break;
- }
- usleep(US_PER_MSEC);
- }
-
- kill(pid, SIGKILL);
- ASSERT_EQ(waitpid(pid, nullptr, 0), pid);
-
- ASSERT_TRUE(done) << "Test function never found in unwind.";
-}
-
-TEST_F(BacktraceTest, unwind_thread_doesnt_exist) {
- std::unique_ptr<Backtrace> backtrace(
- Backtrace::Create(BACKTRACE_CURRENT_PROCESS, 99999999));
- ASSERT_TRUE(backtrace.get() != nullptr);
- ASSERT_FALSE(backtrace->Unwind(0));
- ASSERT_EQ(BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST, backtrace->GetError().error_code);
-}
-
-TEST_F(BacktraceTest, local_get_function_name_before_unwind) {
- std::unique_ptr<Backtrace> backtrace(
- Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
- ASSERT_TRUE(backtrace.get() != nullptr);
-
- // Verify that trying to get a function name before doing an unwind works.
- uint64_t cur_func_offset = reinterpret_cast<uint64_t>(test_level_one_) + 1;
- uint64_t offset;
- ASSERT_NE(std::string(""), backtrace->GetFunctionName(cur_func_offset, &offset));
-}
-
-TEST_F(BacktraceTest, remote_get_function_name_before_unwind) {
- pid_t pid;
- CreateRemoteProcess(&pid);
-
- // Now create an unwind object.
- std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, pid));
-
- // Verify that trying to get a function name before doing an unwind works.
- uint64_t cur_func_offset = reinterpret_cast<uint64_t>(test_level_one_) + 1;
- uint64_t offset;
- ASSERT_NE(std::string(""), backtrace->GetFunctionName(cur_func_offset, &offset));
-
- FinishRemoteProcess(pid);
-}
-
-static void SetUcontextSp(uint64_t sp, ucontext_t* ucontext) {
-#if defined(__arm__)
- ucontext->uc_mcontext.arm_sp = sp;
-#elif defined(__aarch64__)
- ucontext->uc_mcontext.sp = sp;
-#elif defined(__i386__)
- ucontext->uc_mcontext.gregs[REG_ESP] = sp;
-#elif defined(__x86_64__)
- ucontext->uc_mcontext.gregs[REG_RSP] = sp;
-#else
- UNUSED(sp);
- UNUSED(ucontext);
- ASSERT_TRUE(false) << "Unsupported architecture";
-#endif
-}
-
-static void SetUcontextPc(uint64_t pc, ucontext_t* ucontext) {
-#if defined(__arm__)
- ucontext->uc_mcontext.arm_pc = pc;
-#elif defined(__aarch64__)
- ucontext->uc_mcontext.pc = pc;
-#elif defined(__i386__)
- ucontext->uc_mcontext.gregs[REG_EIP] = pc;
-#elif defined(__x86_64__)
- ucontext->uc_mcontext.gregs[REG_RIP] = pc;
-#else
- UNUSED(pc);
- UNUSED(ucontext);
- ASSERT_TRUE(false) << "Unsupported architecture";
-#endif
-}
-
-static void SetUcontextLr(uint64_t lr, ucontext_t* ucontext) {
-#if defined(__arm__)
- ucontext->uc_mcontext.arm_lr = lr;
-#elif defined(__aarch64__)
- ucontext->uc_mcontext.regs[30] = lr;
-#elif defined(__i386__)
- // The lr is on the stack.
- ASSERT_TRUE(lr != 0);
- ASSERT_TRUE(ucontext != nullptr);
-#elif defined(__x86_64__)
- // The lr is on the stack.
- ASSERT_TRUE(lr != 0);
- ASSERT_TRUE(ucontext != nullptr);
-#else
- UNUSED(lr);
- UNUSED(ucontext);
- ASSERT_TRUE(false) << "Unsupported architecture";
-#endif
-}
-
-static constexpr size_t DEVICE_MAP_SIZE = 1024;
-
-static void SetupDeviceMap(void** device_map) {
- // Make sure that anything in a device map will result in fails
- // to read.
- android::base::unique_fd device_fd(open("/dev/zero", O_RDONLY | O_CLOEXEC));
-
- *device_map = mmap(nullptr, 1024, PROT_READ, MAP_PRIVATE, device_fd, 0);
- ASSERT_TRUE(*device_map != MAP_FAILED);
-
- // Make sure the map is readable.
- ASSERT_EQ(0, reinterpret_cast<int*>(*device_map)[0]);
-}
-
-static void UnwindFromDevice(Backtrace* backtrace, void* device_map) {
- uint64_t device_map_uint = reinterpret_cast<uint64_t>(device_map);
-
- backtrace_map_t map;
- backtrace->FillInMap(device_map_uint, &map);
- // Verify the flag is set.
- ASSERT_EQ(PROT_DEVICE_MAP, map.flags & PROT_DEVICE_MAP);
-
- // Quick basic checks of functionality.
- uint64_t offset;
- ASSERT_EQ(std::string(""), backtrace->GetFunctionName(device_map_uint, &offset));
- ASSERT_EQ(std::string(""), backtrace->GetFunctionName(device_map_uint, &offset, &map));
- ASSERT_EQ(std::string(""), backtrace->GetFunctionName(0, &offset));
-
- uint64_t cur_func_offset = reinterpret_cast<uint64_t>(BacktraceTest::test_level_one_) + 1;
- // Now verify the device map flag actually causes the function name to be empty.
- backtrace->FillInMap(cur_func_offset, &map);
- ASSERT_TRUE((map.flags & PROT_DEVICE_MAP) == 0);
- ASSERT_NE(std::string(""), backtrace->GetFunctionName(cur_func_offset, &offset, &map));
- map.flags |= PROT_DEVICE_MAP;
- ASSERT_EQ(std::string(""), backtrace->GetFunctionName(cur_func_offset, &offset, &map));
-
- ucontext_t ucontext;
-
- // Create a context that has the pc in the device map, but the sp
- // in a non-device map.
- memset(&ucontext, 0, sizeof(ucontext));
- SetUcontextSp(reinterpret_cast<uint64_t>(&ucontext), &ucontext);
- SetUcontextPc(device_map_uint, &ucontext);
- SetUcontextLr(cur_func_offset, &ucontext);
-
- ASSERT_TRUE(backtrace->Unwind(0, &ucontext));
-
- // The buffer should only be a single element.
- ASSERT_EQ(1U, backtrace->NumFrames());
- const backtrace_frame_data_t* frame = backtrace->GetFrame(0);
- ASSERT_EQ(device_map_uint, frame->pc);
- ASSERT_EQ(reinterpret_cast<uint64_t>(&ucontext), frame->sp);
-
- // Check what happens when skipping the first frame.
- ASSERT_TRUE(backtrace->Unwind(1, &ucontext));
- ASSERT_EQ(0U, backtrace->NumFrames());
-
- // Create a context that has the sp in the device map, but the pc
- // in a non-device map.
- memset(&ucontext, 0, sizeof(ucontext));
- SetUcontextSp(device_map_uint, &ucontext);
- SetUcontextPc(cur_func_offset, &ucontext);
- SetUcontextLr(cur_func_offset, &ucontext);
-
- ASSERT_TRUE(backtrace->Unwind(0, &ucontext));
-
- // The buffer should only be a single element.
- ASSERT_EQ(1U, backtrace->NumFrames());
- frame = backtrace->GetFrame(0);
- ASSERT_EQ(cur_func_offset, frame->pc);
- ASSERT_EQ(device_map_uint, frame->sp);
-
- // Check what happens when skipping the first frame.
- ASSERT_TRUE(backtrace->Unwind(1, &ucontext));
- ASSERT_EQ(0U, backtrace->NumFrames());
-}
-
-TEST_F(BacktraceTest, unwind_disallow_device_map_local) {
- void* device_map;
- SetupDeviceMap(&device_map);
-
- // Now create an unwind object.
- std::unique_ptr<Backtrace> backtrace(
- Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
- ASSERT_TRUE(backtrace);
-
- UnwindFromDevice(backtrace.get(), device_map);
-
- munmap(device_map, DEVICE_MAP_SIZE);
-}
-
-TEST_F(BacktraceTest, unwind_disallow_device_map_remote) {
- void* device_map;
- SetupDeviceMap(&device_map);
-
- // Fork a process to do a remote backtrace.
- pid_t pid;
- CreateRemoteProcess(&pid);
-
- // Now create an unwind object.
- std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, pid));
-
- UnwindFromDevice(backtrace.get(), device_map);
-
- FinishRemoteProcess(pid);
-
- munmap(device_map, DEVICE_MAP_SIZE);
-}
-
-class ScopedSignalHandler {
- public:
- ScopedSignalHandler(int signal_number, void (*handler)(int)) : signal_number_(signal_number) {
- memset(&action_, 0, sizeof(action_));
- action_.sa_handler = handler;
- sigaction(signal_number_, &action_, &old_action_);
- }
-
- ScopedSignalHandler(int signal_number, void (*action)(int, siginfo_t*, void*))
- : signal_number_(signal_number) {
- memset(&action_, 0, sizeof(action_));
- action_.sa_flags = SA_SIGINFO;
- action_.sa_sigaction = action;
- sigaction(signal_number_, &action_, &old_action_);
- }
-
- ~ScopedSignalHandler() { sigaction(signal_number_, &old_action_, nullptr); }
-
- private:
- struct sigaction action_;
- struct sigaction old_action_;
- const int signal_number_;
-};
-
-static void SetValueAndLoop(void* data) {
- volatile int* value = reinterpret_cast<volatile int*>(data);
-
- *value = 1;
- for (volatile int i = 0;; i++)
- ;
-}
-
-static void UnwindThroughSignal(bool use_action, create_func_t create_func,
- map_create_func_t map_create_func) {
- volatile int value = 0;
- pid_t pid;
- if ((pid = fork()) == 0) {
- if (use_action) {
- ScopedSignalHandler ssh(SIGUSR1, BacktraceTest::test_signal_action_);
-
- BacktraceTest::test_level_one_(1, 2, 3, 4, SetValueAndLoop, const_cast<int*>(&value));
- } else {
- ScopedSignalHandler ssh(SIGUSR1, BacktraceTest::test_signal_handler_);
-
- BacktraceTest::test_level_one_(1, 2, 3, 4, SetValueAndLoop, const_cast<int*>(&value));
- }
- }
- ASSERT_NE(-1, pid);
-
- int read_value = 0;
- uint64_t start = NanoTime();
- while (read_value == 0) {
- usleep(1000);
-
- // Loop until the remote function gets into the final function.
- ASSERT_TRUE(ptrace(PTRACE_ATTACH, pid, 0, 0) == 0);
-
- WaitForStop(pid);
-
- std::unique_ptr<BacktraceMap> map(map_create_func(pid, false));
- std::unique_ptr<Backtrace> backtrace(create_func(pid, pid, map.get()));
-
- size_t bytes_read = backtrace->Read(reinterpret_cast<uint64_t>(const_cast<int*>(&value)),
- reinterpret_cast<uint8_t*>(&read_value), sizeof(read_value));
- ASSERT_EQ(sizeof(read_value), bytes_read);
-
- ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0);
-
- ASSERT_TRUE(NanoTime() - start < 5 * NS_PER_SEC)
- << "Remote process did not execute far enough in 5 seconds.";
- }
-
- // Now need to send a signal to the remote process.
- kill(pid, SIGUSR1);
-
- // Wait for the process to get to the signal handler loop.
- Backtrace::const_iterator frame_iter;
- start = NanoTime();
- std::unique_ptr<BacktraceMap> map;
- std::unique_ptr<Backtrace> backtrace;
- while (true) {
- usleep(1000);
-
- ASSERT_TRUE(ptrace(PTRACE_ATTACH, pid, 0, 0) == 0);
-
- WaitForStop(pid);
-
- map.reset(map_create_func(pid, false));
- ASSERT_TRUE(map.get() != nullptr);
- backtrace.reset(create_func(pid, pid, map.get()));
- ASSERT_TRUE(backtrace->Unwind(0));
- bool found = false;
- for (frame_iter = backtrace->begin(); frame_iter != backtrace->end(); ++frame_iter) {
- if (frame_iter->func_name == "test_loop_forever") {
- ++frame_iter;
- found = true;
- break;
- }
- }
- if (found) {
- break;
- }
-
- ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0);
-
- ASSERT_TRUE(NanoTime() - start < 5 * NS_PER_SEC)
- << "Remote process did not get in signal handler in 5 seconds." << std::endl
- << DumpFrames(backtrace.get());
- }
-
- std::vector<std::string> names;
- // Loop through the frames, and save the function names.
- size_t frame = 0;
- for (; frame_iter != backtrace->end(); ++frame_iter) {
- if (frame_iter->func_name == "test_level_four") {
- frame = names.size() + 1;
- }
- names.push_back(frame_iter->func_name);
- }
- ASSERT_NE(0U, frame) << "Unable to find test_level_four in backtrace" << std::endl
- << DumpFrames(backtrace.get());
-
- // The expected order of the frames:
- // test_loop_forever
- // test_signal_handler|test_signal_action
- // <OPTIONAL_FRAME> May or may not exist.
- // SetValueAndLoop (but the function name might be empty)
- // test_level_four
- // test_level_three
- // test_level_two
- // test_level_one
- ASSERT_LE(frame + 2, names.size()) << DumpFrames(backtrace.get());
- ASSERT_LE(2U, frame) << DumpFrames(backtrace.get());
- if (use_action) {
- ASSERT_EQ("test_signal_action", names[0]) << DumpFrames(backtrace.get());
- } else {
- ASSERT_EQ("test_signal_handler", names[0]) << DumpFrames(backtrace.get());
- }
- ASSERT_EQ("test_level_three", names[frame]) << DumpFrames(backtrace.get());
- ASSERT_EQ("test_level_two", names[frame + 1]) << DumpFrames(backtrace.get());
- ASSERT_EQ("test_level_one", names[frame + 2]) << DumpFrames(backtrace.get());
-
- FinishRemoteProcess(pid);
-}
-
-TEST_F(BacktraceTest, unwind_remote_through_signal_using_handler) {
- UnwindThroughSignal(false, Backtrace::Create, BacktraceMap::Create);
-}
-
-TEST_F(BacktraceTest, unwind_remote_through_signal_using_action) {
- UnwindThroughSignal(true, Backtrace::Create, BacktraceMap::Create);
-}
-
-static void TestFrameSkipNumbering(create_func_t create_func, map_create_func_t map_create_func) {
- std::unique_ptr<BacktraceMap> map(map_create_func(getpid(), false));
- std::unique_ptr<Backtrace> backtrace(
- create_func(getpid(), android::base::GetThreadId(), map.get()));
- backtrace->Unwind(1);
- ASSERT_NE(0U, backtrace->NumFrames());
- ASSERT_EQ(0U, backtrace->GetFrame(0)->num);
-}
-
-TEST_F(BacktraceTest, unwind_frame_skip_numbering) {
- TestFrameSkipNumbering(Backtrace::Create, BacktraceMap::Create);
-}
-
-#define MAX_LEAK_BYTES (32*1024UL)
-
-static void CheckForLeak(pid_t pid, pid_t tid) {
- std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(pid));
-
- // Loop enough that even a small leak should be detectable.
- size_t first_allocated_bytes = 0;
- size_t last_allocated_bytes = 0;
- for (size_t i = 0; i < 4096; i++) {
- Backtrace* backtrace = Backtrace::Create(pid, tid, map.get());
- ASSERT_TRUE(backtrace != nullptr);
- ASSERT_TRUE(backtrace->Unwind(0));
- VERIFY_NO_ERROR(backtrace->GetError().error_code);
- delete backtrace;
-
- size_t allocated_bytes = mallinfo().uordblks;
- if (first_allocated_bytes == 0) {
- first_allocated_bytes = allocated_bytes;
- } else if (last_allocated_bytes > first_allocated_bytes) {
- // Check that the memory did not increase too much over the first loop.
- ASSERT_LE(last_allocated_bytes - first_allocated_bytes, MAX_LEAK_BYTES);
- }
- last_allocated_bytes = allocated_bytes;
- }
-}
-
-TEST_F(BacktraceTest, check_for_leak_local) {
- CheckForLeak(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD);
-}
-
-TEST_F(BacktraceTest, check_for_leak_local_thread) {
- thread_t thread_data = { 0, 0, 0, nullptr };
- pthread_t thread;
- ASSERT_TRUE(pthread_create(&thread, nullptr, ThreadLevelRun, &thread_data) == 0);
-
- // Wait up to 2 seconds for the tid to be set.
- ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2));
-
- CheckForLeak(BACKTRACE_CURRENT_PROCESS, thread_data.tid);
-
- // Tell the thread to exit its infinite loop.
- android_atomic_acquire_store(0, &thread_data.state);
-
- ASSERT_TRUE(pthread_join(thread, nullptr) == 0);
-}
-
-TEST_F(BacktraceTest, check_for_leak_remote) {
- pid_t pid;
- CreateRemoteProcess(&pid);
-
- CheckForLeak(pid, BACKTRACE_CURRENT_THREAD);
-
- FinishRemoteProcess(pid);
-}
diff --git a/libbacktrace/backtrace_testlib.cpp b/libbacktrace/backtrace_testlib.cpp
deleted file mode 100644
index fec7d98..0000000
--- a/libbacktrace/backtrace_testlib.cpp
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2013 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 <signal.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include <memory>
-#include <vector>
-
-#include <unwindstack/Regs.h>
-#include <unwindstack/RegsGetLocal.h>
-
-#include "backtrace_testlib.h"
-
-void test_loop_forever() {
- while (1)
- ;
-}
-
-void test_signal_handler(int) { test_loop_forever(); }
-
-void test_signal_action(int, siginfo_t*, void*) { test_loop_forever(); }
-
-int test_level_four(int one, int two, int three, int four, void (*callback_func)(void*),
- void* data) {
- if (callback_func != NULL) {
- callback_func(data);
- } else {
- while (1)
- ;
- }
- return one + two + three + four;
-}
-
-int test_level_three(int one, int two, int three, int four, void (*callback_func)(void*),
- void* data) {
- return test_level_four(one + 3, two + 6, three + 9, four + 12, callback_func, data) + 3;
-}
-
-int test_level_two(int one, int two, int three, int four, void (*callback_func)(void*), void* data) {
- return test_level_three(one + 2, two + 4, three + 6, four + 8, callback_func, data) + 2;
-}
-
-int test_level_one(int one, int two, int three, int four, void (*callback_func)(void*), void* data) {
- return test_level_two(one + 1, two + 2, three + 3, four + 4, callback_func, data) + 1;
-}
-
-int test_recursive_call(int level, void (*callback_func)(void*), void* data) {
- if (level > 0) {
- return test_recursive_call(level - 1, callback_func, data) + level;
- } else if (callback_func != NULL) {
- callback_func(data);
- } else {
- while (1) {
- }
- }
- return 0;
-}
-
-typedef struct {
- std::vector<uint8_t>* ucontext;
- volatile int* exit_flag;
-} GetContextArg;
-
-static void GetContextAndExit(void* data) {
- GetContextArg* arg = reinterpret_cast<GetContextArg*>(data);
-
- std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromLocal());
- unwindstack::RegsGetLocal(regs.get());
-
- ucontext_t ucontext;
- memset(&ucontext, 0, sizeof(ucontext));
-#if defined(__arm__)
- memcpy(&ucontext.uc_mcontext, regs->RawData(), sizeof(uint32_t) * 16);
-#elif defined(__aarch64__)
- memcpy(&ucontext.uc_mcontext, regs->RawData(), sizeof(uint64_t) * 33);
-#elif defined(__i386__)
- uint32_t* reg_data = reinterpret_cast<uint32_t*>(regs->RawData());
- ucontext.uc_mcontext.gregs[0] = reg_data[15];
- ucontext.uc_mcontext.gregs[1] = reg_data[14];
- ucontext.uc_mcontext.gregs[2] = reg_data[13];
- ucontext.uc_mcontext.gregs[3] = reg_data[12];
- ucontext.uc_mcontext.gregs[4] = reg_data[7];
- ucontext.uc_mcontext.gregs[5] = reg_data[6];
- ucontext.uc_mcontext.gregs[6] = reg_data[5];
- ucontext.uc_mcontext.gregs[7] = reg_data[4];
- ucontext.uc_mcontext.gregs[8] = reg_data[3];
- ucontext.uc_mcontext.gregs[9] = reg_data[2];
- ucontext.uc_mcontext.gregs[10] = reg_data[1];
- ucontext.uc_mcontext.gregs[11] = reg_data[0];
- ucontext.uc_mcontext.gregs[14] = reg_data[8];
- ucontext.uc_mcontext.gregs[15] = reg_data[10];
-#elif defined(__x86_64__)
- uint64_t* reg_data = reinterpret_cast<uint64_t*>(regs->RawData());
- ucontext.uc_mcontext.gregs[0] = reg_data[8];
- ucontext.uc_mcontext.gregs[1] = reg_data[9];
- ucontext.uc_mcontext.gregs[2] = reg_data[10];
- ucontext.uc_mcontext.gregs[3] = reg_data[11];
- ucontext.uc_mcontext.gregs[4] = reg_data[12];
- ucontext.uc_mcontext.gregs[5] = reg_data[13];
- ucontext.uc_mcontext.gregs[6] = reg_data[14];
- ucontext.uc_mcontext.gregs[7] = reg_data[15];
- ucontext.uc_mcontext.gregs[8] = reg_data[5];
- ucontext.uc_mcontext.gregs[9] = reg_data[4];
- ucontext.uc_mcontext.gregs[10] = reg_data[6];
- ucontext.uc_mcontext.gregs[11] = reg_data[3];
- ucontext.uc_mcontext.gregs[12] = reg_data[1];
- ucontext.uc_mcontext.gregs[13] = reg_data[0];
- ucontext.uc_mcontext.gregs[14] = reg_data[2];
- ucontext.uc_mcontext.gregs[15] = reg_data[7];
- ucontext.uc_mcontext.gregs[16] = reg_data[16];
-#endif
-
- arg->ucontext->resize(sizeof(ucontext));
- memcpy(arg->ucontext->data(), &ucontext, sizeof(ucontext));
-
- // Don't touch the stack anymore.
- while (*arg->exit_flag == 0) {
- }
-}
-
-void test_get_context_and_wait(void* ucontext, volatile int* exit_flag) {
- GetContextArg arg;
- arg.ucontext = reinterpret_cast<std::vector<uint8_t>*>(ucontext);
- arg.exit_flag = exit_flag;
- test_level_one(1, 2, 3, 4, GetContextAndExit, &arg);
-}
diff --git a/libbacktrace/backtrace_testlib.h b/libbacktrace/backtrace_testlib.h
deleted file mode 100644
index 9b55e56..0000000
--- a/libbacktrace/backtrace_testlib.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef _LIBBACKTRACE_BACKTRACE_TESTLIB_H
-#define _LIBBACKTRACE_BACKTRACE_TESTLIB_H
-
-#include <sys/cdefs.h>
-
-__BEGIN_DECLS
-
-void test_loop_forever();
-void test_signal_handler(int);
-void test_signal_action(int, siginfo_t*, void*);
-int test_level_four(int, int, int, int, void (*)(void*), void*);
-int test_level_three(int, int, int, int, void (*)(void*), void*);
-int test_level_two(int, int, int, int, void (*)(void*), void*);
-int test_level_one(int, int, int, int, void (*)(void*), void*);
-int test_recursive_call(int, void (*)(void*), void*);
-void test_get_context_and_wait(void*, volatile int*);
-
-__END_DECLS
-
-#endif // _LIBBACKTRACE_BACKTRACE_TESTLIB_H
diff --git a/libbacktrace/include/backtrace/Backtrace.h b/libbacktrace/include/backtrace/Backtrace.h
deleted file mode 100644
index 664b531..0000000
--- a/libbacktrace/include/backtrace/Backtrace.h
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef _BACKTRACE_BACKTRACE_H
-#define _BACKTRACE_BACKTRACE_H
-
-#include <inttypes.h>
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-#include <backtrace/backtrace_constants.h>
-#include <backtrace/BacktraceMap.h>
-
-#if defined(__LP64__)
-#define PRIPTR "016" PRIx64
-typedef uint64_t word_t;
-#else
-#define PRIPTR "08" PRIx64
-typedef uint32_t word_t;
-#endif
-
-enum BacktraceUnwindErrorCode : uint32_t {
- BACKTRACE_UNWIND_NO_ERROR,
- // Something failed while trying to perform the setup to begin the unwind.
- BACKTRACE_UNWIND_ERROR_SETUP_FAILED,
- // There is no map information to use with the unwind.
- BACKTRACE_UNWIND_ERROR_MAP_MISSING,
- // An error occurred that indicates a programming error.
- BACKTRACE_UNWIND_ERROR_INTERNAL,
- // The thread to unwind has disappeared before the unwind can begin.
- BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST,
- // The thread to unwind has not responded to a signal in a timely manner.
- BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT,
- // Attempt to do an unsupported operation.
- BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION,
- // Attempt to do an offline unwind without a context.
- BACKTRACE_UNWIND_ERROR_NO_CONTEXT,
- // The count of frames exceed MAX_BACKTRACE_FRAMES.
- BACKTRACE_UNWIND_ERROR_EXCEED_MAX_FRAMES_LIMIT,
- // Failed to read memory.
- BACKTRACE_UNWIND_ERROR_ACCESS_MEM_FAILED,
- // Failed to read registers.
- BACKTRACE_UNWIND_ERROR_ACCESS_REG_FAILED,
- // Failed to find a function in debug sections.
- BACKTRACE_UNWIND_ERROR_FIND_PROC_INFO_FAILED,
- // Failed to execute dwarf instructions in debug sections.
- BACKTRACE_UNWIND_ERROR_EXECUTE_DWARF_INSTRUCTION_FAILED,
- // Unwind information is incorrect.
- BACKTRACE_UNWIND_ERROR_UNWIND_INFO,
- // Unwind information stopped due to sp/pc repeating.
- BACKTRACE_UNWIND_ERROR_REPEATED_FRAME,
- // Unwind information stopped due to invalid elf.
- BACKTRACE_UNWIND_ERROR_INVALID_ELF,
-};
-
-struct BacktraceUnwindError {
- enum BacktraceUnwindErrorCode error_code;
-
- union {
- // for BACKTRACE_UNWIND_ERROR_ACCESS_MEM_FAILED
- uint64_t addr;
- // for BACKTRACE_UNWIND_ERROR_ACCESS_REG_FAILED
- uint64_t regno;
- } error_info;
-
- BacktraceUnwindError() : error_code(BACKTRACE_UNWIND_NO_ERROR) {}
-};
-
-struct backtrace_frame_data_t {
- size_t num; // The current fame number.
- uint64_t pc; // The absolute pc.
- uint64_t rel_pc; // The relative pc.
- uint64_t sp; // The top of the stack.
- size_t stack_size; // The size of the stack, zero indicate an unknown stack size.
- backtrace_map_t map; // The map associated with the given pc.
- std::string func_name; // The function name associated with this pc, NULL if not found.
- uint64_t func_offset; // pc relative to the start of the function, only valid if func_name is not
- // NULL.
-};
-
-struct backtrace_stackinfo_t {
- uint64_t start;
- uint64_t end;
- const uint8_t* data;
-};
-
-namespace unwindstack {
-class Regs;
-}
-
-class Backtrace {
- public:
- enum ArchEnum : uint8_t {
- ARCH_ARM,
- ARCH_ARM64,
- ARCH_X86,
- ARCH_X86_64,
- };
-
- static void SetGlobalElfCache(bool enable);
-
- // Create the correct Backtrace object based on what is to be unwound.
- // If pid < 0 or equals the current pid, then the Backtrace object
- // corresponds to the current process.
- // If pid < 0 or equals the current pid and tid >= 0, then the Backtrace
- // object corresponds to a thread in the current process.
- // If pid >= 0 and tid < 0, then the Backtrace object corresponds to a
- // different process.
- // Tracing a thread in a different process is not supported.
- // If map is NULL, then create the map and manage it internally.
- // If map is not NULL, the map is still owned by the caller.
- static Backtrace* Create(pid_t pid, pid_t tid, BacktraceMap* map = nullptr);
-
- virtual ~Backtrace();
-
- // Get the current stack trace and store in the backtrace_ structure.
- virtual bool Unwind(size_t num_ignore_frames, void* context = nullptr) = 0;
-
- static bool Unwind(unwindstack::Regs* regs, BacktraceMap* back_map,
- std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames,
- std::vector<std::string>* skip_names, BacktraceUnwindError* error = nullptr);
-
- // Get the function name and offset into the function given the pc.
- // If the string is empty, then no valid function name was found,
- // or the pc is not in any valid map.
- virtual std::string GetFunctionName(uint64_t pc, uint64_t* offset,
- const backtrace_map_t* map = nullptr);
-
- // Fill in the map data associated with the given pc.
- virtual void FillInMap(uint64_t pc, backtrace_map_t* map);
-
- // Read the data at a specific address.
- virtual bool ReadWord(uint64_t ptr, word_t* out_value) = 0;
-
- // Read arbitrary data from a specific address. If a read request would
- // span from one map to another, this call only reads up until the end
- // of the current map.
- // Returns the total number of bytes actually read.
- virtual size_t Read(uint64_t addr, uint8_t* buffer, size_t bytes) = 0;
-
- // Create a string representing the formatted line of backtrace information
- // for a single frame.
- virtual std::string FormatFrameData(size_t frame_num);
- static std::string FormatFrameData(const backtrace_frame_data_t* frame);
-
- pid_t Pid() const { return pid_; }
- pid_t Tid() const { return tid_; }
- size_t NumFrames() const { return frames_.size(); }
-
- const backtrace_frame_data_t* GetFrame(size_t frame_num) {
- if (frame_num >= frames_.size()) {
- return nullptr;
- }
- return &frames_[frame_num];
- }
-
- typedef std::vector<backtrace_frame_data_t>::iterator iterator;
- iterator begin() { return frames_.begin(); }
- iterator end() { return frames_.end(); }
-
- typedef std::vector<backtrace_frame_data_t>::const_iterator const_iterator;
- const_iterator begin() const { return frames_.begin(); }
- const_iterator end() const { return frames_.end(); }
-
- BacktraceMap* GetMap() { return map_; }
-
- BacktraceUnwindError GetError() { return error_; }
-
- std::string GetErrorString(BacktraceUnwindError error);
-
- // Set whether to skip frames in libbacktrace/libunwindstack when doing a local unwind.
- void SetSkipFrames(bool skip_frames) { skip_frames_ = skip_frames; }
-
- protected:
- Backtrace(pid_t pid, pid_t tid, BacktraceMap* map);
-
- // The name returned is not demangled, GetFunctionName() takes care of
- // demangling the name.
- virtual std::string GetFunctionNameRaw(uint64_t pc, uint64_t* offset) = 0;
-
- virtual bool VerifyReadWordArgs(uint64_t ptr, word_t* out_value);
-
- bool BuildMap();
-
- pid_t pid_;
- pid_t tid_;
-
- BacktraceMap* map_;
- bool map_shared_;
-
- std::vector<backtrace_frame_data_t> frames_;
-
- // Skip frames in libbacktrace/libunwindstack when doing a local unwind.
- bool skip_frames_ = true;
-
- BacktraceUnwindError error_;
-};
-
-#endif // _BACKTRACE_BACKTRACE_H
diff --git a/libbacktrace/include/backtrace/BacktraceMap.h b/libbacktrace/include/backtrace/BacktraceMap.h
deleted file mode 100644
index e000a00..0000000
--- a/libbacktrace/include/backtrace/BacktraceMap.h
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#ifndef _BACKTRACE_BACKTRACE_MAP_H
-#define _BACKTRACE_BACKTRACE_MAP_H
-
-#include <stdint.h>
-#include <sys/types.h>
-#ifdef _WIN32
-// MINGW does not define these constants.
-#define PROT_NONE 0
-#define PROT_READ 0x1
-#define PROT_WRITE 0x2
-#define PROT_EXEC 0x4
-#else
-#include <sys/mman.h>
-#endif
-
-#include <deque>
-#include <iterator>
-#include <memory>
-#include <string>
-#include <vector>
-
-// Forward declaration.
-struct backtrace_stackinfo_t;
-
-// Special flag to indicate a map is in /dev/. However, a map in
-// /dev/ashmem/... does not set this flag.
-static constexpr int PROT_DEVICE_MAP = 0x8000;
-// Special flag to indicate that this map represents an elf file
-// created by ART for use with the gdb jit debug interface.
-// This should only ever appear in offline maps data.
-static constexpr int PROT_JIT_SYMFILE_MAP = 0x4000;
-
-struct backtrace_map_t {
- uint64_t start = 0;
- uint64_t end = 0;
- uint64_t offset = 0;
- uint64_t load_bias = 0;
- int flags = 0;
- std::string name;
-
- // Returns `name` if non-empty, or `<anonymous:0x...>` otherwise.
- std::string Name() const;
-};
-
-namespace unwindstack {
-class Memory;
-}
-
-class BacktraceMap {
-public:
- // If uncached is true, then parse the current process map as of the call.
- // Passing a map created with uncached set to true to Backtrace::Create()
- // is unsupported.
- static BacktraceMap* Create(pid_t pid, bool uncached = false);
-
- virtual ~BacktraceMap();
-
- class iterator : public std::iterator<std::bidirectional_iterator_tag, backtrace_map_t*> {
- public:
- iterator(BacktraceMap* map, size_t index) : map_(map), index_(index) {}
-
- iterator& operator++() {
- index_++;
- return *this;
- }
- const iterator operator++(int increment) {
- index_ += increment;
- return *this;
- }
- iterator& operator--() {
- index_--;
- return *this;
- }
- const iterator operator--(int decrement) {
- index_ -= decrement;
- return *this;
- }
-
- bool operator==(const iterator& rhs) { return this->index_ == rhs.index_; }
- bool operator!=(const iterator& rhs) { return this->index_ != rhs.index_; }
-
- const backtrace_map_t* operator*() {
- if (index_ >= map_->size()) {
- return nullptr;
- }
- backtrace_map_t* map = &map_->maps_[index_];
- if (map->load_bias == static_cast<uint64_t>(-1)) {
- map->load_bias = map_->GetLoadBias(index_);
- }
- return map;
- }
-
- private:
- BacktraceMap* map_ = nullptr;
- size_t index_ = 0;
- };
-
- iterator begin() { return iterator(this, 0); }
- iterator end() { return iterator(this, maps_.size()); }
-
- // Fill in the map data structure for the given address.
- virtual void FillIn(uint64_t addr, backtrace_map_t* map);
-
- // Only supported with the new unwinder.
- virtual std::string GetFunctionName(uint64_t /*pc*/, uint64_t* /*offset*/) { return ""; }
- virtual std::shared_ptr<unwindstack::Memory> GetProcessMemory() { return nullptr; }
-
- // The flags returned are the same flags as used by the mmap call.
- // The values are PROT_*.
- int GetFlags(uint64_t pc) {
- backtrace_map_t map;
- FillIn(pc, &map);
- if (IsValid(map)) {
- return map.flags;
- }
- return PROT_NONE;
- }
-
- bool IsReadable(uint64_t pc) { return GetFlags(pc) & PROT_READ; }
- bool IsWritable(uint64_t pc) { return GetFlags(pc) & PROT_WRITE; }
- bool IsExecutable(uint64_t pc) { return GetFlags(pc) & PROT_EXEC; }
-
- // In order to use the iterators on this object, a caller must
- // call the LockIterator and UnlockIterator function to guarantee
- // that the data does not change while it's being used.
- virtual void LockIterator() {}
- virtual void UnlockIterator() {}
-
- size_t size() const { return maps_.size(); }
-
- virtual bool Build();
-
- static inline bool IsValid(const backtrace_map_t& map) {
- return map.end > 0;
- }
-
- void SetSuffixesToIgnore(std::vector<std::string> suffixes) {
- suffixes_to_ignore_.insert(suffixes_to_ignore_.end(), suffixes.begin(), suffixes.end());
- }
-
- const std::vector<std::string>& GetSuffixesToIgnore() { return suffixes_to_ignore_; }
-
- // Disabling the resolving of names results in the function name being
- // set to an empty string and the function offset being set to zero
- // in the frame data when unwinding.
- void SetResolveNames(bool resolve) { resolve_names_ = resolve; }
-
- bool ResolveNames() { return resolve_names_; }
-
- protected:
- BacktraceMap(pid_t pid);
-
- virtual uint64_t GetLoadBias(size_t /* index */) { return 0; }
-
- pid_t pid_;
- std::deque<backtrace_map_t> maps_;
- std::vector<std::string> suffixes_to_ignore_;
- bool resolve_names_ = true;
-};
-
-class ScopedBacktraceMapIteratorLock {
-public:
- explicit ScopedBacktraceMapIteratorLock(BacktraceMap* map) : map_(map) {
- map->LockIterator();
- }
-
- ~ScopedBacktraceMapIteratorLock() {
- map_->UnlockIterator();
- }
-
-private:
- BacktraceMap* map_;
-};
-
-#endif // _BACKTRACE_BACKTRACE_MAP_H
diff --git a/libbacktrace/include/backtrace/backtrace_constants.h b/libbacktrace/include/backtrace/backtrace_constants.h
deleted file mode 100644
index 1a2da36..0000000
--- a/libbacktrace/include/backtrace/backtrace_constants.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#ifndef _BACKTRACE_BACKTRACE_CONSTANTS_H
-#define _BACKTRACE_BACKTRACE_CONSTANTS_H
-
-// When the pid to be traced is set to this value, then trace the current
-// process. If the tid value is not BACKTRACE_NO_TID, then the specified
-// thread from the current process will be traced.
-#define BACKTRACE_CURRENT_PROCESS (-1)
-// When the tid to be traced is set to this value, then trace the specified
-// current thread of the specified pid.
-#define BACKTRACE_CURRENT_THREAD (-1)
-
-#define MAX_BACKTRACE_FRAMES 256
-
-#endif // _BACKTRACE_BACKTRACE_CONSTANTS_H
diff --git a/libbacktrace/testdata/arm/libGLESv2_adreno.so b/libbacktrace/testdata/arm/libGLESv2_adreno.so
deleted file mode 100644
index 871f6dc..0000000
--- a/libbacktrace/testdata/arm/libGLESv2_adreno.so
+++ /dev/null
Binary files differ
diff --git a/libbacktrace/testdata/arm/libandroid_runtime.so b/libbacktrace/testdata/arm/libandroid_runtime.so
deleted file mode 100644
index e4283e6..0000000
--- a/libbacktrace/testdata/arm/libandroid_runtime.so
+++ /dev/null
Binary files differ
diff --git a/libbacktrace/testdata/arm/libart.so b/libbacktrace/testdata/arm/libart.so
deleted file mode 100644
index bed8e35..0000000
--- a/libbacktrace/testdata/arm/libart.so
+++ /dev/null
Binary files differ
diff --git a/libbacktrace/testdata/arm/libbacktrace_test_arm_exidx.so b/libbacktrace/testdata/arm/libbacktrace_test_arm_exidx.so
deleted file mode 100755
index 454b032..0000000
--- a/libbacktrace/testdata/arm/libbacktrace_test_arm_exidx.so
+++ /dev/null
Binary files differ
diff --git a/libbacktrace/testdata/arm/libbacktrace_test_debug_frame.so b/libbacktrace/testdata/arm/libbacktrace_test_debug_frame.so
deleted file mode 100755
index 787f2cb..0000000
--- a/libbacktrace/testdata/arm/libbacktrace_test_debug_frame.so
+++ /dev/null
Binary files differ
diff --git a/libbacktrace/testdata/arm/libbacktrace_test_gnu_debugdata.so b/libbacktrace/testdata/arm/libbacktrace_test_gnu_debugdata.so
deleted file mode 100755
index 9340d98..0000000
--- a/libbacktrace/testdata/arm/libbacktrace_test_gnu_debugdata.so
+++ /dev/null
Binary files differ
diff --git a/libbacktrace/testdata/arm/offline_testdata b/libbacktrace/testdata/arm/offline_testdata
deleted file mode 100644
index d5b8f47..0000000
--- a/libbacktrace/testdata/arm/offline_testdata
+++ /dev/null
@@ -1,105 +0,0 @@
-pid: 32232 tid: 32233
-map: start: aad19000 end: aad6c000 offset: 0 load_bias: 0 flags: 5 name: /data/backtrace_test32
-map: start: aad6c000 end: aad6e000 offset: 52000 load_bias: 0 flags: 1 name: /data/backtrace_test32
-map: start: aad6e000 end: aad6f000 offset: 54000 load_bias: 0 flags: 3 name: /data/backtrace_test32
-map: start: e7380000 end: e7400000 offset: 0 load_bias: 0 flags: 3 name: [anon:libc_malloc]
-map: start: e745f000 end: e7463000 offset: 0 load_bias: 0 flags: 5 name: /system/lib/libnetd_client.so
-map: start: e7463000 end: e7464000 offset: 3000 load_bias: 0 flags: 1 name: /system/lib/libnetd_client.so
-map: start: e7464000 end: e7465000 offset: 4000 load_bias: 0 flags: 3 name: /system/lib/libnetd_client.so
-map: start: e7480000 end: e7500000 offset: 0 load_bias: 0 flags: 3 name: [anon:libc_malloc]
-map: start: e7558000 end: e756c000 offset: 0 load_bias: 0 flags: 5 name: /system/lib/libunwind.so
-map: start: e756c000 end: e756d000 offset: 0 load_bias: 0 flags: 0 name:
-map: start: e756d000 end: e756e000 offset: 14000 load_bias: 0 flags: 1 name: /system/lib/libunwind.so
-map: start: e756e000 end: e756f000 offset: 15000 load_bias: 0 flags: 3 name: /system/lib/libunwind.so
-map: start: e756f000 end: e75b5000 offset: 0 load_bias: 0 flags: 3 name: [anon:.bss]
-map: start: e75d4000 end: e75e1000 offset: 0 load_bias: 0 flags: 5 name: /system/lib/libbase.so
-map: start: e75e1000 end: e75e2000 offset: c000 load_bias: 0 flags: 1 name: /system/lib/libbase.so
-map: start: e75e2000 end: e75e3000 offset: d000 load_bias: 0 flags: 3 name: /system/lib/libbase.so
-map: start: e7600000 end: e7616000 offset: 0 load_bias: 0 flags: 5 name: /system/lib/liblzma.so
-map: start: e7616000 end: e7617000 offset: 15000 load_bias: 0 flags: 1 name: /system/lib/liblzma.so
-map: start: e7617000 end: e7618000 offset: 16000 load_bias: 0 flags: 3 name: /system/lib/liblzma.so
-map: start: e7618000 end: e761d000 offset: 0 load_bias: 0 flags: 3 name: [anon:.bss]
-map: start: e7647000 end: e7656000 offset: 0 load_bias: 0 flags: 5 name: /system/lib/liblog.so
-map: start: e7656000 end: e7657000 offset: e000 load_bias: 0 flags: 1 name: /system/lib/liblog.so
-map: start: e7657000 end: e7658000 offset: f000 load_bias: 0 flags: 3 name: /system/lib/liblog.so
-map: start: e7681000 end: e76a2000 offset: 0 load_bias: 0 flags: 5 name: /system/lib/libm.so
-map: start: e76a2000 end: e76a3000 offset: 20000 load_bias: 0 flags: 1 name: /system/lib/libm.so
-map: start: e76a3000 end: e76a4000 offset: 21000 load_bias: 0 flags: 3 name: /system/lib/libm.so
-map: start: e76eb000 end: e76ee000 offset: 0 load_bias: 0 flags: 5 name: /data/libbacktrace_test.so
-map: start: e76ee000 end: e76ef000 offset: 2000 load_bias: 0 flags: 1 name: /data/libbacktrace_test.so
-map: start: e76ef000 end: e76f0000 offset: 3000 load_bias: 0 flags: 3 name: /data/libbacktrace_test.so
-map: start: e7712000 end: e771f000 offset: 0 load_bias: 0 flags: 5 name: /system/lib/libbacktrace.so
-map: start: e771f000 end: e7720000 offset: 0 load_bias: 0 flags: 0 name:
-map: start: e7720000 end: e7721000 offset: d000 load_bias: 0 flags: 1 name: /system/lib/libbacktrace.so
-map: start: e7721000 end: e7722000 offset: e000 load_bias: 0 flags: 3 name: /system/lib/libbacktrace.so
-map: start: e7761000 end: e7778000 offset: 0 load_bias: 0 flags: 5 name: /system/lib/libutils.so
-map: start: e7778000 end: e7779000 offset: 16000 load_bias: 0 flags: 1 name: /system/lib/libutils.so
-map: start: e7779000 end: e777a000 offset: 17000 load_bias: 0 flags: 3 name: /system/lib/libutils.so
-map: start: e77a5000 end: e782d000 offset: 0 load_bias: 0 flags: 5 name: /system/lib/libc.so
-map: start: e782d000 end: e7831000 offset: 87000 load_bias: 0 flags: 1 name: /system/lib/libc.so
-map: start: e7831000 end: e7833000 offset: 8b000 load_bias: 0 flags: 3 name: /system/lib/libc.so
-map: start: e7833000 end: e7834000 offset: 0 load_bias: 0 flags: 3 name: [anon:.bss]
-map: start: e7834000 end: e7835000 offset: 0 load_bias: 0 flags: 1 name: [anon:.bss]
-map: start: e7835000 end: e783b000 offset: 0 load_bias: 0 flags: 3 name: [anon:.bss]
-map: start: e7845000 end: e8437000 offset: 0 load_bias: 2b000 flags: 5 name: /system/lib/libLLVM.so
-map: start: e8437000 end: e8438000 offset: 0 load_bias: 0 flags: 0 name:
-map: start: e8438000 end: e848a000 offset: bf2000 load_bias: 0 flags: 1 name: /system/lib/libLLVM.so
-map: start: e848a000 end: e848b000 offset: c44000 load_bias: 0 flags: 3 name: /system/lib/libLLVM.so
-map: start: e848b000 end: e84a1000 offset: 0 load_bias: 0 flags: 3 name: [anon:.bss]
-map: start: e84eb000 end: e84f7000 offset: 0 load_bias: 0 flags: 5 name: /system/lib/libcutils.so
-map: start: e84f7000 end: e84f8000 offset: 0 load_bias: 0 flags: 0 name:
-map: start: e84f8000 end: e84f9000 offset: c000 load_bias: 0 flags: 1 name: /system/lib/libcutils.so
-map: start: e84f9000 end: e84fa000 offset: d000 load_bias: 0 flags: 3 name: /system/lib/libcutils.so
-map: start: e852e000 end: e85b3000 offset: 0 load_bias: 2000 flags: 5 name: /system/lib/libc++.so
-map: start: e85b3000 end: e85b4000 offset: 0 load_bias: 0 flags: 0 name:
-map: start: e85b4000 end: e85b8000 offset: 85000 load_bias: 0 flags: 1 name: /system/lib/libc++.so
-map: start: e85b8000 end: e85b9000 offset: 89000 load_bias: 0 flags: 3 name: /system/lib/libc++.so
-map: start: e85b9000 end: e85ba000 offset: 0 load_bias: 0 flags: 3 name: [anon:.bss]
-map: start: e85ce000 end: e85cf000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc]
-map: start: e85e4000 end: e85e5000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_small_objects]
-map: start: e8607000 end: e8608000 offset: 0 load_bias: 0 flags: 1 name: [anon:linker_alloc]
-map: start: e8680000 end: e8700000 offset: 0 load_bias: 0 flags: 3 name: [anon:libc_malloc]
-map: start: e870d000 end: e8719000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: e8719000 end: e871b000 offset: 0 load_bias: 0 flags: 1 name: [anon:atexit handlers]
-map: start: e871b000 end: e873b000 offset: 0 load_bias: 0 flags: 32769 name: /dev/__properties__/u:object_r:default_prop:s0
-map: start: e873b000 end: e875b000 offset: 0 load_bias: 0 flags: 32769 name: /dev/__properties__/properties_serial
-map: start: e875b000 end: e875c000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_vector]
-map: start: e875c000 end: e875d000 offset: 0 load_bias: 0 flags: 3 name: [anon:arc4random data]
-map: start: e875d000 end: e875e000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc]
-map: start: e875e000 end: e875f000 offset: 0 load_bias: 0 flags: 1 name: [anon:linker_alloc]
-map: start: e875f000 end: e877f000 offset: 0 load_bias: 0 flags: 32769 name: /dev/__properties__/u:object_r:debug_prop:s0
-map: start: e877f000 end: e879f000 offset: 0 load_bias: 0 flags: 32769 name: /dev/__properties__/properties_serial
-map: start: e879f000 end: e87a0000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_vector]
-map: start: e87a0000 end: e87a1000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_small_objects]
-map: start: e87a1000 end: e87a2000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_vector]
-map: start: e87a2000 end: e87a3000 offset: 0 load_bias: 0 flags: 0 name:
-map: start: e87a3000 end: e87a4000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: e87a4000 end: e87a5000 offset: 0 load_bias: 0 flags: 0 name:
-map: start: e87a5000 end: e87a6000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_lob]
-map: start: e87a6000 end: e87a7000 offset: 0 load_bias: 0 flags: 1 name: [anon:linker_alloc]
-map: start: e87a7000 end: e87a8000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_vector]
-map: start: e87a8000 end: e87a9000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_small_objects]
-map: start: e87a9000 end: e87aa000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_vector]
-map: start: e87aa000 end: e87ab000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_small_objects]
-map: start: e87ab000 end: e87ac000 offset: 0 load_bias: 0 flags: 1 name: [anon:atexit handlers]
-map: start: e87ac000 end: e87ad000 offset: 0 load_bias: 0 flags: 0 name: [anon:thread signal stack guard page]
-map: start: e87ad000 end: e87af000 offset: 0 load_bias: 0 flags: 3 name: [anon:thread signal stack]
-map: start: e87af000 end: e87b0000 offset: 0 load_bias: 0 flags: 3 name: [anon:arc4random data]
-map: start: e87b0000 end: e880d000 offset: 0 load_bias: 0 flags: 5 name: /system/bin/linker
-map: start: e880d000 end: e880f000 offset: 5c000 load_bias: 0 flags: 1 name: /system/bin/linker
-map: start: e880f000 end: e8810000 offset: 5e000 load_bias: 0 flags: 3 name: /system/bin/linker
-map: start: e8810000 end: e8812000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: e8812000 end: e8813000 offset: 0 load_bias: 0 flags: 1 name:
-map: start: e8813000 end: e8815000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: ff886000 end: ff8a9000 offset: 0 load_bias: 0 flags: 3 name: [stack]
-map: start: ffff0000 end: ffff1000 offset: 0 load_bias: 0 flags: 5 name: [vectors]
-ucontext: 104 000000000000000000000000000000000000000000000000000000000000000034868affdc8871e8150000001c0000001c000000150000000e00000007000000e08771e834868aff2354d2aa24f9ffffdc8871e88c8771e875b86ee778ba6ee70000000000000000
-stack: start: e8715000 end: e8719000 size: 16384 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dc8871e87dba6ee734868affdc8871e8dc8871e85dba6ee7070000000e000000150000001c000000dc8871e85dba6ee71c000000150000000e00000007000000100000000c0000000800000004000000ddb86ee75dba6ee7dc8871e804000000080000000c00000010000000dc8871e85dba6ee7100000000c000000080000000400000008000000060000000400000002000000288871e835b96ee75dba6ee7dc8871e802000000040000000600000008000000dc8871e85dba6ee70800000006000000040000000200000004000000030000000200000001000000708871e88db96ee75dba6ee7dc8871e801000000020000000300000004000000dc8871e85dba6ee70400000003000000020000000100000004000000208971e8208971e878000000e87d00003dba6ee75dba6ee7dc8871e878000000c5807ce7fc7183e734868aff78868aff78868aff34868aff34868aff78868affe0879437208971e84154d2aa0020000034868aff34868aff34868aff78000000c9b87ee7b1b87ee7a3f47be7288971e8b1b87ee7208971e800000000f83481e800000000e97d0000e87d000000000000005071e82039000000100000000000000000000000000000000000002354d2aa34868aff00000000002071e801000000000000000000000000000000708971e8208971e8000000000000000000000000e0879437000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-function: start: 0 end: e76eb835 name: unknown_start
-function: start: e76eb835 end: e76eb88d name: test_level_four
-function: start: e76eb88d end: e76eb8e5 name: test_level_three
-function: start: e76eb8e5 end: e76eb93d name: test_level_two
-function: start: e76eb93d end: e76eb995 name: test_level_one
-function: start: e76eb995 end: e76eb9f1 name: test_recursive_call
-function: start: e76eb9f1 end: ffffffff name: test_get_context_and_wait
-function: start: ffffffff end: ffffffff name: unknown_end
diff --git a/libbacktrace/testdata/arm/offline_testdata_for_libGLESv2_adreno b/libbacktrace/testdata/arm/offline_testdata_for_libGLESv2_adreno
deleted file mode 100644
index d7c186e..0000000
--- a/libbacktrace/testdata/arm/offline_testdata_for_libGLESv2_adreno
+++ /dev/null
@@ -1,6 +0,0 @@
-pid: 7288 tid: 31656
-ucontext: 104 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f017cc00000000356241cc0000000000000000
-map: start: cc361000 end: cc758000 offset: 0 load_bias: 9000 flags: 5 name: /vendor/lib/egl/libGLESv2_adreno.so
-stack: start: cc17f234 end: cc17f258 size: 36 0000000000000000000000000000000000000000000000000000000000000000b36141cc
-function: start: be1f0 end: be304 name: EsxContext::Clear(unsigned int, unsigned int, unsigned int, EsxClearValues*)
-function: start: be058 end: be1f0 name: EsxContext::ClearBuffersForDebug()
diff --git a/libbacktrace/testdata/arm/offline_testdata_for_libandroid_runtime b/libbacktrace/testdata/arm/offline_testdata_for_libandroid_runtime
deleted file mode 100644
index 54f3525..0000000
--- a/libbacktrace/testdata/arm/offline_testdata_for_libandroid_runtime
+++ /dev/null
@@ -1,6 +0,0 @@
-pid: 7288 tid: 31656
-ucontext: 104 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003069fed80000000049dcf6f10000000000000000
-map: start: f1f10000 end: f2049000 offset: 0 load_bias: 10000 flags: 5 name: /system/lib/libandroid_runtime.so
-stack: start: d8fe6948 end: d8fe6958 size: 16 000000000000000000000000e7dcf6f1
-function: start: 6dbf9 end: 6dce5 name: android::AndroidRuntime::javaThreadShell
-function: start: 6dce5 end: 6dd79 name: android::AndroidRuntime::javaCreateThreadEtc
diff --git a/libbacktrace/testdata/arm/offline_testdata_for_libart b/libbacktrace/testdata/arm/offline_testdata_for_libart
deleted file mode 100644
index c1369ff..0000000
--- a/libbacktrace/testdata/arm/offline_testdata_for_libart
+++ /dev/null
@@ -1,10 +0,0 @@
-pid: 32232 tid: 32233
-ucontext: 104 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006473602451b3e2e700000000d82fd1ff5600000000908eec00000000d42dd1ff00000000c02dd1ff617171e9617171e90000000000000000
-map: start: e9380000 end: e9766000 offset: 0 load_bias: b000 flags: 5 name: /system/lib/libart.so
-stack: start: ffd12dc0 end: ffd1306c size: 684 00000000000c5024070000000300000005070a0a0100000051b3e2e700000000d82fd1ff560000004c2ed1ff000000000000000081b771e9d82fd1ff000000004c2ed1ff0c2ed1ff40a8d27024bf76e900908eec000000000834d1ff0000000000000000000000000d000000050000000000000000000000080000000101d1ff44b8bfeb4b0000000000000000000000e8b8952400000000fc2ed1ff4fb3e2e7bc49ac6f00908eecb02ed1ffd82fd1ff040000008c908eec942fd1ffd5c141e9d82fd1ff4fb3e2e7542fd1ff336c68e940000000400000007030d1fff031d1ff00000000bc49ac6f5c30d1ff942fd1ff842fd1ffd82fd1ff00000000b8f1786f4fb3e2e7610d67e9d82fd1ff4fb3e2e77880adeb7980adeb7a80adeb7b80adeb7c80adeb7d80adeb7e80adeb7f80adeb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007430d1ff02000000e8b89524e8d895240200000000908eec5c30d1ffbc49ac6f4fb3e2e74030d1ffe8d8952400000000b8f1786fbc49ac6f332367e94fb3e2e701000000637171e9637171e9000000005c30d1ff8430d1ffe0c08bec882fd1ff4fb3e2e70200000004000000942fd1ffe8b8952400908eec58d8952458d895247fbd69e90500000000400fe40100000000908eec58d89524060000009c86bd6f6b876fe900908eece0c08bec00008eec0000000000000000000000000000000044b8bfeb4b000000009be86f040000000038d1ff01000000c8e7446f060000000000000000908eec30d89524e8b895249c86bd6f7893476f00908eec00000000358c6fe970400fe4116e71e9a0285a6fa4d49c6f4489bd6f30d8952458d89524e8d8952400908eeca431d1ff2c31d1ffb75861e90100000000908eec30528bec409181e958d89524
-function: start: 3a2121 end: 3a217a name: art_quick_invoke_stub_internal
-function: start: 3a66a5 end: 3a6787 name: art_quick_invoke_static_stub
-function: start: a7129 end: a72f1 name: art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)
-function: start: 2fbd35 end: 2fc789 name: art::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, art::ArgArray*, art::JValue*, char const*)
-function: start: 2fcf75 end: 2fd88d name: art::InvokeMethod(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jobject*, _jobject*, unsigned int)
-function: start: 2a089d end: 2a08bb name: art::Method_invoke(_JNIEnv*, _jobject*, _jobject*, _jobject*)
diff --git a/libbacktrace/testdata/arm64/eglSubDriverAndroid.so b/libbacktrace/testdata/arm64/eglSubDriverAndroid.so
deleted file mode 100644
index 10ce06b..0000000
--- a/libbacktrace/testdata/arm64/eglSubDriverAndroid.so
+++ /dev/null
Binary files differ
diff --git a/libbacktrace/testdata/arm64/libbacktrace_test_eh_frame.so b/libbacktrace/testdata/arm64/libbacktrace_test_eh_frame.so
deleted file mode 100755
index 880f337..0000000
--- a/libbacktrace/testdata/arm64/libbacktrace_test_eh_frame.so
+++ /dev/null
Binary files differ
diff --git a/libbacktrace/testdata/arm64/libskia.so b/libbacktrace/testdata/arm64/libskia.so
deleted file mode 100644
index ef1a6a1..0000000
--- a/libbacktrace/testdata/arm64/libskia.so
+++ /dev/null
Binary files differ
diff --git a/libbacktrace/testdata/arm64/offline_testdata b/libbacktrace/testdata/arm64/offline_testdata
deleted file mode 100644
index cee9f72..0000000
--- a/libbacktrace/testdata/arm64/offline_testdata
+++ /dev/null
@@ -1,107 +0,0 @@
-pid: 32438 tid: 32439
-map: start: 557066e000 end: 55706ee000 offset: 0 load_bias: 0 flags: 5 name: /data/backtrace_test64
-map: start: 55706ef000 end: 55706f2000 offset: 80000 load_bias: 0 flags: 1 name: /data/backtrace_test64
-map: start: 55706f2000 end: 55706f3000 offset: 83000 load_bias: 0 flags: 3 name: /data/backtrace_test64
-map: start: 7014200000 end: 7014600000 offset: 0 load_bias: 0 flags: 3 name: [anon:libc_malloc]
-map: start: 701464c000 end: 701465c000 offset: 0 load_bias: 0 flags: 5 name: /system/lib64/libcutils.so
-map: start: 701465c000 end: 701465d000 offset: 0 load_bias: 0 flags: 0 name:
-map: start: 701465d000 end: 701465e000 offset: 10000 load_bias: 0 flags: 1 name: /system/lib64/libcutils.so
-map: start: 701465e000 end: 701465f000 offset: 11000 load_bias: 0 flags: 3 name: /system/lib64/libcutils.so
-map: start: 7014691000 end: 70146b5000 offset: 0 load_bias: 0 flags: 5 name: /system/lib64/liblzma.so
-map: start: 70146b5000 end: 70146b6000 offset: 23000 load_bias: 0 flags: 1 name: /system/lib64/liblzma.so
-map: start: 70146b6000 end: 70146b7000 offset: 24000 load_bias: 0 flags: 3 name: /system/lib64/liblzma.so
-map: start: 70146b7000 end: 70146bc000 offset: 0 load_bias: 0 flags: 3 name: [anon:.bss]
-map: start: 70146c9000 end: 70158b5000 offset: 0 load_bias: af000 flags: 5 name: /system/lib64/libLLVM.so
-map: start: 70158b5000 end: 701596b000 offset: 11eb000 load_bias: 0 flags: 1 name: /system/lib64/libLLVM.so
-map: start: 701596b000 end: 701596c000 offset: 12a1000 load_bias: 0 flags: 3 name: /system/lib64/libLLVM.so
-map: start: 701596c000 end: 701599f000 offset: 0 load_bias: 0 flags: 3 name: [anon:.bss]
-map: start: 70159c2000 end: 70159f9000 offset: 0 load_bias: 0 flags: 5 name: /system/lib64/libm.so
-map: start: 70159f9000 end: 70159fa000 offset: 36000 load_bias: 0 flags: 1 name: /system/lib64/libm.so
-map: start: 70159fa000 end: 70159fb000 offset: 37000 load_bias: 0 flags: 3 name: /system/lib64/libm.so
-map: start: 7015a1e000 end: 7015a2e000 offset: 0 load_bias: 0 flags: 5 name: /system/lib64/libbacktrace.so
-map: start: 7015a2e000 end: 7015a2f000 offset: f000 load_bias: 0 flags: 1 name: /system/lib64/libbacktrace.so
-map: start: 7015a2f000 end: 7015a30000 offset: 10000 load_bias: 0 flags: 3 name: /system/lib64/libbacktrace.so
-map: start: 7015a5e000 end: 7015a7d000 offset: 0 load_bias: 1000 flags: 5 name: /system/lib64/libutils.so
-map: start: 7015a7d000 end: 7015a7e000 offset: 0 load_bias: 0 flags: 0 name:
-map: start: 7015a7e000 end: 7015a7f000 offset: 1f000 load_bias: 0 flags: 1 name: /system/lib64/libutils.so
-map: start: 7015a7f000 end: 7015a80000 offset: 20000 load_bias: 0 flags: 3 name: /system/lib64/libutils.so
-map: start: 7015a99000 end: 7015b6d000 offset: 0 load_bias: 9000 flags: 5 name: /system/lib64/libc++.so
-map: start: 7015b6d000 end: 7015b6e000 offset: 0 load_bias: 0 flags: 0 name:
-map: start: 7015b6e000 end: 7015b76000 offset: d4000 load_bias: 0 flags: 1 name: /system/lib64/libc++.so
-map: start: 7015b76000 end: 7015b77000 offset: dc000 load_bias: 0 flags: 3 name: /system/lib64/libc++.so
-map: start: 7015b77000 end: 7015b7a000 offset: 0 load_bias: 0 flags: 3 name: [anon:.bss]
-map: start: 7015b81000 end: 7015b92000 offset: 0 load_bias: 0 flags: 5 name: /system/lib64/liblog.so
-map: start: 7015b92000 end: 7015b93000 offset: 10000 load_bias: 0 flags: 1 name: /system/lib64/liblog.so
-map: start: 7015b93000 end: 7015b94000 offset: 11000 load_bias: 0 flags: 3 name: /system/lib64/liblog.so
-map: start: 7015be3000 end: 7015ca3000 offset: 0 load_bias: 0 flags: 5 name: /system/lib64/libc.so
-map: start: 7015ca3000 end: 7015ca9000 offset: bf000 load_bias: 0 flags: 1 name: /system/lib64/libc.so
-map: start: 7015ca9000 end: 7015cab000 offset: c5000 load_bias: 0 flags: 3 name: /system/lib64/libc.so
-map: start: 7015cab000 end: 7015cac000 offset: 0 load_bias: 0 flags: 3 name: [anon:.bss]
-map: start: 7015cac000 end: 7015cad000 offset: 0 load_bias: 0 flags: 1 name: [anon:.bss]
-map: start: 7015cad000 end: 7015cb4000 offset: 0 load_bias: 0 flags: 3 name: [anon:.bss]
-map: start: 7015cf5000 end: 7015cf6000 offset: 0 load_bias: 0 flags: 5 name: /data/libbacktrace_test.so
-map: start: 7015cf6000 end: 7015cf7000 offset: 0 load_bias: 0 flags: 1 name: /data/libbacktrace_test.so
-map: start: 7015cf7000 end: 7015cf8000 offset: 1000 load_bias: 0 flags: 3 name: /data/libbacktrace_test.so
-map: start: 7015d1f000 end: 7015d39000 offset: 0 load_bias: 0 flags: 5 name: /system/lib64/libunwind.so
-map: start: 7015d39000 end: 7015d3a000 offset: 19000 load_bias: 0 flags: 1 name: /system/lib64/libunwind.so
-map: start: 7015d3a000 end: 7015d3b000 offset: 1a000 load_bias: 0 flags: 3 name: /system/lib64/libunwind.so
-map: start: 7015d3b000 end: 7015da4000 offset: 0 load_bias: 0 flags: 3 name: [anon:.bss]
-map: start: 7015de8000 end: 7015df7000 offset: 0 load_bias: 0 flags: 5 name: /system/lib64/libbase.so
-map: start: 7015df7000 end: 7015df8000 offset: 0 load_bias: 0 flags: 0 name:
-map: start: 7015df8000 end: 7015df9000 offset: f000 load_bias: 0 flags: 1 name: /system/lib64/libbase.so
-map: start: 7015df9000 end: 7015dfa000 offset: 10000 load_bias: 0 flags: 3 name: /system/lib64/libbase.so
-map: start: 7015e35000 end: 7015e36000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc]
-map: start: 7015e4f000 end: 7015e50000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_small_objects]
-map: start: 7015f11000 end: 7015f13000 offset: 0 load_bias: 0 flags: 5 name: /system/lib64/libnetd_client.so
-map: start: 7015f13000 end: 7015f14000 offset: 1000 load_bias: 0 flags: 1 name: /system/lib64/libnetd_client.so
-map: start: 7015f14000 end: 7015f15000 offset: 2000 load_bias: 0 flags: 3 name: /system/lib64/libnetd_client.so
-map: start: 7015f6c000 end: 7015f79000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: 7015f79000 end: 7015f99000 offset: 0 load_bias: 0 flags: 32769 name: /dev/__properties__/u:object_r:default_prop:s0
-map: start: 7015f99000 end: 7015f9a000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_vector]
-map: start: 7015f9a000 end: 7015f9b000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_small_objects]
-map: start: 7015fa6000 end: 7015fa7000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_vector]
-map: start: 7015fa8000 end: 7015fa9000 offset: 0 load_bias: 0 flags: 1 name: [anon:linker_alloc]
-map: start: 7015faf000 end: 7015fcf000 offset: 0 load_bias: 0 flags: 32769 name: /dev/__properties__/properties_serial
-map: start: 7015fcf000 end: 7015fd0000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_vector]
-map: start: 7015fd0000 end: 7015fd1000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_small_objects]
-map: start: 7015fd1000 end: 7015fd2000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_vector]
-map: start: 7015fd4000 end: 7015fd7000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: 7015fd7000 end: 7015fdb000 offset: 0 load_bias: 0 flags: 1 name: [anon:atexit handlers]
-map: start: 7015fdb000 end: 7015fdc000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc]
-map: start: 7015fdc000 end: 7015fdd000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: 7015fdd000 end: 7015fde000 offset: 0 load_bias: 0 flags: 1 name: [anon:linker_alloc]
-map: start: 7015fde000 end: 7015ffe000 offset: 0 load_bias: 0 flags: 32769 name: /dev/__properties__/u:object_r:debug_prop:s0
-map: start: 7015ffe000 end: 701601e000 offset: 0 load_bias: 0 flags: 32769 name: /dev/__properties__/properties_serial
-map: start: 701601e000 end: 701601f000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_vector]
-map: start: 701601f000 end: 7016020000 offset: 0 load_bias: 0 flags: 0 name:
-map: start: 7016020000 end: 7016021000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: 7016021000 end: 7016022000 offset: 0 load_bias: 0 flags: 0 name:
-map: start: 7016022000 end: 7016023000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_lob]
-map: start: 7016023000 end: 7016025000 offset: 0 load_bias: 0 flags: 1 name: [anon:linker_alloc]
-map: start: 7016025000 end: 7016026000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_small_objects]
-map: start: 7016026000 end: 7016027000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_vector]
-map: start: 7016027000 end: 7016028000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_small_objects]
-map: start: 7016028000 end: 7016029000 offset: 0 load_bias: 0 flags: 3 name: [anon:arc4random data]
-map: start: 7016029000 end: 701602a000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_small_objects]
-map: start: 701602a000 end: 701602b000 offset: 0 load_bias: 0 flags: 1 name: [anon:atexit handlers]
-map: start: 701602b000 end: 701602c000 offset: 0 load_bias: 0 flags: 0 name: [anon:thread signal stack guard page]
-map: start: 701602c000 end: 7016030000 offset: 0 load_bias: 0 flags: 3 name: [anon:thread signal stack]
-map: start: 7016030000 end: 7016031000 offset: 0 load_bias: 0 flags: 3 name: [anon:arc4random data]
-map: start: 7016031000 end: 7016033000 offset: 0 load_bias: 0 flags: 5 name: [vdso]
-map: start: 7016033000 end: 70160dd000 offset: 0 load_bias: 0 flags: 5 name: /system/bin/linker64
-map: start: 70160dd000 end: 70160e0000 offset: a9000 load_bias: 0 flags: 1 name: /system/bin/linker64
-map: start: 70160e0000 end: 70160e1000 offset: ac000 load_bias: 0 flags: 3 name: /system/bin/linker64
-map: start: 70160e1000 end: 70160e4000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: 70160e4000 end: 70160e5000 offset: 0 load_bias: 0 flags: 1 name:
-map: start: 70160e5000 end: 70160e8000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: 7fd8baf000 end: 7fd8be6000 offset: 0 load_bias: 0 flags: 3 name: [stack]
-ucontext: 464 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f838bed87f0000000e0000000000000015000000000000001c00000000000000ec59cf1570000000b863fd15700000005064fd15700000000000000000000000ec59cf15700000000200000000000000b863fd1570000000144abed87f0000006064fd15700000005064fd157000000000010000000000005826bed87f000000d86fcf15700000006057cf157000000000000000000000005064fd15700000005064fd15700000005064fd1570000000b67e00000000000040fd677055000000d064fd15700000000030fd157000000002000000000000000100000000000000fcb58a56000000000063fd15700000009857cf1570000000c062fd15700000001c5acf157000000000000000000000000000000000000000
-stack: start: 7015fd3000 end: 7015fd7000 size: 16384 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f838bed87f0000004038bed87f000000b863fd1570000000b863fd1570000000b863fd1570000000ec59cf15700000001c000000150000000e000000070000003063fd15700000001c58cf1570000000b863fd1570000000ec59cf1570000000100000000c00000008000000040000006063fd15700000007c58cf1570000000b863fd1570000000ec59cf1570000000080000000600000004000000020000009063fd1570000000dc58cf1570000000b863fd1570000000ec59cf157000000004000000030000000200000001000000d063fd1570000000c459cf15700000000100000000000000144abed87f0000004038bed87f0000004038bed87f000000144abed87f000000d3aec914588f4bcd1064fd157000000074fd6770550000004038bed87f0000004038bed87f000000ec84c41570000000e484c41570000000c484c4157000000000000000000000004064fd15700000004015c01570000000b67e0000000000000000000000000000705a0e1670000000185b0e167000000000000000000000000000000000000000705a0e16700000000000000000000000b77e0000b67e000000000000550000000030fd157000000050340000000000000010000000000000000000000000000000b222147000000000102a14700000000000000000000000000000000000000040fd6770550000004038bed87f000000000000000000000000a0fa1570000000010000000000000000000000000000000000000000000000e864fd15700000005064fd1570000000000000000000000000000000000000000000000000000000d3aec914588f4bcd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-function: start: 0 end: 7015cf5760 name: unknown_start
-function: start: 7015cf5760 end: 7015cf57cc name: test_level_four
-function: start: 7015cf57cc end: 7015cf582c name: test_level_three
-function: start: 7015cf582c end: 7015cf588c name: test_level_two
-function: start: 7015cf588c end: 7015cf58ec name: test_level_one
-function: start: 7015cf58ec end: 7015cf5968 name: test_recursive_call
-function: start: 7015cf5968 end: ffffffffffffffff name: test_get_context_and_wait
-function: start: ffffffffffffffff end: ffffffffffffffff name: unknown_end
diff --git a/libbacktrace/testdata/arm64/offline_testdata_for_eglSubDriverAndroid b/libbacktrace/testdata/arm64/offline_testdata_for_eglSubDriverAndroid
deleted file mode 100644
index 673e30e..0000000
--- a/libbacktrace/testdata/arm64/offline_testdata_for_eglSubDriverAndroid
+++ /dev/null
@@ -1,6 +0,0 @@
-pid: 12276 tid: 12303
-map: start: 7b8c01e000 end: 7b8c030000 offset: 0 load_bias: 0 flags: 5 name: /vendor/lib64/egl/eglSubDriverAndroid.so
-ucontext: 464 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004070158c7b00000000000000000000001070158c7b000000647f028c7b00000000000000000000000000000000000000
-stack: start: 7b8c157020 end: 7b8c157050 size: 48 00000000000000000000000000000000000000000000000000000000000000000000000000000000547e028c7b000000
-function: start: 9ed8 end: a1b0 name: EglAndroidWindowSurface::Initialize(EglAndroidConfig*, int const*)
-function: start: 9dcc end: 9ed8 name: EglAndroidWindowSurface::Create(ANativeWindow*, EglAndroidConfig*, EglAndroidWindowSurface**, int const*)
diff --git a/libbacktrace/testdata/arm64/offline_testdata_for_libskia b/libbacktrace/testdata/arm64/offline_testdata_for_libskia
deleted file mode 100644
index da820c0..0000000
--- a/libbacktrace/testdata/arm64/offline_testdata_for_libskia
+++ /dev/null
@@ -1,6 +0,0 @@
-pid: 32232 tid: 32233
-map: start: 7c24c80000 end: 7c25413000 offset: 0 load_bias: 5f000 flags: 5 name: /system/lib64/libskia.so
-ucontext: 464 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b04b158c7b0000000000000000000000504b158c7b0000000c9a18257c00000000000000000000000000000000000000
-stack: start: 7b8c154b80 end: 7b8c154bc0 size: 64 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ec43f2247c000000
-function: start: 568970 end: 568c08 name: SkScalerContext_FreeType::generateImage(SkGlyph const&)
-function: start: 30330c end: 3044b0 name: SkScalerContext::getImage(SkGlyph const&)
diff --git a/libbacktrace/testdata/x86/libbacktrace_test_debug_frame.so b/libbacktrace/testdata/x86/libbacktrace_test_debug_frame.so
deleted file mode 100755
index a6f3b29..0000000
--- a/libbacktrace/testdata/x86/libbacktrace_test_debug_frame.so
+++ /dev/null
Binary files differ
diff --git a/libbacktrace/testdata/x86/libbacktrace_test_gnu_debugdata.so b/libbacktrace/testdata/x86/libbacktrace_test_gnu_debugdata.so
deleted file mode 100755
index ea58dfb..0000000
--- a/libbacktrace/testdata/x86/libbacktrace_test_gnu_debugdata.so
+++ /dev/null
Binary files differ
diff --git a/libbacktrace/testdata/x86/offline_testdata b/libbacktrace/testdata/x86/offline_testdata
deleted file mode 100644
index 920b338..0000000
--- a/libbacktrace/testdata/x86/offline_testdata
+++ /dev/null
@@ -1,82 +0,0 @@
-pid: 34545 tid: 34546
-map: start: f705a000 end: f705c000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: f705c000 end: f707f000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib/liblzma.so
-map: start: f707f000 end: f7080000 offset: 22000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib/liblzma.so
-map: start: f7080000 end: f7081000 offset: 23000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib/liblzma.so
-map: start: f7081000 end: f7088000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: f7088000 end: f7230000 offset: 0 load_bias: 0 flags: 5 name: /lib/i386-linux-gnu/libc-2.19.so
-map: start: f7230000 end: f7231000 offset: 1a8000 load_bias: 0 flags: 0 name: /lib/i386-linux-gnu/libc-2.19.so
-map: start: f7231000 end: f7233000 offset: 1a8000 load_bias: 0 flags: 1 name: /lib/i386-linux-gnu/libc-2.19.so
-map: start: f7233000 end: f7234000 offset: 1aa000 load_bias: 0 flags: 3 name: /lib/i386-linux-gnu/libc-2.19.so
-map: start: f7234000 end: f7237000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: f7237000 end: f727b000 offset: 0 load_bias: 0 flags: 5 name: /lib/i386-linux-gnu/libm-2.19.so
-map: start: f727b000 end: f727c000 offset: 43000 load_bias: 0 flags: 1 name: /lib/i386-linux-gnu/libm-2.19.so
-map: start: f727c000 end: f727d000 offset: 44000 load_bias: 0 flags: 3 name: /lib/i386-linux-gnu/libm-2.19.so
-map: start: f727d000 end: f7299000 offset: 0 load_bias: 0 flags: 5 name: /lib/i386-linux-gnu/libgcc_s.so.1
-map: start: f7299000 end: f729a000 offset: 1b000 load_bias: 0 flags: 3 name: /lib/i386-linux-gnu/libgcc_s.so.1
-map: start: f729a000 end: f72b8000 offset: 0 load_bias: 0 flags: 5 name: /lib/i386-linux-gnu/libtinfo.so.5.9
-map: start: f72b8000 end: f72b9000 offset: 1e000 load_bias: 0 flags: 0 name: /lib/i386-linux-gnu/libtinfo.so.5.9
-map: start: f72b9000 end: f72bb000 offset: 1e000 load_bias: 0 flags: 1 name: /lib/i386-linux-gnu/libtinfo.so.5.9
-map: start: f72bb000 end: f72bc000 offset: 20000 load_bias: 0 flags: 3 name: /lib/i386-linux-gnu/libtinfo.so.5.9
-map: start: f72bc000 end: f72bd000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: f72bd000 end: f72e0000 offset: 0 load_bias: 0 flags: 5 name: /lib/i386-linux-gnu/libncurses.so.5.9
-map: start: f72e0000 end: f72e1000 offset: 22000 load_bias: 0 flags: 1 name: /lib/i386-linux-gnu/libncurses.so.5.9
-map: start: f72e1000 end: f72e2000 offset: 23000 load_bias: 0 flags: 3 name: /lib/i386-linux-gnu/libncurses.so.5.9
-map: start: f72e2000 end: f72e5000 offset: 0 load_bias: 0 flags: 5 name: /lib/i386-linux-gnu/libdl-2.19.so
-map: start: f72e5000 end: f72e6000 offset: 2000 load_bias: 0 flags: 1 name: /lib/i386-linux-gnu/libdl-2.19.so
-map: start: f72e6000 end: f72e7000 offset: 3000 load_bias: 0 flags: 3 name: /lib/i386-linux-gnu/libdl-2.19.so
-map: start: f72e7000 end: f72ee000 offset: 0 load_bias: 0 flags: 5 name: /lib/i386-linux-gnu/librt-2.19.so
-map: start: f72ee000 end: f72ef000 offset: 6000 load_bias: 0 flags: 1 name: /lib/i386-linux-gnu/librt-2.19.so
-map: start: f72ef000 end: f72f0000 offset: 7000 load_bias: 0 flags: 3 name: /lib/i386-linux-gnu/librt-2.19.so
-map: start: f72f0000 end: f7308000 offset: 0 load_bias: 0 flags: 5 name: /lib/i386-linux-gnu/libpthread-2.19.so
-map: start: f7308000 end: f7309000 offset: 18000 load_bias: 0 flags: 1 name: /lib/i386-linux-gnu/libpthread-2.19.so
-map: start: f7309000 end: f730a000 offset: 19000 load_bias: 0 flags: 3 name: /lib/i386-linux-gnu/libpthread-2.19.so
-map: start: f730a000 end: f730c000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: f732f000 end: f7331000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: f7331000 end: f7425000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libc++.so
-map: start: f7425000 end: f7426000 offset: f4000 load_bias: 0 flags: 0 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libc++.so
-map: start: f7426000 end: f742a000 offset: f4000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libc++.so
-map: start: f742a000 end: f742b000 offset: f8000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libc++.so
-map: start: f742b000 end: f742d000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: f742d000 end: f7446000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libunwind.so
-map: start: f7446000 end: f7447000 offset: 18000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libunwind.so
-map: start: f7447000 end: f7448000 offset: 19000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libunwind.so
-map: start: f7448000 end: f7457000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: f7457000 end: f745c000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib/liblog.so
-map: start: f745c000 end: f745d000 offset: 4000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib/liblog.so
-map: start: f745d000 end: f745e000 offset: 5000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib/liblog.so
-map: start: f745e000 end: f7467000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libcutils.so
-map: start: f7467000 end: f7468000 offset: 9000 load_bias: 0 flags: 0 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libcutils.so
-map: start: f7468000 end: f7469000 offset: 9000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libcutils.so
-map: start: f7469000 end: f746a000 offset: a000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libcutils.so
-map: start: f746a000 end: f7477000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbase.so
-map: start: f7477000 end: f7478000 offset: c000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbase.so
-map: start: f7478000 end: f7479000 offset: d000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbase.so
-map: start: f7479000 end: f7489000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbacktrace.so
-map: start: f7489000 end: f748a000 offset: f000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbacktrace.so
-map: start: f748a000 end: f748b000 offset: 10000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbacktrace.so
-map: start: f748b000 end: f748c000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: f748c000 end: f748d000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbacktrace_test.so
-map: start: f748d000 end: f748e000 offset: 0 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbacktrace_test.so
-map: start: f748e000 end: f748f000 offset: 1000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbacktrace_test.so
-map: start: f748f000 end: f7491000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: f7491000 end: f74b1000 offset: 0 load_bias: 0 flags: 5 name: /lib/i386-linux-gnu/ld-2.19.so
-map: start: f74b1000 end: f74b2000 offset: 1f000 load_bias: 0 flags: 1 name: /lib/i386-linux-gnu/ld-2.19.so
-map: start: f74b2000 end: f74b3000 offset: 20000 load_bias: 0 flags: 3 name: /lib/i386-linux-gnu/ld-2.19.so
-map: start: f74b3000 end: f77c6000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/nativetest/backtrace_test/backtrace_test32
-map: start: f77c6000 end: f77c7000 offset: 0 load_bias: ffffe000 flags: 5 name: [vdso]
-map: start: f77c7000 end: f77d4000 offset: 313000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/nativetest/backtrace_test/backtrace_test32
-map: start: f77d4000 end: f77d5000 offset: 320000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/nativetest/backtrace_test/backtrace_test32
-map: start: f77d5000 end: f77d6000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: f7ec6000 end: f7ee7000 offset: 0 load_bias: 0 flags: 3 name: [heap]
-map: start: ffe4e000 end: ffe70000 offset: 0 load_bias: 0 flags: 3 name: [stack]
-ucontext: 96 0000000000000000000000000000000000000000abdae6ff00000000afdae6ff78dae6ff150000001c000000b8f132f7a0f132f7d0df48f7a0ca48f728d9e6ff000000000000000000000000ceca48f7a8dae6ff000000000000000000000000
-stack: start: f732c000 end: f7330000 size: 16384 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009d9d49f761b009f71e382ff7000000000000000000000000000000000000000002000000f6372ff704c82bf70000000000204bf7f0a908f7ceca48f728d9e6fff4a449f70000000020f332f720f332f7d0df48f7f8f132f794c748f720f332f70c144205978142a8d4be08f7d0df48f720f332f7a0ca48f71c000000150000000e000000070000001c000000a0ca48f7d0df48f748f232f739c848f7070000000e000000150000001c000000a0ca48f720f332f70000000000000000d0df48f720f332f7a0ca48f7100000000c000000080000000400000010000000a0ca48f7d0df48f798f232f7c9c848f704000000080000000c00000010000000a0ca48f720f332f70000000000000000d0df48f720f332f7a0ca48f70800000006000000040000000200000008000000a0ca48f7d0df48f7e8f232f759c948f702000000040000000600000008000000a0ca48f720f332f70000000000000000d0df48f720f332f7a0ca48f7040000000300000002000000010000000046bdaa00000000d0df48f738f332f77cca48f701000000020000000300000004000000a0ca48f720f332f700000000f83b7df7696d4df7d0df48f788dae6ff28d9e6ff28d9e6ff88dae6ff58f332f70046bdaa40fb32f7f83b7df758f332f78d6d4df728d9e6ff88dae6fff83b7df728d9e6ff28d9e6ff009030f728f432f7726f2ff728d9e6ff40fb32f740fb32f740fb32f790f332f700000000000000000000000000000000000000000000000000000000009030f740fb32f7000f3d0028f432f703b12c75032f144e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a06e2ff700000000000f3d00000000008e3f17f740fb32f7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a03823f7c4fd32f700000000e0341df7e02e1df7e03d1df70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040fb32f7188eecf740fb32f70100000030647cf70046bdaa28658876000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060a705f7a4b130f7f2860000f1860000b0fb32f7ecffffff000000000000000090f332f7000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ccfb32f70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000c2638cfa7f3e1d0000000000000000000000000000000000406d4df728d9e6ff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c032f7004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-function: start: 0 end: f748c740 name: unknown_start
-function: start: f748c740 end: f748c7c0 name: test_level_four
-function: start: f748c7c0 end: f748c850 name: test_level_three
-function: start: f748c850 end: f748c8e0 name: test_level_two
-function: start: f748c8e0 end: f748c970 name: test_level_one
-function: start: f748c970 end: f748ca10 name: test_recursive_call
-function: start: f748ca10 end: ffffffff name: test_get_context_and_wait
-function: start: ffffffff end: ffffffff name: unknown_end
diff --git a/libbacktrace/testdata/x86_64/libbacktrace_test_eh_frame.so b/libbacktrace/testdata/x86_64/libbacktrace_test_eh_frame.so
deleted file mode 100755
index f116658..0000000
--- a/libbacktrace/testdata/x86_64/libbacktrace_test_eh_frame.so
+++ /dev/null
Binary files differ
diff --git a/libbacktrace/testdata/x86_64/offline_testdata b/libbacktrace/testdata/x86_64/offline_testdata
deleted file mode 100644
index c6bb241..0000000
--- a/libbacktrace/testdata/x86_64/offline_testdata
+++ /dev/null
@@ -1,93 +0,0 @@
-pid: 25683 tid: 25692
-map: start: 7fd5aa784000 end: 7fd5aa93e000 offset: 0 load_bias: 0 flags: 5 name: /lib/x86_64-linux-gnu/libc-2.19.so
-map: start: 7fd5aa93e000 end: 7fd5aab3e000 offset: 1ba000 load_bias: 0 flags: 0 name: /lib/x86_64-linux-gnu/libc-2.19.so
-map: start: 7fd5aab3e000 end: 7fd5aab42000 offset: 1ba000 load_bias: 0 flags: 1 name: /lib/x86_64-linux-gnu/libc-2.19.so
-map: start: 7fd5aab42000 end: 7fd5aab44000 offset: 1be000 load_bias: 0 flags: 3 name: /lib/x86_64-linux-gnu/libc-2.19.so
-map: start: 7fd5aab44000 end: 7fd5aab49000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: 7fd5aab49000 end: 7fd5aac4e000 offset: 0 load_bias: 0 flags: 5 name: /lib/x86_64-linux-gnu/libm-2.19.so
-map: start: 7fd5aac4e000 end: 7fd5aae4d000 offset: 105000 load_bias: 0 flags: 0 name: /lib/x86_64-linux-gnu/libm-2.19.so
-map: start: 7fd5aae4d000 end: 7fd5aae4e000 offset: 104000 load_bias: 0 flags: 1 name: /lib/x86_64-linux-gnu/libm-2.19.so
-map: start: 7fd5aae4e000 end: 7fd5aae4f000 offset: 105000 load_bias: 0 flags: 3 name: /lib/x86_64-linux-gnu/libm-2.19.so
-map: start: 7fd5aae4f000 end: 7fd5aae65000 offset: 0 load_bias: 0 flags: 5 name: /lib/x86_64-linux-gnu/libgcc_s.so.1
-map: start: 7fd5aae65000 end: 7fd5ab064000 offset: 16000 load_bias: 0 flags: 0 name: /lib/x86_64-linux-gnu/libgcc_s.so.1
-map: start: 7fd5ab064000 end: 7fd5ab065000 offset: 15000 load_bias: 0 flags: 3 name: /lib/x86_64-linux-gnu/libgcc_s.so.1
-map: start: 7fd5ab065000 end: 7fd5ab08a000 offset: 0 load_bias: 0 flags: 5 name: /lib/x86_64-linux-gnu/libtinfo.so.5.9
-map: start: 7fd5ab08a000 end: 7fd5ab289000 offset: 25000 load_bias: 0 flags: 0 name: /lib/x86_64-linux-gnu/libtinfo.so.5.9
-map: start: 7fd5ab289000 end: 7fd5ab28d000 offset: 24000 load_bias: 0 flags: 1 name: /lib/x86_64-linux-gnu/libtinfo.so.5.9
-map: start: 7fd5ab28d000 end: 7fd5ab28e000 offset: 28000 load_bias: 0 flags: 3 name: /lib/x86_64-linux-gnu/libtinfo.so.5.9
-map: start: 7fd5ab28e000 end: 7fd5ab2b0000 offset: 0 load_bias: 0 flags: 5 name: /lib/x86_64-linux-gnu/libncurses.so.5.9
-map: start: 7fd5ab2b0000 end: 7fd5ab4af000 offset: 22000 load_bias: 0 flags: 0 name: /lib/x86_64-linux-gnu/libncurses.so.5.9
-map: start: 7fd5ab4af000 end: 7fd5ab4b0000 offset: 21000 load_bias: 0 flags: 1 name: /lib/x86_64-linux-gnu/libncurses.so.5.9
-map: start: 7fd5ab4b0000 end: 7fd5ab4b1000 offset: 22000 load_bias: 0 flags: 3 name: /lib/x86_64-linux-gnu/libncurses.so.5.9
-map: start: 7fd5ab4b1000 end: 7fd5ab4b4000 offset: 0 load_bias: 0 flags: 5 name: /lib/x86_64-linux-gnu/libdl-2.19.so
-map: start: 7fd5ab4b4000 end: 7fd5ab6b3000 offset: 3000 load_bias: 0 flags: 0 name: /lib/x86_64-linux-gnu/libdl-2.19.so
-map: start: 7fd5ab6b3000 end: 7fd5ab6b4000 offset: 2000 load_bias: 0 flags: 1 name: /lib/x86_64-linux-gnu/libdl-2.19.so
-map: start: 7fd5ab6b4000 end: 7fd5ab6b5000 offset: 3000 load_bias: 0 flags: 3 name: /lib/x86_64-linux-gnu/libdl-2.19.so
-map: start: 7fd5ab6b5000 end: 7fd5ab6bc000 offset: 0 load_bias: 0 flags: 5 name: /lib/x86_64-linux-gnu/librt-2.19.so
-map: start: 7fd5ab6bc000 end: 7fd5ab8bb000 offset: 7000 load_bias: 0 flags: 0 name: /lib/x86_64-linux-gnu/librt-2.19.so
-map: start: 7fd5ab8bb000 end: 7fd5ab8bc000 offset: 6000 load_bias: 0 flags: 1 name: /lib/x86_64-linux-gnu/librt-2.19.so
-map: start: 7fd5ab8bc000 end: 7fd5ab8bd000 offset: 7000 load_bias: 0 flags: 3 name: /lib/x86_64-linux-gnu/librt-2.19.so
-map: start: 7fd5ab8bd000 end: 7fd5ab8d6000 offset: 0 load_bias: 0 flags: 5 name: /lib/x86_64-linux-gnu/libpthread-2.19.so
-map: start: 7fd5ab8d6000 end: 7fd5abad5000 offset: 19000 load_bias: 0 flags: 0 name: /lib/x86_64-linux-gnu/libpthread-2.19.so
-map: start: 7fd5abad5000 end: 7fd5abad6000 offset: 18000 load_bias: 0 flags: 1 name: /lib/x86_64-linux-gnu/libpthread-2.19.so
-map: start: 7fd5abad6000 end: 7fd5abad7000 offset: 19000 load_bias: 0 flags: 3 name: /lib/x86_64-linux-gnu/libpthread-2.19.so
-map: start: 7fd5abad7000 end: 7fd5abadb000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: 7fd5abadb000 end: 7fd5abafe000 offset: 0 load_bias: 0 flags: 5 name: /lib/x86_64-linux-gnu/ld-2.19.so
-map: start: 7fd5abb17000 end: 7fd5abb1a000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: 7fd5abb1a000 end: 7fd5abb40000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/liblzma.so
-map: start: 7fd5abb40000 end: 7fd5abb41000 offset: 25000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/liblzma.so
-map: start: 7fd5abb41000 end: 7fd5abb42000 offset: 26000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/liblzma.so
-map: start: 7fd5abb42000 end: 7fd5abb4b000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: 7fd5abb6a000 end: 7fd5abb70000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: 7fd5abb70000 end: 7fd5abc62000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libc++.so
-map: start: 7fd5abc62000 end: 7fd5abc63000 offset: f2000 load_bias: 0 flags: 0 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libc++.so
-map: start: 7fd5abc63000 end: 7fd5abc6b000 offset: f2000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libc++.so
-map: start: 7fd5abc6b000 end: 7fd5abc6c000 offset: fa000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libc++.so
-map: start: 7fd5abc6c000 end: 7fd5abc70000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: 7fd5abc70000 end: 7fd5abc8d000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libunwind.so
-map: start: 7fd5abc8d000 end: 7fd5abc8e000 offset: 1c000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libunwind.so
-map: start: 7fd5abc8e000 end: 7fd5abc8f000 offset: 1d000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libunwind.so
-map: start: 7fd5abc8f000 end: 7fd5abcb8000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: 7fd5abcb8000 end: 7fd5abcbe000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/liblog.so
-map: start: 7fd5abcbe000 end: 7fd5abcbf000 offset: 6000 load_bias: 0 flags: 0 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/liblog.so
-map: start: 7fd5abcbf000 end: 7fd5abcc0000 offset: 6000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/liblog.so
-map: start: 7fd5abcc0000 end: 7fd5abcc1000 offset: 7000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/liblog.so
-map: start: 7fd5abcc1000 end: 7fd5abcc2000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: 7fd5abcc2000 end: 7fd5abccd000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libcutils.so
-map: start: 7fd5abccd000 end: 7fd5abcce000 offset: b000 load_bias: 0 flags: 0 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libcutils.so
-map: start: 7fd5abcce000 end: 7fd5abccf000 offset: b000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libcutils.so
-map: start: 7fd5abccf000 end: 7fd5abcd0000 offset: c000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libcutils.so
-map: start: 7fd5abcd0000 end: 7fd5abcdf000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbase.so
-map: start: 7fd5abcdf000 end: 7fd5abce0000 offset: f000 load_bias: 0 flags: 0 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbase.so
-map: start: 7fd5abce0000 end: 7fd5abce1000 offset: f000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbase.so
-map: start: 7fd5abce1000 end: 7fd5abce2000 offset: 10000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbase.so
-map: start: 7fd5abce2000 end: 7fd5abcf5000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbacktrace.so
-map: start: 7fd5abcf5000 end: 7fd5abcf6000 offset: 12000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbacktrace.so
-map: start: 7fd5abcf6000 end: 7fd5abcf7000 offset: 13000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbacktrace.so
-map: start: 7fd5abcf7000 end: 7fd5abcf8000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbacktrace_test.so
-map: start: 7fd5abcf8000 end: 7fd5abcf9000 offset: 1000 load_bias: 0 flags: 0 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbacktrace_test.so
-map: start: 7fd5abcf9000 end: 7fd5abcfa000 offset: 1000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbacktrace_test.so
-map: start: 7fd5abcfa000 end: 7fd5abcfb000 offset: 2000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbacktrace_test.so
-map: start: 7fd5abcfb000 end: 7fd5abcfd000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: 7fd5abcfd000 end: 7fd5abcfe000 offset: 22000 load_bias: 0 flags: 1 name: /lib/x86_64-linux-gnu/ld-2.19.so
-map: start: 7fd5abcfe000 end: 7fd5abcff000 offset: 23000 load_bias: 0 flags: 3 name: /lib/x86_64-linux-gnu/ld-2.19.so
-map: start: 7fd5abcff000 end: 7fd5abd00000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: 7fd5abd00000 end: 7fd5ac053000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/nativetest64/backtrace_test/backtrace_test64
-map: start: 7fd5ac053000 end: 7fd5ac054000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: 7fd5ac054000 end: 7fd5ac06f000 offset: 353000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/nativetest64/backtrace_test/backtrace_test64
-map: start: 7fd5ac06f000 end: 7fd5ac070000 offset: 36e000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/nativetest64/backtrace_test/backtrace_test64
-map: start: 7fd5ac070000 end: 7fd5ac071000 offset: 0 load_bias: 0 flags: 3 name:
-map: start: 7fd5ad54e000 end: 7fd5ad56f000 offset: 0 load_bias: 0 flags: 3 name: [heap]
-map: start: 7ffcf47ed000 end: 7ffcf480f000 offset: 0 load_bias: 0 flags: 3 name: [stack]
-map: start: 7ffcf48d5000 end: 7ffcf48d7000 offset: 0 load_bias: ffffffffff700000 flags: 5 name: [vdso]
-map: start: ffffffffff600000 end: ffffffffff601000 offset: 0 load_bias: 0 flags: 5 name: [vsyscall]
-ucontext: 224 00000000000000000000000000000000000000000000000000000000000000000000000000000000b07bcfabd57f000098deb6abd57f0000b82455add57f0000010000000000000000000000000000000000000000000000c0e354add57f000000e7b6abd57f0000c8b080f4fc7f00000e0000000000000080ddb6abd57f000000000000000000001500000000000000b07bcfabd57f00001c0000000000000060ddb6abd57f0000d07bcfabd57f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-stack: start: 7fd5abb6b000 end: 7fd5abb6f000 size: 16384 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c4eaeabd57f00000000000000000000978142a8000000000f0000000000000012000000000000003888b4abd57f0000e657aeabd57f00000000000000000000a0dcb6abd57f0000307d78aad57f0000b0ddb6abd57f000028d978aad57f0000060aa10200000000a0ddb6abd57f0000000000000000000000000000000000002091b1abd57f0000e094b4abd57f000017008cabd57f0000c84d79aad57f000028e28babd57f00000000000005000000d503000001000000000000000000000068deb6abd57f000040deb6abd57f00002091b1abd57f00000100000000000000e0f3c6abd57f000088f0c6abd57f00006159aeabd57f000000000000000000002091b1abd57f000005000000000000000000000000000000010000000000000088f0c6abd57f00000000000000000000d07bcfabd57f00000000000000000000000000000000000098deb6abd57f000098deb6abd57f0000b0ddb6abd57f00006179cfabd57f000098deb6abd57f0000b07bcfabd57f00001c000000150000000e00000007000000f0ddb6abd57f0000e179cfabd57f00000000000000000000150000001c00000098deb6abd57f0000b07bcfabd57f0000100000000c000000080000000400000030deb6abd57f0000417acfabd57f000000000000000000000c0000001000000098deb6abd57f0000b07bcfabd57f00000800000006000000040000000200000070deb6abd57f0000a17acfabd57f00000000000000000000060000000800000098deb6abd57f0000b07bcfabd57f000004000000030000000200000001000000b0deb6abd57f0000817bcfabd57f0000000000000000000074b480f4fc7f0000c8b080f4fc7f0000c8b080f4fc7f000074b480f4fc7f000000006a80f3f73cf1d0deb6abd57f00002a52d5abd57f0000c8b080f4fc7f0000c8b080f4fc7f0000000000000000000084518cabd57f0000000000000000000000e7b6abd57f000000e7b6abd57f00008f990b1e3bad5a6700000000000000000000000000000000c0e354add57f000000e7b6abd57f00008f99cba356faf1988f9991bc23faf1980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e7b6abd57f00007de387aad57f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006030b4aad57f0000b8edb6abd57f00000000000000000000000000000000000080b88eaad57f0000000000000000000080b28eaad57f0000000000000000000080c18eaad57f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e7b6abd57f0000402555add57f000000e7b6abd57f00000100000000000000000000000000000000006a80f3f73cf1058f9d56adb3c7cc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000407ab1abd57f000030a3adabd57f00005c64000053640000e0e9b6abd57f0000e0e9b6abd57f0000e0ffffffffffffff00000000000000000000000000000000f0deb6abd57f00000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010eab6abd57f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000c46ad90f52391d00000000000000000000000000000000000000000000000000f051d5abd57f0000c8b080f4fc7f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b0b6abd57f000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-function: start: 0 end: 7fd5abcf7930 name: unknown_start
-function: start: 7fd5abcf7930 end: 7fd5abcf7990 name: test_level_four
-function: start: 7fd5abcf7990 end: 7fd5abcf79f0 name: test_level_three
-function: start: 7fd5abcf79f0 end: 7fd5abcf7a50 name: test_level_two
-function: start: 7fd5abcf7a50 end: 7fd5abcf7ab0 name: test_level_one
-function: start: 7fd5abcf7ab0 end: 7fd5abcf7b30 name: test_recursive_call
-function: start: 7fd5abcf7b30 end: ffffffffffffffff name: test_get_context_and_wait
-function: start: ffffffffffffffff end: ffffffffffffffff name: unknown_end
diff --git a/libprocinfo b/libprocinfo
new file mode 120000
index 0000000..dec8cf8
--- /dev/null
+++ b/libprocinfo
@@ -0,0 +1 @@
+../libprocinfo
\ No newline at end of file
diff --git a/libprocinfo/.clang-format b/libprocinfo/.clang-format
deleted file mode 120000
index fd0645f..0000000
--- a/libprocinfo/.clang-format
+++ /dev/null
@@ -1 +0,0 @@
-../.clang-format-2
\ No newline at end of file
diff --git a/libprocinfo/Android.bp b/libprocinfo/Android.bp
deleted file mode 100644
index ae45742..0000000
--- a/libprocinfo/Android.bp
+++ /dev/null
@@ -1,131 +0,0 @@
-//
-// Copyright (C) 2015 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.
-//
-
-cc_defaults {
- name: "libprocinfo_defaults",
- cflags: [
- "-Wall",
- "-Werror",
- "-Wextra",
- ],
-}
-
-cc_library {
- name: "libprocinfo",
- defaults: ["libprocinfo_defaults"],
- vendor_available: true,
- // TODO(b/153609531): remove when no longer needed.
- native_bridge_supported: true,
- recovery_available: true,
- vndk: {
- enabled: true,
- },
- host_supported: true,
- srcs: [
- "process.cpp",
- "process_map.cpp",
- ],
-
- local_include_dirs: ["include"],
- export_include_dirs: ["include"],
- shared_libs: ["libbase"],
- target: {
- darwin: {
- enabled: false,
- },
- linux_bionic: {
- enabled: true,
- },
- windows: {
- enabled: false,
- },
- },
-
- apex_available: [
- "//apex_available:platform",
- "com.android.art.debug",
- "com.android.art.release",
- ],
-}
-
-// Tests
-// ------------------------------------------------------------------------------
-cc_test {
- name: "libprocinfo_test",
- defaults: ["libprocinfo_defaults"],
- host_supported: true,
- isolated: true,
- srcs: [
- "process_test.cpp",
- "process_map_test.cpp",
- ],
- target: {
- darwin: {
- enabled: false,
- },
- windows: {
- enabled: false,
- },
- },
-
- shared_libs: [
- "libbase",
- "libprocinfo",
- ],
-
- compile_multilib: "both",
- multilib: {
- lib32: {
- suffix: "32",
- },
- lib64: {
- suffix: "64",
- },
- },
-
- data: [
- "testdata/*",
- ],
-
- test_suites: ["device-tests"],
-}
-
-cc_benchmark {
- name: "libprocinfo_benchmark",
- defaults: ["libprocinfo_defaults"],
- srcs: [
- "process_map_benchmark.cpp",
- ],
- shared_libs: [
- "libbacktrace",
- "libbase",
- "libprocinfo",
- "libunwindstack",
- ],
- compile_multilib: "both",
- multilib: {
- lib32: {
- suffix: "32",
- },
- lib64: {
- suffix: "64",
- },
- },
-
- data: [
- "testdata/*",
- ],
-}
diff --git a/libprocinfo/OWNERS b/libprocinfo/OWNERS
deleted file mode 100644
index a70cc57..0000000
--- a/libprocinfo/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-jmgao@google.com
diff --git a/libprocinfo/include/procinfo/process.h b/libprocinfo/include/procinfo/process.h
deleted file mode 100644
index 9278e18..0000000
--- a/libprocinfo/include/procinfo/process.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2016 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 <dirent.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <memory>
-#include <string>
-#include <type_traits>
-
-#include <android-base/logging.h>
-#include <android-base/parseint.h>
-#include <android-base/unique_fd.h>
-
-namespace android {
-namespace procinfo {
-
-#if defined(__linux__)
-
-enum ProcessState {
- kProcessStateUnknown,
- kProcessStateRunning,
- kProcessStateSleeping,
- kProcessStateUninterruptibleWait,
- kProcessStateStopped,
- kProcessStateZombie,
-};
-
-struct ProcessInfo {
- std::string name;
- ProcessState state;
- pid_t tid;
- pid_t pid;
- pid_t ppid;
- pid_t tracer;
- uid_t uid;
- uid_t gid;
-};
-
-// Parse the contents of /proc/<tid>/status into |process_info|.
-bool GetProcessInfo(pid_t tid, ProcessInfo* process_info, std::string* error = nullptr);
-
-// Parse the contents of <fd>/status into |process_info|.
-// |fd| should be an fd pointing at a /proc/<pid> directory.
-bool GetProcessInfoFromProcPidFd(int fd, ProcessInfo* process_info, std::string* error = nullptr);
-
-// Fetch the list of threads from a given process's /proc/<pid> directory.
-// |fd| should be an fd pointing at a /proc/<pid> directory.
-template <typename Collection>
-auto GetProcessTidsFromProcPidFd(int fd, Collection* out, std::string* error = nullptr) ->
- typename std::enable_if<sizeof(typename Collection::value_type) >= sizeof(pid_t), bool>::type {
- out->clear();
-
- int task_fd = openat(fd, "task", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
- std::unique_ptr<DIR, int (*)(DIR*)> dir(fdopendir(task_fd), closedir);
- if (!dir) {
- if (error != nullptr) {
- *error = "failed to open task directory";
- }
- return false;
- }
-
- struct dirent* dent;
- while ((dent = readdir(dir.get()))) {
- if (strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0) {
- pid_t tid;
- if (!android::base::ParseInt(dent->d_name, &tid, 1, std::numeric_limits<pid_t>::max())) {
- if (error != nullptr) {
- *error = std::string("failed to parse task id: ") + dent->d_name;
- }
- return false;
- }
-
- out->insert(out->end(), tid);
- }
- }
-
- return true;
-}
-
-template <typename Collection>
-auto GetProcessTids(pid_t pid, Collection* out, std::string* error = nullptr) ->
- typename std::enable_if<sizeof(typename Collection::value_type) >= sizeof(pid_t), bool>::type {
- char task_path[PATH_MAX];
- if (snprintf(task_path, PATH_MAX, "/proc/%d", pid) >= PATH_MAX) {
- if (error != nullptr) {
- *error = "task path overflow (pid = " + std::to_string(pid) + ")";
- }
- return false;
- }
-
- android::base::unique_fd fd(open(task_path, O_DIRECTORY | O_RDONLY | O_CLOEXEC));
- if (fd == -1) {
- if (error != nullptr) {
- *error = std::string("failed to open ") + task_path;
- }
- return false;
- }
-
- return GetProcessTidsFromProcPidFd(fd.get(), out, error);
-}
-
-#endif
-
-} /* namespace procinfo */
-} /* namespace android */
diff --git a/libprocinfo/include/procinfo/process_map.h b/libprocinfo/include/procinfo/process_map.h
deleted file mode 100644
index 569a022..0000000
--- a/libprocinfo/include/procinfo/process_map.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2018 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 <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-
-#include <functional>
-#include <string>
-#include <vector>
-
-#include <android-base/file.h>
-
-namespace android {
-namespace procinfo {
-
-template <class CallbackType>
-bool ReadMapFileContent(char* content, const CallbackType& callback) {
- uint64_t start_addr;
- uint64_t end_addr;
- uint16_t flags;
- uint64_t pgoff;
- ino_t inode;
- char* next_line = content;
- char* p;
-
- auto pass_space = [&]() {
- if (*p != ' ') {
- return false;
- }
- while (*p == ' ') {
- p++;
- }
- return true;
- };
-
- auto pass_xdigit = [&]() {
- if (!isxdigit(*p)) {
- return false;
- }
- do {
- p++;
- } while (isxdigit(*p));
- return true;
- };
-
- while (next_line != nullptr && *next_line != '\0') {
- p = next_line;
- next_line = strchr(next_line, '\n');
- if (next_line != nullptr) {
- *next_line = '\0';
- next_line++;
- }
- // Parse line like: 00400000-00409000 r-xp 00000000 fc:00 426998 /usr/lib/gvfs/gvfsd-http
- char* end;
- // start_addr
- start_addr = strtoull(p, &end, 16);
- if (end == p || *end != '-') {
- return false;
- }
- p = end + 1;
- // end_addr
- end_addr = strtoull(p, &end, 16);
- if (end == p) {
- return false;
- }
- p = end;
- if (!pass_space()) {
- return false;
- }
- // flags
- flags = 0;
- if (*p == 'r') {
- flags |= PROT_READ;
- } else if (*p != '-') {
- return false;
- }
- p++;
- if (*p == 'w') {
- flags |= PROT_WRITE;
- } else if (*p != '-') {
- return false;
- }
- p++;
- if (*p == 'x') {
- flags |= PROT_EXEC;
- } else if (*p != '-') {
- return false;
- }
- p++;
- if (*p != 'p' && *p != 's') {
- return false;
- }
- p++;
- if (!pass_space()) {
- return false;
- }
- // pgoff
- pgoff = strtoull(p, &end, 16);
- if (end == p) {
- return false;
- }
- p = end;
- if (!pass_space()) {
- return false;
- }
- // major:minor
- if (!pass_xdigit() || *p++ != ':' || !pass_xdigit() || !pass_space()) {
- return false;
- }
- // inode
- inode = strtoull(p, &end, 10);
- if (end == p) {
- return false;
- }
- p = end;
-
- if (*p != '\0' && !pass_space()) {
- return false;
- }
-
- // filename
- callback(start_addr, end_addr, flags, pgoff, inode, p);
- }
- return true;
-}
-
-inline bool ReadMapFile(const std::string& map_file,
- const std::function<void(uint64_t, uint64_t, uint16_t, uint64_t, ino_t,
- const char*)>& callback) {
- std::string content;
- if (!android::base::ReadFileToString(map_file, &content)) {
- return false;
- }
- return ReadMapFileContent(&content[0], callback);
-}
-
-inline bool ReadProcessMaps(pid_t pid,
- const std::function<void(uint64_t, uint64_t, uint16_t, uint64_t, ino_t,
- const char*)>& callback) {
- return ReadMapFile("/proc/" + std::to_string(pid) + "/maps", callback);
-}
-
-struct MapInfo {
- uint64_t start;
- uint64_t end;
- uint16_t flags;
- uint64_t pgoff;
- ino_t inode;
- std::string name;
-
- MapInfo(uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t inode,
- const char* name)
- : start(start), end(end), flags(flags), pgoff(pgoff), inode(inode), name(name) {}
-};
-
-inline bool ReadProcessMaps(pid_t pid, std::vector<MapInfo>* maps) {
- return ReadProcessMaps(
- pid, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t inode,
- const char* name) { maps->emplace_back(start, end, flags, pgoff, inode, name); });
-}
-
-bool ReadMapFileAsyncSafe(const char* map_file, void* buffer, size_t buffer_size,
- const std::function<void(uint64_t, uint64_t, uint16_t, uint64_t, ino_t,
- const char*)>& callback);
-
-} /* namespace procinfo */
-} /* namespace android */
diff --git a/libprocinfo/process.cpp b/libprocinfo/process.cpp
deleted file mode 100644
index 2efd49c..0000000
--- a/libprocinfo/process.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2016 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 <procinfo/process.h>
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <string>
-
-#include <android-base/unique_fd.h>
-
-using android::base::unique_fd;
-
-namespace android {
-namespace procinfo {
-
-bool GetProcessInfo(pid_t tid, ProcessInfo* process_info, std::string* error) {
- char path[PATH_MAX];
- snprintf(path, sizeof(path), "/proc/%d", tid);
-
- unique_fd dirfd(open(path, O_DIRECTORY | O_RDONLY));
- if (dirfd == -1) {
- if (error != nullptr) {
- *error = std::string("failed to open ") + path;
- }
- return false;
- }
-
- return GetProcessInfoFromProcPidFd(dirfd.get(), process_info, error);
-}
-
-static ProcessState parse_state(const char* state) {
- switch (*state) {
- case 'R':
- return kProcessStateRunning;
- case 'S':
- return kProcessStateSleeping;
- case 'D':
- return kProcessStateUninterruptibleWait;
- case 'T':
- return kProcessStateStopped;
- case 'Z':
- return kProcessStateZombie;
- default:
- return kProcessStateUnknown;
- }
-}
-
-bool GetProcessInfoFromProcPidFd(int fd, ProcessInfo* process_info, std::string* error) {
- int status_fd = openat(fd, "status", O_RDONLY | O_CLOEXEC);
-
- if (status_fd == -1) {
- if (error != nullptr) {
- *error = "failed to open status fd in GetProcessInfoFromProcPidFd";
- }
- return false;
- }
-
- std::unique_ptr<FILE, decltype(&fclose)> fp(fdopen(status_fd, "r"), fclose);
- if (!fp) {
- if (error != nullptr) {
- *error = "failed to open status file in GetProcessInfoFromProcPidFd";
- }
- close(status_fd);
- return false;
- }
-
- int field_bitmap = 0;
- static constexpr int finished_bitmap = 255;
- char* line = nullptr;
- size_t len = 0;
-
- while (getline(&line, &len, fp.get()) != -1 && field_bitmap != finished_bitmap) {
- char* tab = strchr(line, '\t');
- if (tab == nullptr) {
- continue;
- }
-
- size_t header_len = tab - line;
- std::string header = std::string(line, header_len);
- if (header == "Name:") {
- std::string name = line + header_len + 1;
-
- // line includes the trailing newline.
- name.pop_back();
- process_info->name = std::move(name);
-
- field_bitmap |= 1;
- } else if (header == "Pid:") {
- process_info->tid = atoi(tab + 1);
- field_bitmap |= 2;
- } else if (header == "Tgid:") {
- process_info->pid = atoi(tab + 1);
- field_bitmap |= 4;
- } else if (header == "PPid:") {
- process_info->ppid = atoi(tab + 1);
- field_bitmap |= 8;
- } else if (header == "TracerPid:") {
- process_info->tracer = atoi(tab + 1);
- field_bitmap |= 16;
- } else if (header == "Uid:") {
- process_info->uid = atoi(tab + 1);
- field_bitmap |= 32;
- } else if (header == "Gid:") {
- process_info->gid = atoi(tab + 1);
- field_bitmap |= 64;
- } else if (header == "State:") {
- process_info->state = parse_state(tab + 1);
- field_bitmap |= 128;
- }
- }
-
- free(line);
- return field_bitmap == finished_bitmap;
-}
-
-} /* namespace procinfo */
-} /* namespace android */
diff --git a/libprocinfo/process_map.cpp b/libprocinfo/process_map.cpp
deleted file mode 100644
index 5e240b9..0000000
--- a/libprocinfo/process_map.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2019 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 <procinfo/process_map.h>
-
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <procinfo/process.h>
-
-namespace android {
-namespace procinfo {
-
-bool ReadMapFileAsyncSafe(const char* map_file, void* buffer, size_t buffer_size,
- const std::function<void(uint64_t, uint64_t, uint16_t, uint64_t, ino_t,
- const char*)>& callback) {
- if (buffer == nullptr || buffer_size == 0) {
- return false;
- }
-
- int fd = open(map_file, O_RDONLY | O_CLOEXEC);
- if (fd == -1) {
- return false;
- }
-
- char* char_buffer = reinterpret_cast<char*>(buffer);
- size_t start = 0;
- size_t read_bytes = 0;
- char* line = nullptr;
- bool read_complete = false;
- while (true) {
- ssize_t bytes =
- TEMP_FAILURE_RETRY(read(fd, char_buffer + read_bytes, buffer_size - read_bytes - 1));
- if (bytes <= 0) {
- if (read_bytes == 0) {
- close(fd);
- return bytes == 0;
- }
- // Treat the last piece of data as the last line.
- char_buffer[start + read_bytes] = '\n';
- bytes = 1;
- read_complete = true;
- }
- read_bytes += bytes;
-
- while (read_bytes > 0) {
- char* newline = reinterpret_cast<char*>(memchr(&char_buffer[start], '\n', read_bytes));
- if (newline == nullptr) {
- break;
- }
- *newline = '\0';
- line = &char_buffer[start];
- start = newline - char_buffer + 1;
- read_bytes -= newline - line + 1;
-
- // Ignore the return code, errors are okay.
- ReadMapFileContent(line, callback);
- }
-
- if (read_complete) {
- close(fd);
- return true;
- }
-
- if (start == 0 && read_bytes == buffer_size - 1) {
- // The buffer provided is too small to contain this line, give up
- // and indicate failure.
- close(fd);
- return false;
- }
-
- // Copy any leftover data to the front of the buffer.
- if (start > 0) {
- if (read_bytes > 0) {
- memmove(char_buffer, &char_buffer[start], read_bytes);
- }
- start = 0;
- }
- }
-}
-
-} /* namespace procinfo */
-} /* namespace android */
diff --git a/libprocinfo/process_map_benchmark.cpp b/libprocinfo/process_map_benchmark.cpp
deleted file mode 100644
index eba4fd0..0000000
--- a/libprocinfo/process_map_benchmark.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2018 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 <procinfo/process_map.h>
-
-#include <string.h>
-#include <sys/types.h>
-
-#include <string>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <backtrace/BacktraceMap.h>
-#include <unwindstack/Maps.h>
-
-#include <benchmark/benchmark.h>
-
-static void BM_ReadMapFile(benchmark::State& state) {
- std::string map_file = android::base::GetExecutableDirectory() + "/testdata/maps";
- for (auto _ : state) {
- std::vector<android::procinfo::MapInfo> maps;
- android::procinfo::ReadMapFile(map_file, [&](uint64_t start, uint64_t end, uint16_t flags,
- uint64_t pgoff, ino_t inode, const char* name) {
- maps.emplace_back(start, end, flags, pgoff, inode, name);
- });
- CHECK_EQ(maps.size(), 2043u);
- }
-}
-BENCHMARK(BM_ReadMapFile);
-
-static void BM_unwindstack_FileMaps(benchmark::State& state) {
- std::string map_file = android::base::GetExecutableDirectory() + "/testdata/maps";
- for (auto _ : state) {
- unwindstack::FileMaps maps(map_file);
- maps.Parse();
- CHECK_EQ(maps.Total(), 2043u);
- }
-}
-BENCHMARK(BM_unwindstack_FileMaps);
-
-static void BM_unwindstack_BufferMaps(benchmark::State& state) {
- std::string map_file = android::base::GetExecutableDirectory() + "/testdata/maps";
- std::string content;
- CHECK(android::base::ReadFileToString(map_file, &content));
- for (auto _ : state) {
- unwindstack::BufferMaps maps(content.c_str());
- maps.Parse();
- CHECK_EQ(maps.Total(), 2043u);
- }
-}
-BENCHMARK(BM_unwindstack_BufferMaps);
-
-static void BM_backtrace_BacktraceMap(benchmark::State& state) {
- pid_t pid = getpid();
- for (auto _ : state) {
- BacktraceMap* map = BacktraceMap::Create(pid, true);
- CHECK(map != nullptr);
- delete map;
- }
-}
-BENCHMARK(BM_backtrace_BacktraceMap);
-
-BENCHMARK_MAIN();
diff --git a/libprocinfo/process_map_test.cpp b/libprocinfo/process_map_test.cpp
deleted file mode 100644
index b1bdc08..0000000
--- a/libprocinfo/process_map_test.cpp
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Copyright (C) 2018 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 <procinfo/process_map.h>
-
-#include <inttypes.h>
-#include <sys/mman.h>
-
-#include <string>
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/stringprintf.h>
-
-#include <gtest/gtest.h>
-
-TEST(process_map, ReadMapFile) {
- std::string map_file = android::base::GetExecutableDirectory() + "/testdata/maps";
- std::vector<android::procinfo::MapInfo> maps;
- ASSERT_TRUE(android::procinfo::ReadMapFile(
- map_file,
- [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t inode,
- const char* name) { maps.emplace_back(start, end, flags, pgoff, inode, name); }));
- ASSERT_EQ(2043u, maps.size());
- ASSERT_EQ(maps[0].start, 0x12c00000ULL);
- ASSERT_EQ(maps[0].end, 0x2ac00000ULL);
- ASSERT_EQ(maps[0].flags, PROT_READ | PROT_WRITE);
- ASSERT_EQ(maps[0].pgoff, 0ULL);
- ASSERT_EQ(maps[0].inode, 10267643UL);
- ASSERT_EQ(maps[0].name, "[anon:dalvik-main space (region space)]");
- ASSERT_EQ(maps[876].start, 0x70e6c4f000ULL);
- ASSERT_EQ(maps[876].end, 0x70e6c6b000ULL);
- ASSERT_EQ(maps[876].flags, PROT_READ | PROT_EXEC);
- ASSERT_EQ(maps[876].pgoff, 0ULL);
- ASSERT_EQ(maps[876].inode, 2407UL);
- ASSERT_EQ(maps[876].name, "/system/lib64/libutils.so");
- ASSERT_EQ(maps[1260].start, 0x70e96fa000ULL);
- ASSERT_EQ(maps[1260].end, 0x70e96fb000ULL);
- ASSERT_EQ(maps[1260].flags, PROT_READ);
- ASSERT_EQ(maps[1260].pgoff, 0ULL);
- ASSERT_EQ(maps[1260].inode, 10266154UL);
- ASSERT_EQ(maps[1260].name,
- "[anon:dalvik-classes.dex extracted in memory from "
- "/data/app/com.google.sample.tunnel-HGGRU03Gu1Mwkf_-RnFmvw==/base.apk]");
-}
-
-TEST(process_map, ReadProcessMaps) {
- std::vector<android::procinfo::MapInfo> maps;
- ASSERT_TRUE(android::procinfo::ReadProcessMaps(
- getpid(),
- [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t inode,
- const char* name) { maps.emplace_back(start, end, flags, pgoff, inode, name); }));
- ASSERT_GT(maps.size(), 0u);
- maps.clear();
- ASSERT_TRUE(android::procinfo::ReadProcessMaps(getpid(), &maps));
- ASSERT_GT(maps.size(), 0u);
-}
-
-extern "C" void malloc_disable();
-extern "C" void malloc_enable();
-
-struct TestMapInfo {
- TestMapInfo() = default;
- TestMapInfo(uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t inode,
- const char* new_name)
- : start(start), end(end), flags(flags), pgoff(pgoff), inode(inode) {
- strcpy(name, new_name);
- }
- uint64_t start = 0;
- uint64_t end = 0;
- uint16_t flags = 0;
- uint64_t pgoff = 0;
- ino_t inode = 0;
- char name[100] = {};
-};
-
-void VerifyReadMapFileAsyncSafe(const char* maps_data,
- const std::vector<TestMapInfo>& expected_info) {
- TemporaryFile tf;
- ASSERT_TRUE(android::base::WriteStringToFd(maps_data, tf.fd));
-
- std::vector<TestMapInfo> saved_info(expected_info.size());
- size_t num_maps = 0;
-
- auto callback = [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t inode,
- const char* name) {
- if (num_maps != saved_info.size()) {
- TestMapInfo& saved = saved_info[num_maps];
- saved.start = start;
- saved.end = end;
- saved.flags = flags;
- saved.pgoff = pgoff;
- saved.inode = inode;
- strcpy(saved.name, name);
- }
- num_maps++;
- };
-
- std::vector<char> buffer(64 * 1024);
-
-#if defined(__BIONIC__)
- // Any allocations will block after this call.
- malloc_disable();
-#endif
-
- bool parsed =
- android::procinfo::ReadMapFileAsyncSafe(tf.path, buffer.data(), buffer.size(), callback);
-
-#if defined(__BIONIC__)
- malloc_enable();
-#endif
-
- ASSERT_TRUE(parsed) << "Parsing of data failed:\n" << maps_data;
- ASSERT_EQ(expected_info.size(), num_maps);
- for (size_t i = 0; i < expected_info.size(); i++) {
- const TestMapInfo& expected = expected_info[i];
- const TestMapInfo& saved = saved_info[i];
- EXPECT_EQ(expected.start, saved.start);
- EXPECT_EQ(expected.end, saved.end);
- EXPECT_EQ(expected.flags, saved.flags);
- EXPECT_EQ(expected.pgoff, saved.pgoff);
- EXPECT_EQ(expected.inode, saved.inode);
- EXPECT_STREQ(expected.name, saved.name);
- }
-}
-
-TEST(process_map, ReadMapFileAsyncSafe_invalid) {
- std::vector<TestMapInfo> expected_info;
-
- VerifyReadMapFileAsyncSafe("12c00000-2ac00000", expected_info);
-}
-
-TEST(process_map, ReadMapFileAsyncSafe_single) {
- std::vector<TestMapInfo> expected_info;
- expected_info.emplace_back(0x12c00000, 0x2ac00000, PROT_READ | PROT_WRITE, 0x100, 10267643,
- "/lib/fake.so");
-
- VerifyReadMapFileAsyncSafe("12c00000-2ac00000 rw-p 00000100 00:05 10267643 /lib/fake.so",
- expected_info);
-}
-
-TEST(process_map, ReadMapFileAsyncSafe_single_with_newline) {
- std::vector<TestMapInfo> expected_info;
- expected_info.emplace_back(0x12c00000, 0x2ac00000, PROT_READ | PROT_WRITE, 0x100, 10267643,
- "/lib/fake.so");
-
- VerifyReadMapFileAsyncSafe("12c00000-2ac00000 rw-p 00000100 00:05 10267643 /lib/fake.so\n",
- expected_info);
-}
-
-TEST(process_map, ReadMapFileAsyncSafe_single_no_library) {
- std::vector<TestMapInfo> expected_info;
- expected_info.emplace_back(0xa0000, 0xc0000, PROT_READ | PROT_WRITE | PROT_EXEC, 0xb00, 101, "");
-
- VerifyReadMapFileAsyncSafe("a0000-c0000 rwxp 00000b00 00:05 101", expected_info);
-}
-
-TEST(process_map, ReadMapFileAsyncSafe_multiple) {
- std::vector<TestMapInfo> expected_info;
- expected_info.emplace_back(0xa0000, 0xc0000, PROT_READ | PROT_WRITE | PROT_EXEC, 1, 100, "");
- expected_info.emplace_back(0xd0000, 0xe0000, PROT_READ, 2, 101, "/lib/libsomething1.so");
- expected_info.emplace_back(0xf0000, 0x100000, PROT_WRITE, 3, 102, "/lib/libsomething2.so");
- expected_info.emplace_back(0x110000, 0x120000, PROT_EXEC, 4, 103, "[anon:something or another]");
-
- std::string map_data =
- "0a0000-0c0000 rwxp 00000001 00:05 100\n"
- "0d0000-0e0000 r--p 00000002 00:05 101 /lib/libsomething1.so\n"
- "0f0000-100000 -w-p 00000003 00:05 102 /lib/libsomething2.so\n"
- "110000-120000 --xp 00000004 00:05 103 [anon:something or another]\n";
-
- VerifyReadMapFileAsyncSafe(map_data.c_str(), expected_info);
-}
-
-TEST(process_map, ReadMapFileAsyncSafe_multiple_reads) {
- std::vector<TestMapInfo> expected_info;
- std::string map_data;
- uint64_t start = 0xa0000;
- for (size_t i = 0; i < 10000; i++) {
- map_data += android::base::StringPrintf("%" PRIx64 "-%" PRIx64 " r--p %zx 01:20 %zu fake.so\n",
- start, start + 0x1000, i, 1000 + i);
- expected_info.emplace_back(start, start + 0x1000, PROT_READ, i, 1000 + i, "fake.so");
- }
-
- VerifyReadMapFileAsyncSafe(map_data.c_str(), expected_info);
-}
-
-TEST(process_map, ReadMapFileAsyncSafe_buffer_nullptr) {
- size_t num_calls = 0;
- auto callback = [&](uint64_t, uint64_t, uint16_t, uint64_t, ino_t, const char*) { num_calls++; };
-
-#if defined(__BIONIC__)
- // Any allocations will block after this call.
- malloc_disable();
-#endif
-
- bool parsed = android::procinfo::ReadMapFileAsyncSafe("/proc/self/maps", nullptr, 10, callback);
-
-#if defined(__BIONIC__)
- malloc_enable();
-#endif
-
- ASSERT_FALSE(parsed);
- EXPECT_EQ(0UL, num_calls);
-}
-
-TEST(process_map, ReadMapFileAsyncSafe_buffer_size_zero) {
- size_t num_calls = 0;
- auto callback = [&](uint64_t, uint64_t, uint16_t, uint64_t, ino_t, const char*) { num_calls++; };
-
-#if defined(__BIONIC__)
- // Any allocations will block after this call.
- malloc_disable();
-#endif
-
- char buffer[10];
- bool parsed = android::procinfo::ReadMapFileAsyncSafe("/proc/self/maps", buffer, 0, callback);
-
-#if defined(__BIONIC__)
- malloc_enable();
-#endif
-
- ASSERT_FALSE(parsed);
- EXPECT_EQ(0UL, num_calls);
-}
-
-TEST(process_map, ReadMapFileAsyncSafe_buffer_too_small_no_calls) {
- size_t num_calls = 0;
- auto callback = [&](uint64_t, uint64_t, uint16_t, uint64_t, ino_t, const char*) { num_calls++; };
-
-#if defined(__BIONIC__)
- // Any allocations will block after this call.
- malloc_disable();
-#endif
-
- char buffer[10];
- bool parsed =
- android::procinfo::ReadMapFileAsyncSafe("/proc/self/maps", buffer, sizeof(buffer), callback);
-
-#if defined(__BIONIC__)
- malloc_enable();
-#endif
-
- ASSERT_FALSE(parsed);
- EXPECT_EQ(0UL, num_calls);
-}
-
-TEST(process_map, ReadMapFileAsyncSafe_buffer_too_small_could_parse) {
- TemporaryFile tf;
- ASSERT_TRUE(android::base::WriteStringToFd(
- "0a0000-0c0000 rwxp 00000001 00:05 100 /fake/lib.so\n", tf.fd));
-
- size_t num_calls = 0;
- auto callback = [&](uint64_t, uint64_t, uint16_t, uint64_t, ino_t, const char*) { num_calls++; };
-
-#if defined(__BIONIC__)
- // Any allocations will block after this call.
- malloc_disable();
-#endif
-
- char buffer[39];
- bool parsed = android::procinfo::ReadMapFileAsyncSafe(tf.path, buffer, sizeof(buffer), callback);
-
-#if defined(__BIONIC__)
- malloc_enable();
-#endif
-
- ASSERT_FALSE(parsed);
- EXPECT_EQ(0UL, num_calls);
-}
diff --git a/libprocinfo/process_test.cpp b/libprocinfo/process_test.cpp
deleted file mode 100644
index 9da9278..0000000
--- a/libprocinfo/process_test.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2016 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 <procinfo/process.h>
-
-#include <fcntl.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <chrono>
-#include <set>
-#include <thread>
-#include <vector>
-
-#include <gtest/gtest.h>
-
-#include <android-base/stringprintf.h>
-
-using namespace std::chrono_literals;
-
-#if !defined(__BIONIC__)
-#include <syscall.h>
-static pid_t gettid() {
- return syscall(__NR_gettid);
-}
-#endif
-
-TEST(process_info, process_info_smoke) {
- android::procinfo::ProcessInfo self;
- ASSERT_TRUE(android::procinfo::GetProcessInfo(gettid(), &self));
- ASSERT_EQ(gettid(), self.tid);
- ASSERT_EQ(getpid(), self.pid);
- ASSERT_EQ(getppid(), self.ppid);
- ASSERT_EQ(getuid(), self.uid);
- ASSERT_EQ(getgid(), self.gid);
-}
-
-TEST(process_info, process_info_proc_pid_fd_smoke) {
- android::procinfo::ProcessInfo self;
- int fd = open(android::base::StringPrintf("/proc/%d", gettid()).c_str(), O_DIRECTORY | O_RDONLY);
- ASSERT_NE(-1, fd);
- ASSERT_TRUE(android::procinfo::GetProcessInfoFromProcPidFd(fd, &self));
-
- // Process name is capped at 15 bytes.
- ASSERT_EQ("libprocinfo_tes", self.name);
- ASSERT_EQ(gettid(), self.tid);
- ASSERT_EQ(getpid(), self.pid);
- ASSERT_EQ(getppid(), self.ppid);
- ASSERT_EQ(getuid(), self.uid);
- ASSERT_EQ(getgid(), self.gid);
- close(fd);
-}
-
-TEST(process_info, process_tids_smoke) {
- pid_t main_tid = gettid();
- std::thread([main_tid]() {
- pid_t thread_tid = gettid();
-
- {
- std::vector<pid_t> vec;
- ASSERT_TRUE(android::procinfo::GetProcessTids(getpid(), &vec));
- ASSERT_EQ(1, std::count(vec.begin(), vec.end(), main_tid));
- ASSERT_EQ(1, std::count(vec.begin(), vec.end(), thread_tid));
- }
-
- {
- std::set<pid_t> set;
- ASSERT_TRUE(android::procinfo::GetProcessTids(getpid(), &set));
- ASSERT_EQ(1, std::count(set.begin(), set.end(), main_tid));
- ASSERT_EQ(1, std::count(set.begin(), set.end(), thread_tid));
- }
- }).join();
-}
-
-TEST(process_info, process_state) {
- int pipefd[2];
- ASSERT_EQ(0, pipe2(pipefd, O_CLOEXEC));
- pid_t forkpid = fork();
-
- ASSERT_NE(-1, forkpid);
- if (forkpid == 0) {
- close(pipefd[1]);
- char buf;
- TEMP_FAILURE_RETRY(read(pipefd[0], &buf, 1));
- _exit(0);
- }
-
- // Give the child some time to get to the read.
- std::this_thread::sleep_for(100ms);
-
- android::procinfo::ProcessInfo procinfo;
- ASSERT_TRUE(android::procinfo::GetProcessInfo(forkpid, &procinfo));
- ASSERT_EQ(android::procinfo::kProcessStateSleeping, procinfo.state);
-
- ASSERT_EQ(0, kill(forkpid, SIGKILL));
-
- // Give the kernel some time to kill the child.
- std::this_thread::sleep_for(100ms);
-
- ASSERT_TRUE(android::procinfo::GetProcessInfo(forkpid, &procinfo));
- ASSERT_EQ(android::procinfo::kProcessStateZombie, procinfo.state);
-
- ASSERT_EQ(forkpid, waitpid(forkpid, nullptr, 0));
-}
diff --git a/libprocinfo/testdata/maps b/libprocinfo/testdata/maps
deleted file mode 100644
index 098cf25..0000000
--- a/libprocinfo/testdata/maps
+++ /dev/null
@@ -1,2043 +0,0 @@
-12c00000-2ac00000 rw-p 00000000 00:05 10267643 [anon:dalvik-main space (region space)]
-6fb5d000-6fd6e000 rw-p 00000000 103:1d 639511 /data/dalvik-cache/arm64/system@framework@boot.art
-6fd6e000-6fd82000 r--p 00211000 103:1d 639511 /data/dalvik-cache/arm64/system@framework@boot.art
-6fd82000-6fe47000 rw-p 00000000 103:1d 639514 /data/dalvik-cache/arm64/system@framework@boot-core-libart.art
-6fe47000-6fe52000 r--p 000c5000 103:1d 639514 /data/dalvik-cache/arm64/system@framework@boot-core-libart.art
-6fe52000-6fe84000 rw-p 00000000 103:1d 639517 /data/dalvik-cache/arm64/system@framework@boot-conscrypt.art
-6fe84000-6fe87000 r--p 00032000 103:1d 639517 /data/dalvik-cache/arm64/system@framework@boot-conscrypt.art
-6fe87000-6feb2000 rw-p 00000000 103:1d 639520 /data/dalvik-cache/arm64/system@framework@boot-okhttp.art
-6feb2000-6feb5000 r--p 0002b000 103:1d 639520 /data/dalvik-cache/arm64/system@framework@boot-okhttp.art
-6feb5000-6fef4000 rw-p 00000000 103:1d 639523 /data/dalvik-cache/arm64/system@framework@boot-bouncycastle.art
-6fef4000-6fefb000 r--p 0003f000 103:1d 639523 /data/dalvik-cache/arm64/system@framework@boot-bouncycastle.art
-6fefb000-6ff3f000 rw-p 00000000 103:1d 639526 /data/dalvik-cache/arm64/system@framework@boot-apache-xml.art
-6ff3f000-6ff45000 r--p 00044000 103:1d 639526 /data/dalvik-cache/arm64/system@framework@boot-apache-xml.art
-6ff45000-6ff7a000 rw-p 00000000 103:1d 639529 /data/dalvik-cache/arm64/system@framework@boot-ext.art
-6ff7a000-6ff85000 r--p 00035000 103:1d 639529 /data/dalvik-cache/arm64/system@framework@boot-ext.art
-6ff85000-70594000 rw-p 00000000 103:1d 639532 /data/dalvik-cache/arm64/system@framework@boot-framework.art
-70594000-705cb000 r--p 0060f000 103:1d 639532 /data/dalvik-cache/arm64/system@framework@boot-framework.art
-705cb000-7061f000 rw-p 00000000 103:1d 639535 /data/dalvik-cache/arm64/system@framework@boot-telephony-common.art
-7061f000-70629000 r--p 00054000 103:1d 639535 /data/dalvik-cache/arm64/system@framework@boot-telephony-common.art
-70629000-70635000 rw-p 00000000 103:1d 639538 /data/dalvik-cache/arm64/system@framework@boot-voip-common.art
-70635000-70636000 r--p 0000c000 103:1d 639538 /data/dalvik-cache/arm64/system@framework@boot-voip-common.art
-70636000-70644000 rw-p 00000000 103:1d 639541 /data/dalvik-cache/arm64/system@framework@boot-ims-common.art
-70644000-70645000 r--p 0000e000 103:1d 639541 /data/dalvik-cache/arm64/system@framework@boot-ims-common.art
-70645000-70648000 rw-p 00000000 103:1d 639544 /data/dalvik-cache/arm64/system@framework@boot-android.hidl.base-V1.0-java.art
-70648000-7064c000 rw-p 00000000 103:1d 639547 /data/dalvik-cache/arm64/system@framework@boot-android.hidl.manager-V1.0-java.art
-7064c000-7064d000 r--p 00004000 103:1d 639547 /data/dalvik-cache/arm64/system@framework@boot-android.hidl.manager-V1.0-java.art
-7064d000-7064e000 rw-p 00000000 103:1d 639550 /data/dalvik-cache/arm64/system@framework@boot-framework-oahl-backward-compatibility.art
-7064e000-70652000 rw-p 00000000 103:1d 639553 /data/dalvik-cache/arm64/system@framework@boot-android.test.base.art
-70652000-70653000 r--p 00004000 103:1d 639553 /data/dalvik-cache/arm64/system@framework@boot-android.test.base.art
-70653000-70654000 rw-p 00000000 103:1d 639556 /data/dalvik-cache/arm64/system@framework@boot-com.google.vr.platform.art
-70654000-70655000 r--p 00001000 103:1d 639556 /data/dalvik-cache/arm64/system@framework@boot-com.google.vr.platform.art
-70655000-70731000 r--p 00000000 fc:00 940 /system/framework/arm64/boot.oat
-70731000-709ca000 r-xp 000dc000 fc:00 940 /system/framework/arm64/boot.oat
-709ca000-709cb000 rw-p 00000000 00:00 0 [anon:.bss]
-709cb000-70e4c000 r--s 00000000 fc:00 961 /system/framework/boot.vdex
-70e4c000-70e4d000 r--p 00375000 fc:00 940 /system/framework/arm64/boot.oat
-70e4d000-70e4e000 rw-p 00376000 fc:00 940 /system/framework/arm64/boot.oat
-70e4e000-70eab000 r--p 00000000 fc:00 916 /system/framework/arm64/boot-core-libart.oat
-70eab000-70fad000 r-xp 0005d000 fc:00 916 /system/framework/arm64/boot-core-libart.oat
-70fad000-70fae000 rw-p 00000000 00:00 0 [anon:.bss]
-70fae000-712a9000 r--s 00000000 fc:00 702 /system/framework/boot-core-libart.vdex
-712a9000-712aa000 r--p 0015f000 fc:00 916 /system/framework/arm64/boot-core-libart.oat
-712aa000-712ab000 rw-p 00160000 fc:00 916 /system/framework/arm64/boot-core-libart.oat
-712ab000-712bb000 r--p 00000000 fc:00 941 /system/framework/arm64/boot-conscrypt.oat
-712bb000-712e4000 r-xp 00010000 fc:00 941 /system/framework/arm64/boot-conscrypt.oat
-712e4000-712e5000 rw-p 00000000 00:00 0 [anon:.bss]
-712e5000-71346000 r--s 00000000 fc:00 970 /system/framework/boot-conscrypt.vdex
-71346000-71347000 r--p 00039000 fc:00 941 /system/framework/arm64/boot-conscrypt.oat
-71347000-71348000 rw-p 0003a000 fc:00 941 /system/framework/arm64/boot-conscrypt.oat
-71348000-71361000 r--p 00000000 fc:00 908 /system/framework/arm64/boot-okhttp.oat
-71361000-713a3000 r-xp 00019000 fc:00 908 /system/framework/arm64/boot-okhttp.oat
-713a3000-713a4000 rw-p 00000000 00:00 0 [anon:.bss]
-713a4000-71403000 r--s 00000000 fc:00 886 /system/framework/boot-okhttp.vdex
-71403000-71404000 r--p 0005b000 fc:00 908 /system/framework/arm64/boot-okhttp.oat
-71404000-71405000 rw-p 0005c000 fc:00 908 /system/framework/arm64/boot-okhttp.oat
-71405000-71415000 r--p 00000000 fc:00 936 /system/framework/arm64/boot-bouncycastle.oat
-71415000-71437000 r-xp 00010000 fc:00 936 /system/framework/arm64/boot-bouncycastle.oat
-71437000-71438000 rw-p 00000000 00:00 0 [anon:.bss]
-71438000-7157b000 r--s 00000000 fc:00 1006 /system/framework/boot-bouncycastle.vdex
-7157b000-7157c000 r--p 00032000 fc:00 936 /system/framework/arm64/boot-bouncycastle.oat
-7157c000-7157d000 rw-p 00033000 fc:00 936 /system/framework/arm64/boot-bouncycastle.oat
-7157d000-71583000 r--p 00000000 fc:00 932 /system/framework/arm64/boot-apache-xml.oat
-71583000-71584000 r-xp 00006000 fc:00 932 /system/framework/arm64/boot-apache-xml.oat
-71584000-716a7000 r--s 00000000 fc:00 883 /system/framework/boot-apache-xml.vdex
-716a7000-716a8000 r--p 00007000 fc:00 932 /system/framework/arm64/boot-apache-xml.oat
-716a8000-716a9000 rw-p 00008000 fc:00 932 /system/framework/arm64/boot-apache-xml.oat
-716a9000-716b5000 r--p 00000000 fc:00 891 /system/framework/arm64/boot-ext.oat
-716b5000-716cc000 r-xp 0000c000 fc:00 891 /system/framework/arm64/boot-ext.oat
-716cc000-716cd000 rw-p 00000000 00:00 0 [anon:.bss]
-716cd000-717b8000 r--s 00000000 fc:00 879 /system/framework/boot-ext.vdex
-717b8000-717b9000 r--p 00023000 fc:00 891 /system/framework/arm64/boot-ext.oat
-717b9000-717ba000 rw-p 00024000 fc:00 891 /system/framework/arm64/boot-ext.oat
-717ba000-71aeb000 r--p 00000000 fc:00 943 /system/framework/arm64/boot-framework.oat
-71aeb000-72390000 r-xp 00331000 fc:00 943 /system/framework/arm64/boot-framework.oat
-72390000-72396000 rw-p 00000000 00:00 0 [anon:.bss]
-72396000-73746000 r--s 00000000 fc:00 985 /system/framework/boot-framework.vdex
-73746000-73747000 r--p 00bd6000 fc:00 943 /system/framework/arm64/boot-framework.oat
-73747000-73748000 rw-p 00bd7000 fc:00 943 /system/framework/arm64/boot-framework.oat
-73748000-73780000 r--p 00000000 fc:00 893 /system/framework/arm64/boot-telephony-common.oat
-73780000-73818000 r-xp 00038000 fc:00 893 /system/framework/arm64/boot-telephony-common.oat
-73818000-7381a000 rw-p 00000000 00:00 0 [anon:.bss]
-7381a000-73af0000 r--s 00000000 fc:00 697 /system/framework/boot-telephony-common.vdex
-73af0000-73af1000 r--p 000d0000 fc:00 893 /system/framework/arm64/boot-telephony-common.oat
-73af1000-73af2000 rw-p 000d1000 fc:00 893 /system/framework/arm64/boot-telephony-common.oat
-73af2000-73af6000 r--p 00000000 fc:00 922 /system/framework/arm64/boot-voip-common.oat
-73af6000-73af8000 r-xp 00004000 fc:00 922 /system/framework/arm64/boot-voip-common.oat
-73af8000-73af9000 rw-p 00000000 00:00 0 [anon:.bss]
-73af9000-73b1e000 r--s 00000000 fc:00 959 /system/framework/boot-voip-common.vdex
-73b1e000-73b1f000 r--p 00006000 fc:00 922 /system/framework/arm64/boot-voip-common.oat
-73b1f000-73b20000 rw-p 00007000 fc:00 922 /system/framework/arm64/boot-voip-common.oat
-73b20000-73b23000 r--p 00000000 fc:00 918 /system/framework/arm64/boot-ims-common.oat
-73b23000-73b25000 r-xp 00003000 fc:00 918 /system/framework/arm64/boot-ims-common.oat
-73b25000-73b26000 rw-p 00000000 00:00 0 [anon:.bss]
-73b26000-73b48000 r--s 00000000 fc:00 957 /system/framework/boot-ims-common.vdex
-73b48000-73b49000 r--p 00005000 fc:00 918 /system/framework/arm64/boot-ims-common.oat
-73b49000-73b4a000 rw-p 00006000 fc:00 918 /system/framework/arm64/boot-ims-common.oat
-73b4a000-73b4d000 r--p 00000000 fc:00 909 /system/framework/arm64/boot-android.hidl.base-V1.0-java.oat
-73b4d000-73b4e000 r-xp 00003000 fc:00 909 /system/framework/arm64/boot-android.hidl.base-V1.0-java.oat
-73b4e000-73b55000 r--s 00000000 fc:00 972 /system/framework/boot-android.hidl.base-V1.0-java.vdex
-73b55000-73b56000 r--p 00004000 fc:00 909 /system/framework/arm64/boot-android.hidl.base-V1.0-java.oat
-73b56000-73b57000 rw-p 00005000 fc:00 909 /system/framework/arm64/boot-android.hidl.base-V1.0-java.oat
-73b57000-73b5a000 r--p 00000000 fc:00 954 /system/framework/arm64/boot-android.hidl.manager-V1.0-java.oat
-73b5a000-73b5c000 r-xp 00003000 fc:00 954 /system/framework/arm64/boot-android.hidl.manager-V1.0-java.oat
-73b5c000-73b5d000 rw-p 00000000 00:00 0 [anon:.bss]
-73b5d000-73b68000 r--s 00000000 fc:00 704 /system/framework/boot-android.hidl.manager-V1.0-java.vdex
-73b68000-73b69000 r--p 00005000 fc:00 954 /system/framework/arm64/boot-android.hidl.manager-V1.0-java.oat
-73b69000-73b6a000 rw-p 00006000 fc:00 954 /system/framework/arm64/boot-android.hidl.manager-V1.0-java.oat
-73b6a000-73b6d000 r--p 00000000 fc:00 904 /system/framework/arm64/boot-framework-oahl-backward-compatibility.oat
-73b6d000-73b6e000 r-xp 00003000 fc:00 904 /system/framework/arm64/boot-framework-oahl-backward-compatibility.oat
-73b6e000-73b6f000 r--s 00000000 fc:00 994 /system/framework/boot-framework-oahl-backward-compatibility.vdex
-73b6f000-73b70000 r--p 00004000 fc:00 904 /system/framework/arm64/boot-framework-oahl-backward-compatibility.oat
-73b70000-73b71000 rw-p 00005000 fc:00 904 /system/framework/arm64/boot-framework-oahl-backward-compatibility.oat
-73b71000-73b75000 r--p 00000000 fc:00 896 /system/framework/arm64/boot-android.test.base.oat
-73b75000-73b79000 r-xp 00004000 fc:00 896 /system/framework/arm64/boot-android.test.base.oat
-73b79000-73b7a000 rw-p 00000000 00:00 0 [anon:.bss]
-73b7a000-73b82000 r--s 00000000 fc:00 706 /system/framework/boot-android.test.base.vdex
-73b82000-73b83000 r--p 00008000 fc:00 896 /system/framework/arm64/boot-android.test.base.oat
-73b83000-73b84000 rw-p 00009000 fc:00 896 /system/framework/arm64/boot-android.test.base.oat
-73b84000-73b87000 r--p 00000000 fc:00 899 /system/framework/arm64/boot-com.google.vr.platform.oat
-73b87000-73b88000 r-xp 00003000 fc:00 899 /system/framework/arm64/boot-com.google.vr.platform.oat
-73b88000-73b89000 r--s 00000000 fc:00 884 /system/framework/boot-com.google.vr.platform.vdex
-73b89000-73b8a000 r--p 00004000 fc:00 899 /system/framework/arm64/boot-com.google.vr.platform.oat
-73b8a000-73b8b000 rw-p 00005000 fc:00 899 /system/framework/arm64/boot-com.google.vr.platform.oat
-73b8b000-73b93000 rw-p 00000000 00:05 10267640 [anon:dalvik-non moving space]
-73b93000-77b8b000 ---p 00008000 00:05 10267640 [anon:dalvik-non moving space]
-77b8b000-97b8b000 rw-p 00000000 00:05 10267645 [anon:dalvik-free list large object space]
-97b8b000-99b8b000 rw-p 00000000 00:05 10270989 [anon:dalvik-data-code-cache]
-99b8b000-9bb8b000 r-xp 00000000 00:05 10270990 [anon:dalvik-jit-code-cache]
-ebad6000-ebad7000 ---p 00000000 00:05 10269717 [anon:dalvik-Sentinel fault page]
-7ffb6e000-7ffb76000 rw-s 000e5000 00:10 20630 /dev/kgsl-3d0
-7ffb76000-7ffb78000 rw-s 000e0000 00:10 20630 /dev/kgsl-3d0
-7ffbc3000-7ffbc4000 rw-s 000e8000 00:10 20630 /dev/kgsl-3d0
-7ffbc4000-7ffbc5000 rw-s 000e7000 00:10 20630 /dev/kgsl-3d0
-7ffbc6000-7ffbce000 rw-s 000e4000 00:10 20630 /dev/kgsl-3d0
-7ffbd0000-7ffbd2000 rw-s 000df000 00:10 20630 /dev/kgsl-3d0
-7ffbd2000-7ffbd4000 rw-s 000de000 00:10 20630 /dev/kgsl-3d0
-7ffbd4000-7ffbd6000 rw-s 000dd000 00:10 20630 /dev/kgsl-3d0
-7ffbd6000-7ffbd8000 rw-s 000dc000 00:10 20630 /dev/kgsl-3d0
-7ffbd8000-7ffbda000 rw-s 000db000 00:10 20630 /dev/kgsl-3d0
-7ffbda000-7ffbdc000 rw-s 000da000 00:10 20630 /dev/kgsl-3d0
-7ffbdd000-7ffbde000 rw-s 000ec000 00:10 20630 /dev/kgsl-3d0
-7ffbde000-7ffbe0000 rw-s 000d8000 00:10 20630 /dev/kgsl-3d0
-7ffce1000-7ffce2000 rw-s 000e6000 00:10 20630 /dev/kgsl-3d0
-7ffce2000-7ffce4000 rw-s 000d9000 00:10 20630 /dev/kgsl-3d0
-7ffce4000-7ffce8000 rw-s 000d4000 00:10 20630 /dev/kgsl-3d0
-7ffce8000-7ffcf8000 rw-s 000d2000 00:10 20630 /dev/kgsl-3d0
-7ffcf8000-7ffd08000 rw-s 000d1000 00:10 20630 /dev/kgsl-3d0
-7ffd08000-7ffd10000 rw-s 000d0000 00:10 20630 /dev/kgsl-3d0
-7ffd14000-7ffd18000 rw-s 000cd000 00:10 20630 /dev/kgsl-3d0
-7ffd18000-7ffd28000 rw-s 000cc000 00:10 20630 /dev/kgsl-3d0
-7ffd28000-7ffd38000 rw-s 000cb000 00:10 20630 /dev/kgsl-3d0
-7ffd38000-7ffd48000 rw-s 000ca000 00:10 20630 /dev/kgsl-3d0
-7ffd48000-7ffd58000 rw-s 000c9000 00:10 20630 /dev/kgsl-3d0
-7ffd58000-7ffd68000 rw-s 000c8000 00:10 20630 /dev/kgsl-3d0
-7ffd68000-7ffd6c000 rw-s 000c7000 00:10 20630 /dev/kgsl-3d0
-7ffdb1000-7ffdb2000 rw-s 000e3000 00:10 20630 /dev/kgsl-3d0
-7ffdb4000-7ffdb5000 rw-s 000e2000 00:10 20630 /dev/kgsl-3d0
-7ffdb5000-7ffdb7000 rw-s 000d7000 00:10 20630 /dev/kgsl-3d0
-7ffdb7000-7ffdb8000 rw-s 000c2000 00:10 20630 /dev/kgsl-3d0
-7ffdb8000-7ffdbc000 rw-s 000c0000 00:10 20630 /dev/kgsl-3d0
-7ffdbc000-7ffdc0000 rw-s 000be000 00:10 20630 /dev/kgsl-3d0
-7ffdc0000-7ffe00000 rw-s 000bb000 00:10 20630 /dev/kgsl-3d0
-7ffe00000-7ffe20000 rw-s 000ba000 00:10 20630 /dev/kgsl-3d0
-7ffe20000-7ffee0000 rw-s 000b9000 00:10 20630 /dev/kgsl-3d0
-7ffee1000-7ffee3000 rw-s 000c1000 00:10 20630 /dev/kgsl-3d0
-7ffee3000-7ffee4000 rw-s 000bf000 00:10 20630 /dev/kgsl-3d0
-7ffee4000-7ffee8000 rw-s 000bd000 00:10 20630 /dev/kgsl-3d0
-7ffee8000-7ffee9000 rw-s 000bc000 00:10 20630 /dev/kgsl-3d0
-7ffeea000-7ffeeb000 rw-s 000e1000 00:10 20630 /dev/kgsl-3d0
-7ffeeb000-7ffeec000 rw-s 000b6000 00:10 20630 /dev/kgsl-3d0
-7ffeec000-7ffeed000 rw-s 000b5000 00:10 20630 /dev/kgsl-3d0
-7ffeed000-7ffeee000 rw-s 000b4000 00:10 20630 /dev/kgsl-3d0
-7ffeee000-7ffeef000 rw-s 000b3000 00:10 20630 /dev/kgsl-3d0
-7ffeef000-7ffef0000 rw-s 000b2000 00:10 20630 /dev/kgsl-3d0
-7ffef0000-7ffef1000 rw-s 000b1000 00:10 20630 /dev/kgsl-3d0
-7ffef1000-7ffef2000 rw-s 000b0000 00:10 20630 /dev/kgsl-3d0
-7ffef2000-7ffef3000 rw-s 000af000 00:10 20630 /dev/kgsl-3d0
-7ffef3000-7ffef4000 rw-s 000ae000 00:10 20630 /dev/kgsl-3d0
-7ffef4000-7ffef5000 rw-s 000ad000 00:10 20630 /dev/kgsl-3d0
-7ffef5000-7ffef6000 rw-s 000ac000 00:10 20630 /dev/kgsl-3d0
-7ffef6000-7ffef7000 rw-s 000ab000 00:10 20630 /dev/kgsl-3d0
-7ffef7000-7ffef8000 rw-s 000aa000 00:10 20630 /dev/kgsl-3d0
-7ffef8000-7ffef9000 rw-s 000a9000 00:10 20630 /dev/kgsl-3d0
-7ffef9000-7ffefa000 rw-s 000a8000 00:10 20630 /dev/kgsl-3d0
-7ffefa000-7ffefb000 rw-s 000a7000 00:10 20630 /dev/kgsl-3d0
-7ffefb000-7ffefc000 rw-s 000a6000 00:10 20630 /dev/kgsl-3d0
-7ffefc000-7ffefd000 rw-s 000a5000 00:10 20630 /dev/kgsl-3d0
-7ffefd000-7ffefe000 rw-s 000a4000 00:10 20630 /dev/kgsl-3d0
-7ffefe000-7ffeff000 rw-s 000a3000 00:10 20630 /dev/kgsl-3d0
-7ffeff000-7fff00000 rw-s 000a2000 00:10 20630 /dev/kgsl-3d0
-7fff00000-7fff01000 rw-s 000a1000 00:10 20630 /dev/kgsl-3d0
-7fff01000-7fff02000 rw-s 000a0000 00:10 20630 /dev/kgsl-3d0
-7fff02000-7fff03000 rw-s 0009f000 00:10 20630 /dev/kgsl-3d0
-7fff03000-7fff04000 rw-s 0009e000 00:10 20630 /dev/kgsl-3d0
-7fff04000-7fff05000 rw-s 0009d000 00:10 20630 /dev/kgsl-3d0
-7fff05000-7fff06000 rw-s 0009c000 00:10 20630 /dev/kgsl-3d0
-7fff06000-7fff07000 rw-s 0009b000 00:10 20630 /dev/kgsl-3d0
-7fff07000-7fff08000 rw-s 0009a000 00:10 20630 /dev/kgsl-3d0
-7fff08000-7fff09000 rw-s 00099000 00:10 20630 /dev/kgsl-3d0
-7fff09000-7fff0a000 rw-s 00098000 00:10 20630 /dev/kgsl-3d0
-7fff0a000-7fff0b000 rw-s 00097000 00:10 20630 /dev/kgsl-3d0
-7fff0b000-7fff0c000 rw-s 00096000 00:10 20630 /dev/kgsl-3d0
-7fff0c000-7fff0d000 rw-s 00095000 00:10 20630 /dev/kgsl-3d0
-7fff0d000-7fff0e000 rw-s 00094000 00:10 20630 /dev/kgsl-3d0
-7fff0e000-7fff0f000 rw-s 00093000 00:10 20630 /dev/kgsl-3d0
-7fff0f000-7fff10000 rw-s 00092000 00:10 20630 /dev/kgsl-3d0
-7fff10000-7fff11000 rw-s 00091000 00:10 20630 /dev/kgsl-3d0
-7fff11000-7fff12000 rw-s 00090000 00:10 20630 /dev/kgsl-3d0
-7fff12000-7fff13000 rw-s 0008f000 00:10 20630 /dev/kgsl-3d0
-7fff13000-7fff14000 rw-s 0008e000 00:10 20630 /dev/kgsl-3d0
-7fff14000-7fff15000 rw-s 0008d000 00:10 20630 /dev/kgsl-3d0
-7fff15000-7fff16000 rw-s 0008c000 00:10 20630 /dev/kgsl-3d0
-7fff16000-7fff17000 rw-s 0008b000 00:10 20630 /dev/kgsl-3d0
-7fff17000-7fff18000 rw-s 0008a000 00:10 20630 /dev/kgsl-3d0
-7fff18000-7fff19000 rw-s 00089000 00:10 20630 /dev/kgsl-3d0
-7fff19000-7fff1a000 rw-s 00088000 00:10 20630 /dev/kgsl-3d0
-7fff1a000-7fff1b000 rw-s 00087000 00:10 20630 /dev/kgsl-3d0
-7fff1b000-7fff1c000 rw-s 00086000 00:10 20630 /dev/kgsl-3d0
-7fff1c000-7fff1d000 rw-s 00085000 00:10 20630 /dev/kgsl-3d0
-7fff1d000-7fff1e000 rw-s 00084000 00:10 20630 /dev/kgsl-3d0
-7fff1e000-7fff1f000 rw-s 00083000 00:10 20630 /dev/kgsl-3d0
-7fff1f000-7fff20000 rw-s 00082000 00:10 20630 /dev/kgsl-3d0
-7fff20000-7fff21000 rw-s 00081000 00:10 20630 /dev/kgsl-3d0
-7fff21000-7fff22000 rw-s 00080000 00:10 20630 /dev/kgsl-3d0
-7fff22000-7fff23000 rw-s 0007f000 00:10 20630 /dev/kgsl-3d0
-7fff23000-7fff24000 rw-s 0007e000 00:10 20630 /dev/kgsl-3d0
-7fff24000-7fff25000 rw-s 0007d000 00:10 20630 /dev/kgsl-3d0
-7fff25000-7fff26000 rw-s 0007c000 00:10 20630 /dev/kgsl-3d0
-7fff26000-7fff27000 rw-s 0007b000 00:10 20630 /dev/kgsl-3d0
-7fff27000-7fff28000 rw-s 0007a000 00:10 20630 /dev/kgsl-3d0
-7fff28000-7fff29000 rw-s 00079000 00:10 20630 /dev/kgsl-3d0
-7fff29000-7fff2a000 rw-s 00078000 00:10 20630 /dev/kgsl-3d0
-7fff2a000-7fff2b000 rw-s 00077000 00:10 20630 /dev/kgsl-3d0
-7fff2b000-7fff2c000 rw-s 00076000 00:10 20630 /dev/kgsl-3d0
-7fff2c000-7fff2d000 rw-s 00075000 00:10 20630 /dev/kgsl-3d0
-7fff2d000-7fff2e000 rw-s 00074000 00:10 20630 /dev/kgsl-3d0
-7fff2e000-7fff2f000 rw-s 00073000 00:10 20630 /dev/kgsl-3d0
-7fff2f000-7fff30000 rw-s 00072000 00:10 20630 /dev/kgsl-3d0
-7fff30000-7fff31000 rw-s 00071000 00:10 20630 /dev/kgsl-3d0
-7fff31000-7fff32000 rw-s 00070000 00:10 20630 /dev/kgsl-3d0
-7fff32000-7fff33000 rw-s 0006f000 00:10 20630 /dev/kgsl-3d0
-7fff33000-7fff34000 rw-s 0006e000 00:10 20630 /dev/kgsl-3d0
-7fff34000-7fff35000 rw-s 0006d000 00:10 20630 /dev/kgsl-3d0
-7fff35000-7fff36000 rw-s 0006c000 00:10 20630 /dev/kgsl-3d0
-7fff36000-7fff37000 rw-s 0006b000 00:10 20630 /dev/kgsl-3d0
-7fff37000-7fff38000 rw-s 0006a000 00:10 20630 /dev/kgsl-3d0
-7fff38000-7fff39000 rw-s 00069000 00:10 20630 /dev/kgsl-3d0
-7fff39000-7fff3a000 rw-s 00068000 00:10 20630 /dev/kgsl-3d0
-7fff3a000-7fff3b000 rw-s 00067000 00:10 20630 /dev/kgsl-3d0
-7fff3b000-7fff3c000 rw-s 00066000 00:10 20630 /dev/kgsl-3d0
-7fff3c000-7fff3d000 rw-s 00065000 00:10 20630 /dev/kgsl-3d0
-7fff3d000-7fff3e000 rw-s 00064000 00:10 20630 /dev/kgsl-3d0
-7fff3e000-7fff3f000 rw-s 00063000 00:10 20630 /dev/kgsl-3d0
-7fff3f000-7fff40000 rw-s 00062000 00:10 20630 /dev/kgsl-3d0
-7fff40000-7fff41000 rw-s 00061000 00:10 20630 /dev/kgsl-3d0
-7fff41000-7fff42000 rw-s 00060000 00:10 20630 /dev/kgsl-3d0
-7fff42000-7fff43000 rw-s 0005f000 00:10 20630 /dev/kgsl-3d0
-7fff43000-7fff44000 rw-s 0005e000 00:10 20630 /dev/kgsl-3d0
-7fff44000-7fff45000 rw-s 0005d000 00:10 20630 /dev/kgsl-3d0
-7fff45000-7fff46000 rw-s 0005c000 00:10 20630 /dev/kgsl-3d0
-7fff46000-7fff47000 rw-s 0005b000 00:10 20630 /dev/kgsl-3d0
-7fff47000-7fff48000 rw-s 0005a000 00:10 20630 /dev/kgsl-3d0
-7fff48000-7fff49000 rw-s 00059000 00:10 20630 /dev/kgsl-3d0
-7fff49000-7fff4a000 rw-s 00058000 00:10 20630 /dev/kgsl-3d0
-7fff4a000-7fff4b000 rw-s 00057000 00:10 20630 /dev/kgsl-3d0
-7fff4b000-7fff4c000 rw-s 00056000 00:10 20630 /dev/kgsl-3d0
-7fff4c000-7fff4d000 rw-s 00055000 00:10 20630 /dev/kgsl-3d0
-7fff4d000-7fff4e000 rw-s 00054000 00:10 20630 /dev/kgsl-3d0
-7fff4e000-7fff4f000 rw-s 00053000 00:10 20630 /dev/kgsl-3d0
-7fff4f000-7fff50000 rw-s 00052000 00:10 20630 /dev/kgsl-3d0
-7fff50000-7fff51000 rw-s 00051000 00:10 20630 /dev/kgsl-3d0
-7fff51000-7fff52000 rw-s 00050000 00:10 20630 /dev/kgsl-3d0
-7fff52000-7fff53000 rw-s 0004f000 00:10 20630 /dev/kgsl-3d0
-7fff53000-7fff54000 rw-s 0004e000 00:10 20630 /dev/kgsl-3d0
-7fff54000-7fff55000 rw-s 0004d000 00:10 20630 /dev/kgsl-3d0
-7fff55000-7fff56000 rw-s 0004c000 00:10 20630 /dev/kgsl-3d0
-7fff56000-7fff57000 rw-s 0004b000 00:10 20630 /dev/kgsl-3d0
-7fff57000-7fff58000 rw-s 0004a000 00:10 20630 /dev/kgsl-3d0
-7fff58000-7fff59000 rw-s 00049000 00:10 20630 /dev/kgsl-3d0
-7fff59000-7fff5a000 rw-s 00048000 00:10 20630 /dev/kgsl-3d0
-7fff5a000-7fff5b000 rw-s 00047000 00:10 20630 /dev/kgsl-3d0
-7fff5b000-7fff5c000 rw-s 00046000 00:10 20630 /dev/kgsl-3d0
-7fff5c000-7fff5d000 rw-s 00045000 00:10 20630 /dev/kgsl-3d0
-7fff5d000-7fff5e000 rw-s 00044000 00:10 20630 /dev/kgsl-3d0
-7fff5e000-7fff5f000 rw-s 00043000 00:10 20630 /dev/kgsl-3d0
-7fff5f000-7fff60000 rw-s 00042000 00:10 20630 /dev/kgsl-3d0
-7fff60000-7fff61000 rw-s 00041000 00:10 20630 /dev/kgsl-3d0
-7fff61000-7fff62000 rw-s 00040000 00:10 20630 /dev/kgsl-3d0
-7fff62000-7fff63000 rw-s 0003f000 00:10 20630 /dev/kgsl-3d0
-7fff63000-7fff64000 rw-s 0003e000 00:10 20630 /dev/kgsl-3d0
-7fff64000-7fff65000 rw-s 0003d000 00:10 20630 /dev/kgsl-3d0
-7fff65000-7fff66000 rw-s 0003c000 00:10 20630 /dev/kgsl-3d0
-7fff66000-7fff67000 rw-s 0003b000 00:10 20630 /dev/kgsl-3d0
-7fff67000-7fff68000 rw-s 0003a000 00:10 20630 /dev/kgsl-3d0
-7fff68000-7fff69000 rw-s 00039000 00:10 20630 /dev/kgsl-3d0
-7fff69000-7fff6a000 rw-s 00038000 00:10 20630 /dev/kgsl-3d0
-7fff6a000-7fff6b000 rw-s 00037000 00:10 20630 /dev/kgsl-3d0
-7fff6b000-7fff6c000 rw-s 00036000 00:10 20630 /dev/kgsl-3d0
-7fff6c000-7fff6d000 rw-s 00035000 00:10 20630 /dev/kgsl-3d0
-7fff6d000-7fff6e000 rw-s 00034000 00:10 20630 /dev/kgsl-3d0
-7fff6e000-7fff6f000 rw-s 00033000 00:10 20630 /dev/kgsl-3d0
-7fff6f000-7fff70000 rw-s 00032000 00:10 20630 /dev/kgsl-3d0
-7fff70000-7fff71000 rw-s 00031000 00:10 20630 /dev/kgsl-3d0
-7fff71000-7fff72000 rw-s 00030000 00:10 20630 /dev/kgsl-3d0
-7fff72000-7fff73000 rw-s 0002f000 00:10 20630 /dev/kgsl-3d0
-7fff73000-7fff74000 rw-s 0002e000 00:10 20630 /dev/kgsl-3d0
-7fff74000-7fff75000 rw-s 0002d000 00:10 20630 /dev/kgsl-3d0
-7fff75000-7fff76000 rw-s 0002c000 00:10 20630 /dev/kgsl-3d0
-7fff76000-7fff77000 rw-s 0002b000 00:10 20630 /dev/kgsl-3d0
-7fff77000-7fff78000 rw-s 0002a000 00:10 20630 /dev/kgsl-3d0
-7fff78000-7fff79000 rw-s 00029000 00:10 20630 /dev/kgsl-3d0
-7fff79000-7fff7a000 rw-s 00028000 00:10 20630 /dev/kgsl-3d0
-7fff7a000-7fff7b000 rw-s 00027000 00:10 20630 /dev/kgsl-3d0
-7fff7b000-7fff7c000 rw-s 00026000 00:10 20630 /dev/kgsl-3d0
-7fff7c000-7fff7d000 rw-s 00025000 00:10 20630 /dev/kgsl-3d0
-7fff7d000-7fff7e000 rw-s 00024000 00:10 20630 /dev/kgsl-3d0
-7fff7e000-7fff7f000 rw-s 00023000 00:10 20630 /dev/kgsl-3d0
-7fff7f000-7fff80000 rw-s 00022000 00:10 20630 /dev/kgsl-3d0
-7fff80000-7fff90000 rw-s 00019000 00:10 20630 /dev/kgsl-3d0
-7fff90000-7fffb0000 rw-s 00018000 00:10 20630 /dev/kgsl-3d0
-7fffb1000-7fffb2000 rw-s 00021000 00:10 20630 /dev/kgsl-3d0
-7fffb2000-7fffb3000 rw-s 00020000 00:10 20630 /dev/kgsl-3d0
-7fffb3000-7fffb4000 rw-s 0001f000 00:10 20630 /dev/kgsl-3d0
-7fffba000-7fffbe000 rw-s 0001b000 00:10 20630 /dev/kgsl-3d0
-7fffbe000-7fffbf000 rw-s 0001a000 00:10 20630 /dev/kgsl-3d0
-7fffbf000-7fffc0000 rw-s 00017000 00:10 20630 /dev/kgsl-3d0
-7fffc0000-7fffe0000 rw-s 00016000 00:10 20630 /dev/kgsl-3d0
-7fffe0000-7fffe1000 rw-s 00014000 00:10 20630 /dev/kgsl-3d0
-7fffe1000-7fffe5000 rw-s 00013000 00:10 20630 /dev/kgsl-3d0
-7fffe5000-7fffe6000 rw-s 00012000 00:10 20630 /dev/kgsl-3d0
-7fffe6000-7fffe7000 rw-s 00011000 00:10 20630 /dev/kgsl-3d0
-7fffe7000-7fffe8000 rw-s 00010000 00:10 20630 /dev/kgsl-3d0
-7fffe8000-7fffe9000 rw-s 0000f000 00:10 20630 /dev/kgsl-3d0
-7fffe9000-7fffea000 rw-s 0000e000 00:10 20630 /dev/kgsl-3d0
-7fffea000-7fffeb000 rw-s 0000d000 00:10 20630 /dev/kgsl-3d0
-7fffeb000-7fffec000 rw-s 0000c000 00:10 20630 /dev/kgsl-3d0
-7fffec000-7ffff0000 rw-s 0000b000 00:10 20630 /dev/kgsl-3d0
-7ffff0000-7ffff1000 rw-s 0000a000 00:10 20630 /dev/kgsl-3d0
-7ffff1000-7ffff5000 rw-s 00009000 00:10 20630 /dev/kgsl-3d0
-7ffff5000-7ffff6000 rw-s 00008000 00:10 20630 /dev/kgsl-3d0
-7ffff6000-7ffff7000 rw-s 00007000 00:10 20630 /dev/kgsl-3d0
-7ffff7000-7ffff8000 rw-s 00006000 00:10 20630 /dev/kgsl-3d0
-7ffff8000-7ffff9000 rw-s 00005000 00:10 20630 /dev/kgsl-3d0
-7ffff9000-7ffffa000 rw-s 00004000 00:10 20630 /dev/kgsl-3d0
-7ffffa000-7ffffb000 rw-s 00003000 00:10 20630 /dev/kgsl-3d0
-7ffffb000-7ffffc000 rw-s 00002000 00:10 20630 /dev/kgsl-3d0
-7ffffc000-800000000 rw-s 00001000 00:10 20630 /dev/kgsl-3d0
-5ff1d4f000-5ff1d54000 r-xp 00000000 fc:00 3419 /system/bin/app_process64
-5ff1d6e000-5ff1d6f000 r--p 0000f000 fc:00 3419 /system/bin/app_process64
-5ff1d6f000-5ff1d71000 rw-p 00000000 00:00 0
-704defa000-704defb000 ---p 00000000 00:00 0 [anon:thread stack guard]
-704defb000-704defc000 ---p 00000000 00:00 0
-704defc000-704e000000 rw-p 00000000 00:00 0
-704e000000-704e400000 rw-p 00000000 00:00 0 [anon:libc_malloc]
-704e455000-704e456000 ---p 00000000 00:00 0 [anon:thread stack guard]
-704e456000-704e457000 ---p 00000000 00:00 0
-704e457000-704e553000 rw-p 00000000 00:00 0
-704e553000-704e651000 r--p 00000000 00:10 16029 /dev/hwbinder
-704e651000-704e65f000 r-xp 00000000 fc:01 1040 /vendor/lib64/egl/eglSubDriverAndroid.so
-704e65f000-704e660000 r--p 0000e000 fc:01 1040 /vendor/lib64/egl/eglSubDriverAndroid.so
-704e660000-704e661000 rw-p 0000f000 fc:01 1040 /vendor/lib64/egl/eglSubDriverAndroid.so
-704e69d000-704e69e000 ---p 00000000 00:00 0 [anon:thread stack guard]
-704e69e000-704e79b000 rw-p 00000000 00:00 0
-704e79b000-704f79b000 rw-s 00000000 00:05 10271021 /dev/ashmem/AudioFlinger::Client(29312) (deleted)
-704f79b000-704f79c000 ---p 00000000 00:00 0 [anon:thread stack guard]
-704f79c000-704f899000 rw-p 00000000 00:00 0
-704f899000-704f89a000 ---p 00000000 00:00 0 [anon:thread stack guard]
-704f89a000-704f89b000 ---p 00000000 00:00 0
-704f89b000-704f997000 rw-p 00000000 00:00 0
-704f997000-704f9ee000 r-xp 00000000 103:1d 1737338 /data/app/com.google.sample.tunnel-HGGRU03Gu1Mwkf_-RnFmvw==/lib/arm64/libgame.so
-704f9ee000-704f9fd000 ---p 00000000 00:00 0
-704f9fd000-704fa00000 r--p 00056000 103:1d 1737338 /data/app/com.google.sample.tunnel-HGGRU03Gu1Mwkf_-RnFmvw==/lib/arm64/libgame.so
-704fa00000-704fa01000 rw-p 00059000 103:1d 1737338 /data/app/com.google.sample.tunnel-HGGRU03Gu1Mwkf_-RnFmvw==/lib/arm64/libgame.so
-704fa01000-704fa19000 rw-p 00000000 00:00 0 [anon:.bss]
-704fa40000-70507e7000 r-xp 00000000 fc:01 1026 /vendor/lib64/libllvm-glnext.so
-70507e7000-70507fc000 ---p 00000000 00:00 0
-70507fc000-7050835000 r--p 00da7000 fc:01 1026 /vendor/lib64/libllvm-glnext.so
-7050835000-705083a000 rw-p 00de0000 fc:01 1026 /vendor/lib64/libllvm-glnext.so
-705083a000-7050855000 rw-p 00000000 00:00 0 [anon:.bss]
-705089b000-7050f19000 r-xp 00000000 fc:01 1039 /vendor/lib64/egl/libGLESv2_adreno.so
-7050f19000-7050f22000 r--p 0067e000 fc:01 1039 /vendor/lib64/egl/libGLESv2_adreno.so
-7050f22000-7050f29000 rw-p 00687000 fc:01 1039 /vendor/lib64/egl/libGLESv2_adreno.so
-7050f29000-7050f2c000 rw-p 00000000 00:00 0 [anon:.bss]
-7050f83000-7050fbc000 r-xp 00000000 fc:01 1041 /vendor/lib64/egl/libGLESv1_CM_adreno.so
-7050fbc000-7050fbd000 r--p 00039000 fc:01 1041 /vendor/lib64/egl/libGLESv1_CM_adreno.so
-7050fbd000-7050fbe000 rw-p 0003a000 fc:01 1041 /vendor/lib64/egl/libGLESv1_CM_adreno.so
-7050fbe000-7050fbf000 rw-p 00000000 00:00 0 [anon:.bss]
-7050fc6000-705111d000 r-xp 00000000 fc:01 865 /vendor/lib64/libgsl.so
-705111d000-705111e000 r--p 00157000 fc:01 865 /vendor/lib64/libgsl.so
-705111e000-705111f000 rw-p 00158000 fc:01 865 /vendor/lib64/libgsl.so
-705111f000-7051120000 rw-p 00000000 00:00 0 [anon:.bss]
-7051146000-705115d000 r-xp 00000000 fc:00 2587 /system/lib64/vndk-sp-28/libz.so
-705115d000-7051175000 ---p 00000000 00:00 0
-7051175000-7051176000 r--p 0001f000 fc:00 2587 /system/lib64/vndk-sp-28/libz.so
-7051176000-7051177000 rw-p 00020000 fc:00 2587 /system/lib64/vndk-sp-28/libz.so
-705119f000-70511ac000 r-xp 00000000 fc:01 886 /vendor/lib64/libadreno_utils.so
-70511ac000-70511ad000 r--p 0000d000 fc:01 886 /vendor/lib64/libadreno_utils.so
-70511ad000-70511ae000 rw-p 0000e000 fc:01 886 /vendor/lib64/libadreno_utils.so
-70511ae000-70511b0000 rw-p 00000000 00:00 0 [anon:.bss]
-70511c0000-70511d7000 r-xp 00000000 fc:01 1044 /vendor/lib64/egl/libEGL_adreno.so
-70511d7000-70511d8000 r--p 00017000 fc:01 1044 /vendor/lib64/egl/libEGL_adreno.so
-70511d8000-70511d9000 rw-p 00018000 fc:01 1044 /vendor/lib64/egl/libEGL_adreno.so
-70511d9000-70511da000 rw-p 00000000 00:00 0 [anon:.bss]
-705120a000-705120d000 r-xp 00000000 fc:01 972 /vendor/lib64/libdrmutils.so
-705120d000-7051229000 ---p 00000000 00:00 0
-7051229000-705122a000 r--p 0000f000 fc:01 972 /vendor/lib64/libdrmutils.so
-705122a000-705122b000 rw-p 00010000 fc:01 972 /vendor/lib64/libdrmutils.so
-705125a000-705125c000 r-xp 00000000 fc:01 1046 /vendor/lib64/libqdMetaData.so
-705125c000-7051279000 ---p 00000000 00:00 0
-7051279000-705127a000 r--p 0000f000 fc:01 1046 /vendor/lib64/libqdMetaData.so
-705127a000-705127b000 rw-p 00010000 fc:01 1046 /vendor/lib64/libqdMetaData.so
-7051286000-7051297000 r-xp 00000000 fc:01 1024 /vendor/lib64/libdrm.so
-7051297000-70512b5000 ---p 00000000 00:00 0
-70512b5000-70512b6000 r--p 0001f000 fc:01 1024 /vendor/lib64/libdrm.so
-70512b6000-70512b7000 rw-p 00020000 fc:01 1024 /vendor/lib64/libdrm.so
-70512cb000-70512de000 r-xp 00000000 fc:01 1008 /vendor/lib64/hw/gralloc.msm8998.so
-70512de000-70512fa000 ---p 00000000 00:00 0
-70512fa000-70512fb000 r--p 0001f000 fc:01 1008 /vendor/lib64/hw/gralloc.msm8998.so
-70512fb000-70512fc000 rw-p 00020000 fc:01 1008 /vendor/lib64/hw/gralloc.msm8998.so
-7051326000-7051327000 ---p 00000000 00:00 0 [anon:thread stack guard]
-7051327000-7051328000 ---p 00000000 00:00 0
-7051328000-7051424000 rw-p 00000000 00:00 0
-7051424000-705143d000 r--p 00000000 fc:00 739 /system/framework/oat/arm64/org.apache.http.legacy.boot.odex
-705143d000-7051480000 r-xp 00019000 fc:00 739 /system/framework/oat/arm64/org.apache.http.legacy.boot.odex
-7051480000-7051494000 r--p 00211000 103:1d 639511 /data/dalvik-cache/arm64/system@framework@boot.art
-7051494000-705149f000 r--p 000c5000 103:1d 639514 /data/dalvik-cache/arm64/system@framework@boot-core-libart.art
-705149f000-70514a2000 r--p 00032000 103:1d 639517 /data/dalvik-cache/arm64/system@framework@boot-conscrypt.art
-70514a2000-70514a5000 r--p 0002b000 103:1d 639520 /data/dalvik-cache/arm64/system@framework@boot-okhttp.art
-70514a5000-70514ac000 r--p 0003f000 103:1d 639523 /data/dalvik-cache/arm64/system@framework@boot-bouncycastle.art
-70514ac000-70514b2000 r--p 00044000 103:1d 639526 /data/dalvik-cache/arm64/system@framework@boot-apache-xml.art
-70514b2000-70514bd000 r--p 00035000 103:1d 639529 /data/dalvik-cache/arm64/system@framework@boot-ext.art
-70514bd000-70514f4000 r--p 0060f000 103:1d 639532 /data/dalvik-cache/arm64/system@framework@boot-framework.art
-70514f4000-70514fe000 r--p 00054000 103:1d 639535 /data/dalvik-cache/arm64/system@framework@boot-telephony-common.art
-70514fe000-70514ff000 r--p 0000c000 103:1d 639538 /data/dalvik-cache/arm64/system@framework@boot-voip-common.art
-70514ff000-7051500000 r--p 0000e000 103:1d 639541 /data/dalvik-cache/arm64/system@framework@boot-ims-common.art
-7051500000-7051501000 r--p 00004000 103:1d 639547 /data/dalvik-cache/arm64/system@framework@boot-android.hidl.manager-V1.0-java.art
-7051501000-7051502000 r--p 00004000 103:1d 639553 /data/dalvik-cache/arm64/system@framework@boot-android.test.base.art
-7051502000-7051503000 r--p 00001000 103:1d 639556 /data/dalvik-cache/arm64/system@framework@boot-com.google.vr.platform.art
-7051503000-7051504000 rw-p 00000000 00:00 0 [anon:.bss]
-7051504000-7051579000 r--s 00000000 fc:00 790 /system/framework/oat/arm64/org.apache.http.legacy.boot.vdex
-7051579000-705157a000 r--p 0005c000 fc:00 739 /system/framework/oat/arm64/org.apache.http.legacy.boot.odex
-705157a000-705157b000 rw-p 0005d000 fc:00 739 /system/framework/oat/arm64/org.apache.http.legacy.boot.odex
-705158b000-7057f4d000 ---p 00000000 00:00 0
-7057f4d000-7057f4f000 r-xp 00000000 fc:00 2646 /system/lib64/libwebviewchromium_loader.so
-7057f4f000-7057f6c000 ---p 00000000 00:00 0
-7057f6c000-7057f6d000 r--p 0000f000 fc:00 2646 /system/lib64/libwebviewchromium_loader.so
-7057f6d000-7057f6e000 rw-p 00010000 fc:00 2646 /system/lib64/libwebviewchromium_loader.so
-7057f76000-7057f96000 r--s 00000000 00:10 16615 /dev/__properties__/u:object_r:hwservicemanager_prop:s0
-7057f96000-7057fb6000 r--s 00000000 00:10 16639 /dev/__properties__/u:object_r:public_vendor_default_prop:s0
-7057fb6000-7058004000 r--s 00000000 fc:00 1112 /system/usr/hyphen-data/hyph-hu.hyb
-7058004000-7058024000 r-xp 00000000 fc:00 2354 /system/lib64/libcompiler_rt.so
-7058024000-7058043000 ---p 00000000 00:00 0
-7058043000-7058044000 r--p 0002f000 fc:00 2354 /system/lib64/libcompiler_rt.so
-7058044000-7058045000 rw-p 00030000 fc:00 2354 /system/lib64/libcompiler_rt.so
-7058045000-70580b2000 rw-p 00000000 00:00 0 [anon:.bss]
-70580bd000-70580dd000 rw-p 00000000 00:05 10265386 [anon:dalvik-LinearAlloc]
-70580dd000-70580df000 r-xp 00000000 fc:00 2597 /system/lib64/vndk-sp-28/libhardware.so
-70580df000-70580fc000 ---p 00000000 00:00 0
-70580fc000-70580fd000 r--p 0000f000 fc:00 2597 /system/lib64/vndk-sp-28/libhardware.so
-70580fd000-70580fe000 rw-p 00010000 fc:00 2597 /system/lib64/vndk-sp-28/libhardware.so
-705810e000-705811f000 r-xp 00000000 fc:00 2589 /system/lib64/vndk-sp-28/libbase.so
-705811f000-705813d000 ---p 00000000 00:00 0
-705813d000-705813e000 r--p 0001f000 fc:00 2589 /system/lib64/vndk-sp-28/libbase.so
-705813e000-705813f000 rw-p 00020000 fc:00 2589 /system/lib64/vndk-sp-28/libbase.so
-7058140000-7058167000 r-xp 00000000 fc:00 2572 /system/lib64/vndk-sp-28/libhwbinder.so
-7058167000-705817d000 ---p 00000000 00:00 0
-705817d000-705817f000 r--p 0002e000 fc:00 2572 /system/lib64/vndk-sp-28/libhwbinder.so
-705817f000-7058180000 rw-p 00030000 fc:00 2572 /system/lib64/vndk-sp-28/libhwbinder.so
-705818c000-705818d000 r-xp 00000000 fc:00 2584 /system/lib64/vndk-sp-28/android.hardware.graphics.common@1.0.so
-705818d000-70581ab000 ---p 00000000 00:00 0
-70581ab000-70581ac000 r--p 0000f000 fc:00 2584 /system/lib64/vndk-sp-28/android.hardware.graphics.common@1.0.so
-70581ac000-70581ad000 rw-p 00010000 fc:00 2584 /system/lib64/vndk-sp-28/android.hardware.graphics.common@1.0.so
-70581b7000-70581d7000 r--s 00000000 00:10 16619 /dev/__properties__/u:object_r:log_prop:s0
-70581d7000-7058237000 r-xp 00000000 fc:00 2574 /system/lib64/vndk-sp-28/libhidltransport.so
-7058237000-7058255000 ---p 00000000 00:00 0
-7058255000-705825d000 r--p 00068000 fc:00 2574 /system/lib64/vndk-sp-28/libhidltransport.so
-705825d000-705825e000 rw-p 00070000 fc:00 2574 /system/lib64/vndk-sp-28/libhidltransport.so
-7058260000-7058284000 r--s 00000000 fc:00 1138 /system/usr/hyphen-data/hyph-nn.hyb
-7058284000-70582a0000 r-xp 00000000 fc:00 2576 /system/lib64/vndk-sp-28/libutils.so
-70582a0000-70582b3000 ---p 00000000 00:00 0
-70582b3000-70582b4000 r--p 0001f000 fc:00 2576 /system/lib64/vndk-sp-28/libutils.so
-70582b4000-70582b5000 rw-p 00020000 fc:00 2576 /system/lib64/vndk-sp-28/libutils.so
-70582c4000-7058391000 r-xp 00000000 fc:00 2568 /system/lib64/vndk-sp-28/libc++.so
-7058391000-70583ad000 ---p 00000000 00:00 0
-70583ad000-70583b7000 r--p 000d6000 fc:00 2568 /system/lib64/vndk-sp-28/libc++.so
-70583b7000-70583b8000 rw-p 000e0000 fc:00 2568 /system/lib64/vndk-sp-28/libc++.so
-70583b8000-70583bb000 rw-p 00000000 00:00 0 [anon:.bss]
-70583cd000-70583e4000 r-xp 00000000 fc:00 2580 /system/lib64/vndk-sp-28/android.hardware.graphics.mapper@2.0.so
-70583e4000-70583f9000 ---p 00000000 00:00 0
-70583f9000-70583fb000 r--p 0001e000 fc:00 2580 /system/lib64/vndk-sp-28/android.hardware.graphics.mapper@2.0.so
-70583fb000-70583fc000 rw-p 00020000 fc:00 2580 /system/lib64/vndk-sp-28/android.hardware.graphics.mapper@2.0.so
-705841b000-7058421000 r-xp 00000000 fc:01 1001 /vendor/lib64/hw/android.hardware.graphics.mapper@2.0-impl.so
-7058421000-705843a000 ---p 00000000 00:00 0
-705843a000-705843b000 r--p 0000f000 fc:01 1001 /vendor/lib64/hw/android.hardware.graphics.mapper@2.0-impl.so
-705843b000-705843c000 rw-p 00010000 fc:01 1001 /vendor/lib64/hw/android.hardware.graphics.mapper@2.0-impl.so
-705844f000-7058473000 r--s 00000000 fc:00 1150 /system/usr/hyphen-data/hyph-nb.hyb
-7058473000-7058495000 r-xp 00000000 fc:00 2582 /system/lib64/vndk-sp-28/libhidlbase.so
-7058495000-70584b1000 ---p 00000000 00:00 0
-70584b1000-70584b3000 r--p 0002e000 fc:00 2582 /system/lib64/vndk-sp-28/libhidlbase.so
-70584b3000-70584b4000 rw-p 00030000 fc:00 2582 /system/lib64/vndk-sp-28/libhidlbase.so
-70584cd000-70584df000 r-xp 00000000 fc:00 2595 /system/lib64/vndk-sp-28/libcutils.so
-70584df000-70584fb000 ---p 00000000 00:00 0
-70584fb000-70584fd000 r--p 0001e000 fc:00 2595 /system/lib64/vndk-sp-28/libcutils.so
-70584fd000-70584fe000 rw-p 00020000 fc:00 2595 /system/lib64/vndk-sp-28/libcutils.so
-7058519000-7058537000 r--s 00000000 fc:00 1124 /system/usr/hyphen-data/hyph-de-ch-1901.hyb
-7058537000-7059fd1000 r--s 0070b000 fc:00 989 /system/framework/framework-res.apk
-7059fd1000-705a013000 r-xp 00000000 fc:00 2610 /system/lib64/libjavacrypto.so
-705a013000-705a02b000 ---p 00000000 00:00 0
-705a02b000-705a02d000 r--p 0004e000 fc:00 2610 /system/lib64/libjavacrypto.so
-705a02d000-705a02f000 rw-p 00050000 fc:00 2610 /system/lib64/libjavacrypto.so
-705a041000-705a05f000 r--s 00000000 fc:00 1128 /system/usr/hyphen-data/hyph-de-1996.hyb
-705a05f000-705a06a000 r-xp 00000000 fc:00 2917 /system/lib64/libsoundpool.so
-705a06a000-705a07e000 ---p 00000000 00:00 0
-705a07e000-705a07f000 r--p 0000f000 fc:00 2917 /system/lib64/libsoundpool.so
-705a07f000-705a080000 rw-p 00010000 fc:00 2917 /system/lib64/libsoundpool.so
-705a087000-705a102000 r--s 00000000 fc:00 1246 /system/usr/share/zoneinfo/tzdata
-705a102000-705a863000 r--s 00000000 fc:00 101 /system/fonts/NotoColorEmoji.ttf
-705a863000-705c000000 r--s 00000000 fc:00 251 /system/fonts/NotoSerifCJK-Regular.ttc
-705c000000-705c200000 rw-p 00000000 00:00 0 [anon:libc_malloc]
-705c209000-705c227000 r--s 00000000 fc:00 1077 /system/usr/hyphen-data/hyph-de-1901.hyb
-705c227000-705c26e000 r--s 02284000 fc:00 989 /system/framework/framework-res.apk
-705c26e000-705d43e000 r--s 00000000 fc:00 95 /system/fonts/NotoSansCJK-Regular.ttc
-705d43e000-705d4ec000 r--s 00000000 fc:00 278 /system/fonts/NotoSansSymbols-Regular-Subsetted.ttf
-705d4ec000-705d548000 r--s 00000000 fc:00 233 /system/fonts/NotoSansTibetan-Bold.ttf
-705d548000-705d5ab000 r--s 00000000 fc:00 177 /system/fonts/NotoSansTibetan-Regular.ttf
-705d5ab000-705d627000 r--s 00000000 fc:00 197 /system/fonts/NotoSansEgyptianHieroglyphs-Regular.ttf
-705d627000-705d6a2000 r--s 00000000 fc:00 76 /system/fonts/NotoSansCuneiform-Regular.ttf
-705d6a2000-705d6f3000 r--s 00000000 fc:00 67 /system/fonts/RobotoCondensed-BoldItalic.ttf
-705d6f3000-705d73e000 r--s 00000000 fc:00 199 /system/fonts/RobotoCondensed-Bold.ttf
-705d73e000-705d78f000 r--s 00000000 fc:00 230 /system/fonts/RobotoCondensed-MediumItalic.ttf
-705d78f000-705d7da000 r--s 00000000 fc:00 92 /system/fonts/RobotoCondensed-Medium.ttf
-705d7da000-705d82b000 r--s 00000000 fc:00 128 /system/fonts/RobotoCondensed-Italic.ttf
-705d82b000-705d875000 r--s 00000000 fc:00 164 /system/fonts/RobotoCondensed-Regular.ttf
-705d875000-705d8c7000 r--s 00000000 fc:00 292 /system/fonts/RobotoCondensed-LightItalic.ttf
-705d8c7000-705d919000 r--s 00000000 fc:00 85 /system/fonts/Roboto-BoldItalic.ttf
-705d919000-705d964000 r--s 00000000 fc:00 175 /system/fonts/Roboto-Bold.ttf
-705d964000-705d9b5000 r--s 00000000 fc:00 266 /system/fonts/Roboto-BlackItalic.ttf
-705d9b5000-705da00000 r--s 00000000 fc:00 187 /system/fonts/Roboto-Black.ttf
-705da00000-705dc00000 rw-p 00000000 00:00 0 [anon:libc_malloc]
-705dc1d000-705dc6e000 r--s 00000000 fc:00 148 /system/fonts/Roboto-MediumItalic.ttf
-705dc6e000-705dcb9000 r--s 00000000 fc:00 284 /system/fonts/Roboto-Medium.ttf
-705dcb9000-705dd0a000 r--s 00000000 fc:00 105 /system/fonts/Roboto-Italic.ttf
-705dd0a000-705dd55000 r--s 00000000 fc:00 156 /system/fonts/Roboto-Regular.ttf
-705dd55000-705dda7000 r--s 00000000 fc:00 217 /system/fonts/Roboto-LightItalic.ttf
-705dda7000-705ddf8000 r--s 00000000 fc:00 166 /system/fonts/Roboto-ThinItalic.ttf
-705ddf8000-705ddf9000 ---p 00000000 00:00 0 [anon:thread stack guard]
-705ddf9000-705ddfa000 ---p 00000000 00:00 0
-705ddfa000-705def6000 rw-p 00000000 00:00 0
-705def6000-705f5ec000 r--s 00000000 fc:00 1350 /system/usr/icu/icudt60l.dat
-705f5ec000-705f5ed000 ---p 00000000 00:00 0 [anon:thread stack guard]
-705f5ed000-705f5ee000 ---p 00000000 00:00 0
-705f5ee000-705f6ea000 rw-p 00000000 00:00 0
-705f6ea000-705f7e8000 r--p 00000000 00:10 20636 /dev/binder
-705f7e8000-705f7e9000 ---p 00000000 00:00 0 [anon:thread stack guard]
-705f7e9000-705f7ea000 ---p 00000000 00:00 0
-705f7ea000-705f8ee000 rw-p 00000000 00:00 0
-705f8ee000-705f8ef000 ---p 00000000 00:00 0 [anon:thread stack guard]
-705f8ef000-705f8f0000 ---p 00000000 00:00 0
-705f8f0000-705f9f4000 rw-p 00000000 00:00 0
-705f9f4000-705f9f5000 ---p 00000000 00:00 0 [anon:thread stack guard]
-705f9f5000-705f9f6000 ---p 00000000 00:00 0
-705f9f6000-705fafa000 rw-p 00000000 00:00 0
-705fafa000-705fafb000 ---p 00000000 00:00 0 [anon:thread stack guard]
-705fafb000-705fafc000 ---p 00000000 00:00 0
-705fafc000-705fc00000 rw-p 00000000 00:00 0
-705fc00000-705fe00000 rw-p 00000000 00:00 0 [anon:libc_malloc]
-705fe01000-705fe4c000 r--s 00000000 fc:00 97 /system/fonts/Roboto-Light.ttf
-705fe4c000-705fe4d000 ---p 00000000 00:00 0 [anon:thread stack guard]
-705fe4d000-705fe4e000 ---p 00000000 00:00 0
-705fe4e000-705ff4a000 rw-p 00000000 00:00 0
-705ff4a000-705ff4b000 ---p 00000000 00:05 10270991 [anon:dalvik-Jit thread pool worker thread 0]
-705ff4b000-705ff4c000 ---p 00001000 00:05 10270991 [anon:dalvik-Jit thread pool worker thread 0]
-705ff4c000-706004b000 rw-p 00002000 00:05 10270991 [anon:dalvik-Jit thread pool worker thread 0]
-706004b000-706010f000 r-xp 00000000 fc:00 2390 /system/lib64/libvixl-arm64.so
-706010f000-7060120000 ---p 00000000 00:00 0
-7060120000-7060125000 r--p 000cb000 fc:00 2390 /system/lib64/libvixl-arm64.so
-7060125000-7060126000 rw-p 000d0000 fc:00 2390 /system/lib64/libvixl-arm64.so
-7060126000-706012d000 rw-p 00000000 00:00 0 [anon:.bss]
-7060135000-7060151000 r--s 00000000 fc:01 1180 /vendor/overlay/framework-res__auto_generated_rro.apk
-7060151000-7060263000 r-xp 00000000 fc:00 2669 /system/lib64/libvixl-arm.so
-7060263000-7060275000 ---p 00000000 00:00 0
-7060275000-706027a000 r--p 0011b000 fc:00 2669 /system/lib64/libvixl-arm.so
-706027a000-706027b000 rw-p 00120000 fc:00 2669 /system/lib64/libvixl-arm.so
-706028b000-706056c000 r-xp 00000000 fc:00 2972 /system/lib64/libart-compiler.so
-706056c000-7060580000 ---p 00000000 00:00 0
-7060580000-7060598000 r--p 002e8000 fc:00 2972 /system/lib64/libart-compiler.so
-7060598000-7060599000 rw-p 00300000 fc:00 2972 /system/lib64/libart-compiler.so
-7060599000-70605a0000 rw-p 00000000 00:00 0 [anon:.bss]
-70605b0000-70605d0000 r--s 00000000 00:10 16571 /dev/__properties__/u:object_r:config_prop:s0
-70605d0000-7060619000 r-xp 00000000 fc:00 2702 /system/lib64/libssl.so
-7060619000-706062d000 ---p 00000000 00:00 0
-706062d000-7060630000 r--p 0004d000 fc:00 2702 /system/lib64/libssl.so
-7060630000-7060631000 rw-p 00050000 fc:00 2702 /system/lib64/libssl.so
-7060647000-7060667000 r--s 00000000 00:10 16595 /dev/__properties__/u:object_r:exported3_radio_prop:s0
-7060667000-706069d000 r-xp 00000000 fc:00 2371 /system/lib64/libopenjdk.so
-706069d000-70606b2000 ---p 00000000 00:00 0
-70606b2000-70606b4000 r--p 0003e000 fc:00 2371 /system/lib64/libopenjdk.so
-70606b4000-70606b6000 rw-p 00040000 fc:00 2371 /system/lib64/libopenjdk.so
-70606bb000-70606db000 r--s 00000000 00:10 16608 /dev/__properties__/u:object_r:exported_system_prop:s0
-70606db000-70606e3000 r-xp 00000000 fc:00 2538 /system/lib64/libopenjdkjvm.so
-70606e3000-70606fa000 ---p 00000000 00:00 0
-70606fa000-70606fb000 r--p 0000f000 fc:00 2538 /system/lib64/libopenjdkjvm.so
-70606fb000-70606fc000 rw-p 00010000 fc:00 2538 /system/lib64/libopenjdkjvm.so
-7060701000-7060722000 r--s 00000000 fc:00 227 /system/fonts/NotoSansAnatolianHieroglyphs-Regular.otf
-7060722000-7061e18000 r--s 00000000 fc:00 1350 /system/usr/icu/icudt60l.dat
-7061e18000-7061e5d000 r-xp 00000000 fc:00 2368 /system/lib64/libjavacore.so
-7061e5d000-7061e71000 ---p 00000000 00:00 0
-7061e71000-7061e73000 r--p 0004e000 fc:00 2368 /system/lib64/libjavacore.so
-7061e73000-7061e75000 rw-p 00050000 fc:00 2368 /system/lib64/libjavacore.so
-7061e75000-7061e76000 rw-p 00000000 00:00 0 [anon:.bss]
-7061e77000-7061e96000 r--s 00000000 fc:00 186 /system/fonts/NotoSansYi-Regular.ttf
-7061e96000-7061e99000 r-xp 00000000 fc:00 2953 /system/lib64/libwebviewchromium_plat_support.so
-7061e99000-7061eb5000 ---p 00000000 00:00 0
-7061eb5000-7061eb6000 r--p 0000f000 fc:00 2953 /system/lib64/libwebviewchromium_plat_support.so
-7061eb6000-7061eb7000 rw-p 00010000 fc:00 2953 /system/lib64/libwebviewchromium_plat_support.so
-7061ebc000-7061edd000 r--s 00000000 fc:00 100 /system/fonts/NotoSansBamum-Regular.ttf
-7061edd000-7061eed000 r-xp 00000000 fc:00 2945 /system/lib64/libRS.so
-7061eed000-7061efc000 ---p 00000000 00:00 0
-7061efc000-7061efd000 r--p 0000f000 fc:00 2945 /system/lib64/libRS.so
-7061efd000-7061efe000 rw-p 00010000 fc:00 2945 /system/lib64/libRS.so
-7061f05000-7061f6b000 r-xp 00000000 fc:00 2423 /system/lib64/android.hardware.renderscript@1.0.so
-7061f6b000-7061f7a000 ---p 00000000 00:00 0
-7061f7a000-7061f7f000 r--p 0006b000 fc:00 2423 /system/lib64/android.hardware.renderscript@1.0.so
-7061f7f000-7061f80000 rw-p 00070000 fc:00 2423 /system/lib64/android.hardware.renderscript@1.0.so
-7061f99000-7061f9b000 r-xp 00000000 fc:00 2614 /system/lib64/libOpenSLES.so
-7061f9b000-7061fb8000 ---p 00000000 00:00 0
-7061fb8000-7061fb9000 r--p 0000f000 fc:00 2614 /system/lib64/libOpenSLES.so
-7061fb9000-7061fba000 rw-p 00010000 fc:00 2614 /system/lib64/libOpenSLES.so
-7061fc6000-7061fc8000 r-xp 00000000 fc:00 2963 /system/lib64/libOpenMAXAL.so
-7061fc8000-7061fe5000 ---p 00000000 00:00 0
-7061fe5000-7061fe6000 r--p 0000f000 fc:00 2963 /system/lib64/libOpenMAXAL.so
-7061fe6000-7061fe7000 rw-p 00010000 fc:00 2963 /system/lib64/libOpenMAXAL.so
-7061fe7000-7062000000 r--s 00000000 fc:00 143 /system/fonts/NotoSansBhaiksuki-Regular.otf
-7062000000-7062003000 r-xp 00000000 fc:00 2447 /system/lib64/libtextclassifier_hash.so
-7062003000-706201f000 ---p 00000000 00:00 0
-706201f000-7062020000 r--p 0000f000 fc:00 2447 /system/lib64/libtextclassifier_hash.so
-7062020000-7062021000 rw-p 00010000 fc:00 2447 /system/lib64/libtextclassifier_hash.so
-7062022000-7062042000 rw-p 00000000 00:05 10269731 [anon:dalvik-CompilerMetadata]
-7062042000-7062077000 r-xp 00000000 fc:00 2372 /system/lib64/android.hardware.neuralnetworks@1.0.so
-7062077000-7062095000 ---p 00000000 00:00 0
-7062095000-706209b000 r--p 0003a000 fc:00 2372 /system/lib64/android.hardware.neuralnetworks@1.0.so
-706209b000-706209c000 rw-p 00040000 fc:00 2372 /system/lib64/android.hardware.neuralnetworks@1.0.so
-70620a9000-70620c9000 rw-p 00000000 00:05 10269730 [anon:dalvik-CompilerMetadata]
-70620c9000-70620e3000 r-xp 00000000 fc:00 2956 /system/lib64/android.hardware.neuralnetworks@1.1.so
-70620e3000-70620f4000 ---p 00000000 00:00 0
-70620f4000-70620f7000 r--p 0001d000 fc:00 2956 /system/lib64/android.hardware.neuralnetworks@1.1.so
-70620f7000-70620f8000 rw-p 00020000 fc:00 2956 /system/lib64/android.hardware.neuralnetworks@1.1.so
-706210b000-70621d0000 r-xp 00000000 fc:00 2387 /system/lib64/libneuralnetworks.so
-70621d0000-70621e3000 ---p 00000000 00:00 0
-70621e3000-70621e5000 r--p 000ce000 fc:00 2387 /system/lib64/libneuralnetworks.so
-70621e5000-70621e7000 rw-p 000d0000 fc:00 2387 /system/lib64/libneuralnetworks.so
-70621e7000-7062372000 rw-p 00000000 00:00 0 [anon:.bss]
-7062373000-7062395000 r--s 00000000 fc:00 274 /system/fonts/NotoSerifMyanmar-Bold.otf
-7062395000-7062398000 r-xp 00000000 fc:00 2937 /system/lib64/libjnigraphics.so
-7062398000-70623b4000 ---p 00000000 00:00 0
-70623b4000-70623b5000 r--p 0000f000 fc:00 2937 /system/lib64/libjnigraphics.so
-70623b5000-70623b6000 rw-p 00010000 fc:00 2937 /system/lib64/libjnigraphics.so
-70623c8000-70623e0000 r-xp 00000000 fc:00 2662 /system/lib64/libGLESv3.so
-70623e0000-70623f7000 ---p 00000000 00:00 0
-70623f7000-70623f8000 r--p 0001f000 fc:00 2662 /system/lib64/libGLESv3.so
-70623f8000-70623f9000 rw-p 00020000 fc:00 2662 /system/lib64/libGLESv3.so
-70623fc000-706241c000 rw-p 00000000 00:05 10269729 [anon:dalvik-CompilerMetadata]
-706241c000-7062444000 r-xp 00000000 fc:00 2603 /system/lib64/libexif.so
-7062444000-706245f000 ---p 00000000 00:00 0
-706245f000-7062472000 r--p 0002d000 fc:00 2603 /system/lib64/libexif.so
-7062472000-7062473000 rw-p 00040000 fc:00 2603 /system/lib64/libexif.so
-7062474000-7062490000 r--s 00000000 fc:00 286 /system/fonts/NotoSansMongolian-Regular.ttf
-7062490000-7062491000 r-xp 00000000 fc:00 2357 /system/lib64/libasyncio.so
-7062491000-70624af000 ---p 00000000 00:00 0
-70624af000-70624b0000 r--p 0000f000 fc:00 2357 /system/lib64/libasyncio.so
-70624b0000-70624b1000 rw-p 00010000 fc:00 2357 /system/lib64/libasyncio.so
-70624b5000-70624cf000 r--s 00000000 fc:00 221 /system/fonts/NotoSansMyanmarUI-Bold.ttf
-70624cf000-7062508000 r-xp 00000000 fc:00 2401 /system/lib64/libmtp.so
-7062508000-7062522000 ---p 00000000 00:00 0
-7062522000-7062525000 r--p 0003d000 fc:00 2401 /system/lib64/libmtp.so
-7062525000-706252c000 rw-p 00040000 fc:00 2401 /system/lib64/libmtp.so
-7062530000-7062550000 rw-p 00000000 00:05 10269728 [anon:dalvik-CompilerMetadata]
-7062550000-7062572000 r--s 00000000 fc:00 234 /system/fonts/NotoSerifMyanmar-Regular.otf
-7062572000-706259e000 r-xp 00000000 fc:00 2620 /system/lib64/libmediandk.so
-706259e000-70625b9000 ---p 00000000 00:00 0
-70625b9000-70625bc000 r--p 0002d000 fc:00 2620 /system/lib64/libmediandk.so
-70625bc000-70625c0000 rw-p 00030000 fc:00 2620 /system/lib64/libmediandk.so
-70625c2000-70625d1000 r-xp 00000000 fc:00 2613 /system/lib64/libmidi.so
-70625d1000-70625ef000 ---p 00000000 00:00 0
-70625ef000-70625f1000 r--p 0000e000 fc:00 2613 /system/lib64/libmidi.so
-70625f1000-70625f2000 rw-p 00010000 fc:00 2613 /system/lib64/libmidi.so
-7062600000-7062621000 r-xp 00000000 fc:00 2366 /system/lib64/libmediadrmmetrics_lite.so
-7062621000-706263d000 ---p 00000000 00:00 0
-706263d000-706263f000 r--p 0002e000 fc:00 2366 /system/lib64/libmediadrmmetrics_lite.so
-706263f000-7062640000 rw-p 00030000 fc:00 2366 /system/lib64/libmediadrmmetrics_lite.so
-706264b000-706266b000 rw-p 00000000 00:05 10269727 [anon:dalvik-CompilerMetadata]
-706266b000-70626d4000 r-xp 00000000 fc:00 2727 /system/lib64/libmedia_jni.so
-70626d4000-70626eb000 ---p 00000000 00:00 0
-70626eb000-70626f2000 r--p 00069000 fc:00 2727 /system/lib64/libmedia_jni.so
-70626f2000-70626f3000 rw-p 00070000 fc:00 2727 /system/lib64/libmedia_jni.so
-7062703000-7062732000 r-xp 00000000 fc:00 2399 /system/lib64/libcamera2ndk.so
-7062732000-7062748000 ---p 00000000 00:00 0
-7062748000-706274b000 r--p 0003d000 fc:00 2399 /system/lib64/libcamera2ndk.so
-706274b000-7062750000 rw-p 00040000 fc:00 2399 /system/lib64/libcamera2ndk.so
-7062768000-7062788000 rw-p 00000000 00:05 10269726 [anon:dalvik-CompilerMetadata]
-7062788000-70627ee000 r-xp 00000000 fc:00 2974 /system/lib64/android.hardware.drm@1.0.so
-70627ee000-7062805000 ---p 00000000 00:00 0
-7062805000-706280d000 r--p 00068000 fc:00 2974 /system/lib64/android.hardware.drm@1.0.so
-706280d000-706280e000 rw-p 00070000 fc:00 2974 /system/lib64/android.hardware.drm@1.0.so
-706281a000-706281b000 ---p 00000000 00:00 0 [anon:thread signal stack guard]
-706281b000-706281f000 rw-p 00000000 00:00 0 [anon:thread signal stack]
-706281f000-7062843000 r--s 00000000 fc:00 142 /system/fonts/NotoSansKhmer-VF.ttf
-7062843000-7062886000 r-xp 00000000 fc:00 2637 /system/lib64/android.hardware.drm@1.1.so
-7062886000-70628a5000 ---p 00000000 00:00 0
-70628a5000-70628ab000 r--p 0004a000 fc:00 2637 /system/lib64/android.hardware.drm@1.1.so
-70628ab000-70628ac000 rw-p 00050000 fc:00 2637 /system/lib64/android.hardware.drm@1.1.so
-70628b0000-70628b1000 ---p 00000000 00:00 0 [anon:thread signal stack guard]
-70628b1000-70628b5000 rw-p 00000000 00:00 0 [anon:thread signal stack]
-70628b5000-70628db000 r--s 00000000 fc:00 137 /system/fonts/NotoSansSinhala-Bold.ttf
-70628db000-7062907000 r-xp 00000000 fc:00 2478 /system/lib64/libmediadrm.so
-7062907000-7062918000 ---p 00000000 00:00 0
-7062918000-7062920000 r--p 00038000 fc:00 2478 /system/lib64/libmediadrm.so
-7062920000-7062921000 rw-p 00040000 fc:00 2478 /system/lib64/libmediadrm.so
-7062922000-7062929000 rw-p 00000000 fc:00 583 /system/etc/event-log-tags
-7062929000-7062951000 r--s 00000000 fc:00 296 /system/fonts/NotoSansSinhala-Regular.ttf
-7062951000-7062997000 r-xp 00000000 fc:00 2448 /system/lib64/libaaudio.so
-7062997000-70629ac000 ---p 00000000 00:00 0
-70629ac000-70629b2000 r--p 0004a000 fc:00 2448 /system/lib64/libaaudio.so
-70629b2000-70629ba000 rw-p 00050000 fc:00 2448 /system/lib64/libaaudio.so
-70629ba000-70629bb000 ---p 00000000 00:00 0 [anon:thread signal stack guard]
-70629bb000-70629bf000 rw-p 00000000 00:00 0 [anon:thread signal stack]
-70629bf000-70629c0000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70629c0000-70629c3000 rw-p 00000000 00:00 0 [anon:bionic TLS]
-70629c3000-70629c4000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70629c4000-70629c5000 ---p 00000000 00:00 0 [anon:thread signal stack guard]
-70629c5000-70629c9000 rw-p 00000000 00:00 0 [anon:thread signal stack]
-70629c9000-70629e3000 r-xp 00000000 fc:00 2940 /system/lib64/libandroid.so
-70629e3000-70629f3000 ---p 00000000 00:00 0
-70629f3000-70629f6000 r--p 0001d000 fc:00 2940 /system/lib64/libandroid.so
-70629f6000-70629f7000 rw-p 00020000 fc:00 2940 /system/lib64/libandroid.so
-70629f8000-70629f9000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70629f9000-70629fc000 rw-p 00000000 00:00 0 [anon:bionic TLS]
-70629fc000-70629fd000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70629fd000-7062a3e000 r--s 00000000 fc:00 216 /system/fonts/NotoSerif-BoldItalic.ttf
-7062a3e000-7062b06000 rw-p 00000000 00:05 10270984 [anon:dalvik-indirect ref table]
-7062b06000-7062bce000 rw-p 00000000 00:05 10270983 [anon:dalvik-indirect ref table]
-7062bce000-7062dce000 rw-p 00000000 00:05 10270726 [anon:dalvik-rb copying gc mark stack]
-7062dce000-70635ce000 rw-p 00000000 00:05 10270725 [anon:dalvik-concurrent copying gc mark stack]
-70635ce000-7063dcf000 rw-p 00000000 00:05 10270724 [anon:dalvik-live stack]
-7063dcf000-70645d0000 rw-p 00000000 00:05 10270723 [anon:dalvik-allocation stack]
-70645d0000-70649d1000 rw-p 00000000 00:05 10270721 [anon:dalvik-card table]
-70649d1000-7064ad1000 rw-p 00000000 00:05 10267648 [anon:dalvik-large object free list space allocation info map]
-7064ad1000-7065ad1000 rw-p 00000000 00:05 10267644 [anon:dalvik-region space live bitmap]
-7065ad1000-7065bd1000 rw-p 00000000 00:05 10267642 [anon:dalvik-allocspace zygote / non moving space mark-bitmap 0]
-7065bd1000-7065cd1000 rw-p 00000000 00:05 10267641 [anon:dalvik-allocspace zygote / non moving space live-bitmap 0]
-7065cd1000-7065cd2000 r-xp 00000000 fc:00 2946 /system/lib64/libsigchain.so
-7065cd2000-7065cf0000 ---p 00000000 00:00 0
-7065cf0000-7065cf1000 r--p 0000f000 fc:00 2946 /system/lib64/libsigchain.so
-7065cf1000-7065cf2000 rw-p 00010000 fc:00 2946 /system/lib64/libsigchain.so
-7065cf4000-7065d0f000 r--s 00000000 fc:00 190 /system/fonts/NotoSansMyanmar-Bold.ttf
-7065d0f000-7065d22000 r-xp 00000000 fc:00 2405 /system/lib64/liblz4.so
-7065d22000-7065d3e000 ---p 00000000 00:00 0
-7065d3e000-7065d3f000 r--p 0001f000 fc:00 2405 /system/lib64/liblz4.so
-7065d3f000-7065d40000 rw-p 00020000 fc:00 2405 /system/lib64/liblz4.so
-7065d40000-7065d5a000 r--s 00000000 fc:00 222 /system/fonts/NotoSansMyanmarUI-Regular.ttf
-7065d5a000-7065d5e000 r-xp 00000000 fc:00 2609 /system/lib64/libtombstoned_client.so
-7065d5e000-7065d79000 ---p 00000000 00:00 0
-7065d79000-7065d7a000 r--p 0000f000 fc:00 2609 /system/lib64/libtombstoned_client.so
-7065d7a000-7065d7b000 rw-p 00010000 fc:00 2609 /system/lib64/libtombstoned_client.so
-7065d7f000-7065d80000 ---p 00000000 00:00 0 [anon:thread signal stack guard]
-7065d80000-7065d84000 rw-p 00000000 00:00 0 [anon:thread signal stack]
-7065d84000-706636e000 r-xp 00000000 fc:00 2671 /system/lib64/libart.so
-706636e000-706638d000 ---p 00000000 00:00 0
-706638d000-706639e000 r--p 005ef000 fc:00 2671 /system/lib64/libart.so
-706639e000-70663a1000 rw-p 00600000 fc:00 2671 /system/lib64/libart.so
-70663a1000-70663a4000 rw-p 00000000 00:00 0 [anon:.bss]
-70663a6000-70663c6000 rw-p 00000000 00:05 10269725 [anon:dalvik-CompilerMetadata]
-70663c6000-70663c8000 r-xp 00000000 fc:00 2673 /system/lib64/libmetricslogger.so
-70663c8000-70663e5000 ---p 00000000 00:00 0
-70663e5000-70663e6000 r--p 0000f000 fc:00 2673 /system/lib64/libmetricslogger.so
-70663e6000-70663e7000 rw-p 00010000 fc:00 2673 /system/lib64/libmetricslogger.so
-70663e7000-7066400000 r--s 00000000 fc:00 110 /system/fonts/NotoSansLepcha-Regular.ttf
-7066400000-7066800000 rw-p 00000000 00:00 0 [anon:libc_malloc]
-7066803000-706681e000 r--s 00000000 fc:00 297 /system/fonts/NotoSansMyanmar-Regular.ttf
-706681e000-7066821000 r--p 00000000 00:00 0 [anon:cfi shadow]
-7066821000-7066822000 r--p 00000000 00:00 0 [anon:cfi shadow]
-7066822000-7066b1d000 r--p 00000000 00:00 0 [anon:cfi shadow]
-7066b1d000-7066b1e000 r--p 00000000 00:00 0 [anon:cfi shadow]
-7066b1e000-7066ba0000 r--p 00000000 00:00 0 [anon:cfi shadow]
-7066ba0000-7066ba1000 r--p 00000000 00:00 0 [anon:cfi shadow]
-7066ba1000-7066ba2000 r--p 00000000 00:00 0 [anon:cfi shadow]
-7066ba2000-7066ba5000 r--p 00000000 00:00 0 [anon:cfi shadow]
-7066ba5000-7066ba6000 r--p 00000000 00:00 0 [anon:cfi shadow]
-7066ba6000-70e681e000 r--p 00000000 00:00 0 [anon:cfi shadow]
-70e681e000-70e6854000 r-xp 00000000 fc:00 2431 /system/lib64/libstagefright_foundation.so
-70e6854000-70e6865000 ---p 00000000 00:00 0
-70e6865000-70e6867000 r--p 0003e000 fc:00 2431 /system/lib64/libstagefright_foundation.so
-70e6867000-70e686c000 rw-p 00040000 fc:00 2431 /system/lib64/libstagefright_foundation.so
-70e686d000-70e686e000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70e686e000-70e6871000 rw-p 00000000 00:00 0 [anon:bionic TLS]
-70e6871000-70e6873000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70e6873000-70e6876000 rw-p 00000000 00:00 0 [anon:bionic TLS]
-70e6876000-70e6877000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70e6877000-70e688c000 r--s 00000000 fc:00 301 /system/fonts/NotoSansSinhalaUI-Bold.otf
-70e688c000-70e688e000 r-xp 00000000 fc:00 2943 /system/lib64/libion.so
-70e688e000-70e68ab000 ---p 00000000 00:00 0
-70e68ab000-70e68ac000 r--p 0000f000 fc:00 2943 /system/lib64/libion.so
-70e68ac000-70e68ad000 rw-p 00010000 fc:00 2943 /system/lib64/libion.so
-70e68ad000-70e68af000 rw-p 00000000 00:05 10282496 [anon:dalvik-indirect ref table]
-70e68af000-70e68b1000 rw-p 00000000 00:05 10282493 [anon:dalvik-indirect ref table]
-70e68b1000-70e68ee000 r--s 00000000 fc:00 256 /system/fonts/NotoSerif-Italic.ttf
-70e68ee000-70e6910000 r-xp 00000000 fc:00 2502 /system/lib64/libhidlbase.so
-70e6910000-70e692c000 ---p 00000000 00:00 0
-70e692c000-70e692e000 r--p 0002e000 fc:00 2502 /system/lib64/libhidlbase.so
-70e692e000-70e692f000 rw-p 00030000 fc:00 2502 /system/lib64/libhidlbase.so
-70e6930000-70e693f000 r--s 00000000 fc:00 1082 /system/usr/hyphen-data/hyph-en-us.hyb
-70e693f000-70e6954000 r--s 00000000 fc:00 138 /system/fonts/NotoSansSinhalaUI-Regular.otf
-70e6954000-70e6978000 r-xp 00000000 fc:00 2482 /system/lib64/libui.so
-70e6978000-70e6992000 ---p 00000000 00:00 0
-70e6992000-70e6994000 r--p 0002e000 fc:00 2482 /system/lib64/libui.so
-70e6994000-70e6995000 rw-p 00030000 fc:00 2482 /system/lib64/libui.so
-70e6996000-70e69a2000 r--s 00000000 fc:00 1117 /system/usr/hyphen-data/hyph-en-gb.hyb
-70e69a2000-70e69b7000 r--s 00000000 fc:00 202 /system/fonts/NotoSerifSinhala-Bold.otf
-70e69b7000-70e69cb000 r--s 00000000 fc:00 124 /system/fonts/NotoSansOriyaUI-Bold.ttf
-70e69cb000-70e69e1000 r-xp 00000000 fc:00 2537 /system/lib64/liblog.so
-70e69e1000-70e69fa000 ---p 00000000 00:00 0
-70e69fa000-70e69fb000 r--p 0001f000 fc:00 2537 /system/lib64/liblog.so
-70e69fb000-70e69fc000 rw-p 00020000 fc:00 2537 /system/lib64/liblog.so
-70e69fc000-70e69fe000 rw-p 00000000 00:05 10266158 [anon:dalvik-indirect ref table]
-70e69fe000-70e69ff000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70e69ff000-70e6a02000 rw-p 00000000 00:00 0 [anon:bionic TLS]
-70e6a02000-70e6a03000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70e6a03000-70e6a05000 r-xp 00000000 fc:00 2489 /system/lib64/android.hidl.token@1.0-utils.so
-70e6a05000-70e6a22000 ---p 00000000 00:00 0
-70e6a22000-70e6a23000 r--p 0000f000 fc:00 2489 /system/lib64/android.hidl.token@1.0-utils.so
-70e6a23000-70e6a24000 rw-p 00010000 fc:00 2489 /system/lib64/android.hidl.token@1.0-utils.so
-70e6a25000-70e6a2e000 r--s 00000000 fc:00 1120 /system/usr/hyphen-data/hyph-ga.hyb
-70e6a2e000-70e6a42000 r--s 00000000 fc:00 109 /system/fonts/NotoSansOriyaUI-Regular.ttf
-70e6a42000-70e6a59000 r-xp 00000000 fc:00 2446 /system/lib64/android.hardware.graphics.mapper@2.0.so
-70e6a59000-70e6a6e000 ---p 00000000 00:00 0
-70e6a6e000-70e6a70000 r--p 0001e000 fc:00 2446 /system/lib64/android.hardware.graphics.mapper@2.0.so
-70e6a70000-70e6a71000 rw-p 00020000 fc:00 2446 /system/lib64/android.hardware.graphics.mapper@2.0.so
-70e6a72000-70e6a78000 r--s 00000000 fc:00 1084 /system/usr/hyphen-data/hyph-et.hyb
-70e6a78000-70e6a9d000 r--s 00000000 fc:00 207 /system/fonts/NotoSerifTelugu-Bold.ttf
-70e6a9d000-70e6a9f000 r-xp 00000000 fc:00 2330 /system/lib64/android.hardware.configstore-utils.so
-70e6a9f000-70e6abc000 ---p 00000000 00:00 0
-70e6abc000-70e6abd000 r--p 0000f000 fc:00 2330 /system/lib64/android.hardware.configstore-utils.so
-70e6abd000-70e6abe000 rw-p 00010000 fc:00 2330 /system/lib64/android.hardware.configstore-utils.so
-70e6abe000-70e6ac0000 r--s f8042000 00:10 20630 /dev/kgsl-3d0
-70e6ac0000-70e6adc000 r--s 00000000 fc:00 172 /system/fonts/NotoSansTeluguUI-Bold.ttf
-70e6adc000-70e6ae0000 r-xp 00000000 fc:00 2555 /system/lib64/libstagefright_omx_utils.so
-70e6ae0000-70e6afb000 ---p 00000000 00:00 0
-70e6afb000-70e6afc000 r--p 0000f000 fc:00 2555 /system/lib64/libstagefright_omx_utils.so
-70e6afc000-70e6afd000 rw-p 00010000 fc:00 2555 /system/lib64/libstagefright_omx_utils.so
-70e6afd000-70e6afe000 ---p 00000000 00:00 0 [anon:thread signal stack guard]
-70e6afe000-70e6b02000 rw-p 00000000 00:00 0 [anon:thread signal stack]
-70e6b02000-70e6b27000 r--s 00000000 fc:00 271 /system/fonts/NotoSerifTelugu-Regular.ttf
-70e6b27000-70e6b61000 r-xp 00000000 fc:00 2695 /system/lib64/libdexfile.so
-70e6b61000-70e6b73000 ---p 00000000 00:00 0
-70e6b73000-70e6b75000 r--p 0003e000 fc:00 2695 /system/lib64/libdexfile.so
-70e6b75000-70e6b76000 rw-p 00040000 fc:00 2695 /system/lib64/libdexfile.so
-70e6b76000-70e6b78000 rw-p 00000000 00:05 10253452 [anon:dalvik-indirect ref table]
-70e6b78000-70e6b85000 r--s 00000000 fc:00 1080 /system/usr/hyphen-data/hyph-cu.hyb
-70e6b85000-70e6b96000 r-xp 00000000 fc:00 2957 /system/lib64/libaudioutils.so
-70e6b96000-70e6bb4000 ---p 00000000 00:00 0
-70e6bb4000-70e6bb5000 r--p 0001f000 fc:00 2957 /system/lib64/libaudioutils.so
-70e6bb5000-70e6bb6000 rw-p 00020000 fc:00 2957 /system/lib64/libaudioutils.so
-70e6bb6000-70e6bb7000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70e6bb7000-70e6bba000 rw-p 00000000 00:00 0 [anon:bionic TLS]
-70e6bba000-70e6bbb000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70e6bbb000-70e6bd7000 r--s 00000000 fc:00 132 /system/fonts/NotoSansTeluguUI-Regular.ttf
-70e6bd7000-70e6bdc000 r-xp 00000000 fc:00 2409 /system/lib64/libprocessgroup.so
-70e6bdc000-70e6bf6000 ---p 00000000 00:00 0
-70e6bf6000-70e6bf7000 r--p 0000f000 fc:00 2409 /system/lib64/libprocessgroup.so
-70e6bf7000-70e6bf8000 rw-p 00010000 fc:00 2409 /system/lib64/libprocessgroup.so
-70e6bf8000-70e6c09000 r--s 00000000 fc:00 79 /system/fonts/NotoSansNewa-Regular.otf
-70e6c09000-70e6c1c000 r-xp 00000000 fc:00 2329 /system/lib64/android.hidl.memory.token@1.0.so
-70e6c1c000-70e6c36000 ---p 00000000 00:00 0
-70e6c36000-70e6c38000 r--p 0001e000 fc:00 2329 /system/lib64/android.hidl.memory.token@1.0.so
-70e6c38000-70e6c39000 rw-p 00020000 fc:00 2329 /system/lib64/android.hidl.memory.token@1.0.so
-70e6c3a000-70e6c4f000 r--s 00000000 fc:00 253 /system/fonts/NotoSansOriya-Bold.ttf
-70e6c4f000-70e6c6b000 r-xp 00000000 fc:00 2407 /system/lib64/libutils.so
-70e6c6b000-70e6c7e000 ---p 00000000 00:00 0
-70e6c7e000-70e6c7f000 r--p 0001f000 fc:00 2407 /system/lib64/libutils.so
-70e6c7f000-70e6c80000 rw-p 00020000 fc:00 2407 /system/lib64/libutils.so
-70e6c80000-70e6c9d000 r-xp 00000000 fc:00 2934 /system/lib64/libtinyxml2.so
-70e6c9d000-70e6cba000 ---p 00000000 00:00 0
-70e6cba000-70e6cbc000 r--p 0001e000 fc:00 2934 /system/lib64/libtinyxml2.so
-70e6cbc000-70e6cbf000 rw-p 00020000 fc:00 2934 /system/lib64/libtinyxml2.so
-70e6cbf000-70e6ccf000 r--s 00000000 fc:00 80 /system/fonts/NotoSansMarchen-Regular.otf
-70e6ccf000-70e6ce0000 r-xp 00000000 fc:00 2655 /system/lib64/libbase.so
-70e6ce0000-70e6cfe000 ---p 00000000 00:00 0
-70e6cfe000-70e6cff000 r--p 0001f000 fc:00 2655 /system/lib64/libbase.so
-70e6cff000-70e6d00000 rw-p 00020000 fc:00 2655 /system/lib64/libbase.so
-70e6d00000-70e6d09000 r--s 00000000 fc:00 1113 /system/usr/hyphen-data/hyph-cy.hyb
-70e6d09000-70e6d50000 r-xp 00000000 fc:00 2495 /system/lib64/libRScpp.so
-70e6d50000-70e6d68000 ---p 00000000 00:00 0
-70e6d68000-70e6d69000 r--p 0004f000 fc:00 2495 /system/lib64/libRScpp.so
-70e6d69000-70e6d6a000 rw-p 00050000 fc:00 2495 /system/lib64/libRScpp.so
-70e6d6b000-70e6d6d000 r--s 00088000 103:1d 1736830 /data/app/com.google.sample.tunnel-HGGRU03Gu1Mwkf_-RnFmvw==/base.apk
-70e6d6d000-70e6d7d000 r--s 00000000 fc:00 238 /system/fonts/NotoSansVai-Regular.ttf
-70e6d7d000-70e6d98000 r--s 00000000 fc:00 276 /system/fonts/NotoSansTelugu-Bold.ttf
-70e6d98000-70e6f2b000 r-xp 00000000 fc:00 2961 /system/lib64/libicuuc.so
-70e6f2b000-70e6f47000 ---p 00000000 00:00 0
-70e6f47000-70e6f5c000 r--p 0019b000 fc:00 2961 /system/lib64/libicuuc.so
-70e6f5c000-70e6f5d000 rw-p 001b0000 fc:00 2961 /system/lib64/libicuuc.so
-70e6f5d000-70e6f5e000 rw-p 00000000 00:00 0 [anon:.bss]
-70e6f5f000-70e6f68000 r--s 00000000 fc:00 159 /system/fonts/NotoSansLinearA-Regular.otf
-70e6f68000-70e6f84000 r--s 00000000 fc:00 170 /system/fonts/NotoSansTelugu-Regular.ttf
-70e6f84000-70e7058000 r-xp 00000000 fc:00 2356 /system/lib64/libc.so
-70e7058000-70e706e000 ---p 00000000 00:00 0
-70e706e000-70e7074000 r--p 000da000 fc:00 2356 /system/lib64/libc.so
-70e7074000-70e7076000 rw-p 000e0000 fc:00 2356 /system/lib64/libc.so
-70e7076000-70e7077000 rw-p 00000000 00:00 0 [anon:.bss]
-70e7077000-70e7078000 r--p 00000000 00:00 0 [anon:.bss]
-70e7078000-70e7080000 rw-p 00000000 00:00 0 [anon:.bss]
-70e7080000-70e7087000 r--s 00000000 fc:00 102 /system/fonts/NotoSansSharada-Regular.otf
-70e7087000-70e708e000 r-xp 00000000 fc:00 2378 /system/lib64/libheif.so
-70e708e000-70e70a4000 ---p 00000000 00:00 0
-70e70a4000-70e70a6000 r--p 0000e000 fc:00 2378 /system/lib64/libheif.so
-70e70a6000-70e70a7000 rw-p 00010000 fc:00 2378 /system/lib64/libheif.so
-70e70a7000-70e70a9000 r--s 00000000 fc:00 1116 /system/usr/hyphen-data/hyph-sl.hyb
-70e70a9000-70e70ab000 r--s 00000000 fc:00 1147 /system/usr/hyphen-data/hyph-mn-cyrl.hyb
-70e70ab000-70e70c5000 r--s 00000000 fc:00 291 /system/fonts/NotoSansBengaliUI-Bold.ttf
-70e70c5000-70e70ea000 r-xp 00000000 fc:00 2545 /system/lib64/libEGL.so
-70e70ea000-70e7109000 ---p 00000000 00:00 0
-70e7109000-70e710d000 r--p 0002c000 fc:00 2545 /system/lib64/libEGL.so
-70e710d000-70e710e000 rw-p 00030000 fc:00 2545 /system/lib64/libEGL.so
-70e710e000-70e7115000 rw-p 00000000 00:00 0 [anon:.bss]
-70e7115000-70e7119000 r--s 00000000 fc:00 1143 /system/usr/hyphen-data/hyph-es.hyb
-70e7119000-70e712e000 r--s 00000000 fc:00 71 /system/fonts/NotoSansOriya-Regular.ttf
-70e712e000-70e717a000 r--s 00000000 fc:00 272 /system/fonts/Roboto-Thin.ttf
-70e717a000-70e71db000 r-xp 00000000 fc:00 2393 /system/lib64/libpdx_default_transport.so
-70e71db000-70e71f7000 ---p 00000000 00:00 0
-70e71f7000-70e71f9000 r--p 0006e000 fc:00 2393 /system/lib64/libpdx_default_transport.so
-70e71f9000-70e71fa000 rw-p 00070000 fc:00 2393 /system/lib64/libpdx_default_transport.so
-70e71fa000-70e71fb000 rw-p 00000000 00:00 0 [anon:.bss]
-70e71fc000-70e71fe000 r--s 00000000 fc:00 1107 /system/usr/hyphen-data/hyph-fr.hyb
-70e71fe000-70e7200000 r--s 00000000 fc:00 1097 /system/usr/hyphen-data/hyph-da.hyb
-70e7200000-70e7223000 r-xp 00000000 fc:00 2380 /system/lib64/libminikin.so
-70e7223000-70e723e000 ---p 00000000 00:00 0
-70e723e000-70e723f000 r--p 0002f000 fc:00 2380 /system/lib64/libminikin.so
-70e723f000-70e7240000 rw-p 00030000 fc:00 2380 /system/lib64/libminikin.so
-70e7241000-70e724d000 r--s 00000000 fc:00 179 /system/fonts/NotoSansTaiTham-Regular.ttf
-70e724d000-70e725c000 r-xp 00000000 fc:00 2527 /system/lib64/libmediautils.so
-70e725c000-70e7279000 ---p 00000000 00:00 0
-70e7279000-70e727b000 r--p 0001e000 fc:00 2527 /system/lib64/libmediautils.so
-70e727b000-70e727c000 rw-p 00020000 fc:00 2527 /system/lib64/libmediautils.so
-70e727d000-70e7283000 r--s 00000000 fc:00 136 /system/fonts/NotoSansMiao-Regular.otf
-70e7283000-70e74d2000 r-xp 00000000 fc:00 2349 /system/lib64/libicui18n.so
-70e74d2000-70e74e6000 ---p 00000000 00:00 0
-70e74e6000-70e74fa000 r--p 0025c000 fc:00 2349 /system/lib64/libicui18n.so
-70e74fa000-70e74fb000 rw-p 00270000 fc:00 2349 /system/lib64/libicui18n.so
-70e74fc000-70e74ff000 r--s 00000000 103:1d 1474562 /data/resource-cache/vendor@overlay@framework-res__auto_generated_rro.apk@idmap
-70e74ff000-70e750c000 r--s 00000000 fc:00 126 /system/fonts/NotoSansSyriacWestern-Regular.ttf
-70e750c000-70e751b000 r-xp 00000000 fc:00 2466 /system/lib64/libmediaextractor.so
-70e751b000-70e753a000 ---p 00000000 00:00 0
-70e753a000-70e753b000 r--p 0000f000 fc:00 2466 /system/lib64/libmediaextractor.so
-70e753b000-70e753c000 rw-p 00010000 fc:00 2466 /system/lib64/libmediaextractor.so
-70e753d000-70e7540000 r--s 00000000 fc:00 107 /system/fonts/NotoSansPauCinHau-Regular.otf
-70e7540000-70e7593000 r-xp 00000000 fc:00 2363 /system/lib64/libandroidfw.so
-70e7593000-70e75ac000 ---p 00000000 00:00 0
-70e75ac000-70e75af000 r--p 0005d000 fc:00 2363 /system/lib64/libandroidfw.so
-70e75af000-70e75b0000 rw-p 00060000 fc:00 2363 /system/lib64/libandroidfw.so
-70e75b0000-70e75b2000 r--s 00000000 fc:00 1083 /system/usr/hyphen-data/hyph-be.hyb
-70e75b2000-70e75cd000 r--s 00000000 fc:00 270 /system/fonts/NotoSansBengaliUI-Regular.ttf
-70e75cd000-70e75cf000 r-xp 00000000 fc:00 2701 /system/lib64/libmemtrack.so
-70e75cf000-70e75ec000 ---p 00000000 00:00 0
-70e75ec000-70e75ed000 r--p 0000f000 fc:00 2701 /system/lib64/libmemtrack.so
-70e75ed000-70e75ee000 rw-p 00010000 fc:00 2701 /system/lib64/libmemtrack.so
-70e75ee000-70e75f0000 r--s 00000000 fc:00 209 /system/fonts/NotoSansSoraSompeng-Regular.otf
-70e75f0000-70e760d000 r--s 00000000 fc:00 243 /system/fonts/NotoSerifBengali-Bold.ttf
-70e760d000-70e7613000 r-xp 00000000 fc:00 2667 /system/lib64/libutilscallstack.so
-70e7613000-70e762c000 ---p 00000000 00:00 0
-70e762c000-70e762d000 r--p 0000f000 fc:00 2667 /system/lib64/libutilscallstack.so
-70e762d000-70e762e000 rw-p 00010000 fc:00 2667 /system/lib64/libutilscallstack.so
-70e762e000-70e7632000 r--s 00000000 fc:00 99 /system/fonts/NotoSansPahawhHmong-Regular.otf
-70e7632000-70e764f000 r--s 00000000 fc:00 205 /system/fonts/NotoSerifBengali-Regular.ttf
-70e764f000-70e7661000 r-xp 00000000 fc:00 2710 /system/lib64/libcutils.so
-70e7661000-70e767d000 ---p 00000000 00:00 0
-70e767d000-70e767f000 r--p 0001e000 fc:00 2710 /system/lib64/libcutils.so
-70e767f000-70e7680000 rw-p 00020000 fc:00 2710 /system/lib64/libcutils.so
-70e7680000-70e7683000 r--s 00000000 fc:00 257 /system/fonts/NotoSansPalmyrene-Regular.otf
-70e7683000-70e7697000 r--s 00000000 fc:00 78 /system/fonts/NotoSansKannadaUI-Bold.ttf
-70e7697000-70e769a000 r-xp 00000000 fc:00 2362 /system/lib64/libstagefright_http_support.so
-70e769a000-70e76b6000 ---p 00000000 00:00 0
-70e76b6000-70e76b7000 r--p 0000f000 fc:00 2362 /system/lib64/libstagefright_http_support.so
-70e76b7000-70e76b8000 rw-p 00010000 fc:00 2362 /system/lib64/libstagefright_http_support.so
-70e76b8000-70e76b9000 rw-p 00000000 00:00 0 [anon:linker_alloc_lob]
-70e76b9000-70e76be000 r--s 00000000 fc:00 165 /system/fonts/NotoSansMeroitic-Regular.otf
-70e76be000-70e76cb000 r--s 00000000 fc:00 112 /system/fonts/NotoSansSyriacEastern-Regular.ttf
-70e76cb000-70e76de000 r-xp 00000000 fc:00 2343 /system/lib64/libsensor.so
-70e76de000-70e76f5000 ---p 00000000 00:00 0
-70e76f5000-70e76f8000 r--p 0001d000 fc:00 2343 /system/lib64/libsensor.so
-70e76f8000-70e76f9000 rw-p 00020000 fc:00 2343 /system/lib64/libsensor.so
-70e76f9000-70e76fc000 r--s 00000000 fc:00 157 /system/fonts/NotoSansOldPermic-Regular.otf
-70e76fc000-70e7708000 r--s 00000000 fc:00 189 /system/fonts/NotoSansSyriacEstrangela-Regular.ttf
-70e7708000-70e771d000 r-xp 00000000 fc:00 2339 /system/lib64/android.hidl.token@1.0.so
-70e771d000-70e7735000 ---p 00000000 00:00 0
-70e7735000-70e7737000 r--p 0001e000 fc:00 2339 /system/lib64/android.hidl.token@1.0.so
-70e7737000-70e7738000 rw-p 00020000 fc:00 2339 /system/lib64/android.hidl.token@1.0.so
-70e7738000-70e7739000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70e7739000-70e773b000 r--s 00000000 fc:00 267 /system/fonts/NotoSansOldNorthArabian-Regular.otf
-70e773b000-70e7740000 r--s 00000000 fc:00 208 /system/fonts/NotoSansManichaean-Regular.otf
-70e7740000-70e775c000 r--s 00000000 fc:00 118 /system/fonts/NotoSansGujaratiUI-Bold.ttf
-70e775c000-70e7767000 r-xp 00000000 fc:00 2525 /system/lib64/libappfuse.so
-70e7767000-70e777b000 ---p 00000000 00:00 0
-70e777b000-70e777c000 r--p 0000f000 fc:00 2525 /system/lib64/libappfuse.so
-70e777c000-70e777d000 rw-p 00010000 fc:00 2525 /system/lib64/libappfuse.so
-70e777e000-70e7795000 r--s 00000000 fc:00 250 /system/fonts/NotoSerifKannada-Bold.ttf
-70e7795000-70e7798000 r-xp 00000000 fc:00 2413 /system/lib64/libpackagelistparser.so
-70e7798000-70e77b4000 ---p 00000000 00:00 0
-70e77b4000-70e77b5000 r--p 0000f000 fc:00 2413 /system/lib64/libpackagelistparser.so
-70e77b5000-70e77b6000 rw-p 00010000 fc:00 2413 /system/lib64/libpackagelistparser.so
-70e77b6000-70e77b8000 r--s 00000000 fc:00 147 /system/fonts/NotoSansNabataean-Regular.otf
-70e77b8000-70e77ba000 r--s 00000000 fc:00 146 /system/fonts/NotoSansMultani-Regular.otf
-70e77ba000-70e77c1000 r--s 00000000 fc:00 214 /system/fonts/NotoSansPhagsPa-Regular.ttf
-70e77c1000-70e77de000 r--s 00000000 fc:00 90 /system/fonts/NotoSansGujaratiUI-Regular.ttf
-70e77de000-70e77e0000 r-xp 00000000 fc:00 2430 /system/lib64/libdl.so
-70e77e0000-70e77fd000 ---p 00000000 00:00 0
-70e77fd000-70e77fe000 r--p 0000f000 fc:00 2430 /system/lib64/libdl.so
-70e77fe000-70e77ff000 r--p 00000000 00:00 0 [anon:.bss]
-70e7800000-70e7809000 r--s 00000000 fc:00 258 /system/fonts/NotoSansSymbols-Regular-Subsetted2.ttf
-70e7809000-70e7857000 r-xp 00000000 fc:00 2560 /system/lib64/libjpeg.so
-70e7857000-70e7868000 ---p 00000000 00:00 0
-70e7868000-70e7869000 r--p 0004f000 fc:00 2560 /system/lib64/libjpeg.so
-70e7869000-70e786a000 rw-p 00050000 fc:00 2560 /system/lib64/libjpeg.so
-70e786a000-70e7887000 r--s 00000000 fc:00 237 /system/fonts/NotoSansGujarati-Bold.ttf
-70e7887000-70e788a000 r-xp 00000000 fc:00 2608 /system/lib64/libnetd_client.so
-70e788a000-70e78a6000 ---p 00000000 00:00 0
-70e78a6000-70e78a7000 r--p 0000f000 fc:00 2608 /system/lib64/libnetd_client.so
-70e78a7000-70e78a8000 rw-p 00010000 fc:00 2608 /system/lib64/libnetd_client.so
-70e78a8000-70e78aa000 r--s 00000000 fc:00 290 /system/fonts/NotoSansMro-Regular.otf
-70e78aa000-70e78b9000 r--s 00000000 fc:00 84 /system/fonts/NotoSansLinearB-Regular.ttf
-70e78b9000-70e78d7000 r--s 00000000 fc:00 287 /system/fonts/NotoSansGujarati-Regular.ttf
-70e78d7000-70e78d8000 r-xp 00000000 fc:00 2651 /system/lib64/libvndksupport.so
-70e78d8000-70e78f6000 ---p 00000000 00:00 0
-70e78f6000-70e78f7000 r--p 0000f000 fc:00 2651 /system/lib64/libvndksupport.so
-70e78f7000-70e78f8000 rw-p 00010000 fc:00 2651 /system/lib64/libvndksupport.so
-70e78f9000-70e78fc000 r--s 00000000 fc:00 178 /system/fonts/NotoSansTaiLe-Regular.ttf
-70e78fc000-70e7900000 r--s 00000000 fc:00 163 /system/fonts/NotoSansTifinagh-Regular.ttf
-70e7900000-70e7906000 r-xp 00000000 fc:00 2659 /system/lib64/libnativeloader.so
-70e7906000-70e791f000 ---p 00000000 00:00 0
-70e791f000-70e7920000 r--p 0000f000 fc:00 2659 /system/lib64/libnativeloader.so
-70e7920000-70e7921000 rw-p 00010000 fc:00 2659 /system/lib64/libnativeloader.so
-70e7921000-70e7923000 r--s 00000000 fc:00 268 /system/fonts/NotoSansHatran-Regular.otf
-70e7923000-70e7927000 r--s 00000000 fc:00 195 /system/fonts/NotoSansTaiViet-Regular.ttf
-70e7927000-70e7945000 r--s 00000000 fc:00 139 /system/fonts/NotoSansDevanagariUI-Bold.ttf
-70e7945000-70e79a3000 r-xp 00000000 fc:00 2450 /system/lib64/libharfbuzz_ng.so
-70e79a3000-70e79b3000 ---p 00000000 00:00 0
-70e79b3000-70e79b5000 r--p 0005e000 fc:00 2450 /system/lib64/libharfbuzz_ng.so
-70e79b5000-70e79b6000 rw-p 00060000 fc:00 2450 /system/lib64/libharfbuzz_ng.so
-70e79b6000-70e79c5000 r--s 00000000 fc:00 111 /system/fonts/NotoSansKaithi-Regular.ttf
-70e79c5000-70e7a92000 r-xp 00000000 fc:00 2332 /system/lib64/libc++.so
-70e7a92000-70e7aae000 ---p 00000000 00:00 0
-70e7aae000-70e7ab8000 r--p 000d6000 fc:00 2332 /system/lib64/libc++.so
-70e7ab8000-70e7ab9000 rw-p 000e0000 fc:00 2332 /system/lib64/libc++.so
-70e7ab9000-70e7abc000 rw-p 00000000 00:00 0 [anon:.bss]
-70e7abc000-70e7abe000 r--s 00000000 fc:00 73 /system/fonts/NotoSansBassaVah-Regular.otf
-70e7abe000-70e7ac8000 r--s 00000000 fc:00 254 /system/fonts/NotoSansJavanese-Regular.ttf
-70e7ac8000-70e7acb000 r-xp 00000000 fc:00 2660 /system/lib64/libnativebridge.so
-70e7acb000-70e7ae7000 ---p 00000000 00:00 0
-70e7ae7000-70e7ae8000 r--p 0000f000 fc:00 2660 /system/lib64/libnativebridge.so
-70e7ae8000-70e7ae9000 rw-p 00010000 fc:00 2660 /system/lib64/libnativebridge.so
-70e7ae9000-70e7aee000 r--s 00000000 fc:00 158 /system/fonts/NotoSansSaurashtra-Regular.ttf
-70e7aee000-70e7b0f000 r--s 00000000 fc:00 82 /system/fonts/NotoSansDevanagari-Bold.ttf
-70e7b0f000-70e7b2e000 r-xp 00000000 fc:00 2612 /system/lib64/libpcre2.so
-70e7b2e000-70e7b3e000 ---p 00000000 00:00 0
-70e7b3e000-70e7b3f000 r--p 0001f000 fc:00 2612 /system/lib64/libpcre2.so
-70e7b3f000-70e7b40000 rw-p 00020000 fc:00 2612 /system/lib64/libpcre2.so
-70e7b40000-70e7bcc000 r-xp 00000000 fc:00 2975 /system/lib64/libgui.so
-70e7bcc000-70e7be2000 ---p 00000000 00:00 0
-70e7be2000-70e7bf5000 r--p 0008d000 fc:00 2975 /system/lib64/libgui.so
-70e7bf5000-70e7bf6000 rw-p 000a0000 fc:00 2975 /system/lib64/libgui.so
-70e7bf6000-70e7bf7000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70e7bf7000-70e7bf9000 r--s 00000000 fc:00 228 /system/fonts/NotoSansUgaritic-Regular.ttf
-70e7bf9000-70e7c08000 r--s 00000000 fc:00 89 /system/fonts/NotoSansCherokee-Regular.ttf
-70e7c08000-70e7dea000 r-xp 00000000 fc:00 2441 /system/lib64/libandroid_runtime.so
-70e7dea000-70e7e04000 ---p 00000000 00:00 0
-70e7e04000-70e7e23000 r--p 001e1000 fc:00 2441 /system/lib64/libandroid_runtime.so
-70e7e23000-70e7e24000 rw-p 00200000 fc:00 2441 /system/lib64/libandroid_runtime.so
-70e7e24000-70e7e28000 rw-p 00000000 00:00 0 [anon:.bss]
-70e7e29000-70e7e66000 r--s 00000000 fc:00 74 /system/fonts/NotoSerif-Bold.ttf
-70e7e66000-70e7ed0000 r-xp 00000000 fc:00 2547 /system/lib64/libclang_rt.ubsan_standalone-aarch64-android.so
-70e7ed0000-70e7edf000 ---p 00000000 00:00 0
-70e7edf000-70e7ee1000 r--p 00069000 fc:00 2547 /system/lib64/libclang_rt.ubsan_standalone-aarch64-android.so
-70e7ee1000-70e7ee4000 rw-p 0006b000 fc:00 2547 /system/lib64/libclang_rt.ubsan_standalone-aarch64-android.so
-70e7ee4000-70e89f6000 rw-p 00000000 00:00 0 [anon:.bss]
-70e89f6000-70e89fa000 r--s 00000000 fc:00 127 /system/fonts/NotoSansSylotiNagri-Regular.ttf
-70e89fa000-70e8a06000 r--s 00000000 fc:00 93 /system/fonts/NotoSansCanadianAboriginal-Regular.ttf
-70e8a06000-70e8a1b000 r-xp 00000000 fc:00 2460 /system/lib64/android.hardware.graphics.allocator@2.0.so
-70e8a1b000-70e8a33000 ---p 00000000 00:00 0
-70e8a33000-70e8a35000 r--p 0001e000 fc:00 2460 /system/lib64/android.hardware.graphics.allocator@2.0.so
-70e8a35000-70e8a36000 rw-p 00020000 fc:00 2460 /system/lib64/android.hardware.graphics.allocator@2.0.so
-70e8a36000-70e8a55000 r--s 00000000 fc:00 145 /system/fonts/NotoSansDevanagariUI-Regular.ttf
-70e8a55000-70e8a61000 r-xp 00000000 fc:00 2540 /system/lib64/libstagefright_xmlparser.so
-70e8a61000-70e8a74000 ---p 00000000 00:00 0
-70e8a74000-70e8a75000 r--p 0000f000 fc:00 2540 /system/lib64/libstagefright_xmlparser.so
-70e8a75000-70e8a76000 rw-p 00010000 fc:00 2540 /system/lib64/libstagefright_xmlparser.so
-70e8a76000-70e8a78000 r--s 00000000 fc:00 293 /system/fonts/NotoSansTagbanwa-Regular.ttf
-70e8a78000-70e8a8f000 r--s 00000000 fc:00 161 /system/fonts/NotoSerifKannada-Regular.ttf
-70e8a8f000-70e8b23000 r-xp 00000000 fc:00 2633 /system/lib64/libaudioclient.so
-70e8b23000-70e8b37000 ---p 00000000 00:00 0
-70e8b37000-70e8b49000 r--p 0009e000 fc:00 2633 /system/lib64/libaudioclient.so
-70e8b49000-70e8b55000 rw-p 000b0000 fc:00 2633 /system/lib64/libaudioclient.so
-70e8b55000-70e8b9f000 r--s 00000000 fc:00 83 /system/fonts/RobotoCondensed-Light.ttf
-70e8b9f000-70e8ba1000 r-xp 00000000 fc:00 2520 /system/lib64/libhardware_legacy.so
-70e8ba1000-70e8bbe000 ---p 00000000 00:00 0
-70e8bbe000-70e8bbf000 r--p 0000f000 fc:00 2520 /system/lib64/libhardware_legacy.so
-70e8bbf000-70e8bc0000 rw-p 00010000 fc:00 2520 /system/lib64/libhardware_legacy.so
-70e8bc0000-70e8be0000 r-xp 00000000 fc:00 2410 /system/lib64/android.hidl.memory@1.0.so
-70e8be0000-70e8bfa000 ---p 00000000 00:00 0
-70e8bfa000-70e8bfd000 r--p 0002d000 fc:00 2410 /system/lib64/android.hidl.memory@1.0.so
-70e8bfd000-70e8bfe000 rw-p 00030000 fc:00 2410 /system/lib64/android.hidl.memory@1.0.so
-70e8bfe000-70e8bff000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70e8bff000-70e8c02000 r--s 00000000 fc:00 273 /system/fonts/NotoSansSundanese-Regular.ttf
-70e8c02000-70e8c0f000 r--s 00000000 fc:00 115 /system/fonts/NotoSansAdlam-Regular.ttf
-70e8c0f000-70e8c18000 r-xp 00000000 fc:00 2350 /system/lib64/libnetdutils.so
-70e8c18000-70e8c2e000 ---p 00000000 00:00 0
-70e8c2e000-70e8c2f000 r--p 0000f000 fc:00 2350 /system/lib64/libnetdutils.so
-70e8c2f000-70e8c30000 rw-p 00010000 fc:00 2350 /system/lib64/libnetdutils.so
-70e8c30000-70e8c44000 r--s 00000000 fc:00 283 /system/fonts/NotoSansKannadaUI-Regular.ttf
-70e8c44000-70e8c45000 r-xp 00000000 fc:00 2926 /system/lib64/libhidlallocatorutils.so
-70e8c45000-70e8c63000 ---p 00000000 00:00 0
-70e8c63000-70e8c64000 r--p 0000f000 fc:00 2926 /system/lib64/libhidlallocatorutils.so
-70e8c64000-70e8c65000 rw-p 00010000 fc:00 2926 /system/lib64/libhidlallocatorutils.so
-70e8c65000-70e8c67000 r--s 00000000 fc:00 65 /system/fonts/NotoSansTagalog-Regular.ttf
-70e8c67000-70e8c70000 r--s 00000000 fc:00 294 /system/fonts/NotoSansChakma-Regular.ttf
-70e8c70000-70e8c92000 r--s 00000000 fc:00 116 /system/fonts/NotoSansDevanagari-Regular.ttf
-70e8c92000-70e8c94000 r-xp 00000000 fc:00 2501 /system/lib64/libsync.so
-70e8c94000-70e8cb1000 ---p 00000000 00:00 0
-70e8cb1000-70e8cb2000 r--p 0000f000 fc:00 2501 /system/lib64/libsync.so
-70e8cb2000-70e8cb3000 rw-p 00010000 fc:00 2501 /system/lib64/libsync.so
-70e8cb3000-70e8cc6000 r--s 00000000 fc:00 196 /system/fonts/NotoSerifSinhala-Regular.otf
-70e8cc6000-70e8d5c000 r-xp 00000000 fc:00 2403 /system/lib64/libmedia.so
-70e8d5c000-70e8d70000 ---p 00000000 00:00 0
-70e8d70000-70e8d88000 r--p 00098000 fc:00 2403 /system/lib64/libmedia.so
-70e8d88000-70e8d95000 rw-p 000b0000 fc:00 2403 /system/lib64/libmedia.so
-70e8d95000-70e8d96000 r--p 00000000 00:00 0 [anon:atexit handlers]
-70e8d96000-70e8d99000 r--s 00000000 fc:00 247 /system/fonts/NotoSansSamaritan-Regular.ttf
-70e8d99000-70e8dad000 r--s 00000000 fc:00 108 /system/fonts/NotoSansKannada-Bold.ttf
-70e8dad000-70e8dcd000 r--s 00000000 fc:00 303 /system/fonts/NotoSerifEthiopic-Bold.otf
-70e8dcd000-70e8de5000 r-xp 00000000 fc:00 2954 /system/lib64/libGLESv2.so
-70e8de5000-70e8dfc000 ---p 00000000 00:00 0
-70e8dfc000-70e8dfd000 r--p 0001f000 fc:00 2954 /system/lib64/libGLESv2.so
-70e8dfd000-70e8dfe000 rw-p 00020000 fc:00 2954 /system/lib64/libGLESv2.so
-70e8dfe000-70e8e06000 r--s 00000000 fc:00 265 /system/fonts/NotoSansBalinese-Regular.ttf
-70e8e06000-70e8e0e000 r--s 00000000 fc:00 219 /system/fonts/NotoSansLaoUI-Bold.ttf
-70e8e0e000-70e8e12000 r-xp 00000000 fc:00 2617 /system/lib64/libdebuggerd_client.so
-70e8e12000-70e8e2d000 ---p 00000000 00:00 0
-70e8e2d000-70e8e2e000 r--p 0000f000 fc:00 2617 /system/lib64/libdebuggerd_client.so
-70e8e2e000-70e8e2f000 rw-p 00010000 fc:00 2617 /system/lib64/libdebuggerd_client.so
-70e8e2f000-70e8e4b000 r--s 00000000 fc:00 211 /system/fonts/NotoSerifEthiopic-Regular.otf
-70e8e4b000-70e8e5e000 r-xp 00000000 fc:00 2484 /system/lib64/android.hardware.memtrack@1.0.so
-70e8e5e000-70e8e78000 ---p 00000000 00:00 0
-70e8e78000-70e8e7a000 r--p 0001e000 fc:00 2484 /system/lib64/android.hardware.memtrack@1.0.so
-70e8e7a000-70e8e7b000 rw-p 00020000 fc:00 2484 /system/lib64/android.hardware.memtrack@1.0.so
-70e8e7b000-70e8e7d000 r--s 00000000 fc:00 261 /system/fonts/NotoSansShavian-Regular.ttf
-70e8e7d000-70e8e80000 r--s 00000000 fc:00 204 /system/fonts/NotoSansRunic-Regular.ttf
-70e8e80000-70e8ea1000 r-xp 00000000 fc:00 2512 /system/lib64/android.hardware.configstore@1.0.so
-70e8ea1000-70e8ebb000 ---p 00000000 00:00 0
-70e8ebb000-70e8ebe000 r--p 0002d000 fc:00 2512 /system/lib64/android.hardware.configstore@1.0.so
-70e8ebe000-70e8ebf000 rw-p 00030000 fc:00 2512 /system/lib64/android.hardware.configstore@1.0.so
-70e8ebf000-70e8ee3000 r--s 00000000 fc:00 226 /system/fonts/NotoSansEthiopic-Bold.ttf
-70e8ee3000-70e8f1a000 r-xp 00000000 fc:00 2337 /system/lib64/libm.so
-70e8f1a000-70e8f32000 ---p 00000000 00:00 0
-70e8f32000-70e8f33000 r--p 0003f000 fc:00 2337 /system/lib64/libm.so
-70e8f33000-70e8f34000 rw-p 00040000 fc:00 2337 /system/lib64/libm.so
-70e8f34000-70e8f36000 r--s 00000000 fc:00 133 /system/fonts/NotoSansRejang-Regular.ttf
-70e8f36000-70e8f38000 r--s 00000000 fc:00 69 /system/fonts/NotoSansPhoenician-Regular.ttf
-70e8f38000-70e8f40000 r--s 00000000 fc:00 245 /system/fonts/NotoSansLaoUI-Regular.ttf
-70e8f40000-70e8f45000 r-xp 00000000 fc:00 2341 /system/lib64/libstagefright_codecbase.so
-70e8f45000-70e8f5f000 ---p 00000000 00:00 0
-70e8f5f000-70e8f60000 r--p 0000f000 fc:00 2341 /system/lib64/libstagefright_codecbase.so
-70e8f60000-70e8f61000 rw-p 00010000 fc:00 2341 /system/lib64/libstagefright_codecbase.so
-70e8f61000-70e8f62000 r--p 00000000 00:00 0 [anon:atexit handlers]
-70e8f62000-70e8f66000 r--s 00000000 fc:00 225 /system/fonts/NotoSansOldPersian-Regular.ttf
-70e8f66000-70e8f89000 r--s 00000000 fc:00 167 /system/fonts/NotoSansEthiopic-Regular.ttf
-70e8f89000-70e8f92000 r-xp 00000000 fc:00 2515 /system/lib64/libGLESv1_CM.so
-70e8f92000-70e8fa8000 ---p 00000000 00:00 0
-70e8fa8000-70e8fa9000 r--p 0000f000 fc:00 2515 /system/lib64/libGLESv1_CM.so
-70e8fa9000-70e8faa000 rw-p 00010000 fc:00 2515 /system/lib64/libGLESv1_CM.so
-70e8faa000-70e8fad000 r--s 00000000 fc:00 206 /system/fonts/NotoSansOsage-Regular.ttf
-70e8fad000-70e8fb5000 r--s 00000000 fc:00 121 /system/fonts/NotoSerifLao-Bold.ttf
-70e8fb5000-70e8fd3000 r--s 00000000 fc:00 68 /system/fonts/NotoNaskhArabicUI-Bold.ttf
-70e8fd3000-70e9010000 r-xp 00000000 fc:00 2600 /system/lib64/android.hardware.cas@1.0.so
-70e9010000-70e9026000 ---p 00000000 00:00 0
-70e9026000-70e902c000 r--p 0004a000 fc:00 2600 /system/lib64/android.hardware.cas@1.0.so
-70e902c000-70e902d000 rw-p 00050000 fc:00 2600 /system/lib64/android.hardware.cas@1.0.so
-70e902d000-70e902e000 r--s 00000000 00:05 31475 /dev/ashmem/5c7d41a6-003d-45a5-9e3b-2d34c5829a2d (deleted)
-70e902e000-70e9043000 r--s 00000000 fc:00 120 /system/fonts/NotoSansKannada-Regular.ttf
-70e9043000-70e9067000 r-xp 00000000 fc:00 2729 /system/lib64/libexpat.so
-70e9067000-70e9081000 ---p 00000000 00:00 0
-70e9081000-70e9083000 r--p 0002e000 fc:00 2729 /system/lib64/libexpat.so
-70e9083000-70e9084000 rw-p 00030000 fc:00 2729 /system/lib64/libexpat.so
-70e9084000-70e9086000 r--s 00000000 fc:00 155 /system/fonts/NotoSansOsmanya-Regular.ttf
-70e9086000-70e90c3000 r--s 00000000 fc:00 91 /system/fonts/NotoSerif-Regular.ttf
-70e90c3000-70e91ce000 r-xp 00000000 fc:00 2647 /system/lib64/libcrypto.so
-70e91ce000-70e91e2000 ---p 00000000 00:00 0
-70e91e2000-70e91f3000 r--p 0010f000 fc:00 2647 /system/lib64/libcrypto.so
-70e91f3000-70e91f4000 rw-p 00120000 fc:00 2647 /system/lib64/libcrypto.so
-70e91f4000-70e91f5000 rw-p 00000000 00:00 0 [anon:.bss]
-70e91f5000-70e91fa000 r--s 00000000 fc:00 149 /system/fonts/NotoSansNKo-Regular.ttf
-70e91fa000-70e9202000 r--s 00000000 fc:00 198 /system/fonts/NotoSerifLao-Regular.ttf
-70e9202000-70e921b000 r-xp 00000000 fc:00 2682 /system/lib64/libmedia_helper.so
-70e921b000-70e922d000 ---p 00000000 00:00 0
-70e922d000-70e9230000 r--p 0001d000 fc:00 2682 /system/lib64/libmedia_helper.so
-70e9230000-70e9231000 rw-p 00020000 fc:00 2682 /system/lib64/libmedia_helper.so
-70e9231000-70e924a000 r--s 00000000 fc:00 232 /system/fonts/NotoSansBengali-Bold.ttf
-70e924a000-70e9256000 r-xp 00000000 fc:00 2467 /system/lib64/libsoundtrigger.so
-70e9256000-70e9272000 ---p 00000000 00:00 0
-70e9272000-70e9276000 r--p 0000c000 fc:00 2467 /system/lib64/libsoundtrigger.so
-70e9276000-70e9277000 rw-p 00010000 fc:00 2467 /system/lib64/libsoundtrigger.so
-70e9277000-70e9278000 r--s 00000000 fc:01 1177 /vendor/overlay/Pixel/PixelThemeOverlay.apk
-70e9278000-70e927c000 r--s 00000000 fc:00 215 /system/fonts/NotoSansNewTaiLue-Regular.ttf
-70e927c000-70e929a000 r--s 00000000 fc:00 235 /system/fonts/NotoNaskhArabicUI-Regular.ttf
-70e929a000-70e929b000 r-xp 00000000 fc:00 2375 /system/lib64/android.hardware.graphics.common@1.1.so
-70e929b000-70e92b9000 ---p 00000000 00:00 0
-70e92b9000-70e92ba000 r--p 0000f000 fc:00 2375 /system/lib64/android.hardware.graphics.common@1.1.so
-70e92ba000-70e92bb000 rw-p 00010000 fc:00 2375 /system/lib64/android.hardware.graphics.common@1.1.so
-70e92bb000-70e92da000 r--s 00000000 fc:00 281 /system/fonts/GoogleSans-BoldItalic.ttf
-70e92da000-70e9302000 r-xp 00000000 fc:00 2529 /system/lib64/libinput.so
-70e9302000-70e931b000 ---p 00000000 00:00 0
-70e931b000-70e9322000 r--p 00029000 fc:00 2529 /system/lib64/libinput.so
-70e9322000-70e9323000 rw-p 00030000 fc:00 2529 /system/lib64/libinput.so
-70e9323000-70e9340000 r--s 00000000 fc:00 130 /system/fonts/NotoNaskhArabic-Bold.ttf
-70e9340000-70e934b000 r-xp 00000000 fc:00 2451 /system/lib64/libbpf.so
-70e934b000-70e935f000 ---p 00000000 00:00 0
-70e935f000-70e9360000 r--p 0000f000 fc:00 2451 /system/lib64/libbpf.so
-70e9360000-70e9361000 rw-p 00010000 fc:00 2451 /system/lib64/libbpf.so
-70e9361000-70e9367000 r--s 00000000 fc:00 96 /system/fonts/NotoSansKharoshthi-Regular.ttf
-70e9367000-70e9385000 r--s 00000000 fc:00 151 /system/fonts/GoogleSans-Bold.ttf
-70e9385000-70e93b8000 r-xp 00000000 fc:00 2494 /system/lib64/libpng.so
-70e93b8000-70e93d4000 ---p 00000000 00:00 0
-70e93d4000-70e93d5000 r--p 0003f000 fc:00 2494 /system/lib64/libpng.so
-70e93d5000-70e93d6000 rw-p 00040000 fc:00 2494 /system/lib64/libpng.so
-70e93d6000-70e93d7000 r--s 00004000 fc:01 1177 /vendor/overlay/Pixel/PixelThemeOverlay.apk
-70e93d7000-70e93d9000 r--s 00000000 fc:00 295 /system/fonts/NotoSansOldTurkic-Regular.ttf
-70e93d9000-70e93e5000 r--s 00000000 fc:00 86 /system/fonts/NotoSerifKhmer-Bold.otf
-70e93e5000-70e9404000 r--s 00000000 fc:00 240 /system/fonts/GoogleSans-MediumItalic.ttf
-70e9404000-70e9409000 r-xp 00000000 fc:00 2404 /system/lib64/libhidlmemory.so
-70e9409000-70e9423000 ---p 00000000 00:00 0
-70e9423000-70e9424000 r--p 0000f000 fc:00 2404 /system/lib64/libhidlmemory.so
-70e9424000-70e9425000 rw-p 00010000 fc:00 2404 /system/lib64/libhidlmemory.so
-70e9425000-70e943e000 r--s 00000000 fc:00 185 /system/fonts/NotoSansBengali-Regular.ttf
-70e943e000-70e945c000 r--s 00000000 fc:00 129 /system/fonts/GoogleSans-Medium.ttf
-70e945c000-70e960c000 r-xp 00000000 fc:00 2398 /system/lib64/libstagefright.so
-70e960c000-70e9625000 ---p 00000000 00:00 0
-70e9625000-70e9638000 r--p 001bd000 fc:00 2398 /system/lib64/libstagefright.so
-70e9638000-70e966c000 rw-p 001d0000 fc:00 2398 /system/lib64/libstagefright.so
-70e966c000-70e966d000 rw-p 00000000 00:00 0 [anon:.bss]
-70e966d000-70e966e000 r--s 00000000 103:1d 1474566 /data/resource-cache/vendor@overlay@Pixel@PixelThemeOverlay.apk@idmap
-70e966e000-70e9672000 r--s 00000000 fc:00 241 /system/fonts/NotoSansMeeteiMayek-Regular.ttf
-70e9672000-70e9680000 r--s 00000000 fc:00 150 /system/fonts/NotoSansMalayalamUI-Bold.ttf
-70e9680000-70e96a7000 r-xp 00000000 fc:00 2365 /system/lib64/libhwbinder.so
-70e96a7000-70e96bd000 ---p 00000000 00:00 0
-70e96bd000-70e96bf000 r--p 0002e000 fc:00 2365 /system/lib64/libhwbinder.so
-70e96bf000-70e96c0000 rw-p 00030000 fc:00 2365 /system/lib64/libhwbinder.so
-70e96c0000-70e96c1000 r--s 00088000 103:1d 1736830 /data/app/com.google.sample.tunnel-HGGRU03Gu1Mwkf_-RnFmvw==/base.apk
-70e96c1000-70e96cb000 r--s 00000000 fc:00 94 /system/fonts/NotoSansKhmerUI-Regular.ttf
-70e96cb000-70e96d9000 r--s 00000000 fc:00 275 /system/fonts/NotoSansMalayalamUI-Regular.ttf
-70e96d9000-70e96dd000 r-xp 00000000 fc:00 2386 /system/lib64/libusbhost.so
-70e96dd000-70e96f8000 ---p 00000000 00:00 0
-70e96f8000-70e96f9000 r--p 0000f000 fc:00 2386 /system/lib64/libusbhost.so
-70e96f9000-70e96fa000 rw-p 00010000 fc:00 2386 /system/lib64/libusbhost.so
-70e96fa000-70e96fb000 r--p 00000000 00:05 10266154 [anon:dalvik-classes.dex extracted in memory from /data/app/com.google.sample.tunnel-HGGRU03Gu1Mwkf_-RnFmvw==/base.apk]
-70e96fb000-70e9701000 r--s 00000000 fc:00 280 /system/fonts/NotoSansCoptic-Regular.ttf
-70e9701000-70e9720000 r-xp 00000000 fc:00 2490 /system/lib64/libstagefright_bufferqueue_helper.so
-70e9720000-70e973b000 ---p 00000000 00:00 0
-70e973b000-70e973e000 r--p 0002d000 fc:00 2490 /system/lib64/libstagefright_bufferqueue_helper.so
-70e973e000-70e9740000 rw-p 00030000 fc:00 2490 /system/lib64/libstagefright_bufferqueue_helper.so
-70e9740000-70e9742000 r--s 00000000 fc:00 141 /system/fonts/NotoSansOldSouthArabian-Regular.ttf
-70e9742000-70e974c000 r--s 00000000 fc:00 229 /system/fonts/NotoSerifKhmer-Regular.otf
-70e974c000-70e9759000 r--s 00000000 fc:00 260 /system/fonts/NotoSerifMalayalam-Bold.ttf
-70e9759000-70e97c7000 r-xp 00000000 fc:00 2428 /system/lib64/libstagefright_omx.so
-70e97c7000-70e97dc000 ---p 00000000 00:00 0
-70e97dc000-70e97e6000 r--p 00076000 fc:00 2428 /system/lib64/libstagefright_omx.so
-70e97e6000-70e97ed000 rw-p 00080000 fc:00 2428 /system/lib64/libstagefright_omx.so
-70e97ed000-70e97fa000 r--s 00000000 fc:00 66 /system/fonts/NotoSerifMalayalam-Regular.ttf
-70e97fa000-70e9819000 r--s 00000000 fc:00 183 /system/fonts/GoogleSans-Italic.ttf
-70e9819000-70e9856000 r-xp 00000000 fc:00 2434 /system/lib64/libprotobuf-cpp-lite.so
-70e9856000-70e9867000 ---p 00000000 00:00 0
-70e9867000-70e9869000 r--p 0003e000 fc:00 2434 /system/lib64/libprotobuf-cpp-lite.so
-70e9869000-70e986a000 rw-p 00040000 fc:00 2434 /system/lib64/libprotobuf-cpp-lite.so
-70e986a000-70e9873000 r--s 00000000 fc:00 134 /system/fonts/NotoSansKhmerUI-Bold.ttf
-70e9873000-70e9891000 r--s 00000000 fc:00 81 /system/fonts/GoogleSans-Regular.ttf
-70e9891000-70e989e000 r-xp 00000000 fc:00 2377 /system/lib64/libmediametrics.so
-70e989e000-70e98ae000 ---p 00000000 00:00 0
-70e98ae000-70e98b0000 r--p 0000e000 fc:00 2377 /system/lib64/libmediametrics.so
-70e98b0000-70e98b1000 rw-p 00010000 fc:00 2377 /system/lib64/libmediametrics.so
-70e98b1000-70e98b9000 r--s 00000000 fc:00 152 /system/fonts/NotoSansLao-Bold.ttf
-70e98b9000-70e98c7000 r--s 00000000 fc:00 279 /system/fonts/NotoSansMalayalam-Bold.ttf
-70e98c7000-70e98ca000 r-xp 00000000 fc:00 2952 /system/lib64/libETC1.so
-70e98ca000-70e98e6000 ---p 00000000 00:00 0
-70e98e6000-70e98e7000 r--p 0000f000 fc:00 2952 /system/lib64/libETC1.so
-70e98e7000-70e98e8000 rw-p 00010000 fc:00 2952 /system/lib64/libETC1.so
-70e98e8000-70e98e9000 r--s 00000000 fc:00 1121 /system/usr/hyphen-data/hyph-und-ethi.hyb
-70e98e9000-70e98ef000 r--s 00000000 fc:00 64 /system/fonts/NotoSansBrahmi-Regular.ttf
-70e98ef000-70e990f000 rw-p 00000000 00:05 10271012 [anon:dalvik-CompilerMetadata]
-70e990f000-70e9926000 r-xp 00000000 fc:00 2526 /system/lib64/libbacktrace.so
-70e9926000-70e993e000 ---p 00000000 00:00 0
-70e993e000-70e993f000 r--p 0001f000 fc:00 2526 /system/lib64/libbacktrace.so
-70e993f000-70e9940000 rw-p 00020000 fc:00 2526 /system/lib64/libbacktrace.so
-70e9940000-70e9941000 r--s 00000000 fc:00 1129 /system/usr/hyphen-data/hyph-tk.hyb
-70e9941000-70e99a4000 r-xp 00000000 fc:00 2528 /system/lib64/libcamera_client.so
-70e99a4000-70e99bc000 ---p 00000000 00:00 0
-70e99bc000-70e99c9000 r--p 00063000 fc:00 2528 /system/lib64/libcamera_client.so
-70e99c9000-70e99d0000 rw-p 00070000 fc:00 2528 /system/lib64/libcamera_client.so
-70e99d0000-70e99d1000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70e99d1000-70e99d3000 r--s 00000000 fc:00 200 /system/fonts/NotoSansOldItalic-Regular.ttf
-70e99d3000-70e99e1000 r--s 00000000 fc:00 153 /system/fonts/NotoSansMalayalam-Regular.ttf
-70e99e1000-70e9a01000 rw-p 00000000 00:05 10271011 [anon:dalvik-CompilerMetadata]
-70e9a01000-70e9a1e000 r-xp 00000000 fc:00 2542 /system/lib64/libimg_utils.so
-70e9a1e000-70e9a39000 ---p 00000000 00:00 0
-70e9a39000-70e9a3c000 r--p 0001d000 fc:00 2542 /system/lib64/libimg_utils.so
-70e9a3c000-70e9a3f000 rw-p 00020000 fc:00 2542 /system/lib64/libimg_utils.so
-70e9a3f000-70e9a5c000 r--s 00000000 fc:00 262 /system/fonts/NotoNaskhArabic-Regular.ttf
-70e9a5c000-70e9a69000 r-xp 00000000 fc:00 2706 /system/lib64/libziparchive.so
-70e9a69000-70e9a7b000 ---p 00000000 00:00 0
-70e9a7b000-70e9a7c000 r--p 0000f000 fc:00 2706 /system/lib64/libziparchive.so
-70e9a7c000-70e9a7d000 rw-p 00010000 fc:00 2706 /system/lib64/libziparchive.so
-70e9a7d000-70e9a85000 r--s 00000000 fc:00 119 /system/fonts/NotoSansLao-Regular.ttf
-70e9a85000-70e9a8e000 r--s 00000000 fc:00 77 /system/fonts/NotoSansTamilUI-Bold.ttf
-70e9a8e000-70e9a97000 r--s 00000000 fc:00 160 /system/fonts/NotoSansTamilUI-Regular.ttf
-70e9a97000-70e9a9d000 r-xp 00000000 fc:00 2536 /system/lib64/libnativehelper.so
-70e9a9d000-70e9ab6000 ---p 00000000 00:00 0
-70e9ab6000-70e9ab7000 r--p 0000f000 fc:00 2536 /system/lib64/libnativehelper.so
-70e9ab7000-70e9ab8000 rw-p 00010000 fc:00 2536 /system/lib64/libnativehelper.so
-70e9ab8000-70e9ab9000 r--s 00000000 fc:00 1134 /system/usr/hyphen-data/hyph-te.hyb
-70e9ab9000-70e9ac2000 r--s 00000000 fc:00 246 /system/fonts/NotoSerifTamil-Bold.ttf
-70e9ac2000-70e9acb000 r--s 00000000 fc:00 302 /system/fonts/NotoSerifTamil-Regular.ttf
-70e9acb000-70e9af4000 r-xp 00000000 fc:00 2950 /system/lib64/libmemunreachable.so
-70e9af4000-70e9b09000 ---p 00000000 00:00 0
-70e9b09000-70e9b0b000 r--p 0002e000 fc:00 2950 /system/lib64/libmemunreachable.so
-70e9b0b000-70e9b0c000 rw-p 00030000 fc:00 2950 /system/lib64/libmemunreachable.so
-70e9b0c000-70e9b0d000 r--s 00000000 fc:00 1088 /system/usr/hyphen-data/hyph-ta.hyb
-70e9b0d000-70e9b0f000 r--s 00000000 fc:00 72 /system/fonts/NotoSansOlChiki-Regular.ttf
-70e9b0f000-70e9b2f000 rw-p 00000000 00:05 10271010 [anon:dalvik-CompilerMetadata]
-70e9b2f000-70e9b4f000 r--s 00000000 00:10 16633 /dev/__properties__/u:object_r:persist_debug_prop:s0
-70e9b4f000-70e9b65000 r-xp 00000000 fc:00 2920 /system/lib64/android.hardware.cas.native@1.0.so
-70e9b65000-70e9b7b000 ---p 00000000 00:00 0
-70e9b7b000-70e9b7d000 r--p 0001e000 fc:00 2920 /system/lib64/android.hardware.cas.native@1.0.so
-70e9b7d000-70e9b7e000 rw-p 00020000 fc:00 2920 /system/lib64/android.hardware.cas.native@1.0.so
-70e9b7e000-70e9b7f000 r--s 00000000 fc:00 1145 /system/usr/hyphen-data/hyph-pt.hyb
-70e9b7f000-70e9b83000 r--s 00000000 fc:00 277 /system/fonts/NotoSansMandaic-Regular.ttf
-70e9b83000-70e9bdb000 r-xp 00000000 fc:00 2334 /system/lib64/libsonivox.so
-70e9bdb000-70e9bf2000 ---p 00000000 00:00 0
-70e9bf2000-70e9bf3000 r--p 0005f000 fc:00 2334 /system/lib64/libsonivox.so
-70e9bf3000-70e9bf4000 rw-p 00060000 fc:00 2334 /system/lib64/libsonivox.so
-70e9bf4000-70e9bfb000 rw-p 00000000 00:00 0 [anon:.bss]
-70e9bfb000-70e9c01000 r--s 00000000 fc:00 123 /system/fonts/NotoSansCham-Bold.ttf
-70e9c01000-70e9c0a000 r--s 00000000 fc:00 255 /system/fonts/NotoSansTamil-Bold.ttf
-70e9c0a000-70e9c13000 r--s 00000000 fc:00 135 /system/fonts/NotoSansTamil-Regular.ttf
-70e9c13000-70e9c15000 r-xp 00000000 fc:00 2519 /system/lib64/libgraphicsenv.so
-70e9c15000-70e9c32000 ---p 00000000 00:00 0
-70e9c32000-70e9c33000 r--p 0000f000 fc:00 2519 /system/lib64/libgraphicsenv.so
-70e9c33000-70e9c34000 rw-p 00010000 fc:00 2519 /system/lib64/libgraphicsenv.so
-70e9c34000-70e9c3a000 r--s 00000000 fc:00 259 /system/fonts/NotoSansCham-Regular.ttf
-70e9c3a000-70e9c42000 r--s 00000000 fc:00 114 /system/fonts/NotoSansGurmukhiUI-Bold.ttf
-70e9c42000-70e9c4a000 r--s 00000000 fc:00 122 /system/fonts/NotoSansGurmukhiUI-Regular.ttf
-70e9c4a000-70e9c5f000 r-xp 00000000 fc:00 2348 /system/lib64/android.hidl.allocator@1.0.so
-70e9c5f000-70e9c77000 ---p 00000000 00:00 0
-70e9c77000-70e9c79000 r--p 0001e000 fc:00 2348 /system/lib64/android.hidl.allocator@1.0.so
-70e9c79000-70e9c7a000 rw-p 00020000 fc:00 2348 /system/lib64/android.hidl.allocator@1.0.so
-70e9c7a000-70e9c7b000 r--s 00000000 fc:00 1095 /system/usr/hyphen-data/hyph-pa.hyb
-70e9c7b000-70e9c83000 r--s 00000000 fc:00 298 /system/fonts/NotoSerifGurmukhi-Bold.otf
-70e9c83000-70e9d01000 r-xp 00000000 fc:00 2665 /system/lib64/libbinder.so
-70e9d01000-70e9d1e000 ---p 00000000 00:00 0
-70e9d1e000-70e9d2e000 r--p 00080000 fc:00 2665 /system/lib64/libbinder.so
-70e9d2e000-70e9d2f000 rw-p 00090000 fc:00 2665 /system/lib64/libbinder.so
-70e9d2f000-70e9d4f000 rw-p 00000000 00:05 10271009 [anon:dalvik-CompilerMetadata]
-70e9d4f000-70e9d53000 r-xp 00000000 fc:00 2454 /system/lib64/libaudiomanager.so
-70e9d53000-70e9d6e000 ---p 00000000 00:00 0
-70e9d6e000-70e9d6f000 r--p 0000f000 fc:00 2454 /system/lib64/libaudiomanager.so
-70e9d6f000-70e9d70000 rw-p 00010000 fc:00 2454 /system/lib64/libaudiomanager.so
-70e9d70000-70e9d71000 r--s 00000000 fc:00 1087 /system/usr/hyphen-data/hyph-or.hyb
-70e9d71000-70e9d91000 rw-p 00000000 00:05 10271008 [anon:dalvik-CompilerMetadata]
-70e9d91000-70e9e21000 r-xp 00000000 fc:00 2627 /system/lib64/libft2.so
-70e9e21000-70e9e37000 ---p 00000000 00:00 0
-70e9e37000-70e9e3c000 r--p 0009b000 fc:00 2627 /system/lib64/libft2.so
-70e9e3c000-70e9e3d000 rw-p 000a0000 fc:00 2627 /system/lib64/libft2.so
-70e9e3d000-70e9e3e000 r--s 00000000 fc:00 1142 /system/usr/hyphen-data/hyph-mr.hyb
-70e9e3e000-70e9e45000 r--s 00000000 fc:00 88 /system/fonts/NotoSerifGurmukhi-Regular.otf
-70e9e45000-70e9e65000 r--s 00000000 00:10 16594 /dev/__properties__/u:object_r:exported3_default_prop:s0
-70e9e65000-70e9e7f000 r-xp 00000000 fc:00 2643 /system/lib64/libunwind.so
-70e9e7f000-70e9e94000 ---p 00000000 00:00 0
-70e9e94000-70e9e95000 r--p 0001f000 fc:00 2643 /system/lib64/libunwind.so
-70e9e95000-70e9e96000 rw-p 00020000 fc:00 2643 /system/lib64/libunwind.so
-70e9e96000-70e9eff000 rw-p 00000000 00:00 0 [anon:.bss]
-70e9eff000-70e9f00000 r--s 00000000 fc:00 1130 /system/usr/hyphen-data/hyph-ml.hyb
-70e9f00000-70e9f02000 r--s 00000000 fc:00 75 /system/fonts/NotoSansOgham-Regular.ttf
-70e9f02000-70e9f0a000 r--s 00000000 fc:00 193 /system/fonts/NotoSansGurmukhi-Bold.ttf
-70e9f0a000-70ea022000 r-xp 00000000 fc:00 2328 /system/lib64/libsqlite.so
-70ea022000-70ea033000 ---p 00000000 00:00 0
-70ea033000-70ea036000 r--p 0011d000 fc:00 2328 /system/lib64/libsqlite.so
-70ea036000-70ea038000 rw-p 00120000 fc:00 2328 /system/lib64/libsqlite.so
-70ea038000-70ea03c000 r--s 00000000 fc:00 285 /system/fonts/NotoSansGlagolitic-Regular.ttf
-70ea03c000-70ea04c000 r--s 00000000 fc:00 184 /system/fonts/NotoSerifGujarati-Bold.ttf
-70ea04c000-70ea060000 r-xp 00000000 fc:00 2731 /system/lib64/libstatslog.so
-70ea060000-70ea07b000 ---p 00000000 00:00 0
-70ea07b000-70ea07c000 r--p 0001f000 fc:00 2731 /system/lib64/libstatslog.so
-70ea07c000-70ea07d000 rw-p 00020000 fc:00 2731 /system/lib64/libstatslog.so
-70ea07d000-70ea081000 r--s 00000000 fc:00 182 /system/fonts/NotoSansBatak-Regular.ttf
-70ea081000-70ea091000 r--s 00000000 fc:00 264 /system/fonts/NotoSerifGujarati-Regular.ttf
-70ea091000-70ea160000 r-xp 00000000 fc:00 2728 /system/lib64/libdng_sdk.so
-70ea160000-70ea173000 ---p 00000000 00:00 0
-70ea173000-70ea17a000 r--p 000d9000 fc:00 2728 /system/lib64/libdng_sdk.so
-70ea17a000-70ea17b000 rw-p 000e0000 fc:00 2728 /system/lib64/libdng_sdk.so
-70ea17b000-70ea198000 r--s 00000000 fc:00 223 /system/fonts/DancingScript-Bold.ttf
-70ea198000-70ea19c000 r-xp 00000000 fc:00 2344 /system/lib64/libnativewindow.so
-70ea19c000-70ea1b7000 ---p 00000000 00:00 0
-70ea1b7000-70ea1b8000 r--p 0000f000 fc:00 2344 /system/lib64/libnativewindow.so
-70ea1b8000-70ea1b9000 rw-p 00010000 fc:00 2344 /system/lib64/libnativewindow.so
-70ea1b9000-70ea1bd000 r--s 00000000 fc:00 98 /system/fonts/NotoSansAhom-Regular.otf
-70ea1bd000-70ea1d1000 r--s 00000000 fc:00 104 /system/fonts/NotoSerifDevanagari-Bold.ttf
-70ea1d1000-70ea1d4000 r-xp 00000000 fc:00 2923 /system/lib64/libstdc++.so
-70ea1d4000-70ea1f0000 ---p 00000000 00:00 0
-70ea1f0000-70ea1f1000 r--p 0000f000 fc:00 2923 /system/lib64/libstdc++.so
-70ea1f1000-70ea1f2000 rw-p 00010000 fc:00 2923 /system/lib64/libstdc++.so
-70ea1f2000-70ea1f4000 r--s 00000000 fc:00 117 /system/fonts/NotoSansLydian-Regular.ttf
-70ea1f4000-70ea211000 r--s 00000000 fc:00 239 /system/fonts/DancingScript-Regular.ttf
-70ea211000-70ea24a000 r-xp 00000000 fc:00 2933 /system/lib64/android.hardware.graphics.bufferqueue@1.0.so
-70ea24a000-70ea268000 ---p 00000000 00:00 0
-70ea268000-70ea26c000 r--p 0003c000 fc:00 2933 /system/lib64/android.hardware.graphics.bufferqueue@1.0.so
-70ea26c000-70ea26d000 rw-p 00040000 fc:00 2933 /system/lib64/android.hardware.graphics.bufferqueue@1.0.so
-70ea26d000-70ea26f000 r--s 00000000 fc:00 244 /system/fonts/NotoSansLycian-Regular.ttf
-70ea26f000-70ea273000 r--s 00000000 fc:00 173 /system/fonts/NotoSansThaana-Bold.ttf
-70ea273000-70ea287000 r--s 00000000 fc:00 106 /system/fonts/NotoSerifDevanagari-Regular.ttf
-70ea287000-70ea29e000 r-xp 00000000 fc:00 2938 /system/lib64/libpiex.so
-70ea29e000-70ea2b6000 ---p 00000000 00:00 0
-70ea2b6000-70ea2b7000 r--p 0001f000 fc:00 2938 /system/lib64/libpiex.so
-70ea2b7000-70ea2b8000 rw-p 00020000 fc:00 2938 /system/lib64/libpiex.so
-70ea2b8000-70ea2c0000 r--s 00000000 fc:00 113 /system/fonts/NotoSansGurmukhi-Regular.ttf
-70ea2c0000-70ea2c6000 r--s 00000000 fc:00 263 /system/fonts/NotoSerifGeorgian-Bold.ttf
-70ea2c6000-70ea2cc000 r--s 00000000 fc:00 249 /system/fonts/NotoSerifGeorgian-Regular.ttf
-70ea2cc000-70ea9b4000 r-xp 00000000 fc:00 2532 /system/lib64/libhwui.so
-70ea9b4000-70ea9d3000 ---p 00000000 00:00 0
-70ea9d3000-70eaa0b000 r--p 006e8000 fc:00 2532 /system/lib64/libhwui.so
-70eaa0b000-70eaa0c000 rw-p 00720000 fc:00 2532 /system/lib64/libhwui.so
-70eaa0c000-70eaa11000 rw-p 00000000 00:00 0 [anon:.bss]
-70eaa11000-70eaa12000 r--s 00000000 fc:00 1110 /system/usr/hyphen-data/hyph-la.hyb
-70eaa12000-70eaa16000 r--s 00000000 fc:00 87 /system/fonts/NotoSansThaana-Regular.ttf
-70eaa16000-70eaa1b000 r--s 00000000 fc:00 218 /system/fonts/NotoSansGeorgian-Bold.ttf
-70eaa1b000-70eaa20000 r--s 00000000 fc:00 125 /system/fonts/NotoSansGeorgian-Regular.ttf
-70eaa20000-70eaa40000 rw-p 00000000 00:05 10271007 [anon:dalvik-CompilerMetadata]
-70eaa40000-70eaaa0000 r-xp 00000000 fc:00 2384 /system/lib64/libhidltransport.so
-70eaaa0000-70eaabe000 ---p 00000000 00:00 0
-70eaabe000-70eaac6000 r--p 00068000 fc:00 2384 /system/lib64/libhidltransport.so
-70eaac6000-70eaac7000 rw-p 00070000 fc:00 2384 /system/lib64/libhidltransport.so
-70eaac7000-70eaacb000 r--s 00000000 fc:00 192 /system/fonts/NotoSerifArmenian-Bold.ttf
-70eaacb000-70eaad0000 r--s 00000000 fc:00 210 /system/fonts/NotoSansThaiUI-Bold.ttf
-70eaad0000-70eaaf0000 rw-p 00000000 00:05 10271006 [anon:dalvik-CompilerMetadata]
-70eaaf0000-70eab10000 rw-p 00000000 00:05 10271005 [anon:dalvik-CompilerMetadata]
-70eab10000-70eab57000 r-xp 00000000 fc:00 2546 /system/lib64/libmedia_omx.so
-70eab57000-70eab6d000 ---p 00000000 00:00 0
-70eab6d000-70eab7a000 r--p 00053000 fc:00 2546 /system/lib64/libmedia_omx.so
-70eab7a000-70eab7f000 rw-p 00060000 fc:00 2546 /system/lib64/libmedia_omx.so
-70eab7f000-70eab80000 r--s 00000000 fc:00 1119 /system/usr/hyphen-data/hyph-kn.hyb
-70eab80000-70eab86000 r--s 00000000 fc:00 224 /system/fonts/NotoSansThaiUI-Regular.ttf
-70eab86000-70eab8b000 r--s 00000000 fc:00 300 /system/fonts/NotoSerifThai-Bold.ttf
-70eab8b000-70eabab000 rw-p 00000000 00:05 10271004 [anon:dalvik-CompilerMetadata]
-70eabab000-70eac21000 r-xp 00000000 fc:00 2385 /system/lib64/libvintf.so
-70eac21000-70eac31000 ---p 00000000 00:00 0
-70eac31000-70eac36000 r--p 0007b000 fc:00 2385 /system/lib64/libvintf.so
-70eac36000-70eac37000 rw-p 00080000 fc:00 2385 /system/lib64/libvintf.so
-70eac37000-70eac39000 rw-p 00000000 00:00 0 [anon:.bss]
-70eac39000-70eac3a000 r--s 00000000 fc:00 1104 /system/usr/hyphen-data/hyph-hy.hyb
-70eac3a000-70eac3f000 r--s 00000000 fc:00 212 /system/fonts/NotoSerifThai-Regular.ttf
-70eac3f000-70eac44000 r--s 00000000 fc:00 220 /system/fonts/NotoSansThai-Bold.ttf
-70eac44000-70eacb2000 r-xp 00000000 fc:00 2606 /system/lib64/android.hardware.media.omx@1.0.so
-70eacb2000-70eaccf000 ---p 00000000 00:00 0
-70eaccf000-70eacd8000 r--p 00077000 fc:00 2606 /system/lib64/android.hardware.media.omx@1.0.so
-70eacd8000-70eacd9000 rw-p 00080000 fc:00 2606 /system/lib64/android.hardware.media.omx@1.0.so
-70eacd9000-70eacdf000 r--s 00000000 fc:00 169 /system/fonts/NotoSansThai-Regular.ttf
-70eacdf000-70eace9000 r--s 00000000 fc:00 140 /system/fonts/CarroisGothicSC-Regular.ttf
-70eace9000-70ead09000 rw-p 00000000 00:05 10271003 [anon:dalvik-CompilerMetadata]
-70ead09000-70ead22000 r-xp 00000000 fc:00 2539 /system/lib64/android.hardware.graphics.mapper@2.1.so
-70ead22000-70ead34000 ---p 00000000 00:00 0
-70ead34000-70ead37000 r--p 0001d000 fc:00 2539 /system/lib64/android.hardware.graphics.mapper@2.1.so
-70ead37000-70ead38000 rw-p 00020000 fc:00 2539 /system/lib64/android.hardware.graphics.mapper@2.1.so
-70ead38000-70ead47000 r--s 00000000 fc:00 188 /system/fonts/ComingSoon.ttf
-70ead47000-70ead5d000 r-xp 00000000 fc:00 2379 /system/lib64/libselinux.so
-70ead5d000-70ead76000 ---p 00000000 00:00 0
-70ead76000-70ead77000 r--p 0001f000 fc:00 2379 /system/lib64/libselinux.so
-70ead77000-70ead78000 rw-p 00020000 fc:00 2379 /system/lib64/libselinux.so
-70ead78000-70ead79000 rw-p 00000000 00:00 0 [anon:.bss]
-70ead79000-70ead7d000 r--s 00000000 fc:00 282 /system/fonts/NotoSerifArmenian-Regular.ttf
-70ead7d000-70ead82000 r--s 00000000 fc:00 288 /system/fonts/NotoSerifHebrew-Bold.ttf
-70ead82000-70ead83000 r-xp 00000000 fc:00 2680 /system/lib64/android.hardware.media@1.0.so
-70ead83000-70eada1000 ---p 00000000 00:00 0
-70eada1000-70eada2000 r--p 0000f000 fc:00 2680 /system/lib64/android.hardware.media@1.0.so
-70eada2000-70eada3000 rw-p 00010000 fc:00 2680 /system/lib64/android.hardware.media@1.0.so
-70eada3000-70eada8000 r--s 00000000 fc:00 248 /system/fonts/NotoSerifHebrew-Regular.ttf
-70eada8000-70eadb9000 r--s 00000000 fc:00 252 /system/fonts/CutiveMono.ttf
-70eadb9000-70eadd9000 r--s 00000000 00:10 16641 /dev/__properties__/u:object_r:radio_prop:s0
-70eadd9000-70eadda000 r-xp 00000000 fc:00 2533 /system/lib64/android.hardware.graphics.common@1.0.so
-70eadda000-70eadf8000 ---p 00000000 00:00 0
-70eadf8000-70eadf9000 r--p 0000f000 fc:00 2533 /system/lib64/android.hardware.graphics.common@1.0.so
-70eadf9000-70eadfa000 rw-p 00010000 fc:00 2533 /system/lib64/android.hardware.graphics.common@1.0.so
-70eadfa000-70eadfb000 r--s 00000000 fc:00 1126 /system/usr/hyphen-data/hyph-hr.hyb
-70eadfb000-70eadfd000 r--s 00000000 fc:00 194 /system/fonts/NotoSansLisu-Regular.ttf
-70eadfd000-70eae18000 r--s 00000000 fc:00 201 /system/fonts/DroidSansMono.ttf
-70eae18000-70eae3b000 r-xp 00000000 fc:00 2925 /system/lib64/liblzma.so
-70eae3b000-70eae57000 ---p 00000000 00:00 0
-70eae57000-70eae58000 r--p 0002f000 fc:00 2925 /system/lib64/liblzma.so
-70eae58000-70eae59000 rw-p 00030000 fc:00 2925 /system/lib64/liblzma.so
-70eae59000-70eae5f000 rw-p 00000000 00:00 0 [anon:.bss]
-70eae5f000-70eae62000 r--s 00000000 fc:00 103 /system/fonts/NotoSansLimbu-Regular.ttf
-70eae62000-70eae67000 r--s 00000000 fc:00 236 /system/fonts/NotoSansHebrew-Bold.ttf
-70eae67000-70eae84000 r--s 001c2000 fc:00 990 /system/framework/ext.jar
-70eae84000-70eaea4000 rw-p 00000000 00:05 10269720 [anon:dalvik-LinearAlloc]
-70eaea4000-70eaede000 r-xp 00000000 fc:00 2924 /system/lib64/libwilhelm.so
-70eaede000-70eaefa000 ---p 00000000 00:00 0
-70eaefa000-70eaeff000 r--p 0003b000 fc:00 2924 /system/lib64/libwilhelm.so
-70eaeff000-70eaf00000 rw-p 00040000 fc:00 2924 /system/lib64/libwilhelm.so
-70eaf00000-70eaf03000 r--s 00000000 fc:00 242 /system/fonts/NotoSansElbasan-Regular.otf
-70eaf03000-70eaf21000 r-xp 00000000 fc:00 2415 /system/lib64/libdrmframework.so
-70eaf21000-70eaf38000 ---p 00000000 00:00 0
-70eaf38000-70eaf3d000 r--p 0002b000 fc:00 2415 /system/lib64/libdrmframework.so
-70eaf3d000-70eaf3e000 rw-p 00030000 fc:00 2415 /system/lib64/libdrmframework.so
-70eaf3e000-70eaf43000 r--s 00000000 fc:00 70 /system/fonts/NotoSansHebrew-Regular.ttf
-70eaf43000-70eaf44000 ---p 00000000 00:00 0 [anon:thread signal stack guard]
-70eaf44000-70eaf48000 rw-p 00000000 00:00 0 [anon:thread signal stack]
-70eaf48000-70eaf49000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70eaf49000-70eaf4c000 rw-p 00000000 00:00 0 [anon:bionic TLS]
-70eaf4c000-70eaf4d000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70eaf4d000-70eaf4e000 ---p 00000000 00:00 0 [anon:thread signal stack guard]
-70eaf4e000-70eaf52000 rw-p 00000000 00:00 0 [anon:thread signal stack]
-70eaf52000-70eaf98000 r-xp 00000000 fc:00 2426 /system/lib64/libunwindstack.so
-70eaf98000-70eafb6000 ---p 00000000 00:00 0
-70eafb6000-70eafbd000 r--p 00049000 fc:00 2426 /system/lib64/libunwindstack.so
-70eafbd000-70eafbe000 rw-p 00050000 fc:00 2426 /system/lib64/libunwindstack.so
-70eafbe000-70eafc0000 r--s 00000000 fc:00 162 /system/fonts/NotoSansKayahLi-Regular.ttf
-70eafc0000-70eafe4000 r-xp 00000000 fc:00 2944 /system/lib64/libvulkan.so
-70eafe4000-70eaffc000 ---p 00000000 00:00 0
-70eaffc000-70eaffe000 r--p 0002e000 fc:00 2944 /system/lib64/libvulkan.so
-70eaffe000-70eafff000 rw-p 00030000 fc:00 2944 /system/lib64/libvulkan.so
-70eafff000-70eb001000 r--s 00000000 fc:00 180 /system/fonts/NotoSansInscriptionalParthian-Regular.ttf
-70eb001000-70eb01d000 r-xp 00000000 fc:00 2400 /system/lib64/libbufferhubqueue.so
-70eb01d000-70eb030000 ---p 00000000 00:00 0
-70eb030000-70eb031000 r--p 0001f000 fc:00 2400 /system/lib64/libbufferhubqueue.so
-70eb031000-70eb032000 rw-p 00020000 fc:00 2400 /system/lib64/libbufferhubqueue.so
-70eb032000-70eb036000 r--s 00000000 fc:00 269 /system/fonts/NotoSansArmenian-Bold.ttf
-70eb036000-70eb037000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70eb037000-70eb03a000 rw-p 00000000 00:00 0 [anon:bionic TLS]
-70eb03a000-70eb03b000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70eb03b000-70eb03c000 ---p 00000000 00:00 0 [anon:thread signal stack guard]
-70eb03c000-70eb040000 rw-p 00000000 00:00 0 [anon:thread signal stack]
-70eb040000-70eb042000 r-xp 00000000 fc:00 2935 /system/lib64/libhardware.so
-70eb042000-70eb05f000 ---p 00000000 00:00 0
-70eb05f000-70eb060000 r--p 0000f000 fc:00 2935 /system/lib64/libhardware.so
-70eb060000-70eb061000 rw-p 00010000 fc:00 2935 /system/lib64/libhardware.so
-70eb061000-70eb063000 r--s 00000000 fc:00 171 /system/fonts/NotoSansInscriptionalPahlavi-Regular.ttf
-70eb063000-70eb064000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70eb064000-70eb067000 rw-p 00000000 00:00 0 [anon:bionic TLS]
-70eb067000-70eb068000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70eb068000-70eb069000 ---p 00000000 00:00 0 [anon:thread signal stack guard]
-70eb069000-70eb06d000 rw-p 00000000 00:00 0 [anon:thread signal stack]
-70eb06d000-70eb06e000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70eb06e000-70eb071000 rw-p 00000000 00:00 0 [anon:bionic TLS]
-70eb071000-70eb072000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70eb072000-70eb073000 ---p 00000000 00:00 0 [anon:thread signal stack guard]
-70eb073000-70eb077000 rw-p 00000000 00:00 0 [anon:thread signal stack]
-70eb077000-70eb078000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70eb078000-70eb07b000 rw-p 00000000 00:00 0 [anon:bionic TLS]
-70eb07b000-70eb07c000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70eb07c000-70eb07d000 ---p 00000000 00:00 0 [anon:thread signal stack guard]
-70eb07d000-70eb081000 rw-p 00000000 00:00 0 [anon:thread signal stack]
-70eb081000-70eb082000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70eb082000-70eb085000 rw-p 00000000 00:00 0 [anon:bionic TLS]
-70eb085000-70eb086000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70eb086000-70eb09d000 r-xp 00000000 fc:00 2604 /system/lib64/libz.so
-70eb09d000-70eb0b5000 ---p 00000000 00:00 0
-70eb0b5000-70eb0b6000 r--p 0001f000 fc:00 2604 /system/lib64/libz.so
-70eb0b6000-70eb0b7000 rw-p 00020000 fc:00 2604 /system/lib64/libz.so
-70eb0b7000-70eb0bb000 r--s 00000000 fc:00 289 /system/fonts/NotoSansArmenian-Regular.ttf
-70eb0bb000-70eb0bc000 ---p 00000000 00:00 0 [anon:thread signal stack guard]
-70eb0bc000-70eb0c0000 rw-p 00000000 00:00 0 [anon:thread signal stack]
-70eb0c0000-70eb0c1000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70eb0c1000-70eb0c4000 rw-p 00000000 00:00 0 [anon:bionic TLS]
-70eb0c4000-70eb0c5000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70eb0c5000-70eb0c6000 ---p 00000000 00:00 0 [anon:thread signal stack guard]
-70eb0c6000-70eb0ca000 rw-p 00000000 00:00 0 [anon:thread signal stack]
-70eb0ca000-70eb0cb000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70eb0cb000-70eb0ce000 rw-p 00000000 00:00 0 [anon:bionic TLS]
-70eb0ce000-70eb0cf000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70eb0cf000-70eb0ef000 rw-p 00000000 00:05 10270988 [anon:dalvik-LinearAlloc]
-70eb0ef000-70eb5bb000 r-xp 00000000 fc:00 2374 /system/lib64/libpdfium.so
-70eb5bb000-70eb5cf000 ---p 00000000 00:00 0
-70eb5cf000-70eb5e6000 r--p 004d9000 fc:00 2374 /system/lib64/libpdfium.so
-70eb5e6000-70eb5ea000 rw-p 004f0000 fc:00 2374 /system/lib64/libpdfium.so
-70eb5ea000-70eb5f1000 rw-p 00000000 00:00 0 [anon:.bss]
-70eb5f1000-70eb5f2000 r--s 00000000 fc:00 1094 /system/usr/hyphen-data/hyph-hi.hyb
-70eb5f2000-70eb5f6000 rw-p 00000000 00:05 10270982 [anon:dalvik-thread local mark stack]
-70eb5f6000-70eb5fa000 rw-p 00000000 00:05 10270981 [anon:dalvik-thread local mark stack]
-70eb5fa000-70eb5fe000 rw-p 00000000 00:05 10270980 [anon:dalvik-thread local mark stack]
-70eb5fe000-70eb602000 rw-p 00000000 00:05 10270979 [anon:dalvik-thread local mark stack]
-70eb602000-70eb606000 rw-p 00000000 00:05 10270978 [anon:dalvik-thread local mark stack]
-70eb606000-70eb60a000 rw-p 00000000 00:05 10270977 [anon:dalvik-thread local mark stack]
-70eb60a000-70eb60e000 rw-p 00000000 00:05 10270976 [anon:dalvik-thread local mark stack]
-70eb60e000-70eb612000 rw-p 00000000 00:05 10270975 [anon:dalvik-thread local mark stack]
-70eb612000-70eb616000 rw-p 00000000 00:05 10270974 [anon:dalvik-thread local mark stack]
-70eb616000-70eb61a000 r-xp 00000000 fc:00 2479 /system/lib64/libspeexresampler.so
-70eb61a000-70eb635000 ---p 00000000 00:00 0
-70eb635000-70eb636000 r--p 0000f000 fc:00 2479 /system/lib64/libspeexresampler.so
-70eb636000-70eb637000 rw-p 00010000 fc:00 2479 /system/lib64/libspeexresampler.so
-70eb637000-70eb639000 r--s 00000000 fc:00 299 /system/fonts/NotoSansImperialAramaic-Regular.ttf
-70eb639000-70eb63d000 rw-p 00000000 00:05 10270973 [anon:dalvik-thread local mark stack]
-70eb63d000-70eb641000 rw-p 00000000 00:05 10270972 [anon:dalvik-thread local mark stack]
-70eb641000-70eb645000 rw-p 00000000 00:05 10270971 [anon:dalvik-thread local mark stack]
-70eb645000-70eb649000 rw-p 00000000 00:05 10270970 [anon:dalvik-thread local mark stack]
-70eb649000-70eb64d000 rw-p 00000000 00:05 10270969 [anon:dalvik-thread local mark stack]
-70eb64d000-70eb651000 rw-p 00000000 00:05 10270968 [anon:dalvik-thread local mark stack]
-70eb651000-70eb655000 rw-p 00000000 00:05 10270967 [anon:dalvik-thread local mark stack]
-70eb655000-70eb659000 rw-p 00000000 00:05 10270966 [anon:dalvik-thread local mark stack]
-70eb659000-70eb65d000 rw-p 00000000 00:05 10270965 [anon:dalvik-thread local mark stack]
-70eb65d000-70eb661000 rw-p 00000000 00:05 10270964 [anon:dalvik-thread local mark stack]
-70eb661000-70eb6c5000 r-xp 00000000 fc:00 2461 /system/lib64/libhidl-gen-utils.so
-70eb6c5000-70eb6df000 ---p 00000000 00:00 0
-70eb6df000-70eb6e1000 r--p 0006e000 fc:00 2461 /system/lib64/libhidl-gen-utils.so
-70eb6e1000-70eb6e2000 rw-p 00070000 fc:00 2461 /system/lib64/libhidl-gen-utils.so
-70eb6e2000-70eb6e6000 rw-p 00000000 00:05 10270963 [anon:dalvik-thread local mark stack]
-70eb6e6000-70eb6ea000 rw-p 00000000 00:05 10270962 [anon:dalvik-thread local mark stack]
-70eb6ea000-70eb6ee000 rw-p 00000000 00:05 10270961 [anon:dalvik-thread local mark stack]
-70eb6ee000-70eb6f2000 rw-p 00000000 00:05 10270960 [anon:dalvik-thread local mark stack]
-70eb6f2000-70eb6f6000 rw-p 00000000 00:05 10270959 [anon:dalvik-thread local mark stack]
-70eb6f6000-70eb6fa000 rw-p 00000000 00:05 10270958 [anon:dalvik-thread local mark stack]
-70eb6fa000-70eb6fe000 rw-p 00000000 00:05 10270957 [anon:dalvik-thread local mark stack]
-70eb6fe000-70eb702000 rw-p 00000000 00:05 10270956 [anon:dalvik-thread local mark stack]
-70eb702000-70eb706000 rw-p 00000000 00:05 10270955 [anon:dalvik-thread local mark stack]
-70eb706000-70eb70a000 rw-p 00000000 00:05 10270954 [anon:dalvik-thread local mark stack]
-70eb70a000-70eb70e000 rw-p 00000000 00:05 10270953 [anon:dalvik-thread local mark stack]
-70eb70e000-70eb712000 rw-p 00000000 00:05 10270952 [anon:dalvik-thread local mark stack]
-70eb712000-70eb71a000 r-xp 00000000 fc:00 2652 /system/lib64/libcamera_metadata.so
-70eb71a000-70eb72f000 ---p 00000000 00:00 0
-70eb72f000-70eb730000 r--p 0000f000 fc:00 2652 /system/lib64/libcamera_metadata.so
-70eb730000-70eb732000 rw-p 00010000 fc:00 2652 /system/lib64/libcamera_metadata.so
-70eb732000-70eb734000 r--s 00000000 fc:00 131 /system/fonts/NotoSansHanunoo-Regular.ttf
-70eb734000-70eb738000 rw-p 00000000 00:05 10270951 [anon:dalvik-thread local mark stack]
-70eb738000-70eb73c000 rw-p 00000000 00:05 10270950 [anon:dalvik-thread local mark stack]
-70eb73c000-70eb740000 rw-p 00000000 00:05 10270949 [anon:dalvik-thread local mark stack]
-70eb740000-70eb744000 rw-p 00000000 00:05 10270948 [anon:dalvik-thread local mark stack]
-70eb744000-70eb748000 rw-p 00000000 00:05 10270947 [anon:dalvik-thread local mark stack]
-70eb748000-70eb74c000 rw-p 00000000 00:05 10270946 [anon:dalvik-thread local mark stack]
-70eb74c000-70eb750000 rw-p 00000000 00:05 10270945 [anon:dalvik-thread local mark stack]
-70eb750000-70eb754000 rw-p 00000000 00:05 10270944 [anon:dalvik-thread local mark stack]
-70eb754000-70eb758000 rw-p 00000000 00:05 10270943 [anon:dalvik-thread local mark stack]
-70eb758000-70eb75c000 rw-p 00000000 00:05 10270942 [anon:dalvik-thread local mark stack]
-70eb75c000-70eb760000 rw-p 00000000 00:05 10270941 [anon:dalvik-thread local mark stack]
-70eb760000-70eb764000 rw-p 00000000 00:05 10270940 [anon:dalvik-thread local mark stack]
-70eb764000-70eb767000 rw-p 00000000 00:00 0 [anon:linker_alloc]
-70eb767000-70eb768000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70eb768000-70eb76c000 rw-p 00000000 00:05 10270939 [anon:dalvik-thread local mark stack]
-70eb76c000-70eb770000 rw-p 00000000 00:05 10270938 [anon:dalvik-thread local mark stack]
-70eb770000-70eb771000 rw-p 00000000 00:00 0 [anon:linker_alloc]
-70eb771000-70eb774000 r--s 00000000 fc:00 231 /system/fonts/NotoSansDeseret-Regular.ttf
-70eb774000-70eb778000 rw-p 00000000 00:05 10270937 [anon:dalvik-thread local mark stack]
-70eb778000-70eb77c000 rw-p 00000000 00:05 10270936 [anon:dalvik-thread local mark stack]
-70eb77c000-70eb780000 rw-p 00000000 00:05 10270935 [anon:dalvik-thread local mark stack]
-70eb780000-70eb784000 rw-p 00000000 00:05 10270934 [anon:dalvik-thread local mark stack]
-70eb784000-70eb788000 rw-p 00000000 00:05 10270933 [anon:dalvik-thread local mark stack]
-70eb788000-70eb78c000 rw-p 00000000 00:05 10270932 [anon:dalvik-thread local mark stack]
-70eb78c000-70eb790000 rw-p 00000000 00:05 10270931 [anon:dalvik-thread local mark stack]
-70eb790000-70eb794000 rw-p 00000000 00:05 10270930 [anon:dalvik-thread local mark stack]
-70eb794000-70eb798000 rw-p 00000000 00:05 10270929 [anon:dalvik-thread local mark stack]
-70eb798000-70eb79c000 rw-p 00000000 00:05 10270928 [anon:dalvik-thread local mark stack]
-70eb79c000-70eb7a0000 rw-p 00000000 00:05 10270927 [anon:dalvik-thread local mark stack]
-70eb7a0000-70eb7a1000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70eb7a1000-70eb7a3000 r--s 00000000 fc:00 176 /system/fonts/NotoSansGothic-Regular.ttf
-70eb7a3000-70eb7a7000 rw-p 00000000 00:05 10270926 [anon:dalvik-thread local mark stack]
-70eb7a7000-70eb7a8000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70eb7a8000-70eb7a9000 r--s 00000000 fc:00 1109 /system/usr/hyphen-data/hyph-gu.hyb
-70eb7a9000-70eb7ad000 rw-p 00000000 00:05 10270925 [anon:dalvik-thread local mark stack]
-70eb7ad000-70eb7ae000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70eb7ae000-70eb7af000 rw-p 00000000 00:00 0 [anon:linker_alloc]
-70eb7af000-70eb7b0000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70eb7b0000-70eb7b2000 r--s 00000000 fc:00 191 /system/fonts/NotoSansCypriot-Regular.ttf
-70eb7b2000-70eb7b6000 rw-p 00000000 00:05 10270924 [anon:dalvik-thread local mark stack]
-70eb7b6000-70eb7ba000 rw-p 00000000 00:05 10270923 [anon:dalvik-thread local mark stack]
-70eb7ba000-70eb7be000 rw-p 00000000 00:05 10270922 [anon:dalvik-thread local mark stack]
-70eb7be000-70eb7c2000 rw-p 00000000 00:05 10270921 [anon:dalvik-thread local mark stack]
-70eb7c2000-70eb7c6000 rw-p 00000000 00:05 10270920 [anon:dalvik-thread local mark stack]
-70eb7c6000-70eb7ca000 rw-p 00000000 00:05 10270919 [anon:dalvik-thread local mark stack]
-70eb7ca000-70eb7ce000 rw-p 00000000 00:05 10270918 [anon:dalvik-thread local mark stack]
-70eb7ce000-70eb7d2000 rw-p 00000000 00:05 10270917 [anon:dalvik-thread local mark stack]
-70eb7d2000-70eb7d6000 rw-p 00000000 00:05 10270916 [anon:dalvik-thread local mark stack]
-70eb7d6000-70eb7d7000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects]
-70eb7d7000-70eb7db000 rw-p 00000000 00:05 10270915 [anon:dalvik-thread local mark stack]
-70eb7db000-70eb7df000 rw-p 00000000 00:05 10270914 [anon:dalvik-thread local mark stack]
-70eb7df000-70eb7e3000 rw-p 00000000 00:05 10270913 [anon:dalvik-thread local mark stack]
-70eb7e3000-70eb7e7000 rw-p 00000000 00:05 10270912 [anon:dalvik-thread local mark stack]
-70eb7e7000-70eb7e8000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70eb7e8000-70eb7ea000 r--s 00000000 fc:00 174 /system/fonts/NotoSansCarian-Regular.ttf
-70eb7ea000-70eb7ee000 rw-p 00000000 00:05 10270911 [anon:dalvik-thread local mark stack]
-70eb7ee000-70eb7f2000 rw-p 00000000 00:05 10270910 [anon:dalvik-thread local mark stack]
-70eb7f2000-70eb7f6000 rw-p 00000000 00:05 10270909 [anon:dalvik-thread local mark stack]
-70eb7f6000-70eb7f7000 rw-p 00000000 00:00 0 [anon:linker_alloc]
-70eb7f7000-70eb7f8000 r--s 00000000 fc:00 1096 /system/usr/hyphen-data/hyph-eu.hyb
-70eb7f8000-70eb7fc000 rw-p 00000000 00:05 10270908 [anon:dalvik-thread local mark stack]
-70eb7fc000-70eb800000 rw-p 00000000 00:05 10270907 [anon:dalvik-thread local mark stack]
-70eb800000-70eb804000 rw-p 00000000 00:05 10270906 [anon:dalvik-thread local mark stack]
-70eb804000-70eb808000 rw-p 00000000 00:05 10270905 [anon:dalvik-thread local mark stack]
-70eb808000-70eb80c000 rw-p 00000000 00:05 10270904 [anon:dalvik-thread local mark stack]
-70eb80c000-70eb810000 rw-p 00000000 00:05 10270903 [anon:dalvik-thread local mark stack]
-70eb810000-70eb814000 rw-p 00000000 00:05 10270902 [anon:dalvik-thread local mark stack]
-70eb814000-70eb815000 rw-p 00000000 00:00 0 [anon:linker_alloc_vector]
-70eb815000-70eb819000 rw-p 00000000 00:05 10270901 [anon:dalvik-thread local mark stack]
-70eb819000-70eb81d000 rw-p 00000000 00:05 10270900 [anon:dalvik-thread local mark stack]
-70eb81d000-70eb81e000 rw-p 00000000 00:00 0 [anon:linker_alloc]
-70eb81e000-70eb822000 rw-p 00000000 00:05 10270899 [anon:dalvik-thread local mark stack]
-70eb822000-70eb826000 rw-p 00000000 00:05 10270898 [anon:dalvik-thread local mark stack]
-70eb826000-70eb82a000 rw-p 00000000 00:05 10270897 [anon:dalvik-thread local mark stack]
-70eb82a000-70eb82e000 rw-p 00000000 00:05 10270896 [anon:dalvik-thread local mark stack]
-70eb82e000-70eb832000 rw-p 00000000 00:05 10270895 [anon:dalvik-thread local mark stack]
-70eb832000-70eb836000 rw-p 00000000 00:05 10270894 [anon:dalvik-thread local mark stack]
-70eb836000-70eb837000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70eb837000-70eb83b000 rw-p 00000000 00:05 10270893 [anon:dalvik-thread local mark stack]
-70eb83b000-70eb83f000 rw-p 00000000 00:05 10270892 [anon:dalvik-thread local mark stack]
-70eb83f000-70eb843000 rw-p 00000000 00:05 10270891 [anon:dalvik-thread local mark stack]
-70eb843000-70eb847000 rw-p 00000000 00:05 10270890 [anon:dalvik-thread local mark stack]
-70eb847000-70eb84b000 rw-p 00000000 00:05 10270889 [anon:dalvik-thread local mark stack]
-70eb84b000-70eb84f000 rw-p 00000000 00:05 10270888 [anon:dalvik-thread local mark stack]
-70eb84f000-70eb850000 rw-p 00000000 00:00 0 [anon:linker_alloc]
-70eb850000-70eb854000 rw-p 00000000 00:05 10270887 [anon:dalvik-thread local mark stack]
-70eb854000-70eb858000 rw-p 00000000 00:05 10270886 [anon:dalvik-thread local mark stack]
-70eb858000-70eb85c000 rw-p 00000000 00:05 10270885 [anon:dalvik-thread local mark stack]
-70eb85c000-70eb860000 rw-p 00000000 00:05 10270884 [anon:dalvik-thread local mark stack]
-70eb860000-70eb864000 rw-p 00000000 00:05 10270883 [anon:dalvik-thread local mark stack]
-70eb864000-70eb868000 rw-p 00000000 00:05 10270882 [anon:dalvik-thread local mark stack]
-70eb868000-70eb869000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70eb869000-70eb86d000 rw-p 00000000 00:05 10270881 [anon:dalvik-thread local mark stack]
-70eb86d000-70eb871000 rw-p 00000000 00:05 10270880 [anon:dalvik-thread local mark stack]
-70eb871000-70eb875000 rw-p 00000000 00:05 10270879 [anon:dalvik-thread local mark stack]
-70eb875000-70eb879000 rw-p 00000000 00:05 10270878 [anon:dalvik-thread local mark stack]
-70eb879000-70eb87d000 rw-p 00000000 00:05 10270877 [anon:dalvik-thread local mark stack]
-70eb87d000-70eb881000 rw-p 00000000 00:05 10270876 [anon:dalvik-thread local mark stack]
-70eb881000-70eb885000 rw-p 00000000 00:05 10270875 [anon:dalvik-thread local mark stack]
-70eb885000-70eb889000 rw-p 00000000 00:05 10270874 [anon:dalvik-thread local mark stack]
-70eb889000-70eb88d000 rw-p 00000000 00:05 10270873 [anon:dalvik-thread local mark stack]
-70eb88d000-70eb891000 rw-p 00000000 00:05 10270872 [anon:dalvik-thread local mark stack]
-70eb891000-70eb892000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70eb892000-70eb896000 rw-p 00000000 00:05 10270871 [anon:dalvik-thread local mark stack]
-70eb896000-70eb89a000 rw-p 00000000 00:05 10270870 [anon:dalvik-thread local mark stack]
-70eb89a000-70eb89b000 rw-p 00000000 00:00 0 [anon:linker_alloc_vector]
-70eb89b000-70eb89c000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects]
-70eb89c000-70eb8a0000 rw-p 00000000 00:05 10270869 [anon:dalvik-thread local mark stack]
-70eb8a0000-70eb8a4000 rw-p 00000000 00:05 10270868 [anon:dalvik-thread local mark stack]
-70eb8a4000-70eb8a5000 r--p 00000000 00:00 0 [anon:atexit handlers]
-70eb8a5000-70eb8a9000 rw-p 00000000 00:05 10270867 [anon:dalvik-thread local mark stack]
-70eb8a9000-70eb8ad000 rw-p 00000000 00:05 10270866 [anon:dalvik-thread local mark stack]
-70eb8ad000-70eb8b1000 rw-p 00000000 00:05 10270865 [anon:dalvik-thread local mark stack]
-70eb8b1000-70eb8b5000 rw-p 00000000 00:05 10270864 [anon:dalvik-thread local mark stack]
-70eb8b5000-70eb8b9000 rw-p 00000000 00:05 10270863 [anon:dalvik-thread local mark stack]
-70eb8b9000-70eb8bd000 rw-p 00000000 00:05 10270862 [anon:dalvik-thread local mark stack]
-70eb8bd000-70eb8be000 rw-p 00000000 00:00 0 [anon:linker_alloc]
-70eb8be000-70eb8c1000 r--s 00000000 fc:00 168 /system/fonts/NotoSansAvestan-Regular.ttf
-70eb8c1000-70eb8c5000 rw-p 00000000 00:05 10270861 [anon:dalvik-thread local mark stack]
-70eb8c5000-70eb8c9000 rw-p 00000000 00:05 10270860 [anon:dalvik-thread local mark stack]
-70eb8c9000-70eb8cd000 rw-p 00000000 00:05 10270859 [anon:dalvik-thread local mark stack]
-70eb8cd000-70eb8d1000 rw-p 00000000 00:05 10270858 [anon:dalvik-thread local mark stack]
-70eb8d1000-70eb8d5000 rw-p 00000000 00:05 10270857 [anon:dalvik-thread local mark stack]
-70eb8d5000-70eb8d7000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70eb8d7000-70eb8db000 rw-p 00000000 00:05 10270856 [anon:dalvik-thread local mark stack]
-70eb8db000-70eb8df000 rw-p 00000000 00:05 10270855 [anon:dalvik-thread local mark stack]
-70eb8df000-70eb8e3000 rw-p 00000000 00:05 10270854 [anon:dalvik-thread local mark stack]
-70eb8e3000-70eb8e7000 rw-p 00000000 00:05 10270853 [anon:dalvik-thread local mark stack]
-70eb8e7000-70eb8eb000 rw-p 00000000 00:05 10270852 [anon:dalvik-thread local mark stack]
-70eb8eb000-70eb8ec000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70eb8ec000-70eb8ed000 r--s 00000000 fc:00 1099 /system/usr/hyphen-data/hyph-bn.hyb
-70eb8ed000-70eb8f1000 rw-p 00000000 00:05 10270851 [anon:dalvik-thread local mark stack]
-70eb8f1000-70eb8f5000 rw-p 00000000 00:05 10270850 [anon:dalvik-thread local mark stack]
-70eb8f5000-70eb8f9000 rw-p 00000000 00:05 10270849 [anon:dalvik-thread local mark stack]
-70eb8f9000-70eb8fd000 rw-p 00000000 00:05 10270848 [anon:dalvik-thread local mark stack]
-70eb8fd000-70eb901000 rw-p 00000000 00:05 10270847 [anon:dalvik-thread local mark stack]
-70eb901000-70eb905000 rw-p 00000000 00:05 10270846 [anon:dalvik-thread local mark stack]
-70eb905000-70eb909000 rw-p 00000000 00:05 10270845 [anon:dalvik-thread local mark stack]
-70eb909000-70eb90d000 rw-p 00000000 00:05 10270844 [anon:dalvik-thread local mark stack]
-70eb90d000-70eb911000 rw-p 00000000 00:05 10270843 [anon:dalvik-thread local mark stack]
-70eb911000-70eb915000 rw-p 00000000 00:05 10270842 [anon:dalvik-thread local mark stack]
-70eb915000-70eb916000 rw-p 00000000 00:00 0 [anon:linker_alloc]
-70eb916000-70eb917000 r--s 00000000 fc:00 1114 /system/usr/hyphen-data/hyph-bg.hyb
-70eb917000-70eb91b000 rw-p 00000000 00:05 10270841 [anon:dalvik-thread local mark stack]
-70eb91b000-70eb91c000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70eb91c000-70eb91d000 r--s 00000000 fc:00 1133 /system/usr/hyphen-data/hyph-as.hyb
-70eb91d000-70eb921000 rw-p 00000000 00:05 10270840 [anon:dalvik-thread local mark stack]
-70eb921000-70eb925000 rw-p 00000000 00:05 10270839 [anon:dalvik-thread local mark stack]
-70eb925000-70eb926000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects]
-70eb926000-70eb927000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70eb927000-70eb929000 r--s 00000000 fc:00 203 /system/fonts/NotoSansBuhid-Regular.ttf
-70eb929000-70eb92d000 rw-p 00000000 00:05 10270838 [anon:dalvik-thread local mark stack]
-70eb92d000-70eb931000 rw-p 00000000 00:05 10270837 [anon:dalvik-thread local mark stack]
-70eb931000-70eb935000 rw-p 00000000 00:05 10270836 [anon:dalvik-thread local mark stack]
-70eb935000-70eb939000 rw-p 00000000 00:05 10270835 [anon:dalvik-thread local mark stack]
-70eb939000-70eb93d000 rw-p 00000000 00:05 10270834 [anon:dalvik-thread local mark stack]
-70eb93d000-70eb941000 rw-p 00000000 00:05 10270833 [anon:dalvik-thread local mark stack]
-70eb941000-70eb945000 rw-p 00000000 00:05 10270832 [anon:dalvik-thread local mark stack]
-70eb945000-70eb949000 rw-p 00000000 00:05 10270831 [anon:dalvik-thread local mark stack]
-70eb949000-70eb94d000 rw-p 00000000 00:05 10270830 [anon:dalvik-thread local mark stack]
-70eb94d000-70eb951000 rw-p 00000000 00:05 10270829 [anon:dalvik-thread local mark stack]
-70eb951000-70eb991000 rw-p 00000000 00:05 10270722 [anon:dalvik-mark stack]
-70eb991000-70eb992000 rw-p 00000000 00:00 0 [anon:linker_alloc]
-70eb992000-70eb996000 rw-p 00000000 00:05 10270828 [anon:dalvik-thread local mark stack]
-70eb996000-70eb99a000 rw-p 00000000 00:05 10270827 [anon:dalvik-thread local mark stack]
-70eb99a000-70eb99e000 rw-p 00000000 00:05 10270826 [anon:dalvik-thread local mark stack]
-70eb99e000-70eb9a2000 rw-p 00000000 00:05 10270825 [anon:dalvik-thread local mark stack]
-70eb9a2000-70eb9a4000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70eb9a4000-70eb9a8000 rw-p 00000000 00:05 10270824 [anon:dalvik-thread local mark stack]
-70eb9a8000-70eb9ac000 rw-p 00000000 00:05 10270823 [anon:dalvik-thread local mark stack]
-70eb9ac000-70eb9b0000 rw-p 00000000 00:05 10270822 [anon:dalvik-thread local mark stack]
-70eb9b0000-70eb9b1000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70eb9b1000-70eb9b2000 r--s 00021000 fc:01 1180 /vendor/overlay/framework-res__auto_generated_rro.apk
-70eb9b2000-70eb9b6000 rw-p 00000000 00:05 10270821 [anon:dalvik-thread local mark stack]
-70eb9b6000-70eb9ba000 rw-p 00000000 00:05 10270820 [anon:dalvik-thread local mark stack]
-70eb9ba000-70eb9be000 rw-p 00000000 00:05 10270819 [anon:dalvik-thread local mark stack]
-70eb9be000-70eb9c2000 rw-p 00000000 00:05 10270818 [anon:dalvik-thread local mark stack]
-70eb9c2000-70eb9c6000 rw-p 00000000 00:05 10270817 [anon:dalvik-thread local mark stack]
-70eb9c6000-70eb9ca000 rw-p 00000000 00:05 10270816 [anon:dalvik-thread local mark stack]
-70eb9ca000-70eb9ce000 rw-p 00000000 00:05 10270815 [anon:dalvik-thread local mark stack]
-70eb9ce000-70eb9cf000 rw-p 00000000 00:00 0 [anon:linker_alloc]
-70eb9cf000-70eb9d1000 r--s 00000000 fc:00 213 /system/fonts/NotoSansBuginese-Regular.ttf
-70eb9d1000-70eb9d5000 rw-p 00000000 00:05 10270814 [anon:dalvik-thread local mark stack]
-70eb9d5000-70eb9d9000 rw-p 00000000 00:05 10270813 [anon:dalvik-thread local mark stack]
-70eb9d9000-70eb9dd000 rw-p 00000000 00:05 10270812 [anon:dalvik-thread local mark stack]
-70eb9dd000-70eb9e1000 rw-p 00000000 00:05 10270811 [anon:dalvik-thread local mark stack]
-70eb9e1000-70eb9e5000 rw-p 00000000 00:05 10270810 [anon:dalvik-thread local mark stack]
-70eb9e5000-70eb9e9000 rw-p 00000000 00:05 10270809 [anon:dalvik-thread local mark stack]
-70eb9e9000-70eb9ed000 rw-p 00000000 00:05 10270808 [anon:dalvik-thread local mark stack]
-70eb9ed000-70eb9f1000 rw-p 00000000 00:05 10270807 [anon:dalvik-thread local mark stack]
-70eb9f1000-70eb9f5000 rw-p 00000000 00:05 10270806 [anon:dalvik-thread local mark stack]
-70eb9f5000-70eb9f6000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70eb9f6000-70eb9f8000 rw-p 00000000 00:05 10271002 [anon:dalvik-indirect ref table]
-70eb9f8000-70eb9fc000 rw-p 00000000 00:05 10270805 [anon:dalvik-thread local mark stack]
-70eb9fc000-70eb9fd000 rw-p 00000000 00:00 0 [anon:linker_alloc]
-70eb9fd000-70eb9ff000 rw-p 00000000 00:05 10270999 [anon:dalvik-indirect ref table]
-70eb9ff000-70eba00000 r--s 00000000 fc:00 983 /system/framework/com.google.vr.platform.jar
-70eba00000-70eba04000 rw-p 00000000 00:05 10270804 [anon:dalvik-thread local mark stack]
-70eba04000-70eba08000 rw-p 00000000 00:05 10270803 [anon:dalvik-thread local mark stack]
-70eba08000-70eba0c000 rw-p 00000000 00:05 10270802 [anon:dalvik-thread local mark stack]
-70eba0c000-70eba10000 rw-p 00000000 00:05 10270801 [anon:dalvik-thread local mark stack]
-70eba10000-70eba14000 rw-p 00000000 00:05 10270800 [anon:dalvik-thread local mark stack]
-70eba14000-70eba18000 rw-p 00000000 00:05 10270799 [anon:dalvik-thread local mark stack]
-70eba18000-70eba1c000 rw-p 00000000 00:05 10270798 [anon:dalvik-thread local mark stack]
-70eba1c000-70eba20000 rw-p 00000000 00:05 10270797 [anon:dalvik-thread local mark stack]
-70eba20000-70eba24000 rw-p 00000000 00:05 10270796 [anon:dalvik-thread local mark stack]
-70eba24000-70eba28000 rw-p 00000000 00:05 10270795 [anon:dalvik-thread local mark stack]
-70eba28000-70eba2c000 rw-p 00000000 00:05 10270794 [anon:dalvik-thread local mark stack]
-70eba2c000-70eba2d000 rw-p 00000000 00:00 0 [anon:linker_alloc]
-70eba2d000-70eba2e000 r--s 00000000 fc:00 881 /system/framework/android.test.base.jar
-70eba2e000-70eba2f000 r--s 00000000 fc:00 707 /system/framework/framework-oahl-backward-compatibility.jar
-70eba2f000-70eba30000 r--s 00000000 fc:00 705 /system/framework/android.hidl.manager-V1.0-java.jar
-70eba30000-70eba34000 rw-p 00000000 00:05 10270793 [anon:dalvik-thread local mark stack]
-70eba34000-70eba38000 rw-p 00000000 00:05 10270792 [anon:dalvik-thread local mark stack]
-70eba38000-70eba3c000 rw-p 00000000 00:05 10270791 [anon:dalvik-thread local mark stack]
-70eba3c000-70eba40000 rw-p 00000000 00:05 10270790 [anon:dalvik-thread local mark stack]
-70eba40000-70eba44000 rw-p 00000000 00:05 10270789 [anon:dalvik-thread local mark stack]
-70eba44000-70eba48000 rw-p 00000000 00:05 10270788 [anon:dalvik-thread local mark stack]
-70eba48000-70eba4c000 rw-p 00000000 00:05 10270787 [anon:dalvik-thread local mark stack]
-70eba4c000-70eba50000 rw-p 00000000 00:05 10270786 [anon:dalvik-thread local mark stack]
-70eba50000-70eba52000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70eba52000-70eba53000 r--s 00000000 fc:00 971 /system/framework/android.hidl.base-V1.0-java.jar
-70eba53000-70eba57000 rw-p 00000000 00:05 10270785 [anon:dalvik-thread local mark stack]
-70eba57000-70eba5b000 rw-p 00000000 00:05 10270784 [anon:dalvik-thread local mark stack]
-70eba5b000-70eba5f000 rw-p 00000000 00:05 10270783 [anon:dalvik-thread local mark stack]
-70eba5f000-70eba63000 rw-p 00000000 00:05 10270782 [anon:dalvik-thread local mark stack]
-70eba63000-70eba64000 rw-p 00000000 00:00 0 [anon:linker_alloc]
-70eba64000-70eba65000 r--s 00000000 fc:00 889 /system/framework/ims-common.jar
-70eba65000-70eba69000 rw-p 00000000 00:05 10270781 [anon:dalvik-thread local mark stack]
-70eba69000-70eba6d000 rw-p 00000000 00:05 10270780 [anon:dalvik-thread local mark stack]
-70eba6d000-70eba71000 rw-p 00000000 00:05 10270779 [anon:dalvik-thread local mark stack]
-70eba71000-70eba75000 rw-p 00000000 00:05 10270778 [anon:dalvik-thread local mark stack]
-70eba75000-70eba95000 rw-p 00000000 00:05 10267647 [anon:dalvik-large marked objects]
-70eba95000-70ebab5000 rw-p 00000000 00:05 10267646 [anon:dalvik-large live objects]
-70ebab5000-70ebab6000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70ebab6000-70ebab7000 rw-p 00000000 00:00 0 [anon:linker_alloc]
-70ebab7000-70ebabb000 rw-p 00000000 00:05 10270777 [anon:dalvik-thread local mark stack]
-70ebabb000-70ebadb000 r--s 00000000 00:10 16603 /dev/__properties__/u:object_r:exported_fingerprint_prop:s0
-70ebadb000-70ebadc000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70ebadc000-70ebadd000 r--s 00000000 fc:00 878 /system/framework/voip-common.jar
-70ebadd000-70ebadf000 rw-p 00000000 00:05 10270995 [anon:dalvik-indirect ref table]
-70ebadf000-70ebae3000 rw-p 00000000 00:05 10270776 [anon:dalvik-thread local mark stack]
-70ebae3000-70ebae7000 rw-p 00000000 00:05 10270775 [anon:dalvik-thread local mark stack]
-70ebae7000-70ebaeb000 rw-p 00000000 00:05 10270774 [anon:dalvik-thread local mark stack]
-70ebaeb000-70ebaef000 rw-p 00000000 00:05 10270773 [anon:dalvik-thread local mark stack]
-70ebaef000-70ebb0f000 r--s 00000000 00:10 16582 /dev/__properties__/u:object_r:debug_prop:s0
-70ebb0f000-70ebb10000 rw-p 00000000 00:00 0 [anon:linker_alloc]
-70ebb10000-70ebb11000 r--s 00000000 fc:00 703 /system/framework/telephony-common.jar
-70ebb11000-70ebb13000 rw-p 00000000 00:05 10270994 [anon:dalvik-indirect ref table]
-70ebb13000-70ebb17000 rw-p 00000000 00:05 10270772 [anon:dalvik-thread local mark stack]
-70ebb17000-70ebb19000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70ebb19000-70ebb1d000 rw-p 00000000 00:05 10270771 [anon:dalvik-thread local mark stack]
-70ebb1d000-70ebb3d000 r--s 00000000 00:10 16600 /dev/__properties__/u:object_r:exported_default_prop:s0
-70ebb3d000-70ebb5d000 r--s 00000000 00:10 16650 /dev/__properties__/u:object_r:system_prop:s0
-70ebb5d000-70ebb7d000 r--s 00000000 00:10 16610 /dev/__properties__/u:object_r:exported_vold_prop:s0
-70ebb7d000-70ebb9d000 r--s 00000000 00:10 16598 /dev/__properties__/u:object_r:exported_config_prop:s0
-70ebb9d000-70ebb9e000 rw-p 00000000 00:00 0 [anon:linker_alloc]
-70ebb9e000-70ebba2000 rw-p 00000000 00:05 10270770 [anon:dalvik-thread local mark stack]
-70ebba2000-70ebba6000 rw-p 00000000 00:05 10270769 [anon:dalvik-thread local mark stack]
-70ebba6000-70ebba7000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70ebba7000-70ebba8000 r--s 00000000 fc:00 1004 /system/framework/framework.jar
-70ebba8000-70ebbac000 rw-p 00000000 00:05 10270768 [anon:dalvik-thread local mark stack]
-70ebbac000-70ebbb0000 rw-p 00000000 00:05 10270767 [anon:dalvik-thread local mark stack]
-70ebbb0000-70ebbb4000 rw-p 00000000 00:05 10270766 [anon:dalvik-thread local mark stack]
-70ebbb4000-70ebbb8000 rw-p 00000000 00:05 10270765 [anon:dalvik-thread local mark stack]
-70ebbb8000-70ebbbc000 rw-p 00000000 00:05 10270764 [anon:dalvik-thread local mark stack]
-70ebbbc000-70ebbc0000 rw-p 00000000 00:05 10270763 [anon:dalvik-thread local mark stack]
-70ebbc0000-70ebbc4000 rw-p 00000000 00:05 10270762 [anon:dalvik-thread local mark stack]
-70ebbc4000-70ebbe4000 r--s 00000000 00:10 16581 /dev/__properties__/u:object_r:dalvik_prop:s0
-70ebbe4000-70ebbe5000 rw-p 00000000 00:00 0 [anon:linker_alloc]
-70ebbe5000-70ebbe6000 r--s 00004000 fc:00 877 /system/framework/apache-xml.jar
-70ebbe6000-70ebbe8000 rw-p 00000000 00:05 10270993 [anon:dalvik-indirect ref table]
-70ebbe8000-70ebbec000 rw-p 00000000 00:05 10270761 [anon:dalvik-thread local mark stack]
-70ebbec000-70ebbf0000 rw-p 00000000 00:05 10270760 [anon:dalvik-thread local mark stack]
-70ebbf0000-70ebbf4000 rw-p 00000000 00:05 10270759 [anon:dalvik-thread local mark stack]
-70ebbf4000-70ebbf8000 rw-p 00000000 00:05 10270758 [anon:dalvik-thread local mark stack]
-70ebbf8000-70ebbf9000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70ebbf9000-70ebbfa000 r--s 00000000 fc:00 968 /system/framework/bouncycastle.jar
-70ebbfa000-70ebbfc000 rw-p 00000000 00:05 10270992 [anon:dalvik-indirect ref table]
-70ebbfc000-70ebc00000 rw-p 00000000 00:05 10270757 [anon:dalvik-thread local mark stack]
-70ebc00000-70ebc04000 rw-p 00000000 00:05 10270756 [anon:dalvik-thread local mark stack]
-70ebc04000-70ebc08000 rw-p 00000000 00:05 10270755 [anon:dalvik-thread local mark stack]
-70ebc08000-70ebc0c000 rw-p 00000000 00:05 10270754 [anon:dalvik-thread local mark stack]
-70ebc0c000-70ebc10000 rw-p 00000000 00:05 10270753 [anon:dalvik-thread local mark stack]
-70ebc10000-70ebc14000 rw-p 00000000 00:05 10270752 [anon:dalvik-thread local mark stack]
-70ebc14000-70ebc15000 rw-p 00000000 00:00 0 [anon:linker_alloc]
-70ebc15000-70ebc16000 r--s 00000000 fc:00 960 /system/framework/okhttp.jar
-70ebc16000-70ebc1a000 rw-p 00000000 00:05 10270751 [anon:dalvik-thread local mark stack]
-70ebc1a000-70ebc1e000 rw-p 00000000 00:05 10270750 [anon:dalvik-thread local mark stack]
-70ebc1e000-70ebc3e000 r--s 00000000 00:10 16584 /dev/__properties__/u:object_r:default_prop:s0
-70ebc3e000-70ebc3f000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70ebc3f000-70ebc40000 r--s 00000000 fc:00 974 /system/framework/conscrypt.jar
-70ebc40000-70ebc42000 rw-p 00000000 00:05 10269719 [anon:dalvik-indirect ref table]
-70ebc42000-70ebc46000 rw-p 00000000 00:05 10270749 [anon:dalvik-thread local mark stack]
-70ebc46000-70ebc4a000 rw-p 00000000 00:05 10270748 [anon:dalvik-thread local mark stack]
-70ebc4a000-70ebc4e000 rw-p 00000000 00:05 10270747 [anon:dalvik-thread local mark stack]
-70ebc4e000-70ebc4f000 rw-p 00000000 00:00 0 [anon:linker_alloc]
-70ebc4f000-70ebc51000 rw-p 00000000 00:05 10269718 [anon:dalvik-indirect ref table]
-70ebc51000-70ebc55000 rw-p 00000000 00:05 10270746 [anon:dalvik-thread local mark stack]
-70ebc55000-70ebc59000 rw-p 00000000 00:05 10270745 [anon:dalvik-thread local mark stack]
-70ebc59000-70ebc5d000 rw-p 00000000 00:05 10270744 [anon:dalvik-thread local mark stack]
-70ebc5d000-70ebc7d000 r--s 00000000 00:10 16599 /dev/__properties__/u:object_r:exported_dalvik_prop:s0
-70ebc7d000-70ebc7e000 rw-p 00000000 00:00 0 [anon:linker_alloc]
-70ebc7e000-70ebc7f000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70ebc7f000-70ebc80000 r--s 00004000 fc:00 963 /system/framework/core-libart.jar
-70ebc80000-70ebc81000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70ebc81000-70ebc85000 rw-p 00000000 00:05 10270743 [anon:dalvik-thread local mark stack]
-70ebc85000-70ebc89000 rw-p 00000000 00:05 10270742 [anon:dalvik-thread local mark stack]
-70ebc89000-70ebc8a000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects]
-70ebc8a000-70ebc8c000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70ebc8c000-70ebc8d000 r--s 0001e000 fc:00 699 /system/framework/core-oj.jar
-70ebc8d000-70ebc91000 rw-p 00000000 00:05 10270741 [anon:dalvik-thread local mark stack]
-70ebc91000-70ebc95000 rw-p 00000000 00:05 10270740 [anon:dalvik-thread local mark stack]
-70ebc95000-70ebc99000 rw-p 00000000 00:05 10270739 [anon:dalvik-thread local mark stack]
-70ebc99000-70ebc9b000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70ebc9b000-70ebc9c000 rw-p 00000000 00:00 0 [anon:linker_alloc]
-70ebc9c000-70ebca0000 rw-p 00000000 00:05 10270738 [anon:dalvik-thread local mark stack]
-70ebca0000-70ebca4000 rw-p 00000000 00:05 10270737 [anon:dalvik-thread local mark stack]
-70ebca4000-70ebca8000 rw-p 00000000 00:05 10270736 [anon:dalvik-thread local mark stack]
-70ebca8000-70ebcac000 rw-p 00000000 00:05 10270735 [anon:dalvik-thread local mark stack]
-70ebcac000-70ebcb0000 rw-p 00000000 00:05 10270734 [anon:dalvik-thread local mark stack]
-70ebcb0000-70ebcd0000 r--s 00000000 00:10 16592 /dev/__properties__/u:object_r:exported2_system_prop:s0
-70ebcd0000-70ebcd1000 rw-p 00000000 00:00 0 [anon:linker_alloc]
-70ebcd1000-70ebcd5000 rw-p 00000000 00:05 10270733 [anon:dalvik-thread local mark stack]
-70ebcd5000-70ebcd9000 rw-p 00000000 00:05 10270732 [anon:dalvik-thread local mark stack]
-70ebcd9000-70ebcdd000 rw-p 00000000 00:05 10270731 [anon:dalvik-thread local mark stack]
-70ebcdd000-70ebce1000 rw-p 00000000 00:05 10270730 [anon:dalvik-thread local mark stack]
-70ebce1000-70ebce5000 rw-p 00000000 00:05 10270729 [anon:dalvik-thread local mark stack]
-70ebce5000-70ebce9000 rw-p 00000000 00:05 10270728 [anon:dalvik-thread local mark stack]
-70ebce9000-70ebcea000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70ebcea000-70ebcec000 rw-p 00000000 00:05 10270987 [anon:dalvik-indirect ref table]
-70ebcec000-70ebcf9000 r--p 00646000 103:1d 639532 /data/dalvik-cache/arm64/system@framework@boot-framework.art
-70ebcf9000-70ebd19000 r--s 00000000 00:10 16620 /dev/__properties__/u:object_r:log_tag_prop:s0
-70ebd19000-70ebd39000 r--s 00000000 00:10 16621 /dev/__properties__/u:object_r:logd_prop:s0
-70ebd39000-70ebd3a000 rw-p 00000000 00:00 0 [anon:linker_alloc]
-70ebd3a000-70ebd3b000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70ebd3b000-70ebd3f000 rw-p 00000000 00:05 10270727 [anon:dalvik-thread local mark stack]
-70ebd3f000-70ebd40000 r--p 00002000 103:1d 639556 /data/dalvik-cache/arm64/system@framework@boot-com.google.vr.platform.art
-70ebd40000-70ebd41000 r--p 00005000 103:1d 639553 /data/dalvik-cache/arm64/system@framework@boot-android.test.base.art
-70ebd41000-70ebd42000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70ebd42000-70ebd43000 r--p 00001000 103:1d 639550 /data/dalvik-cache/arm64/system@framework@boot-framework-oahl-backward-compatibility.art
-70ebd43000-70ebd44000 r--p 00005000 103:1d 639547 /data/dalvik-cache/arm64/system@framework@boot-android.hidl.manager-V1.0-java.art
-70ebd44000-70ebd45000 r--p 00003000 103:1d 639544 /data/dalvik-cache/arm64/system@framework@boot-android.hidl.base-V1.0-java.art
-70ebd45000-70ebd46000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70ebd46000-70ebd47000 r--p 0000f000 103:1d 639541 /data/dalvik-cache/arm64/system@framework@boot-ims-common.art
-70ebd47000-70ebd48000 r--p 0000d000 103:1d 639538 /data/dalvik-cache/arm64/system@framework@boot-voip-common.art
-70ebd48000-70ebd4a000 r--p 0005e000 103:1d 639535 /data/dalvik-cache/arm64/system@framework@boot-telephony-common.art
-70ebd4a000-70ebd4b000 r--p 00040000 103:1d 639529 /data/dalvik-cache/arm64/system@framework@boot-ext.art
-70ebd4b000-70ebd4c000 r--p 0004a000 103:1d 639526 /data/dalvik-cache/arm64/system@framework@boot-apache-xml.art
-70ebd4c000-70ebd4d000 r--p 00046000 103:1d 639523 /data/dalvik-cache/arm64/system@framework@boot-bouncycastle.art
-70ebd4d000-70ebd4e000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70ebd4e000-70ebd53000 r--p 00225000 103:1d 639511 /data/dalvik-cache/arm64/system@framework@boot.art
-70ebd53000-70ebd5a000 rw-p 00000000 fc:00 583 /system/etc/event-log-tags
-70ebd5a000-70ebd5b000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70ebd5b000-70ebd5c000 r--p 0002e000 103:1d 639520 /data/dalvik-cache/arm64/system@framework@boot-okhttp.art
-70ebd5c000-70ebd5d000 r--p 00035000 103:1d 639517 /data/dalvik-cache/arm64/system@framework@boot-conscrypt.art
-70ebd5d000-70ebd5f000 r--p 000d0000 103:1d 639514 /data/dalvik-cache/arm64/system@framework@boot-core-libart.art
-70ebd5f000-70ebd62000 r--p 00000000 00:00 0 [anon:atexit handlers]
-70ebd62000-70ebd63000 rw-p 00000000 00:00 0
-70ebd63000-70ebd83000 r--s 00000000 00:10 16590 /dev/__properties__/u:object_r:exported2_default_prop:s0
-70ebd83000-70ebd84000 rw-p 00000000 00:00 0 [anon:linker_alloc]
-70ebd84000-70ebd89000 rw-p 00000000 00:00 0
-70ebd89000-70ebda9000 r--s 00000000 00:10 16669 /dev/__properties__/properties_serial
-70ebda9000-70ebdb3000 r--s 00000000 00:10 16560 /dev/__properties__/property_info
-70ebdb3000-70ebdb4000 rw-p 00000000 00:00 0 [anon:linker_alloc_vector]
-70ebdb4000-70ebdb5000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects]
-70ebdb5000-70ebdb7000 rw-p 00000000 00:00 0 [anon:System property context nodes]
-70ebdb7000-70ebdb8000 rw-p 00000000 00:00 0 [anon:linker_alloc_vector]
-70ebdb8000-70ebdba000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects]
-70ebdba000-70ebdbb000 rw-p 00000000 00:00 0 [anon:linker_alloc]
-70ebdbb000-70ebdbd000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects]
-70ebdbd000-70ebdbe000 r--p 00000000 00:00 0 [anon:atexit handlers]
-70ebdbe000-70ebdbf000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70ebdbf000-70ebdc0000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects]
-70ebdc0000-70ebdc1000 rw-p 00000000 00:00 0 [anon:linker_alloc_vector]
-70ebdc1000-70ebdc2000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects]
-70ebdc2000-70ebdc3000 rw-p 00000000 00:00 0 [anon:linker_alloc_vector]
-70ebdc3000-70ebdc5000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects]
-70ebdc5000-70ebde5000 r--s 00000000 00:10 16600 /dev/__properties__/u:object_r:exported_default_prop:s0
-70ebde5000-70ebde6000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects]
-70ebde6000-70ebde8000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70ebde8000-70ebe08000 r--s 00000000 00:10 16582 /dev/__properties__/u:object_r:debug_prop:s0
-70ebe08000-70ebe09000 ---p 00000000 00:00 0
-70ebe09000-70ebe0a000 rw-p 00000000 00:00 0
-70ebe0a000-70ebe0b000 ---p 00000000 00:00 0
-70ebe0b000-70ebe2b000 r--s 00000000 00:10 16669 /dev/__properties__/properties_serial
-70ebe2b000-70ebe2d000 rw-p 00000000 00:00 0 [anon:System property context nodes]
-70ebe2d000-70ebf55000 r-xp 00000000 fc:00 3184 /system/bin/linker64
-70ebf55000-70ebf5f000 r--s 00000000 00:10 16560 /dev/__properties__/property_info
-70ebf5f000-70ebf60000 r--p 00000000 00:00 0 [anon:linker_alloc]
-70ebf60000-70ebf61000 rw-p 00000000 00:00 0 [anon:linker_alloc_vector]
-70ebf61000-70ebf62000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects]
-70ebf62000-70ebf63000 rw-p 00000000 00:00 0 [anon:arc4random data]
-70ebf63000-70ebf64000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects]
-70ebf64000-70ebf65000 r--p 00000000 00:00 0 [anon:atexit handlers]
-70ebf65000-70ebf66000 ---p 00000000 00:00 0 [anon:thread signal stack guard]
-70ebf66000-70ebf6a000 rw-p 00000000 00:00 0 [anon:thread signal stack]
-70ebf6a000-70ebf6b000 rw-p 00000000 00:00 0 [anon:arc4random data]
-70ebf6b000-70ebf6c000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70ebf6c000-70ebf6f000 rw-p 00000000 00:00 0 [anon:bionic TLS]
-70ebf6f000-70ebf70000 ---p 00000000 00:00 0 [anon:bionic TLS guard]
-70ebf70000-70ebf71000 r--p 00000000 00:00 0 [vvar]
-70ebf71000-70ebf72000 r-xp 00000000 00:00 0 [vdso]
-70ebf72000-70ebf7d000 r--p 00135000 fc:00 3184 /system/bin/linker64
-70ebf7d000-70ebf7e000 rw-p 00140000 fc:00 3184 /system/bin/linker64
-70ebf7e000-70ebf81000 rw-p 00000000 00:00 0
-70ebf81000-70ebf82000 r--p 00000000 00:00 0
-70ebf82000-70ebf89000 rw-p 00000000 00:00 0
-7fc7df1000-7fc7df2000 ---p 00000000 00:00 0
-7fc7df2000-7fc85f1000 rw-p 00000000 00:00 0 [stack]
diff --git a/libunwindstack b/libunwindstack
new file mode 120000
index 0000000..9a12403
--- /dev/null
+++ b/libunwindstack
@@ -0,0 +1 @@
+../unwinding/libunwindstack
\ No newline at end of file
diff --git a/libunwindstack/.clang-format b/libunwindstack/.clang-format
deleted file mode 120000
index fd0645f..0000000
--- a/libunwindstack/.clang-format
+++ /dev/null
@@ -1 +0,0 @@
-../.clang-format-2
\ No newline at end of file
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
deleted file mode 100644
index 7770b13..0000000
--- a/libunwindstack/Android.bp
+++ /dev/null
@@ -1,494 +0,0 @@
-//
-// Copyright (C) 2017 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.
-//
-
-cc_defaults {
- name: "libunwindstack_flags",
-
- host_supported: true,
-
- cflags: [
- "-Wall",
- "-Werror",
- "-Wextra",
- ],
-
- target: {
- darwin: {
- enabled: false,
- },
- linux_bionic: {
- enabled: true,
- },
- },
-}
-
-cc_defaults {
- name: "libunwindstack_defaults",
- defaults: ["libunwindstack_flags"],
- export_include_dirs: ["include"],
-
- srcs: [
- "ArmExidx.cpp",
- "DexFiles.cpp",
- "DwarfCfa.cpp",
- "DwarfEhFrameWithHdr.cpp",
- "DwarfMemory.cpp",
- "DwarfOp.cpp",
- "DwarfSection.cpp",
- "Elf.cpp",
- "ElfInterface.cpp",
- "ElfInterfaceArm.cpp",
- "Global.cpp",
- "JitDebug.cpp",
- "Log.cpp",
- "MapInfo.cpp",
- "Maps.cpp",
- "Memory.cpp",
- "MemoryMte.cpp",
- "LocalUnwinder.cpp",
- "Regs.cpp",
- "RegsArm.cpp",
- "RegsArm64.cpp",
- "RegsX86.cpp",
- "RegsX86_64.cpp",
- "RegsMips.cpp",
- "RegsMips64.cpp",
- "Unwinder.cpp",
- "Symbols.cpp",
- ],
-
- cflags: [
- "-Wexit-time-destructors",
- ],
-
- target: {
- host: {
- // Always disable optimizations for host to make it easier to debug.
- cflags: [
- "-O0",
- "-g",
- ],
- },
- android: {
- header_libs: ["bionic_libc_platform_headers"],
- product_variables: {
- experimental_mte: {
- cflags: ["-DANDROID_EXPERIMENTAL_MTE"],
- },
- },
- },
- linux_bionic: {
- header_libs: ["bionic_libc_platform_headers"],
- product_variables: {
- experimental_mte: {
- cflags: ["-DANDROID_EXPERIMENTAL_MTE"],
- },
- },
- },
- },
-
- arch: {
- x86: {
- srcs: ["AsmGetRegsX86.S"],
- },
- x86_64: {
- srcs: ["AsmGetRegsX86_64.S"],
- },
- },
-
- static_libs: [
- "libprocinfo",
- ],
-
- shared_libs: [
- "libbase",
- "liblog",
- "liblzma",
- ],
-}
-
-cc_library {
- name: "libunwindstack",
- vendor_available: true,
- recovery_available: true,
- // TODO(b/153609531): remove when no longer needed.
- native_bridge_supported: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- defaults: ["libunwindstack_defaults"],
- srcs: ["DexFile.cpp"],
- cflags: ["-DDEXFILE_SUPPORT"],
- shared_libs: ["libdexfile_support"],
-
- target: {
- vendor: {
- cflags: ["-UDEXFILE_SUPPORT"],
- exclude_srcs: ["DexFile.cpp"],
- exclude_shared_libs: ["libdexfile_support"],
- },
- recovery: {
- cflags: ["-UDEXFILE_SUPPORT"],
- exclude_srcs: ["DexFile.cpp"],
- exclude_shared_libs: ["libdexfile_support"],
- },
- native_bridge: {
- cflags: ["-UDEXFILE_SUPPORT"],
- exclude_srcs: ["DexFile.cpp"],
- exclude_shared_libs: ["libdexfile_support"],
- },
- },
-
- apex_available: [
- "//apex_available:platform",
- "com.android.art.debug",
- "com.android.art.release",
- ],
-}
-
-// Static library without DEX support to avoid dependencies on the ART APEX.
-cc_library_static {
- name: "libunwindstack_no_dex",
- recovery_available: true,
- defaults: ["libunwindstack_defaults"],
-
- visibility: [
- "//external/gwp_asan",
- "//system/core/debuggerd",
- "//system/core/init",
- "//system/core/libbacktrace",
- ],
- apex_available: [
- "//apex_available:platform",
- "com.android.runtime",
- ],
-}
-
-//-------------------------------------------------------------------------
-// Unit Tests
-//-------------------------------------------------------------------------
-cc_test_library {
- name: "libunwindstack_local",
- defaults: ["libunwindstack_flags"],
- srcs: ["tests/TestLocal.cpp"],
-
- cflags: [
- "-O0",
- "-g",
- ],
-
- shared_libs: [
- "libunwindstack",
- ],
- relative_install_path: "libunwindstack_test",
-}
-
-cc_defaults {
- name: "libunwindstack_testlib_flags",
- defaults: ["libunwindstack_flags"],
-
- srcs: [
- "tests/ArmExidxDecodeTest.cpp",
- "tests/ArmExidxExtractTest.cpp",
- "tests/DexFileTest.cpp",
- "tests/DexFilesTest.cpp",
- "tests/DwarfCfaLogTest.cpp",
- "tests/DwarfCfaTest.cpp",
- "tests/DwarfDebugFrameTest.cpp",
- "tests/DwarfEhFrameTest.cpp",
- "tests/DwarfEhFrameWithHdrTest.cpp",
- "tests/DwarfMemoryTest.cpp",
- "tests/DwarfOpLogTest.cpp",
- "tests/DwarfOpTest.cpp",
- "tests/DwarfSectionTest.cpp",
- "tests/DwarfSectionImplTest.cpp",
- "tests/ElfCacheTest.cpp",
- "tests/ElfFake.cpp",
- "tests/ElfInterfaceArmTest.cpp",
- "tests/ElfInterfaceTest.cpp",
- "tests/ElfTest.cpp",
- "tests/ElfTestUtils.cpp",
- "tests/IsolatedSettings.cpp",
- "tests/JitDebugTest.cpp",
- "tests/LocalUpdatableMapsTest.cpp",
- "tests/LogFake.cpp",
- "tests/MapInfoCreateMemoryTest.cpp",
- "tests/MapInfoGetBuildIDTest.cpp",
- "tests/MapInfoGetElfTest.cpp",
- "tests/MapInfoGetLoadBiasTest.cpp",
- "tests/MapInfoTest.cpp",
- "tests/MapsTest.cpp",
- "tests/MemoryBufferTest.cpp",
- "tests/MemoryCacheTest.cpp",
- "tests/MemoryFake.cpp",
- "tests/MemoryFileTest.cpp",
- "tests/MemoryLocalTest.cpp",
- "tests/MemoryOfflineBufferTest.cpp",
- "tests/MemoryOfflineTest.cpp",
- "tests/MemoryRangeTest.cpp",
- "tests/MemoryRangesTest.cpp",
- "tests/MemoryRemoteTest.cpp",
- "tests/MemoryTest.cpp",
- "tests/MemoryMteTest.cpp",
- "tests/RegsInfoTest.cpp",
- "tests/RegsIterateTest.cpp",
- "tests/RegsStepIfSignalHandlerTest.cpp",
- "tests/RegsTest.cpp",
- "tests/SymbolsTest.cpp",
- "tests/TestUtils.cpp",
- "tests/UnwindOfflineTest.cpp",
- "tests/UnwindTest.cpp",
- "tests/UnwinderTest.cpp",
- "tests/VerifyBionicTerminationTest.cpp",
- ],
-
- cflags: [
- "-O0",
- "-g",
- ],
-
- shared_libs: [
- "libbase",
- "liblog",
- "liblzma",
- "libunwindstack",
- "libdexfile_support",
- ],
-
- static_libs: [
- "libgmock",
- ],
-
- test_suites: ["device-tests"],
- data: [
- "tests/files/elf32.xz",
- "tests/files/elf64.xz",
- "tests/files/offline/art_quick_osr_stub_arm/*",
- "tests/files/offline/bad_eh_frame_hdr_arm64/*",
- "tests/files/offline/debug_frame_first_x86/*",
- "tests/files/offline/debug_frame_load_bias_arm/*",
- "tests/files/offline/eh_frame_bias_x86/*",
- "tests/files/offline/eh_frame_hdr_begin_x86_64/*",
- "tests/files/offline/empty_arm64/*",
- "tests/files/offline/invalid_elf_offset_arm/*",
- "tests/files/offline/jit_debug_arm/*",
- "tests/files/offline/jit_debug_x86/*",
- "tests/files/offline/jit_map_arm/*",
- "tests/files/offline/gnu_debugdata_arm/*",
- "tests/files/offline/load_bias_different_section_bias_arm64/*",
- "tests/files/offline/load_bias_ro_rx_x86_64/*",
- "tests/files/offline/offset_arm/*",
- "tests/files/offline/shared_lib_in_apk_arm64/*",
- "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/*",
- ],
-
- target: {
- android: {
- header_libs: ["bionic_libc_platform_headers"],
- product_variables: {
- experimental_mte: {
- cflags: ["-DANDROID_EXPERIMENTAL_MTE"],
- },
- },
- },
- linux_bionic: {
- header_libs: ["bionic_libc_platform_headers"],
- product_variables: {
- experimental_mte: {
- cflags: ["-DANDROID_EXPERIMENTAL_MTE"],
- },
- },
- },
- },
-}
-
-cc_test {
- name: "libunwindstack_test",
- defaults: ["libunwindstack_testlib_flags"],
- isolated: true,
-
- srcs: [
- "tests/LocalUnwinderTest.cpp",
- ],
- required: [
- "libunwindstack_local",
- ],
-}
-
-// Skip LocalUnwinderTest until atest understands required properly.
-cc_test {
- name: "libunwindstack_unit_test",
- defaults: ["libunwindstack_testlib_flags"],
- isolated: true,
-}
-
-//-------------------------------------------------------------------------
-// Fuzzers
-//-------------------------------------------------------------------------
-cc_defaults {
- name: "libunwindstack_fuzz_defaults",
- host_supported: true,
- defaults: ["libunwindstack_flags"],
- cflags: [
- "-Wno-exit-time-destructors",
- "-g",
- ],
- shared_libs: [
- "libbase",
- "liblog",
- "liblzma",
- "libunwindstack",
- "libdexfile_support",
- ],
-}
-
-cc_fuzz {
- name: "libunwindstack_fuzz_unwinder",
- defaults: ["libunwindstack_fuzz_defaults"],
- srcs: [
- "tests/MemoryFake.cpp",
- "tests/ElfFake.cpp",
- "tests/fuzz/UnwinderComponentCreator.cpp",
- "tests/fuzz/UnwinderFuzz.cpp",
- ],
-}
-
-//-------------------------------------------------------------------------
-// Tools
-//-------------------------------------------------------------------------
-cc_defaults {
- name: "libunwindstack_tools",
- defaults: ["libunwindstack_flags"],
-
- shared_libs: [
- "libunwindstack",
- "libbase",
- "liblzma",
- ],
- target: {
- // Always disable optimizations for host to make it easier to debug.
- host: {
- cflags: [
- "-O0",
- "-g",
- ],
- },
- },
-}
-
-cc_binary {
- name: "unwind",
- defaults: ["libunwindstack_tools"],
-
- srcs: [
- "tools/unwind.cpp",
- ],
-}
-
-cc_binary {
- name: "unwind_info",
- defaults: ["libunwindstack_tools"],
-
- srcs: [
- "tools/unwind_info.cpp",
- ],
-}
-
-cc_binary {
- name: "unwind_symbols",
- defaults: ["libunwindstack_tools"],
-
- srcs: [
- "tools/unwind_symbols.cpp",
- ],
-}
-
-cc_binary {
- name: "unwind_for_offline",
- defaults: ["libunwindstack_tools"],
-
- srcs: [
- "tools/unwind_for_offline.cpp",
- ],
-}
-
-cc_binary {
- name: "unwind_reg_info",
- defaults: ["libunwindstack_tools"],
-
- srcs: [
- "tools/unwind_reg_info.cpp",
- ],
-}
-
-//-------------------------------------------------------------------------
-// Benchmarks
-//-------------------------------------------------------------------------
-cc_benchmark {
- name: "unwind_benchmarks",
- host_supported: true,
- defaults: ["libunwindstack_flags"],
-
- // Disable optimizations so that all of the calls are not optimized away.
- cflags: [
- "-O0",
- ],
-
- srcs: [
- "benchmarks/unwind_benchmarks.cpp",
- "benchmarks/ElfBenchmark.cpp",
- "benchmarks/MapsBenchmark.cpp",
- "benchmarks/SymbolBenchmark.cpp",
- "benchmarks/Utils.cpp",
- ],
-
- data: [
- "benchmarks/files/*",
- ],
-
- shared_libs: [
- "libbase",
- "libunwindstack",
- ],
-
- target: {
- android: {
- static_libs: [
- "libmeminfo",
- "libprocinfo",
- ],
- },
- },
-}
-
-// Generates the elf data for use in the tests for .gnu_debugdata frames.
-// Once these files are generated, use the xz command to compress the data.
-cc_binary_host {
- name: "gen_gnudebugdata",
- defaults: ["libunwindstack_flags"],
-
- srcs: [
- "tests/GenGnuDebugdata.cpp",
- ],
-}
-
diff --git a/libunwindstack/AndroidVersions.md b/libunwindstack/AndroidVersions.md
deleted file mode 100644
index 234f639..0000000
--- a/libunwindstack/AndroidVersions.md
+++ /dev/null
@@ -1,116 +0,0 @@
-# Unwinder Support Per Android Release
-This document describes the changes in the way the libunwindstack
-unwinder works on different Android versions. It does not describe
-every change in the code made between different versions, but is
-meant to allow an app developer to know what might be supported
-on different versions. It also describes the different way an unwind
-will display on different versions of Android.
-
-## Android P
-libunwindstack was first introduced in Android P.
-
-* Supports up to and including Dwarf 4 unwinding information.
- See http://dwarfstd.org/ for Dwarf standards.
-* Supports Arm exidx unwinding.
-* Supports the gdb JIT unwinding interface, which is how ART creates unwinding
- information for the JIT'd Java frames.
-* Supports special frames added to represent an ART Java interpreter frame.
- ART has marked the dex pc using cfi information that the unwinder
- understands and handles by adding a new frame in the stacktrace.
-
-## Note
-By default, lld creates two separate maps of the elf in memory, one read-only
-and one read/executable. The libunwindstack on P and the unwinder on older
-versions of Android will not unwind properly in this case. For apps that
-target Android P or older, make sure that `-Wl,--no-rosegment` is
-included in linker arguments when using lld.
-
-## Android Q
-* Fix bug (b/109824792) that handled load bias data incorrectly when
- FDEs use pc relative addressing in the eh\_frame\_hdr.
- Unfortunately, this wasn't fixed correctly in Q since it assumes
- that the bias is coming from the program header for the executable
- load. The real fix was to use the bias from the actual section data and
- is not completely fixed until Android R. For apps targeting Android Q,
- if it is being compiled with the llvm linker lld, it might be necessary
- to add the linker option `-Wl,-zseparate-code` to avoid creating an elf
- created this way.
-* Change the way the exidx section offset is found (b/110704153). Before
- the p\_vaddr value from the program header minus the load bias was used
- to find the start of the exidx data. Changed to use the p\_offset since
- it doesn't require any load bias manipulations.
-* Fix bug handling of dwarf sections without any header (b/110235461).
- Previously, the code assumed that FDEs are non-overlapping, and the FDEs
- are always in sorted order from low pc to high pc. Thus the code would
- read the entire set of CIEs/FDEs and then do a binary search to find
- the appropriate FDE for a given pc. Now the code does a sequential read
- and stops when it finds the FDE for a pc. It also understands the
- overlapping FDEs, so find the first FDE that matches a pc. In practice,
- elf files with this format only ever occurs if the file was generated
- without an eh\_frame/eh\_frame\_hdr section and only a debug\_frame. The
- other way this has been observed is when running simpleperf to unwind since
- sometimes there is not enough information in the eh\_frame for all points
- in the executable. On Android P, this would result in some incorrect
- unwinds coming from simpleperf. Nearly all crashes from Android P should
- be correct since the eh\_frame information was enough to do the unwind
- properly.
-* Be permissive of badly formed elf files. Previously, any detected error
- would result in unwinds stopping even if there is enough valid information
- to do an unwind.
- * The code now allows program header/section header offsets to point
- to unreadable memory. As long as the code can find the unwind tables,
- that is good enough.
- * The code allows program headers/section headers to be missing.
- * Allow a symbol table section header to point to invalid symbol table
- values.
-* Support for the linker read-only segment option (b/109657296).
- This is a feature of lld whereby there are two sections that
- contain elf data. The first is read-only and contains the elf header data,
- and the second is read-execute or execute only that
- contains the executable code from the elf. Before this, the unwinder
- always assumed that there was only a single read-execute section that
- contained the elf header data and the executable code.
-* Build ID information for elf objects added. This will display the
- NT\_GNU\_BUILD\_ID note found in elf files. This information can be used
- to identify the exact version of a shared library to help get symbol
- information when looking at a crash.
-* Add support for displaying the soname from an apk frame. Previously,
- a frame map name would be only the apk, but now if the shared library
- in the apk has set a soname, the map name will be `app.apk!libexample.so`
- instead of only `app.apk`.
-* Minimal support for Dwarf 5. This merely treats a Dwarf 5 version
- elf file as Dwarf 4. It does not support the new dwarf ops in Dwarf 5.
- Since the new ops are not likely to be used very often, this allows
- continuing to unwind even when encountering Dwarf 5 elf files.
-* Fix bug in pc handling of signal frames (b/130302288). In the previous
- version, the pc would be wrong in the signal frame. The rest of the
- unwind was correct, only the frame in the signal handler was incorrect
- in Android P.
-* Detect when an elf file is not readable so that a message can be
- displayed indicating that. This can happen when an app puts the shared
- libraries in non-standard locations that are not readable due to
- security restrictions (selinux rules).
-
-## Android R
-* Display the offsets for Java interpreter frames. If this frame came
- from a non-zero offset map, no offset is printed. Previously, the
- line would look like:
-
- #17 pc 00500d7a GoogleCamera.apk (com.google.camera.AndroidPriorityThread.run+10)
-
- to:
-
- #17 pc 00500d7a GoogleCamera.apk (offset 0x11d0000) (com.google.camera.AndroidPriorityThread.run+10)
-* Fix bug where the load bias was set from the first PT\_LOAD program
- header that has a zero p\_offset value. Now it is set from the first
- executable PT\_LOAD program header. This has only ever been a problem
- for host executables compiled for the x86\_64 architecture.
-* Switched to the libc++ demangler for function names. Previously, the
- demangler used was not complete, so some less common demangled function
- names would not be properly demangled or the function name would not be
- demangled at all.
-* Fix bug in load bias handling. If the unwind information in the eh\_frame
- or eh\_frame\_hdr does not have the same bias as the executable section,
- and uses pc relative FDEs, the unwind will be incorrect. This tends
- to truncate unwinds since the unwinder could not find the correct unwind
- information for a given pc.
diff --git a/libunwindstack/ArmExidx.cpp b/libunwindstack/ArmExidx.cpp
deleted file mode 100644
index 818f5d1..0000000
--- a/libunwindstack/ArmExidx.cpp
+++ /dev/null
@@ -1,862 +0,0 @@
-/*
- * Copyright (C) 2016 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 <stdint.h>
-
-#include <deque>
-#include <string>
-
-#include <android-base/stringprintf.h>
-
-#include <unwindstack/Log.h>
-#include <unwindstack/MachineArm.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/RegsArm.h>
-
-#include "ArmExidx.h"
-#include "Check.h"
-
-namespace unwindstack {
-
-static constexpr uint8_t LOG_CFA_REG = 64;
-
-void ArmExidx::LogRawData() {
- std::string log_str("Raw Data:");
- for (const uint8_t data : data_) {
- log_str += android::base::StringPrintf(" 0x%02x", data);
- }
- log(log_indent_, log_str.c_str());
-}
-
-bool ArmExidx::ExtractEntryData(uint32_t entry_offset) {
- data_.clear();
- status_ = ARM_STATUS_NONE;
-
- if (entry_offset & 1) {
- // The offset needs to be at least two byte aligned.
- status_ = ARM_STATUS_INVALID_ALIGNMENT;
- return false;
- }
-
- // Each entry is a 32 bit prel31 offset followed by 32 bits
- // of unwind information. If bit 31 of the unwind data is zero,
- // then this is a prel31 offset to the start of the unwind data.
- // If the unwind data is 1, then this is a cant unwind entry.
- // Otherwise, this data is the compact form of the unwind information.
- uint32_t data;
- if (!elf_memory_->Read32(entry_offset + 4, &data)) {
- status_ = ARM_STATUS_READ_FAILED;
- status_address_ = entry_offset + 4;
- return false;
- }
- if (data == 1) {
- // This is a CANT UNWIND entry.
- status_ = ARM_STATUS_NO_UNWIND;
- if (log_type_ != ARM_LOG_NONE) {
- if (log_type_ == ARM_LOG_FULL) {
- log(log_indent_, "Raw Data: 0x00 0x00 0x00 0x01");
- }
- log(log_indent_, "[cantunwind]");
- }
- return false;
- }
-
- if (data & (1UL << 31)) {
- // This is a compact table entry.
- if ((data >> 24) & 0xf) {
- // This is a non-zero index, this code doesn't support
- // other formats.
- status_ = ARM_STATUS_INVALID_PERSONALITY;
- return false;
- }
- data_.push_back((data >> 16) & 0xff);
- data_.push_back((data >> 8) & 0xff);
- uint8_t last_op = data & 0xff;
- data_.push_back(last_op);
- if (last_op != ARM_OP_FINISH) {
- // If this didn't end with a finish op, add one.
- data_.push_back(ARM_OP_FINISH);
- }
- if (log_type_ == ARM_LOG_FULL) {
- LogRawData();
- }
- return true;
- }
-
- // Get the address of the ops.
- // Sign extend the data value if necessary.
- int32_t signed_data = static_cast<int32_t>(data << 1) >> 1;
- uint32_t addr = (entry_offset + 4) + signed_data;
- if (!elf_memory_->Read32(addr, &data)) {
- status_ = ARM_STATUS_READ_FAILED;
- status_address_ = addr;
- return false;
- }
-
- size_t num_table_words;
- if (data & (1UL << 31)) {
- // Compact model.
- switch ((data >> 24) & 0xf) {
- case 0:
- num_table_words = 0;
- data_.push_back((data >> 16) & 0xff);
- break;
- case 1:
- case 2:
- num_table_words = (data >> 16) & 0xff;
- addr += 4;
- break;
- default:
- // Only a personality of 0, 1, 2 is valid.
- status_ = ARM_STATUS_INVALID_PERSONALITY;
- return false;
- }
- data_.push_back((data >> 8) & 0xff);
- data_.push_back(data & 0xff);
- } else {
- // Generic model.
-
- // Skip the personality routine data, it doesn't contain any data
- // needed to decode the unwind information.
- addr += 4;
- if (!elf_memory_->Read32(addr, &data)) {
- status_ = ARM_STATUS_READ_FAILED;
- status_address_ = addr;
- return false;
- }
- num_table_words = (data >> 24) & 0xff;
- data_.push_back((data >> 16) & 0xff);
- data_.push_back((data >> 8) & 0xff);
- data_.push_back(data & 0xff);
- addr += 4;
- }
-
- if (num_table_words > 5) {
- status_ = ARM_STATUS_MALFORMED;
- return false;
- }
-
- for (size_t i = 0; i < num_table_words; i++) {
- if (!elf_memory_->Read32(addr, &data)) {
- status_ = ARM_STATUS_READ_FAILED;
- status_address_ = addr;
- return false;
- }
- data_.push_back((data >> 24) & 0xff);
- data_.push_back((data >> 16) & 0xff);
- data_.push_back((data >> 8) & 0xff);
- data_.push_back(data & 0xff);
- addr += 4;
- }
-
- if (data_.back() != ARM_OP_FINISH) {
- // If this didn't end with a finish op, add one.
- data_.push_back(ARM_OP_FINISH);
- }
-
- if (log_type_ == ARM_LOG_FULL) {
- LogRawData();
- }
- return true;
-}
-
-inline bool ArmExidx::GetByte(uint8_t* byte) {
- if (data_.empty()) {
- status_ = ARM_STATUS_TRUNCATED;
- return false;
- }
- *byte = data_.front();
- data_.pop_front();
- return true;
-}
-
-inline bool ArmExidx::DecodePrefix_10_00(uint8_t byte) {
- CHECK((byte >> 4) == 0x8);
-
- uint16_t registers = (byte & 0xf) << 8;
- if (!GetByte(&byte)) {
- return false;
- }
-
- registers |= byte;
- if (registers == 0) {
- // 10000000 00000000: Refuse to unwind
- if (log_type_ != ARM_LOG_NONE) {
- log(log_indent_, "Refuse to unwind");
- }
- status_ = ARM_STATUS_NO_UNWIND;
- return false;
- }
- // 1000iiii iiiiiiii: Pop up to 12 integer registers under masks {r15-r12}, {r11-r4}
- registers <<= 4;
-
- if (log_type_ != ARM_LOG_NONE) {
- if (log_type_ == ARM_LOG_FULL) {
- bool add_comma = false;
- std::string msg = "pop {";
- for (size_t reg = 4; reg < 16; reg++) {
- if (registers & (1 << reg)) {
- if (add_comma) {
- msg += ", ";
- }
- msg += android::base::StringPrintf("r%zu", reg);
- add_comma = true;
- }
- }
- log(log_indent_, "%s}", msg.c_str());
- } else {
- uint32_t cfa_offset = __builtin_popcount(registers) * 4;
- log_cfa_offset_ += cfa_offset;
- for (size_t reg = 4; reg < 16; reg++) {
- if (registers & (1 << reg)) {
- log_regs_[reg] = cfa_offset;
- cfa_offset -= 4;
- }
- }
- }
-
- if (log_skip_execution_) {
- return true;
- }
- }
-
- for (size_t reg = 4; reg < 16; reg++) {
- if (registers & (1 << reg)) {
- if (!process_memory_->Read32(cfa_, &(*regs_)[reg])) {
- status_ = ARM_STATUS_READ_FAILED;
- status_address_ = cfa_;
- return false;
- }
- cfa_ += 4;
- }
- }
-
- // If the sp register is modified, change the cfa value.
- if (registers & (1 << ARM_REG_SP)) {
- cfa_ = (*regs_)[ARM_REG_SP];
- }
-
- // Indicate if the pc register was set.
- if (registers & (1 << ARM_REG_PC)) {
- pc_set_ = true;
- }
- return true;
-}
-
-inline bool ArmExidx::DecodePrefix_10_01(uint8_t byte) {
- CHECK((byte >> 4) == 0x9);
-
- uint8_t bits = byte & 0xf;
- if (bits == 13 || bits == 15) {
- // 10011101: Reserved as prefix for ARM register to register moves
- // 10011111: Reserved as prefix for Intel Wireless MMX register to register moves
- if (log_type_ != ARM_LOG_NONE) {
- log(log_indent_, "[Reserved]");
- }
- status_ = ARM_STATUS_RESERVED;
- return false;
- }
- // 1001nnnn: Set vsp = r[nnnn] (nnnn != 13, 15)
- if (log_type_ != ARM_LOG_NONE) {
- if (log_type_ == ARM_LOG_FULL) {
- log(log_indent_, "vsp = r%d", bits);
- } else {
- log_regs_[LOG_CFA_REG] = bits;
- }
-
- if (log_skip_execution_) {
- return true;
- }
- }
- // It is impossible for bits to be larger than the total number of
- // arm registers, so don't bother checking if bits is a valid register.
- cfa_ = (*regs_)[bits];
- return true;
-}
-
-inline bool ArmExidx::DecodePrefix_10_10(uint8_t byte) {
- CHECK((byte >> 4) == 0xa);
-
- // 10100nnn: Pop r4-r[4+nnn]
- // 10101nnn: Pop r4-r[4+nnn], r14
- if (log_type_ != ARM_LOG_NONE) {
- uint8_t end_reg = byte & 0x7;
- if (log_type_ == ARM_LOG_FULL) {
- std::string msg = "pop {r4";
- if (end_reg) {
- msg += android::base::StringPrintf("-r%d", 4 + end_reg);
- }
- if (byte & 0x8) {
- log(log_indent_, "%s, r14}", msg.c_str());
- } else {
- log(log_indent_, "%s}", msg.c_str());
- }
- } else {
- end_reg += 4;
- uint32_t cfa_offset = (end_reg - 3) * 4;
- if (byte & 0x8) {
- cfa_offset += 4;
- }
- log_cfa_offset_ += cfa_offset;
-
- for (uint8_t reg = 4; reg <= end_reg; reg++) {
- log_regs_[reg] = cfa_offset;
- cfa_offset -= 4;
- }
-
- if (byte & 0x8) {
- log_regs_[14] = cfa_offset;
- }
- }
-
- if (log_skip_execution_) {
- return true;
- }
- }
-
- for (size_t i = 4; i <= 4 + (byte & 0x7); i++) {
- if (!process_memory_->Read32(cfa_, &(*regs_)[i])) {
- status_ = ARM_STATUS_READ_FAILED;
- status_address_ = cfa_;
- return false;
- }
- cfa_ += 4;
- }
- if (byte & 0x8) {
- if (!process_memory_->Read32(cfa_, &(*regs_)[ARM_REG_R14])) {
- status_ = ARM_STATUS_READ_FAILED;
- status_address_ = cfa_;
- return false;
- }
- cfa_ += 4;
- }
- return true;
-}
-
-inline bool ArmExidx::DecodePrefix_10_11_0000() {
- // 10110000: Finish
- if (log_type_ != ARM_LOG_NONE) {
- if (log_type_ == ARM_LOG_FULL) {
- log(log_indent_, "finish");
- }
-
- if (log_skip_execution_) {
- status_ = ARM_STATUS_FINISH;
- return false;
- }
- }
- status_ = ARM_STATUS_FINISH;
- return false;
-}
-
-inline bool ArmExidx::DecodePrefix_10_11_0001() {
- uint8_t byte;
- if (!GetByte(&byte)) {
- return false;
- }
-
- if (byte == 0) {
- // 10110001 00000000: Spare
- if (log_type_ != ARM_LOG_NONE) {
- log(log_indent_, "Spare");
- }
- status_ = ARM_STATUS_SPARE;
- return false;
- }
- if (byte >> 4) {
- // 10110001 xxxxyyyy: Spare (xxxx != 0000)
- if (log_type_ != ARM_LOG_NONE) {
- log(log_indent_, "Spare");
- }
- status_ = ARM_STATUS_SPARE;
- return false;
- }
-
- // 10110001 0000iiii: Pop integer registers under mask {r3, r2, r1, r0}
- if (log_type_ != ARM_LOG_NONE) {
- if (log_type_ == ARM_LOG_FULL) {
- bool add_comma = false;
- std::string msg = "pop {";
- for (size_t i = 0; i < 4; i++) {
- if (byte & (1 << i)) {
- if (add_comma) {
- msg += ", ";
- }
- msg += android::base::StringPrintf("r%zu", i);
- add_comma = true;
- }
- }
- log(log_indent_, "%s}", msg.c_str());
- } else {
- byte &= 0xf;
- uint32_t cfa_offset = __builtin_popcount(byte) * 4;
- log_cfa_offset_ += cfa_offset;
- for (size_t reg = 0; reg < 4; reg++) {
- if (byte & (1 << reg)) {
- log_regs_[reg] = cfa_offset;
- cfa_offset -= 4;
- }
- }
- }
-
- if (log_skip_execution_) {
- return true;
- }
- }
-
- for (size_t reg = 0; reg < 4; reg++) {
- if (byte & (1 << reg)) {
- if (!process_memory_->Read32(cfa_, &(*regs_)[reg])) {
- status_ = ARM_STATUS_READ_FAILED;
- status_address_ = cfa_;
- return false;
- }
- cfa_ += 4;
- }
- }
- return true;
-}
-
-inline void ArmExidx::AdjustRegisters(int32_t offset) {
- for (auto& entry : log_regs_) {
- if (entry.first >= LOG_CFA_REG) {
- break;
- }
- entry.second += offset;
- }
-}
-
-inline bool ArmExidx::DecodePrefix_10_11_0010() {
- // 10110010 uleb128: vsp = vsp + 0x204 + (uleb128 << 2)
- uint32_t result = 0;
- uint32_t shift = 0;
- uint8_t byte;
- do {
- if (!GetByte(&byte)) {
- return false;
- }
-
- result |= (byte & 0x7f) << shift;
- shift += 7;
- } while (byte & 0x80);
- result <<= 2;
- if (log_type_ != ARM_LOG_NONE) {
- int32_t cfa_offset = 0x204 + result;
- if (log_type_ == ARM_LOG_FULL) {
- log(log_indent_, "vsp = vsp + %d", cfa_offset);
- } else {
- log_cfa_offset_ += cfa_offset;
- }
- AdjustRegisters(cfa_offset);
-
- if (log_skip_execution_) {
- return true;
- }
- }
- cfa_ += 0x204 + result;
- return true;
-}
-
-inline bool ArmExidx::DecodePrefix_10_11_0011() {
- // 10110011 sssscccc: Pop VFP double precision registers D[ssss]-D[ssss+cccc] by FSTMFDX
- uint8_t byte;
- if (!GetByte(&byte)) {
- return false;
- }
-
- if (log_type_ != ARM_LOG_NONE) {
- uint8_t start_reg = byte >> 4;
- uint8_t end_reg = start_reg + (byte & 0xf);
-
- if (log_type_ == ARM_LOG_FULL) {
- std::string msg = android::base::StringPrintf("pop {d%d", start_reg);
- if (end_reg) {
- msg += android::base::StringPrintf("-d%d", end_reg);
- }
- log(log_indent_, "%s}", msg.c_str());
- } else {
- log(log_indent_, "Unsupported DX register display");
- }
-
- if (log_skip_execution_) {
- return true;
- }
- }
- cfa_ += (byte & 0xf) * 8 + 12;
- return true;
-}
-
-inline bool ArmExidx::DecodePrefix_10_11_01nn() {
- // 101101nn: Spare
- if (log_type_ != ARM_LOG_NONE) {
- log(log_indent_, "Spare");
- }
- status_ = ARM_STATUS_SPARE;
- return false;
-}
-
-inline bool ArmExidx::DecodePrefix_10_11_1nnn(uint8_t byte) {
- CHECK((byte & ~0x07) == 0xb8);
-
- // 10111nnn: Pop VFP double-precision registers D[8]-D[8+nnn] by FSTMFDX
- if (log_type_ != ARM_LOG_NONE) {
- if (log_type_ == ARM_LOG_FULL) {
- uint8_t last_reg = (byte & 0x7);
- std::string msg = "pop {d8";
- if (last_reg) {
- msg += android::base::StringPrintf("-d%d", last_reg + 8);
- }
- log(log_indent_, "%s}", msg.c_str());
- } else {
- log(log_indent_, "Unsupported DX register display");
- }
-
- if (log_skip_execution_) {
- return true;
- }
- }
- // Only update the cfa.
- cfa_ += (byte & 0x7) * 8 + 12;
- return true;
-}
-
-inline bool ArmExidx::DecodePrefix_10(uint8_t byte) {
- CHECK((byte >> 6) == 0x2);
-
- switch ((byte >> 4) & 0x3) {
- case 0:
- return DecodePrefix_10_00(byte);
- case 1:
- return DecodePrefix_10_01(byte);
- case 2:
- return DecodePrefix_10_10(byte);
- default:
- switch (byte & 0xf) {
- case 0:
- return DecodePrefix_10_11_0000();
- case 1:
- return DecodePrefix_10_11_0001();
- case 2:
- return DecodePrefix_10_11_0010();
- case 3:
- return DecodePrefix_10_11_0011();
- default:
- if (byte & 0x8) {
- return DecodePrefix_10_11_1nnn(byte);
- } else {
- return DecodePrefix_10_11_01nn();
- }
- }
- }
-}
-
-inline bool ArmExidx::DecodePrefix_11_000(uint8_t byte) {
- CHECK((byte & ~0x07) == 0xc0);
-
- uint8_t bits = byte & 0x7;
- if (bits == 6) {
- if (!GetByte(&byte)) {
- return false;
- }
-
- // 11000110 sssscccc: Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc]
- if (log_type_ != ARM_LOG_NONE) {
- if (log_type_ == ARM_LOG_FULL) {
- uint8_t start_reg = byte >> 4;
- std::string msg = android::base::StringPrintf("pop {wR%d", start_reg);
- uint8_t end_reg = byte & 0xf;
- if (end_reg) {
- msg += android::base::StringPrintf("-wR%d", start_reg + end_reg);
- }
- log(log_indent_, "%s}", msg.c_str());
- } else {
- log(log_indent_, "Unsupported wRX register display");
- }
-
- if (log_skip_execution_) {
- return true;
- }
- }
- // Only update the cfa.
- cfa_ += (byte & 0xf) * 8 + 8;
- } else if (bits == 7) {
- if (!GetByte(&byte)) {
- return false;
- }
-
- if (byte == 0) {
- // 11000111 00000000: Spare
- if (log_type_ != ARM_LOG_NONE) {
- log(log_indent_, "Spare");
- }
- status_ = ARM_STATUS_SPARE;
- return false;
- } else if ((byte >> 4) == 0) {
- // 11000111 0000iiii: Intel Wireless MMX pop wCGR registers {wCGR0,1,2,3}
- if (log_type_ != ARM_LOG_NONE) {
- if (log_type_ == ARM_LOG_FULL) {
- bool add_comma = false;
- std::string msg = "pop {";
- for (size_t i = 0; i < 4; i++) {
- if (byte & (1 << i)) {
- if (add_comma) {
- msg += ", ";
- }
- msg += android::base::StringPrintf("wCGR%zu", i);
- add_comma = true;
- }
- }
- log(log_indent_, "%s}", msg.c_str());
- } else {
- log(log_indent_, "Unsupported wCGR register display");
- }
-
- if (log_skip_execution_) {
- return true;
- }
- }
- // Only update the cfa.
- cfa_ += __builtin_popcount(byte) * 4;
- } else {
- // 11000111 xxxxyyyy: Spare (xxxx != 0000)
- if (log_type_ != ARM_LOG_NONE) {
- log(log_indent_, "Spare");
- }
- status_ = ARM_STATUS_SPARE;
- return false;
- }
- } else {
- // 11000nnn: Intel Wireless MMX pop wR[10]-wR[10+nnn] (nnn != 6, 7)
- if (log_type_ != ARM_LOG_NONE) {
- if (log_type_ == ARM_LOG_FULL) {
- std::string msg = "pop {wR10";
- uint8_t nnn = byte & 0x7;
- if (nnn) {
- msg += android::base::StringPrintf("-wR%d", 10 + nnn);
- }
- log(log_indent_, "%s}", msg.c_str());
- } else {
- log(log_indent_, "Unsupported wRX register display");
- }
-
- if (log_skip_execution_) {
- return true;
- }
- }
- // Only update the cfa.
- cfa_ += (byte & 0x7) * 8 + 8;
- }
- return true;
-}
-
-inline bool ArmExidx::DecodePrefix_11_001(uint8_t byte) {
- CHECK((byte & ~0x07) == 0xc8);
-
- uint8_t bits = byte & 0x7;
- if (bits == 0) {
- // 11001000 sssscccc: Pop VFP double precision registers D[16+ssss]-D[16+ssss+cccc] by VPUSH
- if (!GetByte(&byte)) {
- return false;
- }
-
- if (log_type_ != ARM_LOG_NONE) {
- if (log_type_ == ARM_LOG_FULL) {
- uint8_t start_reg = byte >> 4;
- std::string msg = android::base::StringPrintf("pop {d%d", 16 + start_reg);
- uint8_t end_reg = byte & 0xf;
- if (end_reg) {
- msg += android::base::StringPrintf("-d%d", 16 + start_reg + end_reg);
- }
- log(log_indent_, "%s}", msg.c_str());
- } else {
- log(log_indent_, "Unsupported DX register display");
- }
-
- if (log_skip_execution_) {
- return true;
- }
- }
- // Only update the cfa.
- cfa_ += (byte & 0xf) * 8 + 8;
- } else if (bits == 1) {
- // 11001001 sssscccc: Pop VFP double precision registers D[ssss]-D[ssss+cccc] by VPUSH
- if (!GetByte(&byte)) {
- return false;
- }
-
- if (log_type_ != ARM_LOG_NONE) {
- if (log_type_ == ARM_LOG_FULL) {
- uint8_t start_reg = byte >> 4;
- std::string msg = android::base::StringPrintf("pop {d%d", start_reg);
- uint8_t end_reg = byte & 0xf;
- if (end_reg) {
- msg += android::base::StringPrintf("-d%d", start_reg + end_reg);
- }
- log(log_indent_, "%s}", msg.c_str());
- } else {
- log(log_indent_, "Unsupported DX register display");
- }
-
- if (log_skip_execution_) {
- return true;
- }
- }
- // Only update the cfa.
- cfa_ += (byte & 0xf) * 8 + 8;
- } else {
- // 11001yyy: Spare (yyy != 000, 001)
- if (log_type_ != ARM_LOG_NONE) {
- log(log_indent_, "Spare");
- }
- status_ = ARM_STATUS_SPARE;
- return false;
- }
- return true;
-}
-
-inline bool ArmExidx::DecodePrefix_11_010(uint8_t byte) {
- CHECK((byte & ~0x07) == 0xd0);
-
- // 11010nnn: Pop VFP double precision registers D[8]-D[8+nnn] by VPUSH
- if (log_type_ != ARM_LOG_NONE) {
- if (log_type_ == ARM_LOG_FULL) {
- std::string msg = "pop {d8";
- uint8_t end_reg = byte & 0x7;
- if (end_reg) {
- msg += android::base::StringPrintf("-d%d", 8 + end_reg);
- }
- log(log_indent_, "%s}", msg.c_str());
- } else {
- log(log_indent_, "Unsupported DX register display");
- }
-
- if (log_skip_execution_) {
- return true;
- }
- }
- cfa_ += (byte & 0x7) * 8 + 8;
- return true;
-}
-
-inline bool ArmExidx::DecodePrefix_11(uint8_t byte) {
- CHECK((byte >> 6) == 0x3);
-
- switch ((byte >> 3) & 0x7) {
- case 0:
- return DecodePrefix_11_000(byte);
- case 1:
- return DecodePrefix_11_001(byte);
- case 2:
- return DecodePrefix_11_010(byte);
- default:
- // 11xxxyyy: Spare (xxx != 000, 001, 010)
- if (log_type_ != ARM_LOG_NONE) {
- log(log_indent_, "Spare");
- }
- status_ = ARM_STATUS_SPARE;
- return false;
- }
-}
-
-bool ArmExidx::Decode() {
- status_ = ARM_STATUS_NONE;
- uint8_t byte;
- if (!GetByte(&byte)) {
- return false;
- }
-
- switch (byte >> 6) {
- case 0:
- // 00xxxxxx: vsp = vsp + (xxxxxxx << 2) + 4
- if (log_type_ != ARM_LOG_NONE) {
- int32_t cfa_offset = ((byte & 0x3f) << 2) + 4;
- if (log_type_ == ARM_LOG_FULL) {
- log(log_indent_, "vsp = vsp + %d", cfa_offset);
- } else {
- log_cfa_offset_ += cfa_offset;
- }
- AdjustRegisters(cfa_offset);
-
- if (log_skip_execution_) {
- break;
- }
- }
- cfa_ += ((byte & 0x3f) << 2) + 4;
- break;
- case 1:
- // 01xxxxxx: vsp = vsp - (xxxxxxx << 2) + 4
- if (log_type_ != ARM_LOG_NONE) {
- uint32_t cfa_offset = ((byte & 0x3f) << 2) + 4;
- if (log_type_ == ARM_LOG_FULL) {
- log(log_indent_, "vsp = vsp - %d", cfa_offset);
- } else {
- log_cfa_offset_ -= cfa_offset;
- }
- AdjustRegisters(-cfa_offset);
-
- if (log_skip_execution_) {
- break;
- }
- }
- cfa_ -= ((byte & 0x3f) << 2) + 4;
- break;
- case 2:
- return DecodePrefix_10(byte);
- default:
- return DecodePrefix_11(byte);
- }
- return true;
-}
-
-bool ArmExidx::Eval() {
- pc_set_ = false;
- while (Decode());
- return status_ == ARM_STATUS_FINISH;
-}
-
-void ArmExidx::LogByReg() {
- if (log_type_ != ARM_LOG_BY_REG) {
- return;
- }
-
- uint8_t cfa_reg;
- if (log_regs_.count(LOG_CFA_REG) == 0) {
- cfa_reg = 13;
- } else {
- cfa_reg = log_regs_[LOG_CFA_REG];
- }
-
- if (log_cfa_offset_ != 0) {
- char sign = (log_cfa_offset_ > 0) ? '+' : '-';
- log(log_indent_, "cfa = r%zu %c %d", cfa_reg, sign, abs(log_cfa_offset_));
- } else {
- log(log_indent_, "cfa = r%zu", cfa_reg);
- }
-
- for (const auto& entry : log_regs_) {
- if (entry.first >= LOG_CFA_REG) {
- break;
- }
- if (entry.second == 0) {
- log(log_indent_, "r%zu = [cfa]", entry.first);
- } else {
- char sign = (entry.second > 0) ? '-' : '+';
- log(log_indent_, "r%zu = [cfa %c %d]", entry.first, sign, abs(entry.second));
- }
- }
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/ArmExidx.h b/libunwindstack/ArmExidx.h
deleted file mode 100644
index d9fc371..0000000
--- a/libunwindstack/ArmExidx.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_ARM_EXIDX_H
-#define _LIBUNWINDSTACK_ARM_EXIDX_H
-
-#include <stdint.h>
-
-#include <deque>
-#include <map>
-
-namespace unwindstack {
-
-// Forward declarations.
-class Memory;
-class RegsArm;
-
-enum ArmStatus : size_t {
- ARM_STATUS_NONE = 0,
- ARM_STATUS_NO_UNWIND,
- ARM_STATUS_FINISH,
- ARM_STATUS_RESERVED,
- ARM_STATUS_SPARE,
- ARM_STATUS_TRUNCATED,
- ARM_STATUS_READ_FAILED,
- ARM_STATUS_MALFORMED,
- ARM_STATUS_INVALID_ALIGNMENT,
- ARM_STATUS_INVALID_PERSONALITY,
-};
-
-enum ArmOp : uint8_t {
- ARM_OP_FINISH = 0xb0,
-};
-
-enum ArmLogType : uint8_t {
- ARM_LOG_NONE,
- ARM_LOG_FULL,
- ARM_LOG_BY_REG,
-};
-
-class ArmExidx {
- public:
- ArmExidx(RegsArm* regs, Memory* elf_memory, Memory* process_memory)
- : regs_(regs), elf_memory_(elf_memory), process_memory_(process_memory) {}
- virtual ~ArmExidx() {}
-
- void LogRawData();
-
- void LogByReg();
-
- bool ExtractEntryData(uint32_t entry_offset);
-
- bool Eval();
-
- bool Decode();
-
- std::deque<uint8_t>* data() { return &data_; }
-
- ArmStatus status() { return status_; }
- uint64_t status_address() { return status_address_; }
-
- RegsArm* regs() { return regs_; }
-
- uint32_t cfa() { return cfa_; }
- void set_cfa(uint32_t cfa) { cfa_ = cfa; }
-
- bool pc_set() { return pc_set_; }
- void set_pc_set(bool pc_set) { pc_set_ = pc_set; }
-
- void set_log(ArmLogType log_type) { log_type_ = log_type; }
- void set_log_skip_execution(bool skip_execution) { log_skip_execution_ = skip_execution; }
- void set_log_indent(uint8_t indent) { log_indent_ = indent; }
-
- private:
- bool GetByte(uint8_t* byte);
- void AdjustRegisters(int32_t offset);
-
- bool DecodePrefix_10_00(uint8_t byte);
- bool DecodePrefix_10_01(uint8_t byte);
- bool DecodePrefix_10_10(uint8_t byte);
- bool DecodePrefix_10_11_0000();
- bool DecodePrefix_10_11_0001();
- bool DecodePrefix_10_11_0010();
- bool DecodePrefix_10_11_0011();
- bool DecodePrefix_10_11_01nn();
- bool DecodePrefix_10_11_1nnn(uint8_t byte);
- bool DecodePrefix_10(uint8_t byte);
-
- bool DecodePrefix_11_000(uint8_t byte);
- bool DecodePrefix_11_001(uint8_t byte);
- bool DecodePrefix_11_010(uint8_t byte);
- bool DecodePrefix_11(uint8_t byte);
-
- RegsArm* regs_ = nullptr;
- uint32_t cfa_ = 0;
- std::deque<uint8_t> data_;
- ArmStatus status_ = ARM_STATUS_NONE;
- uint64_t status_address_ = 0;
-
- Memory* elf_memory_;
- Memory* process_memory_;
-
- ArmLogType log_type_ = ARM_LOG_NONE;
- uint8_t log_indent_ = 0;
- bool log_skip_execution_ = false;
- bool pc_set_ = false;
- int32_t log_cfa_offset_ = 0;
- std::map<uint8_t, int32_t> log_regs_;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_ARM_EXIDX_H
diff --git a/libunwindstack/AsmGetRegsX86.S b/libunwindstack/AsmGetRegsX86.S
deleted file mode 100644
index 021e628..0000000
--- a/libunwindstack/AsmGetRegsX86.S
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
- .text
- .global AsmGetRegs
- .balign 16
- .type AsmGetRegs, @function
-AsmGetRegs:
- .cfi_startproc
- mov 4(%esp), %eax
- movl $0, (%eax)
- movl %ecx, 4(%eax)
- movl %edx, 8(%eax)
- movl %ebx, 12(%eax)
-
- /* ESP */
- leal 4(%esp), %ecx
- movl %ecx, 16(%eax)
-
- movl %ebp, 20(%eax)
- movl %esi, 24(%eax)
- movl %edi, 28(%eax)
-
- /* EIP */
- movl (%esp), %ecx
- movl %ecx, 32(%eax)
-
- mov %cs, 36(%eax)
- mov %ss, 40(%eax)
- mov %ds, 44(%eax)
- mov %es, 48(%eax)
- mov %fs, 52(%eax)
- mov %gs, 56(%eax)
- ret
-
- .cfi_endproc
- .size AsmGetRegs, .-AsmGetRegs
diff --git a/libunwindstack/AsmGetRegsX86_64.S b/libunwindstack/AsmGetRegsX86_64.S
deleted file mode 100644
index 4cd3b6f..0000000
--- a/libunwindstack/AsmGetRegsX86_64.S
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
- .text
- .global AsmGetRegs
- .balign 16
- .type AsmGetRegs, @function
-AsmGetRegs:
- .cfi_startproc
- movq %rax, (%rdi)
- movq %rdx, 8(%rdi)
- movq %rcx, 16(%rdi)
- movq %rbx, 24(%rdi)
- movq %rsi, 32(%rdi)
- movq %rdi, 40(%rdi)
- movq %rbp, 48(%rdi)
-
- /* RSP */
- lea 8(%rsp), %rax
- movq %rax, 56(%rdi)
-
- movq %r8, 64(%rdi)
- movq %r9, 72(%rdi)
- movq %r10, 80(%rdi)
- movq %r11, 88(%rdi)
- movq %r12, 96(%rdi)
- movq %r13, 104(%rdi)
- movq %r14, 112(%rdi)
- movq %r15, 120(%rdi)
-
- /* RIP */
- movq (%rsp), %rax
- movq %rax, 128(%rdi)
- ret
-
- .cfi_endproc
- .size AsmGetRegs, .-AsmGetRegs
diff --git a/libunwindstack/Check.h b/libunwindstack/Check.h
deleted file mode 100644
index 9643d76..0000000
--- a/libunwindstack/Check.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef _LIBUNWINDSTACK_CHECK_H
-#define _LIBUNWINDSTACK_CHECK_H
-
-#include <stdlib.h>
-
-#include <unwindstack/Log.h>
-
-namespace unwindstack {
-
-#define CHECK(assertion) \
- if (__builtin_expect(!(assertion), false)) { \
- log(0, "%s:%d: %s\n", __FILE__, __LINE__, #assertion); \
- abort(); \
- }
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_CHECK_H
diff --git a/libunwindstack/DexFile.cpp b/libunwindstack/DexFile.cpp
deleted file mode 100644
index 8fc3d23..0000000
--- a/libunwindstack/DexFile.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (C) 2018 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 <stdint.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <memory>
-
-#define LOG_TAG "unwind"
-#include <log/log.h>
-
-#include <android-base/unique_fd.h>
-#include <art_api/dex_file_support.h>
-
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Memory.h>
-
-#include "DexFile.h"
-
-namespace unwindstack {
-
-static bool CheckDexSupport() {
- if (std::string err_msg; !art_api::dex::TryLoadLibdexfileExternal(&err_msg)) {
- ALOGW("Failed to initialize DEX file support: %s", err_msg.c_str());
- return false;
- }
- return true;
-}
-
-static bool HasDexSupport() {
- static bool has_dex_support = CheckDexSupport();
- return has_dex_support;
-}
-
-std::unique_ptr<DexFile> DexFile::Create(uint64_t dex_file_offset_in_memory, Memory* memory,
- MapInfo* info) {
- if (UNLIKELY(!HasDexSupport())) {
- return nullptr;
- }
-
- size_t max_size = info->end - dex_file_offset_in_memory;
- if (memory->IsLocal()) {
- size_t size = max_size;
-
- std::string err_msg;
- std::unique_ptr<art_api::dex::DexFile> art_dex_file = DexFile::OpenFromMemory(
- reinterpret_cast<void const*>(dex_file_offset_in_memory), &size, info->name, &err_msg);
- if (art_dex_file != nullptr && size <= max_size) {
- return std::unique_ptr<DexFile>(new DexFile(art_dex_file));
- }
- }
-
- if (!info->name.empty()) {
- std::unique_ptr<DexFile> dex_file =
- DexFileFromFile::Create(dex_file_offset_in_memory - info->start + info->offset, info->name);
- if (dex_file) {
- return dex_file;
- }
- }
- return DexFileFromMemory::Create(dex_file_offset_in_memory, memory, info->name, max_size);
-}
-
-bool DexFile::GetMethodInformation(uint64_t dex_offset, std::string* method_name,
- uint64_t* method_offset) {
- art_api::dex::MethodInfo method_info = GetMethodInfoForOffset(dex_offset, false);
- if (method_info.offset == 0) {
- return false;
- }
- *method_name = method_info.name;
- *method_offset = dex_offset - method_info.offset;
- return true;
-}
-
-std::unique_ptr<DexFileFromFile> DexFileFromFile::Create(uint64_t dex_file_offset_in_file,
- const std::string& file) {
- if (UNLIKELY(!HasDexSupport())) {
- return nullptr;
- }
-
- android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(file.c_str(), O_RDONLY | O_CLOEXEC)));
- if (fd == -1) {
- return nullptr;
- }
-
- std::string error_msg;
- std::unique_ptr<art_api::dex::DexFile> art_dex_file =
- OpenFromFd(fd, dex_file_offset_in_file, file, &error_msg);
- if (art_dex_file == nullptr) {
- return nullptr;
- }
-
- return std::unique_ptr<DexFileFromFile>(new DexFileFromFile(art_dex_file));
-}
-
-std::unique_ptr<DexFileFromMemory> DexFileFromMemory::Create(uint64_t dex_file_offset_in_memory,
- Memory* memory,
- const std::string& name,
- size_t max_size) {
- if (UNLIKELY(!HasDexSupport())) {
- return nullptr;
- }
-
- std::vector<uint8_t> backing_memory;
-
- for (size_t size = 0;;) {
- std::string error_msg;
- std::unique_ptr<art_api::dex::DexFile> art_dex_file =
- OpenFromMemory(backing_memory.data(), &size, name, &error_msg);
- if (size > max_size) {
- return nullptr;
- }
-
- if (art_dex_file != nullptr) {
- return std::unique_ptr<DexFileFromMemory>(
- new DexFileFromMemory(art_dex_file, std::move(backing_memory)));
- }
-
- if (!error_msg.empty()) {
- return nullptr;
- }
-
- backing_memory.resize(size);
- if (!memory->ReadFully(dex_file_offset_in_memory, backing_memory.data(),
- backing_memory.size())) {
- return nullptr;
- }
- }
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/DexFile.h b/libunwindstack/DexFile.h
deleted file mode 100644
index fe185da..0000000
--- a/libunwindstack/DexFile.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#ifndef _LIBUNWINDSTACK_DEX_FILE_H
-#define _LIBUNWINDSTACK_DEX_FILE_H
-
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <art_api/dex_file_support.h>
-
-namespace unwindstack {
-
-class DexFile : protected art_api::dex::DexFile {
- public:
- virtual ~DexFile() = default;
-
- bool GetMethodInformation(uint64_t dex_offset, std::string* method_name, uint64_t* method_offset);
-
- static std::unique_ptr<DexFile> Create(uint64_t dex_file_offset_in_memory, Memory* memory,
- MapInfo* info);
-
- protected:
- DexFile(std::unique_ptr<art_api::dex::DexFile>& art_dex_file)
- : art_api::dex::DexFile(art_dex_file) {}
-};
-
-class DexFileFromFile : public DexFile {
- public:
- static std::unique_ptr<DexFileFromFile> Create(uint64_t dex_file_offset_in_file,
- const std::string& file);
-
- private:
- DexFileFromFile(std::unique_ptr<art_api::dex::DexFile>& art_dex_file) : DexFile(art_dex_file) {}
-};
-
-class DexFileFromMemory : public DexFile {
- public:
- static std::unique_ptr<DexFileFromMemory> Create(uint64_t dex_file_offset_in_memory,
- Memory* memory, const std::string& name,
- size_t max_size);
-
- private:
- DexFileFromMemory(std::unique_ptr<art_api::dex::DexFile>& art_dex_file,
- std::vector<uint8_t>&& memory)
- : DexFile(art_dex_file), memory_(std::move(memory)) {}
-
- std::vector<uint8_t> memory_;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_DEX_FILE_H
diff --git a/libunwindstack/DexFiles.cpp b/libunwindstack/DexFiles.cpp
deleted file mode 100644
index 2057fad..0000000
--- a/libunwindstack/DexFiles.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 2018 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 <stdint.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <memory>
-
-#include <unwindstack/DexFiles.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
-
-#if defined(DEXFILE_SUPPORT)
-#include "DexFile.h"
-#endif
-
-namespace unwindstack {
-
-#if !defined(DEXFILE_SUPPORT)
-// Empty class definition.
-class DexFile {
- public:
- DexFile() = default;
- virtual ~DexFile() = default;
-};
-#endif
-
-struct DEXFileEntry32 {
- uint32_t next;
- uint32_t prev;
- uint32_t dex_file;
-};
-
-struct DEXFileEntry64 {
- uint64_t next;
- uint64_t prev;
- uint64_t dex_file;
-};
-
-DexFiles::DexFiles(std::shared_ptr<Memory>& memory) : Global(memory) {}
-
-DexFiles::DexFiles(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs)
- : Global(memory, search_libs) {}
-
-DexFiles::~DexFiles() {}
-
-void DexFiles::ProcessArch() {
- switch (arch()) {
- case ARCH_ARM:
- case ARCH_MIPS:
- case ARCH_X86:
- read_entry_ptr_func_ = &DexFiles::ReadEntryPtr32;
- read_entry_func_ = &DexFiles::ReadEntry32;
- break;
-
- case ARCH_ARM64:
- case ARCH_MIPS64:
- case ARCH_X86_64:
- read_entry_ptr_func_ = &DexFiles::ReadEntryPtr64;
- read_entry_func_ = &DexFiles::ReadEntry64;
- break;
-
- case ARCH_UNKNOWN:
- abort();
- }
-}
-
-uint64_t DexFiles::ReadEntryPtr32(uint64_t addr) {
- uint32_t entry;
- const uint32_t field_offset = 12; // offset of first_entry_ in the descriptor struct.
- if (!memory_->ReadFully(addr + field_offset, &entry, sizeof(entry))) {
- return 0;
- }
- return entry;
-}
-
-uint64_t DexFiles::ReadEntryPtr64(uint64_t addr) {
- uint64_t entry;
- const uint32_t field_offset = 16; // offset of first_entry_ in the descriptor struct.
- if (!memory_->ReadFully(addr + field_offset, &entry, sizeof(entry))) {
- return 0;
- }
- return entry;
-}
-
-bool DexFiles::ReadEntry32() {
- DEXFileEntry32 entry;
- if (!memory_->ReadFully(entry_addr_, &entry, sizeof(entry)) || entry.dex_file == 0) {
- entry_addr_ = 0;
- return false;
- }
-
- addrs_.push_back(entry.dex_file);
- entry_addr_ = entry.next;
- return true;
-}
-
-bool DexFiles::ReadEntry64() {
- DEXFileEntry64 entry;
- if (!memory_->ReadFully(entry_addr_, &entry, sizeof(entry)) || entry.dex_file == 0) {
- entry_addr_ = 0;
- return false;
- }
-
- addrs_.push_back(entry.dex_file);
- entry_addr_ = entry.next;
- return true;
-}
-
-bool DexFiles::ReadVariableData(uint64_t ptr_offset) {
- entry_addr_ = (this->*read_entry_ptr_func_)(ptr_offset);
- return entry_addr_ != 0;
-}
-
-void DexFiles::Init(Maps* maps) {
- if (initialized_) {
- return;
- }
- initialized_ = true;
- entry_addr_ = 0;
-
- FindAndReadVariable(maps, "__dex_debug_descriptor");
-}
-
-#if defined(DEXFILE_SUPPORT)
-DexFile* DexFiles::GetDexFile(uint64_t dex_file_offset, MapInfo* info) {
- // Lock while processing the data.
- DexFile* dex_file;
- auto entry = files_.find(dex_file_offset);
- if (entry == files_.end()) {
- std::unique_ptr<DexFile> new_dex_file = DexFile::Create(dex_file_offset, memory_.get(), info);
- dex_file = new_dex_file.get();
- files_[dex_file_offset] = std::move(new_dex_file);
- } else {
- dex_file = entry->second.get();
- }
- return dex_file;
-}
-#else
-DexFile* DexFiles::GetDexFile(uint64_t, MapInfo*) {
- return nullptr;
-}
-#endif
-
-bool DexFiles::GetAddr(size_t index, uint64_t* addr) {
- if (index < addrs_.size()) {
- *addr = addrs_[index];
- return true;
- }
- if (entry_addr_ != 0 && (this->*read_entry_func_)()) {
- *addr = addrs_.back();
- return true;
- }
- return false;
-}
-
-#if defined(DEXFILE_SUPPORT)
-void DexFiles::GetMethodInformation(Maps* maps, MapInfo* info, uint64_t dex_pc,
- std::string* method_name, uint64_t* method_offset) {
- std::lock_guard<std::mutex> guard(lock_);
- if (!initialized_) {
- Init(maps);
- }
-
- size_t index = 0;
- uint64_t addr;
- while (GetAddr(index++, &addr)) {
- if (addr < info->start || addr >= info->end) {
- continue;
- }
-
- DexFile* dex_file = GetDexFile(addr, info);
- if (dex_file != nullptr &&
- dex_file->GetMethodInformation(dex_pc - addr, method_name, method_offset)) {
- break;
- }
- }
-}
-#else
-void DexFiles::GetMethodInformation(Maps*, MapInfo*, uint64_t, std::string*, uint64_t*) {}
-#endif
-
-} // namespace unwindstack
diff --git a/libunwindstack/DwarfCfa.cpp b/libunwindstack/DwarfCfa.cpp
deleted file mode 100644
index c6db209..0000000
--- a/libunwindstack/DwarfCfa.cpp
+++ /dev/null
@@ -1,768 +0,0 @@
-/*
- * Copyright (C) 2016 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 <inttypes.h>
-#include <stdint.h>
-
-#include <string>
-#include <type_traits>
-#include <vector>
-
-#include <android-base/macros.h>
-#include <android-base/stringprintf.h>
-
-#include <unwindstack/DwarfError.h>
-#include <unwindstack/DwarfLocation.h>
-#include <unwindstack/Elf.h>
-#include <unwindstack/Log.h>
-#include <unwindstack/MachineArm64.h>
-
-#include "DwarfCfa.h"
-#include "DwarfEncoding.h"
-#include "DwarfOp.h"
-
-namespace unwindstack {
-
-template <typename AddressType>
-constexpr typename DwarfCfa<AddressType>::process_func DwarfCfa<AddressType>::kCallbackTable[64];
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::GetLocationInfo(uint64_t pc, uint64_t start_offset, uint64_t end_offset,
- dwarf_loc_regs_t* loc_regs) {
- if (cie_loc_regs_ != nullptr) {
- for (const auto& entry : *cie_loc_regs_) {
- (*loc_regs)[entry.first] = entry.second;
- }
- }
- last_error_.code = DWARF_ERROR_NONE;
- last_error_.address = 0;
-
- memory_->set_cur_offset(start_offset);
- uint64_t cfa_offset;
- cur_pc_ = fde_->pc_start;
- loc_regs->pc_start = cur_pc_;
- while (true) {
- if (cur_pc_ > pc) {
- loc_regs->pc_end = cur_pc_;
- return true;
- }
- if ((cfa_offset = memory_->cur_offset()) >= end_offset) {
- loc_regs->pc_end = fde_->pc_end;
- return true;
- }
- loc_regs->pc_start = cur_pc_;
- operands_.clear();
- // Read the cfa information.
- uint8_t cfa_value;
- if (!memory_->ReadBytes(&cfa_value, 1)) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_->cur_offset();
- return false;
- }
- uint8_t cfa_low = cfa_value & 0x3f;
- // Check the 2 high bits.
- switch (cfa_value >> 6) {
- case 1:
- cur_pc_ += cfa_low * fde_->cie->code_alignment_factor;
- break;
- case 2: {
- uint64_t offset;
- if (!memory_->ReadULEB128(&offset)) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_->cur_offset();
- return false;
- }
- SignedType signed_offset =
- static_cast<SignedType>(offset) * fde_->cie->data_alignment_factor;
- (*loc_regs)[cfa_low] = {.type = DWARF_LOCATION_OFFSET,
- .values = {static_cast<uint64_t>(signed_offset)}};
- break;
- }
- case 3: {
- if (cie_loc_regs_ == nullptr) {
- log(0, "restore while processing cie");
- last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
- return false;
- }
-
- auto reg_entry = cie_loc_regs_->find(cfa_low);
- if (reg_entry == cie_loc_regs_->end()) {
- loc_regs->erase(cfa_low);
- } else {
- (*loc_regs)[cfa_low] = reg_entry->second;
- }
- break;
- }
- case 0: {
- const auto handle_func = DwarfCfa<AddressType>::kCallbackTable[cfa_low];
- if (handle_func == nullptr) {
- last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
- return false;
- }
-
- const auto cfa = &DwarfCfaInfo::kTable[cfa_low];
- for (size_t i = 0; i < cfa->num_operands; i++) {
- if (cfa->operands[i] == DW_EH_PE_block) {
- uint64_t block_length;
- if (!memory_->ReadULEB128(&block_length)) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_->cur_offset();
- return false;
- }
- operands_.push_back(block_length);
- memory_->set_cur_offset(memory_->cur_offset() + block_length);
- continue;
- }
- uint64_t value;
- if (!memory_->ReadEncodedValue<AddressType>(cfa->operands[i], &value)) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_->cur_offset();
- return false;
- }
- operands_.push_back(value);
- }
-
- if (!(this->*handle_func)(loc_regs)) {
- return false;
- }
- break;
- }
- }
- }
-}
-
-template <typename AddressType>
-std::string DwarfCfa<AddressType>::GetOperandString(uint8_t operand, uint64_t value,
- uint64_t* cur_pc) {
- std::string string;
- switch (operand) {
- case DwarfCfaInfo::DWARF_DISPLAY_REGISTER:
- string = " register(" + std::to_string(value) + ")";
- break;
- case DwarfCfaInfo::DWARF_DISPLAY_SIGNED_NUMBER:
- string += " " + std::to_string(static_cast<SignedType>(value));
- break;
- case DwarfCfaInfo::DWARF_DISPLAY_ADVANCE_LOC:
- *cur_pc += value;
- FALLTHROUGH_INTENDED;
- // Fall through to log the value.
- case DwarfCfaInfo::DWARF_DISPLAY_NUMBER:
- string += " " + std::to_string(value);
- break;
- case DwarfCfaInfo::DWARF_DISPLAY_SET_LOC:
- *cur_pc = value;
- FALLTHROUGH_INTENDED;
- // Fall through to log the value.
- case DwarfCfaInfo::DWARF_DISPLAY_ADDRESS:
- if (std::is_same<AddressType, uint32_t>::value) {
- string += android::base::StringPrintf(" 0x%" PRIx32, static_cast<uint32_t>(value));
- } else {
- string += android::base::StringPrintf(" 0x%" PRIx64, static_cast<uint64_t>(value));
- }
- break;
- default:
- string = " unknown";
- }
- return string;
-}
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::LogOffsetRegisterString(uint32_t indent, uint64_t cfa_offset,
- uint8_t reg) {
- uint64_t offset;
- if (!memory_->ReadULEB128(&offset)) {
- return false;
- }
- uint64_t end_offset = memory_->cur_offset();
- memory_->set_cur_offset(cfa_offset);
-
- std::string raw_data = "Raw Data:";
- for (uint64_t i = cfa_offset; i < end_offset; i++) {
- uint8_t value;
- if (!memory_->ReadBytes(&value, 1)) {
- return false;
- }
- raw_data += android::base::StringPrintf(" 0x%02x", value);
- }
- log(indent, "DW_CFA_offset register(%d) %" PRId64, reg, offset);
- log(indent, "%s", raw_data.c_str());
- return true;
-}
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::LogInstruction(uint32_t indent, uint64_t cfa_offset, uint8_t op,
- uint64_t* cur_pc) {
- const auto* cfa = &DwarfCfaInfo::kTable[op];
- if (cfa->name[0] == '\0' || (arch_ != ARCH_ARM64 && op == 0x2d)) {
- if (op == 0x2d) {
- log(indent, "Illegal (Only valid on aarch64)");
- } else {
- log(indent, "Illegal");
- }
- log(indent, "Raw Data: 0x%02x", op);
- return true;
- }
-
- std::string log_string(cfa->name);
- std::vector<std::string> expression_lines;
- for (size_t i = 0; i < cfa->num_operands; i++) {
- if (cfa->operands[i] == DW_EH_PE_block) {
- // This is a Dwarf Expression.
- uint64_t end_offset;
- if (!memory_->ReadULEB128(&end_offset)) {
- return false;
- }
- log_string += " " + std::to_string(end_offset);
- end_offset += memory_->cur_offset();
-
- DwarfOp<AddressType> op(memory_, nullptr);
- op.GetLogInfo(memory_->cur_offset(), end_offset, &expression_lines);
- memory_->set_cur_offset(end_offset);
- } else {
- uint64_t value;
- if (!memory_->ReadEncodedValue<AddressType>(cfa->operands[i], &value)) {
- return false;
- }
- log_string += GetOperandString(cfa->display_operands[i], value, cur_pc);
- }
- }
- log(indent, "%s", log_string.c_str());
-
- // Get the raw bytes of the data.
- uint64_t end_offset = memory_->cur_offset();
- memory_->set_cur_offset(cfa_offset);
- std::string raw_data("Raw Data:");
- for (uint64_t i = 0; i < end_offset - cfa_offset; i++) {
- uint8_t value;
- if (!memory_->ReadBytes(&value, 1)) {
- return false;
- }
-
- // Only show 10 raw bytes per line.
- if ((i % 10) == 0 && i != 0) {
- log(indent, "%s", raw_data.c_str());
- raw_data.clear();
- }
- if (raw_data.empty()) {
- raw_data = "Raw Data:";
- }
- raw_data += android::base::StringPrintf(" 0x%02x", value);
- }
- if (!raw_data.empty()) {
- log(indent, "%s", raw_data.c_str());
- }
-
- // Log any of the expression data.
- for (const auto& line : expression_lines) {
- log(indent + 1, "%s", line.c_str());
- }
- return true;
-}
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::Log(uint32_t indent, uint64_t pc, uint64_t start_offset,
- uint64_t end_offset) {
- memory_->set_cur_offset(start_offset);
- uint64_t cfa_offset;
- uint64_t cur_pc = fde_->pc_start;
- uint64_t old_pc = cur_pc;
- while ((cfa_offset = memory_->cur_offset()) < end_offset && cur_pc <= pc) {
- // Read the cfa information.
- uint8_t cfa_value;
- if (!memory_->ReadBytes(&cfa_value, 1)) {
- return false;
- }
-
- // Check the 2 high bits.
- uint8_t cfa_low = cfa_value & 0x3f;
- switch (cfa_value >> 6) {
- case 0:
- if (!LogInstruction(indent, cfa_offset, cfa_low, &cur_pc)) {
- return false;
- }
- break;
- case 1:
- log(indent, "DW_CFA_advance_loc %d", cfa_low);
- log(indent, "Raw Data: 0x%02x", cfa_value);
- cur_pc += cfa_low * fde_->cie->code_alignment_factor;
- break;
- case 2:
- if (!LogOffsetRegisterString(indent, cfa_offset, cfa_low)) {
- return false;
- }
- break;
- case 3:
- log(indent, "DW_CFA_restore register(%d)", cfa_low);
- log(indent, "Raw Data: 0x%02x", cfa_value);
- break;
- }
- if (cur_pc != old_pc) {
- log(0, "");
- log(indent, "PC 0x%" PRIx64, cur_pc);
- }
- old_pc = cur_pc;
- }
- return true;
-}
-
-// Static data.
-template <typename AddressType>
-bool DwarfCfa<AddressType>::cfa_nop(dwarf_loc_regs_t*) {
- return true;
-}
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::cfa_set_loc(dwarf_loc_regs_t*) {
- AddressType cur_pc = cur_pc_;
- AddressType new_pc = operands_[0];
- if (new_pc < cur_pc) {
- if (std::is_same<AddressType, uint32_t>::value) {
- log(0, "Warning: PC is moving backwards: old 0x%" PRIx32 " new 0x%" PRIx32, cur_pc, new_pc);
- } else {
- log(0, "Warning: PC is moving backwards: old 0x%" PRIx64 " new 0x%" PRIx64, cur_pc, new_pc);
- }
- }
- cur_pc_ = new_pc;
- return true;
-}
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::cfa_advance_loc(dwarf_loc_regs_t*) {
- cur_pc_ += operands_[0] * fde_->cie->code_alignment_factor;
- return true;
-}
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::cfa_offset(dwarf_loc_regs_t* loc_regs) {
- AddressType reg = operands_[0];
- (*loc_regs)[reg] = {.type = DWARF_LOCATION_OFFSET, .values = {operands_[1]}};
- return true;
-}
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::cfa_restore(dwarf_loc_regs_t* loc_regs) {
- AddressType reg = operands_[0];
- if (cie_loc_regs_ == nullptr) {
- log(0, "restore while processing cie");
- last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
- return false;
- }
- auto reg_entry = cie_loc_regs_->find(reg);
- if (reg_entry == cie_loc_regs_->end()) {
- loc_regs->erase(reg);
- } else {
- (*loc_regs)[reg] = reg_entry->second;
- }
- return true;
-}
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::cfa_undefined(dwarf_loc_regs_t* loc_regs) {
- AddressType reg = operands_[0];
- (*loc_regs)[reg] = {.type = DWARF_LOCATION_UNDEFINED};
- return true;
-}
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::cfa_same_value(dwarf_loc_regs_t* loc_regs) {
- AddressType reg = operands_[0];
- loc_regs->erase(reg);
- return true;
-}
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::cfa_register(dwarf_loc_regs_t* loc_regs) {
- AddressType reg = operands_[0];
- AddressType reg_dst = operands_[1];
- (*loc_regs)[reg] = {.type = DWARF_LOCATION_REGISTER, .values = {reg_dst}};
- return true;
-}
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::cfa_remember_state(dwarf_loc_regs_t* loc_regs) {
- loc_reg_state_.push(*loc_regs);
- return true;
-}
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::cfa_restore_state(dwarf_loc_regs_t* loc_regs) {
- if (loc_reg_state_.size() == 0) {
- log(0, "Warning: Attempt to restore without remember.");
- return true;
- }
- *loc_regs = loc_reg_state_.top();
- loc_reg_state_.pop();
- return true;
-}
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::cfa_def_cfa(dwarf_loc_regs_t* loc_regs) {
- (*loc_regs)[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {operands_[0], operands_[1]}};
- return true;
-}
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::cfa_def_cfa_register(dwarf_loc_regs_t* loc_regs) {
- auto cfa_location = loc_regs->find(CFA_REG);
- if (cfa_location == loc_regs->end() || cfa_location->second.type != DWARF_LOCATION_REGISTER) {
- log(0, "Attempt to set new register, but cfa is not already set to a register.");
- last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
- return false;
- }
-
- cfa_location->second.values[0] = operands_[0];
- return true;
-}
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::cfa_def_cfa_offset(dwarf_loc_regs_t* loc_regs) {
- // Changing the offset if this is not a register is illegal.
- auto cfa_location = loc_regs->find(CFA_REG);
- if (cfa_location == loc_regs->end() || cfa_location->second.type != DWARF_LOCATION_REGISTER) {
- log(0, "Attempt to set offset, but cfa is not set to a register.");
- last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
- return false;
- }
- cfa_location->second.values[1] = operands_[0];
- return true;
-}
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::cfa_def_cfa_expression(dwarf_loc_regs_t* loc_regs) {
- // There is only one type of expression for CFA evaluation and the DWARF
- // specification is unclear whether it returns the address or the
- // dereferenced value. GDB expects the value, so will we.
- (*loc_regs)[CFA_REG] = {.type = DWARF_LOCATION_VAL_EXPRESSION,
- .values = {operands_[0], memory_->cur_offset()}};
- return true;
-}
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::cfa_expression(dwarf_loc_regs_t* loc_regs) {
- AddressType reg = operands_[0];
- (*loc_regs)[reg] = {.type = DWARF_LOCATION_EXPRESSION,
- .values = {operands_[1], memory_->cur_offset()}};
- return true;
-}
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::cfa_offset_extended_sf(dwarf_loc_regs_t* loc_regs) {
- AddressType reg = operands_[0];
- SignedType value = static_cast<SignedType>(operands_[1]) * fde_->cie->data_alignment_factor;
- (*loc_regs)[reg] = {.type = DWARF_LOCATION_OFFSET, .values = {static_cast<uint64_t>(value)}};
- return true;
-}
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::cfa_def_cfa_sf(dwarf_loc_regs_t* loc_regs) {
- SignedType offset = static_cast<SignedType>(operands_[1]) * fde_->cie->data_alignment_factor;
- (*loc_regs)[CFA_REG] = {.type = DWARF_LOCATION_REGISTER,
- .values = {operands_[0], static_cast<uint64_t>(offset)}};
- return true;
-}
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::cfa_def_cfa_offset_sf(dwarf_loc_regs_t* loc_regs) {
- // Changing the offset if this is not a register is illegal.
- auto cfa_location = loc_regs->find(CFA_REG);
- if (cfa_location == loc_regs->end() || cfa_location->second.type != DWARF_LOCATION_REGISTER) {
- log(0, "Attempt to set offset, but cfa is not set to a register.");
- last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
- return false;
- }
- SignedType offset = static_cast<SignedType>(operands_[0]) * fde_->cie->data_alignment_factor;
- cfa_location->second.values[1] = static_cast<uint64_t>(offset);
- return true;
-}
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::cfa_val_offset(dwarf_loc_regs_t* loc_regs) {
- AddressType reg = operands_[0];
- SignedType offset = static_cast<SignedType>(operands_[1]) * fde_->cie->data_alignment_factor;
- (*loc_regs)[reg] = {.type = DWARF_LOCATION_VAL_OFFSET, .values = {static_cast<uint64_t>(offset)}};
- return true;
-}
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::cfa_val_offset_sf(dwarf_loc_regs_t* loc_regs) {
- AddressType reg = operands_[0];
- SignedType offset = static_cast<SignedType>(operands_[1]) * fde_->cie->data_alignment_factor;
- (*loc_regs)[reg] = {.type = DWARF_LOCATION_VAL_OFFSET, .values = {static_cast<uint64_t>(offset)}};
- return true;
-}
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::cfa_val_expression(dwarf_loc_regs_t* loc_regs) {
- AddressType reg = operands_[0];
- (*loc_regs)[reg] = {.type = DWARF_LOCATION_VAL_EXPRESSION,
- .values = {operands_[1], memory_->cur_offset()}};
- return true;
-}
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::cfa_gnu_negative_offset_extended(dwarf_loc_regs_t* loc_regs) {
- AddressType reg = operands_[0];
- SignedType offset = -static_cast<SignedType>(operands_[1]);
- (*loc_regs)[reg] = {.type = DWARF_LOCATION_OFFSET, .values = {static_cast<uint64_t>(offset)}};
- return true;
-}
-
-template <typename AddressType>
-bool DwarfCfa<AddressType>::cfa_aarch64_negate_ra_state(dwarf_loc_regs_t* loc_regs) {
- // Only supported on aarch64.
- if (arch_ != ARCH_ARM64) {
- last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
- return false;
- }
-
- auto cfa_location = loc_regs->find(Arm64Reg::ARM64_PREG_RA_SIGN_STATE);
- if (cfa_location == loc_regs->end()) {
- (*loc_regs)[Arm64Reg::ARM64_PREG_RA_SIGN_STATE] = {.type = DWARF_LOCATION_PSEUDO_REGISTER,
- .values = {1}};
- } else {
- cfa_location->second.values[0] ^= 1;
- }
- return true;
-}
-
-const DwarfCfaInfo::Info DwarfCfaInfo::kTable[64] = {
- {
- // 0x00 DW_CFA_nop
- "DW_CFA_nop",
- 2,
- 0,
- {},
- {},
- },
- {
- "DW_CFA_set_loc", // 0x01 DW_CFA_set_loc
- 2,
- 1,
- {DW_EH_PE_absptr},
- {DWARF_DISPLAY_SET_LOC},
- },
- {
- "DW_CFA_advance_loc1", // 0x02 DW_CFA_advance_loc1
- 2,
- 1,
- {DW_EH_PE_udata1},
- {DWARF_DISPLAY_ADVANCE_LOC},
- },
- {
- "DW_CFA_advance_loc2", // 0x03 DW_CFA_advance_loc2
- 2,
- 1,
- {DW_EH_PE_udata2},
- {DWARF_DISPLAY_ADVANCE_LOC},
- },
- {
- "DW_CFA_advance_loc4", // 0x04 DW_CFA_advance_loc4
- 2,
- 1,
- {DW_EH_PE_udata4},
- {DWARF_DISPLAY_ADVANCE_LOC},
- },
- {
- "DW_CFA_offset_extended", // 0x05 DW_CFA_offset_extended
- 2,
- 2,
- {DW_EH_PE_uleb128, DW_EH_PE_uleb128},
- {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_NUMBER},
- },
- {
- "DW_CFA_restore_extended", // 0x06 DW_CFA_restore_extended
- 2,
- 1,
- {DW_EH_PE_uleb128},
- {DWARF_DISPLAY_REGISTER},
- },
- {
- "DW_CFA_undefined", // 0x07 DW_CFA_undefined
- 2,
- 1,
- {DW_EH_PE_uleb128},
- {DWARF_DISPLAY_REGISTER},
- },
- {
- "DW_CFA_same_value", // 0x08 DW_CFA_same_value
- 2,
- 1,
- {DW_EH_PE_uleb128},
- {DWARF_DISPLAY_REGISTER},
- },
- {
- "DW_CFA_register", // 0x09 DW_CFA_register
- 2,
- 2,
- {DW_EH_PE_uleb128, DW_EH_PE_uleb128},
- {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_REGISTER},
- },
- {
- "DW_CFA_remember_state", // 0x0a DW_CFA_remember_state
- 2,
- 0,
- {},
- {},
- },
- {
- "DW_CFA_restore_state", // 0x0b DW_CFA_restore_state
- 2,
- 0,
- {},
- {},
- },
- {
- "DW_CFA_def_cfa", // 0x0c DW_CFA_def_cfa
- 2,
- 2,
- {DW_EH_PE_uleb128, DW_EH_PE_uleb128},
- {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_NUMBER},
- },
- {
- "DW_CFA_def_cfa_register", // 0x0d DW_CFA_def_cfa_register
- 2,
- 1,
- {DW_EH_PE_uleb128},
- {DWARF_DISPLAY_REGISTER},
- },
- {
- "DW_CFA_def_cfa_offset", // 0x0e DW_CFA_def_cfa_offset
- 2,
- 1,
- {DW_EH_PE_uleb128},
- {DWARF_DISPLAY_NUMBER},
- },
- {
- "DW_CFA_def_cfa_expression", // 0x0f DW_CFA_def_cfa_expression
- 2,
- 1,
- {DW_EH_PE_block},
- {DWARF_DISPLAY_EVAL_BLOCK},
- },
- {
- "DW_CFA_expression", // 0x10 DW_CFA_expression
- 2,
- 2,
- {DW_EH_PE_uleb128, DW_EH_PE_block},
- {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_EVAL_BLOCK},
- },
- {
- "DW_CFA_offset_extended_sf", // 0x11 DW_CFA_offset_extend_sf
- 2,
- 2,
- {DW_EH_PE_uleb128, DW_EH_PE_sleb128},
- {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_SIGNED_NUMBER},
- },
- {
- "DW_CFA_def_cfa_sf", // 0x12 DW_CFA_def_cfa_sf
- 2,
- 2,
- {DW_EH_PE_uleb128, DW_EH_PE_sleb128},
- {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_SIGNED_NUMBER},
- },
- {
- "DW_CFA_def_cfa_offset_sf", // 0x13 DW_CFA_def_cfa_offset_sf
- 2,
- 1,
- {DW_EH_PE_sleb128},
- {DWARF_DISPLAY_SIGNED_NUMBER},
- },
- {
- "DW_CFA_val_offset", // 0x14 DW_CFA_val_offset
- 2,
- 2,
- {DW_EH_PE_uleb128, DW_EH_PE_uleb128},
- {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_NUMBER},
- },
- {
- "DW_CFA_val_offset_sf", // 0x15 DW_CFA_val_offset_sf
- 2,
- 2,
- {DW_EH_PE_uleb128, DW_EH_PE_sleb128},
- {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_SIGNED_NUMBER},
- },
- {
- "DW_CFA_val_expression", // 0x16 DW_CFA_val_expression
- 2,
- 2,
- {DW_EH_PE_uleb128, DW_EH_PE_block},
- {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_EVAL_BLOCK},
- },
- {"", 0, 0, {}, {}}, // 0x17 illegal cfa
- {"", 0, 0, {}, {}}, // 0x18 illegal cfa
- {"", 0, 0, {}, {}}, // 0x19 illegal cfa
- {"", 0, 0, {}, {}}, // 0x1a illegal cfa
- {"", 0, 0, {}, {}}, // 0x1b illegal cfa
- {"", 0, 0, {}, {}}, // 0x1c DW_CFA_lo_user (Treat as illegal)
- {"", 0, 0, {}, {}}, // 0x1d illegal cfa
- {"", 0, 0, {}, {}}, // 0x1e illegal cfa
- {"", 0, 0, {}, {}}, // 0x1f illegal cfa
- {"", 0, 0, {}, {}}, // 0x20 illegal cfa
- {"", 0, 0, {}, {}}, // 0x21 illegal cfa
- {"", 0, 0, {}, {}}, // 0x22 illegal cfa
- {"", 0, 0, {}, {}}, // 0x23 illegal cfa
- {"", 0, 0, {}, {}}, // 0x24 illegal cfa
- {"", 0, 0, {}, {}}, // 0x25 illegal cfa
- {"", 0, 0, {}, {}}, // 0x26 illegal cfa
- {"", 0, 0, {}, {}}, // 0x27 illegal cfa
- {"", 0, 0, {}, {}}, // 0x28 illegal cfa
- {"", 0, 0, {}, {}}, // 0x29 illegal cfa
- {"", 0, 0, {}, {}}, // 0x2a illegal cfa
- {"", 0, 0, {}, {}}, // 0x2b illegal cfa
- {"", 0, 0, {}, {}}, // 0x2c illegal cfa
- {
- "DW_CFA_AARCH64_negate_ra_state", // 0x2d DW_CFA_AARCH64_negate_ra_state
- 3,
- 0,
- {},
- {},
- },
- {
- "DW_CFA_GNU_args_size", // 0x2e DW_CFA_GNU_args_size
- 2,
- 1,
- {DW_EH_PE_uleb128},
- {DWARF_DISPLAY_NUMBER},
- },
- {
- "DW_CFA_GNU_negative_offset_extended", // 0x2f DW_CFA_GNU_negative_offset_extended
- 2,
- 2,
- {DW_EH_PE_uleb128, DW_EH_PE_uleb128},
- {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_NUMBER},
- },
- {"", 0, 0, {}, {}}, // 0x31 illegal cfa
- {"", 0, 0, {}, {}}, // 0x32 illegal cfa
- {"", 0, 0, {}, {}}, // 0x33 illegal cfa
- {"", 0, 0, {}, {}}, // 0x34 illegal cfa
- {"", 0, 0, {}, {}}, // 0x35 illegal cfa
- {"", 0, 0, {}, {}}, // 0x36 illegal cfa
- {"", 0, 0, {}, {}}, // 0x37 illegal cfa
- {"", 0, 0, {}, {}}, // 0x38 illegal cfa
- {"", 0, 0, {}, {}}, // 0x39 illegal cfa
- {"", 0, 0, {}, {}}, // 0x3a illegal cfa
- {"", 0, 0, {}, {}}, // 0x3b illegal cfa
- {"", 0, 0, {}, {}}, // 0x3c illegal cfa
- {"", 0, 0, {}, {}}, // 0x3d illegal cfa
- {"", 0, 0, {}, {}}, // 0x3e illegal cfa
- {"", 0, 0, {}, {}}, // 0x3f DW_CFA_hi_user (Treat as illegal)
-};
-
-// Explicitly instantiate DwarfCfa.
-template class DwarfCfa<uint32_t>;
-template class DwarfCfa<uint64_t>;
-
-} // namespace unwindstack
diff --git a/libunwindstack/DwarfCfa.h b/libunwindstack/DwarfCfa.h
deleted file mode 100644
index d627e15..0000000
--- a/libunwindstack/DwarfCfa.h
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_DWARF_CFA_H
-#define _LIBUNWINDSTACK_DWARF_CFA_H
-
-#include <stdint.h>
-
-#include <stack>
-#include <string>
-#include <type_traits>
-#include <vector>
-
-#include <unwindstack/DwarfError.h>
-#include <unwindstack/DwarfLocation.h>
-#include <unwindstack/DwarfMemory.h>
-#include <unwindstack/DwarfStructs.h>
-
-namespace unwindstack {
-
-// Forward declarations.
-enum ArchEnum : uint8_t;
-
-// DWARF Standard home: http://dwarfstd.org/
-// This code is based on DWARF 4: http://http://dwarfstd.org/doc/DWARF4.pdf
-// See section 6.4.2.1 for a description of the DW_CFA_xxx values.
-
-class DwarfCfaInfo {
- public:
- enum DisplayType : uint8_t {
- DWARF_DISPLAY_NONE = 0,
- DWARF_DISPLAY_REGISTER,
- DWARF_DISPLAY_NUMBER,
- DWARF_DISPLAY_SIGNED_NUMBER,
- DWARF_DISPLAY_EVAL_BLOCK,
- DWARF_DISPLAY_ADDRESS,
- DWARF_DISPLAY_SET_LOC,
- DWARF_DISPLAY_ADVANCE_LOC,
- };
-
- struct Info {
- // It may seem cleaner to just change the type of 'name' to 'const char *'.
- // However, having a pointer here would require relocation at runtime,
- // causing 'kTable' to be placed in data.rel.ro section instead of rodata
- // section, adding memory pressure to the system. Note that this is only
- // safe because this is only used in C++ code. C++ standard, unlike C
- // standard, mandates the array size to be large enough to hold the NULL
- // terminator when initialized with a string literal.
- const char name[36];
- uint8_t supported_version;
- uint8_t num_operands;
- uint8_t operands[2];
- uint8_t display_operands[2];
- };
-
- const static Info kTable[64];
-};
-
-template <typename AddressType>
-class DwarfCfa {
- // Signed version of AddressType
- typedef typename std::make_signed<AddressType>::type SignedType;
-
- public:
- DwarfCfa(DwarfMemory* memory, const DwarfFde* fde, ArchEnum arch)
- : memory_(memory), fde_(fde), arch_(arch) {}
- virtual ~DwarfCfa() = default;
-
- bool GetLocationInfo(uint64_t pc, uint64_t start_offset, uint64_t end_offset,
- dwarf_loc_regs_t* loc_regs);
-
- bool Log(uint32_t indent, uint64_t pc, uint64_t start_offset, uint64_t end_offset);
-
- const DwarfErrorData& last_error() { return last_error_; }
- DwarfErrorCode LastErrorCode() { return last_error_.code; }
- uint64_t LastErrorAddress() { return last_error_.address; }
-
- AddressType cur_pc() { return cur_pc_; }
-
- void set_cie_loc_regs(const dwarf_loc_regs_t* cie_loc_regs) { cie_loc_regs_ = cie_loc_regs; }
-
- protected:
- std::string GetOperandString(uint8_t operand, uint64_t value, uint64_t* cur_pc);
-
- bool LogOffsetRegisterString(uint32_t indent, uint64_t cfa_offset, uint8_t reg);
-
- bool LogInstruction(uint32_t indent, uint64_t cfa_offset, uint8_t op, uint64_t* cur_pc);
-
- private:
- DwarfErrorData last_error_;
- DwarfMemory* memory_;
- const DwarfFde* fde_;
- ArchEnum arch_;
-
- AddressType cur_pc_;
- const dwarf_loc_regs_t* cie_loc_regs_ = nullptr;
- std::vector<AddressType> operands_;
- std::stack<dwarf_loc_regs_t> loc_reg_state_;
-
- // CFA processing functions.
- bool cfa_nop(dwarf_loc_regs_t*);
- bool cfa_set_loc(dwarf_loc_regs_t*);
- bool cfa_advance_loc(dwarf_loc_regs_t*);
- bool cfa_offset(dwarf_loc_regs_t*);
- bool cfa_restore(dwarf_loc_regs_t*);
- bool cfa_undefined(dwarf_loc_regs_t*);
- bool cfa_same_value(dwarf_loc_regs_t*);
- bool cfa_register(dwarf_loc_regs_t*);
- bool cfa_remember_state(dwarf_loc_regs_t*);
- bool cfa_restore_state(dwarf_loc_regs_t*);
- bool cfa_def_cfa(dwarf_loc_regs_t*);
- bool cfa_def_cfa_register(dwarf_loc_regs_t*);
- bool cfa_def_cfa_offset(dwarf_loc_regs_t*);
- bool cfa_def_cfa_expression(dwarf_loc_regs_t*);
- bool cfa_expression(dwarf_loc_regs_t*);
- bool cfa_offset_extended_sf(dwarf_loc_regs_t*);
- bool cfa_def_cfa_sf(dwarf_loc_regs_t*);
- bool cfa_def_cfa_offset_sf(dwarf_loc_regs_t*);
- bool cfa_val_offset(dwarf_loc_regs_t*);
- bool cfa_val_offset_sf(dwarf_loc_regs_t*);
- bool cfa_val_expression(dwarf_loc_regs_t*);
- bool cfa_gnu_negative_offset_extended(dwarf_loc_regs_t*);
- bool cfa_aarch64_negate_ra_state(dwarf_loc_regs_t*);
-
- using process_func = bool (DwarfCfa::*)(dwarf_loc_regs_t*);
- constexpr static process_func kCallbackTable[64] = {
- // 0x00 DW_CFA_nop
- &DwarfCfa::cfa_nop,
- // 0x01 DW_CFA_set_loc
- &DwarfCfa::cfa_set_loc,
- // 0x02 DW_CFA_advance_loc1
- &DwarfCfa::cfa_advance_loc,
- // 0x03 DW_CFA_advance_loc2
- &DwarfCfa::cfa_advance_loc,
- // 0x04 DW_CFA_advance_loc4
- &DwarfCfa::cfa_advance_loc,
- // 0x05 DW_CFA_offset_extended
- &DwarfCfa::cfa_offset,
- // 0x06 DW_CFA_restore_extended
- &DwarfCfa::cfa_restore,
- // 0x07 DW_CFA_undefined
- &DwarfCfa::cfa_undefined,
- // 0x08 DW_CFA_same_value
- &DwarfCfa::cfa_same_value,
- // 0x09 DW_CFA_register
- &DwarfCfa::cfa_register,
- // 0x0a DW_CFA_remember_state
- &DwarfCfa::cfa_remember_state,
- // 0x0b DW_CFA_restore_state
- &DwarfCfa::cfa_restore_state,
- // 0x0c DW_CFA_def_cfa
- &DwarfCfa::cfa_def_cfa,
- // 0x0d DW_CFA_def_cfa_register
- &DwarfCfa::cfa_def_cfa_register,
- // 0x0e DW_CFA_def_cfa_offset
- &DwarfCfa::cfa_def_cfa_offset,
- // 0x0f DW_CFA_def_cfa_expression
- &DwarfCfa::cfa_def_cfa_expression,
- // 0x10 DW_CFA_expression
- &DwarfCfa::cfa_expression,
- // 0x11 DW_CFA_offset_extended_sf
- &DwarfCfa::cfa_offset_extended_sf,
- // 0x12 DW_CFA_def_cfa_sf
- &DwarfCfa::cfa_def_cfa_sf,
- // 0x13 DW_CFA_def_cfa_offset_sf
- &DwarfCfa::cfa_def_cfa_offset_sf,
- // 0x14 DW_CFA_val_offset
- &DwarfCfa::cfa_val_offset,
- // 0x15 DW_CFA_val_offset_sf
- &DwarfCfa::cfa_val_offset_sf,
- // 0x16 DW_CFA_val_expression
- &DwarfCfa::cfa_val_expression,
- // 0x17 illegal cfa
- nullptr,
- // 0x18 illegal cfa
- nullptr,
- // 0x19 illegal cfa
- nullptr,
- // 0x1a illegal cfa
- nullptr,
- // 0x1b illegal cfa
- nullptr,
- // 0x1c DW_CFA_lo_user (Treat this as illegal)
- nullptr,
- // 0x1d illegal cfa
- nullptr,
- // 0x1e illegal cfa
- nullptr,
- // 0x1f illegal cfa
- nullptr,
- // 0x20 illegal cfa
- nullptr,
- // 0x21 illegal cfa
- nullptr,
- // 0x22 illegal cfa
- nullptr,
- // 0x23 illegal cfa
- nullptr,
- // 0x24 illegal cfa
- nullptr,
- // 0x25 illegal cfa
- nullptr,
- // 0x26 illegal cfa
- nullptr,
- // 0x27 illegal cfa
- nullptr,
- // 0x28 illegal cfa
- nullptr,
- // 0x29 illegal cfa
- nullptr,
- // 0x2a illegal cfa
- nullptr,
- // 0x2b illegal cfa
- nullptr,
- // 0x2c illegal cfa
- nullptr,
- // 0x2d DW_CFA_AARCH64_negate_ra_state (aarch64 only)
- // DW_CFA_GNU_window_save on other architectures.
- &DwarfCfa::cfa_aarch64_negate_ra_state,
- // 0x2e DW_CFA_GNU_args_size
- &DwarfCfa::cfa_nop,
- // 0x2f DW_CFA_GNU_negative_offset_extended
- &DwarfCfa::cfa_gnu_negative_offset_extended,
- // 0x30 illegal cfa
- nullptr,
- // 0x31 illegal cfa
- nullptr,
- // 0x32 illegal cfa
- nullptr,
- // 0x33 illegal cfa
- nullptr,
- // 0x34 illegal cfa
- nullptr,
- // 0x35 illegal cfa
- nullptr,
- // 0x36 illegal cfa
- nullptr,
- // 0x37 illegal cfa
- nullptr,
- // 0x38 illegal cfa
- nullptr,
- // 0x39 illegal cfa
- nullptr,
- // 0x3a illegal cfa
- nullptr,
- // 0x3b illegal cfa
- nullptr,
- // 0x3c illegal cfa
- nullptr,
- // 0x3d illegal cfa
- nullptr,
- // 0x3e illegal cfa
- nullptr,
- // 0x3f DW_CFA_hi_user (Treat this as illegal)
- nullptr,
- };
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_DWARF_CFA_H
diff --git a/libunwindstack/DwarfDebugFrame.h b/libunwindstack/DwarfDebugFrame.h
deleted file mode 100644
index 635cefd..0000000
--- a/libunwindstack/DwarfDebugFrame.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef _LIBUNWINDSTACK_DWARF_DEBUG_FRAME_H
-#define _LIBUNWINDSTACK_DWARF_DEBUG_FRAME_H
-
-#include <stdint.h>
-
-#include <vector>
-
-#include <unwindstack/DwarfSection.h>
-
-namespace unwindstack {
-
-template <typename AddressType>
-class DwarfDebugFrame : public DwarfSectionImpl<AddressType> {
- public:
- DwarfDebugFrame(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {
- this->cie32_value_ = static_cast<uint32_t>(-1);
- this->cie64_value_ = static_cast<uint64_t>(-1);
- }
- virtual ~DwarfDebugFrame() = default;
-
- uint64_t GetCieOffsetFromFde32(uint32_t pointer) override {
- return this->entries_offset_ + pointer;
- }
-
- uint64_t GetCieOffsetFromFde64(uint64_t pointer) override {
- return this->entries_offset_ + pointer;
- }
-
- uint64_t AdjustPcFromFde(uint64_t pc) override { return pc; }
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_DWARF_DEBUG_FRAME_H
diff --git a/libunwindstack/DwarfEhFrame.h b/libunwindstack/DwarfEhFrame.h
deleted file mode 100644
index 7a41e45..0000000
--- a/libunwindstack/DwarfEhFrame.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_DWARF_EH_FRAME_H
-#define _LIBUNWINDSTACK_DWARF_EH_FRAME_H
-
-#include <stdint.h>
-
-#include <unwindstack/DwarfSection.h>
-#include <unwindstack/Memory.h>
-
-namespace unwindstack {
-
-template <typename AddressType>
-class DwarfEhFrame : public DwarfSectionImpl<AddressType> {
- public:
- DwarfEhFrame(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {}
- virtual ~DwarfEhFrame() = default;
-
- uint64_t GetCieOffsetFromFde32(uint32_t pointer) override {
- return this->memory_.cur_offset() - pointer - 4;
- }
-
- uint64_t GetCieOffsetFromFde64(uint64_t pointer) override {
- return this->memory_.cur_offset() - pointer - 8;
- }
-
- uint64_t AdjustPcFromFde(uint64_t pc) override {
- // The eh_frame uses relative pcs.
- return pc + this->memory_.cur_offset() - 4;
- }
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_DWARF_EH_FRAME_H
diff --git a/libunwindstack/DwarfEhFrameWithHdr.cpp b/libunwindstack/DwarfEhFrameWithHdr.cpp
deleted file mode 100644
index 1358e51..0000000
--- a/libunwindstack/DwarfEhFrameWithHdr.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2017 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 <stdint.h>
-
-#include <unwindstack/DwarfError.h>
-#include <unwindstack/DwarfStructs.h>
-#include <unwindstack/Memory.h>
-
-#include "Check.h"
-#include "DwarfEhFrameWithHdr.h"
-#include "DwarfEncoding.h"
-
-namespace unwindstack {
-
-static inline bool IsEncodingRelative(uint8_t encoding) {
- encoding >>= 4;
- return encoding > 0 && encoding <= DW_EH_PE_funcrel;
-}
-
-template <typename AddressType>
-bool DwarfEhFrameWithHdr<AddressType>::EhFrameInit(uint64_t offset, uint64_t size,
- int64_t section_bias) {
- return DwarfSectionImpl<AddressType>::Init(offset, size, section_bias);
-}
-
-template <typename AddressType>
-bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t, int64_t section_bias) {
- memory_.clear_func_offset();
- memory_.clear_text_offset();
- memory_.set_data_offset(offset);
- memory_.set_cur_offset(offset);
-
- hdr_section_bias_ = section_bias;
-
- // Read the first four bytes all at once.
- uint8_t data[4];
- if (!memory_.ReadBytes(data, 4)) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
-
- version_ = data[0];
- if (version_ != 1) {
- // Unknown version.
- last_error_.code = DWARF_ERROR_UNSUPPORTED_VERSION;
- return false;
- }
-
- uint8_t ptr_encoding = data[1];
- uint8_t fde_count_encoding = data[2];
- table_encoding_ = data[3];
- table_entry_size_ = memory_.template GetEncodedSize<AddressType>(table_encoding_);
-
- // If we can't perform a binary search on the entries, it's not worth
- // using this object. The calling code will fall back to the DwarfEhFrame
- // object in this case.
- if (table_entry_size_ == 0) {
- last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
- return false;
- }
-
- memory_.set_pc_offset(memory_.cur_offset());
- uint64_t ptr_offset;
- if (!memory_.template ReadEncodedValue<AddressType>(ptr_encoding, &ptr_offset)) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
-
- memory_.set_pc_offset(memory_.cur_offset());
- if (!memory_.template ReadEncodedValue<AddressType>(fde_count_encoding, &fde_count_)) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
-
- if (fde_count_ == 0) {
- last_error_.code = DWARF_ERROR_NO_FDES;
- return false;
- }
-
- hdr_entries_offset_ = memory_.cur_offset();
- hdr_entries_data_offset_ = offset;
-
- return true;
-}
-
-template <typename AddressType>
-const DwarfFde* DwarfEhFrameWithHdr<AddressType>::GetFdeFromPc(uint64_t pc) {
- uint64_t fde_offset;
- if (!GetFdeOffsetFromPc(pc, &fde_offset)) {
- return nullptr;
- }
- const DwarfFde* fde = this->GetFdeFromOffset(fde_offset);
- if (fde == nullptr) {
- return nullptr;
- }
-
- // There is a possibility that this entry points to a zero length FDE
- // due to a bug. If this happens, try and find the non-zero length FDE
- // from eh_frame directly. See b/142483624.
- if (fde->pc_start == fde->pc_end) {
- fde = DwarfSectionImpl<AddressType>::GetFdeFromPc(pc);
- if (fde == nullptr) {
- return nullptr;
- }
- }
-
- // Guaranteed pc >= pc_start, need to check pc in the fde range.
- if (pc < fde->pc_end) {
- return fde;
- }
- last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
- return nullptr;
-}
-
-template <typename AddressType>
-const typename DwarfEhFrameWithHdr<AddressType>::FdeInfo*
-DwarfEhFrameWithHdr<AddressType>::GetFdeInfoFromIndex(size_t index) {
- auto entry = fde_info_.find(index);
- if (entry != fde_info_.end()) {
- return &fde_info_[index];
- }
- FdeInfo* info = &fde_info_[index];
-
- memory_.set_data_offset(hdr_entries_data_offset_);
- memory_.set_cur_offset(hdr_entries_offset_ + 2 * index * table_entry_size_);
- memory_.set_pc_offset(0);
- uint64_t value;
- if (!memory_.template ReadEncodedValue<AddressType>(table_encoding_, &value) ||
- !memory_.template ReadEncodedValue<AddressType>(table_encoding_, &info->offset)) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- fde_info_.erase(index);
- return nullptr;
- }
-
- // Relative encodings require adding in the load bias.
- if (IsEncodingRelative(table_encoding_)) {
- value += hdr_section_bias_;
- }
- info->pc = value;
- return info;
-}
-
-template <typename AddressType>
-bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) {
- if (fde_count_ == 0) {
- return false;
- }
-
- size_t first = 0;
- size_t last = fde_count_;
- while (first < last) {
- size_t current = (first + last) / 2;
- const FdeInfo* info = GetFdeInfoFromIndex(current);
- if (info == nullptr) {
- return false;
- }
- if (pc == info->pc) {
- *fde_offset = info->offset;
- return true;
- }
- if (pc < info->pc) {
- last = current;
- } else {
- first = current + 1;
- }
- }
- if (last != 0) {
- const FdeInfo* info = GetFdeInfoFromIndex(last - 1);
- if (info == nullptr) {
- return false;
- }
- *fde_offset = info->offset;
- return true;
- }
- return false;
-}
-
-template <typename AddressType>
-void DwarfEhFrameWithHdr<AddressType>::GetFdes(std::vector<const DwarfFde*>* fdes) {
- for (size_t i = 0; i < fde_count_; i++) {
- const FdeInfo* info = GetFdeInfoFromIndex(i);
- if (info == nullptr) {
- break;
- }
- const DwarfFde* fde = this->GetFdeFromOffset(info->offset);
- if (fde == nullptr) {
- break;
- }
-
- // There is a possibility that this entry points to a zero length FDE
- // due to a bug. If this happens, try and find the non-zero length FDE
- // from eh_frame directly. See b/142483624.
- if (fde->pc_start == fde->pc_end) {
- const DwarfFde* fde_real = DwarfSectionImpl<AddressType>::GetFdeFromPc(fde->pc_start);
- if (fde_real != nullptr) {
- fde = fde_real;
- }
- }
- fdes->push_back(fde);
- }
-}
-
-// Explicitly instantiate DwarfEhFrameWithHdr
-template class DwarfEhFrameWithHdr<uint32_t>;
-template class DwarfEhFrameWithHdr<uint64_t>;
-
-} // namespace unwindstack
diff --git a/libunwindstack/DwarfEhFrameWithHdr.h b/libunwindstack/DwarfEhFrameWithHdr.h
deleted file mode 100644
index f7c010c..0000000
--- a/libunwindstack/DwarfEhFrameWithHdr.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_DWARF_EH_FRAME_WITH_HDR_H
-#define _LIBUNWINDSTACK_DWARF_EH_FRAME_WITH_HDR_H
-
-#include <stdint.h>
-
-#include <unordered_map>
-
-#include <unwindstack/DwarfSection.h>
-
-namespace unwindstack {
-
-// Forward declarations.
-class Memory;
-
-template <typename AddressType>
-class DwarfEhFrameWithHdr : public DwarfSectionImpl<AddressType> {
- public:
- // Add these so that the protected members of DwarfSectionImpl
- // can be accessed without needing a this->.
- using DwarfSectionImpl<AddressType>::memory_;
- using DwarfSectionImpl<AddressType>::last_error_;
-
- struct FdeInfo {
- AddressType pc;
- uint64_t offset;
- };
-
- DwarfEhFrameWithHdr(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {}
- virtual ~DwarfEhFrameWithHdr() = default;
-
- uint64_t GetCieOffsetFromFde32(uint32_t pointer) override {
- return memory_.cur_offset() - pointer - 4;
- }
-
- uint64_t GetCieOffsetFromFde64(uint64_t pointer) override {
- return memory_.cur_offset() - pointer - 8;
- }
-
- uint64_t AdjustPcFromFde(uint64_t pc) override {
- // The eh_frame uses relative pcs.
- return pc + memory_.cur_offset() - 4;
- }
-
- bool EhFrameInit(uint64_t offset, uint64_t size, int64_t section_bias);
- bool Init(uint64_t offset, uint64_t size, int64_t section_bias) override;
-
- const DwarfFde* GetFdeFromPc(uint64_t pc) override;
-
- bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset);
-
- const FdeInfo* GetFdeInfoFromIndex(size_t index);
-
- void GetFdes(std::vector<const DwarfFde*>* fdes) override;
-
- protected:
- uint8_t version_ = 0;
- uint8_t table_encoding_ = 0;
- size_t table_entry_size_ = 0;
-
- uint64_t hdr_entries_offset_ = 0;
- uint64_t hdr_entries_data_offset_ = 0;
- uint64_t hdr_section_bias_ = 0;
-
- uint64_t fde_count_ = 0;
- std::unordered_map<uint64_t, FdeInfo> fde_info_;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_DWARF_EH_FRAME_WITH_HDR_H
diff --git a/libunwindstack/DwarfEncoding.h b/libunwindstack/DwarfEncoding.h
deleted file mode 100644
index 20db222..0000000
--- a/libunwindstack/DwarfEncoding.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_DWARF_ENCODING_H
-#define _LIBUNWINDSTACK_DWARF_ENCODING_H
-
-#include <stdint.h>
-
-namespace unwindstack {
-
-enum DwarfEncoding : uint8_t {
- DW_EH_PE_omit = 0xff,
-
- DW_EH_PE_absptr = 0x00,
- DW_EH_PE_uleb128 = 0x01,
- DW_EH_PE_udata2 = 0x02,
- DW_EH_PE_udata4 = 0x03,
- DW_EH_PE_udata8 = 0x04,
- DW_EH_PE_sleb128 = 0x09,
- DW_EH_PE_sdata2 = 0x0a,
- DW_EH_PE_sdata4 = 0x0b,
- DW_EH_PE_sdata8 = 0x0c,
-
- DW_EH_PE_pcrel = 0x10,
- DW_EH_PE_textrel = 0x20,
- DW_EH_PE_datarel = 0x30,
- DW_EH_PE_funcrel = 0x40,
- DW_EH_PE_aligned = 0x50,
-
- // The following are special values used to encode CFA and OP operands.
- DW_EH_PE_udata1 = 0x0d,
- DW_EH_PE_sdata1 = 0x0e,
- DW_EH_PE_block = 0x0f,
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_DWARF_ENCODING_H
diff --git a/libunwindstack/DwarfMemory.cpp b/libunwindstack/DwarfMemory.cpp
deleted file mode 100644
index 2e388c6..0000000
--- a/libunwindstack/DwarfMemory.cpp
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Copyright (C) 2017 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 <stdint.h>
-
-#include <string>
-
-#include <unwindstack/DwarfMemory.h>
-#include <unwindstack/Memory.h>
-
-#include "Check.h"
-#include "DwarfEncoding.h"
-
-namespace unwindstack {
-
-bool DwarfMemory::ReadBytes(void* dst, size_t num_bytes) {
- if (!memory_->ReadFully(cur_offset_, dst, num_bytes)) {
- return false;
- }
- cur_offset_ += num_bytes;
- return true;
-}
-
-template <typename SignedType>
-bool DwarfMemory::ReadSigned(uint64_t* value) {
- SignedType signed_value;
- if (!ReadBytes(&signed_value, sizeof(SignedType))) {
- return false;
- }
- *value = static_cast<int64_t>(signed_value);
- return true;
-}
-
-bool DwarfMemory::ReadULEB128(uint64_t* value) {
- uint64_t cur_value = 0;
- uint64_t shift = 0;
- uint8_t byte;
- do {
- if (!ReadBytes(&byte, 1)) {
- return false;
- }
- cur_value += static_cast<uint64_t>(byte & 0x7f) << shift;
- shift += 7;
- } while (byte & 0x80);
- *value = cur_value;
- return true;
-}
-
-bool DwarfMemory::ReadSLEB128(int64_t* value) {
- uint64_t cur_value = 0;
- uint64_t shift = 0;
- uint8_t byte;
- do {
- if (!ReadBytes(&byte, 1)) {
- return false;
- }
- cur_value += static_cast<uint64_t>(byte & 0x7f) << shift;
- shift += 7;
- } while (byte & 0x80);
- if (byte & 0x40) {
- // Negative value, need to sign extend.
- cur_value |= static_cast<uint64_t>(-1) << shift;
- }
- *value = static_cast<int64_t>(cur_value);
- return true;
-}
-
-template <typename AddressType>
-size_t DwarfMemory::GetEncodedSize(uint8_t encoding) {
- switch (encoding & 0x0f) {
- case DW_EH_PE_absptr:
- return sizeof(AddressType);
- case DW_EH_PE_udata1:
- case DW_EH_PE_sdata1:
- return 1;
- case DW_EH_PE_udata2:
- case DW_EH_PE_sdata2:
- return 2;
- case DW_EH_PE_udata4:
- case DW_EH_PE_sdata4:
- return 4;
- case DW_EH_PE_udata8:
- case DW_EH_PE_sdata8:
- return 8;
- case DW_EH_PE_uleb128:
- case DW_EH_PE_sleb128:
- default:
- return 0;
- }
-}
-
-bool DwarfMemory::AdjustEncodedValue(uint8_t encoding, uint64_t* value) {
- CHECK((encoding & 0x0f) == 0);
-
- // Handle the encoding.
- switch (encoding) {
- case DW_EH_PE_absptr:
- // Nothing to do.
- break;
- case DW_EH_PE_pcrel:
- if (pc_offset_ == INT64_MAX) {
- // Unsupported encoding.
- return false;
- }
- *value += pc_offset_;
- break;
- case DW_EH_PE_textrel:
- if (text_offset_ == static_cast<uint64_t>(-1)) {
- // Unsupported encoding.
- return false;
- }
- *value += text_offset_;
- break;
- case DW_EH_PE_datarel:
- if (data_offset_ == static_cast<uint64_t>(-1)) {
- // Unsupported encoding.
- return false;
- }
- *value += data_offset_;
- break;
- case DW_EH_PE_funcrel:
- if (func_offset_ == static_cast<uint64_t>(-1)) {
- // Unsupported encoding.
- return false;
- }
- *value += func_offset_;
- break;
- default:
- return false;
- }
-
- return true;
-}
-
-template <typename AddressType>
-bool DwarfMemory::ReadEncodedValue(uint8_t encoding, uint64_t* value) {
- if (encoding == DW_EH_PE_omit) {
- *value = 0;
- return true;
- } else if (encoding == DW_EH_PE_aligned) {
- if (__builtin_add_overflow(cur_offset_, sizeof(AddressType) - 1, &cur_offset_)) {
- return false;
- }
- cur_offset_ &= -sizeof(AddressType);
-
- if (sizeof(AddressType) != sizeof(uint64_t)) {
- *value = 0;
- }
- return ReadBytes(value, sizeof(AddressType));
- }
-
- // Get the data.
- switch (encoding & 0x0f) {
- case DW_EH_PE_absptr:
- if (sizeof(AddressType) != sizeof(uint64_t)) {
- *value = 0;
- }
- if (!ReadBytes(value, sizeof(AddressType))) {
- return false;
- }
- break;
- case DW_EH_PE_uleb128:
- if (!ReadULEB128(value)) {
- return false;
- }
- break;
- case DW_EH_PE_sleb128:
- int64_t signed_value;
- if (!ReadSLEB128(&signed_value)) {
- return false;
- }
- *value = static_cast<uint64_t>(signed_value);
- break;
- case DW_EH_PE_udata1: {
- uint8_t value8;
- if (!ReadBytes(&value8, 1)) {
- return false;
- }
- *value = value8;
- } break;
- case DW_EH_PE_sdata1:
- if (!ReadSigned<int8_t>(value)) {
- return false;
- }
- break;
- case DW_EH_PE_udata2: {
- uint16_t value16;
- if (!ReadBytes(&value16, 2)) {
- return false;
- }
- *value = value16;
- } break;
- case DW_EH_PE_sdata2:
- if (!ReadSigned<int16_t>(value)) {
- return false;
- }
- break;
- case DW_EH_PE_udata4: {
- uint32_t value32;
- if (!ReadBytes(&value32, 4)) {
- return false;
- }
- *value = value32;
- } break;
- case DW_EH_PE_sdata4:
- if (!ReadSigned<int32_t>(value)) {
- return false;
- }
- break;
- case DW_EH_PE_udata8:
- if (!ReadBytes(value, sizeof(uint64_t))) {
- return false;
- }
- break;
- case DW_EH_PE_sdata8:
- if (!ReadSigned<int64_t>(value)) {
- return false;
- }
- break;
- default:
- return false;
- }
-
- return AdjustEncodedValue(encoding & 0x70, value);
-}
-
-// Instantiate all of the needed template functions.
-template bool DwarfMemory::ReadSigned<int8_t>(uint64_t*);
-template bool DwarfMemory::ReadSigned<int16_t>(uint64_t*);
-template bool DwarfMemory::ReadSigned<int32_t>(uint64_t*);
-template bool DwarfMemory::ReadSigned<int64_t>(uint64_t*);
-
-template size_t DwarfMemory::GetEncodedSize<uint32_t>(uint8_t);
-template size_t DwarfMemory::GetEncodedSize<uint64_t>(uint8_t);
-
-template bool DwarfMemory::ReadEncodedValue<uint32_t>(uint8_t, uint64_t*);
-template bool DwarfMemory::ReadEncodedValue<uint64_t>(uint8_t, uint64_t*);
-
-} // namespace unwindstack
diff --git a/libunwindstack/DwarfOp.cpp b/libunwindstack/DwarfOp.cpp
deleted file mode 100644
index 393eb3e..0000000
--- a/libunwindstack/DwarfOp.cpp
+++ /dev/null
@@ -1,1941 +0,0 @@
-/*
- * Copyright (C) 2017 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 <stdint.h>
-
-#include <deque>
-#include <string>
-#include <vector>
-
-#include <android-base/stringprintf.h>
-
-#include <unwindstack/DwarfError.h>
-#include <unwindstack/DwarfMemory.h>
-#include <unwindstack/Log.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/Regs.h>
-
-#include "DwarfOp.h"
-
-namespace unwindstack {
-
-enum DwarfOpHandleFunc : uint8_t {
- OP_ILLEGAL = 0,
- OP_DEREF,
- OP_DEREF_SIZE,
- OP_PUSH,
- OP_DUP,
- OP_DROP,
- OP_OVER,
- OP_PICK,
- OP_SWAP,
- OP_ROT,
- OP_ABS,
- OP_AND,
- OP_DIV,
- OP_MINUS,
- OP_MOD,
- OP_MUL,
- OP_NEG,
- OP_NOT,
- OP_OR,
- OP_PLUS,
- OP_PLUS_UCONST,
- OP_SHL,
- OP_SHR,
- OP_SHRA,
- OP_XOR,
- OP_BRA,
- OP_EQ,
- OP_GE,
- OP_GT,
- OP_LE,
- OP_LT,
- OP_NE,
- OP_SKIP,
- OP_LIT,
- OP_REG,
- OP_REGX,
- OP_BREG,
- OP_BREGX,
- OP_NOP,
- OP_NOT_IMPLEMENTED,
-};
-
-struct OpCallback {
- // It may seem tempting to "clean this up" by replacing "const char[26]" with
- // "const char*", but doing so would place the entire callback table in
- // .data.rel.ro section, instead of .rodata section, and thus increase
- // dirty memory usage. Libunwindstack is used by the linker and therefore
- // loaded for every running process, so every bit of memory counts.
- // Unlike C standard, C++ standard guarantees this array is big enough to
- // store the names, or else we would get a compilation error.
- const char name[26];
-
- // Similarily for this field, we do NOT want to directly store function
- // pointers here. Not only would that cause the callback table to be placed
- // in .data.rel.ro section, but it would be duplicated for each AddressType.
- // Instead, we use DwarfOpHandleFunc enum to decouple the callback table from
- // the function pointers.
- DwarfOpHandleFunc handle_func;
-
- uint8_t num_required_stack_values;
- uint8_t num_operands;
- uint8_t operands[2];
-};
-
-constexpr static OpCallback kCallbackTable[256] = {
- {"", OP_ILLEGAL, 0, 0, {}}, // 0x00 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0x01 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0x02 illegal op
- {
- // 0x03 DW_OP_addr
- "DW_OP_addr",
- OP_PUSH,
- 0,
- 1,
- {DW_EH_PE_absptr},
- },
- {"", OP_ILLEGAL, 0, 0, {}}, // 0x04 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0x05 illegal op
- {
- // 0x06 DW_OP_deref
- "DW_OP_deref",
- OP_DEREF,
- 1,
- 0,
- {},
- },
- {"", OP_ILLEGAL, 0, 0, {}}, // 0x07 illegal op
- {
- // 0x08 DW_OP_const1u
- "DW_OP_const1u",
- OP_PUSH,
- 0,
- 1,
- {DW_EH_PE_udata1},
- },
- {
- // 0x09 DW_OP_const1s
- "DW_OP_const1s",
- OP_PUSH,
- 0,
- 1,
- {DW_EH_PE_sdata1},
- },
- {
- // 0x0a DW_OP_const2u
- "DW_OP_const2u",
- OP_PUSH,
- 0,
- 1,
- {DW_EH_PE_udata2},
- },
- {
- // 0x0b DW_OP_const2s
- "DW_OP_const2s",
- OP_PUSH,
- 0,
- 1,
- {DW_EH_PE_sdata2},
- },
- {
- // 0x0c DW_OP_const4u
- "DW_OP_const4u",
- OP_PUSH,
- 0,
- 1,
- {DW_EH_PE_udata4},
- },
- {
- // 0x0d DW_OP_const4s
- "DW_OP_const4s",
- OP_PUSH,
- 0,
- 1,
- {DW_EH_PE_sdata4},
- },
- {
- // 0x0e DW_OP_const8u
- "DW_OP_const8u",
- OP_PUSH,
- 0,
- 1,
- {DW_EH_PE_udata8},
- },
- {
- // 0x0f DW_OP_const8s
- "DW_OP_const8s",
- OP_PUSH,
- 0,
- 1,
- {DW_EH_PE_sdata8},
- },
- {
- // 0x10 DW_OP_constu
- "DW_OP_constu",
- OP_PUSH,
- 0,
- 1,
- {DW_EH_PE_uleb128},
- },
- {
- // 0x11 DW_OP_consts
- "DW_OP_consts",
- OP_PUSH,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x12 DW_OP_dup
- "DW_OP_dup",
- OP_DUP,
- 1,
- 0,
- {},
- },
- {
- // 0x13 DW_OP_drop
- "DW_OP_drop",
- OP_DROP,
- 1,
- 0,
- {},
- },
- {
- // 0x14 DW_OP_over
- "DW_OP_over",
- OP_OVER,
- 2,
- 0,
- {},
- },
- {
- // 0x15 DW_OP_pick
- "DW_OP_pick",
- OP_PICK,
- 0,
- 1,
- {DW_EH_PE_udata1},
- },
- {
- // 0x16 DW_OP_swap
- "DW_OP_swap",
- OP_SWAP,
- 2,
- 0,
- {},
- },
- {
- // 0x17 DW_OP_rot
- "DW_OP_rot",
- OP_ROT,
- 3,
- 0,
- {},
- },
- {
- // 0x18 DW_OP_xderef
- "DW_OP_xderef",
- OP_NOT_IMPLEMENTED,
- 2,
- 0,
- {},
- },
- {
- // 0x19 DW_OP_abs
- "DW_OP_abs",
- OP_ABS,
- 1,
- 0,
- {},
- },
- {
- // 0x1a DW_OP_and
- "DW_OP_and",
- OP_AND,
- 2,
- 0,
- {},
- },
- {
- // 0x1b DW_OP_div
- "DW_OP_div",
- OP_DIV,
- 2,
- 0,
- {},
- },
- {
- // 0x1c DW_OP_minus
- "DW_OP_minus",
- OP_MINUS,
- 2,
- 0,
- {},
- },
- {
- // 0x1d DW_OP_mod
- "DW_OP_mod",
- OP_MOD,
- 2,
- 0,
- {},
- },
- {
- // 0x1e DW_OP_mul
- "DW_OP_mul",
- OP_MUL,
- 2,
- 0,
- {},
- },
- {
- // 0x1f DW_OP_neg
- "DW_OP_neg",
- OP_NEG,
- 1,
- 0,
- {},
- },
- {
- // 0x20 DW_OP_not
- "DW_OP_not",
- OP_NOT,
- 1,
- 0,
- {},
- },
- {
- // 0x21 DW_OP_or
- "DW_OP_or",
- OP_OR,
- 2,
- 0,
- {},
- },
- {
- // 0x22 DW_OP_plus
- "DW_OP_plus",
- OP_PLUS,
- 2,
- 0,
- {},
- },
- {
- // 0x23 DW_OP_plus_uconst
- "DW_OP_plus_uconst",
- OP_PLUS_UCONST,
- 1,
- 1,
- {DW_EH_PE_uleb128},
- },
- {
- // 0x24 DW_OP_shl
- "DW_OP_shl",
- OP_SHL,
- 2,
- 0,
- {},
- },
- {
- // 0x25 DW_OP_shr
- "DW_OP_shr",
- OP_SHR,
- 2,
- 0,
- {},
- },
- {
- // 0x26 DW_OP_shra
- "DW_OP_shra",
- OP_SHRA,
- 2,
- 0,
- {},
- },
- {
- // 0x27 DW_OP_xor
- "DW_OP_xor",
- OP_XOR,
- 2,
- 0,
- {},
- },
- {
- // 0x28 DW_OP_bra
- "DW_OP_bra",
- OP_BRA,
- 1,
- 1,
- {DW_EH_PE_sdata2},
- },
- {
- // 0x29 DW_OP_eq
- "DW_OP_eq",
- OP_EQ,
- 2,
- 0,
- {},
- },
- {
- // 0x2a DW_OP_ge
- "DW_OP_ge",
- OP_GE,
- 2,
- 0,
- {},
- },
- {
- // 0x2b DW_OP_gt
- "DW_OP_gt",
- OP_GT,
- 2,
- 0,
- {},
- },
- {
- // 0x2c DW_OP_le
- "DW_OP_le",
- OP_LE,
- 2,
- 0,
- {},
- },
- {
- // 0x2d DW_OP_lt
- "DW_OP_lt",
- OP_LT,
- 2,
- 0,
- {},
- },
- {
- // 0x2e DW_OP_ne
- "DW_OP_ne",
- OP_NE,
- 2,
- 0,
- {},
- },
- {
- // 0x2f DW_OP_skip
- "DW_OP_skip",
- OP_SKIP,
- 0,
- 1,
- {DW_EH_PE_sdata2},
- },
- {
- // 0x30 DW_OP_lit0
- "DW_OP_lit0",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x31 DW_OP_lit1
- "DW_OP_lit1",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x32 DW_OP_lit2
- "DW_OP_lit2",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x33 DW_OP_lit3
- "DW_OP_lit3",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x34 DW_OP_lit4
- "DW_OP_lit4",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x35 DW_OP_lit5
- "DW_OP_lit5",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x36 DW_OP_lit6
- "DW_OP_lit6",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x37 DW_OP_lit7
- "DW_OP_lit7",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x38 DW_OP_lit8
- "DW_OP_lit8",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x39 DW_OP_lit9
- "DW_OP_lit9",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x3a DW_OP_lit10
- "DW_OP_lit10",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x3b DW_OP_lit11
- "DW_OP_lit11",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x3c DW_OP_lit12
- "DW_OP_lit12",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x3d DW_OP_lit13
- "DW_OP_lit13",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x3e DW_OP_lit14
- "DW_OP_lit14",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x3f DW_OP_lit15
- "DW_OP_lit15",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x40 DW_OP_lit16
- "DW_OP_lit16",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x41 DW_OP_lit17
- "DW_OP_lit17",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x42 DW_OP_lit18
- "DW_OP_lit18",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x43 DW_OP_lit19
- "DW_OP_lit19",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x44 DW_OP_lit20
- "DW_OP_lit20",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x45 DW_OP_lit21
- "DW_OP_lit21",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x46 DW_OP_lit22
- "DW_OP_lit22",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x47 DW_OP_lit23
- "DW_OP_lit23",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x48 DW_OP_lit24
- "DW_OP_lit24",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x49 DW_OP_lit25
- "DW_OP_lit25",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x4a DW_OP_lit26
- "DW_OP_lit26",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x4b DW_OP_lit27
- "DW_OP_lit27",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x4c DW_OP_lit28
- "DW_OP_lit28",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x4d DW_OP_lit29
- "DW_OP_lit29",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x4e DW_OP_lit30
- "DW_OP_lit30",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x4f DW_OP_lit31
- "DW_OP_lit31",
- OP_LIT,
- 0,
- 0,
- {},
- },
- {
- // 0x50 DW_OP_reg0
- "DW_OP_reg0",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x51 DW_OP_reg1
- "DW_OP_reg1",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x52 DW_OP_reg2
- "DW_OP_reg2",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x53 DW_OP_reg3
- "DW_OP_reg3",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x54 DW_OP_reg4
- "DW_OP_reg4",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x55 DW_OP_reg5
- "DW_OP_reg5",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x56 DW_OP_reg6
- "DW_OP_reg6",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x57 DW_OP_reg7
- "DW_OP_reg7",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x58 DW_OP_reg8
- "DW_OP_reg8",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x59 DW_OP_reg9
- "DW_OP_reg9",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x5a DW_OP_reg10
- "DW_OP_reg10",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x5b DW_OP_reg11
- "DW_OP_reg11",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x5c DW_OP_reg12
- "DW_OP_reg12",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x5d DW_OP_reg13
- "DW_OP_reg13",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x5e DW_OP_reg14
- "DW_OP_reg14",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x5f DW_OP_reg15
- "DW_OP_reg15",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x60 DW_OP_reg16
- "DW_OP_reg16",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x61 DW_OP_reg17
- "DW_OP_reg17",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x62 DW_OP_reg18
- "DW_OP_reg18",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x63 DW_OP_reg19
- "DW_OP_reg19",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x64 DW_OP_reg20
- "DW_OP_reg20",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x65 DW_OP_reg21
- "DW_OP_reg21",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x66 DW_OP_reg22
- "DW_OP_reg22",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x67 DW_OP_reg23
- "DW_OP_reg23",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x68 DW_OP_reg24
- "DW_OP_reg24",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x69 DW_OP_reg25
- "DW_OP_reg25",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x6a DW_OP_reg26
- "DW_OP_reg26",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x6b DW_OP_reg27
- "DW_OP_reg27",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x6c DW_OP_reg28
- "DW_OP_reg28",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x6d DW_OP_reg29
- "DW_OP_reg29",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x6e DW_OP_reg30
- "DW_OP_reg30",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x6f DW_OP_reg31
- "DW_OP_reg31",
- OP_REG,
- 0,
- 0,
- {},
- },
- {
- // 0x70 DW_OP_breg0
- "DW_OP_breg0",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x71 DW_OP_breg1
- "DW_OP_breg1",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x72 DW_OP_breg2
- "DW_OP_breg2",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x73 DW_OP_breg3
- "DW_OP_breg3",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x74 DW_OP_breg4
- "DW_OP_breg4",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x75 DW_OP_breg5
- "DW_OP_breg5",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x76 DW_OP_breg6
- "DW_OP_breg6",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x77 DW_OP_breg7
- "DW_OP_breg7",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x78 DW_OP_breg8
- "DW_OP_breg8",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x79 DW_OP_breg9
- "DW_OP_breg9",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x7a DW_OP_breg10
- "DW_OP_breg10",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x7b DW_OP_breg11
- "DW_OP_breg11",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x7c DW_OP_breg12
- "DW_OP_breg12",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x7d DW_OP_breg13
- "DW_OP_breg13",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x7e DW_OP_breg14
- "DW_OP_breg14",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x7f DW_OP_breg15
- "DW_OP_breg15",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x80 DW_OP_breg16
- "DW_OP_breg16",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x81 DW_OP_breg17
- "DW_OP_breg17",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x82 DW_OP_breg18
- "DW_OP_breg18",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x83 DW_OP_breg19
- "DW_OP_breg19",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x84 DW_OP_breg20
- "DW_OP_breg20",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x85 DW_OP_breg21
- "DW_OP_breg21",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x86 DW_OP_breg22
- "DW_OP_breg22",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x87 DW_OP_breg23
- "DW_OP_breg23",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x88 DW_OP_breg24
- "DW_OP_breg24",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x89 DW_OP_breg25
- "DW_OP_breg25",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x8a DW_OP_breg26
- "DW_OP_breg26",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x8b DW_OP_breg27
- "DW_OP_breg27",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x8c DW_OP_breg28
- "DW_OP_breg28",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x8d DW_OP_breg29
- "DW_OP_breg29",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x8e DW_OP_breg30
- "DW_OP_breg30",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x8f DW_OP_breg31
- "DW_OP_breg31",
- OP_BREG,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x90 DW_OP_regx
- "DW_OP_regx",
- OP_REGX,
- 0,
- 1,
- {DW_EH_PE_uleb128},
- },
- {
- // 0x91 DW_OP_fbreg
- "DW_OP_fbreg",
- OP_NOT_IMPLEMENTED,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x92 DW_OP_bregx
- "DW_OP_bregx",
- OP_BREGX,
- 0,
- 2,
- {DW_EH_PE_uleb128, DW_EH_PE_sleb128},
- },
- {
- // 0x93 DW_OP_piece
- "DW_OP_piece",
- OP_NOT_IMPLEMENTED,
- 0,
- 1,
- {DW_EH_PE_uleb128},
- },
- {
- // 0x94 DW_OP_deref_size
- "DW_OP_deref_size",
- OP_DEREF_SIZE,
- 1,
- 1,
- {DW_EH_PE_udata1},
- },
- {
- // 0x95 DW_OP_xderef_size
- "DW_OP_xderef_size",
- OP_NOT_IMPLEMENTED,
- 0,
- 1,
- {DW_EH_PE_udata1},
- },
- {
- // 0x96 DW_OP_nop
- "DW_OP_nop",
- OP_NOP,
- 0,
- 0,
- {},
- },
- {
- // 0x97 DW_OP_push_object_address
- "DW_OP_push_object_address",
- OP_NOT_IMPLEMENTED,
- 0,
- 0,
- {},
- },
- {
- // 0x98 DW_OP_call2
- "DW_OP_call2",
- OP_NOT_IMPLEMENTED,
- 0,
- 1,
- {DW_EH_PE_udata2},
- },
- {
- // 0x99 DW_OP_call4
- "DW_OP_call4",
- OP_NOT_IMPLEMENTED,
- 0,
- 1,
- {DW_EH_PE_udata4},
- },
- {
- // 0x9a DW_OP_call_ref
- "DW_OP_call_ref",
- OP_NOT_IMPLEMENTED,
- 0,
- 0, // Has a different sized operand (4 bytes or 8 bytes).
- {},
- },
- {
- // 0x9b DW_OP_form_tls_address
- "DW_OP_form_tls_address",
- OP_NOT_IMPLEMENTED,
- 0,
- 0,
- {},
- },
- {
- // 0x9c DW_OP_call_frame_cfa
- "DW_OP_call_frame_cfa",
- OP_NOT_IMPLEMENTED,
- 0,
- 0,
- {},
- },
- {
- // 0x9d DW_OP_bit_piece
- "DW_OP_bit_piece",
- OP_NOT_IMPLEMENTED,
- 0,
- 2,
- {DW_EH_PE_uleb128, DW_EH_PE_uleb128},
- },
- {
- // 0x9e DW_OP_implicit_value
- "DW_OP_implicit_value",
- OP_NOT_IMPLEMENTED,
- 0,
- 1,
- {DW_EH_PE_uleb128},
- },
- {
- // 0x9f DW_OP_stack_value
- "DW_OP_stack_value",
- OP_NOT_IMPLEMENTED,
- 1,
- 0,
- {},
- },
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xa0 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xa1 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xa2 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xa3 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xa4 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xa5 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xa6 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xa7 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xa8 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xa9 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xaa illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xab illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xac illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xad illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xae illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xaf illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xb0 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xb1 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xb2 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xb3 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xb4 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xb5 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xb6 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xb7 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xb8 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xb9 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xba illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xbb illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xbc illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xbd illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xbe illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xbf illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xc0 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xc1 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xc2 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xc3 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xc4 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xc5 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xc6 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xc7 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xc8 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xc9 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xca illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xcb illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xcc illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xcd illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xce illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xcf illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xd0 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xd1 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xd2 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xd3 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xd4 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xd5 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xd6 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xd7 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xd8 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xd9 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xda illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xdb illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xdc illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xdd illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xde illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xdf illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xe0 DW_OP_lo_user
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xe1 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xe2 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xe3 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xe4 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xe5 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xe6 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xe7 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xe8 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xe9 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xea illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xeb illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xec illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xed illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xee illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xef illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xf0 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xf1 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xf2 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xf3 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xf4 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xf5 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xf6 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xf7 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xf8 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xf9 illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xfa illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xfb illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xfc illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xfd illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xfe illegal op
- {"", OP_ILLEGAL, 0, 0, {}}, // 0xff DW_OP_hi_user
-};
-
-template <typename AddressType>
-const typename DwarfOp<AddressType>::OpHandleFuncPtr DwarfOp<AddressType>::kOpHandleFuncList[] = {
- [OP_ILLEGAL] = nullptr,
- [OP_DEREF] = &DwarfOp<AddressType>::op_deref,
- [OP_DEREF_SIZE] = &DwarfOp<AddressType>::op_deref_size,
- [OP_PUSH] = &DwarfOp<AddressType>::op_push,
- [OP_DUP] = &DwarfOp<AddressType>::op_dup,
- [OP_DROP] = &DwarfOp<AddressType>::op_drop,
- [OP_OVER] = &DwarfOp<AddressType>::op_over,
- [OP_PICK] = &DwarfOp<AddressType>::op_pick,
- [OP_SWAP] = &DwarfOp<AddressType>::op_swap,
- [OP_ROT] = &DwarfOp<AddressType>::op_rot,
- [OP_ABS] = &DwarfOp<AddressType>::op_abs,
- [OP_AND] = &DwarfOp<AddressType>::op_and,
- [OP_DIV] = &DwarfOp<AddressType>::op_div,
- [OP_MINUS] = &DwarfOp<AddressType>::op_minus,
- [OP_MOD] = &DwarfOp<AddressType>::op_mod,
- [OP_MUL] = &DwarfOp<AddressType>::op_mul,
- [OP_NEG] = &DwarfOp<AddressType>::op_neg,
- [OP_NOT] = &DwarfOp<AddressType>::op_not,
- [OP_OR] = &DwarfOp<AddressType>::op_or,
- [OP_PLUS] = &DwarfOp<AddressType>::op_plus,
- [OP_PLUS_UCONST] = &DwarfOp<AddressType>::op_plus_uconst,
- [OP_SHL] = &DwarfOp<AddressType>::op_shl,
- [OP_SHR] = &DwarfOp<AddressType>::op_shr,
- [OP_SHRA] = &DwarfOp<AddressType>::op_shra,
- [OP_XOR] = &DwarfOp<AddressType>::op_xor,
- [OP_BRA] = &DwarfOp<AddressType>::op_bra,
- [OP_EQ] = &DwarfOp<AddressType>::op_eq,
- [OP_GE] = &DwarfOp<AddressType>::op_ge,
- [OP_GT] = &DwarfOp<AddressType>::op_gt,
- [OP_LE] = &DwarfOp<AddressType>::op_le,
- [OP_LT] = &DwarfOp<AddressType>::op_lt,
- [OP_NE] = &DwarfOp<AddressType>::op_ne,
- [OP_SKIP] = &DwarfOp<AddressType>::op_skip,
- [OP_LIT] = &DwarfOp<AddressType>::op_lit,
- [OP_REG] = &DwarfOp<AddressType>::op_reg,
- [OP_REGX] = &DwarfOp<AddressType>::op_regx,
- [OP_BREG] = &DwarfOp<AddressType>::op_breg,
- [OP_BREGX] = &DwarfOp<AddressType>::op_bregx,
- [OP_NOP] = &DwarfOp<AddressType>::op_nop,
- [OP_NOT_IMPLEMENTED] = &DwarfOp<AddressType>::op_not_implemented,
-};
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::Eval(uint64_t start, uint64_t end) {
- is_register_ = false;
- stack_.clear();
- memory_->set_cur_offset(start);
- dex_pc_set_ = false;
-
- // Unroll the first Decode calls to be able to check for a special
- // sequence of ops and values that indicate this is the dex pc.
- // The pattern is:
- // OP_const4u (0x0c) 'D' 'E' 'X' '1'
- // OP_drop (0x13)
- if (memory_->cur_offset() < end) {
- if (!Decode()) {
- return false;
- }
- } else {
- return true;
- }
- bool check_for_drop;
- if (cur_op_ == 0x0c && operands_.back() == 0x31584544) {
- check_for_drop = true;
- } else {
- check_for_drop = false;
- }
- if (memory_->cur_offset() < end) {
- if (!Decode()) {
- return false;
- }
- } else {
- return true;
- }
-
- if (check_for_drop && cur_op_ == 0x13) {
- dex_pc_set_ = true;
- }
-
- uint32_t iterations = 2;
- while (memory_->cur_offset() < end) {
- if (!Decode()) {
- return false;
- }
- // To protect against a branch that creates an infinite loop,
- // terminate if the number of iterations gets too high.
- if (iterations++ == 1000) {
- last_error_.code = DWARF_ERROR_TOO_MANY_ITERATIONS;
- return false;
- }
- }
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::Decode() {
- last_error_.code = DWARF_ERROR_NONE;
- if (!memory_->ReadBytes(&cur_op_, 1)) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_->cur_offset();
- return false;
- }
-
- const auto* op = &kCallbackTable[cur_op_];
- if (op->handle_func == OP_ILLEGAL) {
- last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
- return false;
- }
-
- const auto handle_func = kOpHandleFuncList[op->handle_func];
-
- // Make sure that the required number of stack elements is available.
- if (stack_.size() < op->num_required_stack_values) {
- last_error_.code = DWARF_ERROR_STACK_INDEX_NOT_VALID;
- return false;
- }
-
- operands_.clear();
- for (size_t i = 0; i < op->num_operands; i++) {
- uint64_t value;
- if (!memory_->ReadEncodedValue<AddressType>(op->operands[i], &value)) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_->cur_offset();
- return false;
- }
- operands_.push_back(value);
- }
- return (this->*handle_func)();
-}
-
-template <typename AddressType>
-void DwarfOp<AddressType>::GetLogInfo(uint64_t start, uint64_t end,
- std::vector<std::string>* lines) {
- memory_->set_cur_offset(start);
- while (memory_->cur_offset() < end) {
- uint8_t cur_op;
- if (!memory_->ReadBytes(&cur_op, 1)) {
- return;
- }
-
- std::string raw_string(android::base::StringPrintf("Raw Data: 0x%02x", cur_op));
- std::string log_string;
- const auto* op = &kCallbackTable[cur_op];
- if (op->handle_func == OP_ILLEGAL) {
- log_string = "Illegal";
- } else {
- log_string = op->name;
- uint64_t start_offset = memory_->cur_offset();
- for (size_t i = 0; i < op->num_operands; i++) {
- uint64_t value;
- if (!memory_->ReadEncodedValue<AddressType>(op->operands[i], &value)) {
- return;
- }
- log_string += ' ' + std::to_string(value);
- }
- uint64_t end_offset = memory_->cur_offset();
-
- memory_->set_cur_offset(start_offset);
- for (size_t i = start_offset; i < end_offset; i++) {
- uint8_t byte;
- if (!memory_->ReadBytes(&byte, 1)) {
- return;
- }
- raw_string += android::base::StringPrintf(" 0x%02x", byte);
- }
- memory_->set_cur_offset(end_offset);
- }
- lines->push_back(std::move(log_string));
- lines->push_back(std::move(raw_string));
- }
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_deref() {
- // Read the address and dereference it.
- AddressType addr = StackPop();
- AddressType value;
- if (!regular_memory()->ReadFully(addr, &value, sizeof(value))) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = addr;
- return false;
- }
- stack_.push_front(value);
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_deref_size() {
- AddressType bytes_to_read = OperandAt(0);
- if (bytes_to_read > sizeof(AddressType) || bytes_to_read == 0) {
- last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
- return false;
- }
- // Read the address and dereference it.
- AddressType addr = StackPop();
- AddressType value = 0;
- if (!regular_memory()->ReadFully(addr, &value, bytes_to_read)) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = addr;
- return false;
- }
- stack_.push_front(value);
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_push() {
- // Push all of the operands.
- for (auto operand : operands_) {
- stack_.push_front(operand);
- }
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_dup() {
- stack_.push_front(StackAt(0));
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_drop() {
- StackPop();
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_over() {
- stack_.push_front(StackAt(1));
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_pick() {
- AddressType index = OperandAt(0);
- if (index > StackSize()) {
- last_error_.code = DWARF_ERROR_STACK_INDEX_NOT_VALID;
- return false;
- }
- stack_.push_front(StackAt(index));
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_swap() {
- AddressType old_value = stack_[0];
- stack_[0] = stack_[1];
- stack_[1] = old_value;
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_rot() {
- AddressType top = stack_[0];
- stack_[0] = stack_[1];
- stack_[1] = stack_[2];
- stack_[2] = top;
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_abs() {
- SignedType signed_value = static_cast<SignedType>(stack_[0]);
- if (signed_value < 0) {
- signed_value = -signed_value;
- }
- stack_[0] = static_cast<AddressType>(signed_value);
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_and() {
- AddressType top = StackPop();
- stack_[0] &= top;
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_div() {
- AddressType top = StackPop();
- if (top == 0) {
- last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
- return false;
- }
- SignedType signed_divisor = static_cast<SignedType>(top);
- SignedType signed_dividend = static_cast<SignedType>(stack_[0]);
- stack_[0] = static_cast<AddressType>(signed_dividend / signed_divisor);
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_minus() {
- AddressType top = StackPop();
- stack_[0] -= top;
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_mod() {
- AddressType top = StackPop();
- if (top == 0) {
- last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
- return false;
- }
- stack_[0] %= top;
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_mul() {
- AddressType top = StackPop();
- stack_[0] *= top;
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_neg() {
- SignedType signed_value = static_cast<SignedType>(stack_[0]);
- stack_[0] = static_cast<AddressType>(-signed_value);
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_not() {
- stack_[0] = ~stack_[0];
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_or() {
- AddressType top = StackPop();
- stack_[0] |= top;
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_plus() {
- AddressType top = StackPop();
- stack_[0] += top;
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_plus_uconst() {
- stack_[0] += OperandAt(0);
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_shl() {
- AddressType top = StackPop();
- stack_[0] <<= top;
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_shr() {
- AddressType top = StackPop();
- stack_[0] >>= top;
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_shra() {
- AddressType top = StackPop();
- SignedType signed_value = static_cast<SignedType>(stack_[0]) >> top;
- stack_[0] = static_cast<AddressType>(signed_value);
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_xor() {
- AddressType top = StackPop();
- stack_[0] ^= top;
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_bra() {
- // Requires one stack element.
- AddressType top = StackPop();
- int16_t offset = static_cast<int16_t>(OperandAt(0));
- uint64_t cur_offset;
- if (top != 0) {
- cur_offset = memory_->cur_offset() + offset;
- } else {
- cur_offset = memory_->cur_offset() - offset;
- }
- memory_->set_cur_offset(cur_offset);
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_eq() {
- AddressType top = StackPop();
- stack_[0] = bool_to_dwarf_bool(stack_[0] == top);
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_ge() {
- AddressType top = StackPop();
- stack_[0] = bool_to_dwarf_bool(stack_[0] >= top);
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_gt() {
- AddressType top = StackPop();
- stack_[0] = bool_to_dwarf_bool(stack_[0] > top);
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_le() {
- AddressType top = StackPop();
- stack_[0] = bool_to_dwarf_bool(stack_[0] <= top);
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_lt() {
- AddressType top = StackPop();
- stack_[0] = bool_to_dwarf_bool(stack_[0] < top);
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_ne() {
- AddressType top = StackPop();
- stack_[0] = bool_to_dwarf_bool(stack_[0] != top);
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_skip() {
- int16_t offset = static_cast<int16_t>(OperandAt(0));
- uint64_t cur_offset = memory_->cur_offset() + offset;
- memory_->set_cur_offset(cur_offset);
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_lit() {
- stack_.push_front(cur_op() - 0x30);
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_reg() {
- is_register_ = true;
- stack_.push_front(cur_op() - 0x50);
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_regx() {
- is_register_ = true;
- stack_.push_front(OperandAt(0));
- return true;
-}
-
-// It's not clear for breg/bregx, if this op should read the current
-// value of the register, or where we think that register is located.
-// For simplicity, the code will read the value before doing the unwind.
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_breg() {
- uint16_t reg = cur_op() - 0x70;
- if (reg >= regs_info_->Total()) {
- last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
- return false;
- }
- stack_.push_front(regs_info_->Get(reg) + OperandAt(0));
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_bregx() {
- AddressType reg = OperandAt(0);
- if (reg >= regs_info_->Total()) {
- last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
- return false;
- }
- stack_.push_front(regs_info_->Get(reg) + OperandAt(1));
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_nop() {
- return true;
-}
-
-template <typename AddressType>
-bool DwarfOp<AddressType>::op_not_implemented() {
- last_error_.code = DWARF_ERROR_NOT_IMPLEMENTED;
- return false;
-}
-
-// Explicitly instantiate DwarfOp.
-template class DwarfOp<uint32_t>;
-template class DwarfOp<uint64_t>;
-
-} // namespace unwindstack
diff --git a/libunwindstack/DwarfOp.h b/libunwindstack/DwarfOp.h
deleted file mode 100644
index ac9fd2d..0000000
--- a/libunwindstack/DwarfOp.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_DWARF_OP_H
-#define _LIBUNWINDSTACK_DWARF_OP_H
-
-#include <stdint.h>
-
-#include <deque>
-#include <string>
-#include <type_traits>
-#include <vector>
-
-#include <unwindstack/DwarfError.h>
-
-#include "DwarfEncoding.h"
-#include "RegsInfo.h"
-
-namespace unwindstack {
-
-// Forward declarations.
-class DwarfMemory;
-class Memory;
-template <typename AddressType>
-class RegsImpl;
-
-template <typename AddressType>
-class DwarfOp {
- // Signed version of AddressType
- typedef typename std::make_signed<AddressType>::type SignedType;
-
- public:
- DwarfOp(DwarfMemory* memory, Memory* regular_memory)
- : memory_(memory), regular_memory_(regular_memory) {}
- virtual ~DwarfOp() = default;
-
- bool Decode();
-
- bool Eval(uint64_t start, uint64_t end);
-
- void GetLogInfo(uint64_t start, uint64_t end, std::vector<std::string>* lines);
-
- AddressType StackAt(size_t index) { return stack_[index]; }
- size_t StackSize() { return stack_.size(); }
-
- void set_regs_info(RegsInfo<AddressType>* regs_info) { regs_info_ = regs_info; }
-
- const DwarfErrorData& last_error() { return last_error_; }
- DwarfErrorCode LastErrorCode() { return last_error_.code; }
- uint64_t LastErrorAddress() { return last_error_.address; }
-
- bool dex_pc_set() { return dex_pc_set_; }
-
- bool is_register() { return is_register_; }
-
- uint8_t cur_op() { return cur_op_; }
-
- Memory* regular_memory() { return regular_memory_; }
-
- protected:
- AddressType OperandAt(size_t index) { return operands_[index]; }
- size_t OperandsSize() { return operands_.size(); }
-
- AddressType StackPop() {
- AddressType value = stack_.front();
- stack_.pop_front();
- return value;
- }
-
- private:
- DwarfMemory* memory_;
- Memory* regular_memory_;
-
- RegsInfo<AddressType>* regs_info_;
- bool dex_pc_set_ = false;
- bool is_register_ = false;
- DwarfErrorData last_error_{DWARF_ERROR_NONE, 0};
- uint8_t cur_op_;
- std::vector<AddressType> operands_;
- std::deque<AddressType> stack_;
-
- inline AddressType bool_to_dwarf_bool(bool value) { return value ? 1 : 0; }
-
- // Op processing functions.
- bool op_deref();
- bool op_deref_size();
- bool op_push();
- bool op_dup();
- bool op_drop();
- bool op_over();
- bool op_pick();
- bool op_swap();
- bool op_rot();
- bool op_abs();
- bool op_and();
- bool op_div();
- bool op_minus();
- bool op_mod();
- bool op_mul();
- bool op_neg();
- bool op_not();
- bool op_or();
- bool op_plus();
- bool op_plus_uconst();
- bool op_shl();
- bool op_shr();
- bool op_shra();
- bool op_xor();
- bool op_bra();
- bool op_eq();
- bool op_ge();
- bool op_gt();
- bool op_le();
- bool op_lt();
- bool op_ne();
- bool op_skip();
- bool op_lit();
- bool op_reg();
- bool op_regx();
- bool op_breg();
- bool op_bregx();
- bool op_nop();
- bool op_not_implemented();
-
- using OpHandleFuncPtr = bool (DwarfOp::*)();
- static const OpHandleFuncPtr kOpHandleFuncList[];
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_DWARF_OP_H
diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp
deleted file mode 100644
index ad25e80..0000000
--- a/libunwindstack/DwarfSection.cpp
+++ /dev/null
@@ -1,830 +0,0 @@
-/*
- * Copyright (C) 2017 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 <stdint.h>
-
-#include <unwindstack/DwarfError.h>
-#include <unwindstack/DwarfLocation.h>
-#include <unwindstack/DwarfMemory.h>
-#include <unwindstack/DwarfSection.h>
-#include <unwindstack/DwarfStructs.h>
-#include <unwindstack/Elf.h>
-#include <unwindstack/Log.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/Regs.h>
-
-#include "DwarfCfa.h"
-#include "DwarfDebugFrame.h"
-#include "DwarfEhFrame.h"
-#include "DwarfEncoding.h"
-#include "DwarfOp.h"
-#include "RegsInfo.h"
-
-namespace unwindstack {
-
-DwarfSection::DwarfSection(Memory* memory) : memory_(memory) {}
-
-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) {
- last_error_.code = DWARF_ERROR_NONE;
- const DwarfFde* fde = GetFdeFromPc(pc);
- if (fde == nullptr || fde->cie == nullptr) {
- last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
- return false;
- }
-
- // Now get the location information for this pc.
- dwarf_loc_regs_t loc_regs;
- if (!GetCfaLocationInfo(pc, fde, &loc_regs, regs->Arch())) {
- return false;
- }
- loc_regs.cie = fde->cie;
-
- // Store it in the cache.
- 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);
-}
-
-template <typename AddressType>
-const DwarfCie* DwarfSectionImpl<AddressType>::GetCieFromOffset(uint64_t offset) {
- auto cie_entry = cie_entries_.find(offset);
- if (cie_entry != cie_entries_.end()) {
- return &cie_entry->second;
- }
- DwarfCie* cie = &cie_entries_[offset];
- memory_.set_data_offset(entries_offset_);
- memory_.set_cur_offset(offset);
- if (!FillInCieHeader(cie) || !FillInCie(cie)) {
- // Erase the cached entry.
- cie_entries_.erase(offset);
- return nullptr;
- }
- return cie;
-}
-
-template <typename AddressType>
-bool DwarfSectionImpl<AddressType>::FillInCieHeader(DwarfCie* cie) {
- cie->lsda_encoding = DW_EH_PE_omit;
- uint32_t length32;
- if (!memory_.ReadBytes(&length32, sizeof(length32))) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
- if (length32 == static_cast<uint32_t>(-1)) {
- // 64 bit Cie
- uint64_t length64;
- if (!memory_.ReadBytes(&length64, sizeof(length64))) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
-
- cie->cfa_instructions_end = memory_.cur_offset() + length64;
- cie->fde_address_encoding = DW_EH_PE_sdata8;
-
- uint64_t cie_id;
- if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
- if (cie_id != cie64_value_) {
- // This is not a Cie, something has gone horribly wrong.
- last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
- return false;
- }
- } else {
- // 32 bit Cie
- cie->cfa_instructions_end = memory_.cur_offset() + length32;
- cie->fde_address_encoding = DW_EH_PE_sdata4;
-
- uint32_t cie_id;
- if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
- if (cie_id != cie32_value_) {
- // This is not a Cie, something has gone horribly wrong.
- last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
- return false;
- }
- }
- return true;
-}
-
-template <typename AddressType>
-bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) {
- if (!memory_.ReadBytes(&cie->version, sizeof(cie->version))) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
-
- if (cie->version != 1 && cie->version != 3 && cie->version != 4 && cie->version != 5) {
- // Unrecognized version.
- last_error_.code = DWARF_ERROR_UNSUPPORTED_VERSION;
- return false;
- }
-
- // Read the augmentation string.
- char aug_value;
- do {
- if (!memory_.ReadBytes(&aug_value, 1)) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
- cie->augmentation_string.push_back(aug_value);
- } while (aug_value != '\0');
-
- if (cie->version == 4 || cie->version == 5) {
- // Skip the Address Size field since we only use it for validation.
- memory_.set_cur_offset(memory_.cur_offset() + 1);
-
- // Segment Size
- if (!memory_.ReadBytes(&cie->segment_size, 1)) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
- }
-
- // Code Alignment Factor
- if (!memory_.ReadULEB128(&cie->code_alignment_factor)) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
-
- // Data Alignment Factor
- if (!memory_.ReadSLEB128(&cie->data_alignment_factor)) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
-
- if (cie->version == 1) {
- // Return Address is a single byte.
- uint8_t return_address_register;
- if (!memory_.ReadBytes(&return_address_register, 1)) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
- cie->return_address_register = return_address_register;
- } else if (!memory_.ReadULEB128(&cie->return_address_register)) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
-
- if (cie->augmentation_string[0] != 'z') {
- cie->cfa_instructions_offset = memory_.cur_offset();
- return true;
- }
-
- uint64_t aug_length;
- if (!memory_.ReadULEB128(&aug_length)) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
- cie->cfa_instructions_offset = memory_.cur_offset() + aug_length;
-
- for (size_t i = 1; i < cie->augmentation_string.size(); i++) {
- switch (cie->augmentation_string[i]) {
- case 'L':
- if (!memory_.ReadBytes(&cie->lsda_encoding, 1)) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
- break;
- case 'P': {
- uint8_t encoding;
- if (!memory_.ReadBytes(&encoding, 1)) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
- memory_.set_pc_offset(pc_offset_);
- if (!memory_.ReadEncodedValue<AddressType>(encoding, &cie->personality_handler)) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
- } break;
- case 'R':
- if (!memory_.ReadBytes(&cie->fde_address_encoding, 1)) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
- break;
- case 'S':
- cie->is_signal_frame = true;
- break;
- }
- }
- return true;
-}
-
-template <typename AddressType>
-const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromOffset(uint64_t offset) {
- auto fde_entry = fde_entries_.find(offset);
- if (fde_entry != fde_entries_.end()) {
- return &fde_entry->second;
- }
- DwarfFde* fde = &fde_entries_[offset];
- memory_.set_data_offset(entries_offset_);
- memory_.set_cur_offset(offset);
- if (!FillInFdeHeader(fde) || !FillInFde(fde)) {
- fde_entries_.erase(offset);
- return nullptr;
- }
- return fde;
-}
-
-template <typename AddressType>
-bool DwarfSectionImpl<AddressType>::FillInFdeHeader(DwarfFde* fde) {
- uint32_t length32;
- if (!memory_.ReadBytes(&length32, sizeof(length32))) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
-
- if (length32 == static_cast<uint32_t>(-1)) {
- // 64 bit Fde.
- uint64_t length64;
- if (!memory_.ReadBytes(&length64, sizeof(length64))) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
- fde->cfa_instructions_end = memory_.cur_offset() + length64;
-
- uint64_t value64;
- if (!memory_.ReadBytes(&value64, sizeof(value64))) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
- if (value64 == cie64_value_) {
- // This is a Cie, this means something has gone wrong.
- last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
- return false;
- }
-
- // Get the Cie pointer, which is necessary to properly read the rest of
- // of the Fde information.
- fde->cie_offset = GetCieOffsetFromFde64(value64);
- } else {
- // 32 bit Fde.
- fde->cfa_instructions_end = memory_.cur_offset() + length32;
-
- uint32_t value32;
- if (!memory_.ReadBytes(&value32, sizeof(value32))) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
- if (value32 == cie32_value_) {
- // This is a Cie, this means something has gone wrong.
- last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
- return false;
- }
-
- // Get the Cie pointer, which is necessary to properly read the rest of
- // of the Fde information.
- fde->cie_offset = GetCieOffsetFromFde32(value32);
- }
- return true;
-}
-
-template <typename AddressType>
-bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) {
- uint64_t cur_offset = memory_.cur_offset();
-
- const DwarfCie* cie = GetCieFromOffset(fde->cie_offset);
- if (cie == nullptr) {
- return false;
- }
- fde->cie = cie;
-
- if (cie->segment_size != 0) {
- // Skip over the segment selector for now.
- cur_offset += cie->segment_size;
- }
- memory_.set_cur_offset(cur_offset);
-
- // The load bias only applies to the start.
- memory_.set_pc_offset(section_bias_);
- bool valid = memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding, &fde->pc_start);
- fde->pc_start = AdjustPcFromFde(fde->pc_start);
-
- memory_.set_pc_offset(0);
- if (!valid || !memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding, &fde->pc_end)) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
- fde->pc_end += fde->pc_start;
-
- if (cie->augmentation_string.size() > 0 && cie->augmentation_string[0] == 'z') {
- // Augmentation Size
- uint64_t aug_length;
- if (!memory_.ReadULEB128(&aug_length)) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
- uint64_t cur_offset = memory_.cur_offset();
-
- memory_.set_pc_offset(pc_offset_);
- if (!memory_.ReadEncodedValue<AddressType>(cie->lsda_encoding, &fde->lsda_address)) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
-
- // Set our position to after all of the augmentation data.
- memory_.set_cur_offset(cur_offset + aug_length);
- }
- fde->cfa_instructions_offset = memory_.cur_offset();
-
- return true;
-}
-
-template <typename AddressType>
-bool DwarfSectionImpl<AddressType>::EvalExpression(const DwarfLocation& loc, Memory* regular_memory,
- AddressType* value,
- RegsInfo<AddressType>* regs_info,
- bool* is_dex_pc) {
- DwarfOp<AddressType> op(&memory_, regular_memory);
- op.set_regs_info(regs_info);
-
- // Need to evaluate the op data.
- uint64_t end = loc.values[1];
- uint64_t start = end - loc.values[0];
- if (!op.Eval(start, end)) {
- last_error_ = op.last_error();
- return false;
- }
- if (op.StackSize() == 0) {
- last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
- return false;
- }
- // We don't support an expression that evaluates to a register number.
- if (op.is_register()) {
- last_error_.code = DWARF_ERROR_NOT_IMPLEMENTED;
- return false;
- }
- *value = op.StackAt(0);
- if (is_dex_pc != nullptr && op.dex_pc_set()) {
- *is_dex_pc = true;
- }
- return true;
-}
-
-template <typename AddressType>
-struct EvalInfo {
- const dwarf_loc_regs_t* loc_regs;
- const DwarfCie* cie;
- Memory* regular_memory;
- AddressType cfa;
- bool return_address_undefined = false;
- RegsInfo<AddressType> regs_info;
-};
-
-template <typename AddressType>
-bool DwarfSectionImpl<AddressType>::EvalRegister(const DwarfLocation* loc, uint32_t reg,
- AddressType* reg_ptr, void* info) {
- EvalInfo<AddressType>* eval_info = reinterpret_cast<EvalInfo<AddressType>*>(info);
- Memory* regular_memory = eval_info->regular_memory;
- switch (loc->type) {
- case DWARF_LOCATION_OFFSET:
- if (!regular_memory->ReadFully(eval_info->cfa + loc->values[0], reg_ptr, sizeof(AddressType))) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = eval_info->cfa + loc->values[0];
- return false;
- }
- break;
- case DWARF_LOCATION_VAL_OFFSET:
- *reg_ptr = eval_info->cfa + loc->values[0];
- break;
- case DWARF_LOCATION_REGISTER: {
- uint32_t cur_reg = loc->values[0];
- if (cur_reg >= eval_info->regs_info.Total()) {
- last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
- return false;
- }
- *reg_ptr = eval_info->regs_info.Get(cur_reg) + loc->values[1];
- break;
- }
- case DWARF_LOCATION_EXPRESSION:
- case DWARF_LOCATION_VAL_EXPRESSION: {
- AddressType value;
- bool is_dex_pc = false;
- if (!EvalExpression(*loc, regular_memory, &value, &eval_info->regs_info, &is_dex_pc)) {
- return false;
- }
- if (loc->type == DWARF_LOCATION_EXPRESSION) {
- if (!regular_memory->ReadFully(value, reg_ptr, sizeof(AddressType))) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = value;
- return false;
- }
- } else {
- *reg_ptr = value;
- if (is_dex_pc) {
- eval_info->regs_info.regs->set_dex_pc(value);
- }
- }
- break;
- }
- case DWARF_LOCATION_UNDEFINED:
- if (reg == eval_info->cie->return_address_register) {
- eval_info->return_address_undefined = true;
- }
- break;
- case DWARF_LOCATION_PSEUDO_REGISTER:
- last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
- return false;
- default:
- break;
- }
-
- return true;
-}
-
-template <typename AddressType>
-bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_memory,
- const dwarf_loc_regs_t& loc_regs, Regs* regs,
- bool* finished) {
- RegsImpl<AddressType>* cur_regs = reinterpret_cast<RegsImpl<AddressType>*>(regs);
- if (cie->return_address_register >= cur_regs->total_regs()) {
- last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
- return false;
- }
-
- // Get the cfa value;
- auto cfa_entry = loc_regs.find(CFA_REG);
- if (cfa_entry == loc_regs.end()) {
- last_error_.code = DWARF_ERROR_CFA_NOT_DEFINED;
- return false;
- }
-
- // Always set the dex pc to zero when evaluating.
- cur_regs->set_dex_pc(0);
-
- // Reset necessary pseudo registers before evaluation.
- // This is needed for ARM64, for example.
- regs->ResetPseudoRegisters();
-
- EvalInfo<AddressType> eval_info{.loc_regs = &loc_regs,
- .cie = cie,
- .regular_memory = regular_memory,
- .regs_info = RegsInfo<AddressType>(cur_regs)};
- const DwarfLocation* loc = &cfa_entry->second;
- // Only a few location types are valid for the cfa.
- switch (loc->type) {
- case DWARF_LOCATION_REGISTER:
- if (loc->values[0] >= cur_regs->total_regs()) {
- last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
- return false;
- }
- eval_info.cfa = (*cur_regs)[loc->values[0]];
- eval_info.cfa += loc->values[1];
- break;
- case DWARF_LOCATION_VAL_EXPRESSION: {
- AddressType value;
- if (!EvalExpression(*loc, regular_memory, &value, &eval_info.regs_info, nullptr)) {
- return false;
- }
- // There is only one type of valid expression for CFA evaluation.
- eval_info.cfa = value;
- break;
- }
- default:
- last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
- return false;
- }
-
- for (const auto& entry : loc_regs) {
- uint32_t reg = entry.first;
- // Already handled the CFA register.
- if (reg == CFA_REG) continue;
-
- AddressType* reg_ptr;
- if (reg >= cur_regs->total_regs()) {
- if (entry.second.type != DWARF_LOCATION_PSEUDO_REGISTER) {
- // Skip this unknown register.
- continue;
- }
- if (!eval_info.regs_info.regs->SetPseudoRegister(reg, entry.second.values[0])) {
- last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
- return false;
- }
- } else {
- reg_ptr = eval_info.regs_info.Save(reg);
- if (!EvalRegister(&entry.second, reg, reg_ptr, &eval_info)) {
- return false;
- }
- }
- }
-
- // Find the return address location.
- if (eval_info.return_address_undefined) {
- cur_regs->set_pc(0);
- } else {
- cur_regs->set_pc((*cur_regs)[cie->return_address_register]);
- }
-
- // 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);
-
- return true;
-}
-
-template <typename AddressType>
-bool DwarfSectionImpl<AddressType>::GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde,
- dwarf_loc_regs_t* loc_regs, ArchEnum arch) {
- DwarfCfa<AddressType> cfa(&memory_, fde, arch);
-
- // Look for the cached copy of the cie data.
- auto reg_entry = cie_loc_regs_.find(fde->cie_offset);
- if (reg_entry == cie_loc_regs_.end()) {
- if (!cfa.GetLocationInfo(pc, fde->cie->cfa_instructions_offset, fde->cie->cfa_instructions_end,
- loc_regs)) {
- last_error_ = cfa.last_error();
- return false;
- }
- cie_loc_regs_[fde->cie_offset] = *loc_regs;
- }
- cfa.set_cie_loc_regs(&cie_loc_regs_[fde->cie_offset]);
- if (!cfa.GetLocationInfo(pc, fde->cfa_instructions_offset, fde->cfa_instructions_end, loc_regs)) {
- last_error_ = cfa.last_error();
- return false;
- }
- return true;
-}
-
-template <typename AddressType>
-bool DwarfSectionImpl<AddressType>::Log(uint8_t indent, uint64_t pc, const DwarfFde* fde,
- ArchEnum arch) {
- DwarfCfa<AddressType> cfa(&memory_, fde, arch);
-
- // Always print the cie information.
- const DwarfCie* cie = fde->cie;
- if (!cfa.Log(indent, pc, cie->cfa_instructions_offset, cie->cfa_instructions_end)) {
- last_error_ = cfa.last_error();
- return false;
- }
- if (!cfa.Log(indent, pc, fde->cfa_instructions_offset, fde->cfa_instructions_end)) {
- last_error_ = cfa.last_error();
- return false;
- }
- return true;
-}
-
-template <typename AddressType>
-bool DwarfSectionImpl<AddressType>::Init(uint64_t offset, uint64_t size, int64_t section_bias) {
- section_bias_ = section_bias;
- entries_offset_ = offset;
- next_entries_offset_ = offset;
- entries_end_ = offset + size;
-
- memory_.clear_func_offset();
- memory_.clear_text_offset();
- memory_.set_cur_offset(offset);
- pc_offset_ = offset;
-
- return true;
-}
-
-// Create a cached version of the fde information such that it is a std::map
-// that is indexed by end pc and contains a pair that represents the start pc
-// followed by the fde object. The fde pointers are owned by fde_entries_
-// and not by the map object.
-// It is possible for an fde to be represented by multiple entries in
-// the map. This can happen if the the start pc and end pc overlap already
-// existing entries. For example, if there is already an entry of 0x400, 0x200,
-// and an fde has a start pc of 0x100 and end pc of 0x500, two new entries
-// will be added: 0x200, 0x100 and 0x500, 0x400.
-template <typename AddressType>
-void DwarfSectionImpl<AddressType>::InsertFde(const DwarfFde* fde) {
- uint64_t start = fde->pc_start;
- uint64_t end = fde->pc_end;
- auto it = fdes_.upper_bound(start);
- while (it != fdes_.end() && start < end && it->second.first < end) {
- if (start < it->second.first) {
- fdes_[it->second.first] = std::make_pair(start, fde);
- }
- start = it->first;
- ++it;
- }
- if (start < end) {
- fdes_[end] = std::make_pair(start, fde);
- }
-}
-
-template <typename AddressType>
-bool DwarfSectionImpl<AddressType>::GetNextCieOrFde(const DwarfFde** fde_entry) {
- uint64_t start_offset = next_entries_offset_;
-
- memory_.set_data_offset(entries_offset_);
- memory_.set_cur_offset(next_entries_offset_);
- uint32_t value32;
- if (!memory_.ReadBytes(&value32, sizeof(value32))) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
-
- uint64_t cie_offset;
- uint8_t cie_fde_encoding;
- bool entry_is_cie = false;
- if (value32 == static_cast<uint32_t>(-1)) {
- // 64 bit entry.
- uint64_t value64;
- if (!memory_.ReadBytes(&value64, sizeof(value64))) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
-
- next_entries_offset_ = memory_.cur_offset() + value64;
- // Read the Cie Id of a Cie or the pointer of the Fde.
- if (!memory_.ReadBytes(&value64, sizeof(value64))) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
-
- if (value64 == cie64_value_) {
- entry_is_cie = true;
- cie_fde_encoding = DW_EH_PE_sdata8;
- } else {
- cie_offset = GetCieOffsetFromFde64(value64);
- }
- } else {
- next_entries_offset_ = memory_.cur_offset() + value32;
-
- // 32 bit Cie
- if (!memory_.ReadBytes(&value32, sizeof(value32))) {
- last_error_.code = DWARF_ERROR_MEMORY_INVALID;
- last_error_.address = memory_.cur_offset();
- return false;
- }
-
- if (value32 == cie32_value_) {
- entry_is_cie = true;
- cie_fde_encoding = DW_EH_PE_sdata4;
- } else {
- cie_offset = GetCieOffsetFromFde32(value32);
- }
- }
-
- if (entry_is_cie) {
- auto entry = cie_entries_.find(start_offset);
- if (entry == cie_entries_.end()) {
- DwarfCie* cie = &cie_entries_[start_offset];
- cie->lsda_encoding = DW_EH_PE_omit;
- cie->cfa_instructions_end = next_entries_offset_;
- cie->fde_address_encoding = cie_fde_encoding;
-
- if (!FillInCie(cie)) {
- cie_entries_.erase(start_offset);
- return false;
- }
- }
- *fde_entry = nullptr;
- } else {
- auto entry = fde_entries_.find(start_offset);
- if (entry != fde_entries_.end()) {
- *fde_entry = &entry->second;
- } else {
- DwarfFde* fde = &fde_entries_[start_offset];
- fde->cfa_instructions_end = next_entries_offset_;
- fde->cie_offset = cie_offset;
-
- if (!FillInFde(fde)) {
- fde_entries_.erase(start_offset);
- return false;
- }
- *fde_entry = fde;
- }
- }
- return true;
-}
-
-template <typename AddressType>
-void DwarfSectionImpl<AddressType>::GetFdes(std::vector<const DwarfFde*>* fdes) {
- // Loop through the already cached entries.
- uint64_t entry_offset = entries_offset_;
- while (entry_offset < next_entries_offset_) {
- auto cie_it = cie_entries_.find(entry_offset);
- if (cie_it != cie_entries_.end()) {
- entry_offset = cie_it->second.cfa_instructions_end;
- } else {
- auto fde_it = fde_entries_.find(entry_offset);
- if (fde_it == fde_entries_.end()) {
- // No fde or cie at this entry, should not be possible.
- return;
- }
- entry_offset = fde_it->second.cfa_instructions_end;
- fdes->push_back(&fde_it->second);
- }
- }
-
- while (next_entries_offset_ < entries_end_) {
- const DwarfFde* fde;
- if (!GetNextCieOrFde(&fde)) {
- break;
- }
- if (fde != nullptr) {
- InsertFde(fde);
- fdes->push_back(fde);
- }
-
- if (next_entries_offset_ < memory_.cur_offset()) {
- // Simply consider the processing done in this case.
- break;
- }
- }
-}
-
-template <typename AddressType>
-const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromPc(uint64_t pc) {
- // Search in the list of fdes we already have.
- auto it = fdes_.upper_bound(pc);
- if (it != fdes_.end()) {
- if (pc >= it->second.first) {
- return it->second.second;
- }
- }
-
- // The section might have overlapping pcs in fdes, so it is necessary
- // to do a linear search of the fdes by pc. As fdes are read, a cached
- // search map is created.
- while (next_entries_offset_ < entries_end_) {
- const DwarfFde* fde;
- if (!GetNextCieOrFde(&fde)) {
- return nullptr;
- }
- if (fde != nullptr) {
- InsertFde(fde);
- if (pc >= fde->pc_start && pc < fde->pc_end) {
- return fde;
- }
- }
-
- if (next_entries_offset_ < memory_.cur_offset()) {
- // Simply consider the processing done in this case.
- break;
- }
- }
- return nullptr;
-}
-
-// Explicitly instantiate DwarfSectionImpl
-template class DwarfSectionImpl<uint32_t>;
-template class DwarfSectionImpl<uint64_t>;
-
-// Explicitly instantiate DwarfDebugFrame
-template class DwarfDebugFrame<uint32_t>;
-template class DwarfDebugFrame<uint64_t>;
-
-// Explicitly instantiate DwarfEhFrame
-template class DwarfEhFrame<uint32_t>;
-template class DwarfEhFrame<uint64_t>;
-
-} // namespace unwindstack
diff --git a/libunwindstack/Elf.cpp b/libunwindstack/Elf.cpp
deleted file mode 100644
index e098a58..0000000
--- a/libunwindstack/Elf.cpp
+++ /dev/null
@@ -1,422 +0,0 @@
-/*
- * Copyright (C) 2016 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 <elf.h>
-#include <string.h>
-
-#include <memory>
-#include <mutex>
-#include <string>
-#include <utility>
-
-#define LOG_TAG "unwind"
-#include <log/log.h>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/ElfInterface.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/Regs.h>
-
-#include "ElfInterfaceArm.h"
-#include "Symbols.h"
-
-namespace unwindstack {
-
-bool Elf::cache_enabled_;
-std::unordered_map<std::string, std::pair<std::shared_ptr<Elf>, bool>>* Elf::cache_;
-std::mutex* Elf::cache_lock_;
-
-bool Elf::Init() {
- load_bias_ = 0;
- if (!memory_) {
- return false;
- }
-
- interface_.reset(CreateInterfaceFromMemory(memory_.get()));
- if (!interface_) {
- return false;
- }
-
- valid_ = interface_->Init(&load_bias_);
- if (valid_) {
- interface_->InitHeaders();
- InitGnuDebugdata();
- } else {
- interface_.reset(nullptr);
- }
- return valid_;
-}
-
-// It is expensive to initialize the .gnu_debugdata section. Provide a method
-// to initialize this data separately.
-void Elf::InitGnuDebugdata() {
- if (!valid_ || interface_->gnu_debugdata_offset() == 0) {
- return;
- }
-
- gnu_debugdata_memory_.reset(interface_->CreateGnuDebugdataMemory());
- gnu_debugdata_interface_.reset(CreateInterfaceFromMemory(gnu_debugdata_memory_.get()));
- ElfInterface* gnu = gnu_debugdata_interface_.get();
- if (gnu == nullptr) {
- return;
- }
-
- // Ignore the load_bias from the compressed section, the correct load bias
- // is in the uncompressed data.
- int64_t load_bias;
- if (gnu->Init(&load_bias)) {
- gnu->InitHeaders();
- interface_->SetGnuDebugdataInterface(gnu);
- } else {
- // Free all of the memory associated with the gnu_debugdata section.
- gnu_debugdata_memory_.reset(nullptr);
- gnu_debugdata_interface_.reset(nullptr);
- }
-}
-
-void Elf::Invalidate() {
- interface_.reset(nullptr);
- valid_ = false;
-}
-
-std::string Elf::GetSoname() {
- std::lock_guard<std::mutex> guard(lock_);
- if (!valid_) {
- return "";
- }
- return interface_->GetSoname();
-}
-
-uint64_t Elf::GetRelPc(uint64_t pc, const MapInfo* map_info) {
- return pc - map_info->start + load_bias_ + map_info->elf_offset;
-}
-
-bool Elf::GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) {
- std::lock_guard<std::mutex> guard(lock_);
- return valid_ && (interface_->GetFunctionName(addr, name, func_offset) ||
- (gnu_debugdata_interface_ &&
- gnu_debugdata_interface_->GetFunctionName(addr, name, func_offset)));
-}
-
-bool Elf::GetGlobalVariableOffset(const std::string& name, uint64_t* memory_offset) {
- if (!valid_) {
- return false;
- }
-
- uint64_t vaddr;
- if (!interface_->GetGlobalVariable(name, &vaddr) &&
- (gnu_debugdata_interface_ == nullptr ||
- !gnu_debugdata_interface_->GetGlobalVariable(name, &vaddr))) {
- return false;
- }
-
- if (arch() == ARCH_ARM64) {
- // Tagged pointer after Android R would lead top byte to have random values
- // https://source.android.com/devices/tech/debug/tagged-pointers
- vaddr &= (1ULL << 56) - 1;
- }
-
- // Check the .data section.
- uint64_t vaddr_start = interface_->data_vaddr_start();
- if (vaddr >= vaddr_start && vaddr < interface_->data_vaddr_end()) {
- *memory_offset = vaddr - vaddr_start + interface_->data_offset();
- return true;
- }
-
- // Check the .dynamic section.
- vaddr_start = interface_->dynamic_vaddr_start();
- if (vaddr >= vaddr_start && vaddr < interface_->dynamic_vaddr_end()) {
- *memory_offset = vaddr - vaddr_start + interface_->dynamic_offset();
- return true;
- }
-
- return false;
-}
-
-std::string Elf::GetBuildID() {
- if (!valid_) {
- return "";
- }
- return interface_->GetBuildID();
-}
-
-void Elf::GetLastError(ErrorData* data) {
- if (valid_) {
- *data = interface_->last_error();
- }
-}
-
-ErrorCode Elf::GetLastErrorCode() {
- if (valid_) {
- return interface_->LastErrorCode();
- }
- return ERROR_INVALID_ELF;
-}
-
-uint64_t Elf::GetLastErrorAddress() {
- if (valid_) {
- return interface_->LastErrorAddress();
- }
- return 0;
-}
-
-// The relative pc expectd by this function is relative to the start of the elf.
-bool Elf::StepIfSignalHandler(uint64_t rel_pc, Regs* regs, Memory* process_memory) {
- if (!valid_) {
- return false;
- }
-
- // Convert the rel_pc to an elf_offset.
- if (rel_pc < static_cast<uint64_t>(load_bias_)) {
- return false;
- }
- return regs->StepIfSignalHandler(rel_pc - load_bias_, this, process_memory);
-}
-
-// 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* 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, is_signal_frame);
-}
-
-bool Elf::IsValidElf(Memory* memory) {
- if (memory == nullptr) {
- return false;
- }
-
- // Verify that this is a valid elf file.
- uint8_t e_ident[SELFMAG + 1];
- if (!memory->ReadFully(0, e_ident, SELFMAG)) {
- return false;
- }
-
- if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) {
- return false;
- }
- return true;
-}
-
-bool Elf::GetInfo(Memory* memory, uint64_t* size) {
- if (!IsValidElf(memory)) {
- return false;
- }
- *size = 0;
-
- uint8_t class_type;
- if (!memory->ReadFully(EI_CLASS, &class_type, 1)) {
- return false;
- }
-
- // Get the maximum size of the elf data from the header.
- if (class_type == ELFCLASS32) {
- ElfInterface32::GetMaxSize(memory, size);
- } else if (class_type == ELFCLASS64) {
- ElfInterface64::GetMaxSize(memory, size);
- } else {
- return false;
- }
- return true;
-}
-
-bool Elf::IsValidPc(uint64_t pc) {
- if (!valid_ || (load_bias_ > 0 && pc < static_cast<uint64_t>(load_bias_))) {
- return false;
- }
-
- if (interface_->IsValidPc(pc)) {
- return true;
- }
-
- if (gnu_debugdata_interface_ != nullptr && gnu_debugdata_interface_->IsValidPc(pc)) {
- return true;
- }
-
- return false;
-}
-
-ElfInterface* Elf::CreateInterfaceFromMemory(Memory* memory) {
- if (!IsValidElf(memory)) {
- return nullptr;
- }
-
- std::unique_ptr<ElfInterface> interface;
- if (!memory->ReadFully(EI_CLASS, &class_type_, 1)) {
- return nullptr;
- }
- if (class_type_ == ELFCLASS32) {
- Elf32_Half e_machine;
- if (!memory->ReadFully(EI_NIDENT + sizeof(Elf32_Half), &e_machine, sizeof(e_machine))) {
- return nullptr;
- }
-
- machine_type_ = e_machine;
- if (e_machine == EM_ARM) {
- arch_ = ARCH_ARM;
- interface.reset(new ElfInterfaceArm(memory));
- } else if (e_machine == EM_386) {
- arch_ = ARCH_X86;
- interface.reset(new ElfInterface32(memory));
- } else if (e_machine == EM_MIPS) {
- arch_ = ARCH_MIPS;
- interface.reset(new ElfInterface32(memory));
- } else {
- // Unsupported.
- ALOGI("32 bit elf that is neither arm nor x86 nor mips: e_machine = %d\n", e_machine);
- return nullptr;
- }
- } else if (class_type_ == ELFCLASS64) {
- Elf64_Half e_machine;
- if (!memory->ReadFully(EI_NIDENT + sizeof(Elf64_Half), &e_machine, sizeof(e_machine))) {
- return nullptr;
- }
-
- machine_type_ = e_machine;
- if (e_machine == EM_AARCH64) {
- arch_ = ARCH_ARM64;
- } else if (e_machine == EM_X86_64) {
- arch_ = ARCH_X86_64;
- } else if (e_machine == EM_MIPS) {
- arch_ = ARCH_MIPS64;
- } else {
- // Unsupported.
- ALOGI("64 bit elf that is neither aarch64 nor x86_64 nor mips64: e_machine = %d\n",
- e_machine);
- return nullptr;
- }
- interface.reset(new ElfInterface64(memory));
- }
-
- return interface.release();
-}
-
-int64_t Elf::GetLoadBias(Memory* memory) {
- if (!IsValidElf(memory)) {
- return 0;
- }
-
- uint8_t class_type;
- if (!memory->Read(EI_CLASS, &class_type, 1)) {
- return 0;
- }
-
- if (class_type == ELFCLASS32) {
- return ElfInterface::GetLoadBias<Elf32_Ehdr, Elf32_Phdr>(memory);
- } else if (class_type == ELFCLASS64) {
- return ElfInterface::GetLoadBias<Elf64_Ehdr, Elf64_Phdr>(memory);
- }
- return 0;
-}
-
-void Elf::SetCachingEnabled(bool enable) {
- if (!cache_enabled_ && enable) {
- cache_enabled_ = true;
- cache_ = new std::unordered_map<std::string, std::pair<std::shared_ptr<Elf>, bool>>;
- cache_lock_ = new std::mutex;
- } else if (cache_enabled_ && !enable) {
- cache_enabled_ = false;
- delete cache_;
- delete cache_lock_;
- }
-}
-
-void Elf::CacheLock() {
- cache_lock_->lock();
-}
-
-void Elf::CacheUnlock() {
- cache_lock_->unlock();
-}
-
-void Elf::CacheAdd(MapInfo* info) {
- // If elf_offset != 0, then cache both name:offset and name.
- // The cached name is used to do lookups if multiple maps for the same
- // named elf file exist.
- // For example, if there are two maps boot.odex:1000 and boot.odex:2000
- // where each reference the entire boot.odex, the cache will properly
- // use the same cached elf object.
-
- if (info->offset == 0 || info->elf_offset != 0) {
- (*cache_)[info->name] = std::make_pair(info->elf, true);
- }
-
- if (info->offset != 0) {
- // The second element in the pair indicates whether elf_offset should
- // be set to offset when getting out of the cache.
- (*cache_)[info->name + ':' + std::to_string(info->offset)] =
- std::make_pair(info->elf, info->elf_offset != 0);
- }
-}
-
-bool Elf::CacheAfterCreateMemory(MapInfo* info) {
- if (info->name.empty() || info->offset == 0 || info->elf_offset == 0) {
- return false;
- }
-
- auto entry = cache_->find(info->name);
- if (entry == cache_->end()) {
- return false;
- }
-
- // In this case, the whole file is the elf, and the name has already
- // been cached. Add an entry at name:offset to get this directly out
- // of the cache next time.
- info->elf = entry->second.first;
- (*cache_)[info->name + ':' + std::to_string(info->offset)] = std::make_pair(info->elf, true);
- return true;
-}
-
-bool Elf::CacheGet(MapInfo* info) {
- std::string name(info->name);
- if (info->offset != 0) {
- name += ':' + std::to_string(info->offset);
- }
- auto entry = cache_->find(name);
- if (entry != cache_->end()) {
- info->elf = entry->second.first;
- if (entry->second.second) {
- info->elf_offset = info->offset;
- }
- return true;
- }
- return false;
-}
-
-std::string Elf::GetBuildID(Memory* memory) {
- if (!IsValidElf(memory)) {
- return "";
- }
-
- uint8_t class_type;
- if (!memory->Read(EI_CLASS, &class_type, 1)) {
- return "";
- }
-
- if (class_type == ELFCLASS32) {
- return ElfInterface::ReadBuildIDFromMemory<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr>(memory);
- } else if (class_type == ELFCLASS64) {
- return ElfInterface::ReadBuildIDFromMemory<Elf64_Ehdr, Elf64_Shdr, Elf64_Nhdr>(memory);
- }
- return "";
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
deleted file mode 100644
index 0188def..0000000
--- a/libunwindstack/ElfInterface.cpp
+++ /dev/null
@@ -1,720 +0,0 @@
-/*
- * Copyright (C) 2017 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 <elf.h>
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <utility>
-
-#include <7zCrc.h>
-#include <Xz.h>
-#include <XzCrc64.h>
-
-#include <unwindstack/DwarfError.h>
-#include <unwindstack/DwarfSection.h>
-#include <unwindstack/ElfInterface.h>
-#include <unwindstack/Log.h>
-#include <unwindstack/Regs.h>
-
-#include "DwarfDebugFrame.h"
-#include "DwarfEhFrame.h"
-#include "DwarfEhFrameWithHdr.h"
-#include "MemoryBuffer.h"
-#include "Symbols.h"
-
-namespace unwindstack {
-
-ElfInterface::~ElfInterface() {
- for (auto symbol : symbols_) {
- delete symbol;
- }
-}
-
-bool ElfInterface::IsValidPc(uint64_t pc) {
- if (!pt_loads_.empty()) {
- for (auto& entry : pt_loads_) {
- uint64_t start = entry.second.table_offset;
- uint64_t end = start + entry.second.table_size;
- if (pc >= start && pc < end) {
- return true;
- }
- }
- return false;
- }
-
- // No PT_LOAD data, look for a fde for this pc in the section data.
- if (debug_frame_ != nullptr && debug_frame_->GetFdeFromPc(pc) != nullptr) {
- return true;
- }
-
- if (eh_frame_ != nullptr && eh_frame_->GetFdeFromPc(pc) != nullptr) {
- return true;
- }
-
- return false;
-}
-
-Memory* ElfInterface::CreateGnuDebugdataMemory() {
- if (gnu_debugdata_offset_ == 0 || gnu_debugdata_size_ == 0) {
- return nullptr;
- }
-
- // TODO: Only call these initialization functions once.
- CrcGenerateTable();
- Crc64GenerateTable();
-
- // Verify the request is not larger than the max size_t value.
- if (gnu_debugdata_size_ > SIZE_MAX) {
- return nullptr;
- }
- size_t initial_buffer_size;
- if (__builtin_mul_overflow(5, gnu_debugdata_size_, &initial_buffer_size)) {
- return nullptr;
- }
-
- size_t buffer_increment;
- if (__builtin_mul_overflow(2, gnu_debugdata_size_, &buffer_increment)) {
- return nullptr;
- }
-
- std::unique_ptr<uint8_t[]> src(new (std::nothrow) uint8_t[gnu_debugdata_size_]);
- if (src.get() == nullptr) {
- return nullptr;
- }
-
- std::unique_ptr<MemoryBuffer> dst(new MemoryBuffer);
- if (!dst->Resize(initial_buffer_size)) {
- return nullptr;
- }
-
- if (!memory_->ReadFully(gnu_debugdata_offset_, src.get(), gnu_debugdata_size_)) {
- return nullptr;
- }
-
- ISzAlloc alloc;
- CXzUnpacker state;
- alloc.Alloc = [](ISzAllocPtr, size_t size) { return malloc(size); };
- alloc.Free = [](ISzAllocPtr, void* ptr) { return free(ptr); };
- XzUnpacker_Construct(&state, &alloc);
-
- int return_val;
- size_t src_offset = 0;
- size_t dst_offset = 0;
- ECoderStatus status;
- do {
- size_t src_remaining = gnu_debugdata_size_ - src_offset;
- size_t dst_remaining = dst->Size() - dst_offset;
- if (dst_remaining < buffer_increment) {
- size_t new_size;
- if (__builtin_add_overflow(dst->Size(), buffer_increment, &new_size) ||
- !dst->Resize(new_size)) {
- XzUnpacker_Free(&state);
- return nullptr;
- }
- dst_remaining += buffer_increment;
- }
- return_val = XzUnpacker_Code(&state, dst->GetPtr(dst_offset), &dst_remaining, &src[src_offset],
- &src_remaining, true, CODER_FINISH_ANY, &status);
- src_offset += src_remaining;
- dst_offset += dst_remaining;
- } while (return_val == SZ_OK && status == CODER_STATUS_NOT_FINISHED);
- XzUnpacker_Free(&state);
- if (return_val != SZ_OK || !XzUnpacker_IsStreamWasFinished(&state)) {
- return nullptr;
- }
-
- // Shrink back down to the exact size.
- if (!dst->Resize(dst_offset)) {
- return nullptr;
- }
-
- return dst.release();
-}
-
-template <typename AddressType>
-void ElfInterface::InitHeadersWithTemplate() {
- if (eh_frame_hdr_offset_ != 0) {
- DwarfEhFrameWithHdr<AddressType>* eh_frame_hdr = new DwarfEhFrameWithHdr<AddressType>(memory_);
- eh_frame_.reset(eh_frame_hdr);
- if (!eh_frame_hdr->EhFrameInit(eh_frame_offset_, eh_frame_size_, eh_frame_section_bias_) ||
- !eh_frame_->Init(eh_frame_hdr_offset_, eh_frame_hdr_size_, eh_frame_hdr_section_bias_)) {
- eh_frame_.reset(nullptr);
- }
- }
-
- if (eh_frame_.get() == nullptr && eh_frame_offset_ != 0) {
- // If there is an eh_frame section without an eh_frame_hdr section,
- // or using the frame hdr object failed to init.
- eh_frame_.reset(new DwarfEhFrame<AddressType>(memory_));
- if (!eh_frame_->Init(eh_frame_offset_, eh_frame_size_, eh_frame_section_bias_)) {
- eh_frame_.reset(nullptr);
- }
- }
-
- if (eh_frame_.get() == nullptr) {
- eh_frame_hdr_offset_ = 0;
- eh_frame_hdr_section_bias_ = 0;
- eh_frame_hdr_size_ = static_cast<uint64_t>(-1);
- eh_frame_offset_ = 0;
- eh_frame_section_bias_ = 0;
- eh_frame_size_ = static_cast<uint64_t>(-1);
- }
-
- if (debug_frame_offset_ != 0) {
- debug_frame_.reset(new DwarfDebugFrame<AddressType>(memory_));
- if (!debug_frame_->Init(debug_frame_offset_, debug_frame_size_, debug_frame_section_bias_)) {
- debug_frame_.reset(nullptr);
- debug_frame_offset_ = 0;
- debug_frame_size_ = static_cast<uint64_t>(-1);
- }
- }
-}
-
-template <typename EhdrType, typename PhdrType, typename ShdrType>
-bool ElfInterface::ReadAllHeaders(int64_t* load_bias) {
- EhdrType ehdr;
- if (!memory_->ReadFully(0, &ehdr, sizeof(ehdr))) {
- last_error_.code = ERROR_MEMORY_INVALID;
- last_error_.address = 0;
- return false;
- }
-
- // If we have enough information that this is an elf file, then allow
- // malformed program and section headers.
- ReadProgramHeaders<EhdrType, PhdrType>(ehdr, load_bias);
- ReadSectionHeaders<EhdrType, ShdrType>(ehdr);
- return true;
-}
-
-template <typename EhdrType, typename PhdrType>
-int64_t ElfInterface::GetLoadBias(Memory* memory) {
- EhdrType ehdr;
- if (!memory->ReadFully(0, &ehdr, sizeof(ehdr))) {
- return false;
- }
-
- uint64_t offset = ehdr.e_phoff;
- for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) {
- PhdrType phdr;
- if (!memory->ReadFully(offset, &phdr, sizeof(phdr))) {
- return 0;
- }
-
- // Find the first executable load when looking for the load bias.
- if (phdr.p_type == PT_LOAD && (phdr.p_flags & PF_X)) {
- return static_cast<uint64_t>(phdr.p_vaddr) - phdr.p_offset;
- }
- }
- return 0;
-}
-
-template <typename EhdrType, typename PhdrType>
-void ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, int64_t* load_bias) {
- uint64_t offset = ehdr.e_phoff;
- bool first_exec_load_header = true;
- for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) {
- PhdrType phdr;
- if (!memory_->ReadFully(offset, &phdr, sizeof(phdr))) {
- return;
- }
-
- switch (phdr.p_type) {
- case PT_LOAD:
- {
- if ((phdr.p_flags & PF_X) == 0) {
- continue;
- }
-
- pt_loads_[phdr.p_offset] = LoadInfo{phdr.p_offset, phdr.p_vaddr,
- static_cast<size_t>(phdr.p_memsz)};
- // Only set the load bias from the first executable load header.
- if (first_exec_load_header) {
- *load_bias = static_cast<uint64_t>(phdr.p_vaddr) - phdr.p_offset;
- }
- first_exec_load_header = false;
- break;
- }
-
- case PT_GNU_EH_FRAME:
- // This is really the pointer to the .eh_frame_hdr section.
- eh_frame_hdr_offset_ = phdr.p_offset;
- eh_frame_hdr_section_bias_ = static_cast<uint64_t>(phdr.p_vaddr) - phdr.p_offset;
- eh_frame_hdr_size_ = phdr.p_memsz;
- break;
-
- case PT_DYNAMIC:
- dynamic_offset_ = phdr.p_offset;
- dynamic_vaddr_start_ = phdr.p_vaddr;
- if (__builtin_add_overflow(dynamic_vaddr_start_, phdr.p_memsz, &dynamic_vaddr_end_)) {
- dynamic_offset_ = 0;
- dynamic_vaddr_start_ = 0;
- dynamic_vaddr_end_ = 0;
- }
- break;
-
- default:
- HandleUnknownType(phdr.p_type, phdr.p_offset, phdr.p_filesz);
- break;
- }
- }
-}
-
-template <typename NhdrType>
-std::string ElfInterface::ReadBuildID() {
- // Ensure there is no overflow in any of the calulations below.
- uint64_t tmp;
- if (__builtin_add_overflow(gnu_build_id_offset_, gnu_build_id_size_, &tmp)) {
- return "";
- }
-
- uint64_t offset = 0;
- while (offset < gnu_build_id_size_) {
- if (gnu_build_id_size_ - offset < sizeof(NhdrType)) {
- return "";
- }
- NhdrType hdr;
- if (!memory_->ReadFully(gnu_build_id_offset_ + offset, &hdr, sizeof(hdr))) {
- return "";
- }
- offset += sizeof(hdr);
-
- if (gnu_build_id_size_ - offset < hdr.n_namesz) {
- return "";
- }
- if (hdr.n_namesz > 0) {
- std::string name(hdr.n_namesz, '\0');
- if (!memory_->ReadFully(gnu_build_id_offset_ + offset, &(name[0]), hdr.n_namesz)) {
- return "";
- }
-
- // Trim trailing \0 as GNU is stored as a C string in the ELF file.
- if (name.back() == '\0')
- name.resize(name.size() - 1);
-
- // Align hdr.n_namesz to next power multiple of 4. See man 5 elf.
- offset += (hdr.n_namesz + 3) & ~3;
-
- if (name == "GNU" && hdr.n_type == NT_GNU_BUILD_ID) {
- if (gnu_build_id_size_ - offset < hdr.n_descsz || hdr.n_descsz == 0) {
- return "";
- }
- std::string build_id(hdr.n_descsz, '\0');
- if (memory_->ReadFully(gnu_build_id_offset_ + offset, &build_id[0], hdr.n_descsz)) {
- return build_id;
- }
- return "";
- }
- }
- // Align hdr.n_descsz to next power multiple of 4. See man 5 elf.
- offset += (hdr.n_descsz + 3) & ~3;
- }
- return "";
-}
-
-template <typename EhdrType, typename ShdrType>
-void ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) {
- uint64_t offset = ehdr.e_shoff;
- uint64_t sec_offset = 0;
- uint64_t sec_size = 0;
-
- // Get the location of the section header names.
- // If something is malformed in the header table data, we aren't going
- // to terminate, we'll simply ignore this part.
- ShdrType shdr;
- if (ehdr.e_shstrndx < ehdr.e_shnum) {
- uint64_t sh_offset = offset + ehdr.e_shstrndx * ehdr.e_shentsize;
- if (memory_->ReadFully(sh_offset, &shdr, sizeof(shdr))) {
- sec_offset = shdr.sh_offset;
- sec_size = shdr.sh_size;
- }
- }
-
- // 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_->ReadFully(offset, &shdr, sizeof(shdr))) {
- return;
- }
-
- if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
- // 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) {
- continue;
- }
- uint64_t str_offset = ehdr.e_shoff + shdr.sh_link * ehdr.e_shentsize;
- if (!memory_->ReadFully(str_offset, &str_shdr, sizeof(str_shdr))) {
- continue;
- }
- if (str_shdr.sh_type != SHT_STRTAB) {
- continue;
- }
- 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 (shdr.sh_name < sec_size) {
- std::string name;
- if (memory_->ReadString(sec_offset + shdr.sh_name, &name, sec_size - shdr.sh_name)) {
- if (name == ".debug_frame") {
- debug_frame_offset_ = shdr.sh_offset;
- debug_frame_size_ = shdr.sh_size;
- debug_frame_section_bias_ = static_cast<uint64_t>(shdr.sh_addr) - shdr.sh_offset;
- } else if (name == ".gnu_debugdata") {
- gnu_debugdata_offset_ = shdr.sh_offset;
- gnu_debugdata_size_ = shdr.sh_size;
- } else if (name == ".eh_frame") {
- eh_frame_offset_ = shdr.sh_offset;
- eh_frame_section_bias_ = static_cast<uint64_t>(shdr.sh_addr) - shdr.sh_offset;
- eh_frame_size_ = shdr.sh_size;
- } else if (eh_frame_hdr_offset_ == 0 && name == ".eh_frame_hdr") {
- eh_frame_hdr_offset_ = shdr.sh_offset;
- eh_frame_hdr_section_bias_ = static_cast<uint64_t>(shdr.sh_addr) - shdr.sh_offset;
- eh_frame_hdr_size_ = shdr.sh_size;
- } else if (name == ".data") {
- data_offset_ = shdr.sh_offset;
- data_vaddr_start_ = shdr.sh_addr;
- if (__builtin_add_overflow(data_vaddr_start_, shdr.sh_size, &data_vaddr_end_)) {
- data_offset_ = 0;
- data_vaddr_start_ = 0;
- data_vaddr_end_ = 0;
- }
- }
- }
- }
- } else if (shdr.sh_type == SHT_STRTAB) {
- // In order to read soname, keep track of address to offset mapping.
- strtabs_.push_back(std::make_pair<uint64_t, uint64_t>(static_cast<uint64_t>(shdr.sh_addr),
- static_cast<uint64_t>(shdr.sh_offset)));
- } else if (shdr.sh_type == SHT_NOTE) {
- if (shdr.sh_name < sec_size) {
- std::string name;
- if (memory_->ReadString(sec_offset + shdr.sh_name, &name, sec_size - shdr.sh_name) &&
- name == ".note.gnu.build-id") {
- gnu_build_id_offset_ = shdr.sh_offset;
- gnu_build_id_size_ = shdr.sh_size;
- }
- }
- }
- }
-}
-
-template <typename DynType>
-std::string ElfInterface::GetSonameWithTemplate() {
- if (soname_type_ == SONAME_INVALID) {
- return "";
- }
- if (soname_type_ == SONAME_VALID) {
- return soname_;
- }
-
- soname_type_ = SONAME_INVALID;
-
- uint64_t soname_offset = 0;
- uint64_t strtab_addr = 0;
- uint64_t strtab_size = 0;
-
- // Find the soname location from the dynamic headers section.
- DynType dyn;
- uint64_t offset = dynamic_offset_;
- uint64_t max_offset = offset + dynamic_vaddr_end_ - dynamic_vaddr_start_;
- for (uint64_t offset = dynamic_offset_; offset < max_offset; offset += sizeof(DynType)) {
- if (!memory_->ReadFully(offset, &dyn, sizeof(dyn))) {
- last_error_.code = ERROR_MEMORY_INVALID;
- last_error_.address = offset;
- return "";
- }
-
- if (dyn.d_tag == DT_STRTAB) {
- strtab_addr = dyn.d_un.d_ptr;
- } else if (dyn.d_tag == DT_STRSZ) {
- strtab_size = dyn.d_un.d_val;
- } else if (dyn.d_tag == DT_SONAME) {
- soname_offset = dyn.d_un.d_val;
- } else if (dyn.d_tag == DT_NULL) {
- break;
- }
- }
-
- // Need to map the strtab address to the real offset.
- for (const auto& entry : strtabs_) {
- if (entry.first == strtab_addr) {
- soname_offset = entry.second + soname_offset;
- uint64_t soname_max = entry.second + strtab_size;
- if (soname_offset >= soname_max) {
- return "";
- }
- if (!memory_->ReadString(soname_offset, &soname_, soname_max - soname_offset)) {
- return "";
- }
- soname_type_ = SONAME_VALID;
- return soname_;
- }
- }
- return "";
-}
-
-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, memory_, name, func_offset)) {
- return true;
- }
- }
- return false;
-}
-
-template <typename SymType>
-bool ElfInterface::GetGlobalVariableWithTemplate(const std::string& name, uint64_t* memory_address) {
- if (symbols_.empty()) {
- return false;
- }
-
- for (const auto symbol : symbols_) {
- if (symbol->GetGlobal<SymType>(memory_, name, memory_address)) {
- return true;
- }
- }
- return false;
-}
-
-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, 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, is_signal_frame)) {
- return true;
- }
-
- if (gnu_debugdata_interface_ != nullptr &&
- gnu_debugdata_interface_->Step(pc, regs, process_memory, finished, is_signal_frame)) {
- return true;
- }
-
- // Set the error code based on the first error encountered.
- DwarfSection* section = nullptr;
- if (debug_frame_ != nullptr) {
- section = debug_frame_.get();
- } else if (eh_frame_ != nullptr) {
- section = eh_frame_.get();
- } else if (gnu_debugdata_interface_ != nullptr) {
- last_error_ = gnu_debugdata_interface_->last_error();
- return false;
- } else {
- return false;
- }
-
- // Convert the DWARF ERROR to an external error.
- DwarfErrorCode code = section->LastErrorCode();
- switch (code) {
- case DWARF_ERROR_NONE:
- last_error_.code = ERROR_NONE;
- break;
-
- case DWARF_ERROR_MEMORY_INVALID:
- last_error_.code = ERROR_MEMORY_INVALID;
- last_error_.address = section->LastErrorAddress();
- break;
-
- case DWARF_ERROR_ILLEGAL_VALUE:
- case DWARF_ERROR_ILLEGAL_STATE:
- case DWARF_ERROR_STACK_INDEX_NOT_VALID:
- case DWARF_ERROR_TOO_MANY_ITERATIONS:
- case DWARF_ERROR_CFA_NOT_DEFINED:
- case DWARF_ERROR_NO_FDES:
- last_error_.code = ERROR_UNWIND_INFO;
- break;
-
- case DWARF_ERROR_NOT_IMPLEMENTED:
- case DWARF_ERROR_UNSUPPORTED_VERSION:
- last_error_.code = ERROR_UNSUPPORTED;
- break;
- }
- return false;
-}
-
-// This is an estimation of the size of the elf file using the location
-// of the section headers and size. This assumes that the section headers
-// are at the end of the elf file. If the elf has a load bias, the size
-// will be too large, but this is acceptable.
-template <typename EhdrType>
-void ElfInterface::GetMaxSizeWithTemplate(Memory* memory, uint64_t* size) {
- EhdrType ehdr;
- if (!memory->ReadFully(0, &ehdr, sizeof(ehdr))) {
- return;
- }
- if (ehdr.e_shnum == 0) {
- return;
- }
- *size = ehdr.e_shoff + ehdr.e_shentsize * ehdr.e_shnum;
-}
-
-template <typename EhdrType, typename ShdrType>
-bool GetBuildIDInfo(Memory* memory, uint64_t* build_id_offset, uint64_t* build_id_size) {
- EhdrType ehdr;
- if (!memory->ReadFully(0, &ehdr, sizeof(ehdr))) {
- return false;
- }
-
- uint64_t offset = ehdr.e_shoff;
- uint64_t sec_offset;
- uint64_t sec_size;
- ShdrType shdr;
- if (ehdr.e_shstrndx >= ehdr.e_shnum) {
- return false;
- }
-
- uint64_t sh_offset = offset + ehdr.e_shstrndx * ehdr.e_shentsize;
- if (!memory->ReadFully(sh_offset, &shdr, sizeof(shdr))) {
- return false;
- }
- sec_offset = shdr.sh_offset;
- sec_size = shdr.sh_size;
-
- // 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->ReadFully(offset, &shdr, sizeof(shdr))) {
- return false;
- }
- std::string name;
- if (shdr.sh_type == SHT_NOTE && shdr.sh_name < sec_size &&
- memory->ReadString(sec_offset + shdr.sh_name, &name, sec_size - shdr.sh_name) &&
- name == ".note.gnu.build-id") {
- *build_id_offset = shdr.sh_offset;
- *build_id_size = shdr.sh_size;
- return true;
- }
- }
-
- return false;
-}
-
-template <typename EhdrType, typename ShdrType, typename NhdrType>
-std::string ElfInterface::ReadBuildIDFromMemory(Memory* memory) {
- uint64_t note_offset;
- uint64_t note_size;
- if (!GetBuildIDInfo<EhdrType, ShdrType>(memory, ¬e_offset, ¬e_size)) {
- return "";
- }
-
- // Ensure there is no overflow in any of the calculations below.
- uint64_t tmp;
- if (__builtin_add_overflow(note_offset, note_size, &tmp)) {
- return "";
- }
-
- uint64_t offset = 0;
- while (offset < note_size) {
- if (note_size - offset < sizeof(NhdrType)) {
- return "";
- }
- NhdrType hdr;
- if (!memory->ReadFully(note_offset + offset, &hdr, sizeof(hdr))) {
- return "";
- }
- offset += sizeof(hdr);
-
- if (note_size - offset < hdr.n_namesz) {
- return "";
- }
- if (hdr.n_namesz > 0) {
- std::string name(hdr.n_namesz, '\0');
- if (!memory->ReadFully(note_offset + offset, &(name[0]), hdr.n_namesz)) {
- return "";
- }
-
- // Trim trailing \0 as GNU is stored as a C string in the ELF file.
- if (name.back() == '\0') name.resize(name.size() - 1);
-
- // Align hdr.n_namesz to next power multiple of 4. See man 5 elf.
- offset += (hdr.n_namesz + 3) & ~3;
-
- if (name == "GNU" && hdr.n_type == NT_GNU_BUILD_ID) {
- if (note_size - offset < hdr.n_descsz || hdr.n_descsz == 0) {
- return "";
- }
- std::string build_id(hdr.n_descsz, '\0');
- if (memory->ReadFully(note_offset + offset, &build_id[0], hdr.n_descsz)) {
- return build_id;
- }
- return "";
- }
- }
- // Align hdr.n_descsz to next power multiple of 4. See man 5 elf.
- offset += (hdr.n_descsz + 3) & ~3;
- }
- return "";
-}
-
-// Instantiate all of the needed template functions.
-template void ElfInterface::InitHeadersWithTemplate<uint32_t>();
-template void ElfInterface::InitHeadersWithTemplate<uint64_t>();
-
-template bool ElfInterface::ReadAllHeaders<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(int64_t*);
-template bool ElfInterface::ReadAllHeaders<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(int64_t*);
-
-template void ElfInterface::ReadProgramHeaders<Elf32_Ehdr, Elf32_Phdr>(const Elf32_Ehdr&, int64_t*);
-template void ElfInterface::ReadProgramHeaders<Elf64_Ehdr, Elf64_Phdr>(const Elf64_Ehdr&, int64_t*);
-
-template void ElfInterface::ReadSectionHeaders<Elf32_Ehdr, Elf32_Shdr>(const Elf32_Ehdr&);
-template void ElfInterface::ReadSectionHeaders<Elf64_Ehdr, Elf64_Shdr>(const Elf64_Ehdr&);
-
-template std::string ElfInterface::ReadBuildID<Elf32_Nhdr>();
-template std::string ElfInterface::ReadBuildID<Elf64_Nhdr>();
-
-template std::string ElfInterface::GetSonameWithTemplate<Elf32_Dyn>();
-template std::string ElfInterface::GetSonameWithTemplate<Elf64_Dyn>();
-
-template bool ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(uint64_t, std::string*,
- uint64_t*);
-template bool ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(uint64_t, std::string*,
- uint64_t*);
-
-template bool ElfInterface::GetGlobalVariableWithTemplate<Elf32_Sym>(const std::string&, uint64_t*);
-template bool ElfInterface::GetGlobalVariableWithTemplate<Elf64_Sym>(const std::string&, uint64_t*);
-
-template void ElfInterface::GetMaxSizeWithTemplate<Elf32_Ehdr>(Memory*, uint64_t*);
-template void ElfInterface::GetMaxSizeWithTemplate<Elf64_Ehdr>(Memory*, uint64_t*);
-
-template int64_t ElfInterface::GetLoadBias<Elf32_Ehdr, Elf32_Phdr>(Memory*);
-template int64_t ElfInterface::GetLoadBias<Elf64_Ehdr, Elf64_Phdr>(Memory*);
-
-template std::string ElfInterface::ReadBuildIDFromMemory<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr>(
- Memory*);
-template std::string ElfInterface::ReadBuildIDFromMemory<Elf64_Ehdr, Elf64_Shdr, Elf64_Nhdr>(
- Memory*);
-
-} // namespace unwindstack
diff --git a/libunwindstack/ElfInterfaceArm.cpp b/libunwindstack/ElfInterfaceArm.cpp
deleted file mode 100644
index 9352a5d..0000000
--- a/libunwindstack/ElfInterfaceArm.cpp
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2016 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 <elf.h>
-#include <stdint.h>
-
-#include <unwindstack/MachineArm.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/RegsArm.h>
-
-#include "ArmExidx.h"
-#include "ElfInterfaceArm.h"
-
-namespace unwindstack {
-
-bool ElfInterfaceArm::Init(int64_t* load_bias) {
- if (!ElfInterface32::Init(load_bias)) {
- return false;
- }
- load_bias_ = *load_bias;
- return true;
-}
-
-bool ElfInterfaceArm::FindEntry(uint32_t pc, uint64_t* entry_offset) {
- if (start_offset_ == 0 || total_entries_ == 0) {
- last_error_.code = ERROR_UNWIND_INFO;
- return false;
- }
-
- size_t first = 0;
- size_t last = total_entries_;
- while (first < last) {
- size_t current = (first + last) / 2;
- uint32_t addr = addrs_[current];
- if (addr == 0) {
- if (!GetPrel31Addr(start_offset_ + current * 8, &addr)) {
- return false;
- }
- addrs_[current] = addr;
- }
- if (pc == addr) {
- *entry_offset = start_offset_ + current * 8;
- return true;
- }
- if (pc < addr) {
- last = current;
- } else {
- first = current + 1;
- }
- }
- if (last != 0) {
- *entry_offset = start_offset_ + (last - 1) * 8;
- return true;
- }
- last_error_.code = ERROR_UNWIND_INFO;
- return false;
-}
-
-bool ElfInterfaceArm::GetPrel31Addr(uint32_t offset, uint32_t* addr) {
- uint32_t data;
- if (!memory_->Read32(offset, &data)) {
- last_error_.code = ERROR_MEMORY_INVALID;
- last_error_.address = offset;
- return false;
- }
-
- // Sign extend the value if necessary.
- int32_t value = (static_cast<int32_t>(data) << 1) >> 1;
- *addr = offset + value;
- return true;
-}
-
-#if !defined(PT_ARM_EXIDX)
-#define PT_ARM_EXIDX 0x70000001
-#endif
-
-void ElfInterfaceArm::HandleUnknownType(uint32_t type, uint64_t ph_offset, uint64_t ph_filesz) {
- if (type != PT_ARM_EXIDX) {
- return;
- }
-
- // The offset already takes into account the load bias.
- start_offset_ = ph_offset;
-
- // Always use filesz instead of memsz. In most cases they are the same,
- // but some shared libraries wind up setting one correctly and not the other.
- total_entries_ = ph_filesz / 8;
-}
-
-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, is_signal_frame) ||
- StepExidx(pc, regs, process_memory, finished);
-}
-
-bool ElfInterfaceArm::StepExidx(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) {
- // Adjust the load bias to get the real relative pc.
- if (pc < load_bias_) {
- last_error_.code = ERROR_UNWIND_INFO;
- return false;
- }
- pc -= load_bias_;
-
- RegsArm* regs_arm = reinterpret_cast<RegsArm*>(regs);
- uint64_t entry_offset;
- if (!FindEntry(pc, &entry_offset)) {
- return false;
- }
-
- ArmExidx arm(regs_arm, memory_, process_memory);
- arm.set_cfa(regs_arm->sp());
- bool return_value = false;
- if (arm.ExtractEntryData(entry_offset) && arm.Eval()) {
- // If the pc was not set, then use the LR registers for the PC.
- if (!arm.pc_set()) {
- (*regs_arm)[ARM_REG_PC] = (*regs_arm)[ARM_REG_LR];
- }
- (*regs_arm)[ARM_REG_SP] = arm.cfa();
- return_value = true;
-
- // If the pc was set to zero, consider this the final frame.
- *finished = (regs_arm->pc() == 0) ? true : false;
- }
-
- if (arm.status() == ARM_STATUS_NO_UNWIND) {
- *finished = true;
- return true;
- }
-
- if (!return_value) {
- switch (arm.status()) {
- case ARM_STATUS_NONE:
- case ARM_STATUS_NO_UNWIND:
- case ARM_STATUS_FINISH:
- last_error_.code = ERROR_NONE;
- break;
-
- case ARM_STATUS_RESERVED:
- case ARM_STATUS_SPARE:
- case ARM_STATUS_TRUNCATED:
- case ARM_STATUS_MALFORMED:
- case ARM_STATUS_INVALID_ALIGNMENT:
- case ARM_STATUS_INVALID_PERSONALITY:
- last_error_.code = ERROR_UNWIND_INFO;
- break;
-
- case ARM_STATUS_READ_FAILED:
- last_error_.code = ERROR_MEMORY_INVALID;
- last_error_.address = arm.status_address();
- break;
- }
- }
- return return_value;
-}
-
-bool ElfInterfaceArm::GetFunctionName(uint64_t addr, std::string* name, uint64_t* offset) {
- // For ARM, thumb function symbols have bit 0 set, but the address passed
- // in here might not have this bit set and result in a failure to find
- // the thumb function names. Adjust the address and offset to account
- // for this possible case.
- if (ElfInterface32::GetFunctionName(addr | 1, name, offset)) {
- *offset &= ~1;
- return true;
- }
- return false;
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/ElfInterfaceArm.h b/libunwindstack/ElfInterfaceArm.h
deleted file mode 100644
index fd824f8..0000000
--- a/libunwindstack/ElfInterfaceArm.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_ELF_INTERFACE_ARM_H
-#define _LIBUNWINDSTACK_ELF_INTERFACE_ARM_H
-
-#include <elf.h>
-#include <stdint.h>
-
-#include <iterator>
-#include <unordered_map>
-
-#include <unwindstack/ElfInterface.h>
-#include <unwindstack/Memory.h>
-
-namespace unwindstack {
-
-class ElfInterfaceArm : public ElfInterface32 {
- public:
- ElfInterfaceArm(Memory* memory) : ElfInterface32(memory) {}
- virtual ~ElfInterfaceArm() = default;
-
- class iterator : public std::iterator<std::bidirectional_iterator_tag, uint32_t> {
- public:
- iterator(ElfInterfaceArm* interface, size_t index) : interface_(interface), index_(index) { }
-
- iterator& operator++() { index_++; return *this; }
- iterator& operator++(int increment) { index_ += increment; return *this; }
- iterator& operator--() { index_--; return *this; }
- iterator& operator--(int decrement) { index_ -= decrement; return *this; }
-
- bool operator==(const iterator& rhs) { return this->index_ == rhs.index_; }
- bool operator!=(const iterator& rhs) { return this->index_ != rhs.index_; }
-
- uint32_t operator*() {
- uint32_t addr = interface_->addrs_[index_];
- if (addr == 0) {
- if (!interface_->GetPrel31Addr(interface_->start_offset_ + index_ * 8, &addr)) {
- return 0;
- }
- interface_->addrs_[index_] = addr;
- }
- return addr;
- }
-
- private:
- ElfInterfaceArm* interface_ = nullptr;
- size_t index_ = 0;
- };
-
- iterator begin() { return iterator(this, 0); }
- iterator end() { return iterator(this, total_entries_); }
-
- bool Init(int64_t* section_bias) override;
-
- bool GetPrel31Addr(uint32_t offset, uint32_t* addr);
-
- bool FindEntry(uint32_t pc, uint64_t* entry_offset);
-
- 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,
- bool* is_signal_frame) override;
-
- bool StepExidx(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished);
-
- bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* offset) override;
-
- uint64_t start_offset() { return start_offset_; }
-
- size_t total_entries() { return total_entries_; }
-
- void set_load_bias(uint64_t load_bias) { load_bias_ = load_bias; }
-
- protected:
- uint64_t start_offset_ = 0;
- size_t total_entries_ = 0;
- uint64_t load_bias_ = 0;
-
- std::unordered_map<size_t, uint32_t> addrs_;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_ELF_INTERFACE_ARM_H
diff --git a/libunwindstack/Global.cpp b/libunwindstack/Global.cpp
deleted file mode 100644
index ee6c8a5..0000000
--- a/libunwindstack/Global.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2018 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 <stdint.h>
-#include <string.h>
-#include <sys/mman.h>
-
-#include <string>
-#include <vector>
-
-#include <unwindstack/Global.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
-
-namespace unwindstack {
-
-Global::Global(std::shared_ptr<Memory>& memory) : memory_(memory) {}
-Global::Global(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs)
- : memory_(memory), search_libs_(search_libs) {}
-
-void Global::SetArch(ArchEnum arch) {
- if (arch_ == ARCH_UNKNOWN) {
- arch_ = arch;
- ProcessArch();
- }
-}
-
-bool Global::Searchable(const std::string& name) {
- if (search_libs_.empty()) {
- return true;
- }
-
- if (name.empty()) {
- return false;
- }
-
- const char* base_name = basename(name.c_str());
- for (const std::string& lib : search_libs_) {
- if (base_name == lib) {
- return true;
- }
- }
- return false;
-}
-
-void Global::FindAndReadVariable(Maps* maps, const char* var_str) {
- std::string variable(var_str);
- // When looking for global variables, do not arbitrarily search every
- // readable map. Instead look for a specific pattern that must exist.
- // The pattern should be a readable map, followed by a read-write
- // map with a non-zero offset.
- // For example:
- // f0000-f1000 0 r-- /system/lib/libc.so
- // f1000-f2000 1000 r-x /system/lib/libc.so
- // f2000-f3000 2000 rw- /system/lib/libc.so
- // This also works:
- // f0000-f2000 0 r-- /system/lib/libc.so
- // f2000-f3000 2000 rw- /system/lib/libc.so
- // It is also possible to see empty maps after the read-only like so:
- // f0000-f1000 0 r-- /system/lib/libc.so
- // f1000-f2000 0 ---
- // f2000-f3000 1000 r-x /system/lib/libc.so
- // f3000-f4000 2000 rw- /system/lib/libc.so
- MapInfo* map_zero = nullptr;
- for (const auto& info : *maps) {
- if (info->offset != 0 && (info->flags & (PROT_READ | PROT_WRITE)) == (PROT_READ | PROT_WRITE) &&
- map_zero != nullptr && Searchable(info->name) && info->name == map_zero->name) {
- Elf* elf = map_zero->GetElf(memory_, arch());
- uint64_t ptr;
- if (elf->GetGlobalVariableOffset(variable, &ptr) && ptr != 0) {
- uint64_t offset_end = info->offset + info->end - info->start;
- if (ptr >= info->offset && ptr < offset_end) {
- ptr = info->start + ptr - info->offset;
- if (ReadVariableData(ptr)) {
- break;
- }
- }
- }
- } else if (info->offset == 0 && !info->name.empty()) {
- map_zero = info.get();
- }
- }
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/JitDebug.cpp b/libunwindstack/JitDebug.cpp
deleted file mode 100644
index 8a85607..0000000
--- a/libunwindstack/JitDebug.cpp
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 2017 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 <stdint.h>
-#include <sys/mman.h>
-
-#include <memory>
-#include <vector>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/JitDebug.h>
-#include <unwindstack/Maps.h>
-
-#include "MemoryRange.h"
-
-// This implements the JIT Compilation Interface.
-// See https://sourceware.org/gdb/onlinedocs/gdb/JIT-Interface.html
-
-namespace unwindstack {
-
-struct JITCodeEntry32Pack {
- uint32_t next;
- uint32_t prev;
- uint32_t symfile_addr;
- uint64_t symfile_size;
-} __attribute__((packed));
-
-struct JITCodeEntry32Pad {
- uint32_t next;
- uint32_t prev;
- uint32_t symfile_addr;
- uint32_t pad;
- uint64_t symfile_size;
-};
-
-struct JITCodeEntry64 {
- uint64_t next;
- uint64_t prev;
- uint64_t symfile_addr;
- uint64_t symfile_size;
-};
-
-struct JITDescriptorHeader {
- uint32_t version;
- uint32_t action_flag;
-};
-
-struct JITDescriptor32 {
- JITDescriptorHeader header;
- uint32_t relevant_entry;
- uint32_t first_entry;
-};
-
-struct JITDescriptor64 {
- JITDescriptorHeader header;
- uint64_t relevant_entry;
- uint64_t first_entry;
-};
-
-JitDebug::JitDebug(std::shared_ptr<Memory>& memory) : Global(memory) {}
-
-JitDebug::JitDebug(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs)
- : Global(memory, search_libs) {}
-
-JitDebug::~JitDebug() {
- for (auto* elf : elf_list_) {
- delete elf;
- }
-}
-
-uint64_t JitDebug::ReadDescriptor32(uint64_t addr) {
- JITDescriptor32 desc;
- if (!memory_->ReadFully(addr, &desc, sizeof(desc))) {
- return 0;
- }
-
- if (desc.header.version != 1 || desc.first_entry == 0) {
- // Either unknown version, or no jit entries.
- return 0;
- }
-
- return desc.first_entry;
-}
-
-uint64_t JitDebug::ReadDescriptor64(uint64_t addr) {
- JITDescriptor64 desc;
- if (!memory_->ReadFully(addr, &desc, sizeof(desc))) {
- return 0;
- }
-
- if (desc.header.version != 1 || desc.first_entry == 0) {
- // Either unknown version, or no jit entries.
- return 0;
- }
-
- return desc.first_entry;
-}
-
-uint64_t JitDebug::ReadEntry32Pack(uint64_t* start, uint64_t* size) {
- JITCodeEntry32Pack code;
- if (!memory_->ReadFully(entry_addr_, &code, sizeof(code))) {
- return 0;
- }
-
- *start = code.symfile_addr;
- *size = code.symfile_size;
- return code.next;
-}
-
-uint64_t JitDebug::ReadEntry32Pad(uint64_t* start, uint64_t* size) {
- JITCodeEntry32Pad code;
- if (!memory_->ReadFully(entry_addr_, &code, sizeof(code))) {
- return 0;
- }
-
- *start = code.symfile_addr;
- *size = code.symfile_size;
- return code.next;
-}
-
-uint64_t JitDebug::ReadEntry64(uint64_t* start, uint64_t* size) {
- JITCodeEntry64 code;
- if (!memory_->ReadFully(entry_addr_, &code, sizeof(code))) {
- return 0;
- }
-
- *start = code.symfile_addr;
- *size = code.symfile_size;
- return code.next;
-}
-
-void JitDebug::ProcessArch() {
- switch (arch()) {
- case ARCH_X86:
- read_descriptor_func_ = &JitDebug::ReadDescriptor32;
- read_entry_func_ = &JitDebug::ReadEntry32Pack;
- break;
-
- case ARCH_ARM:
- case ARCH_MIPS:
- read_descriptor_func_ = &JitDebug::ReadDescriptor32;
- read_entry_func_ = &JitDebug::ReadEntry32Pad;
- break;
-
- case ARCH_ARM64:
- case ARCH_X86_64:
- case ARCH_MIPS64:
- read_descriptor_func_ = &JitDebug::ReadDescriptor64;
- read_entry_func_ = &JitDebug::ReadEntry64;
- break;
- case ARCH_UNKNOWN:
- abort();
- }
-}
-
-bool JitDebug::ReadVariableData(uint64_t ptr) {
- entry_addr_ = (this->*read_descriptor_func_)(ptr);
- return entry_addr_ != 0;
-}
-
-void JitDebug::Init(Maps* maps) {
- if (initialized_) {
- return;
- }
- // Regardless of what happens below, consider the init finished.
- initialized_ = true;
-
- FindAndReadVariable(maps, "__jit_debug_descriptor");
-}
-
-Elf* JitDebug::GetElf(Maps* maps, uint64_t pc) {
- // Use a single lock, this object should be used so infrequently that
- // a fine grain lock is unnecessary.
- std::lock_guard<std::mutex> guard(lock_);
- if (!initialized_) {
- Init(maps);
- }
-
- // Search the existing elf object first.
- for (Elf* elf : elf_list_) {
- if (elf->IsValidPc(pc)) {
- return elf;
- }
- }
-
- while (entry_addr_ != 0) {
- uint64_t start;
- uint64_t size;
- entry_addr_ = (this->*read_entry_func_)(&start, &size);
-
- Elf* elf = new Elf(new MemoryRange(memory_, start, size, 0));
- elf->Init();
- if (!elf->valid()) {
- // The data is not formatted in a way we understand, do not attempt
- // to process any other entries.
- entry_addr_ = 0;
- delete elf;
- return nullptr;
- }
- elf_list_.push_back(elf);
-
- if (elf->IsValidPc(pc)) {
- return elf;
- }
- }
- return nullptr;
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/LocalUnwinder.cpp b/libunwindstack/LocalUnwinder.cpp
deleted file mode 100644
index 5f51a73..0000000
--- a/libunwindstack/LocalUnwinder.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <pthread.h>
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/LocalUnwinder.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/Regs.h>
-#include <unwindstack/RegsGetLocal.h>
-
-namespace unwindstack {
-
-bool LocalUnwinder::Init() {
- pthread_rwlock_init(&maps_rwlock_, nullptr);
-
- // Create the maps.
- maps_.reset(new unwindstack::LocalUpdatableMaps());
- if (!maps_->Parse()) {
- maps_.reset();
- return false;
- }
-
- process_memory_ = unwindstack::Memory::CreateProcessMemory(getpid());
-
- return true;
-}
-
-bool LocalUnwinder::ShouldSkipLibrary(const std::string& map_name) {
- for (const std::string& skip_library : skip_libraries_) {
- if (skip_library == map_name) {
- return true;
- }
- }
- return false;
-}
-
-MapInfo* LocalUnwinder::GetMapInfo(uint64_t pc) {
- pthread_rwlock_rdlock(&maps_rwlock_);
- MapInfo* map_info = maps_->Find(pc);
- pthread_rwlock_unlock(&maps_rwlock_);
-
- if (map_info == nullptr) {
- pthread_rwlock_wrlock(&maps_rwlock_);
- // This is guaranteed not to invalidate any previous MapInfo objects so
- // we don't need to worry about any MapInfo* values already in use.
- if (maps_->Reparse()) {
- map_info = maps_->Find(pc);
- }
- pthread_rwlock_unlock(&maps_rwlock_);
- }
-
- return map_info;
-}
-
-bool LocalUnwinder::Unwind(std::vector<LocalFrameData>* frame_info, size_t max_frames) {
- std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromLocal());
- unwindstack::RegsGetLocal(regs.get());
- ArchEnum arch = regs->Arch();
-
- size_t num_frames = 0;
- bool adjust_pc = false;
- while (true) {
- uint64_t cur_pc = regs->pc();
- uint64_t cur_sp = regs->sp();
-
- MapInfo* map_info = GetMapInfo(cur_pc);
- if (map_info == nullptr) {
- break;
- }
-
- Elf* elf = map_info->GetElf(process_memory_, arch);
- uint64_t rel_pc = elf->GetRelPc(cur_pc, map_info);
- uint64_t step_pc = rel_pc;
- uint64_t pc_adjustment;
- if (adjust_pc) {
- pc_adjustment = GetPcAdjustment(rel_pc, elf, arch);
- } else {
- pc_adjustment = 0;
- }
- 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,
- &is_signal_frame)) {
- finished = true;
- }
-
- // Skip any locations that are within this library.
- if (num_frames != 0 || !ShouldSkipLibrary(map_info->name)) {
- // Add frame information.
- std::string func_name;
- uint64_t func_offset;
- if (elf->GetFunctionName(rel_pc, &func_name, &func_offset)) {
- frame_info->emplace_back(map_info, cur_pc - pc_adjustment, rel_pc - pc_adjustment,
- func_name, func_offset);
- } else {
- frame_info->emplace_back(map_info, cur_pc - pc_adjustment, rel_pc - pc_adjustment, "", 0);
- }
- num_frames++;
- }
-
- if (finished || frame_info->size() == max_frames ||
- (cur_pc == regs->pc() && cur_sp == regs->sp())) {
- break;
- }
- adjust_pc = true;
- }
- return num_frames != 0;
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/Log.cpp b/libunwindstack/Log.cpp
deleted file mode 100644
index 436e23c..0000000
--- a/libunwindstack/Log.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2016 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 <stdarg.h>
-#include <stdint.h>
-#include <stdio.h>
-
-#include <string>
-
-#define LOG_TAG "unwind"
-#include <log/log.h>
-
-#include <android-base/stringprintf.h>
-
-#include <unwindstack/Log.h>
-
-namespace unwindstack {
-
-static bool g_print_to_stdout = false;
-
-void log_to_stdout(bool enable) {
- g_print_to_stdout = enable;
-}
-
-// Send the data to the log.
-void log(uint8_t indent, const char* format, ...) {
- std::string real_format;
- if (indent > 0) {
- real_format = android::base::StringPrintf("%*s%s", 2 * indent, " ", format);
- } else {
- real_format = format;
- }
- va_list args;
- va_start(args, format);
- if (g_print_to_stdout) {
- real_format += '\n';
- vprintf(real_format.c_str(), args);
- } else {
- LOG_PRI_VA(ANDROID_LOG_INFO, LOG_TAG, real_format.c_str(), args);
- }
- va_end(args);
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/MapInfo.cpp b/libunwindstack/MapInfo.cpp
deleted file mode 100644
index 31f3144..0000000
--- a/libunwindstack/MapInfo.cpp
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * Copyright (C) 2017 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 <stdint.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <memory>
-#include <mutex>
-#include <string>
-
-#include <android-base/stringprintf.h>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Maps.h>
-
-#include "MemoryFileAtOffset.h"
-#include "MemoryRange.h"
-
-namespace unwindstack {
-
-bool MapInfo::InitFileMemoryFromPreviousReadOnlyMap(MemoryFileAtOffset* memory) {
- // One last attempt, see if the previous map is read-only with the
- // same name and stretches across this map.
- if (prev_real_map == nullptr || prev_real_map->flags != PROT_READ) {
- return false;
- }
-
- uint64_t map_size = end - prev_real_map->end;
- if (!memory->Init(name, prev_real_map->offset, map_size)) {
- return false;
- }
-
- uint64_t max_size;
- if (!Elf::GetInfo(memory, &max_size) || max_size < map_size) {
- return false;
- }
-
- if (!memory->Init(name, prev_real_map->offset, max_size)) {
- return false;
- }
-
- elf_offset = offset - prev_real_map->offset;
- elf_start_offset = prev_real_map->offset;
- return true;
-}
-
-Memory* MapInfo::GetFileMemory() {
- std::unique_ptr<MemoryFileAtOffset> memory(new MemoryFileAtOffset);
- if (offset == 0) {
- if (memory->Init(name, 0)) {
- return memory.release();
- }
- return nullptr;
- }
-
- // These are the possibilities when the offset is non-zero.
- // - There is an elf file embedded in a file, and the offset is the
- // the start of the elf in the file.
- // - There is an elf file embedded in a file, and the offset is the
- // the start of the executable part of the file. The actual start
- // of the elf is in the read-only segment preceeding this map.
- // - The whole file is an elf file, and the offset needs to be saved.
- //
- // Map in just the part of the file for the map. If this is not
- // a valid elf, then reinit as if the whole file is an elf file.
- // If the offset is a valid elf, then determine the size of the map
- // and reinit to that size. This is needed because the dynamic linker
- // only maps in a portion of the original elf, and never the symbol
- // file data.
- uint64_t map_size = end - start;
- if (!memory->Init(name, offset, map_size)) {
- return nullptr;
- }
-
- // Check if the start of this map is an embedded elf.
- uint64_t max_size = 0;
- if (Elf::GetInfo(memory.get(), &max_size)) {
- elf_start_offset = offset;
- if (max_size > map_size) {
- if (memory->Init(name, offset, max_size)) {
- return memory.release();
- }
- // Try to reinit using the default map_size.
- if (memory->Init(name, offset, map_size)) {
- return memory.release();
- }
- elf_start_offset = 0;
- return nullptr;
- }
- return memory.release();
- }
-
- // No elf at offset, try to init as if the whole file is an elf.
- if (memory->Init(name, 0) && Elf::IsValidElf(memory.get())) {
- elf_offset = offset;
- // Need to check how to set the elf start offset. If this map is not
- // the r-x map of a r-- map, then use the real offset value. Otherwise,
- // use 0.
- if (prev_real_map == nullptr || prev_real_map->offset != 0 ||
- prev_real_map->flags != PROT_READ || prev_real_map->name != name) {
- elf_start_offset = offset;
- }
- return memory.release();
- }
-
- // See if the map previous to this one contains a read-only map
- // that represents the real start of the elf data.
- if (InitFileMemoryFromPreviousReadOnlyMap(memory.get())) {
- return memory.release();
- }
-
- // Failed to find elf at start of file or at read-only map, return
- // file object from the current map.
- if (memory->Init(name, offset, map_size)) {
- return memory.release();
- }
- return nullptr;
-}
-
-Memory* MapInfo::CreateMemory(const std::shared_ptr<Memory>& process_memory) {
- if (end <= start) {
- return nullptr;
- }
-
- elf_offset = 0;
-
- // Fail on device maps.
- if (flags & MAPS_FLAGS_DEVICE_MAP) {
- return nullptr;
- }
-
- // First try and use the file associated with the info.
- if (!name.empty()) {
- Memory* memory = GetFileMemory();
- if (memory != nullptr) {
- return memory;
- }
- }
-
- if (process_memory == nullptr) {
- return nullptr;
- }
-
- // Need to verify that this elf is valid. It's possible that
- // only part of the elf file to be mapped into memory is in the executable
- // map. In this case, there will be another read-only map that includes the
- // first part of the elf file. This is done if the linker rosegment
- // option is used.
- std::unique_ptr<MemoryRange> memory(new MemoryRange(process_memory, start, end - start, 0));
- if (Elf::IsValidElf(memory.get())) {
- memory_backed_elf = true;
- return memory.release();
- }
-
- // Find the read-only map by looking at the previous map. The linker
- // doesn't guarantee that this invariant will always be true. However,
- // if that changes, there is likely something else that will change and
- // break something.
- if (offset == 0 || name.empty() || prev_real_map == nullptr || prev_real_map->name != name ||
- prev_real_map->offset >= offset) {
- return nullptr;
- }
-
- // Make sure that relative pc values are corrected properly.
- elf_offset = offset - prev_real_map->offset;
- // Use this as the elf start offset, otherwise, you always get offsets into
- // the r-x section, which is not quite the right information.
- elf_start_offset = prev_real_map->offset;
-
- MemoryRanges* ranges = new MemoryRanges;
- ranges->Insert(new MemoryRange(process_memory, prev_real_map->start,
- prev_real_map->end - prev_real_map->start, 0));
- ranges->Insert(new MemoryRange(process_memory, start, end - start, elf_offset));
-
- memory_backed_elf = true;
- return ranges;
-}
-
-Elf* MapInfo::GetElf(const std::shared_ptr<Memory>& process_memory, ArchEnum expected_arch) {
- {
- // Make sure no other thread is trying to add the elf to this map.
- std::lock_guard<std::mutex> guard(mutex_);
-
- if (elf.get() != nullptr) {
- return elf.get();
- }
-
- bool locked = false;
- if (Elf::CachingEnabled() && !name.empty()) {
- Elf::CacheLock();
- locked = true;
- if (Elf::CacheGet(this)) {
- Elf::CacheUnlock();
- return elf.get();
- }
- }
-
- Memory* memory = CreateMemory(process_memory);
- if (locked) {
- if (Elf::CacheAfterCreateMemory(this)) {
- delete memory;
- Elf::CacheUnlock();
- return elf.get();
- }
- }
- elf.reset(new Elf(memory));
- // If the init fails, keep the elf around as an invalid object so we
- // don't try to reinit the object.
- elf->Init();
- if (elf->valid() && expected_arch != elf->arch()) {
- // Make the elf invalid, mismatch between arch and expected arch.
- elf->Invalidate();
- }
-
- if (locked) {
- Elf::CacheAdd(this);
- Elf::CacheUnlock();
- }
- }
-
- if (!elf->valid()) {
- elf_start_offset = offset;
- } else if (prev_real_map != nullptr && elf_start_offset != offset &&
- prev_real_map->offset == elf_start_offset && prev_real_map->name == name) {
- // If there is a read-only map then a read-execute map that represents the
- // same elf object, make sure the previous map is using the same elf
- // object if it hasn't already been set.
- std::lock_guard<std::mutex> guard(prev_real_map->mutex_);
- if (prev_real_map->elf.get() == nullptr) {
- prev_real_map->elf = elf;
- prev_real_map->memory_backed_elf = memory_backed_elf;
- }
- }
- return elf.get();
-}
-
-bool MapInfo::GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) {
- {
- // Make sure no other thread is trying to update this elf object.
- std::lock_guard<std::mutex> guard(mutex_);
- if (elf == nullptr) {
- return false;
- }
- }
- // No longer need the lock, once the elf object is created, it is not deleted
- // until this object is deleted.
- return elf->GetFunctionName(addr, name, func_offset);
-}
-
-uint64_t MapInfo::GetLoadBias(const std::shared_ptr<Memory>& process_memory) {
- int64_t cur_load_bias = load_bias.load();
- if (cur_load_bias != INT64_MAX) {
- return cur_load_bias;
- }
-
- {
- // Make sure no other thread is trying to add the elf to this map.
- std::lock_guard<std::mutex> guard(mutex_);
- if (elf != nullptr) {
- if (elf->valid()) {
- cur_load_bias = elf->GetLoadBias();
- load_bias = cur_load_bias;
- return cur_load_bias;
- } else {
- load_bias = 0;
- return 0;
- }
- }
- }
-
- // Call lightweight static function that will only read enough of the
- // elf data to get the load bias.
- std::unique_ptr<Memory> memory(CreateMemory(process_memory));
- cur_load_bias = Elf::GetLoadBias(memory.get());
- load_bias = cur_load_bias;
- return cur_load_bias;
-}
-
-MapInfo::~MapInfo() {
- uintptr_t id = build_id.load();
- if (id != 0) {
- delete reinterpret_cast<std::string*>(id);
- }
-}
-
-std::string MapInfo::GetBuildID() {
- uintptr_t id = build_id.load();
- if (id != 0) {
- return *reinterpret_cast<std::string*>(id);
- }
-
- // No need to lock, at worst if multiple threads do this at the same
- // time it should be detected and only one thread should win and
- // save the data.
- std::unique_ptr<std::string> cur_build_id(new std::string);
-
- // Now need to see if the elf object exists.
- // Make sure no other thread is trying to add the elf to this map.
- mutex_.lock();
- Elf* elf_obj = elf.get();
- mutex_.unlock();
- if (elf_obj != nullptr) {
- *cur_build_id = elf_obj->GetBuildID();
- } else {
- // This will only work if we can get the file associated with this memory.
- // If this is only available in memory, then the section name information
- // is not present and we will not be able to find the build id info.
- std::unique_ptr<Memory> memory(GetFileMemory());
- if (memory != nullptr) {
- *cur_build_id = Elf::GetBuildID(memory.get());
- }
- }
-
- id = reinterpret_cast<uintptr_t>(cur_build_id.get());
- uintptr_t expected_id = 0;
- if (build_id.compare_exchange_weak(expected_id, id)) {
- // Value saved, so make sure the memory is not freed.
- cur_build_id.release();
- }
- return *reinterpret_cast<std::string*>(id);
-}
-
-std::string MapInfo::GetPrintableBuildID() {
- std::string raw_build_id = GetBuildID();
- if (raw_build_id.empty()) {
- return "";
- }
- std::string printable_build_id;
- for (const char& c : raw_build_id) {
- // Use %hhx to avoid sign extension on abis that have signed chars.
- printable_build_id += android::base::StringPrintf("%02hhx", c);
- }
- return printable_build_id;
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/Maps.cpp b/libunwindstack/Maps.cpp
deleted file mode 100644
index 670d904..0000000
--- a/libunwindstack/Maps.cpp
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (C) 2016 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 <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <android-base/unique_fd.h>
-#include <procinfo/process_map.h>
-
-#include <algorithm>
-#include <cctype>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
-
-namespace unwindstack {
-
-MapInfo* Maps::Find(uint64_t pc) {
- if (maps_.empty()) {
- return nullptr;
- }
- size_t first = 0;
- size_t last = maps_.size();
- while (first < last) {
- size_t index = (first + last) / 2;
- const auto& cur = maps_[index];
- if (pc >= cur->start && pc < cur->end) {
- return cur.get();
- } else if (pc < cur->start) {
- last = index;
- } else {
- first = index + 1;
- }
- }
- return nullptr;
-}
-
-bool Maps::Parse() {
- MapInfo* prev_map = nullptr;
- MapInfo* prev_real_map = nullptr;
- return android::procinfo::ReadMapFile(
- GetMapsFile(),
- [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t, const char* name) {
- // Mark a device map in /dev/ and not in /dev/ashmem/ specially.
- if (strncmp(name, "/dev/", 5) == 0 && strncmp(name + 5, "ashmem/", 7) != 0) {
- flags |= unwindstack::MAPS_FLAGS_DEVICE_MAP;
- }
- maps_.emplace_back(new MapInfo(prev_map, prev_real_map, start, end, pgoff, flags, name));
- prev_map = maps_.back().get();
- if (!prev_map->IsBlank()) {
- prev_real_map = prev_map;
- }
- });
-}
-
-void Maps::Add(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
- const std::string& name, uint64_t load_bias) {
- MapInfo* prev_map = maps_.empty() ? nullptr : maps_.back().get();
- MapInfo* prev_real_map = prev_map;
- while (prev_real_map != nullptr && prev_real_map->IsBlank()) {
- prev_real_map = prev_real_map->prev_map;
- }
-
- auto map_info =
- std::make_unique<MapInfo>(prev_map, prev_real_map, start, end, offset, flags, name);
- map_info->load_bias = load_bias;
- maps_.emplace_back(std::move(map_info));
-}
-
-void Maps::Sort() {
- std::sort(maps_.begin(), maps_.end(),
- [](const std::unique_ptr<MapInfo>& a, const std::unique_ptr<MapInfo>& b) {
- return a->start < b->start; });
-
- // Set the prev_map values on the info objects.
- MapInfo* prev_map = nullptr;
- MapInfo* prev_real_map = nullptr;
- for (const auto& map_info : maps_) {
- map_info->prev_map = prev_map;
- map_info->prev_real_map = prev_real_map;
- prev_map = map_info.get();
- if (!prev_map->IsBlank()) {
- prev_real_map = prev_map;
- }
- }
-}
-
-bool BufferMaps::Parse() {
- std::string content(buffer_);
- MapInfo* prev_map = nullptr;
- MapInfo* prev_real_map = nullptr;
- return android::procinfo::ReadMapFileContent(
- &content[0],
- [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t, const char* name) {
- // Mark a device map in /dev/ and not in /dev/ashmem/ specially.
- if (strncmp(name, "/dev/", 5) == 0 && strncmp(name + 5, "ashmem/", 7) != 0) {
- flags |= unwindstack::MAPS_FLAGS_DEVICE_MAP;
- }
- maps_.emplace_back(new MapInfo(prev_map, prev_real_map, start, end, pgoff, flags, name));
- prev_map = maps_.back().get();
- if (!prev_map->IsBlank()) {
- prev_real_map = prev_map;
- }
- });
-}
-
-const std::string RemoteMaps::GetMapsFile() const {
- return "/proc/" + std::to_string(pid_) + "/maps";
-}
-
-const std::string LocalUpdatableMaps::GetMapsFile() const {
- return "/proc/self/maps";
-}
-
-bool LocalUpdatableMaps::Reparse() {
- // New maps will be added at the end without deleting the old ones.
- size_t last_map_idx = maps_.size();
- if (!Parse()) {
- maps_.resize(last_map_idx);
- return false;
- }
-
- size_t total_entries = maps_.size();
- size_t search_map_idx = 0;
- for (size_t new_map_idx = last_map_idx; new_map_idx < maps_.size(); new_map_idx++) {
- auto& new_map_info = maps_[new_map_idx];
- uint64_t start = new_map_info->start;
- uint64_t end = new_map_info->end;
- uint64_t flags = new_map_info->flags;
- std::string* name = &new_map_info->name;
- for (size_t old_map_idx = search_map_idx; old_map_idx < last_map_idx; old_map_idx++) {
- auto& info = maps_[old_map_idx];
- if (start == info->start && end == info->end && flags == info->flags && *name == info->name) {
- // No need to check
- search_map_idx = old_map_idx + 1;
- if (new_map_idx + 1 < maps_.size()) {
- maps_[new_map_idx + 1]->prev_map = info.get();
- maps_[new_map_idx + 1]->prev_real_map =
- info->IsBlank() ? info->prev_real_map : info.get();
- }
- maps_[new_map_idx] = nullptr;
- total_entries--;
- break;
- } else if (info->start > start) {
- // Stop, there isn't going to be a match.
- search_map_idx = old_map_idx;
- break;
- }
-
- // Never delete these maps, they may be in use. The assumption is
- // that there will only every be a handful of these so waiting
- // to destroy them is not too expensive.
- saved_maps_.emplace_back(std::move(info));
- search_map_idx = old_map_idx + 1;
- maps_[old_map_idx] = nullptr;
- total_entries--;
- }
- if (search_map_idx >= last_map_idx) {
- break;
- }
- }
-
- // Now move out any of the maps that never were found.
- for (size_t i = search_map_idx; i < last_map_idx; i++) {
- saved_maps_.emplace_back(std::move(maps_[i]));
- maps_[i] = nullptr;
- total_entries--;
- }
-
- // Sort all of the values such that the nullptrs wind up at the end, then
- // resize them away.
- std::sort(maps_.begin(), maps_.end(), [](const auto& a, const auto& b) {
- if (a == nullptr) {
- return false;
- } else if (b == nullptr) {
- return true;
- }
- return a->start < b->start;
- });
- maps_.resize(total_entries);
-
- return true;
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/Memory.cpp b/libunwindstack/Memory.cpp
deleted file mode 100644
index b4623fa..0000000
--- a/libunwindstack/Memory.cpp
+++ /dev/null
@@ -1,498 +0,0 @@
-/*
- * Copyright (C) 2016 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 <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/ptrace.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <unistd.h>
-
-#include <algorithm>
-#include <memory>
-
-#include <android-base/unique_fd.h>
-
-#include <unwindstack/Memory.h>
-
-#include "Check.h"
-#include "MemoryBuffer.h"
-#include "MemoryCache.h"
-#include "MemoryFileAtOffset.h"
-#include "MemoryLocal.h"
-#include "MemoryOffline.h"
-#include "MemoryOfflineBuffer.h"
-#include "MemoryRange.h"
-#include "MemoryRemote.h"
-
-namespace unwindstack {
-
-static size_t ProcessVmRead(pid_t pid, uint64_t remote_src, void* dst, size_t len) {
-
- // Split up the remote read across page boundaries.
- // From the manpage:
- // A partial read/write may result if one of the remote_iov elements points to an invalid
- // memory region in the remote process.
- //
- // Partial transfers apply at the granularity of iovec elements. These system calls won't
- // perform a partial transfer that splits a single iovec element.
- constexpr size_t kMaxIovecs = 64;
- struct iovec src_iovs[kMaxIovecs];
-
- uint64_t cur = remote_src;
- size_t total_read = 0;
- while (len > 0) {
- struct iovec dst_iov = {
- .iov_base = &reinterpret_cast<uint8_t*>(dst)[total_read], .iov_len = len,
- };
-
- size_t iovecs_used = 0;
- while (len > 0) {
- if (iovecs_used == kMaxIovecs) {
- break;
- }
-
- // struct iovec uses void* for iov_base.
- if (cur >= UINTPTR_MAX) {
- errno = EFAULT;
- return total_read;
- }
-
- src_iovs[iovecs_used].iov_base = reinterpret_cast<void*>(cur);
-
- uintptr_t misalignment = cur & (getpagesize() - 1);
- size_t iov_len = getpagesize() - misalignment;
- iov_len = std::min(iov_len, len);
-
- len -= iov_len;
- if (__builtin_add_overflow(cur, iov_len, &cur)) {
- errno = EFAULT;
- return total_read;
- }
-
- src_iovs[iovecs_used].iov_len = iov_len;
- ++iovecs_used;
- }
-
- ssize_t rc = process_vm_readv(pid, &dst_iov, 1, src_iovs, iovecs_used, 0);
- if (rc == -1) {
- return total_read;
- }
- total_read += rc;
- }
- return total_read;
-}
-
-static bool PtraceReadLong(pid_t pid, uint64_t addr, long* value) {
- // ptrace() returns -1 and sets errno when the operation fails.
- // To disambiguate -1 from a valid result, we clear errno beforehand.
- errno = 0;
- *value = ptrace(PTRACE_PEEKTEXT, pid, reinterpret_cast<void*>(addr), nullptr);
- if (*value == -1 && errno) {
- return false;
- }
- return true;
-}
-
-static size_t PtraceRead(pid_t pid, uint64_t addr, void* dst, size_t bytes) {
- // Make sure that there is no overflow.
- uint64_t max_size;
- if (__builtin_add_overflow(addr, bytes, &max_size)) {
- return 0;
- }
-
- size_t bytes_read = 0;
- long data;
- size_t align_bytes = addr & (sizeof(long) - 1);
- if (align_bytes != 0) {
- if (!PtraceReadLong(pid, addr & ~(sizeof(long) - 1), &data)) {
- return 0;
- }
- size_t copy_bytes = std::min(sizeof(long) - align_bytes, bytes);
- memcpy(dst, reinterpret_cast<uint8_t*>(&data) + align_bytes, copy_bytes);
- addr += copy_bytes;
- dst = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(dst) + copy_bytes);
- bytes -= copy_bytes;
- bytes_read += copy_bytes;
- }
-
- for (size_t i = 0; i < bytes / sizeof(long); i++) {
- if (!PtraceReadLong(pid, addr, &data)) {
- return bytes_read;
- }
- memcpy(dst, &data, sizeof(long));
- dst = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(dst) + sizeof(long));
- addr += sizeof(long);
- bytes_read += sizeof(long);
- }
-
- size_t left_over = bytes & (sizeof(long) - 1);
- if (left_over) {
- if (!PtraceReadLong(pid, addr, &data)) {
- return bytes_read;
- }
- memcpy(dst, &data, left_over);
- bytes_read += left_over;
- }
- return bytes_read;
-}
-
-bool Memory::ReadFully(uint64_t addr, void* dst, size_t size) {
- size_t rc = Read(addr, dst, size);
- return rc == size;
-}
-
-bool Memory::ReadString(uint64_t addr, std::string* dst, size_t max_read) {
- char buffer[256]; // Large enough for 99% of symbol names.
- size_t size = 0; // Number of bytes which were read into the buffer.
- for (size_t offset = 0; offset < max_read; offset += size) {
- // Look for null-terminator first, so we can allocate string of exact size.
- // If we know the end of valid memory range, do the reads in larger blocks.
- size_t read = std::min(sizeof(buffer), max_read - offset);
- size = Read(addr + offset, buffer, read);
- if (size == 0) {
- return false; // We have not found end of string yet and we can not read more data.
- }
- size_t length = strnlen(buffer, size); // Index of the null-terminator.
- if (length < size) {
- // We found the null-terminator. Allocate the string and set its content.
- if (offset == 0) {
- // We did just single read, so the buffer already contains the whole string.
- dst->assign(buffer, length);
- return true;
- } else {
- // The buffer contains only the last block. Read the whole string again.
- dst->assign(offset + length, '\0');
- return ReadFully(addr, dst->data(), dst->size());
- }
- }
- }
- return false;
-}
-
-std::unique_ptr<Memory> Memory::CreateFileMemory(const std::string& path, uint64_t offset) {
- auto memory = std::make_unique<MemoryFileAtOffset>();
-
- if (memory->Init(path, offset)) {
- return memory;
- }
-
- return nullptr;
-}
-
-std::shared_ptr<Memory> Memory::CreateProcessMemory(pid_t pid) {
- if (pid == getpid()) {
- return std::shared_ptr<Memory>(new MemoryLocal());
- }
- return std::shared_ptr<Memory>(new MemoryRemote(pid));
-}
-
-std::shared_ptr<Memory> Memory::CreateProcessMemoryCached(pid_t pid) {
- if (pid == getpid()) {
- return std::shared_ptr<Memory>(new MemoryCache(new MemoryLocal()));
- }
- return std::shared_ptr<Memory>(new MemoryCache(new MemoryRemote(pid)));
-}
-
-std::shared_ptr<Memory> Memory::CreateOfflineMemory(const uint8_t* data, uint64_t start,
- uint64_t end) {
- return std::shared_ptr<Memory>(new MemoryOfflineBuffer(data, start, end));
-}
-
-size_t MemoryBuffer::Read(uint64_t addr, void* dst, size_t size) {
- if (addr >= size_) {
- return 0;
- }
-
- size_t bytes_left = size_ - static_cast<size_t>(addr);
- const unsigned char* actual_base = static_cast<const unsigned char*>(raw_) + addr;
- size_t actual_len = std::min(bytes_left, size);
-
- memcpy(dst, actual_base, actual_len);
- return actual_len;
-}
-
-uint8_t* MemoryBuffer::GetPtr(size_t offset) {
- if (offset < size_) {
- return &raw_[offset];
- }
- return nullptr;
-}
-
-MemoryFileAtOffset::~MemoryFileAtOffset() {
- Clear();
-}
-
-void MemoryFileAtOffset::Clear() {
- if (data_) {
- munmap(&data_[-offset_], size_ + offset_);
- data_ = nullptr;
- }
-}
-
-bool MemoryFileAtOffset::Init(const std::string& file, uint64_t offset, uint64_t size) {
- // Clear out any previous data if it exists.
- Clear();
-
- android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(file.c_str(), O_RDONLY | O_CLOEXEC)));
- if (fd == -1) {
- return false;
- }
- struct stat buf;
- if (fstat(fd, &buf) == -1) {
- return false;
- }
- if (offset >= static_cast<uint64_t>(buf.st_size)) {
- return false;
- }
-
- offset_ = offset & (getpagesize() - 1);
- uint64_t aligned_offset = offset & ~(getpagesize() - 1);
- if (aligned_offset > static_cast<uint64_t>(buf.st_size) ||
- offset > static_cast<uint64_t>(buf.st_size)) {
- return false;
- }
-
- size_ = buf.st_size - aligned_offset;
- uint64_t max_size;
- if (!__builtin_add_overflow(size, offset_, &max_size) && max_size < size_) {
- // Truncate the mapped size.
- size_ = max_size;
- }
- void* map = mmap(nullptr, size_, PROT_READ, MAP_PRIVATE, fd, aligned_offset);
- if (map == MAP_FAILED) {
- return false;
- }
-
- data_ = &reinterpret_cast<uint8_t*>(map)[offset_];
- size_ -= offset_;
-
- return true;
-}
-
-size_t MemoryFileAtOffset::Read(uint64_t addr, void* dst, size_t size) {
- if (addr >= size_) {
- return 0;
- }
-
- size_t bytes_left = size_ - static_cast<size_t>(addr);
- const unsigned char* actual_base = static_cast<const unsigned char*>(data_) + addr;
- size_t actual_len = std::min(bytes_left, size);
-
- memcpy(dst, actual_base, actual_len);
- return actual_len;
-}
-
-size_t MemoryRemote::Read(uint64_t addr, void* dst, size_t size) {
-#if !defined(__LP64__)
- // Cannot read an address greater than 32 bits in a 32 bit context.
- if (addr > UINT32_MAX) {
- return 0;
- }
-#endif
-
- size_t (*read_func)(pid_t, uint64_t, void*, size_t) =
- reinterpret_cast<size_t (*)(pid_t, uint64_t, void*, size_t)>(read_redirect_func_.load());
- if (read_func != nullptr) {
- return read_func(pid_, addr, dst, size);
- } else {
- // Prefer process_vm_read, try it first. If it doesn't work, use the
- // ptrace function. If at least one of them returns at least some data,
- // set that as the permanent function to use.
- // This assumes that if process_vm_read works once, it will continue
- // to work.
- size_t bytes = ProcessVmRead(pid_, addr, dst, size);
- if (bytes > 0) {
- read_redirect_func_ = reinterpret_cast<uintptr_t>(ProcessVmRead);
- return bytes;
- }
- bytes = PtraceRead(pid_, addr, dst, size);
- if (bytes > 0) {
- read_redirect_func_ = reinterpret_cast<uintptr_t>(PtraceRead);
- }
- return bytes;
- }
-}
-
-size_t MemoryLocal::Read(uint64_t addr, void* dst, size_t size) {
- return ProcessVmRead(getpid(), addr, dst, size);
-}
-
-#if !defined(ANDROID_EXPERIMENTAL_MTE)
-long MemoryRemote::ReadTag(uint64_t) {
- return -1;
-}
-
-long MemoryLocal::ReadTag(uint64_t) {
- return -1;
-}
-#endif
-
-MemoryRange::MemoryRange(const std::shared_ptr<Memory>& memory, uint64_t begin, uint64_t length,
- uint64_t offset)
- : memory_(memory), begin_(begin), length_(length), offset_(offset) {}
-
-size_t MemoryRange::Read(uint64_t addr, void* dst, size_t size) {
- if (addr < offset_) {
- return 0;
- }
-
- uint64_t read_offset = addr - offset_;
- if (read_offset >= length_) {
- return 0;
- }
-
- uint64_t read_length = std::min(static_cast<uint64_t>(size), length_ - read_offset);
- uint64_t read_addr;
- if (__builtin_add_overflow(read_offset, begin_, &read_addr)) {
- return 0;
- }
-
- return memory_->Read(read_addr, dst, read_length);
-}
-
-void MemoryRanges::Insert(MemoryRange* memory) {
- maps_.emplace(memory->offset() + memory->length(), memory);
-}
-
-size_t MemoryRanges::Read(uint64_t addr, void* dst, size_t size) {
- auto entry = maps_.upper_bound(addr);
- if (entry != maps_.end()) {
- return entry->second->Read(addr, dst, size);
- }
- return 0;
-}
-
-bool MemoryOffline::Init(const std::string& file, uint64_t offset) {
- auto memory_file = std::make_shared<MemoryFileAtOffset>();
- if (!memory_file->Init(file, offset)) {
- return false;
- }
-
- // The first uint64_t value is the start of memory.
- uint64_t start;
- if (!memory_file->ReadFully(0, &start, sizeof(start))) {
- return false;
- }
-
- uint64_t size = memory_file->Size();
- if (__builtin_sub_overflow(size, sizeof(start), &size)) {
- return false;
- }
-
- memory_ = std::make_unique<MemoryRange>(memory_file, sizeof(start), size, start);
- return true;
-}
-
-size_t MemoryOffline::Read(uint64_t addr, void* dst, size_t size) {
- if (!memory_) {
- return 0;
- }
-
- return memory_->Read(addr, dst, size);
-}
-
-MemoryOfflineBuffer::MemoryOfflineBuffer(const uint8_t* data, uint64_t start, uint64_t end)
- : data_(data), start_(start), end_(end) {}
-
-void MemoryOfflineBuffer::Reset(const uint8_t* data, uint64_t start, uint64_t end) {
- data_ = data;
- start_ = start;
- end_ = end;
-}
-
-size_t MemoryOfflineBuffer::Read(uint64_t addr, void* dst, size_t size) {
- if (addr < start_ || addr >= end_) {
- return 0;
- }
-
- size_t read_length = std::min(size, static_cast<size_t>(end_ - addr));
- memcpy(dst, &data_[addr - start_], read_length);
- return read_length;
-}
-
-MemoryOfflineParts::~MemoryOfflineParts() {
- for (auto memory : memories_) {
- delete memory;
- }
-}
-
-size_t MemoryOfflineParts::Read(uint64_t addr, void* dst, size_t size) {
- if (memories_.empty()) {
- return 0;
- }
-
- // Do a read on each memory object, no support for reading across the
- // different memory objects.
- for (MemoryOffline* memory : memories_) {
- size_t bytes = memory->Read(addr, dst, size);
- if (bytes != 0) {
- return bytes;
- }
- }
- return 0;
-}
-
-size_t MemoryCache::Read(uint64_t addr, void* dst, size_t size) {
- // Only bother caching and looking at the cache if this is a small read for now.
- if (size > 64) {
- return impl_->Read(addr, dst, size);
- }
-
- uint64_t addr_page = addr >> kCacheBits;
- auto entry = cache_.find(addr_page);
- uint8_t* cache_dst;
- if (entry != cache_.end()) {
- cache_dst = entry->second;
- } else {
- cache_dst = cache_[addr_page];
- if (!impl_->ReadFully(addr_page << kCacheBits, cache_dst, kCacheSize)) {
- // Erase the entry.
- cache_.erase(addr_page);
- return impl_->Read(addr, dst, size);
- }
- }
- size_t max_read = ((addr_page + 1) << kCacheBits) - addr;
- if (size <= max_read) {
- memcpy(dst, &cache_dst[addr & kCacheMask], size);
- return size;
- }
-
- // The read crossed into another cached entry, since a read can only cross
- // into one extra cached page, duplicate the code rather than looping.
- memcpy(dst, &cache_dst[addr & kCacheMask], max_read);
- dst = &reinterpret_cast<uint8_t*>(dst)[max_read];
- addr_page++;
-
- entry = cache_.find(addr_page);
- if (entry != cache_.end()) {
- cache_dst = entry->second;
- } else {
- cache_dst = cache_[addr_page];
- if (!impl_->ReadFully(addr_page << kCacheBits, cache_dst, kCacheSize)) {
- // Erase the entry.
- cache_.erase(addr_page);
- return impl_->Read(addr_page << kCacheBits, dst, size - max_read) + max_read;
- }
- }
- memcpy(dst, cache_dst, size - max_read);
- return size;
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/MemoryBuffer.h b/libunwindstack/MemoryBuffer.h
deleted file mode 100644
index a91e59f..0000000
--- a/libunwindstack/MemoryBuffer.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-#ifndef _LIBUNWINDSTACK_MEMORY_BUFFER_H
-#define _LIBUNWINDSTACK_MEMORY_BUFFER_H
-
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-#include <unwindstack/Memory.h>
-
-namespace unwindstack {
-
-class MemoryBuffer : public Memory {
- public:
- MemoryBuffer() = default;
- virtual ~MemoryBuffer() { free(raw_); }
-
- size_t Read(uint64_t addr, void* dst, size_t size) override;
-
- uint8_t* GetPtr(size_t offset);
-
- bool Resize(size_t size) {
- raw_ = reinterpret_cast<uint8_t*>(realloc(raw_, size));
- if (raw_ == nullptr) {
- size_ = 0;
- return false;
- }
- size_ = size;
- return true;
- }
-
- uint64_t Size() { return size_; }
-
- private:
- uint8_t* raw_ = nullptr;
- size_t size_ = 0;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_MEMORY_BUFFER_H
diff --git a/libunwindstack/MemoryCache.h b/libunwindstack/MemoryCache.h
deleted file mode 100644
index d97640d..0000000
--- a/libunwindstack/MemoryCache.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-#ifndef _LIBUNWINDSTACK_MEMORY_CACHE_H
-#define _LIBUNWINDSTACK_MEMORY_CACHE_H
-
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <unordered_map>
-
-#include <unwindstack/Memory.h>
-
-namespace unwindstack {
-
-class MemoryCache : public Memory {
- public:
- MemoryCache(Memory* memory) : impl_(memory) {}
- virtual ~MemoryCache() = default;
-
- size_t Read(uint64_t addr, void* dst, size_t size) override;
- long ReadTag(uint64_t addr) override { return impl_->ReadTag(addr); }
-
- void Clear() override { cache_.clear(); }
-
- private:
- constexpr static size_t kCacheBits = 12;
- constexpr static size_t kCacheMask = (1 << kCacheBits) - 1;
- constexpr static size_t kCacheSize = 1 << kCacheBits;
- std::unordered_map<uint64_t, uint8_t[kCacheSize]> cache_;
-
- std::unique_ptr<Memory> impl_;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_MEMORY_CACHE_H
diff --git a/libunwindstack/MemoryFileAtOffset.h b/libunwindstack/MemoryFileAtOffset.h
deleted file mode 100644
index d136eb4..0000000
--- a/libunwindstack/MemoryFileAtOffset.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-#ifndef _LIBUNWINDSTACK_MEMORY_FILE_AT_OFFSET_H
-#define _LIBUNWINDSTACK_MEMORY_FILE_AT_OFFSET_H
-
-#include <stdint.h>
-
-#include <unwindstack/Memory.h>
-
-namespace unwindstack {
-
-class MemoryFileAtOffset : public Memory {
- public:
- MemoryFileAtOffset() = default;
- virtual ~MemoryFileAtOffset();
-
- bool Init(const std::string& file, uint64_t offset, uint64_t size = UINT64_MAX);
-
- size_t Read(uint64_t addr, void* dst, size_t size) override;
-
- size_t Size() { return size_; }
-
- void Clear() override;
-
- protected:
- size_t size_ = 0;
- size_t offset_ = 0;
- uint8_t* data_ = nullptr;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_MEMORY_FILE_AT_OFFSET_H
diff --git a/libunwindstack/MemoryLocal.h b/libunwindstack/MemoryLocal.h
deleted file mode 100644
index 741f107..0000000
--- a/libunwindstack/MemoryLocal.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-#ifndef _LIBUNWINDSTACK_MEMORY_LOCAL_H
-#define _LIBUNWINDSTACK_MEMORY_LOCAL_H
-
-#include <stdint.h>
-
-#include <unwindstack/Memory.h>
-
-namespace unwindstack {
-
-class MemoryLocal : public Memory {
- public:
- MemoryLocal() = default;
- virtual ~MemoryLocal() = default;
-
- bool IsLocal() const override { return true; }
-
- size_t Read(uint64_t addr, void* dst, size_t size) override;
- long ReadTag(uint64_t addr) override;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_MEMORY_LOCAL_H
diff --git a/libunwindstack/MemoryMte.cpp b/libunwindstack/MemoryMte.cpp
deleted file mode 100644
index 46a546e..0000000
--- a/libunwindstack/MemoryMte.cpp
+++ /dev/null
@@ -1,64 +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.
- */
-
-#if defined(ANDROID_EXPERIMENTAL_MTE)
-
-#include <sys/ptrace.h>
-#include <sys/uio.h>
-
-#include <bionic/mte.h>
-#include <bionic/mte_kernel.h>
-
-#include "MemoryLocal.h"
-#include "MemoryRemote.h"
-
-namespace unwindstack {
-
-long MemoryRemote::ReadTag(uint64_t addr) {
-#if defined(__aarch64__)
- char tag;
- iovec iov = {&tag, 1};
- if (ptrace(PTRACE_PEEKMTETAGS, pid_, reinterpret_cast<void*>(addr), &iov) != 0 ||
- iov.iov_len != 1) {
- return -1;
- }
- return tag;
-#else
- (void)addr;
- return -1;
-#endif
-}
-
-long MemoryLocal::ReadTag(uint64_t addr) {
-#if defined(__aarch64__)
- // Check that the memory is readable first. This is racy with the ldg but there's not much
- // we can do about it.
- char data;
- if (!mte_supported() || !Read(addr, &data, 1)) {
- return -1;
- }
-
- __asm__ __volatile__(".arch_extension mte; ldg %0, [%0]" : "+r"(addr) : : "memory");
- return (addr >> 56) & 0xf;
-#else
- (void)addr;
- return -1;
-#endif
-}
-
-} // namespace unwindstack
-
-#endif
diff --git a/libunwindstack/MemoryOffline.h b/libunwindstack/MemoryOffline.h
deleted file mode 100644
index 789f1a2..0000000
--- a/libunwindstack/MemoryOffline.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-#ifndef _LIBUNWINDSTACK_MEMORY_OFFLINE_H
-#define _LIBUNWINDSTACK_MEMORY_OFFLINE_H
-
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <unwindstack/Memory.h>
-
-#include "MemoryRange.h"
-
-namespace unwindstack {
-
-class MemoryOffline : public Memory {
- public:
- MemoryOffline() = default;
- virtual ~MemoryOffline() = default;
-
- bool Init(const std::string& file, uint64_t offset);
-
- size_t Read(uint64_t addr, void* dst, size_t size) override;
-
- private:
- std::unique_ptr<MemoryRange> memory_;
-};
-
-class MemoryOfflineParts : public Memory {
- public:
- MemoryOfflineParts() = default;
- virtual ~MemoryOfflineParts();
-
- void Add(MemoryOffline* memory) { memories_.push_back(memory); }
-
- size_t Read(uint64_t addr, void* dst, size_t size) override;
-
- private:
- std::vector<MemoryOffline*> memories_;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_MEMORY_OFFLINE_H
diff --git a/libunwindstack/MemoryOfflineBuffer.h b/libunwindstack/MemoryOfflineBuffer.h
deleted file mode 100644
index 64c49a1..0000000
--- a/libunwindstack/MemoryOfflineBuffer.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-#ifndef _LIBUNWINDSTACK_MEMORY_OFFLINE_BUFFER_H
-#define _LIBUNWINDSTACK_MEMORY_OFFLINE_BUFFER_H
-
-#include <stdint.h>
-
-#include <unwindstack/Memory.h>
-
-namespace unwindstack {
-
-class MemoryOfflineBuffer : public Memory {
- public:
- MemoryOfflineBuffer(const uint8_t* data, uint64_t start, uint64_t end);
- virtual ~MemoryOfflineBuffer() = default;
-
- void Reset(const uint8_t* data, uint64_t start, uint64_t end);
-
- size_t Read(uint64_t addr, void* dst, size_t size) override;
-
- private:
- const uint8_t* data_;
- uint64_t start_;
- uint64_t end_;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_MEMORY_OFFLINE_BUFFER_H
diff --git a/libunwindstack/MemoryRange.h b/libunwindstack/MemoryRange.h
deleted file mode 100644
index 3b4ab5c..0000000
--- a/libunwindstack/MemoryRange.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-#ifndef _LIBUNWINDSTACK_MEMORY_RANGE_H
-#define _LIBUNWINDSTACK_MEMORY_RANGE_H
-
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-#include <string>
-
-#include <unwindstack/Memory.h>
-
-namespace unwindstack {
-
-// MemoryRange maps one address range onto another.
-// The range [src_begin, src_begin + length) in the underlying Memory is mapped onto offset,
-// such that range.read(offset) is equivalent to underlying.read(src_begin).
-class MemoryRange : public Memory {
- public:
- MemoryRange(const std::shared_ptr<Memory>& memory, uint64_t begin, uint64_t length,
- uint64_t offset);
- virtual ~MemoryRange() = default;
-
- size_t Read(uint64_t addr, void* dst, size_t size) override;
-
- uint64_t offset() { return offset_; }
- uint64_t length() { return length_; }
-
- private:
- std::shared_ptr<Memory> memory_;
- uint64_t begin_;
- uint64_t length_;
- uint64_t offset_;
-};
-
-class MemoryRanges : public Memory {
- public:
- MemoryRanges() = default;
- virtual ~MemoryRanges() = default;
-
- void Insert(MemoryRange* memory);
-
- size_t Read(uint64_t addr, void* dst, size_t size) override;
-
- private:
- std::map<uint64_t, std::unique_ptr<MemoryRange>> maps_;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_MEMORY_RANGE_H
diff --git a/libunwindstack/MemoryRemote.h b/libunwindstack/MemoryRemote.h
deleted file mode 100644
index dd09c88..0000000
--- a/libunwindstack/MemoryRemote.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-#ifndef _LIBUNWINDSTACK_MEMORY_REMOTE_H
-#define _LIBUNWINDSTACK_MEMORY_REMOTE_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <atomic>
-
-#include <unwindstack/Memory.h>
-
-namespace unwindstack {
-
-class MemoryRemote : public Memory {
- public:
- MemoryRemote(pid_t pid) : pid_(pid), read_redirect_func_(0) {}
- virtual ~MemoryRemote() = default;
-
- size_t Read(uint64_t addr, void* dst, size_t size) override;
- long ReadTag(uint64_t addr) override;
-
- pid_t pid() { return pid_; }
-
- private:
- pid_t pid_;
- std::atomic_uintptr_t read_redirect_func_;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_MEMORY_REMOTE_H
diff --git a/libunwindstack/OWNERS b/libunwindstack/OWNERS
deleted file mode 100644
index 6f7e4a3..0000000
--- a/libunwindstack/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-cferris@google.com
diff --git a/libunwindstack/Regs.cpp b/libunwindstack/Regs.cpp
deleted file mode 100644
index 03aa6c2..0000000
--- a/libunwindstack/Regs.cpp
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2016 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 <stdint.h>
-#include <sys/ptrace.h>
-#include <sys/uio.h>
-
-#include <vector>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Regs.h>
-#include <unwindstack/RegsArm.h>
-#include <unwindstack/RegsArm64.h>
-#include <unwindstack/RegsMips.h>
-#include <unwindstack/RegsMips64.h>
-#include <unwindstack/RegsX86.h>
-#include <unwindstack/RegsX86_64.h>
-#include <unwindstack/UserArm.h>
-#include <unwindstack/UserArm64.h>
-#include <unwindstack/UserMips.h>
-#include <unwindstack/UserMips64.h>
-#include <unwindstack/UserX86.h>
-#include <unwindstack/UserX86_64.h>
-
-namespace unwindstack {
-
-// The largest user structure.
-constexpr size_t MAX_USER_REGS_SIZE = sizeof(mips64_user_regs) + 10;
-
-// This function assumes that reg_data is already aligned to a 64 bit value.
-// If not this could crash with an unaligned access.
-Regs* Regs::RemoteGet(pid_t pid) {
- // Make the buffer large enough to contain the largest registers type.
- std::vector<uint64_t> buffer(MAX_USER_REGS_SIZE / sizeof(uint64_t));
- struct iovec io;
- io.iov_base = buffer.data();
- io.iov_len = buffer.size() * sizeof(uint64_t);
-
- if (ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, reinterpret_cast<void*>(&io)) == -1) {
- return nullptr;
- }
-
- switch (io.iov_len) {
- case sizeof(x86_user_regs):
- return RegsX86::Read(buffer.data());
- case sizeof(x86_64_user_regs):
- return RegsX86_64::Read(buffer.data());
- case sizeof(arm_user_regs):
- return RegsArm::Read(buffer.data());
- case sizeof(arm64_user_regs):
- return RegsArm64::Read(buffer.data());
- case sizeof(mips_user_regs):
- return RegsMips::Read(buffer.data());
- case sizeof(mips64_user_regs):
- return RegsMips64::Read(buffer.data());
- }
- return nullptr;
-}
-
-Regs* Regs::CreateFromUcontext(ArchEnum arch, void* ucontext) {
- switch (arch) {
- case ARCH_X86:
- return RegsX86::CreateFromUcontext(ucontext);
- case ARCH_X86_64:
- return RegsX86_64::CreateFromUcontext(ucontext);
- case ARCH_ARM:
- return RegsArm::CreateFromUcontext(ucontext);
- case ARCH_ARM64:
- return RegsArm64::CreateFromUcontext(ucontext);
- case ARCH_MIPS:
- return RegsMips::CreateFromUcontext(ucontext);
- case ARCH_MIPS64:
- return RegsMips64::CreateFromUcontext(ucontext);
- case ARCH_UNKNOWN:
- default:
- return nullptr;
- }
-}
-
-ArchEnum Regs::CurrentArch() {
-#if defined(__arm__)
- return ARCH_ARM;
-#elif defined(__aarch64__)
- return ARCH_ARM64;
-#elif defined(__i386__)
- return ARCH_X86;
-#elif defined(__x86_64__)
- return ARCH_X86_64;
-#else
- abort();
-#endif
-}
-
-Regs* Regs::CreateFromLocal() {
- Regs* regs;
-#if defined(__arm__)
- regs = new RegsArm();
-#elif defined(__aarch64__)
- regs = new RegsArm64();
-#elif defined(__i386__)
- regs = new RegsX86();
-#elif defined(__x86_64__)
- regs = new RegsX86_64();
-#else
- abort();
-#endif
- return regs;
-}
-
-uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf, ArchEnum arch) {
- switch (arch) {
- case ARCH_ARM: {
- if (!elf->valid()) {
- return 2;
- }
-
- uint64_t load_bias = elf->GetLoadBias();
- if (rel_pc < load_bias) {
- if (rel_pc < 2) {
- return 0;
- }
- return 2;
- }
- uint64_t adjusted_rel_pc = rel_pc - load_bias;
- if (adjusted_rel_pc < 5) {
- if (adjusted_rel_pc < 2) {
- return 0;
- }
- return 2;
- }
-
- if (adjusted_rel_pc & 1) {
- // This is a thumb instruction, it could be 2 or 4 bytes.
- uint32_t value;
- if (!elf->memory()->ReadFully(adjusted_rel_pc - 5, &value, sizeof(value)) ||
- (value & 0xe000f000) != 0xe000f000) {
- return 2;
- }
- }
- return 4;
- }
- case ARCH_ARM64: {
- if (rel_pc < 4) {
- return 0;
- }
- return 4;
- }
- case ARCH_MIPS:
- case ARCH_MIPS64: {
- if (rel_pc < 8) {
- return 0;
- }
- // For now, just assume no compact branches
- return 8;
- }
- case ARCH_X86:
- case ARCH_X86_64: {
- if (rel_pc == 0) {
- return 0;
- }
- return 1;
- }
- case ARCH_UNKNOWN:
- return 0;
- }
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/RegsArm.cpp b/libunwindstack/RegsArm.cpp
deleted file mode 100644
index 1aaa08f..0000000
--- a/libunwindstack/RegsArm.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2016 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 <stdint.h>
-#include <string.h>
-
-#include <functional>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/MachineArm.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/RegsArm.h>
-#include <unwindstack/UcontextArm.h>
-#include <unwindstack/UserArm.h>
-
-namespace unwindstack {
-
-RegsArm::RegsArm() : RegsImpl<uint32_t>(ARM_REG_LAST, Location(LOCATION_REGISTER, ARM_REG_LR)) {}
-
-ArchEnum RegsArm::Arch() {
- return ARCH_ARM;
-}
-
-uint64_t RegsArm::pc() {
- return regs_[ARM_REG_PC];
-}
-
-uint64_t RegsArm::sp() {
- return regs_[ARM_REG_SP];
-}
-
-void RegsArm::set_pc(uint64_t pc) {
- regs_[ARM_REG_PC] = pc;
-}
-
-void RegsArm::set_sp(uint64_t sp) {
- regs_[ARM_REG_SP] = sp;
-}
-
-bool RegsArm::SetPcFromReturnAddress(Memory*) {
- uint32_t lr = regs_[ARM_REG_LR];
- if (regs_[ARM_REG_PC] == lr) {
- return false;
- }
-
- regs_[ARM_REG_PC] = lr;
- return true;
-}
-
-void RegsArm::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
- fn("r0", regs_[ARM_REG_R0]);
- fn("r1", regs_[ARM_REG_R1]);
- fn("r2", regs_[ARM_REG_R2]);
- fn("r3", regs_[ARM_REG_R3]);
- fn("r4", regs_[ARM_REG_R4]);
- fn("r5", regs_[ARM_REG_R5]);
- fn("r6", regs_[ARM_REG_R6]);
- fn("r7", regs_[ARM_REG_R7]);
- fn("r8", regs_[ARM_REG_R8]);
- fn("r9", regs_[ARM_REG_R9]);
- fn("r10", regs_[ARM_REG_R10]);
- fn("r11", regs_[ARM_REG_R11]);
- fn("ip", regs_[ARM_REG_R12]);
- fn("sp", regs_[ARM_REG_SP]);
- fn("lr", regs_[ARM_REG_LR]);
- fn("pc", regs_[ARM_REG_PC]);
-}
-
-Regs* RegsArm::Read(void* remote_data) {
- arm_user_regs* user = reinterpret_cast<arm_user_regs*>(remote_data);
-
- RegsArm* regs = new RegsArm();
- memcpy(regs->RawData(), &user->regs[0], ARM_REG_LAST * sizeof(uint32_t));
- return regs;
-}
-
-Regs* RegsArm::CreateFromUcontext(void* ucontext) {
- arm_ucontext_t* arm_ucontext = reinterpret_cast<arm_ucontext_t*>(ucontext);
-
- RegsArm* regs = new RegsArm();
- memcpy(regs->RawData(), &arm_ucontext->uc_mcontext.regs[0], ARM_REG_LAST * sizeof(uint32_t));
- return regs;
-}
-
-bool RegsArm::StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) {
- uint32_t data;
- Memory* elf_memory = elf->memory();
- // Read from elf memory since it is usually more expensive to read from
- // process memory.
- if (!elf_memory->ReadFully(elf_offset, &data, sizeof(data))) {
- return false;
- }
-
- uint64_t offset = 0;
- if (data == 0xe3a07077 || data == 0xef900077 || data == 0xdf002777) {
- uint64_t sp = regs_[ARM_REG_SP];
- // non-RT sigreturn call.
- // __restore:
- //
- // Form 1 (arm):
- // 0x77 0x70 mov r7, #0x77
- // 0xa0 0xe3 svc 0x00000000
- //
- // Form 2 (arm):
- // 0x77 0x00 0x90 0xef svc 0x00900077
- //
- // Form 3 (thumb):
- // 0x77 0x27 movs r7, #77
- // 0x00 0xdf svc 0
- if (!process_memory->ReadFully(sp, &data, sizeof(data))) {
- return false;
- }
- if (data == 0x5ac3c35a) {
- // SP + uc_mcontext offset + r0 offset.
- offset = sp + 0x14 + 0xc;
- } else {
- // SP + r0 offset
- offset = sp + 0xc;
- }
- } else if (data == 0xe3a070ad || data == 0xef9000ad || data == 0xdf0027ad) {
- uint64_t sp = regs_[ARM_REG_SP];
- // RT sigreturn call.
- // __restore_rt:
- //
- // Form 1 (arm):
- // 0xad 0x70 mov r7, #0xad
- // 0xa0 0xe3 svc 0x00000000
- //
- // Form 2 (arm):
- // 0xad 0x00 0x90 0xef svc 0x009000ad
- //
- // Form 3 (thumb):
- // 0xad 0x27 movs r7, #ad
- // 0x00 0xdf svc 0
- if (!process_memory->ReadFully(sp, &data, sizeof(data))) {
- return false;
- }
- if (data == sp + 8) {
- // SP + 8 + sizeof(siginfo_t) + uc_mcontext_offset + r0 offset
- offset = sp + 8 + 0x80 + 0x14 + 0xc;
- } else {
- // SP + sizeof(siginfo_t) + uc_mcontext_offset + r0 offset
- offset = sp + 0x80 + 0x14 + 0xc;
- }
- }
- if (offset == 0) {
- return false;
- }
-
- if (!process_memory->ReadFully(offset, regs_.data(), sizeof(uint32_t) * ARM_REG_LAST)) {
- return false;
- }
- return true;
-}
-
-Regs* RegsArm::Clone() {
- return new RegsArm(*this);
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/RegsArm64.cpp b/libunwindstack/RegsArm64.cpp
deleted file mode 100644
index b496187..0000000
--- a/libunwindstack/RegsArm64.cpp
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright (C) 2016 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 <stdint.h>
-#include <string.h>
-
-#include <functional>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/MachineArm64.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/RegsArm64.h>
-#include <unwindstack/UcontextArm64.h>
-#include <unwindstack/UserArm64.h>
-
-namespace unwindstack {
-
-RegsArm64::RegsArm64()
- : RegsImpl<uint64_t>(ARM64_REG_LAST, Location(LOCATION_REGISTER, ARM64_REG_LR)) {
- ResetPseudoRegisters();
- pac_mask_ = 0;
-}
-
-ArchEnum RegsArm64::Arch() {
- return ARCH_ARM64;
-}
-
-uint64_t RegsArm64::pc() {
- return regs_[ARM64_REG_PC];
-}
-
-uint64_t RegsArm64::sp() {
- return regs_[ARM64_REG_SP];
-}
-
-void RegsArm64::set_pc(uint64_t pc) {
- // If the target is aarch64 then the return address may have been
- // signed using the Armv8.3-A Pointer Authentication extension. The
- // original return address can be restored by stripping out the
- // authentication code using a mask or xpaclri. xpaclri is a NOP on
- // pre-Armv8.3-A architectures.
- if ((0 != pc) && IsRASigned()) {
- if (pac_mask_) {
- pc &= ~pac_mask_;
-#if defined(__aarch64__)
- } else {
- register uint64_t x30 __asm("x30") = pc;
- // This is XPACLRI.
- asm("hint 0x7" : "+r"(x30));
- pc = x30;
-#endif
- }
- }
- regs_[ARM64_REG_PC] = pc;
-}
-
-void RegsArm64::set_sp(uint64_t sp) {
- regs_[ARM64_REG_SP] = sp;
-}
-
-bool RegsArm64::SetPcFromReturnAddress(Memory*) {
- uint64_t lr = regs_[ARM64_REG_LR];
- if (regs_[ARM64_REG_PC] == lr) {
- return false;
- }
-
- regs_[ARM64_REG_PC] = lr;
- return true;
-}
-
-void RegsArm64::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
- fn("x0", regs_[ARM64_REG_R0]);
- fn("x1", regs_[ARM64_REG_R1]);
- fn("x2", regs_[ARM64_REG_R2]);
- fn("x3", regs_[ARM64_REG_R3]);
- fn("x4", regs_[ARM64_REG_R4]);
- fn("x5", regs_[ARM64_REG_R5]);
- fn("x6", regs_[ARM64_REG_R6]);
- fn("x7", regs_[ARM64_REG_R7]);
- fn("x8", regs_[ARM64_REG_R8]);
- fn("x9", regs_[ARM64_REG_R9]);
- fn("x10", regs_[ARM64_REG_R10]);
- fn("x11", regs_[ARM64_REG_R11]);
- fn("x12", regs_[ARM64_REG_R12]);
- fn("x13", regs_[ARM64_REG_R13]);
- fn("x14", regs_[ARM64_REG_R14]);
- fn("x15", regs_[ARM64_REG_R15]);
- fn("x16", regs_[ARM64_REG_R16]);
- fn("x17", regs_[ARM64_REG_R17]);
- fn("x18", regs_[ARM64_REG_R18]);
- fn("x19", regs_[ARM64_REG_R19]);
- fn("x20", regs_[ARM64_REG_R20]);
- fn("x21", regs_[ARM64_REG_R21]);
- fn("x22", regs_[ARM64_REG_R22]);
- fn("x23", regs_[ARM64_REG_R23]);
- fn("x24", regs_[ARM64_REG_R24]);
- fn("x25", regs_[ARM64_REG_R25]);
- fn("x26", regs_[ARM64_REG_R26]);
- fn("x27", regs_[ARM64_REG_R27]);
- fn("x28", regs_[ARM64_REG_R28]);
- fn("x29", regs_[ARM64_REG_R29]);
- fn("lr", regs_[ARM64_REG_LR]);
- fn("sp", regs_[ARM64_REG_SP]);
- fn("pc", regs_[ARM64_REG_PC]);
- fn("pst", regs_[ARM64_REG_PSTATE]);
-}
-
-Regs* RegsArm64::Read(void* remote_data) {
- arm64_user_regs* user = reinterpret_cast<arm64_user_regs*>(remote_data);
-
- RegsArm64* regs = new RegsArm64();
- memcpy(regs->RawData(), &user->regs[0], (ARM64_REG_R30 + 1) * sizeof(uint64_t));
- uint64_t* reg_data = reinterpret_cast<uint64_t*>(regs->RawData());
- reg_data[ARM64_REG_SP] = user->sp;
- reg_data[ARM64_REG_PC] = user->pc;
- reg_data[ARM64_REG_PSTATE] = user->pstate;
- return regs;
-}
-
-Regs* RegsArm64::CreateFromUcontext(void* ucontext) {
- arm64_ucontext_t* arm64_ucontext = reinterpret_cast<arm64_ucontext_t*>(ucontext);
-
- RegsArm64* regs = new RegsArm64();
- memcpy(regs->RawData(), &arm64_ucontext->uc_mcontext.regs[0], ARM64_REG_LAST * sizeof(uint64_t));
- return regs;
-}
-
-bool RegsArm64::StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) {
- uint64_t data;
- Memory* elf_memory = elf->memory();
- // Read from elf memory since it is usually more expensive to read from
- // process memory.
- if (!elf_memory->ReadFully(elf_offset, &data, sizeof(data))) {
- return false;
- }
-
- // Look for the kernel sigreturn function.
- // __kernel_rt_sigreturn:
- // 0xd2801168 mov x8, #0x8b
- // 0xd4000001 svc #0x0
- if (data != 0xd4000001d2801168ULL) {
- return false;
- }
-
- // SP + sizeof(siginfo_t) + uc_mcontext offset + X0 offset.
- if (!process_memory->ReadFully(regs_[ARM64_REG_SP] + 0x80 + 0xb0 + 0x08, regs_.data(),
- sizeof(uint64_t) * ARM64_REG_LAST)) {
- return false;
- }
- return true;
-}
-
-void RegsArm64::ResetPseudoRegisters(void) {
- // DWARF for AArch64 says RA_SIGN_STATE should be initialized to 0.
- this->SetPseudoRegister(Arm64Reg::ARM64_PREG_RA_SIGN_STATE, 0);
-}
-
-bool RegsArm64::SetPseudoRegister(uint16_t id, uint64_t value) {
- if ((id >= Arm64Reg::ARM64_PREG_FIRST) && (id < Arm64Reg::ARM64_PREG_LAST)) {
- pseudo_regs_[id - Arm64Reg::ARM64_PREG_FIRST] = value;
- return true;
- }
- return false;
-}
-
-bool RegsArm64::GetPseudoRegister(uint16_t id, uint64_t* value) {
- if ((id >= Arm64Reg::ARM64_PREG_FIRST) && (id < Arm64Reg::ARM64_PREG_LAST)) {
- *value = pseudo_regs_[id - Arm64Reg::ARM64_PREG_FIRST];
- return true;
- }
- return false;
-}
-
-bool RegsArm64::IsRASigned() {
- uint64_t value;
- auto result = this->GetPseudoRegister(Arm64Reg::ARM64_PREG_RA_SIGN_STATE, &value);
- return (result && (value != 0));
-}
-
-void RegsArm64::SetPACMask(uint64_t mask) {
- pac_mask_ = mask;
-}
-
-Regs* RegsArm64::Clone() {
- return new RegsArm64(*this);
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/RegsInfo.h b/libunwindstack/RegsInfo.h
deleted file mode 100644
index e445a91..0000000
--- a/libunwindstack/RegsInfo.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#ifndef _LIBUNWINDSTACK_REGS_INFO_H
-#define _LIBUNWINDSTACK_REGS_INFO_H
-
-#include <stdint.h>
-
-#include <unwindstack/Regs.h>
-
-namespace unwindstack {
-
-template <typename AddressType>
-struct RegsInfo {
- static constexpr size_t MAX_REGISTERS = 64;
-
- RegsInfo(RegsImpl<AddressType>* regs) : regs(regs) {}
-
- RegsImpl<AddressType>* regs = nullptr;
- uint64_t saved_reg_map = 0;
- AddressType saved_regs[MAX_REGISTERS];
-
- inline AddressType Get(uint32_t reg) {
- if (IsSaved(reg)) {
- return saved_regs[reg];
- }
- return (*regs)[reg];
- }
-
- inline AddressType* Save(uint32_t reg) {
- if (reg >= MAX_REGISTERS) {
- // This should never happen since all currently supported
- // architectures have < 64 total registers.
- abort();
- }
- saved_reg_map |= 1ULL << reg;
- saved_regs[reg] = (*regs)[reg];
- return &(*regs)[reg];
- }
-
- inline bool IsSaved(uint32_t reg) {
- if (reg > MAX_REGISTERS) {
- // This should never happen since all currently supported
- // architectures have < 64 total registers.
- abort();
- }
- return saved_reg_map & (1ULL << reg);
- }
-
- inline uint16_t Total() { return regs->total_regs(); }
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_REGS_INFO_H
diff --git a/libunwindstack/RegsMips.cpp b/libunwindstack/RegsMips.cpp
deleted file mode 100644
index ab84691..0000000
--- a/libunwindstack/RegsMips.cpp
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) 2017 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 <stdint.h>
-#include <string.h>
-
-#include <functional>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/MachineMips.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/RegsMips.h>
-#include <unwindstack/UcontextMips.h>
-#include <unwindstack/UserMips.h>
-
-namespace unwindstack {
-
-RegsMips::RegsMips()
- : RegsImpl<uint32_t>(MIPS_REG_LAST, Location(LOCATION_REGISTER, MIPS_REG_RA)) {}
-
-ArchEnum RegsMips::Arch() {
- return ARCH_MIPS;
-}
-
-uint64_t RegsMips::pc() {
- return regs_[MIPS_REG_PC];
-}
-
-uint64_t RegsMips::sp() {
- return regs_[MIPS_REG_SP];
-}
-
-void RegsMips::set_pc(uint64_t pc) {
- regs_[MIPS_REG_PC] = static_cast<uint32_t>(pc);
-}
-
-void RegsMips::set_sp(uint64_t sp) {
- regs_[MIPS_REG_SP] = static_cast<uint32_t>(sp);
-}
-
-bool RegsMips::SetPcFromReturnAddress(Memory*) {
- uint32_t ra = regs_[MIPS_REG_RA];
- if (regs_[MIPS_REG_PC] == ra) {
- return false;
- }
-
- regs_[MIPS_REG_PC] = ra;
- return true;
-}
-
-void RegsMips::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
- fn("r0", regs_[MIPS_REG_R0]);
- fn("r1", regs_[MIPS_REG_R1]);
- fn("r2", regs_[MIPS_REG_R2]);
- fn("r3", regs_[MIPS_REG_R3]);
- fn("r4", regs_[MIPS_REG_R4]);
- fn("r5", regs_[MIPS_REG_R5]);
- fn("r6", regs_[MIPS_REG_R6]);
- fn("r7", regs_[MIPS_REG_R7]);
- fn("r8", regs_[MIPS_REG_R8]);
- fn("r9", regs_[MIPS_REG_R9]);
- fn("r10", regs_[MIPS_REG_R10]);
- fn("r11", regs_[MIPS_REG_R11]);
- fn("r12", regs_[MIPS_REG_R12]);
- fn("r13", regs_[MIPS_REG_R13]);
- fn("r14", regs_[MIPS_REG_R14]);
- fn("r15", regs_[MIPS_REG_R15]);
- fn("r16", regs_[MIPS_REG_R16]);
- fn("r17", regs_[MIPS_REG_R17]);
- fn("r18", regs_[MIPS_REG_R18]);
- fn("r19", regs_[MIPS_REG_R19]);
- fn("r20", regs_[MIPS_REG_R20]);
- fn("r21", regs_[MIPS_REG_R21]);
- fn("r22", regs_[MIPS_REG_R22]);
- fn("r23", regs_[MIPS_REG_R23]);
- fn("r24", regs_[MIPS_REG_R24]);
- fn("r25", regs_[MIPS_REG_R25]);
- fn("r26", regs_[MIPS_REG_R26]);
- fn("r27", regs_[MIPS_REG_R27]);
- fn("r28", regs_[MIPS_REG_R28]);
- fn("sp", regs_[MIPS_REG_SP]);
- fn("r30", regs_[MIPS_REG_R30]);
- fn("ra", regs_[MIPS_REG_RA]);
- fn("pc", regs_[MIPS_REG_PC]);
-}
-
-Regs* RegsMips::Read(void* remote_data) {
- mips_user_regs* user = reinterpret_cast<mips_user_regs*>(remote_data);
- RegsMips* regs = new RegsMips();
- uint32_t* reg_data = reinterpret_cast<uint32_t*>(regs->RawData());
-
- memcpy(regs->RawData(), &user->regs[MIPS32_EF_R0], (MIPS_REG_R31 + 1) * sizeof(uint32_t));
-
- reg_data[MIPS_REG_PC] = user->regs[MIPS32_EF_CP0_EPC];
- return regs;
-}
-
-Regs* RegsMips::CreateFromUcontext(void* ucontext) {
- mips_ucontext_t* mips_ucontext = reinterpret_cast<mips_ucontext_t*>(ucontext);
-
- RegsMips* regs = new RegsMips();
- // Copy 64 bit sc_regs over to 32 bit regs
- for (int i = 0; i < 32; i++) {
- (*regs)[MIPS_REG_R0 + i] = mips_ucontext->uc_mcontext.sc_regs[i];
- }
- (*regs)[MIPS_REG_PC] = mips_ucontext->uc_mcontext.sc_pc;
- return regs;
-}
-
-bool RegsMips::StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) {
- uint64_t data;
- uint64_t offset = 0;
- Memory* elf_memory = elf->memory();
- // Read from elf memory since it is usually more expensive to read from
- // process memory.
- if (!elf_memory->ReadFully(elf_offset, &data, sizeof(data))) {
- return false;
- }
-
- // Look for the kernel sigreturn functions.
- // __vdso_rt_sigreturn:
- // 0x24021061 li v0, 0x1061
- // 0x0000000c syscall
- // __vdso_sigreturn:
- // 0x24021017 li v0, 0x1017
- // 0x0000000c syscall
- if (data == 0x0000000c24021061ULL) {
- // vdso_rt_sigreturn => read rt_sigframe
- // offset = siginfo offset + sizeof(siginfo) + uc_mcontext offset + sc_pc offset
- offset = 24 + 128 + 24 + 8;
- } else if (data == 0x0000000c24021017LL) {
- // vdso_sigreturn => read sigframe
- // offset = sigcontext offset + sc_pc offset
- offset = 24 + 8;
- } else {
- return false;
- }
-
- // read sc_pc and sc_regs[32] from stack
- uint64_t values[MIPS_REG_LAST];
- if (!process_memory->ReadFully(regs_[MIPS_REG_SP] + offset, values, sizeof(values))) {
- return false;
- }
-
- // Copy 64 bit sc_pc over to 32 bit regs_[MIPS_REG_PC]
- regs_[MIPS_REG_PC] = values[0];
-
- // Copy 64 bit sc_regs over to 32 bit regs
- for (int i = 0; i < 32; i++) {
- regs_[MIPS_REG_R0 + i] = values[1 + i];
- }
- return true;
-}
-
-Regs* RegsMips::Clone() {
- return new RegsMips(*this);
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/RegsMips64.cpp b/libunwindstack/RegsMips64.cpp
deleted file mode 100644
index 7f600d3..0000000
--- a/libunwindstack/RegsMips64.cpp
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 2017 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 <stdint.h>
-#include <string.h>
-
-#include <functional>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/MachineMips64.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/RegsMips64.h>
-#include <unwindstack/UcontextMips64.h>
-#include <unwindstack/UserMips64.h>
-
-namespace unwindstack {
-
-RegsMips64::RegsMips64()
- : RegsImpl<uint64_t>(MIPS64_REG_LAST, Location(LOCATION_REGISTER, MIPS64_REG_RA)) {}
-
-ArchEnum RegsMips64::Arch() {
- return ARCH_MIPS64;
-}
-
-uint64_t RegsMips64::pc() {
- return regs_[MIPS64_REG_PC];
-}
-
-uint64_t RegsMips64::sp() {
- return regs_[MIPS64_REG_SP];
-}
-
-void RegsMips64::set_pc(uint64_t pc) {
- regs_[MIPS64_REG_PC] = pc;
-}
-
-void RegsMips64::set_sp(uint64_t sp) {
- regs_[MIPS64_REG_SP] = sp;
-}
-
-bool RegsMips64::SetPcFromReturnAddress(Memory*) {
- uint64_t ra = regs_[MIPS64_REG_RA];
- if (regs_[MIPS64_REG_PC] == ra) {
- return false;
- }
-
- regs_[MIPS64_REG_PC] = ra;
- return true;
-}
-
-void RegsMips64::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
- fn("r0", regs_[MIPS64_REG_R0]);
- fn("r1", regs_[MIPS64_REG_R1]);
- fn("r2", regs_[MIPS64_REG_R2]);
- fn("r3", regs_[MIPS64_REG_R3]);
- fn("r4", regs_[MIPS64_REG_R4]);
- fn("r5", regs_[MIPS64_REG_R5]);
- fn("r6", regs_[MIPS64_REG_R6]);
- fn("r7", regs_[MIPS64_REG_R7]);
- fn("r8", regs_[MIPS64_REG_R8]);
- fn("r9", regs_[MIPS64_REG_R9]);
- fn("r10", regs_[MIPS64_REG_R10]);
- fn("r11", regs_[MIPS64_REG_R11]);
- fn("r12", regs_[MIPS64_REG_R12]);
- fn("r13", regs_[MIPS64_REG_R13]);
- fn("r14", regs_[MIPS64_REG_R14]);
- fn("r15", regs_[MIPS64_REG_R15]);
- fn("r16", regs_[MIPS64_REG_R16]);
- fn("r17", regs_[MIPS64_REG_R17]);
- fn("r18", regs_[MIPS64_REG_R18]);
- fn("r19", regs_[MIPS64_REG_R19]);
- fn("r20", regs_[MIPS64_REG_R20]);
- fn("r21", regs_[MIPS64_REG_R21]);
- fn("r22", regs_[MIPS64_REG_R22]);
- fn("r23", regs_[MIPS64_REG_R23]);
- fn("r24", regs_[MIPS64_REG_R24]);
- fn("r25", regs_[MIPS64_REG_R25]);
- fn("r26", regs_[MIPS64_REG_R26]);
- fn("r27", regs_[MIPS64_REG_R27]);
- fn("r28", regs_[MIPS64_REG_R28]);
- fn("sp", regs_[MIPS64_REG_SP]);
- fn("r30", regs_[MIPS64_REG_R30]);
- fn("ra", regs_[MIPS64_REG_RA]);
- fn("pc", regs_[MIPS64_REG_PC]);
-}
-
-Regs* RegsMips64::Read(void* remote_data) {
- mips64_user_regs* user = reinterpret_cast<mips64_user_regs*>(remote_data);
- RegsMips64* regs = new RegsMips64();
- uint64_t* reg_data = reinterpret_cast<uint64_t*>(regs->RawData());
-
- memcpy(regs->RawData(), &user->regs[MIPS64_EF_R0], (MIPS64_REG_R31 + 1) * sizeof(uint64_t));
-
- reg_data[MIPS64_REG_PC] = user->regs[MIPS64_EF_CP0_EPC];
- return regs;
-}
-
-Regs* RegsMips64::CreateFromUcontext(void* ucontext) {
- mips64_ucontext_t* mips64_ucontext = reinterpret_cast<mips64_ucontext_t*>(ucontext);
-
- RegsMips64* regs = new RegsMips64();
- // Copy 64 bit sc_regs over to 64 bit regs
- memcpy(regs->RawData(), &mips64_ucontext->uc_mcontext.sc_regs[0], 32 * sizeof(uint64_t));
- (*regs)[MIPS64_REG_PC] = mips64_ucontext->uc_mcontext.sc_pc;
- return regs;
-}
-
-bool RegsMips64::StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) {
- uint64_t data;
- Memory* elf_memory = elf->memory();
- // Read from elf memory since it is usually more expensive to read from
- // process memory.
- if (!elf_memory->Read(elf_offset, &data, sizeof(data))) {
- return false;
- }
-
- // Look for the kernel sigreturn function.
- // __vdso_rt_sigreturn:
- // 0x2402145b li v0, 0x145b
- // 0x0000000c syscall
- if (data != 0x0000000c2402145bULL) {
- return false;
- }
-
- // vdso_rt_sigreturn => read rt_sigframe
- // offset = siginfo offset + sizeof(siginfo) + uc_mcontext offset
- // read 64 bit sc_regs[32] from stack into 64 bit regs_
- uint64_t sp = regs_[MIPS64_REG_SP];
- if (!process_memory->Read(sp + 24 + 128 + 40, regs_.data(),
- sizeof(uint64_t) * (MIPS64_REG_LAST - 1))) {
- return false;
- }
-
- // offset = siginfo offset + sizeof(siginfo) + uc_mcontext offset + sc_pc offset
- // read 64 bit sc_pc from stack into 64 bit regs_[MIPS64_REG_PC]
- if (!process_memory->Read(sp + 24 + 128 + 40 + 576, ®s_[MIPS64_REG_PC], sizeof(uint64_t))) {
- return false;
- }
- return true;
-}
-
-Regs* RegsMips64::Clone() {
- return new RegsMips64(*this);
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/RegsX86.cpp b/libunwindstack/RegsX86.cpp
deleted file mode 100644
index 4d3c246..0000000
--- a/libunwindstack/RegsX86.cpp
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2016 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 <stdint.h>
-
-#include <functional>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/MachineX86.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/RegsX86.h>
-#include <unwindstack/UcontextX86.h>
-#include <unwindstack/UserX86.h>
-
-namespace unwindstack {
-
-RegsX86::RegsX86() : RegsImpl<uint32_t>(X86_REG_LAST, Location(LOCATION_SP_OFFSET, -4)) {}
-
-ArchEnum RegsX86::Arch() {
- return ARCH_X86;
-}
-
-uint64_t RegsX86::pc() {
- return regs_[X86_REG_PC];
-}
-
-uint64_t RegsX86::sp() {
- return regs_[X86_REG_SP];
-}
-
-void RegsX86::set_pc(uint64_t pc) {
- regs_[X86_REG_PC] = static_cast<uint32_t>(pc);
-}
-
-void RegsX86::set_sp(uint64_t sp) {
- regs_[X86_REG_SP] = static_cast<uint32_t>(sp);
-}
-
-bool RegsX86::SetPcFromReturnAddress(Memory* process_memory) {
- // Attempt to get the return address from the top of the stack.
- uint32_t new_pc;
- if (!process_memory->ReadFully(regs_[X86_REG_SP], &new_pc, sizeof(new_pc)) ||
- new_pc == regs_[X86_REG_PC]) {
- return false;
- }
-
- regs_[X86_REG_PC] = new_pc;
- return true;
-}
-
-void RegsX86::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
- fn("eax", regs_[X86_REG_EAX]);
- fn("ebx", regs_[X86_REG_EBX]);
- fn("ecx", regs_[X86_REG_ECX]);
- fn("edx", regs_[X86_REG_EDX]);
- fn("ebp", regs_[X86_REG_EBP]);
- fn("edi", regs_[X86_REG_EDI]);
- fn("esi", regs_[X86_REG_ESI]);
- fn("esp", regs_[X86_REG_ESP]);
- fn("eip", regs_[X86_REG_EIP]);
-}
-
-Regs* RegsX86::Read(void* user_data) {
- x86_user_regs* user = reinterpret_cast<x86_user_regs*>(user_data);
-
- RegsX86* regs = new RegsX86();
- (*regs)[X86_REG_EAX] = user->eax;
- (*regs)[X86_REG_EBX] = user->ebx;
- (*regs)[X86_REG_ECX] = user->ecx;
- (*regs)[X86_REG_EDX] = user->edx;
- (*regs)[X86_REG_EBP] = user->ebp;
- (*regs)[X86_REG_EDI] = user->edi;
- (*regs)[X86_REG_ESI] = user->esi;
- (*regs)[X86_REG_ESP] = user->esp;
- (*regs)[X86_REG_EIP] = user->eip;
-
- return regs;
-}
-
-void RegsX86::SetFromUcontext(x86_ucontext_t* ucontext) {
- // Put the registers in the expected order.
- regs_[X86_REG_EDI] = ucontext->uc_mcontext.edi;
- regs_[X86_REG_ESI] = ucontext->uc_mcontext.esi;
- regs_[X86_REG_EBP] = ucontext->uc_mcontext.ebp;
- regs_[X86_REG_ESP] = ucontext->uc_mcontext.esp;
- regs_[X86_REG_EBX] = ucontext->uc_mcontext.ebx;
- regs_[X86_REG_EDX] = ucontext->uc_mcontext.edx;
- regs_[X86_REG_ECX] = ucontext->uc_mcontext.ecx;
- regs_[X86_REG_EAX] = ucontext->uc_mcontext.eax;
- regs_[X86_REG_EIP] = ucontext->uc_mcontext.eip;
-}
-
-Regs* RegsX86::CreateFromUcontext(void* ucontext) {
- x86_ucontext_t* x86_ucontext = reinterpret_cast<x86_ucontext_t*>(ucontext);
-
- RegsX86* regs = new RegsX86();
- regs->SetFromUcontext(x86_ucontext);
- return regs;
-}
-
-bool RegsX86::StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) {
- uint64_t data;
- Memory* elf_memory = elf->memory();
- // Read from elf memory since it is usually more expensive to read from
- // process memory.
- if (!elf_memory->ReadFully(elf_offset, &data, sizeof(data))) {
- return false;
- }
-
- if (data == 0x80cd00000077b858ULL) {
- // Without SA_SIGINFO set, the return sequence is:
- //
- // __restore:
- // 0x58 pop %eax
- // 0xb8 0x77 0x00 0x00 0x00 movl 0x77,%eax
- // 0xcd 0x80 int 0x80
- //
- // SP points at arguments:
- // int signum
- // struct sigcontext (same format as mcontext)
- struct x86_mcontext_t context;
- if (!process_memory->ReadFully(regs_[X86_REG_SP] + 4, &context, sizeof(context))) {
- return false;
- }
- regs_[X86_REG_EBP] = context.ebp;
- regs_[X86_REG_ESP] = context.esp;
- regs_[X86_REG_EBX] = context.ebx;
- regs_[X86_REG_EDX] = context.edx;
- regs_[X86_REG_ECX] = context.ecx;
- regs_[X86_REG_EAX] = context.eax;
- regs_[X86_REG_EIP] = context.eip;
- return true;
- } else if ((data & 0x00ffffffffffffffULL) == 0x0080cd000000adb8ULL) {
- // With SA_SIGINFO set, the return sequence is:
- //
- // __restore_rt:
- // 0xb8 0xad 0x00 0x00 0x00 movl 0xad,%eax
- // 0xcd 0x80 int 0x80
- //
- // SP points at arguments:
- // int signum
- // siginfo*
- // ucontext*
-
- // Get the location of the sigcontext data.
- uint32_t ptr;
- if (!process_memory->ReadFully(regs_[X86_REG_SP] + 8, &ptr, sizeof(ptr))) {
- return false;
- }
- // Only read the portion of the data structure we care about.
- x86_ucontext_t x86_ucontext;
- if (!process_memory->ReadFully(ptr + 0x14, &x86_ucontext.uc_mcontext, sizeof(x86_mcontext_t))) {
- return false;
- }
- SetFromUcontext(&x86_ucontext);
- return true;
- }
- return false;
-}
-
-Regs* RegsX86::Clone() {
- return new RegsX86(*this);
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/RegsX86_64.cpp b/libunwindstack/RegsX86_64.cpp
deleted file mode 100644
index 26d9f65..0000000
--- a/libunwindstack/RegsX86_64.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2016 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 <stdint.h>
-#include <string.h>
-
-#include <functional>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/MachineX86_64.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/RegsX86_64.h>
-#include <unwindstack/UcontextX86_64.h>
-#include <unwindstack/UserX86_64.h>
-
-namespace unwindstack {
-
-RegsX86_64::RegsX86_64() : RegsImpl<uint64_t>(X86_64_REG_LAST, Location(LOCATION_SP_OFFSET, -8)) {}
-
-ArchEnum RegsX86_64::Arch() {
- return ARCH_X86_64;
-}
-
-uint64_t RegsX86_64::pc() {
- return regs_[X86_64_REG_PC];
-}
-
-uint64_t RegsX86_64::sp() {
- return regs_[X86_64_REG_SP];
-}
-
-void RegsX86_64::set_pc(uint64_t pc) {
- regs_[X86_64_REG_PC] = pc;
-}
-
-void RegsX86_64::set_sp(uint64_t sp) {
- regs_[X86_64_REG_SP] = sp;
-}
-
-bool RegsX86_64::SetPcFromReturnAddress(Memory* process_memory) {
- // Attempt to get the return address from the top of the stack.
- uint64_t new_pc;
- if (!process_memory->ReadFully(regs_[X86_64_REG_SP], &new_pc, sizeof(new_pc)) ||
- new_pc == regs_[X86_64_REG_PC]) {
- return false;
- }
-
- regs_[X86_64_REG_PC] = new_pc;
- return true;
-}
-
-void RegsX86_64::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
- fn("rax", regs_[X86_64_REG_RAX]);
- fn("rbx", regs_[X86_64_REG_RBX]);
- fn("rcx", regs_[X86_64_REG_RCX]);
- fn("rdx", regs_[X86_64_REG_RDX]);
- fn("r8", regs_[X86_64_REG_R8]);
- fn("r9", regs_[X86_64_REG_R9]);
- fn("r10", regs_[X86_64_REG_R10]);
- fn("r11", regs_[X86_64_REG_R11]);
- fn("r12", regs_[X86_64_REG_R12]);
- fn("r13", regs_[X86_64_REG_R13]);
- fn("r14", regs_[X86_64_REG_R14]);
- fn("r15", regs_[X86_64_REG_R15]);
- fn("rdi", regs_[X86_64_REG_RDI]);
- fn("rsi", regs_[X86_64_REG_RSI]);
- fn("rbp", regs_[X86_64_REG_RBP]);
- fn("rsp", regs_[X86_64_REG_RSP]);
- fn("rip", regs_[X86_64_REG_RIP]);
-}
-
-Regs* RegsX86_64::Read(void* remote_data) {
- x86_64_user_regs* user = reinterpret_cast<x86_64_user_regs*>(remote_data);
-
- RegsX86_64* regs = new RegsX86_64();
- (*regs)[X86_64_REG_RAX] = user->rax;
- (*regs)[X86_64_REG_RBX] = user->rbx;
- (*regs)[X86_64_REG_RCX] = user->rcx;
- (*regs)[X86_64_REG_RDX] = user->rdx;
- (*regs)[X86_64_REG_R8] = user->r8;
- (*regs)[X86_64_REG_R9] = user->r9;
- (*regs)[X86_64_REG_R10] = user->r10;
- (*regs)[X86_64_REG_R11] = user->r11;
- (*regs)[X86_64_REG_R12] = user->r12;
- (*regs)[X86_64_REG_R13] = user->r13;
- (*regs)[X86_64_REG_R14] = user->r14;
- (*regs)[X86_64_REG_R15] = user->r15;
- (*regs)[X86_64_REG_RDI] = user->rdi;
- (*regs)[X86_64_REG_RSI] = user->rsi;
- (*regs)[X86_64_REG_RBP] = user->rbp;
- (*regs)[X86_64_REG_RSP] = user->rsp;
- (*regs)[X86_64_REG_RIP] = user->rip;
-
- return regs;
-}
-
-void RegsX86_64::SetFromUcontext(x86_64_ucontext_t* ucontext) {
- // R8-R15
- memcpy(®s_[X86_64_REG_R8], &ucontext->uc_mcontext.r8, 8 * sizeof(uint64_t));
-
- // Rest of the registers.
- regs_[X86_64_REG_RDI] = ucontext->uc_mcontext.rdi;
- regs_[X86_64_REG_RSI] = ucontext->uc_mcontext.rsi;
- regs_[X86_64_REG_RBP] = ucontext->uc_mcontext.rbp;
- regs_[X86_64_REG_RBX] = ucontext->uc_mcontext.rbx;
- regs_[X86_64_REG_RDX] = ucontext->uc_mcontext.rdx;
- regs_[X86_64_REG_RAX] = ucontext->uc_mcontext.rax;
- regs_[X86_64_REG_RCX] = ucontext->uc_mcontext.rcx;
- regs_[X86_64_REG_RSP] = ucontext->uc_mcontext.rsp;
- regs_[X86_64_REG_RIP] = ucontext->uc_mcontext.rip;
-}
-
-Regs* RegsX86_64::CreateFromUcontext(void* ucontext) {
- x86_64_ucontext_t* x86_64_ucontext = reinterpret_cast<x86_64_ucontext_t*>(ucontext);
-
- RegsX86_64* regs = new RegsX86_64();
- regs->SetFromUcontext(x86_64_ucontext);
- return regs;
-}
-
-bool RegsX86_64::StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) {
- uint64_t data;
- Memory* elf_memory = elf->memory();
- // Read from elf memory since it is usually more expensive to read from
- // process memory.
- if (!elf_memory->ReadFully(elf_offset, &data, sizeof(data)) || data != 0x0f0000000fc0c748) {
- return false;
- }
-
- uint8_t data2;
- if (!elf_memory->ReadFully(elf_offset + 8, &data2, sizeof(data2)) || data2 != 0x05) {
- return false;
- }
-
- // __restore_rt:
- // 0x48 0xc7 0xc0 0x0f 0x00 0x00 0x00 mov $0xf,%rax
- // 0x0f 0x05 syscall
-
- // Read the mcontext data from the stack.
- // sp points to the ucontext data structure, read only the mcontext part.
- x86_64_ucontext_t x86_64_ucontext;
- if (!process_memory->ReadFully(regs_[X86_64_REG_SP] + 0x28, &x86_64_ucontext.uc_mcontext,
- sizeof(x86_64_mcontext_t))) {
- return false;
- }
- SetFromUcontext(&x86_64_ucontext);
- return true;
-}
-
-Regs* RegsX86_64::Clone() {
- return new RegsX86_64(*this);
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/Symbols.cpp b/libunwindstack/Symbols.cpp
deleted file mode 100644
index 2117ebd..0000000
--- a/libunwindstack/Symbols.cpp
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2017 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 <elf.h>
-#include <stdint.h>
-
-#include <algorithm>
-#include <string>
-#include <vector>
-
-#include <unwindstack/Memory.h>
-
-#include "Check.h"
-#include "Symbols.h"
-
-namespace unwindstack {
-
-Symbols::Symbols(uint64_t offset, uint64_t size, uint64_t entry_size, uint64_t str_offset,
- uint64_t str_size)
- : offset_(offset),
- count_(entry_size != 0 ? size / entry_size : 0),
- entry_size_(entry_size),
- str_offset_(str_offset),
- str_end_(str_offset_ + str_size) {}
-
-template <typename SymType>
-static bool IsFunc(const SymType* entry) {
- return entry->st_shndx != SHN_UNDEF && ELF32_ST_TYPE(entry->st_info) == STT_FUNC;
-}
-
-// Read symbol entry from memory and cache it so we don't have to read it again.
-template <typename SymType>
-inline __attribute__((__always_inline__)) const Symbols::Info* Symbols::ReadFuncInfo(
- uint32_t symbol_index, Memory* elf_memory) {
- auto it = symbols_.find(symbol_index);
- if (it != symbols_.end()) {
- return &it->second;
- }
- SymType sym;
- if (!elf_memory->ReadFully(offset_ + symbol_index * entry_size_, &sym, sizeof(sym))) {
- return nullptr;
- }
- if (!IsFunc(&sym)) {
- // We need the address for binary search, but we don't want it to be matched.
- sym.st_size = 0;
- }
- Info info{.addr = sym.st_value, .size = static_cast<uint32_t>(sym.st_size), .name = sym.st_name};
- return &symbols_.emplace(symbol_index, info).first->second;
-}
-
-// Binary search the symbol table to find function containing the given address.
-// Without remap, the symbol table is assumed to be sorted and accessed directly.
-// If the symbol table is not sorted this method might fail but should not crash.
-// When the indices are remapped, they are guaranteed to be sorted by address.
-template <typename SymType, bool RemapIndices>
-const Symbols::Info* Symbols::BinarySearch(uint64_t addr, Memory* elf_memory) {
- size_t first = 0;
- size_t last = RemapIndices ? remap_->size() : count_;
- while (first < last) {
- size_t current = first + (last - first) / 2;
- size_t symbol_index = RemapIndices ? remap_.value()[current] : current;
- const Info* info = ReadFuncInfo<SymType>(symbol_index, elf_memory);
- if (info == nullptr) {
- return nullptr;
- }
- if (addr < info->addr) {
- last = current;
- } else if (addr < info->addr + info->size) {
- return info;
- } else {
- first = current + 1;
- }
- }
- return nullptr;
-}
-
-// Create remapping table which allows us to access symbols as if they were sorted by address.
-template <typename SymType>
-void Symbols::BuildRemapTable(Memory* elf_memory) {
- std::vector<uint64_t> addrs; // Addresses of all symbols (addrs[i] == symbols[i].st_value).
- addrs.reserve(count_);
- remap_.emplace(); // Construct the optional remap table.
- remap_->reserve(count_);
- for (size_t symbol_idx = 0; symbol_idx < count_;) {
- // Read symbols from memory. We intentionally bypass the cache to save memory.
- // Do the reads in batches so that we minimize the number of memory read calls.
- uint8_t buffer[1024];
- size_t read = std::min<size_t>(sizeof(buffer), (count_ - symbol_idx) * entry_size_);
- size_t size = elf_memory->Read(offset_ + symbol_idx * entry_size_, buffer, read);
- if (size < sizeof(SymType)) {
- break; // Stop processing, something looks like it is corrupted.
- }
- for (size_t offset = 0; offset + sizeof(SymType) <= size; offset += entry_size_, symbol_idx++) {
- SymType sym;
- memcpy(&sym, &buffer[offset], sizeof(SymType)); // Copy to ensure alignment.
- addrs.push_back(sym.st_value); // Always insert so it is indexable by symbol index.
- if (IsFunc(&sym)) {
- remap_->push_back(symbol_idx); // Indices of function symbols only.
- }
- }
- }
- // Sort by address to make the remap list binary searchable (stable due to the a<b tie break).
- auto comp = [&addrs](auto a, auto b) { return std::tie(addrs[a], a) < std::tie(addrs[b], b); };
- std::sort(remap_->begin(), remap_->end(), comp);
- // Remove duplicate entries (methods de-duplicated by the linker).
- auto pred = [&addrs](auto a, auto b) { return addrs[a] == addrs[b]; };
- remap_->erase(std::unique(remap_->begin(), remap_->end(), pred), remap_->end());
- remap_->shrink_to_fit();
-}
-
-template <typename SymType>
-bool Symbols::GetName(uint64_t addr, Memory* elf_memory, std::string* name, uint64_t* func_offset) {
- const Info* info;
- if (!remap_.has_value()) {
- // Assume the symbol table is sorted. If it is not, this will gracefully fail.
- info = BinarySearch<SymType, false>(addr, elf_memory);
- if (info == nullptr) {
- // Create the remapping table and retry the search.
- BuildRemapTable<SymType>(elf_memory);
- symbols_.clear(); // Remove cached symbols since the access pattern will be different.
- info = BinarySearch<SymType, true>(addr, elf_memory);
- }
- } else {
- // Fast search using the previously created remap table.
- info = BinarySearch<SymType, true>(addr, elf_memory);
- }
- if (info == nullptr) {
- return false;
- }
- // Read the function name from the string table.
- *func_offset = addr - info->addr;
- uint64_t str = str_offset_ + info->name;
- return str < str_end_ && elf_memory->ReadString(str, name, str_end_ - str);
-}
-
-template <typename SymType>
-bool Symbols::GetGlobal(Memory* elf_memory, const std::string& name, uint64_t* memory_address) {
- for (uint32_t i = 0; i < count_; i++) {
- SymType entry;
- if (!elf_memory->ReadFully(offset_ + i * entry_size_, &entry, sizeof(entry))) {
- return false;
- }
-
- if (entry.st_shndx != SHN_UNDEF && ELF32_ST_TYPE(entry.st_info) == STT_OBJECT &&
- ELF32_ST_BIND(entry.st_info) == STB_GLOBAL) {
- uint64_t str_offset = str_offset_ + entry.st_name;
- if (str_offset < str_end_) {
- std::string symbol;
- if (elf_memory->ReadString(str_offset, &symbol, str_end_ - str_offset) && symbol == name) {
- *memory_address = entry.st_value;
- return true;
- }
- }
- }
- }
- return false;
-}
-
-// Instantiate all of the needed template functions.
-template bool Symbols::GetName<Elf32_Sym>(uint64_t, Memory*, std::string*, uint64_t*);
-template bool Symbols::GetName<Elf64_Sym>(uint64_t, Memory*, std::string*, uint64_t*);
-
-template bool Symbols::GetGlobal<Elf32_Sym>(Memory*, const std::string&, uint64_t*);
-template bool Symbols::GetGlobal<Elf64_Sym>(Memory*, const std::string&, uint64_t*);
-} // namespace unwindstack
diff --git a/libunwindstack/Symbols.h b/libunwindstack/Symbols.h
deleted file mode 100644
index 3b3f20b..0000000
--- a/libunwindstack/Symbols.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_SYMBOLS_H
-#define _LIBUNWINDSTACK_SYMBOLS_H
-
-#include <stdint.h>
-
-#include <optional>
-#include <string>
-#include <unordered_map>
-
-namespace unwindstack {
-
-// Forward declaration.
-class Memory;
-
-class Symbols {
- struct Info {
- uint64_t addr; // Symbol address.
- uint32_t size; // Symbol size in bytes. Zero if not a function.
- uint32_t name; // Offset in .strtab.
- };
-
- public:
- Symbols(uint64_t offset, uint64_t size, uint64_t entry_size, uint64_t str_offset,
- uint64_t str_size);
- virtual ~Symbols() = default;
-
- template <typename SymType>
- bool GetName(uint64_t addr, Memory* elf_memory, std::string* name, uint64_t* func_offset);
-
- template <typename SymType>
- bool GetGlobal(Memory* elf_memory, const std::string& name, uint64_t* memory_address);
-
- void ClearCache() {
- symbols_.clear();
- remap_.reset();
- }
-
- private:
- template <typename SymType>
- const Info* ReadFuncInfo(uint32_t symbol_index, Memory* elf_memory);
-
- template <typename SymType, bool RemapIndices>
- const Info* BinarySearch(uint64_t addr, Memory* elf_memory);
-
- template <typename SymType>
- void BuildRemapTable(Memory* elf_memory);
-
- const uint64_t offset_;
- const uint64_t count_;
- const uint64_t entry_size_;
- const uint64_t str_offset_;
- const uint64_t str_end_;
-
- std::unordered_map<uint32_t, Info> symbols_; // Cache of read symbols (keyed by symbol index).
- std::optional<std::vector<uint32_t>> remap_; // Indices of function symbols sorted by address.
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_SYMBOLS_H
diff --git a/libunwindstack/TEST_MAPPING b/libunwindstack/TEST_MAPPING
deleted file mode 100644
index 909f897..0000000
--- a/libunwindstack/TEST_MAPPING
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "presubmit": [
- {
- "name": "libunwindstack_unit_test"
- },
- {
- "name": "CtsSimpleperfTestCases"
- }
- ]
-}
diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp
deleted file mode 100644
index 9ffc0f7..0000000
--- a/libunwindstack/Unwinder.cpp
+++ /dev/null
@@ -1,475 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#define _GNU_SOURCE 1
-#include <elf.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <algorithm>
-
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-
-#include <unwindstack/DexFiles.h>
-#include <unwindstack/Elf.h>
-#include <unwindstack/JitDebug.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/Unwinder.h>
-
-#include "Check.h"
-
-// Use the demangler from libc++.
-extern "C" char* __cxa_demangle(const char*, char*, size_t*, int* status);
-
-namespace unwindstack {
-
-// Inject extra 'virtual' frame that represents the dex pc data.
-// The dex pc is a magic register defined in the Mterp interpreter,
-// and thus it will be restored/observed in the frame after it.
-// Adding the dex frame first here will create something like:
-// #7 pc 0015fa20 core.vdex java.util.Arrays.binarySearch+8
-// #8 pc 006b1ba1 libartd.so ExecuteMterpImpl+14625
-// #9 pc 0039a1ef libartd.so art::interpreter::Execute+719
-void Unwinder::FillInDexFrame() {
- size_t frame_num = frames_.size();
- frames_.resize(frame_num + 1);
- FrameData* frame = &frames_.at(frame_num);
- frame->num = frame_num;
-
- uint64_t dex_pc = regs_->dex_pc();
- frame->pc = dex_pc;
- frame->sp = regs_->sp();
-
- MapInfo* info = maps_->Find(dex_pc);
- if (info != nullptr) {
- frame->map_start = info->start;
- frame->map_end = info->end;
- // Since this is a dex file frame, the elf_start_offset is not set
- // by any of the normal code paths. Use the offset of the map since
- // that matches the actual offset.
- frame->map_elf_start_offset = info->offset;
- frame->map_exact_offset = info->offset;
- frame->map_load_bias = info->load_bias;
- frame->map_flags = info->flags;
- if (resolve_names_) {
- frame->map_name = info->name;
- }
- frame->rel_pc = dex_pc - info->start;
- } else {
- frame->rel_pc = dex_pc;
- warnings_ |= WARNING_DEX_PC_NOT_IN_MAP;
- return;
- }
-
- if (!resolve_names_) {
- return;
- }
-
-#if defined(DEXFILE_SUPPORT)
- if (dex_files_ == nullptr) {
- return;
- }
-
- dex_files_->GetMethodInformation(maps_, info, dex_pc, &frame->function_name,
- &frame->function_offset);
-#endif
-}
-
-FrameData* Unwinder::FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc,
- uint64_t pc_adjustment) {
- size_t frame_num = frames_.size();
- frames_.resize(frame_num + 1);
- FrameData* frame = &frames_.at(frame_num);
- frame->num = frame_num;
- frame->sp = regs_->sp();
- frame->rel_pc = rel_pc - pc_adjustment;
- frame->pc = regs_->pc() - pc_adjustment;
-
- if (map_info == nullptr) {
- // Nothing else to update.
- return nullptr;
- }
-
- if (resolve_names_) {
- frame->map_name = map_info->name;
- if (embedded_soname_ && map_info->elf_start_offset != 0 && !frame->map_name.empty()) {
- std::string soname = elf->GetSoname();
- if (!soname.empty()) {
- frame->map_name += '!' + soname;
- }
- }
- }
- frame->map_elf_start_offset = map_info->elf_start_offset;
- frame->map_exact_offset = map_info->offset;
- frame->map_start = map_info->start;
- frame->map_end = map_info->end;
- frame->map_flags = map_info->flags;
- frame->map_load_bias = elf->GetLoadBias();
- return frame;
-}
-
-static bool ShouldStop(const std::vector<std::string>* map_suffixes_to_ignore,
- std::string& map_name) {
- if (map_suffixes_to_ignore == nullptr) {
- return false;
- }
- auto pos = map_name.find_last_of('.');
- if (pos == std::string::npos) {
- return false;
- }
-
- return std::find(map_suffixes_to_ignore->begin(), map_suffixes_to_ignore->end(),
- map_name.substr(pos + 1)) != map_suffixes_to_ignore->end();
-}
-
-void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip,
- const std::vector<std::string>* map_suffixes_to_ignore) {
- CHECK(arch_ != ARCH_UNKNOWN);
- ClearErrors();
-
- frames_.clear();
- elf_from_memory_not_file_ = false;
-
- bool return_address_attempt = false;
- bool adjust_pc = false;
- for (; frames_.size() < max_frames_;) {
- uint64_t cur_pc = regs_->pc();
- uint64_t cur_sp = regs_->sp();
-
- MapInfo* map_info = maps_->Find(regs_->pc());
- uint64_t pc_adjustment = 0;
- uint64_t step_pc;
- uint64_t rel_pc;
- Elf* elf;
- if (map_info == nullptr) {
- step_pc = regs_->pc();
- rel_pc = step_pc;
- last_error_.code = ERROR_INVALID_MAP;
- } else {
- if (ShouldStop(map_suffixes_to_ignore, map_info->name)) {
- break;
- }
- elf = map_info->GetElf(process_memory_, arch_);
- // If this elf is memory backed, and there is a valid file, then set
- // an indicator that we couldn't open the file.
- if (!elf_from_memory_not_file_ && map_info->memory_backed_elf && !map_info->name.empty() &&
- map_info->name[0] != '[' && !android::base::StartsWith(map_info->name, "/memfd:")) {
- elf_from_memory_not_file_ = true;
- }
- step_pc = regs_->pc();
- rel_pc = elf->GetRelPc(step_pc, map_info);
- // Everyone except elf data in gdb jit debug maps uses the relative pc.
- if (!(map_info->flags & MAPS_FLAGS_JIT_SYMFILE_MAP)) {
- step_pc = rel_pc;
- }
- if (adjust_pc) {
- pc_adjustment = GetPcAdjustment(rel_pc, elf, arch_);
- } else {
- pc_adjustment = 0;
- }
- step_pc -= pc_adjustment;
-
- // If the pc is in an invalid elf file, try and get an Elf object
- // using the jit debug information.
- if (!elf->valid() && jit_debug_ != nullptr) {
- uint64_t adjusted_jit_pc = regs_->pc() - pc_adjustment;
- Elf* jit_elf = jit_debug_->GetElf(maps_, adjusted_jit_pc);
- if (jit_elf != nullptr) {
- // The jit debug information requires a non relative adjusted pc.
- step_pc = adjusted_jit_pc;
- elf = jit_elf;
- }
- }
- }
-
- FrameData* frame = nullptr;
- if (map_info == nullptr || initial_map_names_to_skip == nullptr ||
- std::find(initial_map_names_to_skip->begin(), initial_map_names_to_skip->end(),
- basename(map_info->name.c_str())) == initial_map_names_to_skip->end()) {
- if (regs_->dex_pc() != 0) {
- // Add a frame to represent the dex file.
- FillInDexFrame();
- // Clear the dex pc so that we don't repeat this frame later.
- regs_->set_dex_pc(0);
-
- // Make sure there is enough room for the real frame.
- if (frames_.size() == max_frames_) {
- last_error_.code = ERROR_MAX_FRAMES_EXCEEDED;
- break;
- }
- }
-
- frame = FillInFrame(map_info, elf, rel_pc, pc_adjustment);
-
- // Once a frame is added, stop skipping frames.
- initial_map_names_to_skip = nullptr;
- }
- adjust_pc = true;
-
- bool stepped = false;
- bool in_device_map = false;
- bool finished = false;
- if (map_info != nullptr) {
- if (map_info->flags & MAPS_FLAGS_DEVICE_MAP) {
- // Do not stop here, fall through in case we are
- // in the speculative unwind path and need to remove
- // some of the speculative frames.
- in_device_map = true;
- } else {
- MapInfo* sp_info = maps_->Find(regs_->sp());
- if (sp_info != nullptr && sp_info->flags & MAPS_FLAGS_DEVICE_MAP) {
- // Do not stop here, fall through in case we are
- // in the speculative unwind path and need to remove
- // 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;
- 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_);
- }
- }
- }
-
- if (frame != nullptr) {
- if (!resolve_names_ ||
- !elf->GetFunctionName(step_pc, &frame->function_name, &frame->function_offset)) {
- frame->function_name = "";
- frame->function_offset = 0;
- }
- }
-
- if (finished) {
- break;
- }
-
- if (!stepped) {
- if (return_address_attempt) {
- // Only remove the speculative frame if there are more than two frames
- // or the pc in the first frame is in a valid map.
- // This allows for a case where the code jumps into the middle of
- // nowhere, but there is no other unwind information after that.
- if (frames_.size() > 2 || (frames_.size() > 0 && maps_->Find(frames_[0].pc) != nullptr)) {
- // Remove the speculative frame.
- frames_.pop_back();
- }
- break;
- } else if (in_device_map) {
- // Do not attempt any other unwinding, pc or sp is in a device
- // map.
- break;
- } else {
- // Steping didn't work, try this secondary method.
- if (!regs_->SetPcFromReturnAddress(process_memory_.get())) {
- break;
- }
- return_address_attempt = true;
- }
- } else {
- return_address_attempt = false;
- if (max_frames_ == frames_.size()) {
- last_error_.code = ERROR_MAX_FRAMES_EXCEEDED;
- }
- }
-
- // If the pc and sp didn't change, then consider everything stopped.
- if (cur_pc == regs_->pc() && cur_sp == regs_->sp()) {
- last_error_.code = ERROR_REPEATED_FRAME;
- break;
- }
- }
-}
-
-std::string Unwinder::FormatFrame(const FrameData& frame) const {
- std::string data;
- if (ArchIs32Bit(arch_)) {
- data += android::base::StringPrintf(" #%02zu pc %08" PRIx64, frame.num, frame.rel_pc);
- } else {
- data += android::base::StringPrintf(" #%02zu pc %016" PRIx64, frame.num, frame.rel_pc);
- }
-
- if (frame.map_start == frame.map_end) {
- // No valid map associated with this frame.
- data += " <unknown>";
- } else if (!frame.map_name.empty()) {
- data += " " + frame.map_name;
- } else {
- data += android::base::StringPrintf(" <anonymous:%" PRIx64 ">", frame.map_start);
- }
-
- if (frame.map_elf_start_offset != 0) {
- data += android::base::StringPrintf(" (offset 0x%" PRIx64 ")", frame.map_elf_start_offset);
- }
-
- if (!frame.function_name.empty()) {
- char* demangled_name = __cxa_demangle(frame.function_name.c_str(), nullptr, nullptr, nullptr);
- if (demangled_name == nullptr) {
- data += " (" + frame.function_name;
- } else {
- data += " (";
- data += demangled_name;
- free(demangled_name);
- }
- if (frame.function_offset != 0) {
- data += android::base::StringPrintf("+%" PRId64, frame.function_offset);
- }
- data += ')';
- }
-
- MapInfo* map_info = maps_->Find(frame.map_start);
- if (map_info != nullptr && display_build_id_) {
- std::string build_id = map_info->GetPrintableBuildID();
- if (!build_id.empty()) {
- data += " (BuildId: " + build_id + ')';
- }
- }
- return data;
-}
-
-std::string Unwinder::FormatFrame(size_t frame_num) const {
- if (frame_num >= frames_.size()) {
- return "";
- }
- return FormatFrame(frames_[frame_num]);
-}
-
-void Unwinder::SetJitDebug(JitDebug* jit_debug) {
- CHECK(arch_ != ARCH_UNKNOWN);
- jit_debug->SetArch(arch_);
- jit_debug_ = jit_debug;
-}
-
-void Unwinder::SetDexFiles(DexFiles* dex_files) {
- CHECK(arch_ != ARCH_UNKNOWN);
- dex_files->SetArch(arch_);
- dex_files_ = dex_files;
-}
-
-bool UnwinderFromPid::Init() {
- CHECK(arch_ != ARCH_UNKNOWN);
- if (initted_) {
- return true;
- }
- initted_ = true;
-
- if (pid_ == getpid()) {
- maps_ptr_.reset(new LocalMaps());
- } else {
- maps_ptr_.reset(new RemoteMaps(pid_));
- }
- if (!maps_ptr_->Parse()) {
- ClearErrors();
- last_error_.code = ERROR_INVALID_MAP;
- return false;
- }
- maps_ = maps_ptr_.get();
-
- process_memory_ = Memory::CreateProcessMemoryCached(pid_);
-
- jit_debug_ptr_.reset(new JitDebug(process_memory_));
- jit_debug_ = jit_debug_ptr_.get();
- SetJitDebug(jit_debug_);
-#if defined(DEXFILE_SUPPORT)
- dex_files_ptr_.reset(new DexFiles(process_memory_));
- dex_files_ = dex_files_ptr_.get();
- SetDexFiles(dex_files_);
-#endif
-
- return true;
-}
-
-void UnwinderFromPid::Unwind(const std::vector<std::string>* initial_map_names_to_skip,
- const std::vector<std::string>* map_suffixes_to_ignore) {
- if (!Init()) {
- return;
- }
- Unwinder::Unwind(initial_map_names_to_skip, map_suffixes_to_ignore);
-}
-
-FrameData Unwinder::BuildFrameFromPcOnly(uint64_t pc, ArchEnum arch, Maps* maps,
- JitDebug* jit_debug,
- std::shared_ptr<Memory> process_memory,
- bool resolve_names) {
- FrameData frame;
-
- MapInfo* map_info = maps->Find(pc);
- if (map_info == nullptr || arch == ARCH_UNKNOWN) {
- frame.pc = pc;
- frame.rel_pc = pc;
- return frame;
- }
-
- Elf* elf = map_info->GetElf(process_memory, arch);
-
- uint64_t relative_pc = elf->GetRelPc(pc, map_info);
-
- uint64_t pc_adjustment = GetPcAdjustment(relative_pc, elf, arch);
- relative_pc -= pc_adjustment;
- // The debug PC may be different if the PC comes from the JIT.
- uint64_t debug_pc = relative_pc;
-
- // If we don't have a valid ELF file, check the JIT.
- if (!elf->valid() && jit_debug != nullptr) {
- uint64_t jit_pc = pc - pc_adjustment;
- Elf* jit_elf = jit_debug->GetElf(maps, jit_pc);
- if (jit_elf != nullptr) {
- debug_pc = jit_pc;
- elf = jit_elf;
- }
- }
-
- // Copy all the things we need into the frame for symbolization.
- frame.rel_pc = relative_pc;
- frame.pc = pc - pc_adjustment;
- frame.map_name = map_info->name;
- frame.map_elf_start_offset = map_info->elf_start_offset;
- frame.map_exact_offset = map_info->offset;
- frame.map_start = map_info->start;
- frame.map_end = map_info->end;
- frame.map_flags = map_info->flags;
- frame.map_load_bias = elf->GetLoadBias();
-
- if (!resolve_names ||
- !elf->GetFunctionName(debug_pc, &frame.function_name, &frame.function_offset)) {
- frame.function_name = "";
- frame.function_offset = 0;
- }
- return frame;
-}
-
-FrameData Unwinder::BuildFrameFromPcOnly(uint64_t pc) {
- return BuildFrameFromPcOnly(pc, arch_, maps_, jit_debug_, process_memory_, resolve_names_);
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/benchmarks/ElfBenchmark.cpp b/libunwindstack/benchmarks/ElfBenchmark.cpp
deleted file mode 100644
index a46bd7a..0000000
--- a/libunwindstack/benchmarks/ElfBenchmark.cpp
+++ /dev/null
@@ -1,142 +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 <err.h>
-#include <malloc.h>
-#include <stdint.h>
-
-#include <string>
-
-#include <benchmark/benchmark.h>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/Regs.h>
-
-#include "Utils.h"
-
-static void BenchmarkElfCreate(benchmark::State& state, const std::string& elf_file) {
-#if defined(__BIONIC__)
- uint64_t rss_bytes = 0;
-#endif
- uint64_t alloc_bytes = 0;
- for (auto _ : state) {
- state.PauseTiming();
-#if defined(__BIONIC__)
- mallopt(M_PURGE, 0);
- uint64_t rss_bytes_before = 0;
- GatherRss(&rss_bytes_before);
-#endif
- uint64_t alloc_bytes_before = mallinfo().uordblks;
- auto file_memory = unwindstack::Memory::CreateFileMemory(elf_file, 0);
- state.ResumeTiming();
-
- unwindstack::Elf elf(file_memory.release());
- if (!elf.Init() || !elf.valid()) {
- errx(1, "Internal Error: Cannot open elf.");
- }
-
- state.PauseTiming();
-#if defined(__BIONIC__)
- mallopt(M_PURGE, 0);
-#endif
- alloc_bytes += mallinfo().uordblks - alloc_bytes_before;
-#if defined(__BIONIC__)
- GatherRss(&rss_bytes);
- rss_bytes -= rss_bytes_before;
-#endif
- state.ResumeTiming();
- }
-
-#if defined(__BIONIC__)
- state.counters["RSS_BYTES"] = rss_bytes / static_cast<double>(state.iterations());
-#endif
- state.counters["ALLOCATED_BYTES"] = alloc_bytes / static_cast<double>(state.iterations());
-}
-
-void BM_elf_create(benchmark::State& state) {
- BenchmarkElfCreate(state, GetElfFile());
-}
-BENCHMARK(BM_elf_create);
-
-void BM_elf_create_compressed(benchmark::State& state) {
- BenchmarkElfCreate(state, GetCompressedElfFile());
-}
-BENCHMARK(BM_elf_create_compressed);
-
-static void InitializeBuildId(benchmark::State& state, unwindstack::Maps& maps,
- unwindstack::MapInfo** build_id_map_info) {
- if (!maps.Parse()) {
- state.SkipWithError("Failed to parse local maps.");
- return;
- }
-
- // Find the libc.so share library and use that for benchmark purposes.
- *build_id_map_info = nullptr;
- for (auto& map_info : maps) {
- if (map_info->offset == 0 && map_info->GetBuildID() != "") {
- *build_id_map_info = map_info.get();
- break;
- }
- }
-
- if (*build_id_map_info == nullptr) {
- state.SkipWithError("Failed to find a map with a BuildID.");
- }
-}
-
-static void BM_elf_get_build_id_from_object(benchmark::State& state) {
- unwindstack::LocalMaps maps;
- unwindstack::MapInfo* build_id_map_info;
- InitializeBuildId(state, maps, &build_id_map_info);
-
- unwindstack::Elf* elf = build_id_map_info->GetElf(std::shared_ptr<unwindstack::Memory>(),
- unwindstack::Regs::CurrentArch());
- if (!elf->valid()) {
- state.SkipWithError("Cannot get valid elf from map.");
- }
-
- for (auto _ : state) {
- state.PauseTiming();
- uintptr_t id = build_id_map_info->build_id;
- if (id != 0) {
- delete reinterpret_cast<std::string*>(id);
- build_id_map_info->build_id = 0;
- }
- state.ResumeTiming();
- benchmark::DoNotOptimize(build_id_map_info->GetBuildID());
- }
-}
-BENCHMARK(BM_elf_get_build_id_from_object);
-
-static void BM_elf_get_build_id_from_file(benchmark::State& state) {
- unwindstack::LocalMaps maps;
- unwindstack::MapInfo* build_id_map_info;
- InitializeBuildId(state, maps, &build_id_map_info);
-
- for (auto _ : state) {
- state.PauseTiming();
- uintptr_t id = build_id_map_info->build_id;
- if (id != 0) {
- delete reinterpret_cast<std::string*>(id);
- build_id_map_info->build_id = 0;
- }
- state.ResumeTiming();
- benchmark::DoNotOptimize(build_id_map_info->GetBuildID());
- }
-}
-BENCHMARK(BM_elf_get_build_id_from_file);
diff --git a/libunwindstack/benchmarks/MapsBenchmark.cpp b/libunwindstack/benchmarks/MapsBenchmark.cpp
deleted file mode 100644
index 5df1491..0000000
--- a/libunwindstack/benchmarks/MapsBenchmark.cpp
+++ /dev/null
@@ -1,160 +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 <err.h>
-#include <stdint.h>
-
-#include <string>
-
-#include <android-base/file.h>
-#include <android-base/stringprintf.h>
-
-#include <benchmark/benchmark.h>
-
-#include <unwindstack/Maps.h>
-
-class BenchmarkLocalUpdatableMaps : public unwindstack::LocalUpdatableMaps {
- public:
- BenchmarkLocalUpdatableMaps() : unwindstack::LocalUpdatableMaps() {}
- virtual ~BenchmarkLocalUpdatableMaps() = default;
-
- const std::string GetMapsFile() const override { return maps_file_; }
-
- void BenchmarkSetMapsFile(const std::string& maps_file) { maps_file_ = maps_file; }
-
- private:
- std::string maps_file_;
-};
-
-static constexpr size_t kNumSmallMaps = 100;
-static constexpr size_t kNumLargeMaps = 10000;
-
-static void CreateMap(const char* filename, size_t num_maps, size_t increment = 1) {
- std::string maps;
- for (size_t i = 0; i < num_maps; i += increment) {
- maps += android::base::StringPrintf("%zu-%zu r-xp 0000 00:00 0 name%zu\n", i * 1000,
- (i + 1) * 1000 * increment, i * increment);
- }
- if (!android::base::WriteStringToFile(maps, filename)) {
- errx(1, "WriteStringToFile failed");
- }
-}
-
-static void ReparseBenchmark(benchmark::State& state, const char* maps1, size_t maps1_total,
- const char* maps2, size_t maps2_total) {
- for (auto _ : state) {
- BenchmarkLocalUpdatableMaps maps;
- maps.BenchmarkSetMapsFile(maps1);
- if (!maps.Reparse()) {
- errx(1, "Internal Error: reparse of initial maps filed.");
- }
- if (maps.Total() != maps1_total) {
- errx(1, "Internal Error: Incorrect total number of maps %zu, expected %zu.", maps.Total(),
- maps1_total);
- }
- maps.BenchmarkSetMapsFile(maps2);
- if (!maps.Reparse()) {
- errx(1, "Internal Error: reparse of second set of maps filed.");
- }
- if (maps.Total() != maps2_total) {
- errx(1, "Internal Error: Incorrect total number of maps %zu, expected %zu.", maps.Total(),
- maps2_total);
- }
- }
-}
-
-void BM_local_updatable_maps_reparse_double_initial_small(benchmark::State& state) {
- TemporaryFile initial_maps;
- CreateMap(initial_maps.path, kNumSmallMaps, 2);
-
- TemporaryFile reparse_maps;
- CreateMap(reparse_maps.path, kNumSmallMaps);
-
- ReparseBenchmark(state, initial_maps.path, kNumSmallMaps / 2, reparse_maps.path, kNumSmallMaps);
-}
-BENCHMARK(BM_local_updatable_maps_reparse_double_initial_small);
-
-void BM_local_updatable_maps_reparse_double_initial_large(benchmark::State& state) {
- TemporaryFile initial_maps;
- CreateMap(initial_maps.path, kNumLargeMaps, 2);
-
- TemporaryFile reparse_maps;
- CreateMap(reparse_maps.path, kNumLargeMaps);
-
- ReparseBenchmark(state, initial_maps.path, kNumLargeMaps / 2, reparse_maps.path, kNumLargeMaps);
-}
-BENCHMARK(BM_local_updatable_maps_reparse_double_initial_large);
-
-void BM_local_updatable_maps_reparse_same_maps_small(benchmark::State& state) {
- static constexpr size_t kNumSmallMaps = 100;
- TemporaryFile maps;
- CreateMap(maps.path, kNumSmallMaps);
-
- ReparseBenchmark(state, maps.path, kNumSmallMaps, maps.path, kNumSmallMaps);
-}
-BENCHMARK(BM_local_updatable_maps_reparse_same_maps_small);
-
-void BM_local_updatable_maps_reparse_same_maps_large(benchmark::State& state) {
- TemporaryFile maps;
- CreateMap(maps.path, kNumLargeMaps);
-
- ReparseBenchmark(state, maps.path, kNumLargeMaps, maps.path, kNumLargeMaps);
-}
-BENCHMARK(BM_local_updatable_maps_reparse_same_maps_large);
-
-void BM_local_updatable_maps_reparse_few_extra_small(benchmark::State& state) {
- TemporaryFile maps1;
- CreateMap(maps1.path, kNumSmallMaps - 4);
-
- TemporaryFile maps2;
- CreateMap(maps2.path, kNumSmallMaps);
-
- ReparseBenchmark(state, maps1.path, kNumSmallMaps - 4, maps2.path, kNumSmallMaps);
-}
-BENCHMARK(BM_local_updatable_maps_reparse_few_extra_small);
-
-void BM_local_updatable_maps_reparse_few_extra_large(benchmark::State& state) {
- TemporaryFile maps1;
- CreateMap(maps1.path, kNumLargeMaps - 4);
-
- TemporaryFile maps2;
- CreateMap(maps2.path, kNumLargeMaps);
-
- ReparseBenchmark(state, maps1.path, kNumLargeMaps - 4, maps2.path, kNumLargeMaps);
-}
-BENCHMARK(BM_local_updatable_maps_reparse_few_extra_large);
-
-void BM_local_updatable_maps_reparse_few_less_small(benchmark::State& state) {
- TemporaryFile maps1;
- CreateMap(maps1.path, kNumSmallMaps);
-
- TemporaryFile maps2;
- CreateMap(maps2.path, kNumSmallMaps - 4);
-
- ReparseBenchmark(state, maps1.path, kNumSmallMaps, maps2.path, kNumSmallMaps - 4);
-}
-BENCHMARK(BM_local_updatable_maps_reparse_few_less_small);
-
-void BM_local_updatable_maps_reparse_few_less_large(benchmark::State& state) {
- TemporaryFile maps1;
- CreateMap(maps1.path, kNumLargeMaps);
-
- TemporaryFile maps2;
- CreateMap(maps2.path, kNumLargeMaps - 4);
-
- ReparseBenchmark(state, maps1.path, kNumLargeMaps, maps2.path, kNumLargeMaps - 4);
-}
-BENCHMARK(BM_local_updatable_maps_reparse_few_less_large);
diff --git a/libunwindstack/benchmarks/SymbolBenchmark.cpp b/libunwindstack/benchmarks/SymbolBenchmark.cpp
deleted file mode 100644
index 73088da..0000000
--- a/libunwindstack/benchmarks/SymbolBenchmark.cpp
+++ /dev/null
@@ -1,129 +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 <err.h>
-#include <inttypes.h>
-#include <malloc.h>
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-#include <benchmark/benchmark.h>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/Memory.h>
-
-#include "Utils.h"
-
-static void BenchmarkSymbolLookup(benchmark::State& state, std::vector<uint64_t> offsets,
- std::string elf_file, bool expect_found) {
-#if defined(__BIONIC__)
- uint64_t rss_bytes = 0;
-#endif
- uint64_t alloc_bytes = 0;
- for (auto _ : state) {
- state.PauseTiming();
- unwindstack::Elf elf(unwindstack::Memory::CreateFileMemory(elf_file, 0).release());
- if (!elf.Init() || !elf.valid()) {
- errx(1, "Internal Error: Cannot open elf.");
- }
-
-#if defined(__BIONIC__)
- mallopt(M_PURGE, 0);
- uint64_t rss_bytes_before = 0;
- GatherRss(&rss_bytes_before);
-#endif
- uint64_t alloc_bytes_before = mallinfo().uordblks;
- state.ResumeTiming();
-
- for (auto pc : offsets) {
- std::string name;
- uint64_t offset;
- bool found = elf.GetFunctionName(pc, &name, &offset);
- if (expect_found && !found) {
- errx(1, "expected pc 0x%" PRIx64 " present, but not found.", pc);
- } else if (!expect_found && found) {
- errx(1, "expected pc 0x%" PRIx64 " not present, but found.", pc);
- }
- }
-
- state.PauseTiming();
-#if defined(__BIONIC__)
- mallopt(M_PURGE, 0);
-#endif
- alloc_bytes += mallinfo().uordblks - alloc_bytes_before;
-#if defined(__BIONIC__)
- GatherRss(&rss_bytes);
- rss_bytes -= rss_bytes_before;
-#endif
- state.ResumeTiming();
- }
-
-#if defined(__BIONIC__)
- state.counters["RSS_BYTES"] = rss_bytes / static_cast<double>(state.iterations());
-#endif
- state.counters["ALLOCATED_BYTES"] = alloc_bytes / static_cast<double>(state.iterations());
-}
-
-static void BenchmarkSymbolLookup(benchmark::State& state, uint64_t pc, std::string elf_file,
- bool expect_found) {
- BenchmarkSymbolLookup(state, std::vector<uint64_t>{pc}, elf_file, expect_found);
-}
-
-void BM_symbol_not_present(benchmark::State& state) {
- BenchmarkSymbolLookup(state, 0, GetElfFile(), false);
-}
-BENCHMARK(BM_symbol_not_present);
-
-void BM_symbol_find_single(benchmark::State& state) {
- BenchmarkSymbolLookup(state, 0x22b2bc, GetElfFile(), true);
-}
-BENCHMARK(BM_symbol_find_single);
-
-void BM_symbol_find_single_many_times(benchmark::State& state) {
- BenchmarkSymbolLookup(state, std::vector<uint64_t>(15, 0x22b2bc), GetElfFile(), true);
-}
-BENCHMARK(BM_symbol_find_single_many_times);
-
-void BM_symbol_find_multiple(benchmark::State& state) {
- BenchmarkSymbolLookup(state,
- std::vector<uint64_t>{0x22b2bc, 0xd5d30, 0x1312e8, 0x13582e, 0x1389c8},
- GetElfFile(), true);
-}
-BENCHMARK(BM_symbol_find_multiple);
-
-void BM_symbol_not_present_from_sorted(benchmark::State& state) {
- BenchmarkSymbolLookup(state, 0, GetSymbolSortedElfFile(), false);
-}
-BENCHMARK(BM_symbol_not_present_from_sorted);
-
-void BM_symbol_find_single_from_sorted(benchmark::State& state) {
- BenchmarkSymbolLookup(state, 0x138638, GetSymbolSortedElfFile(), true);
-}
-BENCHMARK(BM_symbol_find_single_from_sorted);
-
-void BM_symbol_find_single_many_times_from_sorted(benchmark::State& state) {
- BenchmarkSymbolLookup(state, std::vector<uint64_t>(15, 0x138638), GetSymbolSortedElfFile(), true);
-}
-BENCHMARK(BM_symbol_find_single_many_times_from_sorted);
-
-void BM_symbol_find_multiple_from_sorted(benchmark::State& state) {
- BenchmarkSymbolLookup(state,
- std::vector<uint64_t>{0x138638, 0x84350, 0x14df18, 0x1f3a38, 0x1f3ca8},
- GetSymbolSortedElfFile(), true);
-}
-BENCHMARK(BM_symbol_find_multiple_from_sorted);
diff --git a/libunwindstack/benchmarks/Utils.cpp b/libunwindstack/benchmarks/Utils.cpp
deleted file mode 100644
index c92f109..0000000
--- a/libunwindstack/benchmarks/Utils.cpp
+++ /dev/null
@@ -1,62 +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 <err.h>
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/strings.h>
-#include <benchmark/benchmark.h>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/Memory.h>
-
-std::string GetElfFile() {
- return android::base::GetExecutableDirectory() + "/benchmarks/files/libart_arm.so";
-}
-
-std::string GetSymbolSortedElfFile() {
- return android::base::GetExecutableDirectory() + "/benchmarks/files/boot_arm.oat";
-}
-
-std::string GetCompressedElfFile() {
- // Both are the same right now.
- return GetSymbolSortedElfFile();
-}
-
-#if defined(__BIONIC__)
-
-#include <meminfo/procmeminfo.h>
-#include <procinfo/process_map.h>
-
-void GatherRss(uint64_t* rss_bytes) {
- android::meminfo::ProcMemInfo proc_mem(getpid());
- const std::vector<android::meminfo::Vma>& maps = proc_mem.MapsWithoutUsageStats();
- for (auto& vma : maps) {
- if (vma.name == "[anon:libc_malloc]" || android::base::StartsWith(vma.name, "[anon:scudo:") ||
- android::base::StartsWith(vma.name, "[anon:GWP-ASan")) {
- android::meminfo::Vma update_vma(vma);
- if (!proc_mem.FillInVmaStats(update_vma)) {
- err(1, "FillInVmaStats failed\n");
- }
- *rss_bytes += update_vma.usage.rss;
- }
- }
-}
-#endif
diff --git a/libunwindstack/benchmarks/Utils.h b/libunwindstack/benchmarks/Utils.h
deleted file mode 100644
index bee6efc..0000000
--- a/libunwindstack/benchmarks/Utils.h
+++ /dev/null
@@ -1,39 +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.
- */
-
-#ifndef _LIBUNWINDSTACK_UTILS_H
-#define _LIBUNWINDSTACK_UTILS_H
-
-#include <stdint.h>
-
-#include <string>
-
-std::string GetElfFile();
-
-std::string GetSymbolSortedElfFile();
-
-std::string GetCompressedElfFile();
-
-#if defined(__BIONIC__)
-
-#include <meminfo/procmeminfo.h>
-#include <procinfo/process_map.h>
-
-void GatherRss(uint64_t* rss_bytes);
-
-#endif
-
-#endif // _LIBUNWINDSTACK_UTILS_h
diff --git a/libunwindstack/benchmarks/files/boot_arm.oat b/libunwindstack/benchmarks/files/boot_arm.oat
deleted file mode 100644
index 51188eb..0000000
--- a/libunwindstack/benchmarks/files/boot_arm.oat
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/benchmarks/files/libart_arm.so b/libunwindstack/benchmarks/files/libart_arm.so
deleted file mode 100644
index 2201faf..0000000
--- a/libunwindstack/benchmarks/files/libart_arm.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/benchmarks/unwind_benchmarks.cpp b/libunwindstack/benchmarks/unwind_benchmarks.cpp
deleted file mode 100644
index 0bee6ef..0000000
--- a/libunwindstack/benchmarks/unwind_benchmarks.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2018 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 <stdint.h>
-
-#include <memory>
-
-#include <benchmark/benchmark.h>
-
-#include <android-base/strings.h>
-
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/Regs.h>
-#include <unwindstack/RegsGetLocal.h>
-#include <unwindstack/Unwinder.h>
-
-size_t Call6(std::shared_ptr<unwindstack::Memory>& process_memory, unwindstack::Maps* maps) {
- std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromLocal());
- unwindstack::RegsGetLocal(regs.get());
- unwindstack::Unwinder unwinder(32, maps, regs.get(), process_memory);
- unwinder.Unwind();
- return unwinder.NumFrames();
-}
-
-size_t Call5(std::shared_ptr<unwindstack::Memory>& process_memory, unwindstack::Maps* maps) {
- return Call6(process_memory, maps);
-}
-
-size_t Call4(std::shared_ptr<unwindstack::Memory>& process_memory, unwindstack::Maps* maps) {
- return Call5(process_memory, maps);
-}
-
-size_t Call3(std::shared_ptr<unwindstack::Memory>& process_memory, unwindstack::Maps* maps) {
- return Call4(process_memory, maps);
-}
-
-size_t Call2(std::shared_ptr<unwindstack::Memory>& process_memory, unwindstack::Maps* maps) {
- return Call3(process_memory, maps);
-}
-
-size_t Call1(std::shared_ptr<unwindstack::Memory>& process_memory, unwindstack::Maps* maps) {
- return Call2(process_memory, maps);
-}
-
-static void BM_uncached_unwind(benchmark::State& state) {
- auto process_memory = unwindstack::Memory::CreateProcessMemory(getpid());
- unwindstack::LocalMaps maps;
- if (!maps.Parse()) {
- state.SkipWithError("Failed to parse local maps.");
- }
-
- for (auto _ : state) {
- benchmark::DoNotOptimize(Call1(process_memory, &maps));
- }
-}
-BENCHMARK(BM_uncached_unwind);
-
-static void BM_cached_unwind(benchmark::State& state) {
- auto process_memory = unwindstack::Memory::CreateProcessMemoryCached(getpid());
- unwindstack::LocalMaps maps;
- if (!maps.Parse()) {
- state.SkipWithError("Failed to parse local maps.");
- }
-
- for (auto _ : state) {
- benchmark::DoNotOptimize(Call1(process_memory, &maps));
- }
-}
-BENCHMARK(BM_cached_unwind);
-
-BENCHMARK_MAIN();
diff --git a/libunwindstack/include/unwindstack/Arch.h b/libunwindstack/include/unwindstack/Arch.h
deleted file mode 100644
index 7060004..0000000
--- a/libunwindstack/include/unwindstack/Arch.h
+++ /dev/null
@@ -1,47 +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.
- */
-
-#ifndef _LIBUNWINDSTACK_ARCH_H
-#define _LIBUNWINDSTACK_ARCH_H
-
-#include <stddef.h>
-
-namespace unwindstack {
-
-enum ArchEnum : uint8_t {
- ARCH_UNKNOWN = 0,
- ARCH_ARM,
- ARCH_ARM64,
- ARCH_X86,
- ARCH_X86_64,
- ARCH_MIPS,
- ARCH_MIPS64,
-};
-
-static inline bool ArchIs32Bit(ArchEnum arch) {
- switch (arch) {
- case ARCH_ARM:
- case ARCH_X86:
- case ARCH_MIPS:
- return true;
- default:
- return false;
- }
-}
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_ARCH_H
diff --git a/libunwindstack/include/unwindstack/DexFiles.h b/libunwindstack/include/unwindstack/DexFiles.h
deleted file mode 100644
index 67a9640..0000000
--- a/libunwindstack/include/unwindstack/DexFiles.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#ifndef _LIBUNWINDSTACK_DEX_FILES_H
-#define _LIBUNWINDSTACK_DEX_FILES_H
-
-#include <stdint.h>
-
-#include <memory>
-#include <mutex>
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-#include <unwindstack/Global.h>
-#include <unwindstack/Memory.h>
-
-namespace unwindstack {
-
-// Forward declarations.
-class DexFile;
-class Maps;
-struct MapInfo;
-enum ArchEnum : uint8_t;
-
-class DexFiles : public Global {
- public:
- explicit DexFiles(std::shared_ptr<Memory>& memory);
- DexFiles(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs);
- virtual ~DexFiles();
-
- DexFile* GetDexFile(uint64_t dex_file_offset, MapInfo* info);
-
- void GetMethodInformation(Maps* maps, MapInfo* info, uint64_t dex_pc, std::string* method_name,
- uint64_t* method_offset);
-
- private:
- void Init(Maps* maps);
-
- bool GetAddr(size_t index, uint64_t* addr);
-
- uint64_t ReadEntryPtr32(uint64_t addr);
-
- uint64_t ReadEntryPtr64(uint64_t addr);
-
- bool ReadEntry32();
-
- bool ReadEntry64();
-
- bool ReadVariableData(uint64_t ptr_offset) override;
-
- void ProcessArch() override;
-
- std::mutex lock_;
- bool initialized_ = false;
- std::unordered_map<uint64_t, std::unique_ptr<DexFile>> files_;
-
- uint64_t entry_addr_ = 0;
- uint64_t (DexFiles::*read_entry_ptr_func_)(uint64_t) = nullptr;
- bool (DexFiles::*read_entry_func_)() = nullptr;
- std::vector<uint64_t> addrs_;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_DEX_FILES_H
diff --git a/libunwindstack/include/unwindstack/DwarfError.h b/libunwindstack/include/unwindstack/DwarfError.h
deleted file mode 100644
index 763e2cb..0000000
--- a/libunwindstack/include/unwindstack/DwarfError.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_DWARF_ERROR_H
-#define _LIBUNWINDSTACK_DWARF_ERROR_H
-
-#include <stdint.h>
-
-namespace unwindstack {
-
-enum DwarfErrorCode : uint8_t {
- DWARF_ERROR_NONE,
- DWARF_ERROR_MEMORY_INVALID,
- DWARF_ERROR_ILLEGAL_VALUE,
- DWARF_ERROR_ILLEGAL_STATE,
- DWARF_ERROR_STACK_INDEX_NOT_VALID,
- DWARF_ERROR_NOT_IMPLEMENTED,
- DWARF_ERROR_TOO_MANY_ITERATIONS,
- DWARF_ERROR_CFA_NOT_DEFINED,
- DWARF_ERROR_UNSUPPORTED_VERSION,
- DWARF_ERROR_NO_FDES,
-};
-
-struct DwarfErrorData {
- DwarfErrorCode code;
- uint64_t address;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_DWARF_ERROR_H
diff --git a/libunwindstack/include/unwindstack/DwarfLocation.h b/libunwindstack/include/unwindstack/DwarfLocation.h
deleted file mode 100644
index bf45bc7..0000000
--- a/libunwindstack/include/unwindstack/DwarfLocation.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_DWARF_LOCATION_H
-#define _LIBUNWINDSTACK_DWARF_LOCATION_H
-
-#include <stdint.h>
-
-#include <unordered_map>
-
-namespace unwindstack {
-
-struct DwarfCie;
-
-enum DwarfLocationEnum : uint8_t {
- DWARF_LOCATION_INVALID = 0,
- DWARF_LOCATION_UNDEFINED,
- DWARF_LOCATION_OFFSET,
- DWARF_LOCATION_VAL_OFFSET,
- DWARF_LOCATION_REGISTER,
- DWARF_LOCATION_EXPRESSION,
- DWARF_LOCATION_VAL_EXPRESSION,
- DWARF_LOCATION_PSEUDO_REGISTER,
-};
-
-struct DwarfLocation {
- DwarfLocationEnum type;
- uint64_t values[2];
-};
-
-struct DwarfLocations : public std::unordered_map<uint32_t, DwarfLocation> {
- const DwarfCie* cie;
- // The range of PCs where the locations are valid (end is exclusive).
- uint64_t pc_start = 0;
- uint64_t pc_end = 0;
-};
-typedef DwarfLocations dwarf_loc_regs_t;
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_DWARF_LOCATION_H
diff --git a/libunwindstack/include/unwindstack/DwarfMemory.h b/libunwindstack/include/unwindstack/DwarfMemory.h
deleted file mode 100644
index c45699a..0000000
--- a/libunwindstack/include/unwindstack/DwarfMemory.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_DWARF_MEMORY_H
-#define _LIBUNWINDSTACK_DWARF_MEMORY_H
-
-#include <stdint.h>
-
-namespace unwindstack {
-
-// Forward declarations.
-class Memory;
-
-class DwarfMemory {
- public:
- DwarfMemory(Memory* memory) : memory_(memory) {}
- virtual ~DwarfMemory() = default;
-
- bool ReadBytes(void* dst, size_t num_bytes);
-
- template <typename SignedType>
- bool ReadSigned(uint64_t* value);
-
- bool ReadULEB128(uint64_t* value);
-
- bool ReadSLEB128(int64_t* value);
-
- template <typename AddressType>
- size_t GetEncodedSize(uint8_t encoding);
-
- bool AdjustEncodedValue(uint8_t encoding, uint64_t* value);
-
- template <typename AddressType>
- bool ReadEncodedValue(uint8_t encoding, uint64_t* value);
-
- uint64_t cur_offset() { return cur_offset_; }
- void set_cur_offset(uint64_t cur_offset) { cur_offset_ = cur_offset; }
-
- void set_pc_offset(int64_t offset) { pc_offset_ = offset; }
- void clear_pc_offset() { pc_offset_ = INT64_MAX; }
-
- void set_data_offset(uint64_t offset) { data_offset_ = offset; }
- void clear_data_offset() { data_offset_ = static_cast<uint64_t>(-1); }
-
- void set_func_offset(uint64_t offset) { func_offset_ = offset; }
- void clear_func_offset() { func_offset_ = static_cast<uint64_t>(-1); }
-
- void set_text_offset(uint64_t offset) { text_offset_ = offset; }
- void clear_text_offset() { text_offset_ = static_cast<uint64_t>(-1); }
-
- private:
- Memory* memory_;
- uint64_t cur_offset_ = 0;
-
- int64_t pc_offset_ = INT64_MAX;
- uint64_t data_offset_ = static_cast<uint64_t>(-1);
- uint64_t func_offset_ = static_cast<uint64_t>(-1);
- uint64_t text_offset_ = static_cast<uint64_t>(-1);
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_DWARF_MEMORY_H
diff --git a/libunwindstack/include/unwindstack/DwarfSection.h b/libunwindstack/include/unwindstack/DwarfSection.h
deleted file mode 100644
index f28cf25..0000000
--- a/libunwindstack/include/unwindstack/DwarfSection.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_DWARF_SECTION_H
-#define _LIBUNWINDSTACK_DWARF_SECTION_H
-
-#include <stdint.h>
-
-#include <iterator>
-#include <map>
-#include <unordered_map>
-
-#include <unwindstack/DwarfError.h>
-#include <unwindstack/DwarfLocation.h>
-#include <unwindstack/DwarfMemory.h>
-#include <unwindstack/DwarfStructs.h>
-
-namespace unwindstack {
-
-// Forward declarations.
-enum ArchEnum : uint8_t;
-class Memory;
-class Regs;
-template <typename AddressType>
-struct RegsInfo;
-
-class DwarfSection {
- public:
- DwarfSection(Memory* memory);
- virtual ~DwarfSection() = default;
-
- class iterator : public std::iterator<std::bidirectional_iterator_tag, DwarfFde*> {
- public:
- iterator(DwarfSection* section, size_t index) : index_(index) {
- section->GetFdes(&fdes_);
- if (index_ == static_cast<size_t>(-1)) {
- index_ = fdes_.size();
- }
- }
-
- iterator& operator++() {
- index_++;
- return *this;
- }
- iterator& operator++(int increment) {
- index_ += increment;
- return *this;
- }
- iterator& operator--() {
- index_--;
- return *this;
- }
- iterator& operator--(int decrement) {
- index_ -= decrement;
- return *this;
- }
-
- bool operator==(const iterator& rhs) { return this->index_ == rhs.index_; }
- bool operator!=(const iterator& rhs) { return this->index_ != rhs.index_; }
-
- const DwarfFde* operator*() {
- if (index_ > fdes_.size()) return nullptr;
- return fdes_[index_];
- }
-
- private:
- std::vector<const DwarfFde*> fdes_;
- size_t index_ = 0;
- };
-
- iterator begin() { return iterator(this, 0); }
- iterator end() { return iterator(this, static_cast<size_t>(-1)); }
-
- DwarfErrorCode LastErrorCode() { return last_error_.code; }
- uint64_t LastErrorAddress() { return last_error_.address; }
-
- virtual bool Init(uint64_t offset, uint64_t size, int64_t section_bias) = 0;
-
- virtual bool Eval(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*) = 0;
-
- virtual bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde, ArchEnum arch) = 0;
-
- virtual void GetFdes(std::vector<const DwarfFde*>* fdes) = 0;
-
- virtual const DwarfFde* GetFdeFromPc(uint64_t pc) = 0;
-
- virtual bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs,
- ArchEnum arch) = 0;
-
- virtual uint64_t GetCieOffsetFromFde32(uint32_t pointer) = 0;
-
- virtual uint64_t GetCieOffsetFromFde64(uint64_t pointer) = 0;
-
- virtual uint64_t AdjustPcFromFde(uint64_t pc) = 0;
-
- bool Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished, bool* is_signal_frame);
-
- protected:
- DwarfMemory memory_;
- DwarfErrorData last_error_{DWARF_ERROR_NONE, 0};
-
- uint32_t cie32_value_ = 0;
- uint64_t cie64_value_ = 0;
-
- std::unordered_map<uint64_t, DwarfFde> fde_entries_;
- std::unordered_map<uint64_t, DwarfCie> cie_entries_;
- std::unordered_map<uint64_t, dwarf_loc_regs_t> cie_loc_regs_;
- std::map<uint64_t, dwarf_loc_regs_t> loc_regs_; // Single row indexed by pc_end.
-};
-
-template <typename AddressType>
-class DwarfSectionImpl : public DwarfSection {
- public:
- DwarfSectionImpl(Memory* memory) : DwarfSection(memory) {}
- virtual ~DwarfSectionImpl() = default;
-
- bool Init(uint64_t offset, uint64_t size, int64_t section_bias) override;
-
- const DwarfCie* GetCieFromOffset(uint64_t offset);
-
- const DwarfFde* GetFdeFromOffset(uint64_t offset);
-
- const DwarfFde* GetFdeFromPc(uint64_t pc) override;
-
- void GetFdes(std::vector<const DwarfFde*>* fdes) override;
-
- bool EvalRegister(const DwarfLocation* loc, uint32_t reg, AddressType* reg_ptr, void* info);
-
- bool Eval(const DwarfCie* cie, Memory* regular_memory, const dwarf_loc_regs_t& loc_regs,
- Regs* regs, bool* finished) override;
-
- bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs,
- ArchEnum arch) override;
-
- bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde, ArchEnum arch) override;
-
- protected:
- bool GetNextCieOrFde(const DwarfFde** fde_entry);
-
- bool FillInCieHeader(DwarfCie* cie);
-
- bool FillInCie(DwarfCie* cie);
-
- bool FillInFdeHeader(DwarfFde* fde);
-
- bool FillInFde(DwarfFde* fde);
-
- bool EvalExpression(const DwarfLocation& loc, Memory* regular_memory, AddressType* value,
- RegsInfo<AddressType>* regs_info, bool* is_dex_pc);
-
- void InsertFde(const DwarfFde* fde);
-
- int64_t section_bias_ = 0;
- uint64_t entries_offset_ = 0;
- uint64_t entries_end_ = 0;
- uint64_t next_entries_offset_ = 0;
- uint64_t pc_offset_ = 0;
-
- std::map<uint64_t, std::pair<uint64_t, const DwarfFde*>> fdes_;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_DWARF_SECTION_H
diff --git a/libunwindstack/include/unwindstack/DwarfStructs.h b/libunwindstack/include/unwindstack/DwarfStructs.h
deleted file mode 100644
index 3d8c2db..0000000
--- a/libunwindstack/include/unwindstack/DwarfStructs.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_DWARF_STRUCTS_H
-#define _LIBUNWINDSTACK_DWARF_STRUCTS_H
-
-#include <stdint.h>
-
-#include <vector>
-
-namespace unwindstack {
-
-struct DwarfCie {
- uint8_t version = 0;
- uint8_t fde_address_encoding = 0;
- uint8_t lsda_encoding = 0;
- uint8_t segment_size = 0;
- std::vector<char> augmentation_string;
- uint64_t personality_handler = 0;
- uint64_t cfa_instructions_offset = 0;
- uint64_t cfa_instructions_end = 0;
- 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 {
- uint64_t cie_offset = 0;
- uint64_t cfa_instructions_offset = 0;
- uint64_t cfa_instructions_end = 0;
- uint64_t pc_start = 0;
- uint64_t pc_end = 0;
- uint64_t lsda_address = 0;
- const DwarfCie* cie = nullptr;
-};
-
-constexpr uint16_t CFA_REG = static_cast<uint16_t>(-1);
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_DWARF_STRUCTS_H
diff --git a/libunwindstack/include/unwindstack/Elf.h b/libunwindstack/include/unwindstack/Elf.h
deleted file mode 100644
index e15b221..0000000
--- a/libunwindstack/include/unwindstack/Elf.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_ELF_H
-#define _LIBUNWINDSTACK_ELF_H
-
-#include <stddef.h>
-
-#include <memory>
-#include <mutex>
-#include <string>
-#include <unordered_map>
-#include <utility>
-
-#include <unwindstack/Arch.h>
-#include <unwindstack/ElfInterface.h>
-#include <unwindstack/Memory.h>
-
-#if !defined(EM_AARCH64)
-#define EM_AARCH64 183
-#endif
-
-namespace unwindstack {
-
-// Forward declaration.
-struct MapInfo;
-class Regs;
-
-class Elf {
- public:
- Elf(Memory* memory) : memory_(memory) {}
- virtual ~Elf() = default;
-
- bool Init();
-
- void InitGnuDebugdata();
-
- void Invalidate();
-
- std::string GetSoname();
-
- bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset);
-
- bool GetGlobalVariableOffset(const std::string& name, uint64_t* memory_offset);
-
- uint64_t GetRelPc(uint64_t pc, const MapInfo* map_info);
-
- 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* is_signal_frame);
-
- ElfInterface* CreateInterfaceFromMemory(Memory* memory);
-
- std::string GetBuildID();
-
- int64_t GetLoadBias() { return load_bias_; }
-
- bool IsValidPc(uint64_t pc);
-
- void GetLastError(ErrorData* data);
- ErrorCode GetLastErrorCode();
- uint64_t GetLastErrorAddress();
-
- bool valid() { return valid_; }
-
- uint32_t machine_type() { return machine_type_; }
-
- uint8_t class_type() { return class_type_; }
-
- ArchEnum arch() { return arch_; }
-
- Memory* memory() { return memory_.get(); }
-
- ElfInterface* interface() { return interface_.get(); }
-
- ElfInterface* gnu_debugdata_interface() { return gnu_debugdata_interface_.get(); }
-
- static bool IsValidElf(Memory* memory);
-
- static bool GetInfo(Memory* memory, uint64_t* size);
-
- static int64_t GetLoadBias(Memory* memory);
-
- static std::string GetBuildID(Memory* memory);
-
- static void SetCachingEnabled(bool enable);
- static bool CachingEnabled() { return cache_enabled_; }
-
- static void CacheLock();
- static void CacheUnlock();
- static void CacheAdd(MapInfo* info);
- static bool CacheGet(MapInfo* info);
- static bool CacheAfterCreateMemory(MapInfo* info);
-
- protected:
- bool valid_ = false;
- int64_t load_bias_ = 0;
- std::unique_ptr<ElfInterface> interface_;
- std::unique_ptr<Memory> memory_;
- uint32_t machine_type_;
- uint8_t class_type_;
- ArchEnum arch_;
- // Protect calls that can modify internal state of the interface object.
- std::mutex lock_;
-
- std::unique_ptr<Memory> gnu_debugdata_memory_;
- std::unique_ptr<ElfInterface> gnu_debugdata_interface_;
-
- static bool cache_enabled_;
- static std::unordered_map<std::string, std::pair<std::shared_ptr<Elf>, bool>>* cache_;
- static std::mutex* cache_lock_;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_ELF_H
diff --git a/libunwindstack/include/unwindstack/ElfInterface.h b/libunwindstack/include/unwindstack/ElfInterface.h
deleted file mode 100644
index 5df7ddf..0000000
--- a/libunwindstack/include/unwindstack/ElfInterface.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_ELF_INTERFACE_H
-#define _LIBUNWINDSTACK_ELF_INTERFACE_H
-
-#include <elf.h>
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-#include <unwindstack/DwarfSection.h>
-#include <unwindstack/Error.h>
-
-namespace unwindstack {
-
-// Forward declarations.
-class Memory;
-class Regs;
-class Symbols;
-
-struct LoadInfo {
- uint64_t offset;
- uint64_t table_offset;
- size_t table_size;
-};
-
-enum : uint8_t {
- SONAME_UNKNOWN = 0,
- SONAME_VALID,
- SONAME_INVALID,
-};
-
-class ElfInterface {
- public:
- ElfInterface(Memory* memory) : memory_(memory) {}
- virtual ~ElfInterface();
-
- virtual bool Init(int64_t* load_bias) = 0;
-
- virtual void InitHeaders() = 0;
-
- virtual std::string GetSoname() = 0;
-
- virtual bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* offset) = 0;
-
- virtual bool GetGlobalVariable(const std::string& name, uint64_t* memory_address) = 0;
-
- virtual std::string GetBuildID() = 0;
-
- virtual bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished,
- bool* is_signal_frame);
-
- virtual bool IsValidPc(uint64_t pc);
-
- Memory* CreateGnuDebugdataMemory();
-
- Memory* memory() { return memory_; }
-
- const std::unordered_map<uint64_t, LoadInfo>& pt_loads() { return pt_loads_; }
-
- void SetGnuDebugdataInterface(ElfInterface* interface) { gnu_debugdata_interface_ = interface; }
-
- uint64_t dynamic_offset() { return dynamic_offset_; }
- uint64_t dynamic_vaddr_start() { return dynamic_vaddr_start_; }
- uint64_t dynamic_vaddr_end() { return dynamic_vaddr_end_; }
- uint64_t data_offset() { return data_offset_; }
- uint64_t data_vaddr_start() { return data_vaddr_start_; }
- uint64_t data_vaddr_end() { return data_vaddr_end_; }
- uint64_t eh_frame_hdr_offset() { return eh_frame_hdr_offset_; }
- int64_t eh_frame_hdr_section_bias() { return eh_frame_hdr_section_bias_; }
- uint64_t eh_frame_hdr_size() { return eh_frame_hdr_size_; }
- uint64_t eh_frame_offset() { return eh_frame_offset_; }
- int64_t eh_frame_section_bias() { return eh_frame_section_bias_; }
- uint64_t eh_frame_size() { return eh_frame_size_; }
- uint64_t debug_frame_offset() { return debug_frame_offset_; }
- int64_t debug_frame_section_bias() { return debug_frame_section_bias_; }
- uint64_t debug_frame_size() { return debug_frame_size_; }
- uint64_t gnu_debugdata_offset() { return gnu_debugdata_offset_; }
- uint64_t gnu_debugdata_size() { return gnu_debugdata_size_; }
- uint64_t gnu_build_id_offset() { return gnu_build_id_offset_; }
- uint64_t gnu_build_id_size() { return gnu_build_id_size_; }
-
- DwarfSection* eh_frame() { return eh_frame_.get(); }
- DwarfSection* debug_frame() { return debug_frame_.get(); }
-
- const ErrorData& last_error() { return last_error_; }
- ErrorCode LastErrorCode() { return last_error_.code; }
- uint64_t LastErrorAddress() { return last_error_.address; }
-
- template <typename EhdrType, typename PhdrType>
- static int64_t GetLoadBias(Memory* memory);
-
- template <typename EhdrType, typename ShdrType, typename NhdrType>
- static std::string ReadBuildIDFromMemory(Memory* memory);
-
- protected:
- template <typename AddressType>
- void InitHeadersWithTemplate();
-
- template <typename EhdrType, typename PhdrType, typename ShdrType>
- bool ReadAllHeaders(int64_t* load_bias);
-
- template <typename EhdrType, typename PhdrType>
- void ReadProgramHeaders(const EhdrType& ehdr, int64_t* load_bias);
-
- template <typename EhdrType, typename ShdrType>
- void ReadSectionHeaders(const EhdrType& ehdr);
-
- template <typename DynType>
- std::string GetSonameWithTemplate();
-
- template <typename SymType>
- bool GetFunctionNameWithTemplate(uint64_t addr, std::string* name, uint64_t* func_offset);
-
- template <typename SymType>
- bool GetGlobalVariableWithTemplate(const std::string& name, uint64_t* memory_address);
-
- virtual void HandleUnknownType(uint32_t, uint64_t, uint64_t) {}
-
- template <typename EhdrType>
- static void GetMaxSizeWithTemplate(Memory* memory, uint64_t* size);
-
- template <typename NhdrType>
- std::string ReadBuildID();
-
- Memory* memory_;
- std::unordered_map<uint64_t, LoadInfo> pt_loads_;
-
- // Stored elf data.
- uint64_t dynamic_offset_ = 0;
- uint64_t dynamic_vaddr_start_ = 0;
- uint64_t dynamic_vaddr_end_ = 0;
-
- uint64_t data_offset_ = 0;
- uint64_t data_vaddr_start_ = 0;
- uint64_t data_vaddr_end_ = 0;
-
- uint64_t eh_frame_hdr_offset_ = 0;
- int64_t eh_frame_hdr_section_bias_ = 0;
- uint64_t eh_frame_hdr_size_ = 0;
-
- uint64_t eh_frame_offset_ = 0;
- int64_t eh_frame_section_bias_ = 0;
- uint64_t eh_frame_size_ = 0;
-
- uint64_t debug_frame_offset_ = 0;
- int64_t debug_frame_section_bias_ = 0;
- uint64_t debug_frame_size_ = 0;
-
- uint64_t gnu_debugdata_offset_ = 0;
- uint64_t gnu_debugdata_size_ = 0;
-
- uint64_t gnu_build_id_offset_ = 0;
- uint64_t gnu_build_id_size_ = 0;
-
- uint8_t soname_type_ = SONAME_UNKNOWN;
- std::string soname_;
-
- ErrorData last_error_{ERROR_NONE, 0};
-
- std::unique_ptr<DwarfSection> eh_frame_;
- std::unique_ptr<DwarfSection> debug_frame_;
- // The Elf object owns the gnu_debugdata interface object.
- ElfInterface* gnu_debugdata_interface_ = nullptr;
-
- std::vector<Symbols*> symbols_;
- std::vector<std::pair<uint64_t, uint64_t>> strtabs_;
-};
-
-class ElfInterface32 : public ElfInterface {
- public:
- ElfInterface32(Memory* memory) : ElfInterface(memory) {}
- virtual ~ElfInterface32() = default;
-
- bool Init(int64_t* load_bias) override {
- return ElfInterface::ReadAllHeaders<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(load_bias);
- }
-
- void InitHeaders() override { ElfInterface::InitHeadersWithTemplate<uint32_t>(); }
-
- std::string GetSoname() override { return ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(); }
-
- bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) override {
- return ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(addr, name, func_offset);
- }
-
- bool GetGlobalVariable(const std::string& name, uint64_t* memory_address) override {
- return ElfInterface::GetGlobalVariableWithTemplate<Elf32_Sym>(name, memory_address);
- }
-
- std::string GetBuildID() override { return ElfInterface::ReadBuildID<Elf32_Nhdr>(); }
-
- static void GetMaxSize(Memory* memory, uint64_t* size) {
- GetMaxSizeWithTemplate<Elf32_Ehdr>(memory, size);
- }
-};
-
-class ElfInterface64 : public ElfInterface {
- public:
- ElfInterface64(Memory* memory) : ElfInterface(memory) {}
- virtual ~ElfInterface64() = default;
-
- bool Init(int64_t* load_bias) override {
- return ElfInterface::ReadAllHeaders<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(load_bias);
- }
-
- void InitHeaders() override { ElfInterface::InitHeadersWithTemplate<uint64_t>(); }
-
- std::string GetSoname() override { return ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(); }
-
- bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) override {
- return ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(addr, name, func_offset);
- }
-
- bool GetGlobalVariable(const std::string& name, uint64_t* memory_address) override {
- return ElfInterface::GetGlobalVariableWithTemplate<Elf64_Sym>(name, memory_address);
- }
-
- std::string GetBuildID() override { return ElfInterface::ReadBuildID<Elf64_Nhdr>(); }
-
- static void GetMaxSize(Memory* memory, uint64_t* size) {
- GetMaxSizeWithTemplate<Elf64_Ehdr>(memory, size);
- }
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_ELF_INTERFACE_H
diff --git a/libunwindstack/include/unwindstack/Error.h b/libunwindstack/include/unwindstack/Error.h
deleted file mode 100644
index 0be4572..0000000
--- a/libunwindstack/include/unwindstack/Error.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#ifndef _LIBUNWINDSTACK_ERROR_H
-#define _LIBUNWINDSTACK_ERROR_H
-
-#include <stdint.h>
-
-namespace unwindstack {
-
-// A bit map of warnings, multiple warnings can be set at the same time.
-enum WarningCode : uint64_t {
- WARNING_NONE = 0,
- WARNING_DEX_PC_NOT_IN_MAP = 0x1, // A dex pc was found, but it doesn't exist
- // in any valid map.
-};
-
-enum ErrorCode : uint8_t {
- ERROR_NONE, // No error.
- ERROR_MEMORY_INVALID, // Memory read failed.
- ERROR_UNWIND_INFO, // Unable to use unwind information to unwind.
- ERROR_UNSUPPORTED, // Encountered unsupported feature.
- ERROR_INVALID_MAP, // Unwind in an invalid map.
- ERROR_MAX_FRAMES_EXCEEDED, // The number of frames exceed the total allowed.
- ERROR_REPEATED_FRAME, // The last frame has the same pc/sp as the next.
- ERROR_INVALID_ELF, // Unwind in an invalid elf.
-};
-
-static inline const char* GetErrorCodeString(ErrorCode error) {
- switch (error) {
- case ERROR_NONE:
- return "None";
- case ERROR_MEMORY_INVALID:
- return "Memory Invalid";
- case ERROR_UNWIND_INFO:
- return "Unwind Info";
- case ERROR_UNSUPPORTED:
- return "Unsupported";
- case ERROR_INVALID_MAP:
- return "Invalid Map";
- case ERROR_MAX_FRAMES_EXCEEDED:
- return "Maximum Frames Exceeded";
- case ERROR_REPEATED_FRAME:
- return "Repeated Frame";
- case ERROR_INVALID_ELF:
- return "Invalid Elf";
- }
-}
-
-struct ErrorData {
- ErrorCode code;
- uint64_t address; // Only valid when code is ERROR_MEMORY_INVALID.
- // Indicates the failing address.
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_ERROR_H
diff --git a/libunwindstack/include/unwindstack/Global.h b/libunwindstack/include/unwindstack/Global.h
deleted file mode 100644
index b9bb141..0000000
--- a/libunwindstack/include/unwindstack/Global.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#ifndef _LIBUNWINDSTACK_GLOBAL_H
-#define _LIBUNWINDSTACK_GLOBAL_H
-
-#include <stdint.h>
-
-#include <memory>
-#include <mutex>
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/Memory.h>
-
-namespace unwindstack {
-
-// Forward declarations.
-class Maps;
-struct MapInfo;
-
-class Global {
- public:
- explicit Global(std::shared_ptr<Memory>& memory);
- Global(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs);
- virtual ~Global() = default;
-
- void SetArch(ArchEnum arch);
-
- ArchEnum arch() { return arch_; }
-
- protected:
- bool Searchable(const std::string& name);
- void FindAndReadVariable(Maps* maps, const char* variable);
-
- virtual bool ReadVariableData(uint64_t offset) = 0;
-
- virtual void ProcessArch() = 0;
-
- ArchEnum arch_ = ARCH_UNKNOWN;
-
- std::shared_ptr<Memory> memory_;
- std::vector<std::string> search_libs_;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_GLOBAL_H
diff --git a/libunwindstack/include/unwindstack/JitDebug.h b/libunwindstack/include/unwindstack/JitDebug.h
deleted file mode 100644
index 8b7b4b5..0000000
--- a/libunwindstack/include/unwindstack/JitDebug.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef _LIBUNWINDSTACK_JIT_DEBUG_H
-#define _LIBUNWINDSTACK_JIT_DEBUG_H
-
-#include <stdint.h>
-
-#include <memory>
-#include <mutex>
-#include <string>
-#include <vector>
-
-#include <unwindstack/Global.h>
-#include <unwindstack/Memory.h>
-
-namespace unwindstack {
-
-// Forward declarations.
-class Elf;
-class Maps;
-enum ArchEnum : uint8_t;
-
-class JitDebug : public Global {
- public:
- explicit JitDebug(std::shared_ptr<Memory>& memory);
- JitDebug(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs);
- virtual ~JitDebug();
-
- Elf* GetElf(Maps* maps, uint64_t pc);
-
- private:
- void Init(Maps* maps);
-
- uint64_t (JitDebug::*read_descriptor_func_)(uint64_t) = nullptr;
- uint64_t (JitDebug::*read_entry_func_)(uint64_t*, uint64_t*) = nullptr;
-
- uint64_t ReadDescriptor32(uint64_t);
- uint64_t ReadDescriptor64(uint64_t);
-
- uint64_t ReadEntry32Pack(uint64_t* start, uint64_t* size);
- uint64_t ReadEntry32Pad(uint64_t* start, uint64_t* size);
- uint64_t ReadEntry64(uint64_t* start, uint64_t* size);
-
- bool ReadVariableData(uint64_t ptr_offset) override;
-
- void ProcessArch() override;
-
- uint64_t entry_addr_ = 0;
- bool initialized_ = false;
- std::vector<Elf*> elf_list_;
-
- std::mutex lock_;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_JIT_DEBUG_H
diff --git a/libunwindstack/include/unwindstack/LocalUnwinder.h b/libunwindstack/include/unwindstack/LocalUnwinder.h
deleted file mode 100644
index 80bb53e..0000000
--- a/libunwindstack/include/unwindstack/LocalUnwinder.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#ifndef _LIBUNWINDSTACK_LOCAL_UNWINDER_H
-#define _LIBUNWINDSTACK_LOCAL_UNWINDER_H
-
-#include <pthread.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <unwindstack/Error.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
-
-namespace unwindstack {
-
-// Forward declarations.
-class Elf;
-struct MapInfo;
-
-struct LocalFrameData {
- LocalFrameData(MapInfo* map_info, uint64_t pc, uint64_t rel_pc, const std::string& function_name,
- uint64_t function_offset)
- : map_info(map_info),
- pc(pc),
- rel_pc(rel_pc),
- function_name(function_name),
- function_offset(function_offset) {}
-
- MapInfo* map_info;
- uint64_t pc;
- uint64_t rel_pc;
- std::string function_name;
- uint64_t function_offset;
-};
-
-// This is a specialized class that should only be used for doing local unwinds.
-// The Unwind call can be made as multiple times on the same object, and it can
-// be called by multiple threads at the same time.
-// It is designed to be used in debugging circumstances to get a stack trace
-// as fast as possible.
-class LocalUnwinder {
- public:
- LocalUnwinder() = default;
- LocalUnwinder(const std::vector<std::string>& skip_libraries) : skip_libraries_(skip_libraries) {}
- ~LocalUnwinder() = default;
-
- bool Init();
-
- bool Unwind(std::vector<LocalFrameData>* frame_info, size_t max_frames);
-
- bool ShouldSkipLibrary(const std::string& map_name);
-
- MapInfo* GetMapInfo(uint64_t pc);
-
- ErrorCode LastErrorCode() { return last_error_.code; }
- uint64_t LastErrorAddress() { return last_error_.address; }
-
- private:
- pthread_rwlock_t maps_rwlock_;
- std::unique_ptr<LocalUpdatableMaps> maps_ = nullptr;
- std::shared_ptr<Memory> process_memory_;
- std::vector<std::string> skip_libraries_;
- ErrorData last_error_;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_LOCAL_UNWINDER_H
diff --git a/libunwindstack/include/unwindstack/Log.h b/libunwindstack/include/unwindstack/Log.h
deleted file mode 100644
index aa1219c..0000000
--- a/libunwindstack/include/unwindstack/Log.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_LOG_H
-#define _LIBUNWINDSTACK_LOG_H
-
-#include <stdint.h>
-
-namespace unwindstack {
-
-void log_to_stdout(bool enable);
-void log(uint8_t indent, const char* format, ...);
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_LOG_H
diff --git a/libunwindstack/include/unwindstack/MachineArm.h b/libunwindstack/include/unwindstack/MachineArm.h
deleted file mode 100644
index 3f902b1..0000000
--- a/libunwindstack/include/unwindstack/MachineArm.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef _LIBUNWINDSTACK_MACHINE_ARM_H
-#define _LIBUNWINDSTACK_MACHINE_ARM_H
-
-#include <stdint.h>
-
-namespace unwindstack {
-
-enum ArmReg : uint16_t {
- ARM_REG_R0 = 0,
- ARM_REG_R1,
- ARM_REG_R2,
- ARM_REG_R3,
- ARM_REG_R4,
- ARM_REG_R5,
- ARM_REG_R6,
- ARM_REG_R7,
- ARM_REG_R8,
- ARM_REG_R9,
- ARM_REG_R10,
- ARM_REG_R11,
- ARM_REG_R12,
- ARM_REG_R13,
- ARM_REG_R14,
- ARM_REG_R15,
- ARM_REG_LAST,
-
- ARM_REG_SP = ARM_REG_R13,
- ARM_REG_LR = ARM_REG_R14,
- ARM_REG_PC = ARM_REG_R15,
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_MACHINE_ARM_H
diff --git a/libunwindstack/include/unwindstack/MachineArm64.h b/libunwindstack/include/unwindstack/MachineArm64.h
deleted file mode 100644
index 358e3d9..0000000
--- a/libunwindstack/include/unwindstack/MachineArm64.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef _LIBUNWINDSTACK_MACHINE_ARM64_H
-#define _LIBUNWINDSTACK_MACHINE_ARM64_H
-
-#include <stdint.h>
-
-namespace unwindstack {
-
-enum Arm64Reg : uint16_t {
- ARM64_REG_R0 = 0,
- ARM64_REG_R1,
- ARM64_REG_R2,
- ARM64_REG_R3,
- ARM64_REG_R4,
- ARM64_REG_R5,
- ARM64_REG_R6,
- ARM64_REG_R7,
- ARM64_REG_R8,
- ARM64_REG_R9,
- ARM64_REG_R10,
- ARM64_REG_R11,
- ARM64_REG_R12,
- ARM64_REG_R13,
- ARM64_REG_R14,
- ARM64_REG_R15,
- ARM64_REG_R16,
- ARM64_REG_R17,
- ARM64_REG_R18,
- ARM64_REG_R19,
- ARM64_REG_R20,
- ARM64_REG_R21,
- ARM64_REG_R22,
- ARM64_REG_R23,
- ARM64_REG_R24,
- ARM64_REG_R25,
- ARM64_REG_R26,
- ARM64_REG_R27,
- ARM64_REG_R28,
- ARM64_REG_R29,
- ARM64_REG_R30,
- ARM64_REG_R31,
- ARM64_REG_PC,
- ARM64_REG_PSTATE,
- ARM64_REG_LAST,
-
- ARM64_REG_SP = ARM64_REG_R31,
- ARM64_REG_LR = ARM64_REG_R30,
-
- // Pseudo registers. These are not machine registers.
-
- // AARCH64 Return address signed state pseudo-register
- ARM64_PREG_RA_SIGN_STATE = 34,
- ARM64_PREG_FIRST = ARM64_PREG_RA_SIGN_STATE,
- ARM64_PREG_LAST,
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_MACHINE_ARM64_H
diff --git a/libunwindstack/include/unwindstack/MachineMips.h b/libunwindstack/include/unwindstack/MachineMips.h
deleted file mode 100644
index 2dfb1e9..0000000
--- a/libunwindstack/include/unwindstack/MachineMips.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef _LIBUNWINDSTACK_MACHINE_MIPS_H
-#define _LIBUNWINDSTACK_MACHINE_MIPS_H
-
-#include <stdint.h>
-
-namespace unwindstack {
-
-enum MipsReg : uint16_t {
- MIPS_REG_R0 = 0,
- MIPS_REG_R1,
- MIPS_REG_R2,
- MIPS_REG_R3,
- MIPS_REG_R4,
- MIPS_REG_R5,
- MIPS_REG_R6,
- MIPS_REG_R7,
- MIPS_REG_R8,
- MIPS_REG_R9,
- MIPS_REG_R10,
- MIPS_REG_R11,
- MIPS_REG_R12,
- MIPS_REG_R13,
- MIPS_REG_R14,
- MIPS_REG_R15,
- MIPS_REG_R16,
- MIPS_REG_R17,
- MIPS_REG_R18,
- MIPS_REG_R19,
- MIPS_REG_R20,
- MIPS_REG_R21,
- MIPS_REG_R22,
- MIPS_REG_R23,
- MIPS_REG_R24,
- MIPS_REG_R25,
- MIPS_REG_R26,
- MIPS_REG_R27,
- MIPS_REG_R28,
- MIPS_REG_R29,
- MIPS_REG_R30,
- MIPS_REG_R31,
- MIPS_REG_PC,
- MIPS_REG_LAST,
-
- MIPS_REG_SP = MIPS_REG_R29,
- MIPS_REG_RA = MIPS_REG_R31,
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_MACHINE_MIPS_H
\ No newline at end of file
diff --git a/libunwindstack/include/unwindstack/MachineMips64.h b/libunwindstack/include/unwindstack/MachineMips64.h
deleted file mode 100644
index 34addf2..0000000
--- a/libunwindstack/include/unwindstack/MachineMips64.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef _LIBUNWINDSTACK_MACHINE_MIPS64_H
-#define _LIBUNWINDSTACK_MACHINE_MIPS64_H
-
-#include <stdint.h>
-
-namespace unwindstack {
-
-enum Mips64Reg : uint16_t {
- MIPS64_REG_R0 = 0,
- MIPS64_REG_R1,
- MIPS64_REG_R2,
- MIPS64_REG_R3,
- MIPS64_REG_R4,
- MIPS64_REG_R5,
- MIPS64_REG_R6,
- MIPS64_REG_R7,
- MIPS64_REG_R8,
- MIPS64_REG_R9,
- MIPS64_REG_R10,
- MIPS64_REG_R11,
- MIPS64_REG_R12,
- MIPS64_REG_R13,
- MIPS64_REG_R14,
- MIPS64_REG_R15,
- MIPS64_REG_R16,
- MIPS64_REG_R17,
- MIPS64_REG_R18,
- MIPS64_REG_R19,
- MIPS64_REG_R20,
- MIPS64_REG_R21,
- MIPS64_REG_R22,
- MIPS64_REG_R23,
- MIPS64_REG_R24,
- MIPS64_REG_R25,
- MIPS64_REG_R26,
- MIPS64_REG_R27,
- MIPS64_REG_R28,
- MIPS64_REG_R29,
- MIPS64_REG_R30,
- MIPS64_REG_R31,
- MIPS64_REG_PC,
- MIPS64_REG_LAST,
-
- MIPS64_REG_SP = MIPS64_REG_R29,
- MIPS64_REG_RA = MIPS64_REG_R31,
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_MACHINE_MIPS64_H
\ No newline at end of file
diff --git a/libunwindstack/include/unwindstack/MachineX86.h b/libunwindstack/include/unwindstack/MachineX86.h
deleted file mode 100644
index 02adb98..0000000
--- a/libunwindstack/include/unwindstack/MachineX86.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef _LIBUNWINDSTACK_MACHINE_X86_H
-#define _LIBUNWINDSTACK_MACHINE_X86_H
-
-#include <stdint.h>
-
-namespace unwindstack {
-
-// Matches the numbers for the registers as generated by compilers.
-// If this is changed, then unwinding will fail.
-enum X86Reg : uint16_t {
- X86_REG_EAX = 0,
- X86_REG_ECX = 1,
- X86_REG_EDX = 2,
- X86_REG_EBX = 3,
- X86_REG_ESP = 4,
- X86_REG_EBP = 5,
- X86_REG_ESI = 6,
- X86_REG_EDI = 7,
- X86_REG_EIP = 8,
- X86_REG_EFL = 9,
- X86_REG_CS = 10,
- X86_REG_SS = 11,
- X86_REG_DS = 12,
- X86_REG_ES = 13,
- X86_REG_FS = 14,
- X86_REG_GS = 15,
- X86_REG_LAST,
-
- X86_REG_SP = X86_REG_ESP,
- X86_REG_PC = X86_REG_EIP,
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_MACHINE_X86_H
diff --git a/libunwindstack/include/unwindstack/MachineX86_64.h b/libunwindstack/include/unwindstack/MachineX86_64.h
deleted file mode 100644
index af33fea..0000000
--- a/libunwindstack/include/unwindstack/MachineX86_64.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef _LIBUNWINDSTACK_MACHINE_X86_64_H
-#define _LIBUNWINDSTACK_MACHINE_X86_64_H
-
-#include <stdint.h>
-
-namespace unwindstack {
-
-// Matches the numbers for the registers as generated by compilers.
-// If this is changed, then unwinding will fail.
-enum X86_64Reg : uint16_t {
- X86_64_REG_RAX = 0,
- X86_64_REG_RDX = 1,
- X86_64_REG_RCX = 2,
- X86_64_REG_RBX = 3,
- X86_64_REG_RSI = 4,
- X86_64_REG_RDI = 5,
- X86_64_REG_RBP = 6,
- X86_64_REG_RSP = 7,
- X86_64_REG_R8 = 8,
- X86_64_REG_R9 = 9,
- X86_64_REG_R10 = 10,
- X86_64_REG_R11 = 11,
- X86_64_REG_R12 = 12,
- X86_64_REG_R13 = 13,
- X86_64_REG_R14 = 14,
- X86_64_REG_R15 = 15,
- X86_64_REG_RIP = 16,
- X86_64_REG_LAST,
-
- X86_64_REG_SP = X86_64_REG_RSP,
- X86_64_REG_PC = X86_64_REG_RIP,
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_MACHINE_X86_64_H
diff --git a/libunwindstack/include/unwindstack/MapInfo.h b/libunwindstack/include/unwindstack/MapInfo.h
deleted file mode 100644
index 052e79f..0000000
--- a/libunwindstack/include/unwindstack/MapInfo.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_MAP_INFO_H
-#define _LIBUNWINDSTACK_MAP_INFO_H
-
-#include <stdint.h>
-
-#include <atomic>
-#include <memory>
-#include <mutex>
-#include <string>
-
-#include <unwindstack/Elf.h>
-
-namespace unwindstack {
-
-class MemoryFileAtOffset;
-
-struct MapInfo {
- MapInfo(MapInfo* prev_map, MapInfo* prev_real_map, uint64_t start, uint64_t end, uint64_t offset,
- uint64_t flags, const char* name)
- : start(start),
- end(end),
- offset(offset),
- flags(flags),
- name(name),
- prev_map(prev_map),
- prev_real_map(prev_real_map),
- load_bias(INT64_MAX),
- build_id(0) {}
- MapInfo(MapInfo* prev_map, MapInfo* prev_real_map, uint64_t start, uint64_t end, uint64_t offset,
- uint64_t flags, const std::string& name)
- : start(start),
- end(end),
- offset(offset),
- flags(flags),
- name(name),
- prev_map(prev_map),
- prev_real_map(prev_real_map),
- load_bias(INT64_MAX),
- build_id(0) {}
- ~MapInfo();
-
- uint64_t start = 0;
- uint64_t end = 0;
- uint64_t offset = 0;
- uint16_t flags = 0;
- std::string name;
- std::shared_ptr<Elf> elf;
- // The offset of the beginning of this mapping to the beginning of the
- // ELF file.
- // elf_offset == offset - elf_start_offset.
- // This value is only non-zero if the offset is non-zero but there is
- // no elf signature found at that offset.
- uint64_t elf_offset = 0;
- // This value is the offset into the file of the map in memory that is the
- // start of the elf. This is not equal to offset when the linker splits
- // shared libraries into a read-only and read-execute map.
- uint64_t elf_start_offset = 0;
-
- MapInfo* prev_map = nullptr;
- // This is the previous map that is not empty with a 0 offset. For
- // example, this set of maps:
- // 1000-2000 r--p 000000 00:00 0 libc.so
- // 2000-3000 ---p 000000 00:00 0 libc.so
- // 3000-4000 r-xp 003000 00:00 0 libc.so
- // The last map's prev_map would point to the 2000-3000 map, while the
- // prev_real_map would point to the 1000-2000 map.
- MapInfo* prev_real_map = nullptr;
-
- std::atomic_int64_t load_bias;
-
- // This is a pointer to a new'd std::string.
- // Using an atomic value means that we don't need to lock and will
- // make it easier to move to a fine grained lock in the future.
- std::atomic_uintptr_t build_id;
-
- // Set to true if the elf file data is coming from memory.
- bool memory_backed_elf = false;
-
- // This function guarantees it will never return nullptr.
- Elf* GetElf(const std::shared_ptr<Memory>& process_memory, ArchEnum expected_arch);
-
- uint64_t GetLoadBias(const std::shared_ptr<Memory>& process_memory);
-
- Memory* CreateMemory(const std::shared_ptr<Memory>& process_memory);
-
- bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset);
-
- // Returns the raw build id read from the elf data.
- std::string GetBuildID();
-
- // Returns the printable version of the build id (hex dump of raw data).
- std::string GetPrintableBuildID();
-
- inline bool IsBlank() { return offset == 0 && flags == 0 && name.empty(); }
-
- private:
- MapInfo(const MapInfo&) = delete;
- void operator=(const MapInfo&) = delete;
-
- Memory* GetFileMemory();
- bool InitFileMemoryFromPreviousReadOnlyMap(MemoryFileAtOffset* memory);
-
- // Protect the creation of the elf object.
- std::mutex mutex_;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_MAP_INFO_H
diff --git a/libunwindstack/include/unwindstack/Maps.h b/libunwindstack/include/unwindstack/Maps.h
deleted file mode 100644
index e53f367..0000000
--- a/libunwindstack/include/unwindstack/Maps.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_MAPS_H
-#define _LIBUNWINDSTACK_MAPS_H
-
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <unwindstack/MapInfo.h>
-
-namespace unwindstack {
-
-// Special flag to indicate a map is in /dev/. However, a map in
-// /dev/ashmem/... does not set this flag.
-static constexpr int MAPS_FLAGS_DEVICE_MAP = 0x8000;
-// Special flag to indicate that this map represents an elf file
-// created by ART for use with the gdb jit debug interface.
-// This should only ever appear in offline maps data.
-static constexpr int MAPS_FLAGS_JIT_SYMFILE_MAP = 0x4000;
-
-class Maps {
- public:
- virtual ~Maps() = default;
-
- Maps() = default;
-
- // Maps are not copyable but movable, because they own pointers to MapInfo
- // objects.
- Maps(const Maps&) = delete;
- Maps& operator=(const Maps&) = delete;
- Maps(Maps&&) = default;
- Maps& operator=(Maps&&) = default;
-
- MapInfo* Find(uint64_t pc);
-
- virtual bool Parse();
-
- virtual const std::string GetMapsFile() const { return ""; }
-
- void Add(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags, const std::string& name,
- uint64_t load_bias);
-
- void Sort();
-
- typedef std::vector<std::unique_ptr<MapInfo>>::iterator iterator;
- iterator begin() { return maps_.begin(); }
- iterator end() { return maps_.end(); }
-
- typedef std::vector<std::unique_ptr<MapInfo>>::const_iterator const_iterator;
- const_iterator begin() const { return maps_.begin(); }
- const_iterator end() const { return maps_.end(); }
-
- size_t Total() { return maps_.size(); }
-
- MapInfo* Get(size_t index) {
- if (index >= maps_.size()) return nullptr;
- return maps_[index].get();
- }
-
- protected:
- std::vector<std::unique_ptr<MapInfo>> maps_;
-};
-
-class RemoteMaps : public Maps {
- public:
- RemoteMaps(pid_t pid) : pid_(pid) {}
- virtual ~RemoteMaps() = default;
-
- virtual const std::string GetMapsFile() const override;
-
- private:
- pid_t pid_;
-};
-
-class LocalMaps : public RemoteMaps {
- public:
- LocalMaps() : RemoteMaps(getpid()) {}
- virtual ~LocalMaps() = default;
-};
-
-class LocalUpdatableMaps : public Maps {
- public:
- LocalUpdatableMaps() : Maps() {}
- virtual ~LocalUpdatableMaps() = default;
-
- bool Reparse();
-
- const std::string GetMapsFile() const override;
-
- protected:
- std::vector<std::unique_ptr<MapInfo>> saved_maps_;
-};
-
-class BufferMaps : public Maps {
- public:
- BufferMaps(const char* buffer) : buffer_(buffer) {}
- virtual ~BufferMaps() = default;
-
- bool Parse() override;
-
- private:
- const char* buffer_;
-};
-
-class FileMaps : public Maps {
- public:
- FileMaps(const std::string& file) : file_(file) {}
- virtual ~FileMaps() = default;
-
- const std::string GetMapsFile() const override { return file_; }
-
- protected:
- const std::string file_;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_MAPS_H
diff --git a/libunwindstack/include/unwindstack/Memory.h b/libunwindstack/include/unwindstack/Memory.h
deleted file mode 100644
index 3d81878..0000000
--- a/libunwindstack/include/unwindstack/Memory.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_MEMORY_H
-#define _LIBUNWINDSTACK_MEMORY_H
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <memory>
-#include <string>
-
-namespace unwindstack {
-
-class Memory {
- public:
- Memory() = default;
- virtual ~Memory() = default;
-
- static std::shared_ptr<Memory> CreateProcessMemory(pid_t pid);
- static std::shared_ptr<Memory> CreateProcessMemoryCached(pid_t pid);
- static std::shared_ptr<Memory> CreateOfflineMemory(const uint8_t* data, uint64_t start,
- uint64_t end);
- static std::unique_ptr<Memory> CreateFileMemory(const std::string& path, uint64_t offset);
-
- virtual bool ReadString(uint64_t addr, std::string* dst, size_t max_read);
-
- virtual void Clear() {}
-
- virtual bool IsLocal() const { return false; }
-
- virtual size_t Read(uint64_t addr, void* dst, size_t size) = 0;
- virtual long ReadTag(uint64_t) { return -1; }
-
- bool ReadFully(uint64_t addr, void* dst, size_t size);
-
- inline bool Read32(uint64_t addr, uint32_t* dst) {
- return ReadFully(addr, dst, sizeof(uint32_t));
- }
-
- inline bool Read64(uint64_t addr, uint64_t* dst) {
- return ReadFully(addr, dst, sizeof(uint64_t));
- }
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_MEMORY_H
diff --git a/libunwindstack/include/unwindstack/Regs.h b/libunwindstack/include/unwindstack/Regs.h
deleted file mode 100644
index 1a2a704..0000000
--- a/libunwindstack/include/unwindstack/Regs.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_REGS_H
-#define _LIBUNWINDSTACK_REGS_H
-
-#include <stdint.h>
-#include <unistd.h>
-
-#include <functional>
-#include <string>
-#include <vector>
-
-#include <unwindstack/Arch.h>
-
-namespace unwindstack {
-
-// Forward declarations.
-class Elf;
-class Memory;
-
-class Regs {
- public:
- enum LocationEnum : uint8_t {
- LOCATION_UNKNOWN = 0,
- LOCATION_REGISTER,
- LOCATION_SP_OFFSET,
- };
-
- struct Location {
- Location(LocationEnum type, int16_t value) : type(type), value(value) {}
-
- LocationEnum type;
- int16_t value;
- };
-
- Regs(uint16_t total_regs, const Location& return_loc)
- : total_regs_(total_regs), return_loc_(return_loc) {}
- virtual ~Regs() = default;
-
- virtual ArchEnum Arch() = 0;
-
- bool Is32Bit() { return ArchIs32Bit(Arch()); }
-
- virtual void* RawData() = 0;
- virtual uint64_t pc() = 0;
- virtual uint64_t sp() = 0;
-
- virtual void set_pc(uint64_t pc) = 0;
- virtual void set_sp(uint64_t sp) = 0;
-
- uint64_t dex_pc() { return dex_pc_; }
- void set_dex_pc(uint64_t dex_pc) { dex_pc_ = dex_pc; }
-
- virtual void ResetPseudoRegisters() {}
- virtual bool SetPseudoRegister(uint16_t, uint64_t) { return false; }
- virtual bool GetPseudoRegister(uint16_t, uint64_t*) { return false; }
-
- virtual bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) = 0;
-
- virtual bool SetPcFromReturnAddress(Memory* process_memory) = 0;
-
- virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) = 0;
-
- uint16_t total_regs() { return total_regs_; }
-
- virtual Regs* Clone() = 0;
-
- static ArchEnum CurrentArch();
- static Regs* RemoteGet(pid_t pid);
- static Regs* CreateFromUcontext(ArchEnum arch, void* ucontext);
- static Regs* CreateFromLocal();
-
- protected:
- uint16_t total_regs_;
- Location return_loc_;
- uint64_t dex_pc_ = 0;
-};
-
-template <typename AddressType>
-class RegsImpl : public Regs {
- public:
- RegsImpl(uint16_t total_regs, Location return_loc)
- : Regs(total_regs, return_loc), regs_(total_regs) {}
- virtual ~RegsImpl() = default;
-
- inline AddressType& operator[](size_t reg) { return regs_[reg]; }
-
- void* RawData() override { return regs_.data(); }
-
- virtual void IterateRegisters(std::function<void(const char*, uint64_t)> fn) override {
- for (size_t i = 0; i < regs_.size(); ++i) {
- fn(std::to_string(i).c_str(), regs_[i]);
- }
- }
-
- protected:
- std::vector<AddressType> regs_;
-};
-
-uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf, ArchEnum arch);
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_REGS_H
diff --git a/libunwindstack/include/unwindstack/RegsArm.h b/libunwindstack/include/unwindstack/RegsArm.h
deleted file mode 100644
index fbb34e7..0000000
--- a/libunwindstack/include/unwindstack/RegsArm.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_REGS_ARM_H
-#define _LIBUNWINDSTACK_REGS_ARM_H
-
-#include <stdint.h>
-
-#include <functional>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/Regs.h>
-
-namespace unwindstack {
-
-// Forward declarations.
-class Memory;
-
-class RegsArm : public RegsImpl<uint32_t> {
- public:
- RegsArm();
- virtual ~RegsArm() = default;
-
- ArchEnum Arch() override final;
-
- bool SetPcFromReturnAddress(Memory* process_memory) override;
-
- bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override;
-
- void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
-
- uint64_t pc() override;
- uint64_t sp() override;
-
- void set_pc(uint64_t pc) override;
- void set_sp(uint64_t sp) override;
-
- Regs* Clone() override final;
-
- static Regs* Read(void* data);
-
- static Regs* CreateFromUcontext(void* ucontext);
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_REGS_ARM_H
diff --git a/libunwindstack/include/unwindstack/RegsArm64.h b/libunwindstack/include/unwindstack/RegsArm64.h
deleted file mode 100644
index bf7ab15..0000000
--- a/libunwindstack/include/unwindstack/RegsArm64.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_REGS_ARM64_H
-#define _LIBUNWINDSTACK_REGS_ARM64_H
-
-#include <stdint.h>
-
-#include <functional>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/MachineArm64.h>
-#include <unwindstack/Regs.h>
-
-namespace unwindstack {
-
-// Forward declarations.
-class Memory;
-
-class RegsArm64 : public RegsImpl<uint64_t> {
- public:
- RegsArm64();
- virtual ~RegsArm64() = default;
-
- ArchEnum Arch() override final;
-
- bool SetPcFromReturnAddress(Memory* process_memory) override;
-
- bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override;
-
- void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
-
- uint64_t pc() override;
- uint64_t sp() override;
-
- void set_pc(uint64_t pc) override;
- void set_sp(uint64_t sp) override;
-
- void ResetPseudoRegisters() override;
-
- bool SetPseudoRegister(uint16_t id, uint64_t value) override;
-
- bool GetPseudoRegister(uint16_t id, uint64_t* value) override;
-
- bool IsRASigned();
-
- void SetPACMask(uint64_t mask);
-
- Regs* Clone() override final;
-
- static Regs* Read(void* data);
-
- static Regs* CreateFromUcontext(void* ucontext);
-
- protected:
- uint64_t pseudo_regs_[Arm64Reg::ARM64_PREG_LAST - Arm64Reg::ARM64_PREG_FIRST];
- uint64_t pac_mask_;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_REGS_ARM64_H
diff --git a/libunwindstack/include/unwindstack/RegsGetLocal.h b/libunwindstack/include/unwindstack/RegsGetLocal.h
deleted file mode 100644
index 300a3ec..0000000
--- a/libunwindstack/include/unwindstack/RegsGetLocal.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _LIBUNWINDSTACK_REGS_GET_LOCAL_H
-#define _LIBUNWINDSTACK_REGS_GET_LOCAL_H
-
-namespace unwindstack {
-
-#if defined(__arm__)
-
-inline __attribute__((__always_inline__)) void AsmGetRegs(void* reg_data) {
- asm volatile(
- ".align 2\n"
- "bx pc\n"
- "nop\n"
- ".code 32\n"
- "stmia %[base], {r0-r12}\n"
- "add %[base], #52\n"
- "mov r1, r13\n"
- "mov r2, r14\n"
- "mov r3, r15\n"
- "stmia %[base], {r1-r3}\n"
- "orr %[base], pc, #1\n"
- "bx %[base]\n"
- : [base] "+r"(reg_data)
- :
- : "memory");
-}
-
-#elif defined(__aarch64__)
-
-inline __attribute__((__always_inline__)) void AsmGetRegs(void* reg_data) {
- asm volatile(
- "1:\n"
- "stp x0, x1, [%[base], #0]\n"
- "stp x2, x3, [%[base], #16]\n"
- "stp x4, x5, [%[base], #32]\n"
- "stp x6, x7, [%[base], #48]\n"
- "stp x8, x9, [%[base], #64]\n"
- "stp x10, x11, [%[base], #80]\n"
- "stp x12, x13, [%[base], #96]\n"
- "stp x14, x15, [%[base], #112]\n"
- "stp x16, x17, [%[base], #128]\n"
- "stp x18, x19, [%[base], #144]\n"
- "stp x20, x21, [%[base], #160]\n"
- "stp x22, x23, [%[base], #176]\n"
- "stp x24, x25, [%[base], #192]\n"
- "stp x26, x27, [%[base], #208]\n"
- "stp x28, x29, [%[base], #224]\n"
- "str x30, [%[base], #240]\n"
- "mov x12, sp\n"
- "adr x13, 1b\n"
- "stp x12, x13, [%[base], #248]\n"
- : [base] "+r"(reg_data)
- :
- : "x12", "x13", "memory");
-}
-
-#elif defined(__i386__) || defined(__x86_64__)
-
-extern "C" void AsmGetRegs(void* regs);
-
-#endif
-
-inline __attribute__((__always_inline__)) void RegsGetLocal(Regs* regs) {
- AsmGetRegs(regs->RawData());
-}
-
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_REGS_GET_LOCAL_H
diff --git a/libunwindstack/include/unwindstack/RegsMips.h b/libunwindstack/include/unwindstack/RegsMips.h
deleted file mode 100644
index dc09b83..0000000
--- a/libunwindstack/include/unwindstack/RegsMips.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef _LIBUNWINDSTACK_REGS_MIPS_H
-#define _LIBUNWINDSTACK_REGS_MIPS_H
-
-#include <stdint.h>
-
-#include <functional>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/Regs.h>
-
-namespace unwindstack {
-
-// Forward declarations.
-class Memory;
-
-class RegsMips : public RegsImpl<uint32_t> {
- public:
- RegsMips();
- virtual ~RegsMips() = default;
-
- ArchEnum Arch() override final;
-
- bool SetPcFromReturnAddress(Memory* process_memory) override;
-
- bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override;
-
- void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
-
- uint64_t pc() override;
- uint64_t sp() override;
-
- void set_pc(uint64_t pc) override;
- void set_sp(uint64_t sp) override;
-
- Regs* Clone() override final;
-
- static Regs* Read(void* data);
-
- static Regs* CreateFromUcontext(void* ucontext);
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_REGS_MIPS_H
diff --git a/libunwindstack/include/unwindstack/RegsMips64.h b/libunwindstack/include/unwindstack/RegsMips64.h
deleted file mode 100644
index 64a80dc..0000000
--- a/libunwindstack/include/unwindstack/RegsMips64.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef _LIBUNWINDSTACK_REGS_MIPS64_H
-#define _LIBUNWINDSTACK_REGS_MIPS64_H
-
-#include <stdint.h>
-
-#include <functional>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/Regs.h>
-
-namespace unwindstack {
-
-// Forward declarations.
-class Memory;
-
-class RegsMips64 : public RegsImpl<uint64_t> {
- public:
- RegsMips64();
- virtual ~RegsMips64() = default;
-
- ArchEnum Arch() override final;
-
- bool SetPcFromReturnAddress(Memory* process_memory) override;
-
- bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override;
-
- void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
-
- uint64_t pc() override;
- uint64_t sp() override;
-
- void set_pc(uint64_t pc) override;
- void set_sp(uint64_t sp) override;
-
- Regs* Clone() override final;
-
- static Regs* Read(void* data);
-
- static Regs* CreateFromUcontext(void* ucontext);
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_REGS_MIPS64_H
diff --git a/libunwindstack/include/unwindstack/RegsX86.h b/libunwindstack/include/unwindstack/RegsX86.h
deleted file mode 100644
index cfbdda6..0000000
--- a/libunwindstack/include/unwindstack/RegsX86.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_REGS_X86_H
-#define _LIBUNWINDSTACK_REGS_X86_H
-
-#include <stdint.h>
-
-#include <functional>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/Regs.h>
-
-namespace unwindstack {
-
-// Forward declarations.
-class Memory;
-struct x86_ucontext_t;
-
-class RegsX86 : public RegsImpl<uint32_t> {
- public:
- RegsX86();
- virtual ~RegsX86() = default;
-
- ArchEnum Arch() override final;
-
- bool SetPcFromReturnAddress(Memory* process_memory) override;
-
- bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override;
-
- void SetFromUcontext(x86_ucontext_t* ucontext);
-
- void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
-
- uint64_t pc() override;
- uint64_t sp() override;
-
- void set_pc(uint64_t pc) override;
- void set_sp(uint64_t sp) override;
-
- Regs* Clone() override final;
-
- static Regs* Read(void* data);
-
- static Regs* CreateFromUcontext(void* ucontext);
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_REGS_X86_H
diff --git a/libunwindstack/include/unwindstack/RegsX86_64.h b/libunwindstack/include/unwindstack/RegsX86_64.h
deleted file mode 100644
index a11aef0..0000000
--- a/libunwindstack/include/unwindstack/RegsX86_64.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_REGS_X86_64_H
-#define _LIBUNWINDSTACK_REGS_X86_64_H
-
-#include <stdint.h>
-
-#include <functional>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/Regs.h>
-
-namespace unwindstack {
-
-// Forward declarations.
-class Memory;
-struct x86_64_ucontext_t;
-
-class RegsX86_64 : public RegsImpl<uint64_t> {
- public:
- RegsX86_64();
- virtual ~RegsX86_64() = default;
-
- ArchEnum Arch() override final;
-
- bool SetPcFromReturnAddress(Memory* process_memory) override;
-
- bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override;
-
- void SetFromUcontext(x86_64_ucontext_t* ucontext);
-
- void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
-
- uint64_t pc() override;
- uint64_t sp() override;
-
- void set_pc(uint64_t pc) override;
- void set_sp(uint64_t sp) override;
-
- Regs* Clone() override final;
-
- static Regs* Read(void* data);
-
- static Regs* CreateFromUcontext(void* ucontext);
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_REGS_X86_64_H
diff --git a/libunwindstack/include/unwindstack/UcontextArm.h b/libunwindstack/include/unwindstack/UcontextArm.h
deleted file mode 100644
index 7d1ec3b..0000000
--- a/libunwindstack/include/unwindstack/UcontextArm.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _LIBUNWINDSTACK_UCONTEXT_ARM_H
-#define _LIBUNWINDSTACK_UCONTEXT_ARM_H
-
-#include <stdint.h>
-
-#include <unwindstack/MachineArm.h>
-
-namespace unwindstack {
-
-struct arm_stack_t {
- uint32_t ss_sp; // void __user*
- int32_t ss_flags; // int
- uint32_t ss_size; // size_t
-};
-
-struct arm_mcontext_t {
- uint32_t trap_no; // unsigned long
- uint32_t error_code; // unsigned long
- uint32_t oldmask; // unsigned long
- uint32_t regs[ARM_REG_LAST]; // unsigned long
- uint32_t cpsr; // unsigned long
- uint32_t fault_address; // unsigned long
-};
-
-struct arm_ucontext_t {
- uint32_t uc_flags; // unsigned long
- uint32_t uc_link; // struct ucontext*
- arm_stack_t uc_stack;
- arm_mcontext_t uc_mcontext;
- // Nothing else is used, so don't define it.
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_UCONTEXT_ARM_H
diff --git a/libunwindstack/include/unwindstack/UcontextArm64.h b/libunwindstack/include/unwindstack/UcontextArm64.h
deleted file mode 100644
index a68be3b..0000000
--- a/libunwindstack/include/unwindstack/UcontextArm64.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _LIBUNWINDSTACK_UCONTEXT_ARM64_H
-#define _LIBUNWINDSTACK_UCONTEXT_ARM64_H
-
-#include <stdint.h>
-
-#include <unwindstack/MachineArm64.h>
-
-namespace unwindstack {
-
-struct arm64_stack_t {
- uint64_t ss_sp; // void __user*
- int32_t ss_flags; // int
- uint64_t ss_size; // size_t
-};
-
-struct arm64_sigset_t {
- uint64_t sig; // unsigned long
-};
-
-struct arm64_mcontext_t {
- uint64_t fault_address; // __u64
- uint64_t regs[ARM64_REG_LAST]; // __u64
- uint64_t pstate; // __u64
- // Nothing else is used, so don't define it.
-};
-
-struct arm64_ucontext_t {
- uint64_t uc_flags; // unsigned long
- uint64_t uc_link; // struct ucontext*
- arm64_stack_t uc_stack;
- arm64_sigset_t uc_sigmask;
- // The kernel adds extra padding after uc_sigmask to match glibc sigset_t on ARM64.
- char __padding[128 - sizeof(arm64_sigset_t)];
- // The full structure requires 16 byte alignment, but our partial structure
- // doesn't, so force the alignment.
- arm64_mcontext_t uc_mcontext __attribute__((aligned(16)));
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_UCONTEXT_ARM64_H
diff --git a/libunwindstack/include/unwindstack/UcontextMips.h b/libunwindstack/include/unwindstack/UcontextMips.h
deleted file mode 100644
index 02e33b6..0000000
--- a/libunwindstack/include/unwindstack/UcontextMips.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _LIBUNWINDSTACK_UCONTEXT_MIPS_H
-#define _LIBUNWINDSTACK_UCONTEXT_MIPS_H
-
-#include <stdint.h>
-
-#include <unwindstack/MachineMips.h>
-
-namespace unwindstack {
-
-struct mips_stack_t {
- uint32_t ss_sp; // void __user*
- uint32_t ss_size; // size_t
- int32_t ss_flags; // int
-};
-
-struct mips_mcontext_t {
- uint32_t sc_regmask;
- uint32_t sc_status;
- uint64_t sc_pc;
- uint64_t sc_regs[32];
- // Nothing else is used, so don't define it.
-};
-
-struct mips_ucontext_t {
- uint32_t uc_flags; // unsigned long
- uint32_t uc_link; // struct ucontext*
- mips_stack_t uc_stack;
- mips_mcontext_t uc_mcontext;
- // Nothing else is used, so don't define it.
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_UCONTEXT_MIPS_H
diff --git a/libunwindstack/include/unwindstack/UcontextMips64.h b/libunwindstack/include/unwindstack/UcontextMips64.h
deleted file mode 100644
index 5b92a55..0000000
--- a/libunwindstack/include/unwindstack/UcontextMips64.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _LIBUNWINDSTACK_UCONTEXT_MIPS64_H
-#define _LIBUNWINDSTACK_UCONTEXT_MIPS64_H
-
-#include <stdint.h>
-
-#include <unwindstack/MachineMips64.h>
-
-namespace unwindstack {
-
-struct mips64_stack_t {
- uint64_t ss_sp; // void __user*
- uint64_t ss_size; // size_t
- int32_t ss_flags; // int
-};
-
-struct mips64_mcontext_t {
- uint64_t sc_regs[32];
- uint64_t sc_fpregs[32];
- uint64_t sc_mdhi;
- uint64_t sc_hi1;
- uint64_t sc_hi2;
- uint64_t sc_hi3;
- uint64_t sc_mdlo;
- uint64_t sc_lo1;
- uint64_t sc_lo2;
- uint64_t sc_lo3;
- uint64_t sc_pc;
- // Nothing else is used, so don't define it.
-};
-
-struct mips64_ucontext_t {
- uint64_t uc_flags; // unsigned long
- uint64_t uc_link; // struct ucontext*
- mips64_stack_t uc_stack;
- mips64_mcontext_t uc_mcontext;
- // Nothing else is used, so don't define it.
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_UCONTEXT_MIPS64_H
diff --git a/libunwindstack/include/unwindstack/UcontextX86.h b/libunwindstack/include/unwindstack/UcontextX86.h
deleted file mode 100644
index c96ebb7..0000000
--- a/libunwindstack/include/unwindstack/UcontextX86.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _LIBUNWINDSTACK_UCONTEXT_X86_H
-#define _LIBUNWINDSTACK_UCONTEXT_X86_H
-
-#include <stdint.h>
-
-#include <unwindstack/MachineX86.h>
-
-namespace unwindstack {
-
-struct x86_stack_t {
- uint32_t ss_sp; // void __user*
- int32_t ss_flags; // int
- uint32_t ss_size; // size_t
-};
-
-struct x86_mcontext_t {
- uint32_t gs;
- uint32_t fs;
- uint32_t es;
- uint32_t ds;
- uint32_t edi;
- uint32_t esi;
- uint32_t ebp;
- uint32_t esp;
- uint32_t ebx;
- uint32_t edx;
- uint32_t ecx;
- uint32_t eax;
- uint32_t trapno;
- uint32_t err;
- uint32_t eip;
- uint32_t cs;
- uint32_t efl;
- uint32_t uesp;
- uint32_t ss;
- // Only care about the registers, skip everything else.
-};
-
-struct x86_ucontext_t {
- uint32_t uc_flags; // unsigned long
- uint32_t uc_link; // struct ucontext*
- x86_stack_t uc_stack;
- x86_mcontext_t uc_mcontext;
- // Nothing else is used, so don't define it.
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_UCONTEXT_X86_H
diff --git a/libunwindstack/include/unwindstack/UcontextX86_64.h b/libunwindstack/include/unwindstack/UcontextX86_64.h
deleted file mode 100644
index 4e163e5..0000000
--- a/libunwindstack/include/unwindstack/UcontextX86_64.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _LIBUNWINDSTACK_UCONTEXT_X86_64_H
-#define _LIBUNWINDSTACK_UCONTEXT_X86_64_H
-
-#include <stdint.h>
-
-#include <unwindstack/MachineX86_64.h>
-
-namespace unwindstack {
-
-struct x86_64_stack_t {
- uint64_t ss_sp; // void __user*
- int32_t ss_flags; // int
- int32_t pad;
- uint64_t ss_size; // size_t
-};
-
-struct x86_64_mcontext_t {
- uint64_t r8;
- uint64_t r9;
- uint64_t r10;
- uint64_t r11;
- uint64_t r12;
- uint64_t r13;
- uint64_t r14;
- uint64_t r15;
- uint64_t rdi;
- uint64_t rsi;
- uint64_t rbp;
- uint64_t rbx;
- uint64_t rdx;
- uint64_t rax;
- uint64_t rcx;
- uint64_t rsp;
- uint64_t rip;
- uint64_t efl;
- uint64_t csgsfs;
- uint64_t err;
- uint64_t trapno;
- uint64_t oldmask;
- uint64_t cr2;
- // Only care about the registers, skip everything else.
-};
-
-struct x86_64_ucontext_t {
- uint64_t uc_flags; // unsigned long
- uint64_t uc_link; // struct ucontext*
- x86_64_stack_t uc_stack;
- x86_64_mcontext_t uc_mcontext;
- // Nothing else is used, so don't define it.
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_UCONTEXT_X86_64_H
diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h
deleted file mode 100644
index b274c4c..0000000
--- a/libunwindstack/include/unwindstack/Unwinder.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef _LIBUNWINDSTACK_UNWINDER_H
-#define _LIBUNWINDSTACK_UNWINDER_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <unwindstack/Arch.h>
-#include <unwindstack/DexFiles.h>
-#include <unwindstack/Error.h>
-#include <unwindstack/JitDebug.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/Regs.h>
-
-namespace unwindstack {
-
-// Forward declarations.
-class Elf;
-
-struct FrameData {
- size_t num;
-
- uint64_t rel_pc;
- uint64_t pc;
- uint64_t sp;
-
- std::string function_name;
- uint64_t function_offset = 0;
-
- std::string map_name;
- // The offset from the first map representing the frame. When there are
- // two maps (read-only and read-execute) this will be the offset from
- // the read-only map. When there is only one map, this will be the
- // same as the actual offset of the map and match map_exact_offset.
- uint64_t map_elf_start_offset = 0;
- // The actual offset from the map where the pc lies.
- uint64_t map_exact_offset = 0;
- uint64_t map_start = 0;
- uint64_t map_end = 0;
- uint64_t map_load_bias = 0;
- int map_flags = 0;
-};
-
-class Unwinder {
- public:
- Unwinder(size_t max_frames, Maps* maps, Regs* regs, std::shared_ptr<Memory> process_memory)
- : max_frames_(max_frames),
- maps_(maps),
- regs_(regs),
- process_memory_(process_memory),
- arch_(regs->Arch()) {
- frames_.reserve(max_frames);
- }
- Unwinder(size_t max_frames, Maps* maps, std::shared_ptr<Memory> process_memory)
- : max_frames_(max_frames), maps_(maps), process_memory_(process_memory) {
- frames_.reserve(max_frames);
- }
-
- virtual ~Unwinder() = default;
-
- virtual void Unwind(const std::vector<std::string>* initial_map_names_to_skip = nullptr,
- const std::vector<std::string>* map_suffixes_to_ignore = nullptr);
-
- size_t NumFrames() const { return frames_.size(); }
-
- const std::vector<FrameData>& frames() { return frames_; }
-
- std::vector<FrameData> ConsumeFrames() {
- std::vector<FrameData> frames = std::move(frames_);
- frames_.clear();
- return frames;
- }
-
- std::string FormatFrame(size_t frame_num) const;
- std::string FormatFrame(const FrameData& frame) const;
-
- void SetArch(ArchEnum arch) { arch_ = arch; };
-
- void SetJitDebug(JitDebug* jit_debug);
-
- void SetRegs(Regs* regs) {
- regs_ = regs;
- arch_ = regs_ != nullptr ? regs->Arch() : ARCH_UNKNOWN;
- }
- Maps* GetMaps() { return maps_; }
- std::shared_ptr<Memory>& GetProcessMemory() { return process_memory_; }
-
- // Disabling the resolving of names results in the function name being
- // set to an empty string and the function offset being set to zero.
- void SetResolveNames(bool resolve) { resolve_names_ = resolve; }
-
- // Enable/disable soname printing the soname for a map name if the elf is
- // embedded in a file. This is enabled by default.
- // NOTE: This does nothing unless resolving names is enabled.
- void SetEmbeddedSoname(bool embedded_soname) { embedded_soname_ = embedded_soname; }
-
- void SetDisplayBuildID(bool display_build_id) { display_build_id_ = display_build_id; }
-
- void SetDexFiles(DexFiles* dex_files);
-
- bool elf_from_memory_not_file() { return elf_from_memory_not_file_; }
-
- ErrorCode LastErrorCode() { return last_error_.code; }
- const char* LastErrorCodeString() { return GetErrorCodeString(last_error_.code); }
- uint64_t LastErrorAddress() { return last_error_.address; }
- uint64_t warnings() { return warnings_; }
-
- // Builds a frame for symbolization using the maps from this unwinder. The
- // constructed frame contains just enough information to be used to symbolize
- // frames collected by frame-pointer unwinding that's done outside of
- // libunwindstack. This is used by tombstoned to symbolize frame pointer-based
- // stack traces that are collected by tools such as GWP-ASan and MTE.
- static FrameData BuildFrameFromPcOnly(uint64_t pc, ArchEnum arch, Maps* maps, JitDebug* jit_debug,
- std::shared_ptr<Memory> process_memory, bool resolve_names);
- FrameData BuildFrameFromPcOnly(uint64_t pc);
-
- protected:
- Unwinder(size_t max_frames) : max_frames_(max_frames) { frames_.reserve(max_frames); }
- Unwinder(size_t max_frames, ArchEnum arch) : max_frames_(max_frames), arch_(arch) {
- frames_.reserve(max_frames);
- }
-
- void ClearErrors() {
- warnings_ = WARNING_NONE;
- last_error_.code = ERROR_NONE;
- last_error_.address = 0;
- }
-
- void FillInDexFrame();
- FrameData* FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, uint64_t pc_adjustment);
-
- size_t max_frames_;
- Maps* maps_;
- Regs* regs_;
- std::vector<FrameData> frames_;
- std::shared_ptr<Memory> process_memory_;
- JitDebug* jit_debug_ = nullptr;
- DexFiles* dex_files_ = nullptr;
- bool resolve_names_ = true;
- bool embedded_soname_ = true;
- bool display_build_id_ = false;
- // True if at least one elf file is coming from memory and not the related
- // file. This is only true if there is an actual file backing up the elf.
- bool elf_from_memory_not_file_ = false;
- ErrorData last_error_;
- uint64_t warnings_;
- ArchEnum arch_ = ARCH_UNKNOWN;
-};
-
-class UnwinderFromPid : public Unwinder {
- public:
- UnwinderFromPid(size_t max_frames, pid_t pid) : Unwinder(max_frames), pid_(pid) {}
- UnwinderFromPid(size_t max_frames, pid_t pid, ArchEnum arch)
- : Unwinder(max_frames, arch), pid_(pid) {}
- virtual ~UnwinderFromPid() = default;
-
- bool Init();
-
- void Unwind(const std::vector<std::string>* initial_map_names_to_skip = nullptr,
- const std::vector<std::string>* map_suffixes_to_ignore = nullptr) override;
-
- private:
- pid_t pid_;
- std::unique_ptr<Maps> maps_ptr_;
- std::unique_ptr<JitDebug> jit_debug_ptr_;
- std::unique_ptr<DexFiles> dex_files_ptr_;
- bool initted_ = false;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_UNWINDER_H
diff --git a/libunwindstack/include/unwindstack/UserArm.h b/libunwindstack/include/unwindstack/UserArm.h
deleted file mode 100644
index 7388c03..0000000
--- a/libunwindstack/include/unwindstack/UserArm.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _LIBUNWINDSTACK_USER_ARM_H
-#define _LIBUNWINDSTACK_USER_ARM_H
-
-namespace unwindstack {
-
-struct arm_user_regs {
- uint32_t regs[18];
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_USER_ARM_H
diff --git a/libunwindstack/include/unwindstack/UserArm64.h b/libunwindstack/include/unwindstack/UserArm64.h
deleted file mode 100644
index d74983f..0000000
--- a/libunwindstack/include/unwindstack/UserArm64.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _LIBUNWINDSTACK_USER_ARM64_H
-#define _LIBUNWINDSTACK_USER_ARM64_H
-
-namespace unwindstack {
-
-struct arm64_user_regs {
- uint64_t regs[31];
- uint64_t sp;
- uint64_t pc;
- uint64_t pstate;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_USER_ARM64_H
diff --git a/libunwindstack/include/unwindstack/UserMips.h b/libunwindstack/include/unwindstack/UserMips.h
deleted file mode 100644
index 184be4f..0000000
--- a/libunwindstack/include/unwindstack/UserMips.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _LIBUNWINDSTACK_USER_MIPS_H
-#define _LIBUNWINDSTACK_USER_MIPS_H
-
-namespace unwindstack {
-
-enum Mips32UserReg : uint16_t {
- MIPS32_EF_R0 = 6,
- MIPS32_EF_CP0_EPC = 40,
-};
-
-struct mips_user_regs {
- uint32_t regs[45];
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_USER_MIPS_H
diff --git a/libunwindstack/include/unwindstack/UserMips64.h b/libunwindstack/include/unwindstack/UserMips64.h
deleted file mode 100644
index c46befd..0000000
--- a/libunwindstack/include/unwindstack/UserMips64.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _LIBUNWINDSTACK_USER_MIPS64_H
-#define _LIBUNWINDSTACK_USER_MIPS64_H
-
-namespace unwindstack {
-
-enum Mips64UserReg : uint16_t {
- MIPS64_EF_R0 = 0,
- MIPS64_EF_CP0_EPC = 34,
-};
-
-struct mips64_user_regs {
- uint64_t regs[45];
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_USER_MIPS64_H
diff --git a/libunwindstack/include/unwindstack/UserX86.h b/libunwindstack/include/unwindstack/UserX86.h
deleted file mode 100644
index a040560..0000000
--- a/libunwindstack/include/unwindstack/UserX86.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _LIBUNWINDSTACK_USER_X86_H
-#define _LIBUNWINDSTACK_USER_X86_H
-
-namespace unwindstack {
-
-struct x86_user_regs {
- uint32_t ebx;
- uint32_t ecx;
- uint32_t edx;
- uint32_t esi;
- uint32_t edi;
- uint32_t ebp;
- uint32_t eax;
- uint32_t xds;
- uint32_t xes;
- uint32_t xfs;
- uint32_t xgs;
- uint32_t orig_eax;
- uint32_t eip;
- uint32_t xcs;
- uint32_t eflags;
- uint32_t esp;
- uint32_t xss;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_USER_X86_H
diff --git a/libunwindstack/include/unwindstack/UserX86_64.h b/libunwindstack/include/unwindstack/UserX86_64.h
deleted file mode 100644
index b80d201..0000000
--- a/libunwindstack/include/unwindstack/UserX86_64.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _LIBUNWINDSTACK_USER_X86_64_H
-#define _LIBUNWINDSTACK_USER_X86_64_H
-
-namespace unwindstack {
-
-struct x86_64_user_regs {
- uint64_t r15;
- uint64_t r14;
- uint64_t r13;
- uint64_t r12;
- uint64_t rbp;
- uint64_t rbx;
- uint64_t r11;
- uint64_t r10;
- uint64_t r9;
- uint64_t r8;
- uint64_t rax;
- uint64_t rcx;
- uint64_t rdx;
- uint64_t rsi;
- uint64_t rdi;
- uint64_t orig_rax;
- uint64_t rip;
- uint64_t cs;
- uint64_t eflags;
- uint64_t rsp;
- uint64_t ss;
- uint64_t fs_base;
- uint64_t gs_base;
- uint64_t ds;
- uint64_t es;
- uint64_t fs;
- uint64_t gs;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_USER_X86_64_H
diff --git a/libunwindstack/tests/ArmExidxDecodeTest.cpp b/libunwindstack/tests/ArmExidxDecodeTest.cpp
deleted file mode 100644
index 69a7816..0000000
--- a/libunwindstack/tests/ArmExidxDecodeTest.cpp
+++ /dev/null
@@ -1,1668 +0,0 @@
-/*
- * Copyright (C) 2016 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 <stdint.h>
-
-#include <deque>
-#include <ios>
-#include <memory>
-#include <string>
-
-#include <gtest/gtest.h>
-
-#include <unwindstack/Log.h>
-#include <unwindstack/RegsArm.h>
-
-#include "ArmExidx.h"
-
-#include "LogFake.h"
-#include "MemoryFake.h"
-
-namespace unwindstack {
-
-class ArmExidxDecodeTest : public ::testing::TestWithParam<std::string> {
- protected:
- void Init(Memory* process_memory = nullptr) {
- if (process_memory == nullptr) {
- process_memory = &process_memory_;
- }
-
- regs_arm_.reset(new RegsArm());
- for (size_t i = 0; i < regs_arm_->total_regs(); i++) {
- (*regs_arm_)[i] = 0;
- }
- regs_arm_->set_pc(0);
- regs_arm_->set_sp(0);
-
- exidx_.reset(new ArmExidx(regs_arm_.get(), &elf_memory_, process_memory));
- if (log_ != ARM_LOG_NONE) {
- exidx_->set_log(log_);
- exidx_->set_log_indent(0);
- exidx_->set_log_skip_execution(false);
- }
- data_ = exidx_->data();
- exidx_->set_cfa(0x10000);
- }
-
- void SetUp() override {
- if (GetParam() == "no_logging") {
- log_ = ARM_LOG_NONE;
- } else if (GetParam() == "register_logging") {
- log_ = ARM_LOG_BY_REG;
- } else {
- log_ = ARM_LOG_FULL;
- }
- elf_memory_.Clear();
- process_memory_.Clear();
- ResetExidx();
- }
-
- void ResetExidx() {
- ResetLogs();
- Init();
- }
-
- std::unique_ptr<ArmExidx> exidx_;
- std::unique_ptr<RegsArm> regs_arm_;
- std::deque<uint8_t>* data_;
-
- MemoryFake elf_memory_;
- MemoryFake process_memory_;
- ArmLogType log_;
-};
-
-TEST_P(ArmExidxDecodeTest, vsp_incr) {
- // 00xxxxxx: vsp = vsp + (xxxxxx << 2) + 4
- data_->push_back(0x00);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind vsp = vsp + 4\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ("4 unwind cfa = r13 + 4\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10004U, exidx_->cfa());
-
- ResetExidx();
- data_->clear();
- data_->push_back(0x01);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind vsp = vsp + 8\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ("4 unwind cfa = r13 + 8\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10008U, exidx_->cfa());
-
- ResetExidx();
- data_->clear();
- data_->push_back(0x3f);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind vsp = vsp + 256\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ("4 unwind cfa = r13 + 256\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10100U, exidx_->cfa());
-}
-
-TEST_P(ArmExidxDecodeTest, vsp_decr) {
- // 01xxxxxx: vsp = vsp - (xxxxxx << 2) + 4
- data_->push_back(0x40);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind vsp = vsp - 4\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ("4 unwind cfa = r13 - 4\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0xfffcU, exidx_->cfa());
-
- ResetExidx();
- data_->clear();
- data_->push_back(0x41);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind vsp = vsp - 8\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ("4 unwind cfa = r13 - 8\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0xfff8U, exidx_->cfa());
-
- ResetExidx();
- data_->clear();
- data_->push_back(0x7f);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind vsp = vsp - 256\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ("4 unwind cfa = r13 - 256\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0xff00U, exidx_->cfa());
-}
-
-TEST_P(ArmExidxDecodeTest, refuse_unwind) {
- // 10000000 00000000: Refuse to unwind
- data_->push_back(0x80);
- data_->push_back(0x00);
- ASSERT_FALSE(exidx_->Decode());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Refuse to unwind\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(ARM_STATUS_NO_UNWIND, exidx_->status());
-}
-
-TEST_P(ArmExidxDecodeTest, pop_up_to_12) {
- // 1000iiii iiiiiiii: Pop up to 12 integer registers
- data_->push_back(0x88);
- data_->push_back(0x00);
- process_memory_.SetData32(0x10000, 0x10);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_TRUE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {r15}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ(
- "4 unwind cfa = r13 + 4\n"
- "4 unwind r15 = [cfa - 4]\n",
- GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10004U, exidx_->cfa());
- ASSERT_EQ(0x10U, (*exidx_->regs())[15]);
-
- ResetExidx();
- data_->push_back(0x8f);
- data_->push_back(0xff);
- for (size_t i = 0; i < 12; i++) {
- process_memory_.SetData32(0x10000 + i * 4, i + 0x20);
- }
- exidx_->set_pc_set(false);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_TRUE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15}\n",
- GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ(
- "4 unwind cfa = r13 + 48\n"
- "4 unwind r4 = [cfa - 48]\n"
- "4 unwind r5 = [cfa - 44]\n"
- "4 unwind r6 = [cfa - 40]\n"
- "4 unwind r7 = [cfa - 36]\n"
- "4 unwind r8 = [cfa - 32]\n"
- "4 unwind r9 = [cfa - 28]\n"
- "4 unwind r10 = [cfa - 24]\n"
- "4 unwind r11 = [cfa - 20]\n"
- "4 unwind r12 = [cfa - 16]\n"
- "4 unwind r13 = [cfa - 12]\n"
- "4 unwind r14 = [cfa - 8]\n"
- "4 unwind r15 = [cfa - 4]\n",
- GetFakeLogPrint());
- break;
- }
- // Popping r13 results in a modified cfa.
- ASSERT_EQ(0x29U, exidx_->cfa());
-
- ASSERT_EQ(0x20U, (*exidx_->regs())[4]);
- ASSERT_EQ(0x21U, (*exidx_->regs())[5]);
- ASSERT_EQ(0x22U, (*exidx_->regs())[6]);
- ASSERT_EQ(0x23U, (*exidx_->regs())[7]);
- ASSERT_EQ(0x24U, (*exidx_->regs())[8]);
- ASSERT_EQ(0x25U, (*exidx_->regs())[9]);
- ASSERT_EQ(0x26U, (*exidx_->regs())[10]);
- ASSERT_EQ(0x27U, (*exidx_->regs())[11]);
- ASSERT_EQ(0x28U, (*exidx_->regs())[12]);
- ASSERT_EQ(0x29U, (*exidx_->regs())[13]);
- ASSERT_EQ(0x2aU, (*exidx_->regs())[14]);
- ASSERT_EQ(0x2bU, (*exidx_->regs())[15]);
-
- ResetExidx();
- exidx_->set_cfa(0x10034);
- data_->push_back(0x81);
- data_->push_back(0x28);
- process_memory_.SetData32(0x10034, 0x11);
- process_memory_.SetData32(0x10038, 0x22);
- process_memory_.SetData32(0x1003c, 0x33);
- exidx_->set_pc_set(false);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {r7, r9, r12}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ(
- "4 unwind cfa = r13 + 12\n"
- "4 unwind r7 = [cfa - 12]\n"
- "4 unwind r9 = [cfa - 8]\n"
- "4 unwind r12 = [cfa - 4]\n",
- GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10040U, exidx_->cfa());
- ASSERT_EQ(0x11U, (*exidx_->regs())[7]);
- ASSERT_EQ(0x22U, (*exidx_->regs())[9]);
- ASSERT_EQ(0x33U, (*exidx_->regs())[12]);
-}
-
-TEST_P(ArmExidxDecodeTest, set_vsp_from_register) {
- // 1001nnnn: Set vsp = r[nnnn] (nnnn != 13, 15)
- exidx_->set_cfa(0x100);
- for (size_t i = 0; i < 15; i++) {
- (*regs_arm_)[i] = i + 1;
- }
-
- data_->push_back(0x90);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind vsp = r0\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ("4 unwind cfa = r0\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(1U, exidx_->cfa());
-
- ResetExidx();
- exidx_->set_cfa(0x100);
- for (size_t i = 0; i < 15; i++) {
- (*regs_arm_)[i] = i + 1;
- }
- data_->push_back(0x93);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind vsp = r3\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ("4 unwind cfa = r3\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(4U, exidx_->cfa());
-
- ResetExidx();
- exidx_->set_cfa(0x100);
- for (size_t i = 0; i < 15; i++) {
- (*regs_arm_)[i] = i + 1;
- }
- data_->push_back(0x9e);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind vsp = r14\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ("4 unwind cfa = r14\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(15U, exidx_->cfa());
-}
-
-TEST_P(ArmExidxDecodeTest, reserved_prefix) {
- // 10011101: Reserved as prefix for ARM register to register moves
- data_->push_back(0x9d);
- ASSERT_FALSE(exidx_->Decode());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind [Reserved]\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(ARM_STATUS_RESERVED, exidx_->status());
-
- // 10011111: Reserved as prefix for Intel Wireless MMX register to register moves
- ResetExidx();
- data_->push_back(0x9f);
- ASSERT_FALSE(exidx_->Decode());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind [Reserved]\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(ARM_STATUS_RESERVED, exidx_->status());
-}
-
-TEST_P(ArmExidxDecodeTest, pop_registers) {
- // 10100nnn: Pop r4-r[4+nnn]
- data_->push_back(0xa0);
- process_memory_.SetData32(0x10000, 0x14);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {r4}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ(
- "4 unwind cfa = r13 + 4\n"
- "4 unwind r4 = [cfa - 4]\n",
- GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10004U, exidx_->cfa());
- ASSERT_EQ(0x14U, (*exidx_->regs())[4]);
-
- ResetExidx();
- data_->push_back(0xa3);
- process_memory_.SetData32(0x10000, 0x20);
- process_memory_.SetData32(0x10004, 0x30);
- process_memory_.SetData32(0x10008, 0x40);
- process_memory_.SetData32(0x1000c, 0x50);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {r4-r7}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ(
- "4 unwind cfa = r13 + 16\n"
- "4 unwind r4 = [cfa - 16]\n"
- "4 unwind r5 = [cfa - 12]\n"
- "4 unwind r6 = [cfa - 8]\n"
- "4 unwind r7 = [cfa - 4]\n",
- GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10010U, exidx_->cfa());
- ASSERT_EQ(0x20U, (*exidx_->regs())[4]);
- ASSERT_EQ(0x30U, (*exidx_->regs())[5]);
- ASSERT_EQ(0x40U, (*exidx_->regs())[6]);
- ASSERT_EQ(0x50U, (*exidx_->regs())[7]);
-
- ResetExidx();
- data_->push_back(0xa7);
- process_memory_.SetData32(0x10000, 0x41);
- process_memory_.SetData32(0x10004, 0x51);
- process_memory_.SetData32(0x10008, 0x61);
- process_memory_.SetData32(0x1000c, 0x71);
- process_memory_.SetData32(0x10010, 0x81);
- process_memory_.SetData32(0x10014, 0x91);
- process_memory_.SetData32(0x10018, 0xa1);
- process_memory_.SetData32(0x1001c, 0xb1);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {r4-r11}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ(
- "4 unwind cfa = r13 + 32\n"
- "4 unwind r4 = [cfa - 32]\n"
- "4 unwind r5 = [cfa - 28]\n"
- "4 unwind r6 = [cfa - 24]\n"
- "4 unwind r7 = [cfa - 20]\n"
- "4 unwind r8 = [cfa - 16]\n"
- "4 unwind r9 = [cfa - 12]\n"
- "4 unwind r10 = [cfa - 8]\n"
- "4 unwind r11 = [cfa - 4]\n",
- GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10020U, exidx_->cfa());
- ASSERT_EQ(0x41U, (*exidx_->regs())[4]);
- ASSERT_EQ(0x51U, (*exidx_->regs())[5]);
- ASSERT_EQ(0x61U, (*exidx_->regs())[6]);
- ASSERT_EQ(0x71U, (*exidx_->regs())[7]);
- ASSERT_EQ(0x81U, (*exidx_->regs())[8]);
- ASSERT_EQ(0x91U, (*exidx_->regs())[9]);
- ASSERT_EQ(0xa1U, (*exidx_->regs())[10]);
- ASSERT_EQ(0xb1U, (*exidx_->regs())[11]);
-}
-
-TEST_P(ArmExidxDecodeTest, pop_registers_with_r14) {
- // 10101nnn: Pop r4-r[4+nnn], r14
- data_->push_back(0xa8);
- process_memory_.SetData32(0x10000, 0x12);
- process_memory_.SetData32(0x10004, 0x22);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {r4, r14}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ(
- "4 unwind cfa = r13 + 8\n"
- "4 unwind r4 = [cfa - 8]\n"
- "4 unwind r14 = [cfa - 4]\n",
- GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10008U, exidx_->cfa());
- ASSERT_EQ(0x12U, (*exidx_->regs())[4]);
- ASSERT_EQ(0x22U, (*exidx_->regs())[14]);
-
- ResetExidx();
- data_->push_back(0xab);
- process_memory_.SetData32(0x10000, 0x1);
- process_memory_.SetData32(0x10004, 0x2);
- process_memory_.SetData32(0x10008, 0x3);
- process_memory_.SetData32(0x1000c, 0x4);
- process_memory_.SetData32(0x10010, 0x5);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {r4-r7, r14}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ(
- "4 unwind cfa = r13 + 20\n"
- "4 unwind r4 = [cfa - 20]\n"
- "4 unwind r5 = [cfa - 16]\n"
- "4 unwind r6 = [cfa - 12]\n"
- "4 unwind r7 = [cfa - 8]\n"
- "4 unwind r14 = [cfa - 4]\n",
- GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10014U, exidx_->cfa());
- ASSERT_EQ(0x1U, (*exidx_->regs())[4]);
- ASSERT_EQ(0x2U, (*exidx_->regs())[5]);
- ASSERT_EQ(0x3U, (*exidx_->regs())[6]);
- ASSERT_EQ(0x4U, (*exidx_->regs())[7]);
- ASSERT_EQ(0x5U, (*exidx_->regs())[14]);
-
- ResetExidx();
- data_->push_back(0xaf);
- process_memory_.SetData32(0x10000, 0x1a);
- process_memory_.SetData32(0x10004, 0x2a);
- process_memory_.SetData32(0x10008, 0x3a);
- process_memory_.SetData32(0x1000c, 0x4a);
- process_memory_.SetData32(0x10010, 0x5a);
- process_memory_.SetData32(0x10014, 0x6a);
- process_memory_.SetData32(0x10018, 0x7a);
- process_memory_.SetData32(0x1001c, 0x8a);
- process_memory_.SetData32(0x10020, 0x9a);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {r4-r11, r14}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ(
- "4 unwind cfa = r13 + 36\n"
- "4 unwind r4 = [cfa - 36]\n"
- "4 unwind r5 = [cfa - 32]\n"
- "4 unwind r6 = [cfa - 28]\n"
- "4 unwind r7 = [cfa - 24]\n"
- "4 unwind r8 = [cfa - 20]\n"
- "4 unwind r9 = [cfa - 16]\n"
- "4 unwind r10 = [cfa - 12]\n"
- "4 unwind r11 = [cfa - 8]\n"
- "4 unwind r14 = [cfa - 4]\n",
- GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10024U, exidx_->cfa());
- ASSERT_EQ(0x1aU, (*exidx_->regs())[4]);
- ASSERT_EQ(0x2aU, (*exidx_->regs())[5]);
- ASSERT_EQ(0x3aU, (*exidx_->regs())[6]);
- ASSERT_EQ(0x4aU, (*exidx_->regs())[7]);
- ASSERT_EQ(0x5aU, (*exidx_->regs())[8]);
- ASSERT_EQ(0x6aU, (*exidx_->regs())[9]);
- ASSERT_EQ(0x7aU, (*exidx_->regs())[10]);
- ASSERT_EQ(0x8aU, (*exidx_->regs())[11]);
- ASSERT_EQ(0x9aU, (*exidx_->regs())[14]);
-}
-
-TEST_P(ArmExidxDecodeTest, finish) {
- // 10110000: Finish
- data_->push_back(0xb0);
- ASSERT_FALSE(exidx_->Decode());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind finish\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ("4 unwind cfa = r13\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10000U, exidx_->cfa());
- ASSERT_EQ(ARM_STATUS_FINISH, exidx_->status());
-}
-
-TEST_P(ArmExidxDecodeTest, spare) {
- // 10110001 00000000: Spare
- data_->push_back(0xb1);
- data_->push_back(0x00);
- ASSERT_FALSE(exidx_->Decode());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10000U, exidx_->cfa());
- ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status());
-
- // 10110001 xxxxyyyy: Spare (xxxx != 0000)
- for (size_t x = 1; x < 16; x++) {
- for (size_t y = 0; y < 16; y++) {
- ResetExidx();
- data_->push_back(0xb1);
- data_->push_back((x << 4) | y);
- ASSERT_FALSE(exidx_->Decode()) << "x, y = " << x << ", " << y;
- ASSERT_EQ("", GetFakeLogBuf()) << "x, y = " << x << ", " << y;
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()) << "x, y = " << x << ", " << y;
- break;
- }
- ASSERT_EQ(0x10000U, exidx_->cfa()) << "x, y = " << x << ", " << y;
- ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status());
- }
- }
-
- // 101101nn: Spare
- for (size_t n = 0; n < 4; n++) {
- ResetExidx();
- data_->push_back(0xb4 | n);
- ASSERT_FALSE(exidx_->Decode()) << "n = " << n;
- ASSERT_EQ("", GetFakeLogBuf()) << "n = " << n;
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()) << "n = " << n;
- break;
- }
- ASSERT_EQ(0x10000U, exidx_->cfa()) << "n = " << n;
- ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status());
- }
-
- // 11000111 00000000: Spare
- ResetExidx();
- data_->push_back(0xc7);
- data_->push_back(0x00);
- ASSERT_FALSE(exidx_->Decode());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10000U, exidx_->cfa());
- ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status());
-
- // 11000111 xxxxyyyy: Spare (xxxx != 0000)
- for (size_t x = 1; x < 16; x++) {
- for (size_t y = 0; y < 16; y++) {
- ResetExidx();
- data_->push_back(0xc7);
- data_->push_back(0x10);
- ASSERT_FALSE(exidx_->Decode()) << "x, y = " << x << ", " << y;
- ASSERT_EQ("", GetFakeLogBuf()) << "x, y = " << x << ", " << y;
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()) << "x, y = " << x << ", " << y;
- break;
- }
- ASSERT_EQ(0x10000U, exidx_->cfa()) << "x, y = " << x << ", " << y;
- ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status());
- }
- }
-
- // 11001yyy: Spare (yyy != 000, 001)
- for (size_t y = 2; y < 8; y++) {
- ResetExidx();
- data_->push_back(0xc8 | y);
- ASSERT_FALSE(exidx_->Decode()) << "y = " << y;
- ASSERT_EQ("", GetFakeLogBuf()) << "y = " << y;
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()) << "y = " << y;
- break;
- }
- ASSERT_EQ(0x10000U, exidx_->cfa()) << "y = " << y;
- ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status());
- }
-
- // 11xxxyyy: Spare (xxx != 000, 001, 010)
- for (size_t x = 3; x < 8; x++) {
- for (size_t y = 0; y < 8; y++) {
- ResetExidx();
- data_->push_back(0xc0 | (x << 3) | y);
- ASSERT_FALSE(exidx_->Decode()) << "x, y = " << x << ", " << y;
- ASSERT_EQ("", GetFakeLogBuf()) << "x, y = " << x << ", " << y;
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()) << "x, y = " << x << ", " << y;
- break;
- }
- ASSERT_EQ(0x10000U, exidx_->cfa()) << "x, y = " << x << ", " << y;
- ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status());
- }
- }
-}
-
-TEST_P(ArmExidxDecodeTest, pop_registers_under_mask) {
- // 10110001 0000iiii: Pop integer registers {r0, r1, r2, r3}
- data_->push_back(0xb1);
- data_->push_back(0x01);
- process_memory_.SetData32(0x10000, 0x45);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {r0}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ(
- "4 unwind cfa = r13 + 4\n"
- "4 unwind r0 = [cfa - 4]\n",
- GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10004U, exidx_->cfa());
- ASSERT_EQ(0x45U, (*exidx_->regs())[0]);
-
- ResetExidx();
- data_->push_back(0xb1);
- data_->push_back(0x0a);
- process_memory_.SetData32(0x10000, 0x23);
- process_memory_.SetData32(0x10004, 0x24);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {r1, r3}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ(
- "4 unwind cfa = r13 + 8\n"
- "4 unwind r1 = [cfa - 8]\n"
- "4 unwind r3 = [cfa - 4]\n",
- GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10008U, exidx_->cfa());
- ASSERT_EQ(0x23U, (*exidx_->regs())[1]);
- ASSERT_EQ(0x24U, (*exidx_->regs())[3]);
-
- ResetExidx();
- data_->push_back(0xb1);
- data_->push_back(0x0f);
- process_memory_.SetData32(0x10000, 0x65);
- process_memory_.SetData32(0x10004, 0x54);
- process_memory_.SetData32(0x10008, 0x43);
- process_memory_.SetData32(0x1000c, 0x32);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {r0, r1, r2, r3}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ(
- "4 unwind cfa = r13 + 16\n"
- "4 unwind r0 = [cfa - 16]\n"
- "4 unwind r1 = [cfa - 12]\n"
- "4 unwind r2 = [cfa - 8]\n"
- "4 unwind r3 = [cfa - 4]\n",
- GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10010U, exidx_->cfa());
- ASSERT_EQ(0x65U, (*exidx_->regs())[0]);
- ASSERT_EQ(0x54U, (*exidx_->regs())[1]);
- ASSERT_EQ(0x43U, (*exidx_->regs())[2]);
- ASSERT_EQ(0x32U, (*exidx_->regs())[3]);
-}
-
-TEST_P(ArmExidxDecodeTest, vsp_large_incr) {
- // 10110010 uleb128: vsp = vsp + 0x204 + (uleb128 << 2)
- data_->push_back(0xb2);
- data_->push_back(0x7f);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind vsp = vsp + 1024\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ("4 unwind cfa = r13 + 1024\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10400U, exidx_->cfa());
-
- ResetExidx();
- data_->push_back(0xb2);
- data_->push_back(0xff);
- data_->push_back(0x02);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind vsp = vsp + 2048\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ("4 unwind cfa = r13 + 2048\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10800U, exidx_->cfa());
-
- ResetExidx();
- data_->push_back(0xb2);
- data_->push_back(0xff);
- data_->push_back(0x82);
- data_->push_back(0x30);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind vsp = vsp + 3147776\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ("4 unwind cfa = r13 + 3147776\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x310800U, exidx_->cfa());
-}
-
-TEST_P(ArmExidxDecodeTest, pop_vfp_fstmfdx) {
- // 10110011 sssscccc: Pop VFP double precision registers D[ssss]-D[ssss+cccc] by FSTMFDX
- data_->push_back(0xb3);
- data_->push_back(0x00);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {d0}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x1000cU, exidx_->cfa());
-
- ResetExidx();
- data_->push_back(0xb3);
- data_->push_back(0x48);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {d4-d12}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x1004cU, exidx_->cfa());
-}
-
-TEST_P(ArmExidxDecodeTest, pop_vfp8_fstmfdx) {
- // 10111nnn: Pop VFP double precision registers D[8]-D[8+nnn] by FSTMFDX
- data_->push_back(0xb8);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {d8}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x1000cU, exidx_->cfa());
-
- ResetExidx();
- data_->push_back(0xbb);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {d8-d11}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10024U, exidx_->cfa());
-
- ResetExidx();
- data_->push_back(0xbf);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {d8-d15}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10044U, exidx_->cfa());
-}
-
-TEST_P(ArmExidxDecodeTest, pop_mmx_wr10) {
- // 11000nnn: Intel Wireless MMX pop wR[10]-wR[10+nnn] (nnn != 6, 7)
- data_->push_back(0xc0);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {wR10}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Unsupported wRX register display\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10008U, exidx_->cfa());
-
- ResetExidx();
- data_->push_back(0xc2);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {wR10-wR12}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Unsupported wRX register display\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10018U, exidx_->cfa());
-
- ResetExidx();
- data_->push_back(0xc5);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {wR10-wR15}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Unsupported wRX register display\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10030U, exidx_->cfa());
-}
-
-TEST_P(ArmExidxDecodeTest, pop_mmx_wr) {
- // 11000110 sssscccc: Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc]
- data_->push_back(0xc6);
- data_->push_back(0x00);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {wR0}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Unsupported wRX register display\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10008U, exidx_->cfa());
-
- ResetExidx();
- data_->push_back(0xc6);
- data_->push_back(0x25);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {wR2-wR7}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Unsupported wRX register display\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10030U, exidx_->cfa());
-
- ResetExidx();
- data_->push_back(0xc6);
- data_->push_back(0xff);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {wR15-wR30}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Unsupported wRX register display\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10080U, exidx_->cfa());
-}
-
-TEST_P(ArmExidxDecodeTest, pop_mmx_wcgr) {
- // 11000111 0000iiii: Intel Wireless MMX pop wCGR registes {wCGR0,1,2,3}
- data_->push_back(0xc7);
- data_->push_back(0x01);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {wCGR0}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Unsupported wCGR register display\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10004U, exidx_->cfa());
-
- ResetExidx();
- data_->push_back(0xc7);
- data_->push_back(0x0a);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {wCGR1, wCGR3}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Unsupported wCGR register display\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10008U, exidx_->cfa());
-
- ResetExidx();
- data_->push_back(0xc7);
- data_->push_back(0x0f);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {wCGR0, wCGR1, wCGR2, wCGR3}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Unsupported wCGR register display\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10010U, exidx_->cfa());
-}
-
-TEST_P(ArmExidxDecodeTest, pop_vfp16_vpush) {
- // 11001000 sssscccc: Pop VFP double precision registers d[16+ssss]-D[16+ssss+cccc] by VPUSH
- data_->push_back(0xc8);
- data_->push_back(0x00);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {d16}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10008U, exidx_->cfa());
-
- ResetExidx();
- data_->push_back(0xc8);
- data_->push_back(0x14);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {d17-d21}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10028U, exidx_->cfa());
-
- ResetExidx();
- data_->push_back(0xc8);
- data_->push_back(0xff);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {d31-d46}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10080U, exidx_->cfa());
-}
-
-TEST_P(ArmExidxDecodeTest, pop_vfp_vpush) {
- // 11001001 sssscccc: Pop VFP double precision registers d[ssss]-D[ssss+cccc] by VPUSH
- data_->push_back(0xc9);
- data_->push_back(0x00);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {d0}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10008U, exidx_->cfa());
-
- ResetExidx();
- data_->push_back(0xc9);
- data_->push_back(0x23);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {d2-d5}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10020U, exidx_->cfa());
-
- ResetExidx();
- data_->push_back(0xc9);
- data_->push_back(0xff);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {d15-d30}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10080U, exidx_->cfa());
-}
-
-TEST_P(ArmExidxDecodeTest, pop_vfp8_vpush) {
- // 11010nnn: Pop VFP double precision registers D[8]-D[8+nnn] by VPUSH
- data_->push_back(0xd0);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {d8}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10008U, exidx_->cfa());
-
- ResetExidx();
- data_->push_back(0xd2);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {d8-d10}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10018U, exidx_->cfa());
-
- ResetExidx();
- data_->push_back(0xd7);
- ASSERT_TRUE(exidx_->Decode());
- ASSERT_FALSE(exidx_->pc_set());
- ASSERT_EQ("", GetFakeLogBuf());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ("4 unwind pop {d8-d15}\n", GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10040U, exidx_->cfa());
-}
-
-TEST_P(ArmExidxDecodeTest, expect_truncated) {
- // This test verifies that any op that requires extra ops will
- // fail if the data is not present.
- data_->push_back(0x80);
- ASSERT_FALSE(exidx_->Decode());
- ASSERT_EQ(ARM_STATUS_TRUNCATED, exidx_->status());
-
- data_->clear();
- data_->push_back(0xb1);
- ASSERT_FALSE(exidx_->Decode());
- ASSERT_EQ(ARM_STATUS_TRUNCATED, exidx_->status());
-
- data_->clear();
- data_->push_back(0xb2);
- ASSERT_FALSE(exidx_->Decode());
- ASSERT_EQ(ARM_STATUS_TRUNCATED, exidx_->status());
-
- data_->clear();
- data_->push_back(0xb3);
- ASSERT_FALSE(exidx_->Decode());
- ASSERT_EQ(ARM_STATUS_TRUNCATED, exidx_->status());
-
- data_->clear();
- data_->push_back(0xc6);
- ASSERT_FALSE(exidx_->Decode());
- ASSERT_EQ(ARM_STATUS_TRUNCATED, exidx_->status());
-
- data_->clear();
- data_->push_back(0xc7);
- ASSERT_FALSE(exidx_->Decode());
- ASSERT_EQ(ARM_STATUS_TRUNCATED, exidx_->status());
-
- data_->clear();
- data_->push_back(0xc8);
- ASSERT_FALSE(exidx_->Decode());
- ASSERT_EQ(ARM_STATUS_TRUNCATED, exidx_->status());
-
- data_->clear();
- data_->push_back(0xc9);
- ASSERT_FALSE(exidx_->Decode());
- ASSERT_EQ(ARM_STATUS_TRUNCATED, exidx_->status());
-}
-
-TEST_P(ArmExidxDecodeTest, verify_no_truncated) {
- // This test verifies that no pattern results in a crash or truncation.
- MemoryFakeAlwaysReadZero memory_zero;
- Init(&memory_zero);
-
- for (size_t x = 0; x < 256; x++) {
- if (x == 0xb2) {
- // This opcode is followed by an uleb128, so just skip this one.
- continue;
- }
- for (size_t y = 0; y < 256; y++) {
- data_->clear();
- data_->push_back(x);
- data_->push_back(y);
- if (!exidx_->Decode()) {
- ASSERT_NE(ARM_STATUS_TRUNCATED, exidx_->status())
- << "x y = 0x" << std::hex << x << " 0x" << y;
- ASSERT_NE(ARM_STATUS_READ_FAILED, exidx_->status())
- << "x y = 0x" << std::hex << x << " 0x" << y;
- }
- }
- }
-}
-
-TEST_P(ArmExidxDecodeTest, eval_multiple_decodes) {
- // vsp = vsp + 4
- data_->push_back(0x00);
- // vsp = vsp + 12
- data_->push_back(0x02);
- // Finish
- data_->push_back(0xb0);
-
- ASSERT_TRUE(exidx_->Eval());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ(
- "4 unwind vsp = vsp + 4\n"
- "4 unwind vsp = vsp + 12\n"
- "4 unwind finish\n",
- GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ("4 unwind cfa = r13 + 16\n", GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10010U, exidx_->cfa());
- ASSERT_FALSE(exidx_->pc_set());
-}
-
-TEST_P(ArmExidxDecodeTest, eval_vsp_add_after_pop) {
- // Pop {r15}
- data_->push_back(0x88);
- data_->push_back(0x00);
- // vsp = vsp + 12
- data_->push_back(0x02);
- // Finish
- data_->push_back(0xb0);
- process_memory_.SetData32(0x10000, 0x10);
-
- ASSERT_TRUE(exidx_->Eval());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ(
- "4 unwind pop {r15}\n"
- "4 unwind vsp = vsp + 12\n"
- "4 unwind finish\n",
- GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ(
- "4 unwind cfa = r13 + 16\n"
- "4 unwind r15 = [cfa - 16]\n",
- GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10010U, exidx_->cfa());
- ASSERT_TRUE(exidx_->pc_set());
- ASSERT_EQ(0x10U, (*exidx_->regs())[15]);
-}
-
-TEST_P(ArmExidxDecodeTest, eval_vsp_add_large_after_pop) {
- // Pop {r15}
- data_->push_back(0x88);
- data_->push_back(0x00);
- // vsp = vsp + 1024
- data_->push_back(0xb2);
- data_->push_back(0x7f);
- // Finish
- data_->push_back(0xb0);
- process_memory_.SetData32(0x10000, 0x10);
-
- ASSERT_TRUE(exidx_->Eval());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ(
- "4 unwind pop {r15}\n"
- "4 unwind vsp = vsp + 1024\n"
- "4 unwind finish\n",
- GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ(
- "4 unwind cfa = r13 + 1028\n"
- "4 unwind r15 = [cfa - 1028]\n",
- GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10404U, exidx_->cfa());
- ASSERT_TRUE(exidx_->pc_set());
- ASSERT_EQ(0x10U, (*exidx_->regs())[15]);
-}
-
-TEST_P(ArmExidxDecodeTest, eval_vsp_sub_after_pop) {
- // Pop {r15}
- data_->push_back(0x88);
- data_->push_back(0x00);
- // vsp = vsp - 4
- data_->push_back(0x41);
- // Finish
- data_->push_back(0xb0);
- process_memory_.SetData32(0x10000, 0x10);
-
- ASSERT_TRUE(exidx_->Eval());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ(
- "4 unwind pop {r15}\n"
- "4 unwind vsp = vsp - 8\n"
- "4 unwind finish\n",
- GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ(
- "4 unwind cfa = r13 - 4\n"
- "4 unwind r15 = [cfa + 4]\n",
- GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0xfffcU, exidx_->cfa());
- ASSERT_TRUE(exidx_->pc_set());
- ASSERT_EQ(0x10U, (*exidx_->regs())[15]);
-}
-
-TEST_P(ArmExidxDecodeTest, eval_pc_set) {
- // vsp = vsp + 4
- data_->push_back(0x00);
- // vsp = vsp + 12
- data_->push_back(0x02);
- // Pop {r15}
- data_->push_back(0x88);
- data_->push_back(0x00);
- // vsp = vsp + 12
- data_->push_back(0x02);
- // Finish
- data_->push_back(0xb0);
-
- process_memory_.SetData32(0x10010, 0x10);
-
- ASSERT_TRUE(exidx_->Eval());
- switch (log_) {
- case ARM_LOG_NONE:
- ASSERT_EQ("", GetFakeLogPrint());
- break;
- case ARM_LOG_FULL:
- ASSERT_EQ(
- "4 unwind vsp = vsp + 4\n"
- "4 unwind vsp = vsp + 12\n"
- "4 unwind pop {r15}\n"
- "4 unwind vsp = vsp + 12\n"
- "4 unwind finish\n",
- GetFakeLogPrint());
- break;
- case ARM_LOG_BY_REG:
- exidx_->LogByReg();
- ASSERT_EQ(
- "4 unwind cfa = r13 + 32\n"
- "4 unwind r15 = [cfa - 16]\n",
- GetFakeLogPrint());
- break;
- }
- ASSERT_EQ(0x10020U, exidx_->cfa());
- ASSERT_TRUE(exidx_->pc_set());
- ASSERT_EQ(0x10U, (*exidx_->regs())[15]);
-}
-
-INSTANTIATE_TEST_SUITE_P(Unwindstack, ArmExidxDecodeTest,
- ::testing::Values("logging", "register_logging", "no_logging"));
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/ArmExidxExtractTest.cpp b/libunwindstack/tests/ArmExidxExtractTest.cpp
deleted file mode 100644
index 79c799c..0000000
--- a/libunwindstack/tests/ArmExidxExtractTest.cpp
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * Copyright (C) 2016 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 <stdint.h>
-
-#include <deque>
-#include <vector>
-
-#include <gtest/gtest.h>
-
-#include <unwindstack/Log.h>
-
-#include "ArmExidx.h"
-
-#include "LogFake.h"
-#include "MemoryFake.h"
-
-namespace unwindstack {
-
-class ArmExidxExtractTest : public ::testing::Test {
- protected:
- void SetUp() override {
- ResetLogs();
- elf_memory_.Clear();
- exidx_ = new ArmExidx(nullptr, &elf_memory_, nullptr);
- data_ = exidx_->data();
- data_->clear();
- }
-
- void TearDown() override {
- delete exidx_;
- }
-
- ArmExidx* exidx_ = nullptr;
- std::deque<uint8_t>* data_;
- MemoryFake elf_memory_;
-};
-
-TEST_F(ArmExidxExtractTest, bad_alignment) {
- ASSERT_FALSE(exidx_->ExtractEntryData(0x1001));
- ASSERT_EQ(ARM_STATUS_INVALID_ALIGNMENT, exidx_->status());
- ASSERT_TRUE(data_->empty());
-}
-
-TEST_F(ArmExidxExtractTest, cant_unwind) {
- elf_memory_.SetData32(0x1000, 0x7fff2340);
- elf_memory_.SetData32(0x1004, 1);
- ASSERT_FALSE(exidx_->ExtractEntryData(0x1000));
- ASSERT_EQ(ARM_STATUS_NO_UNWIND, exidx_->status());
- ASSERT_TRUE(data_->empty());
-}
-
-TEST_F(ArmExidxExtractTest, compact) {
- elf_memory_.SetData32(0x4000, 0x7ffa3000);
- elf_memory_.SetData32(0x4004, 0x80a8b0b0);
- ASSERT_TRUE(exidx_->ExtractEntryData(0x4000));
- ASSERT_EQ(3U, data_->size());
- ASSERT_EQ(0xa8, data_->at(0));
- ASSERT_EQ(0xb0, data_->at(1));
- ASSERT_EQ(0xb0, data_->at(2));
-
- // Missing finish gets added.
- elf_memory_.Clear();
- elf_memory_.SetData32(0x534, 0x7ffa3000);
- elf_memory_.SetData32(0x538, 0x80a1a2a3);
- ASSERT_TRUE(exidx_->ExtractEntryData(0x534));
- ASSERT_EQ(4U, data_->size());
- ASSERT_EQ(0xa1, data_->at(0));
- ASSERT_EQ(0xa2, data_->at(1));
- ASSERT_EQ(0xa3, data_->at(2));
- ASSERT_EQ(0xb0, data_->at(3));
-}
-
-TEST_F(ArmExidxExtractTest, compact_non_zero_personality) {
- elf_memory_.SetData32(0x4000, 0x7ffa3000);
-
- uint32_t compact_value = 0x80a8b0b0;
- for (size_t i = 1; i < 16; i++) {
- elf_memory_.SetData32(0x4004, compact_value | (i << 24));
- ASSERT_FALSE(exidx_->ExtractEntryData(0x4000));
- ASSERT_EQ(ARM_STATUS_INVALID_PERSONALITY, exidx_->status());
- }
-}
-
-TEST_F(ArmExidxExtractTest, second_read_compact_personality_1_2) {
- elf_memory_.SetData32(0x5000, 0x1234);
- elf_memory_.SetData32(0x5004, 0x00001230);
- elf_memory_.SetData32(0x6234, 0x8100f3b0);
- ASSERT_TRUE(exidx_->ExtractEntryData(0x5000));
- ASSERT_EQ(2U, data_->size());
- ASSERT_EQ(0xf3, data_->at(0));
- ASSERT_EQ(0xb0, data_->at(1));
-
- elf_memory_.Clear();
- elf_memory_.SetData32(0x5000, 0x1234);
- elf_memory_.SetData32(0x5004, 0x00001230);
- elf_memory_.SetData32(0x6234, 0x8200f3f4);
- ASSERT_TRUE(exidx_->ExtractEntryData(0x5000));
- ASSERT_EQ(3U, data_->size());
- ASSERT_EQ(0xf3, data_->at(0));
- ASSERT_EQ(0xf4, data_->at(1));
- ASSERT_EQ(0xb0, data_->at(2));
-
- elf_memory_.Clear();
- elf_memory_.SetData32(0x5000, 0x1234);
- elf_memory_.SetData32(0x5004, 0x00001230);
- elf_memory_.SetData32(0x6234, 0x8201f3f4);
- elf_memory_.SetData32(0x6238, 0x102030b0);
- ASSERT_TRUE(exidx_->ExtractEntryData(0x5000));
- ASSERT_EQ(6U, data_->size());
- ASSERT_EQ(0xf3, data_->at(0));
- ASSERT_EQ(0xf4, data_->at(1));
- ASSERT_EQ(0x10, data_->at(2));
- ASSERT_EQ(0x20, data_->at(3));
- ASSERT_EQ(0x30, data_->at(4));
- ASSERT_EQ(0xb0, data_->at(5));
-
- elf_memory_.Clear();
- elf_memory_.SetData32(0x5000, 0x1234);
- elf_memory_.SetData32(0x5004, 0x00001230);
- elf_memory_.SetData32(0x6234, 0x8103f3f4);
- elf_memory_.SetData32(0x6238, 0x10203040);
- elf_memory_.SetData32(0x623c, 0x50607080);
- elf_memory_.SetData32(0x6240, 0x90a0c0d0);
- ASSERT_TRUE(exidx_->ExtractEntryData(0x5000));
- ASSERT_EQ(15U, data_->size());
- ASSERT_EQ(0xf3, data_->at(0));
- ASSERT_EQ(0xf4, data_->at(1));
- ASSERT_EQ(0x10, data_->at(2));
- ASSERT_EQ(0x20, data_->at(3));
- ASSERT_EQ(0x30, data_->at(4));
- ASSERT_EQ(0x40, data_->at(5));
- ASSERT_EQ(0x50, data_->at(6));
- ASSERT_EQ(0x60, data_->at(7));
- ASSERT_EQ(0x70, data_->at(8));
- ASSERT_EQ(0x80, data_->at(9));
- ASSERT_EQ(0x90, data_->at(10));
- ASSERT_EQ(0xa0, data_->at(11));
- ASSERT_EQ(0xc0, data_->at(12));
- ASSERT_EQ(0xd0, data_->at(13));
- ASSERT_EQ(0xb0, data_->at(14));
-}
-
-TEST_F(ArmExidxExtractTest, second_read_compact_personality_illegal) {
- elf_memory_.SetData32(0x5000, 0x7ffa1e48);
- elf_memory_.SetData32(0x5004, 0x1230);
- elf_memory_.SetData32(0x6234, 0x832132b0);
- ASSERT_FALSE(exidx_->ExtractEntryData(0x5000));
- ASSERT_EQ(ARM_STATUS_INVALID_PERSONALITY, exidx_->status());
-
- elf_memory_.Clear();
- elf_memory_.SetData32(0x5000, 0x7ffa1e48);
- elf_memory_.SetData32(0x5004, 0x1230);
- elf_memory_.SetData32(0x6234, 0x842132b0);
- ASSERT_FALSE(exidx_->ExtractEntryData(0x5000));
- ASSERT_EQ(ARM_STATUS_INVALID_PERSONALITY, exidx_->status());
-}
-
-TEST_F(ArmExidxExtractTest, second_read_offset_is_negative) {
- elf_memory_.SetData32(0x5000, 0x7ffa1e48);
- elf_memory_.SetData32(0x5004, 0x7fffb1e0);
- elf_memory_.SetData32(0x1e4, 0x842132b0);
- ASSERT_FALSE(exidx_->ExtractEntryData(0x5000));
- ASSERT_EQ(ARM_STATUS_INVALID_PERSONALITY, exidx_->status());
-}
-
-TEST_F(ArmExidxExtractTest, second_read_not_compact) {
- elf_memory_.SetData32(0x5000, 0x1234);
- elf_memory_.SetData32(0x5004, 0x00001230);
- elf_memory_.SetData32(0x6234, 0x1);
- elf_memory_.SetData32(0x6238, 0x001122b0);
- ASSERT_TRUE(exidx_->ExtractEntryData(0x5000));
- ASSERT_EQ(3U, data_->size());
- ASSERT_EQ(0x11, data_->at(0));
- ASSERT_EQ(0x22, data_->at(1));
- ASSERT_EQ(0xb0, data_->at(2));
-
- elf_memory_.Clear();
- elf_memory_.SetData32(0x5000, 0x1234);
- elf_memory_.SetData32(0x5004, 0x00001230);
- elf_memory_.SetData32(0x6234, 0x2);
- elf_memory_.SetData32(0x6238, 0x00112233);
- ASSERT_TRUE(exidx_->ExtractEntryData(0x5000));
- ASSERT_EQ(4U, data_->size());
- ASSERT_EQ(0x11, data_->at(0));
- ASSERT_EQ(0x22, data_->at(1));
- ASSERT_EQ(0x33, data_->at(2));
- ASSERT_EQ(0xb0, data_->at(3));
-
- elf_memory_.Clear();
- elf_memory_.SetData32(0x5000, 0x1234);
- elf_memory_.SetData32(0x5004, 0x00001230);
- elf_memory_.SetData32(0x6234, 0x3);
- elf_memory_.SetData32(0x6238, 0x01112233);
- elf_memory_.SetData32(0x623c, 0x445566b0);
- ASSERT_TRUE(exidx_->ExtractEntryData(0x5000));
- ASSERT_EQ(7U, data_->size());
- ASSERT_EQ(0x11, data_->at(0));
- ASSERT_EQ(0x22, data_->at(1));
- ASSERT_EQ(0x33, data_->at(2));
- ASSERT_EQ(0x44, data_->at(3));
- ASSERT_EQ(0x55, data_->at(4));
- ASSERT_EQ(0x66, data_->at(5));
- ASSERT_EQ(0xb0, data_->at(6));
-
- elf_memory_.Clear();
- elf_memory_.SetData32(0x5000, 0x1234);
- elf_memory_.SetData32(0x5004, 0x00001230);
- elf_memory_.SetData32(0x6234, 0x3);
- elf_memory_.SetData32(0x6238, 0x05112233);
- elf_memory_.SetData32(0x623c, 0x01020304);
- elf_memory_.SetData32(0x6240, 0x05060708);
- elf_memory_.SetData32(0x6244, 0x090a0b0c);
- elf_memory_.SetData32(0x6248, 0x0d0e0f10);
- elf_memory_.SetData32(0x624c, 0x11121314);
- ASSERT_TRUE(exidx_->ExtractEntryData(0x5000));
- ASSERT_EQ(24U, data_->size());
- ASSERT_EQ(0x11, data_->at(0));
- ASSERT_EQ(0x22, data_->at(1));
- ASSERT_EQ(0x33, data_->at(2));
- ASSERT_EQ(0x01, data_->at(3));
- ASSERT_EQ(0x02, data_->at(4));
- ASSERT_EQ(0x03, data_->at(5));
- ASSERT_EQ(0x04, data_->at(6));
- ASSERT_EQ(0x05, data_->at(7));
- ASSERT_EQ(0x06, data_->at(8));
- ASSERT_EQ(0x07, data_->at(9));
- ASSERT_EQ(0x08, data_->at(10));
- ASSERT_EQ(0x09, data_->at(11));
- ASSERT_EQ(0x0a, data_->at(12));
- ASSERT_EQ(0x0b, data_->at(13));
- ASSERT_EQ(0x0c, data_->at(14));
- ASSERT_EQ(0x0d, data_->at(15));
- ASSERT_EQ(0x0e, data_->at(16));
- ASSERT_EQ(0x0f, data_->at(17));
- ASSERT_EQ(0x10, data_->at(18));
- ASSERT_EQ(0x11, data_->at(19));
- ASSERT_EQ(0x12, data_->at(20));
- ASSERT_EQ(0x13, data_->at(21));
- ASSERT_EQ(0x14, data_->at(22));
- ASSERT_EQ(0xb0, data_->at(23));
-}
-
-TEST_F(ArmExidxExtractTest, read_failures) {
- ASSERT_FALSE(exidx_->ExtractEntryData(0x5000));
- ASSERT_EQ(ARM_STATUS_READ_FAILED, exidx_->status());
- EXPECT_EQ(0x5004U, exidx_->status_address());
-
- elf_memory_.SetData32(0x5000, 0x100);
- ASSERT_FALSE(exidx_->ExtractEntryData(0x5000));
- ASSERT_EQ(ARM_STATUS_READ_FAILED, exidx_->status());
- EXPECT_EQ(0x5004U, exidx_->status_address());
-
- elf_memory_.SetData32(0x5004, 0x100);
- ASSERT_FALSE(exidx_->ExtractEntryData(0x5000));
- ASSERT_EQ(ARM_STATUS_READ_FAILED, exidx_->status());
- EXPECT_EQ(0x5104U, exidx_->status_address());
-
- elf_memory_.SetData32(0x5104, 0x1);
- ASSERT_FALSE(exidx_->ExtractEntryData(0x5000));
- ASSERT_EQ(ARM_STATUS_READ_FAILED, exidx_->status());
- EXPECT_EQ(0x5108U, exidx_->status_address());
-
- elf_memory_.SetData32(0x5108, 0x01010203);
- ASSERT_FALSE(exidx_->ExtractEntryData(0x5000));
- ASSERT_EQ(ARM_STATUS_READ_FAILED, exidx_->status());
- EXPECT_EQ(0x510cU, exidx_->status_address());
-}
-
-TEST_F(ArmExidxExtractTest, malformed) {
- elf_memory_.SetData32(0x5000, 0x100);
- elf_memory_.SetData32(0x5004, 0x100);
- elf_memory_.SetData32(0x5104, 0x1);
- elf_memory_.SetData32(0x5108, 0x06010203);
- ASSERT_FALSE(exidx_->ExtractEntryData(0x5000));
- ASSERT_EQ(ARM_STATUS_MALFORMED, exidx_->status());
-
- elf_memory_.Clear();
- elf_memory_.SetData32(0x5000, 0x100);
- elf_memory_.SetData32(0x5004, 0x100);
- elf_memory_.SetData32(0x5104, 0x1);
- elf_memory_.SetData32(0x5108, 0x81060203);
- ASSERT_FALSE(exidx_->ExtractEntryData(0x5000));
- ASSERT_EQ(ARM_STATUS_MALFORMED, exidx_->status());
-}
-
-TEST_F(ArmExidxExtractTest, cant_unwind_log) {
- elf_memory_.SetData32(0x1000, 0x7fff2340);
- elf_memory_.SetData32(0x1004, 1);
-
- exidx_->set_log(ARM_LOG_FULL);
- exidx_->set_log_indent(0);
- exidx_->set_log_skip_execution(false);
-
- ASSERT_FALSE(exidx_->ExtractEntryData(0x1000));
- ASSERT_EQ(ARM_STATUS_NO_UNWIND, exidx_->status());
-
- ASSERT_EQ("4 unwind Raw Data: 0x00 0x00 0x00 0x01\n"
- "4 unwind [cantunwind]\n", GetFakeLogPrint());
-}
-
-TEST_F(ArmExidxExtractTest, raw_data_compact) {
- elf_memory_.SetData32(0x4000, 0x7ffa3000);
- elf_memory_.SetData32(0x4004, 0x80a8b0b0);
-
- exidx_->set_log(ARM_LOG_FULL);
- exidx_->set_log_indent(0);
- exidx_->set_log_skip_execution(false);
-
- ASSERT_TRUE(exidx_->ExtractEntryData(0x4000));
- ASSERT_EQ("4 unwind Raw Data: 0xa8 0xb0 0xb0\n", GetFakeLogPrint());
-}
-
-TEST_F(ArmExidxExtractTest, raw_data_non_compact) {
- elf_memory_.SetData32(0x5000, 0x1234);
- elf_memory_.SetData32(0x5004, 0x00001230);
- elf_memory_.SetData32(0x6234, 0x2);
- elf_memory_.SetData32(0x6238, 0x00112233);
-
- exidx_->set_log(ARM_LOG_FULL);
- exidx_->set_log_indent(0);
- exidx_->set_log_skip_execution(false);
-
- ASSERT_TRUE(exidx_->ExtractEntryData(0x5000));
- ASSERT_EQ("4 unwind Raw Data: 0x11 0x22 0x33 0xb0\n", GetFakeLogPrint());
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/DexFileData.h b/libunwindstack/tests/DexFileData.h
deleted file mode 100644
index 6975c68..0000000
--- a/libunwindstack/tests/DexFileData.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#ifndef _LIBUNWINDSTACK_DEXFILESDATA_H
-#define _LIBUNWINDSTACK_DEXFILESDATA_H
-
-namespace unwindstack {
-
-// Borrowed from art/dex/dex_file_test.cc.
-static constexpr uint32_t kDexData[] = {
- 0x0a786564, 0x00383330, 0xc98b3ab8, 0xf3749d94, 0xaecca4d8, 0xffc7b09a, 0xdca9ca7f, 0x5be5deab,
- 0x00000220, 0x00000070, 0x12345678, 0x00000000, 0x00000000, 0x0000018c, 0x00000008, 0x00000070,
- 0x00000004, 0x00000090, 0x00000002, 0x000000a0, 0x00000000, 0x00000000, 0x00000003, 0x000000b8,
- 0x00000001, 0x000000d0, 0x00000130, 0x000000f0, 0x00000122, 0x0000012a, 0x00000132, 0x00000146,
- 0x00000151, 0x00000154, 0x00000158, 0x0000016d, 0x00000001, 0x00000002, 0x00000004, 0x00000006,
- 0x00000004, 0x00000002, 0x00000000, 0x00000005, 0x00000002, 0x0000011c, 0x00000000, 0x00000000,
- 0x00010000, 0x00000007, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000,
- 0x00000003, 0x00000000, 0x0000017e, 0x00000000, 0x00010001, 0x00000001, 0x00000173, 0x00000004,
- 0x00021070, 0x000e0000, 0x00010001, 0x00000000, 0x00000178, 0x00000001, 0x0000000e, 0x00000001,
- 0x3c060003, 0x74696e69, 0x4c06003e, 0x6e69614d, 0x4c12003b, 0x6176616a, 0x6e616c2f, 0x624f2f67,
- 0x7463656a, 0x4d09003b, 0x2e6e6961, 0x6176616a, 0x00560100, 0x004c5602, 0x6a4c5b13, 0x2f617661,
- 0x676e616c, 0x7274532f, 0x3b676e69, 0x616d0400, 0x01006e69, 0x000e0700, 0x07000103, 0x0000000e,
- 0x81000002, 0x01f00480, 0x02880901, 0x0000000c, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
- 0x00000008, 0x00000070, 0x00000002, 0x00000004, 0x00000090, 0x00000003, 0x00000002, 0x000000a0,
- 0x00000005, 0x00000003, 0x000000b8, 0x00000006, 0x00000001, 0x000000d0, 0x00002001, 0x00000002,
- 0x000000f0, 0x00001001, 0x00000001, 0x0000011c, 0x00002002, 0x00000008, 0x00000122, 0x00002003,
- 0x00000002, 0x00000173, 0x00002000, 0x00000001, 0x0000017e, 0x00001000, 0x00000001, 0x0000018c,
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_DEXFILESDATA_H
diff --git a/libunwindstack/tests/DexFileTest.cpp b/libunwindstack/tests/DexFileTest.cpp
deleted file mode 100644
index 1deba01..0000000
--- a/libunwindstack/tests/DexFileTest.cpp
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright (C) 2018 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 <malloc.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <unordered_map>
-
-#include <MemoryLocal.h>
-#include <android-base/file.h>
-#include <gtest/gtest.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Memory.h>
-
-#include "DexFile.h"
-#include "DexFileData.h"
-#include "MemoryFake.h"
-
-namespace unwindstack {
-
-TEST(DexFileTest, from_file_open_non_exist) {
- EXPECT_TRUE(DexFileFromFile::Create(0, "/file/does/not/exist") == nullptr);
-}
-
-TEST(DexFileTest, from_file_open_too_small) {
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
-
- ASSERT_EQ(size_t{10}, static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, 10))));
-
- // Header too small.
- EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) == nullptr);
-
- // Header correct, file too small.
- ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
- ASSERT_EQ(sizeof(kDexData) - 1,
- static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData) - 1))));
- EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) == nullptr);
-}
-
-TEST(DexFileTest, from_file_open) {
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
-
- ASSERT_EQ(sizeof(kDexData),
- static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
-
- EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) != nullptr);
-}
-
-TEST(DexFileTest, from_file_open_non_zero_offset) {
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
-
- ASSERT_EQ(0x100, lseek(tf.fd, 0x100, SEEK_SET));
- ASSERT_EQ(sizeof(kDexData),
- static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
-
- EXPECT_TRUE(DexFileFromFile::Create(0x100, tf.path) != nullptr);
-}
-
-static constexpr size_t kNumLeakLoops = 5000;
-static constexpr size_t kMaxAllowedLeakBytes = 1024;
-
-static void CheckForLeak(size_t loop, size_t* first_allocated_bytes, size_t* last_allocated_bytes) {
- size_t allocated_bytes = mallinfo().uordblks;
- if (*first_allocated_bytes == 0) {
- *first_allocated_bytes = allocated_bytes;
- } else if (*last_allocated_bytes > *first_allocated_bytes) {
- // Check that the total memory did not increase too much over the first loop.
- ASSERT_LE(*last_allocated_bytes - *first_allocated_bytes, kMaxAllowedLeakBytes)
- << "Failed in loop " << loop << " first_allocated_bytes " << *first_allocated_bytes
- << " last_allocated_bytes " << *last_allocated_bytes;
- }
- *last_allocated_bytes = allocated_bytes;
-}
-
-TEST(DexFileTest, from_file_no_leak) {
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
-
- ASSERT_EQ(sizeof(kDexData),
- static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
-
- size_t first_allocated_bytes = 0;
- size_t last_allocated_bytes = 0;
- for (size_t i = 0; i < kNumLeakLoops; i++) {
- EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) != nullptr);
- ASSERT_NO_FATAL_FAILURE(CheckForLeak(i, &first_allocated_bytes, &last_allocated_bytes));
- }
-}
-
-TEST(DexFileTest, from_memory_fail_too_small_for_header) {
- MemoryFake memory;
-
- memory.SetMemory(0x1000, kDexData, 10);
-
- EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) == nullptr);
-}
-
-TEST(DexFileTest, from_memory_fail_too_small_for_data) {
- MemoryFake memory;
-
- memory.SetMemory(0x1000, kDexData, sizeof(kDexData) - 2);
-
- EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) == nullptr);
-}
-
-TEST(DexFileTest, from_memory_open) {
- MemoryFake memory;
-
- memory.SetMemory(0x1000, kDexData, sizeof(kDexData));
-
- EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) != nullptr);
-}
-
-TEST(DexFileTest, from_memory_no_leak) {
- MemoryFake memory;
-
- memory.SetMemory(0x1000, kDexData, sizeof(kDexData));
-
- size_t first_allocated_bytes = 0;
- size_t last_allocated_bytes = 0;
- for (size_t i = 0; i < kNumLeakLoops; i++) {
- EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) != nullptr);
- ASSERT_NO_FATAL_FAILURE(CheckForLeak(i, &first_allocated_bytes, &last_allocated_bytes));
- }
-}
-
-TEST(DexFileTest, create_using_file) {
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
-
- ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET));
- ASSERT_EQ(sizeof(kDexData),
- static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
-
- MemoryFake memory;
- MapInfo info(nullptr, nullptr, 0, 0x10000, 0, 0x5, tf.path);
- EXPECT_TRUE(DexFile::Create(0x500, &memory, &info) != nullptr);
-}
-
-TEST(DexFileTest, create_using_file_non_zero_start) {
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
-
- ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET));
- ASSERT_EQ(sizeof(kDexData),
- static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
-
- MemoryFake memory;
- MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0, 0x5, tf.path);
- EXPECT_TRUE(DexFile::Create(0x600, &memory, &info) != nullptr);
-}
-
-TEST(DexFileTest, create_using_file_non_zero_offset) {
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
-
- ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET));
- ASSERT_EQ(sizeof(kDexData),
- static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
-
- MemoryFake memory;
- MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, tf.path);
- EXPECT_TRUE(DexFile::Create(0x400, &memory, &info) != nullptr);
-}
-
-TEST(DexFileTest, create_using_memory_empty_file) {
- MemoryFake memory;
- memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
- MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, "");
- EXPECT_TRUE(DexFile::Create(0x4000, &memory, &info) != nullptr);
-}
-
-TEST(DexFileTest, create_using_memory_file_does_not_exist) {
- MemoryFake memory;
- memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
- MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, "/does/not/exist");
- EXPECT_TRUE(DexFile::Create(0x4000, &memory, &info) != nullptr);
-}
-
-TEST(DexFileTest, create_using_memory_file_is_malformed) {
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
-
- ASSERT_EQ(sizeof(kDexData) - 10,
- static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData) - 10))));
-
- MemoryFake memory;
- memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
- MapInfo info(nullptr, nullptr, 0x4000, 0x10000, 0x200, 0x5, "/does/not/exist");
- std::unique_ptr<DexFile> dex_file = DexFile::Create(0x4000, &memory, &info);
- ASSERT_TRUE(dex_file != nullptr);
-
- // Check it came from memory by clearing memory and verifying it fails.
- memory.Clear();
- dex_file = DexFile::Create(0x4000, &memory, &info);
- EXPECT_TRUE(dex_file == nullptr);
-}
-
-TEST(DexFileTest, create_using_memory_size_too_small) {
- MemoryFake memory;
- memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
- MapInfo info(nullptr, nullptr, 0x100, sizeof(kDexData) - 2, 0x200, 0x5, "/does/not/exist");
- EXPECT_TRUE(DexFile::Create(0x4000, &memory, &info) != nullptr);
-}
-
-class MemoryLocalFake : public MemoryLocal {
- public:
- MemoryLocalFake(size_t memory_size) : backing_(memory_size) {}
- virtual ~MemoryLocalFake() = default;
-
- void* Data() { return backing_.data(); }
-
- private:
- std::vector<void*> backing_;
-};
-
-TEST(DexFileTest, create_using_local_memory) {
- MemoryLocalFake memory(sizeof(kDexData));
-
- memcpy(memory.Data(), kDexData, sizeof(kDexData));
- uint64_t start = reinterpret_cast<uint64_t>(memory.Data());
- MapInfo info(nullptr, nullptr, start, start + 0x1000, 0x200, 0x5, "/does/not/exist");
- EXPECT_TRUE(DexFile::Create(start, &memory, &info) != nullptr);
-}
-
-TEST(DexFileTest, create_using_local_memory_size_too_small) {
- MemoryLocalFake memory(sizeof(kDexData));
-
- memcpy(memory.Data(), kDexData, sizeof(kDexData));
- uint64_t start = reinterpret_cast<uint64_t>(memory.Data());
- MapInfo info(nullptr, nullptr, start, start + sizeof(kDexData) - 2, 0x200, 0x5,
- "/does/not/exist");
- EXPECT_TRUE(DexFile::Create(start, &memory, &info) == nullptr);
-}
-
-TEST(DexFileTest, get_method) {
- MemoryFake memory;
- memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
- MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, "");
- std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
- ASSERT_TRUE(dex_file != nullptr);
-
- std::string method;
- uint64_t method_offset;
- ASSERT_TRUE(dex_file->GetMethodInformation(0x102, &method, &method_offset));
- EXPECT_EQ("Main.<init>", method);
- EXPECT_EQ(2U, method_offset);
-
- ASSERT_TRUE(dex_file->GetMethodInformation(0x118, &method, &method_offset));
- EXPECT_EQ("Main.main", method);
- EXPECT_EQ(0U, method_offset);
-}
-
-TEST(DexFileTest, get_method_empty) {
- MemoryFake memory;
- memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
- MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, "");
- std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
- ASSERT_TRUE(dex_file != nullptr);
-
- std::string method;
- uint64_t method_offset;
- EXPECT_FALSE(dex_file->GetMethodInformation(0x100000, &method, &method_offset));
-
- EXPECT_FALSE(dex_file->GetMethodInformation(0x98, &method, &method_offset));
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/DexFilesTest.cpp b/libunwindstack/tests/DexFilesTest.cpp
deleted file mode 100644
index 477cf8e..0000000
--- a/libunwindstack/tests/DexFilesTest.cpp
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- * Copyright (C) 2018 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 <elf.h>
-#include <string.h>
-
-#include <memory>
-#include <vector>
-
-#include <gtest/gtest.h>
-
-#include <unwindstack/DexFiles.h>
-#include <unwindstack/Elf.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
-
-#include "DexFileData.h"
-#include "ElfFake.h"
-#include "MemoryFake.h"
-
-namespace unwindstack {
-
-class DexFilesTest : public ::testing::Test {
- protected:
- void CreateFakeElf(MapInfo* map_info, uint64_t global_offset, uint64_t data_offset,
- uint64_t data_vaddr, uint64_t data_size) {
- MemoryFake* memory = new MemoryFake;
- ElfFake* elf = new ElfFake(memory);
- elf->FakeSetValid(true);
- ElfInterfaceFake* interface = new ElfInterfaceFake(memory);
- elf->FakeSetInterface(interface);
-
- interface->FakeSetGlobalVariable("__dex_debug_descriptor", global_offset);
- interface->FakeSetDataOffset(data_offset);
- interface->FakeSetDataVaddrStart(data_vaddr);
- interface->FakeSetDataVaddrEnd(data_vaddr + data_size);
- map_info->elf.reset(elf);
- }
-
- void Init(ArchEnum arch) {
- dex_files_.reset(new DexFiles(process_memory_));
- dex_files_->SetArch(arch);
-
- maps_.reset(
- new BufferMaps("1000-4000 ---s 00000000 00:00 0 /fake/elf\n"
- "4000-6000 r--s 00000000 00:00 0 /fake/elf\n"
- "6000-8000 -wxs 00002000 00:00 0 /fake/elf\n"
- "a000-c000 r--p 00000000 00:00 0 /fake/elf2\n"
- "c000-f000 rw-p 00002000 00:00 0 /fake/elf2\n"
- "f000-11000 r--p 00000000 00:00 0 /fake/elf3\n"
- "100000-110000 rw-p 00f1000 00:00 0 /fake/elf3\n"
- "200000-210000 rw-p 0002000 00:00 0 /fake/elf3\n"
- "300000-400000 rw-p 0003000 00:00 0 /fake/elf3\n"
- "500000-501000 r--p 0000000 00:00 0 /fake/elf4\n"
- "501000-502000 ---p 0000000 00:00 0\n"
- "503000-510000 rw-p 0003000 00:00 0 /fake/elf4\n"
- "510000-520000 rw-p 0010000 00:00 0 /fake/elf4\n"));
- ASSERT_TRUE(maps_->Parse());
-
- // Global variable in a section that is not readable.
- MapInfo* map_info = maps_->Get(kMapGlobalNonReadable);
- ASSERT_TRUE(map_info != nullptr);
- CreateFakeElf(map_info, 0x2800, 0x2000, 0x2000, 0x3000);
-
- // Global variable not set by default.
- map_info = maps_->Get(kMapGlobalSetToZero);
- ASSERT_TRUE(map_info != nullptr);
- CreateFakeElf(map_info, 0x2800, 0x2000, 0x2000, 0x3000);
-
- // Global variable set in this map.
- map_info = maps_->Get(kMapGlobal);
- ASSERT_TRUE(map_info != nullptr);
- CreateFakeElf(map_info, 0xf1800, 0xf1000, 0xf1000, 0x10000);
-
- // Global variable set in this map, but there is an empty map before rw map.
- map_info = maps_->Get(kMapGlobalAfterEmpty);
- ASSERT_TRUE(map_info != nullptr);
- CreateFakeElf(map_info, 0x3800, 0x3000, 0x3000, 0xd000);
- }
-
- void SetUp() override {
- memory_ = new MemoryFake;
- process_memory_.reset(memory_);
-
- Init(ARCH_ARM);
- }
-
- void WriteDescriptor32(uint64_t addr, uint32_t head);
- void WriteDescriptor64(uint64_t addr, uint64_t head);
- void WriteEntry32(uint64_t entry_addr, uint32_t next, uint32_t prev, uint32_t dex_file);
- void WriteEntry64(uint64_t entry_addr, uint64_t next, uint64_t prev, uint64_t dex_file);
- void WriteDex(uint64_t dex_file);
-
- static constexpr size_t kMapGlobalNonReadable = 2;
- static constexpr size_t kMapGlobalSetToZero = 3;
- static constexpr size_t kMapGlobal = 5;
- static constexpr size_t kMapGlobalRw = 6;
- static constexpr size_t kMapDexFileEntries = 7;
- static constexpr size_t kMapDexFiles = 8;
- static constexpr size_t kMapGlobalAfterEmpty = 9;
- static constexpr size_t kMapDexFilesAfterEmpty = 12;
-
- std::shared_ptr<Memory> process_memory_;
- MemoryFake* memory_;
- std::unique_ptr<DexFiles> dex_files_;
- std::unique_ptr<BufferMaps> maps_;
-};
-
-void DexFilesTest::WriteDescriptor32(uint64_t addr, uint32_t head) {
- // void* first_entry_
- memory_->SetData32(addr + 12, head);
-}
-
-void DexFilesTest::WriteDescriptor64(uint64_t addr, uint64_t head) {
- // void* first_entry_
- memory_->SetData64(addr + 16, head);
-}
-
-void DexFilesTest::WriteEntry32(uint64_t entry_addr, uint32_t next, uint32_t prev,
- uint32_t dex_file) {
- // Format of the 32 bit DEXFileEntry structure:
- // uint32_t next
- memory_->SetData32(entry_addr, next);
- // uint32_t prev
- memory_->SetData32(entry_addr + 4, prev);
- // uint32_t dex_file
- memory_->SetData32(entry_addr + 8, dex_file);
-}
-
-void DexFilesTest::WriteEntry64(uint64_t entry_addr, uint64_t next, uint64_t prev,
- uint64_t dex_file) {
- // Format of the 64 bit DEXFileEntry structure:
- // uint64_t next
- memory_->SetData64(entry_addr, next);
- // uint64_t prev
- memory_->SetData64(entry_addr + 8, prev);
- // uint64_t dex_file
- memory_->SetData64(entry_addr + 16, dex_file);
-}
-
-void DexFilesTest::WriteDex(uint64_t dex_file) {
- memory_->SetMemory(dex_file, kDexData, sizeof(kDexData) * sizeof(uint32_t));
-}
-
-TEST_F(DexFilesTest, get_method_information_invalid) {
- std::string method_name = "nothing";
- uint64_t method_offset = 0x124;
- MapInfo* info = maps_->Get(kMapDexFileEntries);
-
- dex_files_->GetMethodInformation(maps_.get(), info, 0, &method_name, &method_offset);
- EXPECT_EQ("nothing", method_name);
- EXPECT_EQ(0x124U, method_offset);
-}
-
-TEST_F(DexFilesTest, get_method_information_32) {
- std::string method_name = "nothing";
- uint64_t method_offset = 0x124;
- MapInfo* info = maps_->Get(kMapDexFiles);
-
- WriteDescriptor32(0x100800, 0x200000);
- WriteEntry32(0x200000, 0, 0, 0x300000);
- WriteDex(0x300000);
-
- dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
- EXPECT_EQ("Main.<init>", method_name);
- EXPECT_EQ(0U, method_offset);
-}
-
-TEST_F(DexFilesTest, get_method_information_64) {
- Init(ARCH_ARM64);
-
- std::string method_name = "nothing";
- uint64_t method_offset = 0x124;
- MapInfo* info = maps_->Get(kMapDexFiles);
-
- WriteDescriptor64(0x100800, 0x200000);
- WriteEntry64(0x200000, 0, 0, 0x301000);
- WriteDex(0x301000);
-
- dex_files_->GetMethodInformation(maps_.get(), info, 0x301102, &method_name, &method_offset);
- EXPECT_EQ("Main.<init>", method_name);
- EXPECT_EQ(2U, method_offset);
-}
-
-TEST_F(DexFilesTest, get_method_information_not_first_entry_32) {
- std::string method_name = "nothing";
- uint64_t method_offset = 0x124;
- MapInfo* info = maps_->Get(kMapDexFiles);
-
- WriteDescriptor32(0x100800, 0x200000);
- WriteEntry32(0x200000, 0x200100, 0, 0x100000);
- WriteEntry32(0x200100, 0, 0x200000, 0x300000);
- WriteDex(0x300000);
-
- dex_files_->GetMethodInformation(maps_.get(), info, 0x300104, &method_name, &method_offset);
- EXPECT_EQ("Main.<init>", method_name);
- EXPECT_EQ(4U, method_offset);
-}
-
-TEST_F(DexFilesTest, get_method_information_not_first_entry_64) {
- Init(ARCH_ARM64);
-
- std::string method_name = "nothing";
- uint64_t method_offset = 0x124;
- MapInfo* info = maps_->Get(kMapDexFiles);
-
- WriteDescriptor64(0x100800, 0x200000);
- WriteEntry64(0x200000, 0x200100, 0, 0x100000);
- WriteEntry64(0x200100, 0, 0x200000, 0x300000);
- WriteDex(0x300000);
-
- dex_files_->GetMethodInformation(maps_.get(), info, 0x300106, &method_name, &method_offset);
- EXPECT_EQ("Main.<init>", method_name);
- EXPECT_EQ(6U, method_offset);
-}
-
-TEST_F(DexFilesTest, get_method_information_cached) {
- std::string method_name = "nothing";
- uint64_t method_offset = 0x124;
- MapInfo* info = maps_->Get(kMapDexFiles);
-
- WriteDescriptor32(0x100800, 0x200000);
- WriteEntry32(0x200000, 0, 0, 0x300000);
- WriteDex(0x300000);
-
- dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
- EXPECT_EQ("Main.<init>", method_name);
- EXPECT_EQ(0U, method_offset);
-
- // Clear all memory and make sure that data is acquired from the cache.
- memory_->Clear();
- dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
- EXPECT_EQ("Main.<init>", method_name);
- EXPECT_EQ(0U, method_offset);
-}
-
-TEST_F(DexFilesTest, get_method_information_search_libs) {
- std::string method_name = "nothing";
- uint64_t method_offset = 0x124;
- MapInfo* info = maps_->Get(kMapDexFiles);
-
- WriteDescriptor32(0x100800, 0x200000);
- WriteEntry32(0x200000, 0x200100, 0, 0x100000);
- WriteEntry32(0x200100, 0, 0x200000, 0x300000);
- WriteDex(0x300000);
-
- // Only search a given named list of libs.
- std::vector<std::string> libs{"libart.so"};
- dex_files_.reset(new DexFiles(process_memory_, libs));
- dex_files_->SetArch(ARCH_ARM);
-
- dex_files_->GetMethodInformation(maps_.get(), info, 0x300104, &method_name, &method_offset);
- EXPECT_EQ("nothing", method_name);
- EXPECT_EQ(0x124U, method_offset);
-
- MapInfo* map_info = maps_->Get(kMapGlobal);
- map_info->name = "/system/lib/libart.so";
- dex_files_.reset(new DexFiles(process_memory_, libs));
- dex_files_->SetArch(ARCH_ARM);
- // Set the rw map to the same name or this will not scan this entry.
- map_info = maps_->Get(kMapGlobalRw);
- map_info->name = "/system/lib/libart.so";
- // Make sure that clearing out copy of the libs doesn't affect the
- // DexFiles object.
- libs.clear();
-
- dex_files_->GetMethodInformation(maps_.get(), info, 0x300104, &method_name, &method_offset);
- EXPECT_EQ("Main.<init>", method_name);
- EXPECT_EQ(4U, method_offset);
-}
-
-TEST_F(DexFilesTest, get_method_information_global_skip_zero_32) {
- std::string method_name = "nothing";
- uint64_t method_offset = 0x124;
- MapInfo* info = maps_->Get(kMapDexFiles);
-
- // First global variable found, but value is zero.
- WriteDescriptor32(0xc800, 0);
-
- WriteDescriptor32(0x100800, 0x200000);
- WriteEntry32(0x200000, 0, 0, 0x300000);
- WriteDex(0x300000);
-
- dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
- EXPECT_EQ("Main.<init>", method_name);
- EXPECT_EQ(0U, method_offset);
-
- // Verify that second is ignored when first is set to non-zero
- dex_files_.reset(new DexFiles(process_memory_));
- dex_files_->SetArch(ARCH_ARM);
- method_name = "fail";
- method_offset = 0x123;
- WriteDescriptor32(0xc800, 0x100000);
- dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
- EXPECT_EQ("fail", method_name);
- EXPECT_EQ(0x123U, method_offset);
-}
-
-TEST_F(DexFilesTest, get_method_information_global_skip_zero_64) {
- Init(ARCH_ARM64);
-
- std::string method_name = "nothing";
- uint64_t method_offset = 0x124;
- MapInfo* info = maps_->Get(kMapDexFiles);
-
- // First global variable found, but value is zero.
- WriteDescriptor64(0xc800, 0);
-
- WriteDescriptor64(0x100800, 0x200000);
- WriteEntry64(0x200000, 0, 0, 0x300000);
- WriteDex(0x300000);
-
- dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
- EXPECT_EQ("Main.<init>", method_name);
- EXPECT_EQ(0U, method_offset);
-
- // Verify that second is ignored when first is set to non-zero
- dex_files_.reset(new DexFiles(process_memory_));
- dex_files_->SetArch(ARCH_ARM64);
- method_name = "fail";
- method_offset = 0x123;
- WriteDescriptor64(0xc800, 0x100000);
- dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
- EXPECT_EQ("fail", method_name);
- EXPECT_EQ(0x123U, method_offset);
-}
-
-TEST_F(DexFilesTest, get_method_information_with_empty_map) {
- std::string method_name = "nothing";
- uint64_t method_offset = 0x124;
- MapInfo* info = maps_->Get(kMapDexFilesAfterEmpty);
-
- WriteDescriptor32(0x503800, 0x506000);
- WriteEntry32(0x506000, 0, 0, 0x510000);
- WriteDex(0x510000);
-
- dex_files_->GetMethodInformation(maps_.get(), info, 0x510100, &method_name, &method_offset);
- EXPECT_EQ("Main.<init>", method_name);
- EXPECT_EQ(0U, method_offset);
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/DwarfCfaLogTest.cpp b/libunwindstack/tests/DwarfCfaLogTest.cpp
deleted file mode 100644
index 2b5a8dc..0000000
--- a/libunwindstack/tests/DwarfCfaLogTest.cpp
+++ /dev/null
@@ -1,801 +0,0 @@
-/*
- * Copyright (C) 2016 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 <stdint.h>
-
-#include <memory>
-#include <type_traits>
-#include <unordered_map>
-
-#include <android-base/stringprintf.h>
-#include <gtest/gtest.h>
-
-#include <unwindstack/DwarfLocation.h>
-#include <unwindstack/DwarfMemory.h>
-#include <unwindstack/DwarfStructs.h>
-#include <unwindstack/Elf.h>
-#include <unwindstack/Log.h>
-
-#include "DwarfCfa.h"
-
-#include "LogFake.h"
-#include "MemoryFake.h"
-
-namespace unwindstack {
-
-template <typename TypeParam>
-class DwarfCfaLogTest : public ::testing::Test {
- protected:
- void SetUp() override {
- ResetLogs();
- memory_.Clear();
-
- dmem_.reset(new DwarfMemory(&memory_));
-
- cie_.cfa_instructions_offset = 0x1000;
- cie_.cfa_instructions_end = 0x1030;
- // These two values should be different to distinguish between
- // operations that deal with code versus data.
- cie_.code_alignment_factor = 4;
- cie_.data_alignment_factor = 8;
-
- fde_.cfa_instructions_offset = 0x2000;
- fde_.cfa_instructions_end = 0x2030;
- fde_.pc_start = 0x2000;
- fde_.pc_end = 0x2000;
- fde_.pc_end = 0x10000;
- fde_.cie = &cie_;
- cfa_.reset(new DwarfCfa<TypeParam>(dmem_.get(), &fde_, ARCH_UNKNOWN));
- }
-
- MemoryFake memory_;
- std::unique_ptr<DwarfMemory> dmem_;
- std::unique_ptr<DwarfCfa<TypeParam>> cfa_;
- DwarfCie cie_;
- DwarfFde fde_;
-};
-TYPED_TEST_SUITE_P(DwarfCfaLogTest);
-
-// NOTE: All class variable references have to be prefaced with this->.
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_illegal) {
- for (uint8_t i = 0x17; i < 0x3f; i++) {
- if (i == 0x2d || i == 0x2e || i == 0x2f) {
- // Skip gnu extension ops and aarch64 specialized op.
- continue;
- }
- this->memory_.SetMemory(0x2000, std::vector<uint8_t>{i});
-
- ResetLogs();
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2000, 0x2001));
- std::string expected = "4 unwind Illegal\n";
- expected += android::base::StringPrintf("4 unwind Raw Data: 0x%02x\n", i);
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
- }
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_nop) {
- this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x00});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2000, 0x2001));
- std::string expected =
- "4 unwind DW_CFA_nop\n"
- "4 unwind Raw Data: 0x00\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_offset) {
- this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x83, 0x04});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2000, 0x2002));
- std::string expected =
- "4 unwind DW_CFA_offset register(3) 4\n"
- "4 unwind Raw Data: 0x83 0x04\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- this->memory_.SetMemory(0x2100, std::vector<uint8_t>{0x83, 0x84, 0x01});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2100, 0x2103));
- expected =
- "4 unwind DW_CFA_offset register(3) 132\n"
- "4 unwind Raw Data: 0x83 0x84 0x01\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_offset_extended) {
- this->memory_.SetMemory(0x500, std::vector<uint8_t>{0x05, 0x03, 0x02});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x500, 0x503));
- std::string expected =
- "4 unwind DW_CFA_offset_extended register(3) 2\n"
- "4 unwind Raw Data: 0x05 0x03 0x02\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- this->memory_.SetMemory(0x1500, std::vector<uint8_t>{0x05, 0x81, 0x01, 0x82, 0x12});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x1500, 0x1505));
- expected =
- "4 unwind DW_CFA_offset_extended register(129) 2306\n"
- "4 unwind Raw Data: 0x05 0x81 0x01 0x82 0x12\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_offset_extended_sf) {
- this->memory_.SetMemory(0x500, std::vector<uint8_t>{0x11, 0x05, 0x10});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x500, 0x503));
- std::string expected =
- "4 unwind DW_CFA_offset_extended_sf register(5) 16\n"
- "4 unwind Raw Data: 0x11 0x05 0x10\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- // Check a negative value for the offset.
- ResetLogs();
- this->memory_.SetMemory(0x1500, std::vector<uint8_t>{0x11, 0x86, 0x01, 0xff, 0x7f});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x1500, 0x1505));
- expected =
- "4 unwind DW_CFA_offset_extended_sf register(134) -1\n"
- "4 unwind Raw Data: 0x11 0x86 0x01 0xff 0x7f\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_restore) {
- this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0xc2});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2000, 0x2001));
- std::string expected =
- "4 unwind DW_CFA_restore register(2)\n"
- "4 unwind Raw Data: 0xc2\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- this->memory_.SetMemory(0x3000, std::vector<uint8_t>{0x82, 0x04, 0xc2});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x3000, 0x3003));
- expected =
- "4 unwind DW_CFA_offset register(2) 4\n"
- "4 unwind Raw Data: 0x82 0x04\n"
- "4 unwind DW_CFA_restore register(2)\n"
- "4 unwind Raw Data: 0xc2\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_restore_extended) {
- this->memory_.SetMemory(0x4000, std::vector<uint8_t>{0x06, 0x08});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x4000, 0x4002));
- std::string expected =
- "4 unwind DW_CFA_restore_extended register(8)\n"
- "4 unwind Raw Data: 0x06 0x08\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x05, 0x82, 0x02, 0x04, 0x06, 0x82, 0x02});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x5000, 0x5007));
- expected =
- "4 unwind DW_CFA_offset_extended register(258) 4\n"
- "4 unwind Raw Data: 0x05 0x82 0x02 0x04\n"
- "4 unwind DW_CFA_restore_extended register(258)\n"
- "4 unwind Raw Data: 0x06 0x82 0x02\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_set_loc) {
- uint8_t buffer[1 + sizeof(TypeParam)];
- buffer[0] = 0x1;
- TypeParam address;
- std::string raw_data("Raw Data: 0x01 ");
- std::string address_str;
- if (std::is_same<TypeParam, uint32_t>::value) {
- address = 0x81234578U;
- address_str = "0x81234578";
- raw_data += "0x78 0x45 0x23 0x81";
- } else {
- address = 0x8123456712345678ULL;
- address_str = "0x8123456712345678";
- raw_data += "0x78 0x56 0x34 0x12 0x67 0x45 0x23 0x81";
- }
- memcpy(&buffer[1], &address, sizeof(address));
-
- this->memory_.SetMemory(0x50, buffer, sizeof(buffer));
- ResetLogs();
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x50, 0x51 + sizeof(TypeParam)));
- std::string expected = "4 unwind DW_CFA_set_loc " + address_str + "\n";
- expected += "4 unwind " + raw_data + "\n";
- expected += "4 unwind \n";
- expected += "4 unwind PC " + address_str + "\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- // Check for a set going back.
- ResetLogs();
- this->fde_.pc_start = address + 0x10;
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x50, 0x51 + sizeof(TypeParam)));
- expected = "4 unwind DW_CFA_set_loc " + address_str + "\n";
- expected += "4 unwind " + raw_data + "\n";
- expected += "4 unwind \n";
- expected += "4 unwind PC " + address_str + "\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_advance_loc) {
- this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x44});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x201));
- std::string expected =
- "4 unwind DW_CFA_advance_loc 4\n"
- "4 unwind Raw Data: 0x44\n"
- "4 unwind \n"
- "4 unwind PC 0x2010\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_advance_loc1) {
- this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x02, 0x04});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x202));
- std::string expected =
- "4 unwind DW_CFA_advance_loc1 4\n"
- "4 unwind Raw Data: 0x02 0x04\n"
- "4 unwind \n"
- "4 unwind PC 0x2004\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_advance_loc2) {
- this->memory_.SetMemory(0x600, std::vector<uint8_t>{0x03, 0x04, 0x03});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x600, 0x603));
- std::string expected =
- "4 unwind DW_CFA_advance_loc2 772\n"
- "4 unwind Raw Data: 0x03 0x04 0x03\n"
- "4 unwind \n"
- "4 unwind PC 0x2304\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_advance_loc4) {
- this->memory_.SetMemory(0x500, std::vector<uint8_t>{0x04, 0x04, 0x03, 0x02, 0x01});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x500, 0x505));
- std::string expected =
- "4 unwind DW_CFA_advance_loc4 16909060\n"
- "4 unwind Raw Data: 0x04 0x04 0x03 0x02 0x01\n"
- "4 unwind \n"
- "4 unwind PC 0x1022304\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_undefined) {
- this->memory_.SetMemory(0xa00, std::vector<uint8_t>{0x07, 0x09});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0xa00, 0xa02));
- std::string expected =
- "4 unwind DW_CFA_undefined register(9)\n"
- "4 unwind Raw Data: 0x07 0x09\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- dwarf_loc_regs_t cie_loc_regs;
- this->memory_.SetMemory(0x1a00, std::vector<uint8_t>{0x07, 0x81, 0x01});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x1a00, 0x1a03));
- expected =
- "4 unwind DW_CFA_undefined register(129)\n"
- "4 unwind Raw Data: 0x07 0x81 0x01\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_same) {
- this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x08, 0x7f});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x102));
- std::string expected =
- "4 unwind DW_CFA_same_value register(127)\n"
- "4 unwind Raw Data: 0x08 0x7f\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- this->memory_.SetMemory(0x2100, std::vector<uint8_t>{0x08, 0xff, 0x01});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2100, 0x2103));
- expected =
- "4 unwind DW_CFA_same_value register(255)\n"
- "4 unwind Raw Data: 0x08 0xff 0x01\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_register) {
- this->memory_.SetMemory(0x300, std::vector<uint8_t>{0x09, 0x02, 0x01});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x300, 0x303));
- std::string expected =
- "4 unwind DW_CFA_register register(2) register(1)\n"
- "4 unwind Raw Data: 0x09 0x02 0x01\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- this->memory_.SetMemory(0x4300, std::vector<uint8_t>{0x09, 0xff, 0x01, 0xff, 0x03});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x4300, 0x4305));
- expected =
- "4 unwind DW_CFA_register register(255) register(511)\n"
- "4 unwind Raw Data: 0x09 0xff 0x01 0xff 0x03\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_state) {
- this->memory_.SetMemory(0x300, std::vector<uint8_t>{0x0a});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x300, 0x301));
-
- std::string expected =
- "4 unwind DW_CFA_remember_state\n"
- "4 unwind Raw Data: 0x0a\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- this->memory_.SetMemory(0x4300, std::vector<uint8_t>{0x0b});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x4300, 0x4301));
-
- expected =
- "4 unwind DW_CFA_restore_state\n"
- "4 unwind Raw Data: 0x0b\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_state_cfa_offset_restore) {
- this->memory_.SetMemory(0x3000, std::vector<uint8_t>{0x0a, 0x0e, 0x40, 0x0b});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x3000, 0x3004));
-
- std::string expected =
- "4 unwind DW_CFA_remember_state\n"
- "4 unwind Raw Data: 0x0a\n"
- "4 unwind DW_CFA_def_cfa_offset 64\n"
- "4 unwind Raw Data: 0x0e 0x40\n"
- "4 unwind DW_CFA_restore_state\n"
- "4 unwind Raw Data: 0x0b\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa) {
- this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x0c, 0x7f, 0x74});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x103));
-
- std::string expected =
- "4 unwind DW_CFA_def_cfa register(127) 116\n"
- "4 unwind Raw Data: 0x0c 0x7f 0x74\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x0c, 0xff, 0x02, 0xf4, 0x04});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x205));
-
- expected =
- "4 unwind DW_CFA_def_cfa register(383) 628\n"
- "4 unwind Raw Data: 0x0c 0xff 0x02 0xf4 0x04\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_sf) {
- this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x12, 0x30, 0x25});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x103));
-
- std::string expected =
- "4 unwind DW_CFA_def_cfa_sf register(48) 37\n"
- "4 unwind Raw Data: 0x12 0x30 0x25\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- // Test a negative value.
- ResetLogs();
- this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x12, 0xa3, 0x01, 0xfa, 0x7f});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x205));
-
- expected =
- "4 unwind DW_CFA_def_cfa_sf register(163) -6\n"
- "4 unwind Raw Data: 0x12 0xa3 0x01 0xfa 0x7f\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_register) {
- this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x0d, 0x72});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x102));
-
- std::string expected =
- "4 unwind DW_CFA_def_cfa_register register(114)\n"
- "4 unwind Raw Data: 0x0d 0x72\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x0d, 0xf9, 0x20});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x203));
-
- expected =
- "4 unwind DW_CFA_def_cfa_register register(4217)\n"
- "4 unwind Raw Data: 0x0d 0xf9 0x20\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_offset) {
- this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x0e, 0x59});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x102));
-
- std::string expected =
- "4 unwind DW_CFA_def_cfa_offset 89\n"
- "4 unwind Raw Data: 0x0e 0x59\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x102));
-
- expected =
- "4 unwind DW_CFA_def_cfa_offset 89\n"
- "4 unwind Raw Data: 0x0e 0x59\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x0e, 0xd4, 0x0a});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x203));
-
- expected =
- "4 unwind DW_CFA_def_cfa_offset 1364\n"
- "4 unwind Raw Data: 0x0e 0xd4 0x0a\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_offset_sf) {
- this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x13, 0x23});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x102));
-
- std::string expected =
- "4 unwind DW_CFA_def_cfa_offset_sf 35\n"
- "4 unwind Raw Data: 0x13 0x23\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x102));
-
- expected =
- "4 unwind DW_CFA_def_cfa_offset_sf 35\n"
- "4 unwind Raw Data: 0x13 0x23\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- // Negative offset.
- ResetLogs();
- this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x13, 0xf6, 0x7f});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x203));
-
- expected =
- "4 unwind DW_CFA_def_cfa_offset_sf -10\n"
- "4 unwind Raw Data: 0x13 0xf6 0x7f\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_expression) {
- this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x0f, 0x04, 0x01, 0x02, 0x04, 0x05});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x106));
-
- std::string expected =
- "4 unwind DW_CFA_def_cfa_expression 4\n"
- "4 unwind Raw Data: 0x0f 0x04 0x01 0x02 0x04 0x05\n"
- "4 unwind Illegal\n"
- "4 unwind Raw Data: 0x01\n"
- "4 unwind Illegal\n"
- "4 unwind Raw Data: 0x02\n"
- "4 unwind Illegal\n"
- "4 unwind Raw Data: 0x04\n"
- "4 unwind Illegal\n"
- "4 unwind Raw Data: 0x05\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- std::vector<uint8_t> ops{0x0f, 0x81, 0x01};
- expected = "4 unwind Raw Data: 0x0f 0x81 0x01";
- std::string op_string;
- for (uint8_t i = 3; i < 132; i++) {
- ops.push_back(0x05);
- op_string +=
- "4 unwind Illegal\n"
- "4 unwind Raw Data: 0x05\n";
- expected += " 0x05";
- if (((i + 1) % 10) == 0) {
- expected += "\n4 unwind Raw Data:";
- }
- }
- expected += '\n';
- this->memory_.SetMemory(0x200, ops);
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x284));
-
- expected = "4 unwind DW_CFA_def_cfa_expression 129\n" + expected;
- ASSERT_EQ(expected + op_string, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_expression) {
- this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x10, 0x04, 0x02, 0xc0, 0xc1});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x105));
-
- std::string expected =
- "4 unwind DW_CFA_expression register(4) 2\n"
- "4 unwind Raw Data: 0x10 0x04 0x02 0xc0 0xc1\n"
- "4 unwind Illegal\n"
- "4 unwind Raw Data: 0xc0\n"
- "4 unwind Illegal\n"
- "4 unwind Raw Data: 0xc1\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- std::vector<uint8_t> ops{0x10, 0xff, 0x01, 0x82, 0x01};
- expected = "4 unwind Raw Data: 0x10 0xff 0x01 0x82 0x01";
- std::string op_string;
- for (uint8_t i = 5; i < 135; i++) {
- ops.push_back(0xa0 + (i - 5) % 96);
- op_string += "4 unwind Illegal\n";
- op_string += android::base::StringPrintf("4 unwind Raw Data: 0x%02x\n", ops.back());
- expected += android::base::StringPrintf(" 0x%02x", ops.back());
- if (((i + 1) % 10) == 0) {
- expected += "\n4 unwind Raw Data:";
- }
- }
- expected = "4 unwind DW_CFA_expression register(255) 130\n" + expected + "\n";
-
- this->memory_.SetMemory(0x200, ops);
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x287));
-
- ASSERT_EQ(expected + op_string, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_val_offset) {
- this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x14, 0x45, 0x54});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x103));
-
- std::string expected =
- "4 unwind DW_CFA_val_offset register(69) 84\n"
- "4 unwind Raw Data: 0x14 0x45 0x54\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- this->memory_.SetMemory(0x400, std::vector<uint8_t>{0x14, 0xa2, 0x02, 0xb4, 0x05});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x400, 0x405));
-
- expected =
- "4 unwind DW_CFA_val_offset register(290) 692\n"
- "4 unwind Raw Data: 0x14 0xa2 0x02 0xb4 0x05\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_val_offset_sf) {
- this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x15, 0x56, 0x12});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x103));
-
- std::string expected =
- "4 unwind DW_CFA_val_offset_sf register(86) 18\n"
- "4 unwind Raw Data: 0x15 0x56 0x12\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- // Negative value.
- ResetLogs();
- this->memory_.SetMemory(0xa00, std::vector<uint8_t>{0x15, 0xff, 0x01, 0xc0, 0x7f});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0xa00, 0xa05));
-
- expected =
- "4 unwind DW_CFA_val_offset_sf register(255) -64\n"
- "4 unwind Raw Data: 0x15 0xff 0x01 0xc0 0x7f\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_val_expression) {
- this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x16, 0x05, 0x02, 0xb0, 0xb1});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x105));
-
- std::string expected =
- "4 unwind DW_CFA_val_expression register(5) 2\n"
- "4 unwind Raw Data: 0x16 0x05 0x02 0xb0 0xb1\n"
- "4 unwind Illegal\n"
- "4 unwind Raw Data: 0xb0\n"
- "4 unwind Illegal\n"
- "4 unwind Raw Data: 0xb1\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- std::vector<uint8_t> ops{0x16, 0x83, 0x10, 0xa8, 0x01};
- expected = "4 unwind Raw Data: 0x16 0x83 0x10 0xa8 0x01";
- std::string op_string;
- for (uint8_t i = 0; i < 168; i++) {
- ops.push_back(0xa0 + (i % 96));
- op_string += "4 unwind Illegal\n";
- op_string += android::base::StringPrintf("4 unwind Raw Data: 0x%02x\n", ops.back());
- expected += android::base::StringPrintf(" 0x%02x", ops.back());
- if (((i + 6) % 10) == 0) {
- expected += "\n4 unwind Raw Data:";
- }
- }
- expected = "4 unwind DW_CFA_val_expression register(2051) 168\n" + expected + "\n";
-
- this->memory_.SetMemory(0xa00, ops);
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0xa00, 0xaad));
-
- ASSERT_EQ(expected + op_string, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_gnu_args_size) {
- this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x2e, 0x04});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2000, 0x2002));
-
- std::string expected =
- "4 unwind DW_CFA_GNU_args_size 4\n"
- "4 unwind Raw Data: 0x2e 0x04\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x2e, 0xa4, 0x80, 0x04});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x5000, 0x5004));
-
- expected =
- "4 unwind DW_CFA_GNU_args_size 65572\n"
- "4 unwind Raw Data: 0x2e 0xa4 0x80 0x04\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_gnu_negative_offset_extended) {
- this->memory_.SetMemory(0x500, std::vector<uint8_t>{0x2f, 0x08, 0x10});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x500, 0x503));
-
- std::string expected =
- "4 unwind DW_CFA_GNU_negative_offset_extended register(8) 16\n"
- "4 unwind Raw Data: 0x2f 0x08 0x10\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- this->memory_.SetMemory(0x1500, std::vector<uint8_t>{0x2f, 0x81, 0x02, 0xff, 0x01});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x1500, 0x1505));
-
- expected =
- "4 unwind DW_CFA_GNU_negative_offset_extended register(257) 255\n"
- "4 unwind Raw Data: 0x2f 0x81 0x02 0xff 0x01\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_register_override) {
- this->memory_.SetMemory(0x300, std::vector<uint8_t>{0x09, 0x02, 0x01, 0x09, 0x02, 0x04});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x300, 0x306));
-
- std::string expected =
- "4 unwind DW_CFA_register register(2) register(1)\n"
- "4 unwind Raw Data: 0x09 0x02 0x01\n"
- "4 unwind DW_CFA_register register(2) register(4)\n"
- "4 unwind Raw Data: 0x09 0x02 0x04\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaLogTest, cfa_aarch64_negate_ra_state) {
- // Verify that if the cfa op is handled properly depending on aarch.
- this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x2d});
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2000, 0x2001));
- std::string expected = "4 unwind Illegal (Only valid on aarch64)\n";
- expected += "4 unwind Raw Data: 0x2d\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- this->cfa_.reset(new DwarfCfa<TypeParam>(this->dmem_.get(), &this->fde_, ARCH_ARM64));
-
- ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2000, 0x2001));
- expected = "4 unwind DW_CFA_AARCH64_negate_ra_state\n";
- expected += "4 unwind Raw Data: 0x2d\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-REGISTER_TYPED_TEST_SUITE_P(DwarfCfaLogTest, cfa_illegal, cfa_nop, cfa_offset, cfa_offset_extended,
- cfa_offset_extended_sf, cfa_restore, cfa_restore_extended, cfa_set_loc,
- cfa_advance_loc, cfa_advance_loc1, cfa_advance_loc2, cfa_advance_loc4,
- cfa_undefined, cfa_same, cfa_register, cfa_state,
- cfa_state_cfa_offset_restore, cfa_def_cfa, cfa_def_cfa_sf,
- cfa_def_cfa_register, cfa_def_cfa_offset, cfa_def_cfa_offset_sf,
- cfa_def_cfa_expression, cfa_expression, cfa_val_offset,
- cfa_val_offset_sf, cfa_val_expression, cfa_gnu_args_size,
- cfa_gnu_negative_offset_extended, cfa_register_override,
- cfa_aarch64_negate_ra_state);
-
-typedef ::testing::Types<uint32_t, uint64_t> DwarfCfaLogTestTypes;
-INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfCfaLogTest, DwarfCfaLogTestTypes);
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/DwarfCfaTest.cpp b/libunwindstack/tests/DwarfCfaTest.cpp
deleted file mode 100644
index ea7e708..0000000
--- a/libunwindstack/tests/DwarfCfaTest.cpp
+++ /dev/null
@@ -1,1021 +0,0 @@
-/*
- * Copyright (C) 2016 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 <stdint.h>
-
-#include <memory>
-#include <unordered_map>
-
-#include <gtest/gtest.h>
-
-#include <unwindstack/DwarfError.h>
-#include <unwindstack/DwarfLocation.h>
-#include <unwindstack/DwarfMemory.h>
-#include <unwindstack/DwarfStructs.h>
-#include <unwindstack/Elf.h>
-#include <unwindstack/Log.h>
-#include <unwindstack/MachineArm64.h>
-
-#include "DwarfCfa.h"
-
-#include "LogFake.h"
-#include "MemoryFake.h"
-
-namespace unwindstack {
-
-template <typename TypeParam>
-class DwarfCfaTest : public ::testing::Test {
- protected:
- void SetUp() override {
- ResetLogs();
- memory_.Clear();
-
- dmem_.reset(new DwarfMemory(&memory_));
-
- cie_.cfa_instructions_offset = 0x1000;
- cie_.cfa_instructions_end = 0x1030;
- // These two values should be different to distinguish between
- // operations that deal with code versus data.
- cie_.code_alignment_factor = 4;
- cie_.data_alignment_factor = 8;
-
- fde_.cfa_instructions_offset = 0x2000;
- fde_.cfa_instructions_end = 0x2030;
- fde_.pc_start = 0x2000;
- fde_.cie = &cie_;
-
- cfa_.reset(new DwarfCfa<TypeParam>(dmem_.get(), &fde_, ARCH_UNKNOWN));
- }
-
- MemoryFake memory_;
- std::unique_ptr<DwarfMemory> dmem_;
- std::unique_ptr<DwarfCfa<TypeParam>> cfa_;
- DwarfCie cie_;
- DwarfFde fde_;
-};
-TYPED_TEST_SUITE_P(DwarfCfaTest);
-
-// NOTE: All test class variables need to be referenced as this->.
-
-TYPED_TEST_P(DwarfCfaTest, cfa_illegal) {
- for (uint8_t i = 0x17; i < 0x3f; i++) {
- if (i == 0x2d || i == 0x2e || i == 0x2f) {
- // Skip gnu extension ops and aarch64 specialized op.
- continue;
- }
- this->memory_.SetMemory(0x2000, std::vector<uint8_t>{i});
- dwarf_loc_regs_t loc_regs;
-
- ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs));
- ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->cfa_->LastErrorCode());
- ASSERT_EQ(0x2001U, this->dmem_->cur_offset());
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
- }
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_nop) {
- this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x00});
- dwarf_loc_regs_t loc_regs;
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs));
- ASSERT_EQ(0x2001U, this->dmem_->cur_offset());
- ASSERT_EQ(0U, loc_regs.size());
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-// This test needs to be examined.
-TYPED_TEST_P(DwarfCfaTest, cfa_offset) {
- this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x83, 0x04});
- dwarf_loc_regs_t loc_regs;
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2002, &loc_regs));
- ASSERT_EQ(0x2002U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- auto location = loc_regs.find(3);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type);
- ASSERT_EQ(32U, location->second.values[0]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- this->memory_.SetMemory(0x2100, std::vector<uint8_t>{0x83, 0x84, 0x01});
- loc_regs.clear();
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2100, 0x2103, &loc_regs));
- ASSERT_EQ(0x2103U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- location = loc_regs.find(3);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type);
- ASSERT_EQ(1056U, location->second.values[0]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_offset_extended) {
- this->memory_.SetMemory(0x500, std::vector<uint8_t>{0x05, 0x03, 0x02});
- dwarf_loc_regs_t loc_regs;
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x500, 0x503, &loc_regs));
- ASSERT_EQ(0x503U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- auto location = loc_regs.find(3);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type);
- ASSERT_EQ(2U, location->second.values[0]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- loc_regs.clear();
- this->memory_.SetMemory(0x1500, std::vector<uint8_t>{0x05, 0x81, 0x01, 0x82, 0x12});
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x1500, 0x1505, &loc_regs));
- ASSERT_EQ(0x1505U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- location = loc_regs.find(129);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type);
- ASSERT_EQ(2306U, location->second.values[0]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_offset_extended_sf) {
- this->memory_.SetMemory(0x500, std::vector<uint8_t>{0x11, 0x05, 0x10});
- dwarf_loc_regs_t loc_regs;
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x500, 0x503, &loc_regs));
- ASSERT_EQ(0x503U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- auto location = loc_regs.find(5);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type);
- ASSERT_EQ(0x80U, location->second.values[0]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- // Check a negative value for the offset.
- ResetLogs();
- loc_regs.clear();
- this->memory_.SetMemory(0x1500, std::vector<uint8_t>{0x11, 0x86, 0x01, 0xff, 0x7f});
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x1500, 0x1505, &loc_regs));
- ASSERT_EQ(0x1505U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- location = loc_regs.find(134);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type);
- ASSERT_EQ(static_cast<uint64_t>(-8), location->second.values[0]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_restore) {
- this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0xc2});
- dwarf_loc_regs_t loc_regs;
-
- ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs));
- ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode());
- ASSERT_EQ(0x2001U, this->dmem_->cur_offset());
- ASSERT_EQ(0U, loc_regs.size());
-
- ASSERT_EQ("4 unwind restore while processing cie\n", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- dwarf_loc_regs_t cie_loc_regs;
- cie_loc_regs[2] = {.type = DWARF_LOCATION_REGISTER, .values = {0, 0}};
- this->cfa_->set_cie_loc_regs(&cie_loc_regs);
- this->memory_.SetMemory(0x3000, std::vector<uint8_t>{0x82, 0x04, 0xc2});
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x3000, 0x3003, &loc_regs));
- ASSERT_EQ(0x3003U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- auto location = loc_regs.find(2);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_REGISTER, location->second.type);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_restore_extended) {
- this->memory_.SetMemory(0x4000, std::vector<uint8_t>{0x06, 0x08});
- dwarf_loc_regs_t loc_regs;
-
- ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x4000, 0x4002, &loc_regs));
- ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode());
- ASSERT_EQ(0x4002U, this->dmem_->cur_offset());
- ASSERT_EQ(0U, loc_regs.size());
-
- ASSERT_EQ("4 unwind restore while processing cie\n", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- loc_regs.clear();
- this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x05, 0x82, 0x02, 0x04, 0x06, 0x82, 0x02});
- dwarf_loc_regs_t cie_loc_regs;
- cie_loc_regs[258] = {.type = DWARF_LOCATION_REGISTER, .values = {0, 0}};
- this->cfa_->set_cie_loc_regs(&cie_loc_regs);
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x5000, 0x5007, &loc_regs));
- ASSERT_EQ(0x5007U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- auto location = loc_regs.find(258);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_REGISTER, location->second.type);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_set_loc) {
- uint8_t buffer[1 + sizeof(TypeParam)];
- buffer[0] = 0x1;
- TypeParam address;
- std::string raw_data("Raw Data: 0x01 ");
- std::string address_str;
- if (sizeof(TypeParam) == 4) {
- address = 0x81234578U;
- address_str = "0x81234578";
- raw_data += "0x78 0x45 0x23 0x81";
- } else {
- address = 0x8123456712345678ULL;
- address_str = "0x8123456712345678";
- raw_data += "0x78 0x56 0x34 0x12 0x67 0x45 0x23 0x81";
- }
- memcpy(&buffer[1], &address, sizeof(address));
-
- this->memory_.SetMemory(0x50, buffer, sizeof(buffer));
- ResetLogs();
- dwarf_loc_regs_t loc_regs;
- ASSERT_TRUE(
- this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x50, 0x51 + sizeof(TypeParam), &loc_regs));
- ASSERT_EQ(0x51 + sizeof(TypeParam), this->dmem_->cur_offset());
- ASSERT_EQ(address, this->cfa_->cur_pc());
- ASSERT_EQ(0U, loc_regs.size());
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- // Check for a set going back.
- ResetLogs();
- loc_regs.clear();
- this->fde_.pc_start = address + 0x10;
- ASSERT_TRUE(
- this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x50, 0x51 + sizeof(TypeParam), &loc_regs));
- ASSERT_EQ(0x51 + sizeof(TypeParam), this->dmem_->cur_offset());
- ASSERT_EQ(address, this->cfa_->cur_pc());
- ASSERT_EQ(0U, loc_regs.size());
-
- std::string cur_address_str(address_str);
- cur_address_str[cur_address_str.size() - 2] = '8';
- std::string expected = "4 unwind Warning: PC is moving backwards: old " + cur_address_str +
- " new " + address_str + "\n";
- ASSERT_EQ(expected, GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_advance_loc1) {
- this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x02, 0x04});
- dwarf_loc_regs_t loc_regs;
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x202, &loc_regs));
- ASSERT_EQ(0x202U, this->dmem_->cur_offset());
- ASSERT_EQ(this->fde_.pc_start + 0x10, this->cfa_->cur_pc());
- ASSERT_EQ(0U, loc_regs.size());
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_advance_loc2) {
- this->memory_.SetMemory(0x600, std::vector<uint8_t>{0x03, 0x04, 0x03});
- dwarf_loc_regs_t loc_regs;
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x600, 0x603, &loc_regs));
- ASSERT_EQ(0x603U, this->dmem_->cur_offset());
- ASSERT_EQ(this->fde_.pc_start + 0xc10U, this->cfa_->cur_pc());
- ASSERT_EQ(0U, loc_regs.size());
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_advance_loc4) {
- this->memory_.SetMemory(0x500, std::vector<uint8_t>{0x04, 0x04, 0x03, 0x02, 0x01});
- dwarf_loc_regs_t loc_regs;
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x500, 0x505, &loc_regs));
- ASSERT_EQ(0x505U, this->dmem_->cur_offset());
- ASSERT_EQ(this->fde_.pc_start + 0x4080c10, this->cfa_->cur_pc());
- ASSERT_EQ(0U, loc_regs.size());
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_undefined) {
- this->memory_.SetMemory(0xa00, std::vector<uint8_t>{0x07, 0x09});
- dwarf_loc_regs_t loc_regs;
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0xa00, 0xa02, &loc_regs));
- ASSERT_EQ(0xa02U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- auto location = loc_regs.find(9);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_UNDEFINED, location->second.type);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- loc_regs.clear();
- this->memory_.SetMemory(0x1a00, std::vector<uint8_t>{0x07, 0x81, 0x01});
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x1a00, 0x1a03, &loc_regs));
- ASSERT_EQ(0x1a03U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- location = loc_regs.find(129);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_UNDEFINED, location->second.type);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_same) {
- this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x08, 0x7f});
- dwarf_loc_regs_t loc_regs;
-
- loc_regs[127] = {.type = DWARF_LOCATION_REGISTER, .values = {0, 0}};
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs));
- ASSERT_EQ(0x102U, this->dmem_->cur_offset());
- ASSERT_EQ(0U, loc_regs.size());
- ASSERT_EQ(0U, loc_regs.count(127));
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- loc_regs.clear();
- this->memory_.SetMemory(0x2100, std::vector<uint8_t>{0x08, 0xff, 0x01});
-
- loc_regs[255] = {.type = DWARF_LOCATION_REGISTER, .values = {0, 0}};
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2100, 0x2103, &loc_regs));
- ASSERT_EQ(0x2103U, this->dmem_->cur_offset());
- ASSERT_EQ(0U, loc_regs.size());
- ASSERT_EQ(0U, loc_regs.count(255));
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_register) {
- this->memory_.SetMemory(0x300, std::vector<uint8_t>{0x09, 0x02, 0x01});
- dwarf_loc_regs_t loc_regs;
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x300, 0x303, &loc_regs));
- ASSERT_EQ(0x303U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- auto location = loc_regs.find(2);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_REGISTER, location->second.type);
- ASSERT_EQ(1U, location->second.values[0]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- loc_regs.clear();
- this->memory_.SetMemory(0x4300, std::vector<uint8_t>{0x09, 0xff, 0x01, 0xff, 0x03});
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x4300, 0x4305, &loc_regs));
- ASSERT_EQ(0x4305U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- location = loc_regs.find(255);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_REGISTER, location->second.type);
- ASSERT_EQ(511U, location->second.values[0]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_state) {
- this->memory_.SetMemory(0x300, std::vector<uint8_t>{0x0a});
- dwarf_loc_regs_t loc_regs;
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x300, 0x301, &loc_regs));
- ASSERT_EQ(0x301U, this->dmem_->cur_offset());
- ASSERT_EQ(0U, loc_regs.size());
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- this->memory_.SetMemory(0x4300, std::vector<uint8_t>{0x0b});
-
- loc_regs.clear();
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x4300, 0x4301, &loc_regs));
- ASSERT_EQ(0x4301U, this->dmem_->cur_offset());
- ASSERT_EQ(0U, loc_regs.size());
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x85, 0x02, 0x0a, 0x86, 0x04, 0x0b});
-
- loc_regs.clear();
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2005, &loc_regs));
- ASSERT_EQ(0x2005U, this->dmem_->cur_offset());
- ASSERT_EQ(2U, loc_regs.size());
- ASSERT_NE(loc_regs.end(), loc_regs.find(5));
- ASSERT_NE(loc_regs.end(), loc_regs.find(6));
-
- loc_regs.clear();
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2006, &loc_regs));
- ASSERT_EQ(0x2006U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- ASSERT_NE(loc_regs.end(), loc_regs.find(5));
-
- ResetLogs();
- this->memory_.SetMemory(
- 0x6000, std::vector<uint8_t>{0x0a, 0x85, 0x02, 0x0a, 0x86, 0x04, 0x0a, 0x87, 0x01, 0x0a, 0x89,
- 0x05, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b});
-
- loc_regs.clear();
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x6000, 0x600c, &loc_regs));
- ASSERT_EQ(0x600cU, this->dmem_->cur_offset());
- ASSERT_EQ(4U, loc_regs.size());
- ASSERT_NE(loc_regs.end(), loc_regs.find(5));
- ASSERT_NE(loc_regs.end(), loc_regs.find(6));
- ASSERT_NE(loc_regs.end(), loc_regs.find(7));
- ASSERT_NE(loc_regs.end(), loc_regs.find(9));
-
- loc_regs.clear();
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x6000, 0x600d, &loc_regs));
- ASSERT_EQ(0x600dU, this->dmem_->cur_offset());
- ASSERT_EQ(3U, loc_regs.size());
- ASSERT_NE(loc_regs.end(), loc_regs.find(5));
- ASSERT_NE(loc_regs.end(), loc_regs.find(6));
- ASSERT_NE(loc_regs.end(), loc_regs.find(7));
-
- loc_regs.clear();
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x6000, 0x600e, &loc_regs));
- ASSERT_EQ(0x600eU, this->dmem_->cur_offset());
- ASSERT_EQ(2U, loc_regs.size());
- ASSERT_NE(loc_regs.end(), loc_regs.find(5));
- ASSERT_NE(loc_regs.end(), loc_regs.find(6));
-
- loc_regs.clear();
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x6000, 0x600f, &loc_regs));
- ASSERT_EQ(0x600fU, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- ASSERT_NE(loc_regs.end(), loc_regs.find(5));
-
- loc_regs.clear();
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x6000, 0x6010, &loc_regs));
- ASSERT_EQ(0x6010U, this->dmem_->cur_offset());
- ASSERT_EQ(0U, loc_regs.size());
-
- loc_regs.clear();
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x6000, 0x6011, &loc_regs));
- ASSERT_EQ(0x6011U, this->dmem_->cur_offset());
- ASSERT_EQ(0U, loc_regs.size());
-}
-
-// This test verifies that the cfa offset is saved and restored properly.
-// Even though the spec is not clear about whether the offset is also
-// restored, the gcc unwinder does, and libunwind does too.
-TYPED_TEST_P(DwarfCfaTest, cfa_state_cfa_offset_restore) {
- this->memory_.SetMemory(0x3000, std::vector<uint8_t>{0x0a, 0x0e, 0x40, 0x0b});
- dwarf_loc_regs_t loc_regs;
- loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {5, 100}};
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x3000, 0x3004, &loc_regs));
- ASSERT_EQ(0x3004U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type);
- ASSERT_EQ(5U, loc_regs[CFA_REG].values[0]);
- ASSERT_EQ(100U, loc_regs[CFA_REG].values[1]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa) {
- this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x0c, 0x7f, 0x74});
- dwarf_loc_regs_t loc_regs;
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x103, &loc_regs));
- ASSERT_EQ(0x103U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type);
- ASSERT_EQ(0x7fU, loc_regs[CFA_REG].values[0]);
- ASSERT_EQ(0x74U, loc_regs[CFA_REG].values[1]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- loc_regs.clear();
- this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x0c, 0xff, 0x02, 0xf4, 0x04});
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x205, &loc_regs));
- ASSERT_EQ(0x205U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type);
- ASSERT_EQ(0x17fU, loc_regs[CFA_REG].values[0]);
- ASSERT_EQ(0x274U, loc_regs[CFA_REG].values[1]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa_sf) {
- this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x12, 0x30, 0x25});
- dwarf_loc_regs_t loc_regs;
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x103, &loc_regs));
- ASSERT_EQ(0x103U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type);
- ASSERT_EQ(0x30U, loc_regs[CFA_REG].values[0]);
- ASSERT_EQ(0x128U, loc_regs[CFA_REG].values[1]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- // Test a negative value.
- ResetLogs();
- loc_regs.clear();
- this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x12, 0xa3, 0x01, 0xfa, 0x7f});
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x205, &loc_regs));
- ASSERT_EQ(0x205U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type);
- ASSERT_EQ(0xa3U, loc_regs[CFA_REG].values[0]);
- ASSERT_EQ(static_cast<uint64_t>(-48), loc_regs[CFA_REG].values[1]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa_register) {
- this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x0d, 0x72});
- dwarf_loc_regs_t loc_regs;
-
- // This fails because the cfa is not defined as a register.
- ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs));
- ASSERT_EQ(0U, loc_regs.size());
- ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode());
-
- ASSERT_EQ("4 unwind Attempt to set new register, but cfa is not already set to a register.\n",
- GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- loc_regs.clear();
- loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {3, 20}};
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs));
- ASSERT_EQ(0x102U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type);
- ASSERT_EQ(0x72U, loc_regs[CFA_REG].values[0]);
- ASSERT_EQ(20U, loc_regs[CFA_REG].values[1]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x0d, 0xf9, 0x20});
- loc_regs.clear();
- loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {3, 60}};
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x203, &loc_regs));
- ASSERT_EQ(0x203U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type);
- ASSERT_EQ(0x1079U, loc_regs[CFA_REG].values[0]);
- ASSERT_EQ(60U, loc_regs[CFA_REG].values[1]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa_offset) {
- this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x0e, 0x59});
- dwarf_loc_regs_t loc_regs;
-
- // This fails because the cfa is not defined as a register.
- ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs));
- ASSERT_EQ(0U, loc_regs.size());
- ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode());
-
- ASSERT_EQ("4 unwind Attempt to set offset, but cfa is not set to a register.\n",
- GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- loc_regs.clear();
- loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {3}};
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs));
- ASSERT_EQ(0x102U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type);
- ASSERT_EQ(3U, loc_regs[CFA_REG].values[0]);
- ASSERT_EQ(0x59U, loc_regs[CFA_REG].values[1]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x0e, 0xd4, 0x0a});
- loc_regs.clear();
- loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {3}};
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x203, &loc_regs));
- ASSERT_EQ(0x203U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type);
- ASSERT_EQ(3U, loc_regs[CFA_REG].values[0]);
- ASSERT_EQ(0x554U, loc_regs[CFA_REG].values[1]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa_offset_sf) {
- this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x13, 0x23});
- dwarf_loc_regs_t loc_regs;
-
- // This fails because the cfa is not defined as a register.
- ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs));
- ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode());
-
- ASSERT_EQ("4 unwind Attempt to set offset, but cfa is not set to a register.\n",
- GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- loc_regs.clear();
- loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {3}};
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs));
- ASSERT_EQ(0x102U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type);
- ASSERT_EQ(3U, loc_regs[CFA_REG].values[0]);
- ASSERT_EQ(0x118U, loc_regs[CFA_REG].values[1]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- // Negative offset.
- ResetLogs();
- this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x13, 0xf6, 0x7f});
- loc_regs.clear();
- loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {3}};
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x203, &loc_regs));
- ASSERT_EQ(0x203U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type);
- ASSERT_EQ(3U, loc_regs[CFA_REG].values[0]);
- ASSERT_EQ(static_cast<TypeParam>(-80), static_cast<TypeParam>(loc_regs[CFA_REG].values[1]));
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa_expression) {
- this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x0f, 0x04, 0x01, 0x02, 0x03, 0x04});
- dwarf_loc_regs_t loc_regs;
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x106, &loc_regs));
- ASSERT_EQ(0x106U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- std::vector<uint8_t> ops{0x0f, 0x81, 0x01};
- for (uint8_t i = 3; i < 132; i++) {
- ops.push_back(i - 1);
- }
- this->memory_.SetMemory(0x200, ops);
- loc_regs.clear();
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x284, &loc_regs));
- ASSERT_EQ(0x284U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- ASSERT_EQ(DWARF_LOCATION_VAL_EXPRESSION, loc_regs[CFA_REG].type);
- ASSERT_EQ(0x81U, loc_regs[CFA_REG].values[0]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_expression) {
- this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x10, 0x04, 0x02, 0x40, 0x20});
- dwarf_loc_regs_t loc_regs;
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x105, &loc_regs));
- ASSERT_EQ(0x105U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- auto location = loc_regs.find(4);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_EXPRESSION, location->second.type);
- ASSERT_EQ(2U, location->second.values[0]);
- ASSERT_EQ(0x105U, location->second.values[1]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- std::vector<uint8_t> ops{0x10, 0xff, 0x01, 0x82, 0x01};
- for (uint8_t i = 5; i < 135; i++) {
- ops.push_back(i - 4);
- }
-
- this->memory_.SetMemory(0x200, ops);
- loc_regs.clear();
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x287, &loc_regs));
- ASSERT_EQ(0x287U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- location = loc_regs.find(255);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_EXPRESSION, location->second.type);
- ASSERT_EQ(130U, location->second.values[0]);
- ASSERT_EQ(0x287U, location->second.values[1]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_val_offset) {
- this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x14, 0x45, 0x54});
- dwarf_loc_regs_t loc_regs;
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x103, &loc_regs));
- ASSERT_EQ(0x103U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- auto location = loc_regs.find(69);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_VAL_OFFSET, location->second.type);
- ASSERT_EQ(0x2a0U, location->second.values[0]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- loc_regs.clear();
- this->memory_.SetMemory(0x400, std::vector<uint8_t>{0x14, 0xa2, 0x02, 0xb4, 0x05});
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x400, 0x405, &loc_regs));
- ASSERT_EQ(0x405U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- location = loc_regs.find(290);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_VAL_OFFSET, location->second.type);
- ASSERT_EQ(0x15a0U, location->second.values[0]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_val_offset_sf) {
- this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x15, 0x56, 0x12});
- dwarf_loc_regs_t loc_regs;
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x103, &loc_regs));
- ASSERT_EQ(0x103U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- auto location = loc_regs.find(86);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_VAL_OFFSET, location->second.type);
- ASSERT_EQ(0x90U, location->second.values[0]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- // Negative value.
- ResetLogs();
- loc_regs.clear();
- this->memory_.SetMemory(0xa00, std::vector<uint8_t>{0x15, 0xff, 0x01, 0xc0, 0x7f});
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0xa00, 0xa05, &loc_regs));
- ASSERT_EQ(0xa05U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- location = loc_regs.find(255);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_VAL_OFFSET, location->second.type);
- ASSERT_EQ(static_cast<uint64_t>(-512), location->second.values[0]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_val_expression) {
- this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x16, 0x05, 0x02, 0x10, 0x20});
- dwarf_loc_regs_t loc_regs;
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x105, &loc_regs));
- ASSERT_EQ(0x105U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- auto location = loc_regs.find(5);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_VAL_EXPRESSION, location->second.type);
- ASSERT_EQ(2U, location->second.values[0]);
- ASSERT_EQ(0x105U, location->second.values[1]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- std::vector<uint8_t> ops{0x16, 0x83, 0x10, 0xa8, 0x01};
- for (uint8_t i = 0; i < 168; i++) {
- ops.push_back(i);
- }
-
- this->memory_.SetMemory(0xa00, ops);
- loc_regs.clear();
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0xa00, 0xaad, &loc_regs));
- ASSERT_EQ(0xaadU, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- location = loc_regs.find(2051);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_VAL_EXPRESSION, location->second.type);
- ASSERT_EQ(168U, location->second.values[0]);
- ASSERT_EQ(0xaadU, location->second.values[1]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_gnu_args_size) {
- this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x2e, 0x04});
- dwarf_loc_regs_t loc_regs;
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2002, &loc_regs));
- ASSERT_EQ(0x2002U, this->dmem_->cur_offset());
- ASSERT_EQ(0U, loc_regs.size());
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- loc_regs.clear();
- this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x2e, 0xa4, 0x80, 0x04});
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x5000, 0x5004, &loc_regs));
- ASSERT_EQ(0x5004U, this->dmem_->cur_offset());
- ASSERT_EQ(0U, loc_regs.size());
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_gnu_negative_offset_extended) {
- this->memory_.SetMemory(0x500, std::vector<uint8_t>{0x2f, 0x08, 0x10});
- dwarf_loc_regs_t loc_regs;
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x500, 0x503, &loc_regs));
- ASSERT_EQ(0x503U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- auto location = loc_regs.find(8);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type);
- ASSERT_EQ(static_cast<uint64_t>(-16), location->second.values[0]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- loc_regs.clear();
- this->memory_.SetMemory(0x1500, std::vector<uint8_t>{0x2f, 0x81, 0x02, 0xff, 0x01});
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x1500, 0x1505, &loc_regs));
- ASSERT_EQ(0x1505U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- location = loc_regs.find(257);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type);
- ASSERT_EQ(static_cast<uint64_t>(-255), location->second.values[0]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_register_override) {
- this->memory_.SetMemory(0x300, std::vector<uint8_t>{0x09, 0x02, 0x01, 0x09, 0x02, 0x04});
- dwarf_loc_regs_t loc_regs;
-
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x300, 0x306, &loc_regs));
- ASSERT_EQ(0x306U, this->dmem_->cur_offset());
- ASSERT_EQ(1U, loc_regs.size());
- auto location = loc_regs.find(2);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_REGISTER, location->second.type);
- ASSERT_EQ(4U, location->second.values[0]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-TYPED_TEST_P(DwarfCfaTest, cfa_aarch64_negate_ra_state) {
- this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x2d});
- dwarf_loc_regs_t loc_regs;
-
- ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs));
- ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->cfa_->LastErrorCode());
- ASSERT_EQ(0x2001U, this->dmem_->cur_offset());
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- ResetLogs();
- this->cfa_.reset(new DwarfCfa<TypeParam>(this->dmem_.get(), &this->fde_, ARCH_ARM64));
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs));
- ASSERT_EQ(0x2001U, this->dmem_->cur_offset());
-
- auto location = loc_regs.find(Arm64Reg::ARM64_PREG_RA_SIGN_STATE);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_PSEUDO_REGISTER, location->second.type);
- ASSERT_EQ(1U, location->second.values[0]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- // Verify that the value is set to 0 after another evaluation.
- ResetLogs();
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs));
- ASSERT_EQ(0x2001U, this->dmem_->cur_offset());
-
- location = loc_regs.find(Arm64Reg::ARM64_PREG_RA_SIGN_STATE);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_PSEUDO_REGISTER, location->second.type);
- ASSERT_EQ(0U, location->second.values[0]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-
- // Verify that the value is set to 1 again after a third op.
- ResetLogs();
- ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs));
- ASSERT_EQ(0x2001U, this->dmem_->cur_offset());
-
- location = loc_regs.find(Arm64Reg::ARM64_PREG_RA_SIGN_STATE);
- ASSERT_NE(loc_regs.end(), location);
- ASSERT_EQ(DWARF_LOCATION_PSEUDO_REGISTER, location->second.type);
- ASSERT_EQ(1U, location->second.values[0]);
-
- ASSERT_EQ("", GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-REGISTER_TYPED_TEST_SUITE_P(DwarfCfaTest, cfa_illegal, cfa_nop, cfa_offset, cfa_offset_extended,
- cfa_offset_extended_sf, cfa_restore, cfa_restore_extended, cfa_set_loc,
- cfa_advance_loc1, cfa_advance_loc2, cfa_advance_loc4, cfa_undefined,
- cfa_same, cfa_register, cfa_state, cfa_state_cfa_offset_restore,
- cfa_def_cfa, cfa_def_cfa_sf, cfa_def_cfa_register, cfa_def_cfa_offset,
- cfa_def_cfa_offset_sf, cfa_def_cfa_expression, cfa_expression,
- cfa_val_offset, cfa_val_offset_sf, cfa_val_expression,
- cfa_gnu_args_size, cfa_gnu_negative_offset_extended,
- cfa_register_override, cfa_aarch64_negate_ra_state);
-
-typedef ::testing::Types<uint32_t, uint64_t> DwarfCfaTestTypes;
-INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfCfaTest, DwarfCfaTestTypes);
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/DwarfDebugFrameTest.cpp b/libunwindstack/tests/DwarfDebugFrameTest.cpp
deleted file mode 100644
index fac8a0e..0000000
--- a/libunwindstack/tests/DwarfDebugFrameTest.cpp
+++ /dev/null
@@ -1,888 +0,0 @@
-/*
- * Copyright (C) 2016 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 <stdint.h>
-
-#include <vector>
-
-#include <gtest/gtest.h>
-
-#include <unwindstack/DwarfError.h>
-
-#include "DwarfDebugFrame.h"
-#include "DwarfEncoding.h"
-
-#include "LogFake.h"
-#include "MemoryFake.h"
-
-namespace unwindstack {
-
-template <typename TypeParam>
-class DwarfDebugFrameTest : public ::testing::Test {
- protected:
- void SetUp() override {
- memory_.Clear();
- debug_frame_ = new DwarfDebugFrame<TypeParam>(&memory_);
- ResetLogs();
- }
-
- void TearDown() override { delete debug_frame_; }
-
- MemoryFake memory_;
- DwarfDebugFrame<TypeParam>* debug_frame_ = nullptr;
-};
-TYPED_TEST_SUITE_P(DwarfDebugFrameTest);
-
-// NOTE: All test class variables need to be referenced as this->.
-
-static void SetCie32(MemoryFake* memory, uint64_t offset, uint32_t length,
- std::vector<uint8_t> data) {
- memory->SetData32(offset, length);
- offset += 4;
- // Indicates this is a cie.
- memory->SetData32(offset, 0xffffffff);
- offset += 4;
- memory->SetMemory(offset, data);
-}
-
-static void SetCie64(MemoryFake* memory, uint64_t offset, uint64_t length,
- std::vector<uint8_t> data) {
- memory->SetData32(offset, 0xffffffff);
- offset += 4;
- memory->SetData64(offset, length);
- offset += 8;
- // Indicates this is a cie.
- memory->SetData64(offset, 0xffffffffffffffffUL);
- offset += 8;
- memory->SetMemory(offset, data);
-}
-
-static void SetFde32(MemoryFake* memory, uint64_t offset, uint32_t length, uint64_t cie_offset,
- uint32_t pc_start, uint32_t pc_length, uint64_t segment_length = 0,
- std::vector<uint8_t>* data = nullptr) {
- memory->SetData32(offset, length);
- offset += 4;
- memory->SetData32(offset, cie_offset);
- offset += 4 + segment_length;
- memory->SetData32(offset, pc_start);
- offset += 4;
- memory->SetData32(offset, pc_length);
- if (data != nullptr) {
- offset += 4;
- memory->SetMemory(offset, *data);
- }
-}
-
-static void SetFde64(MemoryFake* memory, uint64_t offset, uint64_t length, uint64_t cie_offset,
- uint64_t pc_start, uint64_t pc_length, uint64_t segment_length = 0,
- std::vector<uint8_t>* data = nullptr) {
- memory->SetData32(offset, 0xffffffff);
- offset += 4;
- memory->SetData64(offset, length);
- offset += 8;
- memory->SetData64(offset, cie_offset);
- offset += 8 + segment_length;
- memory->SetData64(offset, pc_start);
- offset += 8;
- memory->SetData64(offset, pc_length);
- if (data != nullptr) {
- offset += 8;
- memory->SetMemory(offset, *data);
- }
-}
-
-static void SetFourFdes32(MemoryFake* memory) {
- SetCie32(memory, 0x5000, 0xfc, std::vector<uint8_t>{1, '\0', 0, 0, 1});
-
- // FDE 32 information.
- SetFde32(memory, 0x5100, 0xfc, 0, 0x1500, 0x200);
- SetFde32(memory, 0x5200, 0xfc, 0, 0x2500, 0x300);
-
- // CIE 32 information.
- SetCie32(memory, 0x5300, 0xfc, std::vector<uint8_t>{1, '\0', 0, 0, 1});
-
- // FDE 32 information.
- SetFde32(memory, 0x5400, 0xfc, 0x300, 0x3500, 0x400);
- SetFde32(memory, 0x5500, 0xfc, 0x300, 0x4500, 0x500);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetFdes32) {
- SetFourFdes32(&this->memory_);
- ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0));
-
- std::vector<const DwarfFde*> fdes;
- this->debug_frame_->GetFdes(&fdes);
-
- ASSERT_EQ(4U, fdes.size());
-
- EXPECT_EQ(0x5000U, fdes[0]->cie_offset);
- EXPECT_EQ(0x5110U, fdes[0]->cfa_instructions_offset);
- EXPECT_EQ(0x5200U, fdes[0]->cfa_instructions_end);
- EXPECT_EQ(0x1500U, fdes[0]->pc_start);
- EXPECT_EQ(0x1700U, fdes[0]->pc_end);
- EXPECT_EQ(0U, fdes[0]->lsda_address);
- EXPECT_TRUE(fdes[0]->cie != nullptr);
-
- EXPECT_EQ(0x5000U, fdes[1]->cie_offset);
- EXPECT_EQ(0x5210U, fdes[1]->cfa_instructions_offset);
- EXPECT_EQ(0x5300U, fdes[1]->cfa_instructions_end);
- EXPECT_EQ(0x2500U, fdes[1]->pc_start);
- EXPECT_EQ(0x2800U, fdes[1]->pc_end);
- EXPECT_EQ(0U, fdes[1]->lsda_address);
- EXPECT_TRUE(fdes[1]->cie != nullptr);
-
- EXPECT_EQ(0x5300U, fdes[2]->cie_offset);
- EXPECT_EQ(0x5410U, fdes[2]->cfa_instructions_offset);
- EXPECT_EQ(0x5500U, fdes[2]->cfa_instructions_end);
- EXPECT_EQ(0x3500U, fdes[2]->pc_start);
- EXPECT_EQ(0x3900U, fdes[2]->pc_end);
- EXPECT_EQ(0U, fdes[2]->lsda_address);
- EXPECT_TRUE(fdes[2]->cie != nullptr);
-
- EXPECT_EQ(0x5300U, fdes[3]->cie_offset);
- EXPECT_EQ(0x5510U, fdes[3]->cfa_instructions_offset);
- EXPECT_EQ(0x5600U, fdes[3]->cfa_instructions_end);
- EXPECT_EQ(0x4500U, fdes[3]->pc_start);
- EXPECT_EQ(0x4a00U, fdes[3]->pc_end);
- EXPECT_EQ(0U, fdes[3]->lsda_address);
- EXPECT_TRUE(fdes[3]->cie != nullptr);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetFdes32_after_GetFdeFromPc) {
- SetFourFdes32(&this->memory_);
- ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0));
-
- const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x3600);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x3500U, fde->pc_start);
- EXPECT_EQ(0x3900U, fde->pc_end);
-
- std::vector<const DwarfFde*> fdes;
- this->debug_frame_->GetFdes(&fdes);
- ASSERT_EQ(4U, fdes.size());
-
- // Verify that they got added in the correct order.
- EXPECT_EQ(0x1500U, fdes[0]->pc_start);
- EXPECT_EQ(0x1700U, fdes[0]->pc_end);
- EXPECT_EQ(0x2500U, fdes[1]->pc_start);
- EXPECT_EQ(0x2800U, fdes[1]->pc_end);
- EXPECT_EQ(0x3500U, fdes[2]->pc_start);
- EXPECT_EQ(0x3900U, fdes[2]->pc_end);
- EXPECT_EQ(0x4500U, fdes[3]->pc_start);
- EXPECT_EQ(0x4a00U, fdes[3]->pc_end);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetFdes32_not_in_section) {
- SetFourFdes32(&this->memory_);
- ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x500, 0));
-
- std::vector<const DwarfFde*> fdes;
- this->debug_frame_->GetFdes(&fdes);
-
- ASSERT_EQ(3U, fdes.size());
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromPc32) {
- SetFourFdes32(&this->memory_);
- ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0));
-
- const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x1600);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x1500U, fde->pc_start);
-
- fde = this->debug_frame_->GetFdeFromPc(0x2600);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x2500U, fde->pc_start);
-
- fde = this->debug_frame_->GetFdeFromPc(0x3600);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x3500U, fde->pc_start);
-
- fde = this->debug_frame_->GetFdeFromPc(0x4600);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x4500U, fde->pc_start);
-
- fde = this->debug_frame_->GetFdeFromPc(0);
- ASSERT_TRUE(fde == nullptr);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromPc32_reverse) {
- SetFourFdes32(&this->memory_);
- ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0));
-
- const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x4600);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x4500U, fde->pc_start);
-
- fde = this->debug_frame_->GetFdeFromPc(0x3600);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x3500U, fde->pc_start);
-
- fde = this->debug_frame_->GetFdeFromPc(0x2600);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x2500U, fde->pc_start);
-
- fde = this->debug_frame_->GetFdeFromPc(0x1600);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x1500U, fde->pc_start);
-
- fde = this->debug_frame_->GetFdeFromPc(0);
- ASSERT_TRUE(fde == nullptr);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromPc32_not_in_section) {
- SetFourFdes32(&this->memory_);
- ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x500, 0));
-
- const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x4600);
- ASSERT_TRUE(fde == nullptr);
-}
-
-static void SetFourFdes64(MemoryFake* memory) {
- // CIE 64 information.
- SetCie64(memory, 0x5000, 0xf4, std::vector<uint8_t>{1, '\0', 0, 0, 1});
-
- // FDE 64 information.
- SetFde64(memory, 0x5100, 0xf4, 0, 0x1500, 0x200);
- SetFde64(memory, 0x5200, 0xf4, 0, 0x2500, 0x300);
-
- // CIE 64 information.
- SetCie64(memory, 0x5300, 0xf4, std::vector<uint8_t>{1, '\0', 0, 0, 1});
-
- // FDE 64 information.
- SetFde64(memory, 0x5400, 0xf4, 0x300, 0x3500, 0x400);
- SetFde64(memory, 0x5500, 0xf4, 0x300, 0x4500, 0x500);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetFdes64) {
- SetFourFdes64(&this->memory_);
- ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0));
-
- std::vector<const DwarfFde*> fdes;
- this->debug_frame_->GetFdes(&fdes);
-
- ASSERT_EQ(4U, fdes.size());
-
- EXPECT_EQ(0x5000U, fdes[0]->cie_offset);
- EXPECT_EQ(0x5124U, fdes[0]->cfa_instructions_offset);
- EXPECT_EQ(0x5200U, fdes[0]->cfa_instructions_end);
- EXPECT_EQ(0x1500U, fdes[0]->pc_start);
- EXPECT_EQ(0x1700U, fdes[0]->pc_end);
- EXPECT_EQ(0U, fdes[0]->lsda_address);
- EXPECT_TRUE(fdes[0]->cie != nullptr);
-
- EXPECT_EQ(0x5000U, fdes[1]->cie_offset);
- EXPECT_EQ(0x5224U, fdes[1]->cfa_instructions_offset);
- EXPECT_EQ(0x5300U, fdes[1]->cfa_instructions_end);
- EXPECT_EQ(0x2500U, fdes[1]->pc_start);
- EXPECT_EQ(0x2800U, fdes[1]->pc_end);
- EXPECT_EQ(0U, fdes[1]->lsda_address);
- EXPECT_TRUE(fdes[1]->cie != nullptr);
-
- EXPECT_EQ(0x5300U, fdes[2]->cie_offset);
- EXPECT_EQ(0x5424U, fdes[2]->cfa_instructions_offset);
- EXPECT_EQ(0x5500U, fdes[2]->cfa_instructions_end);
- EXPECT_EQ(0x3500U, fdes[2]->pc_start);
- EXPECT_EQ(0x3900U, fdes[2]->pc_end);
- EXPECT_EQ(0U, fdes[2]->lsda_address);
- EXPECT_TRUE(fdes[2]->cie != nullptr);
-
- EXPECT_EQ(0x5300U, fdes[3]->cie_offset);
- EXPECT_EQ(0x5524U, fdes[3]->cfa_instructions_offset);
- EXPECT_EQ(0x5600U, fdes[3]->cfa_instructions_end);
- EXPECT_EQ(0x4500U, fdes[3]->pc_start);
- EXPECT_EQ(0x4a00U, fdes[3]->pc_end);
- EXPECT_EQ(0U, fdes[3]->lsda_address);
- EXPECT_TRUE(fdes[3]->cie != nullptr);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetFdes64_after_GetFdeFromPc) {
- SetFourFdes64(&this->memory_);
- ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0));
-
- const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x2600);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x2500U, fde->pc_start);
- EXPECT_EQ(0x2800U, fde->pc_end);
-
- std::vector<const DwarfFde*> fdes;
- this->debug_frame_->GetFdes(&fdes);
- ASSERT_EQ(4U, fdes.size());
-
- // Verify that they got added in the correct order.
- EXPECT_EQ(0x1500U, fdes[0]->pc_start);
- EXPECT_EQ(0x1700U, fdes[0]->pc_end);
- EXPECT_EQ(0x2500U, fdes[1]->pc_start);
- EXPECT_EQ(0x2800U, fdes[1]->pc_end);
- EXPECT_EQ(0x3500U, fdes[2]->pc_start);
- EXPECT_EQ(0x3900U, fdes[2]->pc_end);
- EXPECT_EQ(0x4500U, fdes[3]->pc_start);
- EXPECT_EQ(0x4a00U, fdes[3]->pc_end);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetFdes64_not_in_section) {
- SetFourFdes64(&this->memory_);
- ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x500, 0));
-
- std::vector<const DwarfFde*> fdes;
- this->debug_frame_->GetFdes(&fdes);
-
- ASSERT_EQ(3U, fdes.size());
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromPc64) {
- SetFourFdes64(&this->memory_);
- ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0));
-
- const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x1600);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x1500U, fde->pc_start);
-
- fde = this->debug_frame_->GetFdeFromPc(0x2600);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x2500U, fde->pc_start);
-
- fde = this->debug_frame_->GetFdeFromPc(0x3600);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x3500U, fde->pc_start);
-
- fde = this->debug_frame_->GetFdeFromPc(0x4600);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x4500U, fde->pc_start);
-
- fde = this->debug_frame_->GetFdeFromPc(0);
- ASSERT_TRUE(fde == nullptr);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromPc64_reverse) {
- SetFourFdes64(&this->memory_);
- ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0));
-
- const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x4600);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x4500U, fde->pc_start);
-
- fde = this->debug_frame_->GetFdeFromPc(0x3600);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x3500U, fde->pc_start);
-
- fde = this->debug_frame_->GetFdeFromPc(0x2600);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x2500U, fde->pc_start);
-
- fde = this->debug_frame_->GetFdeFromPc(0x1600);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x1500U, fde->pc_start);
-
- fde = this->debug_frame_->GetFdeFromPc(0);
- ASSERT_TRUE(fde == nullptr);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromPc64_not_in_section) {
- SetFourFdes64(&this->memory_);
- ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x500, 0));
-
- const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x4600);
- ASSERT_TRUE(fde == nullptr);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetCieFde32) {
- SetCie32(&this->memory_, 0xf000, 0x100, std::vector<uint8_t>{1, '\0', 4, 8, 0x20});
- SetFde32(&this->memory_, 0x14000, 0x20, 0xf000, 0x9000, 0x100);
-
- const DwarfFde* fde = this->debug_frame_->GetFdeFromOffset(0x14000);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x14010U, fde->cfa_instructions_offset);
- EXPECT_EQ(0x14024U, fde->cfa_instructions_end);
- EXPECT_EQ(0x9000U, fde->pc_start);
- EXPECT_EQ(0x9100U, fde->pc_end);
- EXPECT_EQ(0xf000U, fde->cie_offset);
- EXPECT_EQ(0U, fde->lsda_address);
-
- ASSERT_TRUE(fde->cie != nullptr);
- EXPECT_EQ(1U, fde->cie->version);
- EXPECT_EQ(DW_EH_PE_sdata4, fde->cie->fde_address_encoding);
- EXPECT_EQ(DW_EH_PE_omit, fde->cie->lsda_encoding);
- EXPECT_EQ(0U, fde->cie->segment_size);
- EXPECT_EQ(1U, fde->cie->augmentation_string.size());
- EXPECT_EQ('\0', fde->cie->augmentation_string[0]);
- EXPECT_EQ(0U, fde->cie->personality_handler);
- EXPECT_EQ(0xf00dU, fde->cie->cfa_instructions_offset);
- EXPECT_EQ(0xf104U, fde->cie->cfa_instructions_end);
- EXPECT_EQ(4U, fde->cie->code_alignment_factor);
- EXPECT_EQ(8, fde->cie->data_alignment_factor);
- EXPECT_EQ(0x20U, fde->cie->return_address_register);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetCieFde64) {
- SetCie64(&this->memory_, 0x6000, 0x100, std::vector<uint8_t>{1, '\0', 4, 8, 0x20});
- SetFde64(&this->memory_, 0x8000, 0x200, 0x6000, 0x5000, 0x300);
-
- const DwarfFde* fde = this->debug_frame_->GetFdeFromOffset(0x8000);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x8024U, fde->cfa_instructions_offset);
- EXPECT_EQ(0x820cU, fde->cfa_instructions_end);
- EXPECT_EQ(0x5000U, fde->pc_start);
- EXPECT_EQ(0x5300U, fde->pc_end);
- EXPECT_EQ(0x6000U, fde->cie_offset);
- EXPECT_EQ(0U, fde->lsda_address);
-
- ASSERT_TRUE(fde->cie != nullptr);
- EXPECT_EQ(1U, fde->cie->version);
- EXPECT_EQ(DW_EH_PE_sdata8, fde->cie->fde_address_encoding);
- EXPECT_EQ(DW_EH_PE_omit, fde->cie->lsda_encoding);
- EXPECT_EQ(0U, fde->cie->segment_size);
- EXPECT_EQ(1U, fde->cie->augmentation_string.size());
- EXPECT_EQ('\0', fde->cie->augmentation_string[0]);
- EXPECT_EQ(0U, fde->cie->personality_handler);
- EXPECT_EQ(0x6019U, fde->cie->cfa_instructions_offset);
- EXPECT_EQ(0x610cU, fde->cie->cfa_instructions_end);
- EXPECT_EQ(4U, fde->cie->code_alignment_factor);
- EXPECT_EQ(8, fde->cie->data_alignment_factor);
- EXPECT_EQ(0x20U, fde->cie->return_address_register);
-}
-
-static void VerifyCieVersion(const DwarfCie* cie, uint8_t version, uint8_t segment_size,
- uint8_t fde_encoding, uint64_t return_address, uint64_t start_offset,
- uint64_t end_offset) {
- EXPECT_EQ(version, cie->version);
- EXPECT_EQ(fde_encoding, cie->fde_address_encoding);
- EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
- EXPECT_EQ(segment_size, cie->segment_size);
- EXPECT_EQ(1U, cie->augmentation_string.size());
- EXPECT_EQ('\0', cie->augmentation_string[0]);
- EXPECT_EQ(0U, cie->personality_handler);
- EXPECT_EQ(4U, cie->code_alignment_factor);
- EXPECT_EQ(8, cie->data_alignment_factor);
- EXPECT_EQ(return_address, cie->return_address_register);
- EXPECT_EQ(0x5000U + start_offset, cie->cfa_instructions_offset);
- EXPECT_EQ(0x5000U + end_offset, cie->cfa_instructions_end);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset32_cie_cached) {
- SetCie32(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{1, '\0', 4, 8, 0x20});
- const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
- EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
- ASSERT_TRUE(cie != nullptr);
- VerifyCieVersion(cie, 1, 0, DW_EH_PE_sdata4, 0x20, 0xd, 0x104);
-
- std::vector<uint8_t> zero(0x100, 0);
- this->memory_.SetMemory(0x5000, zero);
- cie = this->debug_frame_->GetCieFromOffset(0x5000);
- EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
- ASSERT_TRUE(cie != nullptr);
- VerifyCieVersion(cie, 1, 0, DW_EH_PE_sdata4, 0x20, 0xd, 0x104);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset64_cie_cached) {
- SetCie64(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{1, '\0', 4, 8, 0x20});
- const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
- EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
- ASSERT_TRUE(cie != nullptr);
- VerifyCieVersion(cie, 1, 0, DW_EH_PE_sdata8, 0x20, 0x19, 0x10c);
-
- std::vector<uint8_t> zero(0x100, 0);
- this->memory_.SetMemory(0x5000, zero);
- cie = this->debug_frame_->GetCieFromOffset(0x5000);
- EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
- ASSERT_TRUE(cie != nullptr);
- VerifyCieVersion(cie, 1, 0, DW_EH_PE_sdata8, 0x20, 0x19, 0x10c);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset32_version1) {
- SetCie32(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{1, '\0', 4, 8, 0x20});
- const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
- EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
- ASSERT_TRUE(cie != nullptr);
- VerifyCieVersion(cie, 1, 0, DW_EH_PE_sdata4, 0x20, 0xd, 0x104);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset64_version1) {
- SetCie64(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{1, '\0', 4, 8, 0x20});
- const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
- EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
- ASSERT_TRUE(cie != nullptr);
- VerifyCieVersion(cie, 1, 0, DW_EH_PE_sdata8, 0x20, 0x19, 0x10c);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset32_version3) {
- SetCie32(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{3, '\0', 4, 8, 0x81, 3});
- const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
- EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
- ASSERT_TRUE(cie != nullptr);
- VerifyCieVersion(cie, 3, 0, DW_EH_PE_sdata4, 0x181, 0xe, 0x104);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset64_version3) {
- SetCie64(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{3, '\0', 4, 8, 0x81, 3});
- const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
- EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
- ASSERT_TRUE(cie != nullptr);
- VerifyCieVersion(cie, 3, 0, DW_EH_PE_sdata8, 0x181, 0x1a, 0x10c);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset32_version4) {
- SetCie32(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{4, '\0', 0, 10, 4, 8, 0x81, 3});
- const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
- EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
- ASSERT_TRUE(cie != nullptr);
- VerifyCieVersion(cie, 4, 10, DW_EH_PE_sdata4, 0x181, 0x10, 0x104);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset64_version4) {
- SetCie64(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{4, '\0', 0, 10, 4, 8, 0x81, 3});
- const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
- EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
- ASSERT_TRUE(cie != nullptr);
- VerifyCieVersion(cie, 4, 10, DW_EH_PE_sdata8, 0x181, 0x1c, 0x10c);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset32_version5) {
- SetCie32(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{5, '\0', 0, 10, 4, 8, 0x81, 3});
- const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
- EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
- ASSERT_TRUE(cie != nullptr);
- VerifyCieVersion(cie, 5, 10, DW_EH_PE_sdata4, 0x181, 0x10, 0x104);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset64_version5) {
- SetCie64(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{5, '\0', 0, 10, 4, 8, 0x81, 3});
- const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
- EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
- ASSERT_TRUE(cie != nullptr);
- VerifyCieVersion(cie, 5, 10, DW_EH_PE_sdata8, 0x181, 0x1c, 0x10c);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset_version_invalid) {
- SetCie32(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{0, '\0', 1, 2, 3, 4, 5, 6, 7});
- ASSERT_TRUE(this->debug_frame_->GetCieFromOffset(0x5000) == nullptr);
- EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->debug_frame_->LastErrorCode());
- SetCie64(&this->memory_, 0x6000, 0x100, std::vector<uint8_t>{0, '\0', 1, 2, 3, 4, 5, 6, 7});
- ASSERT_TRUE(this->debug_frame_->GetCieFromOffset(0x6000) == nullptr);
- EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->debug_frame_->LastErrorCode());
-
- SetCie32(&this->memory_, 0x7000, 0x100, std::vector<uint8_t>{6, '\0', 1, 2, 3, 4, 5, 6, 7});
- ASSERT_TRUE(this->debug_frame_->GetCieFromOffset(0x7000) == nullptr);
- EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->debug_frame_->LastErrorCode());
- SetCie64(&this->memory_, 0x8000, 0x100, std::vector<uint8_t>{6, '\0', 1, 2, 3, 4, 5, 6, 7});
- ASSERT_TRUE(this->debug_frame_->GetCieFromOffset(0x8000) == nullptr);
- EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->debug_frame_->LastErrorCode());
-}
-
-static void VerifyCieAugment(const DwarfCie* cie, uint64_t inst_offset, uint64_t inst_end) {
- EXPECT_EQ(1U, cie->version);
- EXPECT_EQ(DW_EH_PE_udata2, cie->fde_address_encoding);
- EXPECT_EQ(DW_EH_PE_textrel | DW_EH_PE_udata2, cie->lsda_encoding);
- EXPECT_EQ(0U, cie->segment_size);
- EXPECT_EQ(5U, cie->augmentation_string.size());
- EXPECT_EQ('z', cie->augmentation_string[0]);
- EXPECT_EQ('L', cie->augmentation_string[1]);
- EXPECT_EQ('P', cie->augmentation_string[2]);
- EXPECT_EQ('R', cie->augmentation_string[3]);
- EXPECT_EQ('\0', cie->augmentation_string[4]);
- EXPECT_EQ(0x12345678U, cie->personality_handler);
- EXPECT_EQ(4U, cie->code_alignment_factor);
- EXPECT_EQ(8, cie->data_alignment_factor);
- EXPECT_EQ(0x10U, cie->return_address_register);
- EXPECT_EQ(inst_offset, cie->cfa_instructions_offset);
- EXPECT_EQ(inst_end, cie->cfa_instructions_end);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset32_augment) {
- SetCie32(&this->memory_, 0x5000, 0x100,
- std::vector<uint8_t>{/* version */ 1,
- /* augment string */ 'z', 'L', 'P', 'R', '\0',
- /* code alignment factor */ 4,
- /* data alignment factor */ 8,
- /* return address register */ 0x10,
- /* augment length */ 0xf,
- /* L data */ DW_EH_PE_textrel | DW_EH_PE_udata2,
- /* P data */ DW_EH_PE_udata4, 0x78, 0x56, 0x34, 0x12,
- /* R data */ DW_EH_PE_udata2});
-
- const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
- ASSERT_TRUE(cie != nullptr);
- VerifyCieAugment(cie, 0x5021, 0x5104);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset64_augment) {
- SetCie64(&this->memory_, 0x5000, 0x100,
- std::vector<uint8_t>{/* version */ 1,
- /* augment string */ 'z', 'L', 'P', 'R', '\0',
- /* code alignment factor */ 4,
- /* data alignment factor */ 8,
- /* return address register */ 0x10,
- /* augment length */ 0xf,
- /* L data */ DW_EH_PE_textrel | DW_EH_PE_udata2,
- /* P data */ DW_EH_PE_udata4, 0x78, 0x56, 0x34, 0x12,
- /* R data */ DW_EH_PE_udata2});
-
- const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
- ASSERT_TRUE(cie != nullptr);
- VerifyCieAugment(cie, 0x502d, 0x510c);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromOffset32_augment) {
- SetCie32(&this->memory_, 0x5000, 0xfc,
- std::vector<uint8_t>{/* version */ 4,
- /* augment string */ 'z', '\0',
- /* address size */ 8,
- /* segment size */ 0x10,
- /* code alignment factor */ 16,
- /* data alignment factor */ 32,
- /* return address register */ 10,
- /* augment length */ 0x0});
-
- std::vector<uint8_t> data{/* augment length */ 0x80, 0x3};
- SetFde32(&this->memory_, 0x5200, 0x300, 0x5000, 0x4300, 0x300, 0x10, &data);
-
- const DwarfFde* fde = this->debug_frame_->GetFdeFromOffset(0x5200);
- ASSERT_TRUE(fde != nullptr);
- ASSERT_TRUE(fde->cie != nullptr);
- EXPECT_EQ(4U, fde->cie->version);
- EXPECT_EQ(0x5000U, fde->cie_offset);
- EXPECT_EQ(0x53a2U, fde->cfa_instructions_offset);
- EXPECT_EQ(0x5504U, fde->cfa_instructions_end);
- EXPECT_EQ(0x4300U, fde->pc_start);
- EXPECT_EQ(0x4600U, fde->pc_end);
- EXPECT_EQ(0U, fde->lsda_address);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromOffset64_augment) {
- SetCie64(&this->memory_, 0x5000, 0xfc,
- std::vector<uint8_t>{/* version */ 4,
- /* augment string */ 'z', '\0',
- /* address size */ 8,
- /* segment size */ 0x10,
- /* code alignment factor */ 16,
- /* data alignment factor */ 32,
- /* return address register */ 10,
- /* augment length */ 0x0});
-
- std::vector<uint8_t> data{/* augment length */ 0x80, 0x3};
- SetFde64(&this->memory_, 0x5200, 0x300, 0x5000, 0x4300, 0x300, 0x10, &data);
-
- const DwarfFde* fde = this->debug_frame_->GetFdeFromOffset(0x5200);
- ASSERT_TRUE(fde != nullptr);
- ASSERT_TRUE(fde->cie != nullptr);
- EXPECT_EQ(4U, fde->cie->version);
- EXPECT_EQ(0x5000U, fde->cie_offset);
- EXPECT_EQ(0x53b6U, fde->cfa_instructions_offset);
- EXPECT_EQ(0x550cU, fde->cfa_instructions_end);
- EXPECT_EQ(0x4300U, fde->pc_start);
- EXPECT_EQ(0x4600U, fde->pc_end);
- EXPECT_EQ(0U, fde->lsda_address);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromOffset32_lsda_address) {
- SetCie32(&this->memory_, 0x5000, 0xfc,
- std::vector<uint8_t>{/* version */ 1,
- /* augment string */ 'z', 'L', '\0',
- /* address size */ 8,
- /* code alignment factor */ 16,
- /* data alignment factor */ 32,
- /* return address register */ 10,
- /* augment length */ 0x2,
- /* L data */ DW_EH_PE_udata2});
-
- std::vector<uint8_t> data{/* augment length */ 0x80, 0x3,
- /* lsda address */ 0x20, 0x45};
- SetFde32(&this->memory_, 0x5200, 0x300, 0x5000, 0x4300, 0x300, 0, &data);
-
- const DwarfFde* fde = this->debug_frame_->GetFdeFromOffset(0x5200);
- ASSERT_TRUE(fde != nullptr);
- ASSERT_TRUE(fde->cie != nullptr);
- EXPECT_EQ(1U, fde->cie->version);
- EXPECT_EQ(0x5000U, fde->cie_offset);
- EXPECT_EQ(0x5392U, fde->cfa_instructions_offset);
- EXPECT_EQ(0x5504U, fde->cfa_instructions_end);
- EXPECT_EQ(0x4300U, fde->pc_start);
- EXPECT_EQ(0x4600U, fde->pc_end);
- EXPECT_EQ(0x4520U, fde->lsda_address);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromOffset64_lsda_address) {
- SetCie64(&this->memory_, 0x5000, 0xfc,
- std::vector<uint8_t>{/* version */ 1,
- /* augment string */ 'z', 'L', '\0',
- /* address size */ 8,
- /* code alignment factor */ 16,
- /* data alignment factor */ 32,
- /* return address register */ 10,
- /* augment length */ 0x2,
- /* L data */ DW_EH_PE_udata2});
-
- std::vector<uint8_t> data{/* augment length */ 0x80, 0x3,
- /* lsda address */ 0x20, 0x45};
- SetFde64(&this->memory_, 0x5200, 0x300, 0x5000, 0x4300, 0x300, 0, &data);
-
- const DwarfFde* fde = this->debug_frame_->GetFdeFromOffset(0x5200);
- ASSERT_TRUE(fde != nullptr);
- ASSERT_TRUE(fde->cie != nullptr);
- EXPECT_EQ(1U, fde->cie->version);
- EXPECT_EQ(0x5000U, fde->cie_offset);
- EXPECT_EQ(0x53a6U, fde->cfa_instructions_offset);
- EXPECT_EQ(0x550cU, fde->cfa_instructions_end);
- EXPECT_EQ(0x4300U, fde->pc_start);
- EXPECT_EQ(0x4600U, fde->pc_end);
- EXPECT_EQ(0x4520U, fde->lsda_address);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromPc_interleaved) {
- SetCie32(&this->memory_, 0x5000, 0xfc, std::vector<uint8_t>{1, '\0', 0, 0, 1});
-
- // FDE 0 (0x100 - 0x200)
- SetFde32(&this->memory_, 0x5100, 0xfc, 0, 0x100, 0x100);
- // FDE 1 (0x300 - 0x500)
- SetFde32(&this->memory_, 0x5200, 0xfc, 0, 0x300, 0x200);
- // FDE 2 (0x700 - 0x800)
- SetFde32(&this->memory_, 0x5300, 0xfc, 0, 0x700, 0x100);
- // FDE 3 (0xa00 - 0xb00)
- SetFde32(&this->memory_, 0x5400, 0xfc, 0, 0xa00, 0x100);
- // FDE 4 (0x100 - 0xb00)
- SetFde32(&this->memory_, 0x5500, 0xfc, 0, 0x150, 0xa00);
- // FDE 5 (0x50 - 0xa0)
- SetFde32(&this->memory_, 0x5600, 0xfc, 0, 0x50, 0x50);
- // FDE 6 (0x0 - 0x50)
- SetFde32(&this->memory_, 0x5700, 0xfc, 0, 0, 0x50);
-
- this->debug_frame_->Init(0x5000, 0x800, 0);
-
- // Force reading all entries so no entries are found.
- const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0xfffff);
- ASSERT_TRUE(fde == nullptr);
-
- // 0x50 - 0xa0 FDE 5
- fde = this->debug_frame_->GetFdeFromPc(0x60);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x50U, fde->pc_start);
- EXPECT_EQ(0xa0U, fde->pc_end);
-
- // 0x0 - 0x50 FDE 6
- fde = this->debug_frame_->GetFdeFromPc(0x10);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0U, fde->pc_start);
- EXPECT_EQ(0x50U, fde->pc_end);
-
- // 0x100 - 0x200 FDE 0
- fde = this->debug_frame_->GetFdeFromPc(0x170);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x100U, fde->pc_start);
- EXPECT_EQ(0x200U, fde->pc_end);
-
- // 0x200 - 0x300 FDE 4
- fde = this->debug_frame_->GetFdeFromPc(0x210);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x150U, fde->pc_start);
- EXPECT_EQ(0xb50U, fde->pc_end);
-
- // 0x300 - 0x500 FDE 1
- fde = this->debug_frame_->GetFdeFromPc(0x310);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x300U, fde->pc_start);
- EXPECT_EQ(0x500U, fde->pc_end);
-
- // 0x700 - 0x800 FDE 2
- fde = this->debug_frame_->GetFdeFromPc(0x790);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x700U, fde->pc_start);
- EXPECT_EQ(0x800U, fde->pc_end);
-
- // 0x800 - 0x900 FDE 4
- fde = this->debug_frame_->GetFdeFromPc(0x850);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x150U, fde->pc_start);
- EXPECT_EQ(0xb50U, fde->pc_end);
-
- // 0xa00 - 0xb00 FDE 3
- fde = this->debug_frame_->GetFdeFromPc(0xa35);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0xa00U, fde->pc_start);
- EXPECT_EQ(0xb00U, fde->pc_end);
-
- // 0xb00 - 0xb50 FDE 4
- fde = this->debug_frame_->GetFdeFromPc(0xb20);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x150U, fde->pc_start);
- EXPECT_EQ(0xb50U, fde->pc_end);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromPc_overlap) {
- SetCie32(&this->memory_, 0x5000, 0xfc, std::vector<uint8_t>{1, '\0', 0, 0, 1});
-
- // FDE 0 (0x100 - 0x200)
- SetFde32(&this->memory_, 0x5100, 0xfc, 0, 0x100, 0x100);
- // FDE 1 (0x50 - 0x550)
- SetFde32(&this->memory_, 0x5200, 0xfc, 0, 0x50, 0x500);
- // FDE 2 (0x00 - 0x800)
- SetFde32(&this->memory_, 0x5300, 0xfc, 0, 0x0, 0x800);
-
- this->debug_frame_->Init(0x5000, 0x400, 0);
-
- // Force reading all entries so no entries are found.
- const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0xfffff);
- ASSERT_TRUE(fde == nullptr);
-
- // 0x0 - 0x50 FDE 2
- fde = this->debug_frame_->GetFdeFromPc(0x10);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x0U, fde->pc_start);
- EXPECT_EQ(0x800U, fde->pc_end);
-
- // 0x50 - 0x100 FDE 1
- fde = this->debug_frame_->GetFdeFromPc(0x60);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x50U, fde->pc_start);
- EXPECT_EQ(0x550U, fde->pc_end);
-
- // 0x100 - 0x200 FDE 0
- fde = this->debug_frame_->GetFdeFromPc(0x170);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x100U, fde->pc_start);
- EXPECT_EQ(0x200U, fde->pc_end);
-
- // 0x200 - 0x550 FDE 1
- fde = this->debug_frame_->GetFdeFromPc(0x210);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x50U, fde->pc_start);
- EXPECT_EQ(0x550U, fde->pc_end);
-
- // 0x550 - 0x800 FDE 2
- fde = this->debug_frame_->GetFdeFromPc(0x580);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x0U, fde->pc_start);
- EXPECT_EQ(0x800U, fde->pc_end);
-
- fde = this->debug_frame_->GetFdeFromPc(0x810);
- ASSERT_TRUE(fde == nullptr);
-}
-
-REGISTER_TYPED_TEST_SUITE_P(
- DwarfDebugFrameTest, GetFdes32, GetFdes32_after_GetFdeFromPc, GetFdes32_not_in_section,
- GetFdeFromPc32, GetFdeFromPc32_reverse, GetFdeFromPc32_not_in_section, GetFdes64,
- GetFdes64_after_GetFdeFromPc, GetFdes64_not_in_section, GetFdeFromPc64, GetFdeFromPc64_reverse,
- GetFdeFromPc64_not_in_section, GetCieFde32, GetCieFde64, GetCieFromOffset32_cie_cached,
- GetCieFromOffset64_cie_cached, GetCieFromOffset32_version1, GetCieFromOffset64_version1,
- GetCieFromOffset32_version3, GetCieFromOffset64_version3, GetCieFromOffset32_version4,
- GetCieFromOffset64_version4, GetCieFromOffset32_version5, GetCieFromOffset64_version5,
- GetCieFromOffset_version_invalid, GetCieFromOffset32_augment, GetCieFromOffset64_augment,
- GetFdeFromOffset32_augment, GetFdeFromOffset64_augment, GetFdeFromOffset32_lsda_address,
- GetFdeFromOffset64_lsda_address, GetFdeFromPc_interleaved, GetFdeFromPc_overlap);
-
-typedef ::testing::Types<uint32_t, uint64_t> DwarfDebugFrameTestTypes;
-INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfDebugFrameTest, DwarfDebugFrameTestTypes);
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/DwarfEhFrameTest.cpp b/libunwindstack/tests/DwarfEhFrameTest.cpp
deleted file mode 100644
index 46a25a4..0000000
--- a/libunwindstack/tests/DwarfEhFrameTest.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2016 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 <stdint.h>
-
-#include <gtest/gtest.h>
-
-#include <unwindstack/DwarfError.h>
-
-#include "DwarfEhFrame.h"
-#include "DwarfEncoding.h"
-
-#include "LogFake.h"
-#include "MemoryFake.h"
-
-namespace unwindstack {
-
-template <typename TypeParam>
-class DwarfEhFrameTest : public ::testing::Test {
- protected:
- void SetUp() override {
- memory_.Clear();
- eh_frame_ = new DwarfEhFrame<TypeParam>(&memory_);
- ResetLogs();
- }
-
- void TearDown() override { delete eh_frame_; }
-
- MemoryFake memory_;
- DwarfEhFrame<TypeParam>* eh_frame_ = nullptr;
-};
-TYPED_TEST_SUITE_P(DwarfEhFrameTest);
-
-// NOTE: All test class variables need to be referenced as this->.
-
-// Only verify different cie/fde format. All other DwarfSection corner
-// cases are tested in DwarfDebugFrameTest.cpp.
-
-TYPED_TEST_P(DwarfEhFrameTest, GetFdeCieFromOffset32) {
- // CIE 32 information.
- this->memory_.SetData32(0x5000, 0xfc);
- // Indicates this is a cie for eh_frame.
- this->memory_.SetData32(0x5004, 0);
- this->memory_.SetMemory(0x5008, std::vector<uint8_t>{1, '\0', 16, 32, 1});
-
- // FDE 32 information.
- this->memory_.SetData32(0x5100, 0xfc);
- this->memory_.SetData32(0x5104, 0x104);
- this->memory_.SetData32(0x5108, 0x1500);
- this->memory_.SetData32(0x510c, 0x200);
-
- const DwarfFde* fde = this->eh_frame_->GetFdeFromOffset(0x5100);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x5000U, fde->cie_offset);
- EXPECT_EQ(0x5110U, fde->cfa_instructions_offset);
- EXPECT_EQ(0x5200U, fde->cfa_instructions_end);
- EXPECT_EQ(0x6608U, fde->pc_start);
- EXPECT_EQ(0x6808U, fde->pc_end);
- EXPECT_EQ(0U, fde->lsda_address);
-
- const DwarfCie* cie = fde->cie;
- ASSERT_TRUE(cie != nullptr);
- EXPECT_EQ(1U, cie->version);
- EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
- EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
- EXPECT_EQ(0U, cie->segment_size);
- EXPECT_EQ('\0', cie->augmentation_string[0]);
- EXPECT_EQ(0U, cie->personality_handler);
- EXPECT_EQ(0x500dU, cie->cfa_instructions_offset);
- EXPECT_EQ(0x5100U, cie->cfa_instructions_end);
- EXPECT_EQ(16U, cie->code_alignment_factor);
- EXPECT_EQ(32U, cie->data_alignment_factor);
- EXPECT_EQ(1U, cie->return_address_register);
-}
-
-TYPED_TEST_P(DwarfEhFrameTest, GetFdeCieFromOffset64) {
- // CIE 64 information.
- this->memory_.SetData32(0x5000, 0xffffffff);
- this->memory_.SetData64(0x5004, 0xfc);
- // Indicates this is a cie for eh_frame.
- this->memory_.SetData64(0x500c, 0);
- this->memory_.SetMemory(0x5014, std::vector<uint8_t>{1, '\0', 16, 32, 1});
-
- // FDE 64 information.
- this->memory_.SetData32(0x5100, 0xffffffff);
- this->memory_.SetData64(0x5104, 0xfc);
- this->memory_.SetData64(0x510c, 0x10c);
- this->memory_.SetData64(0x5114, 0x1500);
- this->memory_.SetData64(0x511c, 0x200);
-
- const DwarfFde* fde = this->eh_frame_->GetFdeFromOffset(0x5100);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x5000U, fde->cie_offset);
- EXPECT_EQ(0x5124U, fde->cfa_instructions_offset);
- EXPECT_EQ(0x5208U, fde->cfa_instructions_end);
- EXPECT_EQ(0x6618U, fde->pc_start);
- EXPECT_EQ(0x6818U, fde->pc_end);
- EXPECT_EQ(0U, fde->lsda_address);
-
- const DwarfCie* cie = fde->cie;
- ASSERT_TRUE(cie != nullptr);
- EXPECT_EQ(1U, cie->version);
- EXPECT_EQ(DW_EH_PE_sdata8, cie->fde_address_encoding);
- EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
- EXPECT_EQ(0U, cie->segment_size);
- EXPECT_EQ('\0', cie->augmentation_string[0]);
- EXPECT_EQ(0U, cie->personality_handler);
- EXPECT_EQ(0x5019U, cie->cfa_instructions_offset);
- EXPECT_EQ(0x5108U, cie->cfa_instructions_end);
- EXPECT_EQ(16U, cie->code_alignment_factor);
- EXPECT_EQ(32U, cie->data_alignment_factor);
- EXPECT_EQ(1U, cie->return_address_register);
-}
-
-REGISTER_TYPED_TEST_SUITE_P(DwarfEhFrameTest, GetFdeCieFromOffset32, GetFdeCieFromOffset64);
-
-typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameTestTypes;
-INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfEhFrameTest, DwarfEhFrameTestTypes);
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp b/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp
deleted file mode 100644
index 6aa3867..0000000
--- a/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp
+++ /dev/null
@@ -1,557 +0,0 @@
-/*
- * Copyright (C) 2016 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 <stdint.h>
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include <unwindstack/DwarfError.h>
-
-#include "DwarfEhFrameWithHdr.h"
-#include "DwarfEncoding.h"
-
-#include "LogFake.h"
-#include "MemoryFake.h"
-
-namespace unwindstack {
-
-template <typename TypeParam>
-class TestDwarfEhFrameWithHdr : public DwarfEhFrameWithHdr<TypeParam> {
- public:
- TestDwarfEhFrameWithHdr(Memory* memory) : DwarfEhFrameWithHdr<TypeParam>(memory) {}
- ~TestDwarfEhFrameWithHdr() = default;
-
- void TestSetTableEncoding(uint8_t encoding) { this->table_encoding_ = encoding; }
- void TestSetHdrEntriesOffset(uint64_t offset) { this->hdr_entries_offset_ = offset; }
- void TestSetHdrEntriesDataOffset(uint64_t offset) { this->hdr_entries_data_offset_ = offset; }
- void TestSetTableEntrySize(size_t size) { this->table_entry_size_ = size; }
-
- void TestSetFdeCount(uint64_t count) { this->fde_count_ = count; }
- void TestSetFdeInfo(uint64_t index, const typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo& info) {
- this->fde_info_[index] = info;
- }
-
- uint8_t TestGetVersion() { return this->version_; }
- uint8_t TestGetTableEncoding() { return this->table_encoding_; }
- uint64_t TestGetTableEntrySize() { return this->table_entry_size_; }
- uint64_t TestGetFdeCount() { return this->fde_count_; }
- uint64_t TestGetHdrEntriesOffset() { return this->hdr_entries_offset_; }
- uint64_t TestGetHdrEntriesDataOffset() { return this->hdr_entries_data_offset_; }
-};
-
-template <typename TypeParam>
-class DwarfEhFrameWithHdrTest : public ::testing::Test {
- protected:
- void SetUp() override {
- memory_.Clear();
- eh_frame_ = new TestDwarfEhFrameWithHdr<TypeParam>(&memory_);
- ResetLogs();
- }
-
- void TearDown() override { delete eh_frame_; }
-
- MemoryFake memory_;
- TestDwarfEhFrameWithHdr<TypeParam>* eh_frame_ = nullptr;
-};
-TYPED_TEST_SUITE_P(DwarfEhFrameWithHdrTest);
-
-// NOTE: All test class variables need to be referenced as this->.
-
-TYPED_TEST_P(DwarfEhFrameWithHdrTest, Init) {
- this->memory_.SetMemory(
- 0x1000, std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4, DW_EH_PE_sdata4});
- this->memory_.SetData16(0x1004, 0x500);
- this->memory_.SetData32(0x1006, 126);
-
- ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0));
- EXPECT_EQ(1U, this->eh_frame_->TestGetVersion());
- EXPECT_EQ(DW_EH_PE_sdata4, this->eh_frame_->TestGetTableEncoding());
- EXPECT_EQ(4U, this->eh_frame_->TestGetTableEntrySize());
- EXPECT_EQ(126U, this->eh_frame_->TestGetFdeCount());
- EXPECT_EQ(0x100aU, this->eh_frame_->TestGetHdrEntriesOffset());
- EXPECT_EQ(0x1000U, this->eh_frame_->TestGetHdrEntriesDataOffset());
-
- // Verify a zero table entry size fails to init.
- this->memory_.SetData8(0x1003, 0x1);
- ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100, 0));
- ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->LastErrorCode());
- // Reset the value back to the original.
- this->memory_.SetData8(0x1003, DW_EH_PE_sdata4);
-
- // Verify a zero fde count fails to init.
- this->memory_.SetData32(0x1006, 0);
- ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100, 0));
- ASSERT_EQ(DWARF_ERROR_NO_FDES, this->eh_frame_->LastErrorCode());
-
- // Verify an unexpected version will cause a fail.
- this->memory_.SetData32(0x1006, 126);
- this->memory_.SetData8(0x1000, 0);
- ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100, 0));
- ASSERT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->eh_frame_->LastErrorCode());
- this->memory_.SetData8(0x1000, 2);
- ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100, 0));
- ASSERT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->eh_frame_->LastErrorCode());
-}
-
-TYPED_TEST_P(DwarfEhFrameWithHdrTest, Init_non_zero_load_bias) {
- this->memory_.SetMemory(0x1000, std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4,
- DW_EH_PE_pcrel | DW_EH_PE_sdata4});
- this->memory_.SetData16(0x1004, 0x500);
- this->memory_.SetData32(0x1006, 1);
- this->memory_.SetData32(0x100a, 0x2500);
- this->memory_.SetData32(0x100e, 0x1400);
-
- // CIE 32 information.
- this->memory_.SetData32(0x1300, 0xfc);
- this->memory_.SetData32(0x1304, 0);
- this->memory_.SetMemory(0x1308, std::vector<uint8_t>{1, 'z', 'R', '\0', 0, 0, 0, 0, 0x1b});
-
- // FDE 32 information.
- this->memory_.SetData32(0x1400, 0xfc);
- this->memory_.SetData32(0x1404, 0x104);
- this->memory_.SetData32(0x1408, 0x10f8);
- this->memory_.SetData32(0x140c, 0x200);
- this->memory_.SetData16(0x1410, 0);
-
- ASSERT_TRUE(this->eh_frame_->EhFrameInit(0x1300, 0x200, 0x2000));
- ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0x2000));
- EXPECT_EQ(1U, this->eh_frame_->TestGetVersion());
- EXPECT_EQ(0x1b, this->eh_frame_->TestGetTableEncoding());
- EXPECT_EQ(4U, this->eh_frame_->TestGetTableEntrySize());
- EXPECT_EQ(1U, this->eh_frame_->TestGetFdeCount());
- EXPECT_EQ(0x100aU, this->eh_frame_->TestGetHdrEntriesOffset());
- EXPECT_EQ(0x1000U, this->eh_frame_->TestGetHdrEntriesDataOffset());
-
- const DwarfFde* fde = this->eh_frame_->GetFdeFromPc(0x4600);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x4500U, fde->pc_start);
- EXPECT_EQ(0x4700U, fde->pc_end);
-}
-
-TYPED_TEST_P(DwarfEhFrameWithHdrTest, Init_non_zero_load_bias_different_from_eh_frame_bias) {
- this->memory_.SetMemory(0x1000, std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4,
- DW_EH_PE_pcrel | DW_EH_PE_sdata4});
- this->memory_.SetData16(0x1004, 0x500);
- this->memory_.SetData32(0x1006, 1);
- this->memory_.SetData32(0x100a, 0x2500);
- this->memory_.SetData32(0x100e, 0x1400);
-
- // CIE 32 information.
- this->memory_.SetData32(0x1300, 0xfc);
- this->memory_.SetData32(0x1304, 0);
- this->memory_.SetMemory(0x1308, std::vector<uint8_t>{1, 'z', 'R', '\0', 0, 0, 0, 0, 0x1b});
-
- // FDE 32 information.
- this->memory_.SetData32(0x1400, 0xfc);
- this->memory_.SetData32(0x1404, 0x104);
- this->memory_.SetData32(0x1408, 0x20f8);
- this->memory_.SetData32(0x140c, 0x200);
- this->memory_.SetData16(0x1410, 0);
-
- ASSERT_TRUE(this->eh_frame_->EhFrameInit(0x1300, 0x200, 0x1000));
- ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0x2000));
- EXPECT_EQ(1U, this->eh_frame_->TestGetVersion());
- EXPECT_EQ(0x1b, this->eh_frame_->TestGetTableEncoding());
- EXPECT_EQ(4U, this->eh_frame_->TestGetTableEntrySize());
- EXPECT_EQ(1U, this->eh_frame_->TestGetFdeCount());
- EXPECT_EQ(0x100aU, this->eh_frame_->TestGetHdrEntriesOffset());
- EXPECT_EQ(0x1000U, this->eh_frame_->TestGetHdrEntriesDataOffset());
-
- const DwarfFde* fde = this->eh_frame_->GetFdeFromPc(0x4600);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x4500U, fde->pc_start);
- EXPECT_EQ(0x4700U, fde->pc_end);
-}
-
-TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeFromPc_wtih_empty_fde) {
- this->memory_.SetMemory(0x1000, std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4,
- DW_EH_PE_pcrel | DW_EH_PE_sdata4});
- this->memory_.SetData16(0x1004, 0x500);
- this->memory_.SetData32(0x1006, 1);
- this->memory_.SetData32(0x100a, 0x2500);
- this->memory_.SetData32(0x100e, 0x1400);
-
- // CIE 32 information.
- this->memory_.SetData32(0x1300, 0xfc);
- this->memory_.SetData32(0x1304, 0);
- this->memory_.SetMemory(0x1308, std::vector<uint8_t>{1, 'z', 'R', '\0', 0, 0, 0, 0, 0x1b});
-
- // FDE 32 information.
- this->memory_.SetData32(0x1400, 0xfc);
- this->memory_.SetData32(0x1404, 0x104);
- this->memory_.SetData32(0x1408, 0x30f8);
- this->memory_.SetData32(0x140c, 0);
- this->memory_.SetData16(0x1410, 0);
-
- // FDE 32 information.
- this->memory_.SetData32(0x1500, 0xfc);
- this->memory_.SetData32(0x1504, 0x204);
- this->memory_.SetData32(0x1508, 0x2ff8);
- this->memory_.SetData32(0x150c, 0x200);
- this->memory_.SetData16(0x1510, 0);
-
- ASSERT_TRUE(this->eh_frame_->EhFrameInit(0x1300, 0x300, 0));
- ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0));
-
- const DwarfFde* fde = this->eh_frame_->GetFdeFromPc(0x4600);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x4500U, fde->pc_start);
- EXPECT_EQ(0x4700U, fde->pc_end);
-}
-
-TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdes_with_empty_fde) {
- this->memory_.SetMemory(0x1000, std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4,
- DW_EH_PE_pcrel | DW_EH_PE_sdata4});
- this->memory_.SetData16(0x1004, 0x500);
- this->memory_.SetData32(0x1006, 1);
- this->memory_.SetData32(0x100a, 0x2500);
- this->memory_.SetData32(0x100e, 0x1400);
-
- // CIE 32 information.
- this->memory_.SetData32(0x1300, 0xfc);
- this->memory_.SetData32(0x1304, 0);
- this->memory_.SetMemory(0x1308, std::vector<uint8_t>{1, 'z', 'R', '\0', 0, 0, 0, 0, 0x1b});
-
- // FDE 32 information.
- this->memory_.SetData32(0x1400, 0xfc);
- this->memory_.SetData32(0x1404, 0x104);
- this->memory_.SetData32(0x1408, 0x30f8);
- this->memory_.SetData32(0x140c, 0);
- this->memory_.SetData16(0x1410, 0);
-
- // FDE 32 information.
- this->memory_.SetData32(0x1500, 0xfc);
- this->memory_.SetData32(0x1504, 0x204);
- this->memory_.SetData32(0x1508, 0x2ff8);
- this->memory_.SetData32(0x150c, 0x200);
- this->memory_.SetData16(0x1510, 0);
-
- ASSERT_TRUE(this->eh_frame_->EhFrameInit(0x1300, 0x300, 0));
- ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0));
-
- std::vector<const DwarfFde*> fdes;
- this->eh_frame_->GetFdes(&fdes);
- ASSERT_FALSE(fdes.empty());
- ASSERT_EQ(1U, fdes.size());
- EXPECT_EQ(0x4500U, fdes[0]->pc_start);
- EXPECT_EQ(0x4700U, fdes[0]->pc_end);
-}
-
-TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdes) {
- this->memory_.SetMemory(
- 0x1000, std::vector<uint8_t>{1, DW_EH_PE_udata2, DW_EH_PE_udata4, DW_EH_PE_sdata4});
- this->memory_.SetData16(0x1004, 0x500);
- this->memory_.SetData32(0x1006, 4);
-
- // Header information.
- this->memory_.SetData32(0x100a, 0x4600);
- this->memory_.SetData32(0x100e, 0x1500);
- this->memory_.SetData32(0x1012, 0x5500);
- this->memory_.SetData32(0x1016, 0x1400);
- this->memory_.SetData32(0x101a, 0x6800);
- this->memory_.SetData32(0x101e, 0x1700);
- this->memory_.SetData32(0x1022, 0x7700);
- this->memory_.SetData32(0x1026, 0x1600);
-
- // CIE 32 information.
- this->memory_.SetData32(0x1300, 0xfc);
- this->memory_.SetData32(0x1304, 0);
- this->memory_.SetMemory(0x1308, std::vector<uint8_t>{1, '\0', 0, 0, 0});
-
- // FDE 32 information.
- // pc 0x5500 - 0x5700
- this->memory_.SetData32(0x1400, 0xfc);
- this->memory_.SetData32(0x1404, 0x104);
- this->memory_.SetData32(0x1408, 0x40f8);
- this->memory_.SetData32(0x140c, 0x200);
-
- // pc 0x4600 - 0x4800
- this->memory_.SetData32(0x1500, 0xfc);
- this->memory_.SetData32(0x1504, 0x204);
- this->memory_.SetData32(0x1508, 0x30f8);
- this->memory_.SetData32(0x150c, 0x200);
-
- // pc 0x7700 - 0x7900
- this->memory_.SetData32(0x1600, 0xfc);
- this->memory_.SetData32(0x1604, 0x304);
- this->memory_.SetData32(0x1608, 0x60f8);
- this->memory_.SetData32(0x160c, 0x200);
-
- // pc 0x6800 - 0x6a00
- this->memory_.SetData32(0x1700, 0xfc);
- this->memory_.SetData32(0x1704, 0x404);
- this->memory_.SetData32(0x1708, 0x50f8);
- this->memory_.SetData32(0x170c, 0x200);
-
- ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0));
-
- std::vector<const DwarfFde*> fdes;
- this->eh_frame_->GetFdes(&fdes);
- ASSERT_EQ(4U, fdes.size());
-
- EXPECT_EQ(0x4600U, fdes[0]->pc_start);
- EXPECT_EQ(0x4800U, fdes[0]->pc_end);
- EXPECT_EQ(0x5500U, fdes[1]->pc_start);
- EXPECT_EQ(0x5700U, fdes[1]->pc_end);
- EXPECT_EQ(0x6800U, fdes[2]->pc_start);
- EXPECT_EQ(0x6a00U, fdes[2]->pc_end);
- EXPECT_EQ(0x7700U, fdes[3]->pc_start);
- EXPECT_EQ(0x7900U, fdes[3]->pc_end);
-}
-
-TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_expect_cache_fail) {
- this->eh_frame_->TestSetTableEntrySize(0x10);
- this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
- this->eh_frame_->TestSetHdrEntriesOffset(0x1000);
-
- ASSERT_TRUE(this->eh_frame_->GetFdeInfoFromIndex(0) == nullptr);
- ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->eh_frame_->LastErrorCode());
- EXPECT_EQ(0x1000U, this->eh_frame_->LastErrorAddress());
- ASSERT_TRUE(this->eh_frame_->GetFdeInfoFromIndex(0) == nullptr);
- ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->eh_frame_->LastErrorCode());
- EXPECT_EQ(0x1000U, this->eh_frame_->LastErrorAddress());
-}
-
-// We are assuming that pc rel, is really relative to the load_bias.
-TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_read_pcrel) {
- this->eh_frame_->TestSetTableEncoding(DW_EH_PE_pcrel | DW_EH_PE_udata4);
- this->eh_frame_->TestSetHdrEntriesOffset(0x1000);
- this->eh_frame_->TestSetHdrEntriesDataOffset(0x3000);
- this->eh_frame_->TestSetTableEntrySize(0x10);
-
- this->memory_.SetData32(0x1040, 0x340);
- this->memory_.SetData32(0x1044, 0x500);
-
- auto info = this->eh_frame_->GetFdeInfoFromIndex(2);
- ASSERT_TRUE(info != nullptr);
- EXPECT_EQ(0x340U, info->pc);
- EXPECT_EQ(0x500U, info->offset);
-}
-
-TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_read_datarel) {
- this->eh_frame_->TestSetTableEncoding(DW_EH_PE_datarel | DW_EH_PE_udata4);
- this->eh_frame_->TestSetHdrEntriesOffset(0x1000);
- this->eh_frame_->TestSetHdrEntriesDataOffset(0x3000);
- this->eh_frame_->TestSetTableEntrySize(0x10);
-
- this->memory_.SetData32(0x1040, 0x340);
- this->memory_.SetData32(0x1044, 0x500);
-
- auto info = this->eh_frame_->GetFdeInfoFromIndex(2);
- ASSERT_TRUE(info != nullptr);
- EXPECT_EQ(0x3340U, info->pc);
- EXPECT_EQ(0x3500U, info->offset);
-}
-
-TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_cached) {
- this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
- this->eh_frame_->TestSetHdrEntriesOffset(0x1000);
- this->eh_frame_->TestSetTableEntrySize(0x10);
-
- this->memory_.SetData32(0x1040, 0x340);
- this->memory_.SetData32(0x1044, 0x500);
-
- auto info = this->eh_frame_->GetFdeInfoFromIndex(2);
- ASSERT_TRUE(info != nullptr);
- EXPECT_EQ(0x340U, info->pc);
- EXPECT_EQ(0x500U, info->offset);
-
- // Clear the memory so that this will fail if it doesn't read cached data.
- this->memory_.Clear();
-
- info = this->eh_frame_->GetFdeInfoFromIndex(2);
- ASSERT_TRUE(info != nullptr);
- EXPECT_EQ(0x340U, info->pc);
- EXPECT_EQ(0x500U, info->offset);
-}
-
-TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_verify) {
- this->eh_frame_->TestSetTableEntrySize(0x10);
-
- typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo info;
- for (size_t i = 0; i < 10; i++) {
- info.pc = 0x1000 * (i + 1);
- info.offset = 0x5000 + i * 0x20;
- this->eh_frame_->TestSetFdeInfo(i, info);
- }
-
- uint64_t fde_offset;
- this->eh_frame_->TestSetFdeCount(10);
- EXPECT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x100, &fde_offset));
- // Not an error, just not found.
- ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode());
- // Even number of elements.
- for (size_t i = 0; i < 10; i++) {
- SCOPED_TRACE(testing::Message() << "Failed at index " << i);
- TypeParam pc = 0x1000 * (i + 1);
- EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc, &fde_offset));
- EXPECT_EQ(0x5000 + i * 0x20, fde_offset);
- EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset));
- EXPECT_EQ(0x5000 + i * 0x20, fde_offset);
- EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset));
- EXPECT_EQ(0x5000 + i * 0x20, fde_offset);
- }
-
- // Odd number of elements.
- this->eh_frame_->TestSetFdeCount(9);
- for (size_t i = 0; i < 9; i++) {
- SCOPED_TRACE(testing::Message() << "Failed at index " << i);
- TypeParam pc = 0x1000 * (i + 1);
- EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc, &fde_offset));
- EXPECT_EQ(0x5000 + i * 0x20, fde_offset);
- EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset));
- EXPECT_EQ(0x5000 + i * 0x20, fde_offset);
- EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset));
- EXPECT_EQ(0x5000 + i * 0x20, fde_offset);
- }
-}
-
-TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_index_fail) {
- this->eh_frame_->TestSetTableEntrySize(0x10);
- this->eh_frame_->TestSetFdeCount(10);
-
- uint64_t fde_offset;
- EXPECT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x1000, &fde_offset));
-}
-
-TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_fail_fde_count) {
- this->eh_frame_->TestSetFdeCount(0);
-
- uint64_t fde_offset;
- ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x100, &fde_offset));
- ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode());
-}
-
-TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_search) {
- this->eh_frame_->TestSetTableEntrySize(16);
- this->eh_frame_->TestSetFdeCount(10);
-
- typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo info;
- info.pc = 0x550;
- info.offset = 0x10500;
- this->eh_frame_->TestSetFdeInfo(5, info);
- info.pc = 0x750;
- info.offset = 0x10700;
- this->eh_frame_->TestSetFdeInfo(7, info);
- info.pc = 0x850;
- info.offset = 0x10800;
- this->eh_frame_->TestSetFdeInfo(8, info);
-
- uint64_t fde_offset;
- ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(0x800, &fde_offset));
- EXPECT_EQ(0x10700U, fde_offset);
-}
-
-TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetCieFde32) {
- // CIE 32 information.
- this->memory_.SetData32(0xf000, 0x100);
- this->memory_.SetData32(0xf004, 0);
- this->memory_.SetMemory(0xf008, std::vector<uint8_t>{1, '\0', 4, 8, 0x20});
-
- // FDE 32 information.
- this->memory_.SetData32(0x14000, 0x20);
- this->memory_.SetData32(0x14004, 0x5004);
- this->memory_.SetData32(0x14008, 0x9000);
- this->memory_.SetData32(0x1400c, 0x100);
-
- const DwarfFde* fde = this->eh_frame_->GetFdeFromOffset(0x14000);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x14010U, fde->cfa_instructions_offset);
- EXPECT_EQ(0x14024U, fde->cfa_instructions_end);
- EXPECT_EQ(0x1d008U, fde->pc_start);
- EXPECT_EQ(0x1d108U, fde->pc_end);
- EXPECT_EQ(0xf000U, fde->cie_offset);
- EXPECT_EQ(0U, fde->lsda_address);
-
- ASSERT_TRUE(fde->cie != nullptr);
- EXPECT_EQ(1U, fde->cie->version);
- EXPECT_EQ(DW_EH_PE_sdata4, fde->cie->fde_address_encoding);
- EXPECT_EQ(DW_EH_PE_omit, fde->cie->lsda_encoding);
- EXPECT_EQ(0U, fde->cie->segment_size);
- EXPECT_EQ(1U, fde->cie->augmentation_string.size());
- EXPECT_EQ('\0', fde->cie->augmentation_string[0]);
- EXPECT_EQ(0U, fde->cie->personality_handler);
- EXPECT_EQ(0xf00dU, fde->cie->cfa_instructions_offset);
- EXPECT_EQ(0xf104U, fde->cie->cfa_instructions_end);
- EXPECT_EQ(4U, fde->cie->code_alignment_factor);
- EXPECT_EQ(8, fde->cie->data_alignment_factor);
- EXPECT_EQ(0x20U, fde->cie->return_address_register);
-}
-
-TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetCieFde64) {
- // CIE 64 information.
- this->memory_.SetData32(0x6000, 0xffffffff);
- this->memory_.SetData64(0x6004, 0x100);
- this->memory_.SetData64(0x600c, 0);
- this->memory_.SetMemory(0x6014, std::vector<uint8_t>{1, '\0', 4, 8, 0x20});
-
- // FDE 64 information.
- this->memory_.SetData32(0x8000, 0xffffffff);
- this->memory_.SetData64(0x8004, 0x200);
- this->memory_.SetData64(0x800c, 0x200c);
- this->memory_.SetData64(0x8014, 0x5000);
- this->memory_.SetData64(0x801c, 0x300);
-
- const DwarfFde* fde = this->eh_frame_->GetFdeFromOffset(0x8000);
- ASSERT_TRUE(fde != nullptr);
- EXPECT_EQ(0x8024U, fde->cfa_instructions_offset);
- EXPECT_EQ(0x820cU, fde->cfa_instructions_end);
- EXPECT_EQ(0xd018U, fde->pc_start);
- EXPECT_EQ(0xd318U, fde->pc_end);
- EXPECT_EQ(0x6000U, fde->cie_offset);
- EXPECT_EQ(0U, fde->lsda_address);
-
- ASSERT_TRUE(fde->cie != nullptr);
- EXPECT_EQ(1U, fde->cie->version);
- EXPECT_EQ(DW_EH_PE_sdata8, fde->cie->fde_address_encoding);
- EXPECT_EQ(DW_EH_PE_omit, fde->cie->lsda_encoding);
- EXPECT_EQ(0U, fde->cie->segment_size);
- EXPECT_EQ(1U, fde->cie->augmentation_string.size());
- EXPECT_EQ('\0', fde->cie->augmentation_string[0]);
- EXPECT_EQ(0U, fde->cie->personality_handler);
- EXPECT_EQ(0x6019U, fde->cie->cfa_instructions_offset);
- EXPECT_EQ(0x610cU, fde->cie->cfa_instructions_end);
- EXPECT_EQ(4U, fde->cie->code_alignment_factor);
- EXPECT_EQ(8, fde->cie->data_alignment_factor);
- EXPECT_EQ(0x20U, fde->cie->return_address_register);
-}
-
-TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeFromPc_fde_not_found) {
- this->eh_frame_->TestSetTableEntrySize(16);
- this->eh_frame_->TestSetFdeCount(1);
-
- typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo info;
- info.pc = 0x550;
- info.offset = 0x10500;
- this->eh_frame_->TestSetFdeInfo(0, info);
-
- ASSERT_EQ(nullptr, this->eh_frame_->GetFdeFromPc(0x800));
-}
-
-REGISTER_TYPED_TEST_SUITE_P(DwarfEhFrameWithHdrTest, Init, Init_non_zero_load_bias,
- Init_non_zero_load_bias_different_from_eh_frame_bias,
- GetFdeFromPc_wtih_empty_fde, GetFdes_with_empty_fde, GetFdes,
- GetFdeInfoFromIndex_expect_cache_fail, GetFdeInfoFromIndex_read_pcrel,
- GetFdeInfoFromIndex_read_datarel, GetFdeInfoFromIndex_cached,
- GetFdeOffsetFromPc_verify, GetFdeOffsetFromPc_index_fail,
- GetFdeOffsetFromPc_fail_fde_count, GetFdeOffsetFromPc_search,
- GetCieFde32, GetCieFde64, GetFdeFromPc_fde_not_found);
-
-typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameWithHdrTestTypes;
-INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfEhFrameWithHdrTest, DwarfEhFrameWithHdrTestTypes);
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/DwarfMemoryTest.cpp b/libunwindstack/tests/DwarfMemoryTest.cpp
deleted file mode 100644
index 650e965..0000000
--- a/libunwindstack/tests/DwarfMemoryTest.cpp
+++ /dev/null
@@ -1,545 +0,0 @@
-/*
- * Copyright (C) 2017 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 <stdint.h>
-
-#include <ios>
-#include <vector>
-
-#include <gtest/gtest.h>
-
-#include <unwindstack/DwarfMemory.h>
-
-#include "MemoryFake.h"
-
-namespace unwindstack {
-
-class DwarfMemoryTest : public ::testing::Test {
- protected:
- void SetUp() override {
- memory_.Clear();
- dwarf_mem_.reset(new DwarfMemory(&memory_));
- }
-
- template <typename AddressType>
- void GetEncodedSizeTest(uint8_t value, size_t expected);
- template <typename AddressType>
- void ReadEncodedValue_omit();
- template <typename AddressType>
- void ReadEncodedValue_leb128();
- template <typename AddressType>
- void ReadEncodedValue_data1();
- template <typename AddressType>
- void ReadEncodedValue_data2();
- template <typename AddressType>
- void ReadEncodedValue_data4();
- template <typename AddressType>
- void ReadEncodedValue_data8();
- template <typename AddressType>
- void ReadEncodedValue_non_zero_adjust();
- template <typename AddressType>
- void ReadEncodedValue_overflow();
- template <typename AddressType>
- void ReadEncodedValue_high_bit_set();
- template <typename AddressType>
- void ReadEncodedValue_all();
-
- MemoryFake memory_;
- std::unique_ptr<DwarfMemory> dwarf_mem_;
-};
-
-TEST_F(DwarfMemoryTest, ReadBytes) {
- memory_.SetMemory(0, std::vector<uint8_t>{0x10, 0x18, 0xff, 0xfe});
-
- uint8_t byte;
- ASSERT_TRUE(dwarf_mem_->ReadBytes(&byte, 1));
- ASSERT_EQ(0x10U, byte);
- ASSERT_TRUE(dwarf_mem_->ReadBytes(&byte, 1));
- ASSERT_EQ(0x18U, byte);
- ASSERT_TRUE(dwarf_mem_->ReadBytes(&byte, 1));
- ASSERT_EQ(0xffU, byte);
- ASSERT_TRUE(dwarf_mem_->ReadBytes(&byte, 1));
- ASSERT_EQ(0xfeU, byte);
- ASSERT_EQ(4U, dwarf_mem_->cur_offset());
-
- dwarf_mem_->set_cur_offset(2);
- ASSERT_TRUE(dwarf_mem_->ReadBytes(&byte, 1));
- ASSERT_EQ(0xffU, byte);
- ASSERT_EQ(3U, dwarf_mem_->cur_offset());
-}
-
-TEST_F(DwarfMemoryTest, ReadSigned_check) {
- uint64_t value;
-
- // Signed 8 byte reads.
- memory_.SetData8(0, static_cast<uint8_t>(-10));
- memory_.SetData8(1, 200);
- ASSERT_TRUE(dwarf_mem_->ReadSigned<int8_t>(&value));
- ASSERT_EQ(static_cast<int8_t>(-10), static_cast<int8_t>(value));
- ASSERT_TRUE(dwarf_mem_->ReadSigned<int8_t>(&value));
- ASSERT_EQ(static_cast<int8_t>(200), static_cast<int8_t>(value));
-
- // Signed 16 byte reads.
- memory_.SetData16(0x10, static_cast<uint16_t>(-1000));
- memory_.SetData16(0x12, 50100);
- dwarf_mem_->set_cur_offset(0x10);
- ASSERT_TRUE(dwarf_mem_->ReadSigned<int16_t>(&value));
- ASSERT_EQ(static_cast<int16_t>(-1000), static_cast<int16_t>(value));
- ASSERT_TRUE(dwarf_mem_->ReadSigned<int16_t>(&value));
- ASSERT_EQ(static_cast<int16_t>(50100), static_cast<int16_t>(value));
-
- // Signed 32 byte reads.
- memory_.SetData32(0x100, static_cast<uint32_t>(-1000000000));
- memory_.SetData32(0x104, 3000000000);
- dwarf_mem_->set_cur_offset(0x100);
- ASSERT_TRUE(dwarf_mem_->ReadSigned<int32_t>(&value));
- ASSERT_EQ(static_cast<int32_t>(-1000000000), static_cast<int32_t>(value));
- ASSERT_TRUE(dwarf_mem_->ReadSigned<int32_t>(&value));
- ASSERT_EQ(static_cast<int32_t>(3000000000), static_cast<int32_t>(value));
-
- // Signed 64 byte reads.
- memory_.SetData64(0x200, static_cast<uint64_t>(-2000000000000LL));
- memory_.SetData64(0x208, 5000000000000LL);
- dwarf_mem_->set_cur_offset(0x200);
- ASSERT_TRUE(dwarf_mem_->ReadSigned<int64_t>(&value));
- ASSERT_EQ(static_cast<int64_t>(-2000000000000), static_cast<int64_t>(value));
- ASSERT_TRUE(dwarf_mem_->ReadSigned<int64_t>(&value));
- ASSERT_EQ(static_cast<int64_t>(5000000000000), static_cast<int64_t>(value));
-}
-
-TEST_F(DwarfMemoryTest, ReadULEB128) {
- memory_.SetMemory(0, std::vector<uint8_t>{0x01, 0x80, 0x24, 0xff, 0xc3, 0xff, 0x7f});
-
- uint64_t value;
- ASSERT_TRUE(dwarf_mem_->ReadULEB128(&value));
- ASSERT_EQ(1U, dwarf_mem_->cur_offset());
- ASSERT_EQ(1U, value);
-
- ASSERT_TRUE(dwarf_mem_->ReadULEB128(&value));
- ASSERT_EQ(3U, dwarf_mem_->cur_offset());
- ASSERT_EQ(0x1200U, value);
-
- ASSERT_TRUE(dwarf_mem_->ReadULEB128(&value));
- ASSERT_EQ(7U, dwarf_mem_->cur_offset());
- ASSERT_EQ(0xfffe1ffU, value);
-}
-
-TEST_F(DwarfMemoryTest, ReadSLEB128) {
- memory_.SetMemory(0, std::vector<uint8_t>{0x06, 0x40, 0x82, 0x34, 0x89, 0x64, 0xf9, 0xc3, 0x8f,
- 0x2f, 0xbf, 0xc3, 0xf7, 0x5f});
-
- int64_t value;
- ASSERT_TRUE(dwarf_mem_->ReadSLEB128(&value));
- ASSERT_EQ(1U, dwarf_mem_->cur_offset());
- ASSERT_EQ(6U, value);
-
- ASSERT_TRUE(dwarf_mem_->ReadSLEB128(&value));
- ASSERT_EQ(2U, dwarf_mem_->cur_offset());
- ASSERT_EQ(0xffffffffffffffc0ULL, static_cast<uint64_t>(value));
-
- ASSERT_TRUE(dwarf_mem_->ReadSLEB128(&value));
- ASSERT_EQ(4U, dwarf_mem_->cur_offset());
- ASSERT_EQ(0x1a02U, value);
-
- ASSERT_TRUE(dwarf_mem_->ReadSLEB128(&value));
- ASSERT_EQ(6U, dwarf_mem_->cur_offset());
- ASSERT_EQ(0xfffffffffffff209ULL, static_cast<uint64_t>(value));
-
- ASSERT_TRUE(dwarf_mem_->ReadSLEB128(&value));
- ASSERT_EQ(10U, dwarf_mem_->cur_offset());
- ASSERT_EQ(0x5e3e1f9U, value);
-
- ASSERT_TRUE(dwarf_mem_->ReadSLEB128(&value));
- ASSERT_EQ(14U, dwarf_mem_->cur_offset());
- ASSERT_EQ(0xfffffffffbfde1bfULL, static_cast<uint64_t>(value));
-}
-
-template <typename AddressType>
-void DwarfMemoryTest::GetEncodedSizeTest(uint8_t value, size_t expected) {
- for (size_t i = 0; i < 16; i++) {
- uint8_t encoding = (i << 4) | value;
- ASSERT_EQ(expected, dwarf_mem_->GetEncodedSize<AddressType>(encoding))
- << "encoding 0x" << std::hex << static_cast<uint32_t>(encoding) << " test value 0x"
- << static_cast<size_t>(value);
- }
-}
-
-TEST_F(DwarfMemoryTest, GetEncodedSize_absptr_uint32_t) {
- GetEncodedSizeTest<uint32_t>(0, sizeof(uint32_t));
-}
-
-TEST_F(DwarfMemoryTest, GetEncodedSize_absptr_uint64_t) {
- GetEncodedSizeTest<uint64_t>(0, sizeof(uint64_t));
-}
-
-TEST_F(DwarfMemoryTest, GetEncodedSize_data1) {
- // udata1
- GetEncodedSizeTest<uint32_t>(0x0d, 1);
- GetEncodedSizeTest<uint64_t>(0x0d, 1);
-
- // sdata1
- GetEncodedSizeTest<uint32_t>(0x0e, 1);
- GetEncodedSizeTest<uint64_t>(0x0e, 1);
-}
-
-TEST_F(DwarfMemoryTest, GetEncodedSize_data2) {
- // udata2
- GetEncodedSizeTest<uint32_t>(0x02, 2);
- GetEncodedSizeTest<uint64_t>(0x02, 2);
-
- // sdata2
- GetEncodedSizeTest<uint32_t>(0x0a, 2);
- GetEncodedSizeTest<uint64_t>(0x0a, 2);
-}
-
-TEST_F(DwarfMemoryTest, GetEncodedSize_data4) {
- // udata4
- GetEncodedSizeTest<uint32_t>(0x03, 4);
- GetEncodedSizeTest<uint64_t>(0x03, 4);
-
- // sdata4
- GetEncodedSizeTest<uint32_t>(0x0b, 4);
- GetEncodedSizeTest<uint64_t>(0x0b, 4);
-}
-
-TEST_F(DwarfMemoryTest, GetEncodedSize_data8) {
- // udata8
- GetEncodedSizeTest<uint32_t>(0x04, 8);
- GetEncodedSizeTest<uint64_t>(0x04, 8);
-
- // sdata8
- GetEncodedSizeTest<uint32_t>(0x0c, 8);
- GetEncodedSizeTest<uint64_t>(0x0c, 8);
-}
-
-TEST_F(DwarfMemoryTest, GetEncodedSize_unknown) {
- GetEncodedSizeTest<uint32_t>(0x01, 0);
- GetEncodedSizeTest<uint64_t>(0x01, 0);
-
- GetEncodedSizeTest<uint32_t>(0x09, 0);
- GetEncodedSizeTest<uint64_t>(0x09, 0);
-
- GetEncodedSizeTest<uint32_t>(0x0f, 0);
- GetEncodedSizeTest<uint64_t>(0x0f, 0);
-}
-
-template <typename AddressType>
-void DwarfMemoryTest::ReadEncodedValue_omit() {
- uint64_t value = 123;
- ASSERT_TRUE(dwarf_mem_->ReadEncodedValue<AddressType>(0xff, &value));
- ASSERT_EQ(0U, value);
-}
-
-TEST_F(DwarfMemoryTest, ReadEncodedValue_omit_uint32_t) {
- ReadEncodedValue_omit<uint32_t>();
-}
-
-TEST_F(DwarfMemoryTest, ReadEncodedValue_omit_uint64_t) {
- ReadEncodedValue_omit<uint64_t>();
-}
-
-TEST_F(DwarfMemoryTest, ReadEncodedValue_absptr_uint32_t) {
- uint64_t value = 100;
- ASSERT_FALSE(dwarf_mem_->ReadEncodedValue<uint32_t>(0x00, &value));
-
- memory_.SetData32(0, 0x12345678);
-
- ASSERT_TRUE(dwarf_mem_->ReadEncodedValue<uint32_t>(0x00, &value));
- ASSERT_EQ(4U, dwarf_mem_->cur_offset());
- ASSERT_EQ(0x12345678U, value);
-}
-
-TEST_F(DwarfMemoryTest, ReadEncodedValue_absptr_uint64_t) {
- uint64_t value = 100;
- ASSERT_FALSE(dwarf_mem_->ReadEncodedValue<uint64_t>(0x00, &value));
-
- memory_.SetData64(0, 0x12345678f1f2f3f4ULL);
-
- ASSERT_TRUE(dwarf_mem_->ReadEncodedValue<uint64_t>(0x00, &value));
- ASSERT_EQ(8U, dwarf_mem_->cur_offset());
- ASSERT_EQ(0x12345678f1f2f3f4ULL, value);
-}
-
-TEST_F(DwarfMemoryTest, ReadEncodedValue_aligned_uint32_t) {
- uint64_t value = 100;
- dwarf_mem_->set_cur_offset(1);
- ASSERT_FALSE(dwarf_mem_->ReadEncodedValue<uint32_t>(0x50, &value));
-
- memory_.SetData32(4, 0x12345678);
-
- ASSERT_TRUE(dwarf_mem_->ReadEncodedValue<uint32_t>(0x50, &value));
- ASSERT_EQ(8U, dwarf_mem_->cur_offset());
- ASSERT_EQ(0x12345678U, value);
-}
-
-TEST_F(DwarfMemoryTest, ReadEncodedValue_aligned_uint64_t) {
- uint64_t value = 100;
- dwarf_mem_->set_cur_offset(1);
- ASSERT_FALSE(dwarf_mem_->ReadEncodedValue<uint64_t>(0x50, &value));
-
- memory_.SetData64(8, 0x12345678f1f2f3f4ULL);
-
- ASSERT_TRUE(dwarf_mem_->ReadEncodedValue<uint64_t>(0x50, &value));
- ASSERT_EQ(16U, dwarf_mem_->cur_offset());
- ASSERT_EQ(0x12345678f1f2f3f4ULL, value);
-}
-
-template <typename AddressType>
-void DwarfMemoryTest::ReadEncodedValue_leb128() {
- memory_.SetMemory(0, std::vector<uint8_t>{0x80, 0x42});
-
- uint64_t value = 100;
- // uleb128
- ASSERT_TRUE(dwarf_mem_->ReadEncodedValue<AddressType>(0x01, &value));
- ASSERT_EQ(0x2100U, value);
-
- dwarf_mem_->set_cur_offset(0);
- // sleb128
- ASSERT_TRUE(dwarf_mem_->ReadEncodedValue<AddressType>(0x09, &value));
- ASSERT_EQ(0xffffffffffffe100ULL, value);
-}
-
-TEST_F(DwarfMemoryTest, ReadEncodedValue_leb128_uint32_t) {
- ReadEncodedValue_leb128<uint32_t>();
-}
-
-TEST_F(DwarfMemoryTest, ReadEncodedValue_leb128_uint64_t) {
- ReadEncodedValue_leb128<uint64_t>();
-}
-
-template <typename AddressType>
-void DwarfMemoryTest::ReadEncodedValue_data1() {
- memory_.SetData8(0, 0xe0);
-
- uint64_t value = 0;
- ASSERT_TRUE(dwarf_mem_->ReadEncodedValue<AddressType>(0x0d, &value));
- ASSERT_EQ(0xe0U, value);
-
- dwarf_mem_->set_cur_offset(0);
- ASSERT_TRUE(dwarf_mem_->ReadEncodedValue<AddressType>(0x0e, &value));
- ASSERT_EQ(0xffffffffffffffe0ULL, value);
-}
-
-TEST_F(DwarfMemoryTest, ReadEncodedValue_data1_uint32_t) {
- ReadEncodedValue_data1<uint32_t>();
-}
-
-TEST_F(DwarfMemoryTest, ReadEncodedValue_data1_uint64_t) {
- ReadEncodedValue_data1<uint64_t>();
-}
-
-template <typename AddressType>
-void DwarfMemoryTest::ReadEncodedValue_data2() {
- memory_.SetData16(0, 0xe000);
-
- uint64_t value = 0;
- ASSERT_TRUE(dwarf_mem_->ReadEncodedValue<AddressType>(0x02, &value));
- ASSERT_EQ(0xe000U, value);
-
- dwarf_mem_->set_cur_offset(0);
- ASSERT_TRUE(dwarf_mem_->ReadEncodedValue<AddressType>(0x0a, &value));
- ASSERT_EQ(0xffffffffffffe000ULL, value);
-}
-
-TEST_F(DwarfMemoryTest, ReadEncodedValue_data2_uint32_t) {
- ReadEncodedValue_data2<uint32_t>();
-}
-
-TEST_F(DwarfMemoryTest, ReadEncodedValue_data2_uint64_t) {
- ReadEncodedValue_data2<uint64_t>();
-}
-
-template <typename AddressType>
-void DwarfMemoryTest::ReadEncodedValue_data4() {
- memory_.SetData32(0, 0xe0000000);
-
- uint64_t value = 0;
- ASSERT_TRUE(dwarf_mem_->ReadEncodedValue<AddressType>(0x03, &value));
- ASSERT_EQ(0xe0000000U, value);
-
- dwarf_mem_->set_cur_offset(0);
- ASSERT_TRUE(dwarf_mem_->ReadEncodedValue<AddressType>(0x0b, &value));
- ASSERT_EQ(0xffffffffe0000000ULL, value);
-}
-
-TEST_F(DwarfMemoryTest, ReadEncodedValue_data4_uint32_t) {
- ReadEncodedValue_data4<uint32_t>();
-}
-
-TEST_F(DwarfMemoryTest, ReadEncodedValue_data4_uint64_t) {
- ReadEncodedValue_data4<uint64_t>();
-}
-
-template <typename AddressType>
-void DwarfMemoryTest::ReadEncodedValue_data8() {
- memory_.SetData64(0, 0xe000000000000000ULL);
-
- uint64_t value = 0;
- ASSERT_TRUE(dwarf_mem_->ReadEncodedValue<AddressType>(0x04, &value));
- ASSERT_EQ(0xe000000000000000ULL, value);
-
- dwarf_mem_->set_cur_offset(0);
- ASSERT_TRUE(dwarf_mem_->ReadEncodedValue<AddressType>(0x0c, &value));
- ASSERT_EQ(0xe000000000000000ULL, value);
-}
-
-TEST_F(DwarfMemoryTest, ReadEncodedValue_data8_uint32_t) {
- ReadEncodedValue_data8<uint32_t>();
-}
-
-TEST_F(DwarfMemoryTest, ReadEncodedValue_data8_uint64_t) {
- ReadEncodedValue_data8<uint64_t>();
-}
-
-template <typename AddressType>
-void DwarfMemoryTest::ReadEncodedValue_non_zero_adjust() {
- memory_.SetData64(0, 0xe000000000000000ULL);
-
- uint64_t value = 0;
- dwarf_mem_->set_pc_offset(0x2000);
- ASSERT_TRUE(dwarf_mem_->ReadEncodedValue<AddressType>(0x14, &value));
- ASSERT_EQ(0xe000000000002000ULL, value);
-}
-
-TEST_F(DwarfMemoryTest, ReadEncodedValue_non_zero_adjust_uint32_t) {
- ReadEncodedValue_non_zero_adjust<uint32_t>();
-}
-
-TEST_F(DwarfMemoryTest, ReadEncodedValue_non_zero_adjust_uint64_t) {
- ReadEncodedValue_non_zero_adjust<uint64_t>();
-}
-
-template <typename AddressType>
-void DwarfMemoryTest::ReadEncodedValue_overflow() {
- memory_.SetData64(0, 0);
-
- uint64_t value = 0;
- dwarf_mem_->set_cur_offset(UINT64_MAX);
- ASSERT_FALSE(dwarf_mem_->ReadEncodedValue<AddressType>(0x50, &value));
-}
-
-TEST_F(DwarfMemoryTest, ReadEncodedValue_overflow_uint32_t) {
- ReadEncodedValue_overflow<uint32_t>();
-}
-
-TEST_F(DwarfMemoryTest, ReadEncodedValue_overflow_uint64_t) {
- ReadEncodedValue_overflow<uint64_t>();
-}
-
-template <typename AddressType>
-void DwarfMemoryTest::ReadEncodedValue_high_bit_set() {
- uint64_t value;
- memory_.SetData32(0, 0x15234);
- ASSERT_FALSE(dwarf_mem_->ReadEncodedValue<AddressType>(0xc3, &value));
-
- dwarf_mem_->set_func_offset(0x60000);
- dwarf_mem_->set_cur_offset(0);
- ASSERT_TRUE(dwarf_mem_->ReadEncodedValue<AddressType>(0xc3, &value));
- ASSERT_EQ(0x75234U, value);
-}
-
-TEST_F(DwarfMemoryTest, ReadEncodedValue_high_bit_set_uint32_t) {
- ReadEncodedValue_high_bit_set<uint32_t>();
-}
-
-TEST_F(DwarfMemoryTest, ReadEncodedValue_high_bit_set_uint64_t) {
- ReadEncodedValue_high_bit_set<uint64_t>();
-}
-
-template <typename AddressType>
-void DwarfMemoryTest::ReadEncodedValue_all() {
- MemoryFakeAlwaysReadZero memory;
- DwarfMemory dwarf_mem(&memory);
-
- for (size_t i = 0; i <= 0xff; i++) {
- uint64_t value;
- if (dwarf_mem.ReadEncodedValue<AddressType>(static_cast<uint8_t>(i), &value)) {
- ASSERT_EQ(0U, value);
- }
- }
-}
-
-TEST_F(DwarfMemoryTest, ReadEncodedValue_all_uint32_t) {
- ReadEncodedValue_all<uint32_t>();
-}
-
-TEST_F(DwarfMemoryTest, ReadEncodedValue_all_uint64_t) {
- ReadEncodedValue_all<uint64_t>();
-}
-
-TEST_F(DwarfMemoryTest, AdjustEncodedValue_absptr) {
- uint64_t value = 0x1234;
- ASSERT_TRUE(dwarf_mem_->AdjustEncodedValue(0x00, &value));
- ASSERT_EQ(0x1234U, value);
-}
-
-TEST_F(DwarfMemoryTest, AdjustEncodedValue_pcrel) {
- uint64_t value = 0x1234;
- ASSERT_FALSE(dwarf_mem_->AdjustEncodedValue(0x10, &value));
-
- dwarf_mem_->set_pc_offset(0x2000);
- ASSERT_TRUE(dwarf_mem_->AdjustEncodedValue(0x10, &value));
- ASSERT_EQ(0x3234U, value);
-
- dwarf_mem_->set_pc_offset(static_cast<uint64_t>(-4));
- value = 0x1234;
- ASSERT_TRUE(dwarf_mem_->AdjustEncodedValue(0x10, &value));
- ASSERT_EQ(0x1230U, value);
-}
-
-TEST_F(DwarfMemoryTest, AdjustEncodedValue_textrel) {
- uint64_t value = 0x8234;
- ASSERT_FALSE(dwarf_mem_->AdjustEncodedValue(0x20, &value));
-
- dwarf_mem_->set_text_offset(0x1000);
- ASSERT_TRUE(dwarf_mem_->AdjustEncodedValue(0x20, &value));
- ASSERT_EQ(0x9234U, value);
-
- dwarf_mem_->set_text_offset(static_cast<uint64_t>(-16));
- value = 0x8234;
- ASSERT_TRUE(dwarf_mem_->AdjustEncodedValue(0x20, &value));
- ASSERT_EQ(0x8224U, value);
-}
-
-TEST_F(DwarfMemoryTest, AdjustEncodedValue_datarel) {
- uint64_t value = 0xb234;
- ASSERT_FALSE(dwarf_mem_->AdjustEncodedValue(0x30, &value));
-
- dwarf_mem_->set_data_offset(0x1200);
- ASSERT_TRUE(dwarf_mem_->AdjustEncodedValue(0x30, &value));
- ASSERT_EQ(0xc434U, value);
-
- dwarf_mem_->set_data_offset(static_cast<uint64_t>(-256));
- value = 0xb234;
- ASSERT_TRUE(dwarf_mem_->AdjustEncodedValue(0x30, &value));
- ASSERT_EQ(0xb134U, value);
-}
-
-TEST_F(DwarfMemoryTest, AdjustEncodedValue_funcrel) {
- uint64_t value = 0x15234;
- ASSERT_FALSE(dwarf_mem_->AdjustEncodedValue(0x40, &value));
-
- dwarf_mem_->set_func_offset(0x60000);
- ASSERT_TRUE(dwarf_mem_->AdjustEncodedValue(0x40, &value));
- ASSERT_EQ(0x75234U, value);
-
- dwarf_mem_->set_func_offset(static_cast<uint64_t>(-4096));
- value = 0x15234;
- ASSERT_TRUE(dwarf_mem_->AdjustEncodedValue(0x40, &value));
- ASSERT_EQ(0x14234U, value);
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/DwarfOpLogTest.cpp b/libunwindstack/tests/DwarfOpLogTest.cpp
deleted file mode 100644
index 8dbf6e8..0000000
--- a/libunwindstack/tests/DwarfOpLogTest.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2016 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 <stdint.h>
-
-#include <ios>
-#include <vector>
-
-#include <gtest/gtest.h>
-
-#include <unwindstack/DwarfError.h>
-#include <unwindstack/DwarfMemory.h>
-#include <unwindstack/Log.h>
-#include <unwindstack/Regs.h>
-
-#include "DwarfOp.h"
-
-#include "MemoryFake.h"
-
-namespace unwindstack {
-
-template <typename TypeParam>
-class DwarfOpLogTest : public ::testing::Test {
- protected:
- void SetUp() override {
- op_memory_.Clear();
- regular_memory_.Clear();
- mem_.reset(new DwarfMemory(&op_memory_));
- op_.reset(new DwarfOp<TypeParam>(mem_.get(), ®ular_memory_));
- }
-
- MemoryFake op_memory_;
- MemoryFake regular_memory_;
-
- std::unique_ptr<DwarfMemory> mem_;
- std::unique_ptr<DwarfOp<TypeParam>> op_;
-};
-TYPED_TEST_SUITE_P(DwarfOpLogTest);
-
-TYPED_TEST_P(DwarfOpLogTest, multiple_ops) {
- // Multi operation opcodes.
- std::vector<uint8_t> opcode_buffer = {
- 0x0a, 0x20, 0x10, 0x08, 0x03, 0x12, 0x27,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- std::vector<std::string> lines;
- this->op_->GetLogInfo(0, opcode_buffer.size(), &lines);
- std::vector<std::string> expected{
- "DW_OP_const2u 4128", "Raw Data: 0x0a 0x20 0x10", "DW_OP_const1u 3", "Raw Data: 0x08 0x03",
- "DW_OP_dup", "Raw Data: 0x12", "DW_OP_xor", "Raw Data: 0x27"};
- ASSERT_EQ(expected, lines);
-}
-
-REGISTER_TYPED_TEST_SUITE_P(DwarfOpLogTest, multiple_ops);
-
-typedef ::testing::Types<uint32_t, uint64_t> DwarfOpLogTestTypes;
-INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfOpLogTest, DwarfOpLogTestTypes);
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/DwarfOpTest.cpp b/libunwindstack/tests/DwarfOpTest.cpp
deleted file mode 100644
index 0e2d91a..0000000
--- a/libunwindstack/tests/DwarfOpTest.cpp
+++ /dev/null
@@ -1,1586 +0,0 @@
-/*
- * Copyright (C) 2016 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 <stdint.h>
-
-#include <ios>
-#include <vector>
-
-#include <gtest/gtest.h>
-
-#include <unwindstack/DwarfError.h>
-#include <unwindstack/DwarfMemory.h>
-#include <unwindstack/Log.h>
-
-#include "DwarfOp.h"
-
-#include "MemoryFake.h"
-#include "RegsFake.h"
-
-namespace unwindstack {
-
-template <typename TypeParam>
-class DwarfOpTest : public ::testing::Test {
- protected:
- void SetUp() override {
- op_memory_.Clear();
- regular_memory_.Clear();
- mem_.reset(new DwarfMemory(&op_memory_));
- op_.reset(new DwarfOp<TypeParam>(mem_.get(), ®ular_memory_));
- }
-
- MemoryFake op_memory_;
- MemoryFake regular_memory_;
-
- std::unique_ptr<DwarfMemory> mem_;
- std::unique_ptr<DwarfOp<TypeParam>> op_;
-};
-TYPED_TEST_SUITE_P(DwarfOpTest);
-
-TYPED_TEST_P(DwarfOpTest, decode) {
- // Memory error.
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->LastErrorCode());
- EXPECT_EQ(0U, this->op_->LastErrorAddress());
-
- // No error.
- this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x96});
- this->mem_->set_cur_offset(0);
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_NONE, this->op_->LastErrorCode());
- ASSERT_EQ(0x96U, this->op_->cur_op());
- ASSERT_EQ(1U, this->mem_->cur_offset());
-}
-
-TYPED_TEST_P(DwarfOpTest, eval) {
- // Memory error.
- ASSERT_FALSE(this->op_->Eval(0, 2));
- ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->LastErrorCode());
- EXPECT_EQ(0U, this->op_->LastErrorAddress());
-
- // Register set.
- // Do this first, to verify that subsequent calls reset the value.
- this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x50});
- ASSERT_TRUE(this->op_->Eval(0, 1));
- ASSERT_TRUE(this->op_->is_register());
- ASSERT_EQ(1U, this->mem_->cur_offset());
- ASSERT_EQ(1U, this->op_->StackSize());
-
- // Multi operation opcodes.
- std::vector<uint8_t> opcode_buffer = {
- 0x08, 0x04, 0x08, 0x03, 0x08, 0x02, 0x08, 0x01,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_TRUE(this->op_->Eval(0, 8));
- ASSERT_EQ(DWARF_ERROR_NONE, this->op_->LastErrorCode());
- ASSERT_FALSE(this->op_->is_register());
- ASSERT_EQ(8U, this->mem_->cur_offset());
- ASSERT_EQ(4U, this->op_->StackSize());
- ASSERT_EQ(1U, this->op_->StackAt(0));
- ASSERT_EQ(2U, this->op_->StackAt(1));
- ASSERT_EQ(3U, this->op_->StackAt(2));
- ASSERT_EQ(4U, this->op_->StackAt(3));
-
- // Infinite loop.
- this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x2f, 0xfd, 0xff});
- ASSERT_FALSE(this->op_->Eval(0, 4));
- ASSERT_EQ(DWARF_ERROR_TOO_MANY_ITERATIONS, this->op_->LastErrorCode());
- ASSERT_FALSE(this->op_->is_register());
- ASSERT_EQ(0U, this->op_->StackSize());
-}
-
-TYPED_TEST_P(DwarfOpTest, illegal_opcode) {
- // Fill the buffer with all of the illegal opcodes.
- std::vector<uint8_t> opcode_buffer = {0x00, 0x01, 0x02, 0x04, 0x05, 0x07};
- for (size_t opcode = 0xa0; opcode < 256; opcode++) {
- opcode_buffer.push_back(opcode);
- }
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- for (size_t i = 0; i < opcode_buffer.size(); i++) {
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
- ASSERT_EQ(opcode_buffer[i], this->op_->cur_op());
- }
-}
-
-TYPED_TEST_P(DwarfOpTest, not_implemented) {
- std::vector<uint8_t> opcode_buffer = {
- // Push values so that any not implemented ops will return the right error.
- 0x08, 0x03, 0x08, 0x02, 0x08, 0x01,
- // xderef
- 0x18,
- // fbreg
- 0x91, 0x01,
- // piece
- 0x93, 0x01,
- // xderef_size
- 0x95, 0x01,
- // push_object_address
- 0x97,
- // call2
- 0x98, 0x01, 0x02,
- // call4
- 0x99, 0x01, 0x02, 0x03, 0x04,
- // call_ref
- 0x9a,
- // form_tls_address
- 0x9b,
- // call_frame_cfa
- 0x9c,
- // bit_piece
- 0x9d, 0x01, 0x01,
- // implicit_value
- 0x9e, 0x01,
- // stack_value
- 0x9f,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- // Push the stack values.
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_TRUE(this->op_->Decode());
-
- while (this->mem_->cur_offset() < opcode_buffer.size()) {
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_NOT_IMPLEMENTED, this->op_->LastErrorCode());
- }
-}
-
-TYPED_TEST_P(DwarfOpTest, op_addr) {
- std::vector<uint8_t> opcode_buffer = {0x03, 0x12, 0x23, 0x34, 0x45};
- if (sizeof(TypeParam) == 8) {
- opcode_buffer.push_back(0x56);
- opcode_buffer.push_back(0x67);
- opcode_buffer.push_back(0x78);
- opcode_buffer.push_back(0x89);
- }
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x03, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- if (sizeof(TypeParam) == 4) {
- ASSERT_EQ(0x45342312U, this->op_->StackAt(0));
- } else {
- ASSERT_EQ(0x8978675645342312UL, this->op_->StackAt(0));
- }
-}
-
-TYPED_TEST_P(DwarfOpTest, op_deref) {
- std::vector<uint8_t> opcode_buffer = {
- // Try a dereference with nothing on the stack.
- 0x06,
- // Add an address, then dereference.
- 0x0a, 0x10, 0x20, 0x06,
- // Now do another dereference that should fail in memory.
- 0x06,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
- TypeParam value = 0x12345678;
- this->regular_memory_.SetMemory(0x2010, &value, sizeof(value));
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x06, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(value, this->op_->StackAt(0));
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->LastErrorCode());
- ASSERT_EQ(0x12345678U, this->op_->LastErrorAddress());
-}
-
-TYPED_TEST_P(DwarfOpTest, op_deref_size) {
- this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x94});
- TypeParam value = 0x12345678;
- this->regular_memory_.SetMemory(0x2010, &value, sizeof(value));
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- // Read all byte sizes up to the sizeof the type.
- for (size_t i = 1; i < sizeof(TypeParam); i++) {
- this->op_memory_.SetMemory(
- 0, std::vector<uint8_t>{0x0a, 0x10, 0x20, 0x94, static_cast<uint8_t>(i)});
- ASSERT_TRUE(this->op_->Eval(0, 5)) << "Failed at size " << i;
- ASSERT_EQ(1U, this->op_->StackSize()) << "Failed at size " << i;
- ASSERT_EQ(0x94, this->op_->cur_op()) << "Failed at size " << i;
- TypeParam expected_value = 0;
- memcpy(&expected_value, &value, i);
- ASSERT_EQ(expected_value, this->op_->StackAt(0)) << "Failed at size " << i;
- }
-
- // Zero byte read.
- this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x0a, 0x10, 0x20, 0x94, 0x00});
- ASSERT_FALSE(this->op_->Eval(0, 5));
- ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
-
- // Read too many bytes.
- this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x0a, 0x10, 0x20, 0x94, sizeof(TypeParam) + 1});
- ASSERT_FALSE(this->op_->Eval(0, 5));
- ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
-
- // Force bad memory read.
- this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x0a, 0x10, 0x40, 0x94, 0x01});
- ASSERT_FALSE(this->op_->Eval(0, 5));
- ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->LastErrorCode());
- EXPECT_EQ(0x4010U, this->op_->LastErrorAddress());
-}
-
-TYPED_TEST_P(DwarfOpTest, const_unsigned) {
- std::vector<uint8_t> opcode_buffer = {
- // const1u
- 0x08, 0x12, 0x08, 0xff,
- // const2u
- 0x0a, 0x45, 0x12, 0x0a, 0x00, 0xff,
- // const4u
- 0x0c, 0x12, 0x23, 0x34, 0x45, 0x0c, 0x03, 0x02, 0x01, 0xff,
- // const8u
- 0x0e, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x0e, 0x87, 0x98, 0xa9, 0xba, 0xcb,
- 0xdc, 0xed, 0xfe,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- // const1u
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x08, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(0x12U, this->op_->StackAt(0));
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x08, this->op_->cur_op());
- ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_EQ(0xffU, this->op_->StackAt(0));
-
- // const2u
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x0a, this->op_->cur_op());
- ASSERT_EQ(3U, this->op_->StackSize());
- ASSERT_EQ(0x1245U, this->op_->StackAt(0));
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x0a, this->op_->cur_op());
- ASSERT_EQ(4U, this->op_->StackSize());
- ASSERT_EQ(0xff00U, this->op_->StackAt(0));
-
- // const4u
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x0c, this->op_->cur_op());
- ASSERT_EQ(5U, this->op_->StackSize());
- ASSERT_EQ(0x45342312U, this->op_->StackAt(0));
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x0c, this->op_->cur_op());
- ASSERT_EQ(6U, this->op_->StackSize());
- ASSERT_EQ(0xff010203U, this->op_->StackAt(0));
-
- // const8u
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x0e, this->op_->cur_op());
- ASSERT_EQ(7U, this->op_->StackSize());
- if (sizeof(TypeParam) == 4) {
- ASSERT_EQ(0x05060708U, this->op_->StackAt(0));
- } else {
- ASSERT_EQ(0x0102030405060708ULL, this->op_->StackAt(0));
- }
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x0e, this->op_->cur_op());
- ASSERT_EQ(8U, this->op_->StackSize());
- if (sizeof(TypeParam) == 4) {
- ASSERT_EQ(0xbaa99887UL, this->op_->StackAt(0));
- } else {
- ASSERT_EQ(0xfeeddccbbaa99887ULL, this->op_->StackAt(0));
- }
-}
-
-TYPED_TEST_P(DwarfOpTest, const_signed) {
- std::vector<uint8_t> opcode_buffer = {
- // const1s
- 0x09, 0x12, 0x09, 0xff,
- // const2s
- 0x0b, 0x21, 0x32, 0x0b, 0x08, 0xff,
- // const4s
- 0x0d, 0x45, 0x34, 0x23, 0x12, 0x0d, 0x01, 0x02, 0x03, 0xff,
- // const8s
- 0x0f, 0x89, 0x78, 0x67, 0x56, 0x45, 0x34, 0x23, 0x12, 0x0f, 0x04, 0x03, 0x02, 0x01, 0xef,
- 0xef, 0xef, 0xff,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- // const1s
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x09, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(0x12U, this->op_->StackAt(0));
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x09, this->op_->cur_op());
- ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_EQ(static_cast<TypeParam>(-1), this->op_->StackAt(0));
-
- // const2s
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x0b, this->op_->cur_op());
- ASSERT_EQ(3U, this->op_->StackSize());
- ASSERT_EQ(0x3221U, this->op_->StackAt(0));
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x0b, this->op_->cur_op());
- ASSERT_EQ(4U, this->op_->StackSize());
- ASSERT_EQ(static_cast<TypeParam>(-248), this->op_->StackAt(0));
-
- // const4s
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x0d, this->op_->cur_op());
- ASSERT_EQ(5U, this->op_->StackSize());
- ASSERT_EQ(0x12233445U, this->op_->StackAt(0));
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x0d, this->op_->cur_op());
- ASSERT_EQ(6U, this->op_->StackSize());
- ASSERT_EQ(static_cast<TypeParam>(-16580095), this->op_->StackAt(0));
-
- // const8s
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x0f, this->op_->cur_op());
- ASSERT_EQ(7U, this->op_->StackSize());
- if (sizeof(TypeParam) == 4) {
- ASSERT_EQ(0x56677889ULL, this->op_->StackAt(0));
- } else {
- ASSERT_EQ(0x1223344556677889ULL, this->op_->StackAt(0));
- }
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x0f, this->op_->cur_op());
- ASSERT_EQ(8U, this->op_->StackSize());
- if (sizeof(TypeParam) == 4) {
- ASSERT_EQ(0x01020304U, this->op_->StackAt(0));
- } else {
- ASSERT_EQ(static_cast<TypeParam>(-4521264810949884LL), this->op_->StackAt(0));
- }
-}
-
-TYPED_TEST_P(DwarfOpTest, const_uleb) {
- std::vector<uint8_t> opcode_buffer = {
- // Single byte ULEB128
- 0x10, 0x22, 0x10, 0x7f,
- // Multi byte ULEB128
- 0x10, 0xa2, 0x22, 0x10, 0xa2, 0x74, 0x10, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
- 0x09, 0x10, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x79,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- // Single byte ULEB128
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x10, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(0x22U, this->op_->StackAt(0));
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x10, this->op_->cur_op());
- ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_EQ(0x7fU, this->op_->StackAt(0));
-
- // Multi byte ULEB128
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x10, this->op_->cur_op());
- ASSERT_EQ(3U, this->op_->StackSize());
- ASSERT_EQ(0x1122U, this->op_->StackAt(0));
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x10, this->op_->cur_op());
- ASSERT_EQ(4U, this->op_->StackSize());
- ASSERT_EQ(0x3a22U, this->op_->StackAt(0));
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x10, this->op_->cur_op());
- ASSERT_EQ(5U, this->op_->StackSize());
- if (sizeof(TypeParam) == 4) {
- ASSERT_EQ(0x5080c101U, this->op_->StackAt(0));
- } else {
- ASSERT_EQ(0x9101c305080c101ULL, this->op_->StackAt(0));
- }
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x10, this->op_->cur_op());
- ASSERT_EQ(6U, this->op_->StackSize());
- if (sizeof(TypeParam) == 4) {
- ASSERT_EQ(0x5080c101U, this->op_->StackAt(0));
- } else {
- ASSERT_EQ(0x79101c305080c101ULL, this->op_->StackAt(0));
- }
-}
-
-TYPED_TEST_P(DwarfOpTest, const_sleb) {
- std::vector<uint8_t> opcode_buffer = {
- // Single byte SLEB128
- 0x11, 0x22, 0x11, 0x7f,
- // Multi byte SLEB128
- 0x11, 0xa2, 0x22, 0x11, 0xa2, 0x74, 0x11, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
- 0x09, 0x11,
- };
- if (sizeof(TypeParam) == 4) {
- opcode_buffer.push_back(0xb8);
- opcode_buffer.push_back(0xd3);
- opcode_buffer.push_back(0x63);
- } else {
- opcode_buffer.push_back(0x81);
- opcode_buffer.push_back(0x82);
- opcode_buffer.push_back(0x83);
- opcode_buffer.push_back(0x84);
- opcode_buffer.push_back(0x85);
- opcode_buffer.push_back(0x86);
- opcode_buffer.push_back(0x87);
- opcode_buffer.push_back(0x88);
- opcode_buffer.push_back(0x79);
- }
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- // Single byte SLEB128
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x11, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(0x22U, this->op_->StackAt(0));
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x11, this->op_->cur_op());
- ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_EQ(static_cast<TypeParam>(-1), this->op_->StackAt(0));
-
- // Multi byte SLEB128
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x11, this->op_->cur_op());
- ASSERT_EQ(3U, this->op_->StackSize());
- ASSERT_EQ(0x1122U, this->op_->StackAt(0));
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x11, this->op_->cur_op());
- ASSERT_EQ(4U, this->op_->StackSize());
- ASSERT_EQ(static_cast<TypeParam>(-1502), this->op_->StackAt(0));
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x11, this->op_->cur_op());
- ASSERT_EQ(5U, this->op_->StackSize());
- if (sizeof(TypeParam) == 4) {
- ASSERT_EQ(0x5080c101U, this->op_->StackAt(0));
- } else {
- ASSERT_EQ(0x9101c305080c101ULL, this->op_->StackAt(0));
- }
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x11, this->op_->cur_op());
- ASSERT_EQ(6U, this->op_->StackSize());
- if (sizeof(TypeParam) == 4) {
- ASSERT_EQ(static_cast<TypeParam>(-464456), this->op_->StackAt(0));
- } else {
- ASSERT_EQ(static_cast<TypeParam>(-499868564803501823LL), this->op_->StackAt(0));
- }
-}
-
-TYPED_TEST_P(DwarfOpTest, op_dup) {
- std::vector<uint8_t> opcode_buffer = {
- // Should fail since nothing is on the stack.
- 0x12,
- // Push on a value and dup.
- 0x08, 0x15, 0x12,
- // Do it again.
- 0x08, 0x23, 0x12,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(0x12, this->op_->cur_op());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x12, this->op_->cur_op());
- ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_EQ(0x15U, this->op_->StackAt(0));
- ASSERT_EQ(0x15U, this->op_->StackAt(1));
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(3U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x12, this->op_->cur_op());
- ASSERT_EQ(4U, this->op_->StackSize());
- ASSERT_EQ(0x23U, this->op_->StackAt(0));
- ASSERT_EQ(0x23U, this->op_->StackAt(1));
- ASSERT_EQ(0x15U, this->op_->StackAt(2));
- ASSERT_EQ(0x15U, this->op_->StackAt(3));
-}
-
-TYPED_TEST_P(DwarfOpTest, op_drop) {
- std::vector<uint8_t> opcode_buffer = {
- // Push a couple of values.
- 0x08, 0x10, 0x08, 0x20,
- // Drop the values.
- 0x13, 0x13,
- // Attempt to drop empty stack.
- 0x13,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(2U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x13, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(0x10U, this->op_->StackAt(0));
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x13, this->op_->cur_op());
- ASSERT_EQ(0U, this->op_->StackSize());
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(0x13, this->op_->cur_op());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-}
-
-TYPED_TEST_P(DwarfOpTest, op_over) {
- std::vector<uint8_t> opcode_buffer = {
- // Push a couple of values.
- 0x08, 0x1a, 0x08, 0xed,
- // Copy a value.
- 0x14,
- // Remove all but one element.
- 0x13, 0x13,
- // Provoke a failure with this opcode.
- 0x14,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(2U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x14, this->op_->cur_op());
- ASSERT_EQ(3U, this->op_->StackSize());
- ASSERT_EQ(0x1aU, this->op_->StackAt(0));
- ASSERT_EQ(0xedU, this->op_->StackAt(1));
- ASSERT_EQ(0x1aU, this->op_->StackAt(2));
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(0x14, this->op_->cur_op());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-}
-
-TYPED_TEST_P(DwarfOpTest, op_pick) {
- std::vector<uint8_t> opcode_buffer = {
- // Push a few values.
- 0x08, 0x1a, 0x08, 0xed, 0x08, 0x34,
- // Copy the value at offset 2.
- 0x15, 0x01,
- // Copy the last value in the stack.
- 0x15, 0x03,
- // Choose an invalid index.
- 0x15, 0x10,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(3U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x15, this->op_->cur_op());
- ASSERT_EQ(4U, this->op_->StackSize());
- ASSERT_EQ(0xedU, this->op_->StackAt(0));
- ASSERT_EQ(0x34U, this->op_->StackAt(1));
- ASSERT_EQ(0xedU, this->op_->StackAt(2));
- ASSERT_EQ(0x1aU, this->op_->StackAt(3));
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x15, this->op_->cur_op());
- ASSERT_EQ(5U, this->op_->StackSize());
- ASSERT_EQ(0x1aU, this->op_->StackAt(0));
- ASSERT_EQ(0xedU, this->op_->StackAt(1));
- ASSERT_EQ(0x34U, this->op_->StackAt(2));
- ASSERT_EQ(0xedU, this->op_->StackAt(3));
- ASSERT_EQ(0x1aU, this->op_->StackAt(4));
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(0x15, this->op_->cur_op());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-}
-
-TYPED_TEST_P(DwarfOpTest, op_swap) {
- std::vector<uint8_t> opcode_buffer = {
- // Push a couple of values.
- 0x08, 0x26, 0x08, 0xab,
- // Swap values.
- 0x16,
- // Pop a value to cause a failure.
- 0x13, 0x16,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_EQ(0xabU, this->op_->StackAt(0));
- ASSERT_EQ(0x26U, this->op_->StackAt(1));
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x16, this->op_->cur_op());
- ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_EQ(0x26U, this->op_->StackAt(0));
- ASSERT_EQ(0xabU, this->op_->StackAt(1));
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(0x16, this->op_->cur_op());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-}
-
-TYPED_TEST_P(DwarfOpTest, op_rot) {
- std::vector<uint8_t> opcode_buffer = {
- // Rotate that should cause a failure.
- 0x17, 0x08, 0x10,
- // Only 1 value on stack, should fail.
- 0x17, 0x08, 0x20,
- // Only 2 values on stack, should fail.
- 0x17, 0x08, 0x30,
- // Should rotate properly.
- 0x17,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(2U, this->op_->StackSize());
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(3U, this->op_->StackSize());
- ASSERT_EQ(0x30U, this->op_->StackAt(0));
- ASSERT_EQ(0x20U, this->op_->StackAt(1));
- ASSERT_EQ(0x10U, this->op_->StackAt(2));
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x17, this->op_->cur_op());
- ASSERT_EQ(3U, this->op_->StackSize());
- ASSERT_EQ(0x20U, this->op_->StackAt(0));
- ASSERT_EQ(0x10U, this->op_->StackAt(1));
- ASSERT_EQ(0x30U, this->op_->StackAt(2));
-}
-
-TYPED_TEST_P(DwarfOpTest, op_abs) {
- std::vector<uint8_t> opcode_buffer = {
- // Abs that should fail.
- 0x19,
- // A value that is already positive.
- 0x08, 0x10, 0x19,
- // A value that is negative.
- 0x11, 0x7f, 0x19,
- // A value that is large and negative.
- 0x11, 0x81, 0x80, 0x80, 0x80,
- };
- if (sizeof(TypeParam) == 4) {
- opcode_buffer.push_back(0x08);
- } else {
- opcode_buffer.push_back(0x80);
- opcode_buffer.push_back(0x80);
- opcode_buffer.push_back(0x01);
- }
- opcode_buffer.push_back(0x19);
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(0x10U, this->op_->StackAt(0));
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x19, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(0x10U, this->op_->StackAt(0));
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(2U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x19, this->op_->cur_op());
- ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_EQ(0x1U, this->op_->StackAt(0));
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(3U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x19, this->op_->cur_op());
- ASSERT_EQ(3U, this->op_->StackSize());
- if (sizeof(TypeParam) == 4) {
- ASSERT_EQ(2147483647U, this->op_->StackAt(0));
- } else {
- ASSERT_EQ(4398046511105UL, this->op_->StackAt(0));
- }
-}
-
-TYPED_TEST_P(DwarfOpTest, op_and) {
- std::vector<uint8_t> opcode_buffer = {
- // No stack, and op will fail.
- 0x1b,
- // Push a single value.
- 0x08, 0x20,
- // One element stack, and op will fail.
- 0x1b,
- // Push another value.
- 0x08, 0x02, 0x1b,
- // Push on two negative values.
- 0x11, 0x7c, 0x11, 0x7f, 0x1b,
- // Push one negative, one positive.
- 0x11, 0x10, 0x11, 0x7c, 0x1b,
- // Divide by zero.
- 0x11, 0x10, 0x11, 0x00, 0x1b,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- // Two positive values.
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(2U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x1b, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(0x10U, this->op_->StackAt(0));
-
- // Two negative values.
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(2U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(3U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x1b, this->op_->cur_op());
- ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_EQ(0x04U, this->op_->StackAt(0));
-
- // One negative value, one positive value.
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(3U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(4U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x1b, this->op_->cur_op());
- ASSERT_EQ(3U, this->op_->StackSize());
- ASSERT_EQ(static_cast<TypeParam>(-4), this->op_->StackAt(0));
-
- // Divide by zero.
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(4U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(5U, this->op_->StackSize());
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
-}
-
-TYPED_TEST_P(DwarfOpTest, op_div) {
- std::vector<uint8_t> opcode_buffer = {
- // No stack, and op will fail.
- 0x1a,
- // Push a single value.
- 0x08, 0x48,
- // One element stack, and op will fail.
- 0x1a,
- // Push another value.
- 0x08, 0xf0, 0x1a,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(2U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x1a, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(0x40U, this->op_->StackAt(0));
-}
-
-TYPED_TEST_P(DwarfOpTest, op_minus) {
- std::vector<uint8_t> opcode_buffer = {
- // No stack, and op will fail.
- 0x1c,
- // Push a single value.
- 0x08, 0x48,
- // One element stack, and op will fail.
- 0x1c,
- // Push another value.
- 0x08, 0x04, 0x1c,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(2U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x1c, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(0x44U, this->op_->StackAt(0));
-}
-
-TYPED_TEST_P(DwarfOpTest, op_mod) {
- std::vector<uint8_t> opcode_buffer = {
- // No stack, and op will fail.
- 0x1d,
- // Push a single value.
- 0x08, 0x47,
- // One element stack, and op will fail.
- 0x1d,
- // Push another value.
- 0x08, 0x04, 0x1d,
- // Try a mod of zero.
- 0x08, 0x01, 0x08, 0x00, 0x1d,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(2U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x1d, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(0x03U, this->op_->StackAt(0));
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(3U, this->op_->StackSize());
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
-}
-
-TYPED_TEST_P(DwarfOpTest, op_mul) {
- std::vector<uint8_t> opcode_buffer = {
- // No stack, and op will fail.
- 0x1e,
- // Push a single value.
- 0x08, 0x48,
- // One element stack, and op will fail.
- 0x1e,
- // Push another value.
- 0x08, 0x04, 0x1e,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(2U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x1e, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(0x120U, this->op_->StackAt(0));
-}
-
-TYPED_TEST_P(DwarfOpTest, op_neg) {
- std::vector<uint8_t> opcode_buffer = {
- // No stack, and op will fail.
- 0x1f,
- // Push a single value.
- 0x08, 0x48, 0x1f,
- // Push a negative value.
- 0x11, 0x7f, 0x1f,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x1f, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(static_cast<TypeParam>(-72), this->op_->StackAt(0));
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(2U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x1f, this->op_->cur_op());
- ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_EQ(0x01U, this->op_->StackAt(0));
-}
-
-TYPED_TEST_P(DwarfOpTest, op_not) {
- std::vector<uint8_t> opcode_buffer = {
- // No stack, and op will fail.
- 0x20,
- // Push a single value.
- 0x08, 0x4, 0x20,
- // Push a negative value.
- 0x11, 0x7c, 0x20,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x20, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(static_cast<TypeParam>(-5), this->op_->StackAt(0));
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(2U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x20, this->op_->cur_op());
- ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_EQ(0x03U, this->op_->StackAt(0));
-}
-
-TYPED_TEST_P(DwarfOpTest, op_or) {
- std::vector<uint8_t> opcode_buffer = {
- // No stack, and op will fail.
- 0x21,
- // Push a single value.
- 0x08, 0x48,
- // One element stack, and op will fail.
- 0x21,
- // Push another value.
- 0x08, 0xf4, 0x21,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(2U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x21, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(0xfcU, this->op_->StackAt(0));
-}
-
-TYPED_TEST_P(DwarfOpTest, op_plus) {
- std::vector<uint8_t> opcode_buffer = {
- // No stack, and op will fail.
- 0x22,
- // Push a single value.
- 0x08, 0xff,
- // One element stack, and op will fail.
- 0x22,
- // Push another value.
- 0x08, 0xf2, 0x22,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(2U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x22, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(0x1f1U, this->op_->StackAt(0));
-}
-
-TYPED_TEST_P(DwarfOpTest, op_plus_uconst) {
- std::vector<uint8_t> opcode_buffer = {
- // No stack, and op will fail.
- 0x23,
- // Push a single value.
- 0x08, 0x50, 0x23, 0x80, 0x51,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x23, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(0x28d0U, this->op_->StackAt(0));
-}
-
-TYPED_TEST_P(DwarfOpTest, op_shl) {
- std::vector<uint8_t> opcode_buffer = {
- // No stack, and op will fail.
- 0x24,
- // Push a single value.
- 0x08, 0x67,
- // One element stack, and op will fail.
- 0x24,
- // Push another value.
- 0x08, 0x03, 0x24,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(2U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x24, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(0x338U, this->op_->StackAt(0));
-}
-
-TYPED_TEST_P(DwarfOpTest, op_shr) {
- std::vector<uint8_t> opcode_buffer = {
- // No stack, and op will fail.
- 0x25,
- // Push a single value.
- 0x11, 0x70,
- // One element stack, and op will fail.
- 0x25,
- // Push another value.
- 0x08, 0x03, 0x25,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(2U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x25, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- if (sizeof(TypeParam) == 4) {
- ASSERT_EQ(0x1ffffffeU, this->op_->StackAt(0));
- } else {
- ASSERT_EQ(0x1ffffffffffffffeULL, this->op_->StackAt(0));
- }
-}
-
-TYPED_TEST_P(DwarfOpTest, op_shra) {
- std::vector<uint8_t> opcode_buffer = {
- // No stack, and op will fail.
- 0x26,
- // Push a single value.
- 0x11, 0x70,
- // One element stack, and op will fail.
- 0x26,
- // Push another value.
- 0x08, 0x03, 0x26,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(2U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x26, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(static_cast<TypeParam>(-2), this->op_->StackAt(0));
-}
-
-TYPED_TEST_P(DwarfOpTest, op_xor) {
- std::vector<uint8_t> opcode_buffer = {
- // No stack, and op will fail.
- 0x27,
- // Push a single value.
- 0x08, 0x11,
- // One element stack, and op will fail.
- 0x27,
- // Push another value.
- 0x08, 0x41, 0x27,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(2U, this->op_->StackSize());
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x27, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(0x50U, this->op_->StackAt(0));
-}
-
-TYPED_TEST_P(DwarfOpTest, op_bra) {
- std::vector<uint8_t> opcode_buffer = {
- // No stack, and op will fail.
- 0x28,
- // Push on a non-zero value with a positive branch.
- 0x08, 0x11, 0x28, 0x02, 0x01,
- // Push on a zero value with a positive branch.
- 0x08, 0x00, 0x28, 0x05, 0x00,
- // Push on a non-zero value with a negative branch.
- 0x08, 0x11, 0x28, 0xfc, 0xff,
- // Push on a zero value with a negative branch.
- 0x08, 0x00, 0x28, 0xf0, 0xff,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_FALSE(this->op_->Decode());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- // Push on a non-zero value with a positive branch.
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
-
- uint64_t offset = this->mem_->cur_offset() + 3;
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x28, this->op_->cur_op());
- ASSERT_EQ(0U, this->op_->StackSize());
- ASSERT_EQ(offset + 0x102, this->mem_->cur_offset());
-
- // Push on a zero value with a positive branch.
- this->mem_->set_cur_offset(offset);
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
-
- offset = this->mem_->cur_offset() + 3;
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x28, this->op_->cur_op());
- ASSERT_EQ(0U, this->op_->StackSize());
- ASSERT_EQ(offset - 5, this->mem_->cur_offset());
-
- // Push on a non-zero value with a negative branch.
- this->mem_->set_cur_offset(offset);
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
-
- offset = this->mem_->cur_offset() + 3;
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x28, this->op_->cur_op());
- ASSERT_EQ(0U, this->op_->StackSize());
- ASSERT_EQ(offset - 4, this->mem_->cur_offset());
-
- // Push on a zero value with a negative branch.
- this->mem_->set_cur_offset(offset);
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(1U, this->op_->StackSize());
-
- offset = this->mem_->cur_offset() + 3;
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x28, this->op_->cur_op());
- ASSERT_EQ(0U, this->op_->StackSize());
- ASSERT_EQ(offset + 16, this->mem_->cur_offset());
-}
-
-TYPED_TEST_P(DwarfOpTest, compare_opcode_stack_error) {
- // All of the ops require two stack elements. Loop through all of these
- // ops with potential errors.
- std::vector<uint8_t> opcode_buffer = {
- 0xff, // Place holder for compare op.
- 0x08, 0x11,
- 0xff, // Place holder for compare op.
- };
-
- for (uint8_t opcode = 0x29; opcode <= 0x2e; opcode++) {
- opcode_buffer[0] = opcode;
- opcode_buffer[3] = opcode;
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_FALSE(this->op_->Eval(0, 1));
- ASSERT_EQ(opcode, this->op_->cur_op());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
-
- ASSERT_FALSE(this->op_->Eval(1, 4));
- ASSERT_EQ(opcode, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- }
-}
-
-TYPED_TEST_P(DwarfOpTest, compare_opcodes) {
- // Have three different checks for each compare op:
- // - Both values the same.
- // - The first value larger than the second.
- // - The second value larger than the first.
- std::vector<uint8_t> opcode_buffer = {
- // Values the same.
- 0x08, 0x11, 0x08, 0x11,
- 0xff, // Placeholder.
- // First value larger.
- 0x08, 0x12, 0x08, 0x10,
- 0xff, // Placeholder.
- // Second value larger.
- 0x08, 0x10, 0x08, 0x12,
- 0xff, // Placeholder.
- };
-
- // Opcode followed by the expected values on the stack.
- std::vector<uint8_t> expected = {
- 0x29, 1, 0, 0, // eq
- 0x2a, 1, 1, 0, // ge
- 0x2b, 0, 1, 0, // gt
- 0x2c, 1, 0, 1, // le
- 0x2d, 0, 0, 1, // lt
- 0x2e, 0, 1, 1, // ne
- };
- for (size_t i = 0; i < expected.size(); i += 4) {
- opcode_buffer[4] = expected[i];
- opcode_buffer[9] = expected[i];
- opcode_buffer[14] = expected[i];
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_TRUE(this->op_->Eval(0, 15))
- << "Op: 0x" << std::hex << static_cast<uint32_t>(expected[i]) << " failed";
-
- ASSERT_EQ(3U, this->op_->StackSize());
- ASSERT_EQ(expected[i + 1], this->op_->StackAt(2));
- ASSERT_EQ(expected[i + 2], this->op_->StackAt(1));
- ASSERT_EQ(expected[i + 3], this->op_->StackAt(0));
- }
-}
-
-TYPED_TEST_P(DwarfOpTest, op_skip) {
- std::vector<uint8_t> opcode_buffer = {
- // Positive value.
- 0x2f, 0x10, 0x20,
- // Negative value.
- 0x2f, 0xfd, 0xff,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- uint64_t offset = this->mem_->cur_offset() + 3;
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x2f, this->op_->cur_op());
- ASSERT_EQ(0U, this->op_->StackSize());
- ASSERT_EQ(offset + 0x2010, this->mem_->cur_offset());
-
- this->mem_->set_cur_offset(offset);
- offset = this->mem_->cur_offset() + 3;
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x2f, this->op_->cur_op());
- ASSERT_EQ(0U, this->op_->StackSize());
- ASSERT_EQ(offset - 3, this->mem_->cur_offset());
-}
-
-TYPED_TEST_P(DwarfOpTest, op_lit) {
- std::vector<uint8_t> opcode_buffer;
-
- // Verify every lit opcode.
- for (uint8_t op = 0x30; op <= 0x4f; op++) {
- opcode_buffer.push_back(op);
- }
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- for (size_t i = 0; i < opcode_buffer.size(); i++) {
- uint32_t op = opcode_buffer[i];
- ASSERT_TRUE(this->op_->Eval(i, i + 1)) << "Failed op: 0x" << std::hex << op;
- ASSERT_EQ(op, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize()) << "Failed op: 0x" << std::hex << op;
- ASSERT_EQ(op - 0x30U, this->op_->StackAt(0)) << "Failed op: 0x" << std::hex << op;
- }
-}
-
-TYPED_TEST_P(DwarfOpTest, op_reg) {
- std::vector<uint8_t> opcode_buffer;
-
- // Verify every reg opcode.
- for (uint8_t op = 0x50; op <= 0x6f; op++) {
- opcode_buffer.push_back(op);
- }
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- for (size_t i = 0; i < opcode_buffer.size(); i++) {
- uint32_t op = opcode_buffer[i];
- ASSERT_TRUE(this->op_->Eval(i, i + 1)) << "Failed op: 0x" << std::hex << op;
- ASSERT_EQ(op, this->op_->cur_op());
- ASSERT_TRUE(this->op_->is_register()) << "Failed op: 0x" << std::hex << op;
- ASSERT_EQ(1U, this->op_->StackSize()) << "Failed op: 0x" << std::hex << op;
- ASSERT_EQ(op - 0x50U, this->op_->StackAt(0)) << "Failed op: 0x" << std::hex << op;
- }
-}
-
-TYPED_TEST_P(DwarfOpTest, op_regx) {
- std::vector<uint8_t> opcode_buffer = {
- 0x90, 0x02, 0x90, 0x80, 0x15,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- ASSERT_TRUE(this->op_->Eval(0, 2));
- ASSERT_EQ(0x90, this->op_->cur_op());
- ASSERT_TRUE(this->op_->is_register());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(0x02U, this->op_->StackAt(0));
-
- ASSERT_TRUE(this->op_->Eval(2, 5));
- ASSERT_EQ(0x90, this->op_->cur_op());
- ASSERT_TRUE(this->op_->is_register());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(0xa80U, this->op_->StackAt(0));
-}
-
-TYPED_TEST_P(DwarfOpTest, op_breg) {
- std::vector<uint8_t> opcode_buffer;
-
- // Verify every reg opcode.
- for (uint8_t op = 0x70; op <= 0x8f; op++) {
- // Positive value added to register.
- opcode_buffer.push_back(op);
- opcode_buffer.push_back(0x12);
- // Negative value added to register.
- opcode_buffer.push_back(op);
- opcode_buffer.push_back(0x7e);
- }
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- RegsImplFake<TypeParam> regs(32);
- for (size_t i = 0; i < 32; i++) {
- regs[i] = i + 10;
- }
- RegsInfo<TypeParam> regs_info(®s);
- this->op_->set_regs_info(®s_info);
-
- uint64_t offset = 0;
- for (uint32_t op = 0x70; op <= 0x8f; op++) {
- // Positive value added to register.
- ASSERT_TRUE(this->op_->Eval(offset, offset + 2)) << "Failed op: 0x" << std::hex << op;
- ASSERT_EQ(op, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize()) << "Failed op: 0x" << std::hex << op;
- ASSERT_EQ(op - 0x70 + 10 + 0x12, this->op_->StackAt(0)) << "Failed op: 0x" << std::hex << op;
- offset += 2;
-
- // Negative value added to register.
- ASSERT_TRUE(this->op_->Eval(offset, offset + 2)) << "Failed op: 0x" << std::hex << op;
- ASSERT_EQ(op, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize()) << "Failed op: 0x" << std::hex << op;
- ASSERT_EQ(op - 0x70 + 10 - 2, this->op_->StackAt(0)) << "Failed op: 0x" << std::hex << op;
- offset += 2;
- }
-}
-
-TYPED_TEST_P(DwarfOpTest, op_breg_invalid_register) {
- std::vector<uint8_t> opcode_buffer = {
- 0x7f, 0x12, 0x80, 0x12,
- };
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- RegsImplFake<TypeParam> regs(16);
- for (size_t i = 0; i < 16; i++) {
- regs[i] = i + 10;
- }
- RegsInfo<TypeParam> regs_info(®s);
- this->op_->set_regs_info(®s_info);
-
- // Should pass since this references the last regsister.
- ASSERT_TRUE(this->op_->Eval(0, 2));
- ASSERT_EQ(0x7fU, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(0x2bU, this->op_->StackAt(0));
-
- // Should fail since this references a non-existent register.
- ASSERT_FALSE(this->op_->Eval(2, 4));
- ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
-}
-
-TYPED_TEST_P(DwarfOpTest, op_bregx) {
- std::vector<uint8_t> opcode_buffer = {// Positive value added to register.
- 0x92, 0x05, 0x20,
- // Negative value added to register.
- 0x92, 0x06, 0x80, 0x7e,
- // Illegal register.
- 0x92, 0x80, 0x15, 0x80, 0x02};
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- RegsImplFake<TypeParam> regs(10);
- regs[5] = 0x45;
- regs[6] = 0x190;
- RegsInfo<TypeParam> regs_info(®s);
- this->op_->set_regs_info(®s_info);
-
- ASSERT_TRUE(this->op_->Eval(0, 3));
- ASSERT_EQ(0x92, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(0x65U, this->op_->StackAt(0));
-
- ASSERT_TRUE(this->op_->Eval(3, 7));
- ASSERT_EQ(0x92, this->op_->cur_op());
- ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_EQ(0x90U, this->op_->StackAt(0));
-
- ASSERT_FALSE(this->op_->Eval(7, 12));
- ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
-}
-
-TYPED_TEST_P(DwarfOpTest, op_nop) {
- this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x96});
-
- ASSERT_TRUE(this->op_->Decode());
- ASSERT_EQ(0x96, this->op_->cur_op());
- ASSERT_EQ(0U, this->op_->StackSize());
-}
-
-TYPED_TEST_P(DwarfOpTest, is_dex_pc) {
- // Special sequence that indicates this is a dex pc.
- this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x0c, 'D', 'E', 'X', '1', 0x13});
-
- ASSERT_TRUE(this->op_->Eval(0, 6));
- EXPECT_TRUE(this->op_->dex_pc_set());
-
- // Try without the last op.
- ASSERT_TRUE(this->op_->Eval(0, 5));
- EXPECT_FALSE(this->op_->dex_pc_set());
-
- // Change the constant.
- this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x0c, 'D', 'E', 'X', '2', 0x13});
- ASSERT_TRUE(this->op_->Eval(0, 6));
- EXPECT_FALSE(this->op_->dex_pc_set());
-}
-
-REGISTER_TYPED_TEST_SUITE_P(DwarfOpTest, decode, eval, illegal_opcode, not_implemented, op_addr,
- op_deref, op_deref_size, const_unsigned, const_signed, const_uleb,
- const_sleb, op_dup, op_drop, op_over, op_pick, op_swap, op_rot, op_abs,
- op_and, op_div, op_minus, op_mod, op_mul, op_neg, op_not, op_or,
- op_plus, op_plus_uconst, op_shl, op_shr, op_shra, op_xor, op_bra,
- compare_opcode_stack_error, compare_opcodes, op_skip, op_lit, op_reg,
- op_regx, op_breg, op_breg_invalid_register, op_bregx, op_nop,
- is_dex_pc);
-
-typedef ::testing::Types<uint32_t, uint64_t> DwarfOpTestTypes;
-INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfOpTest, DwarfOpTestTypes);
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/DwarfSectionImplTest.cpp b/libunwindstack/tests/DwarfSectionImplTest.cpp
deleted file mode 100644
index a08a8d0..0000000
--- a/libunwindstack/tests/DwarfSectionImplTest.cpp
+++ /dev/null
@@ -1,624 +0,0 @@
-/*
- * Copyright (C) 2016 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 <stdint.h>
-
-#include <gtest/gtest.h>
-
-#include <unwindstack/DwarfError.h>
-#include <unwindstack/DwarfSection.h>
-#include <unwindstack/Elf.h>
-
-#include "DwarfEncoding.h"
-
-#include "LogFake.h"
-#include "MemoryFake.h"
-#include "RegsFake.h"
-
-namespace unwindstack {
-
-template <typename TypeParam>
-class TestDwarfSectionImpl : public DwarfSectionImpl<TypeParam> {
- public:
- TestDwarfSectionImpl(Memory* memory) : DwarfSectionImpl<TypeParam>(memory) {}
- virtual ~TestDwarfSectionImpl() = default;
-
- bool Init(uint64_t, uint64_t, int64_t) override { return false; }
-
- void GetFdes(std::vector<const DwarfFde*>*) override {}
-
- const DwarfFde* GetFdeFromPc(uint64_t) override { return nullptr; }
-
- uint64_t GetCieOffsetFromFde32(uint32_t) { return 0; }
-
- uint64_t GetCieOffsetFromFde64(uint64_t) { return 0; }
-
- uint64_t AdjustPcFromFde(uint64_t) override { return 0; }
-
- void TestSetCachedCieLocRegs(uint64_t offset, const dwarf_loc_regs_t& loc_regs) {
- this->cie_loc_regs_[offset] = loc_regs;
- }
- void TestClearCachedCieLocRegs() { this->cie_loc_regs_.clear(); }
- void TestClearError() { this->last_error_.code = DWARF_ERROR_NONE; }
-};
-
-template <typename TypeParam>
-class DwarfSectionImplTest : public ::testing::Test {
- protected:
- void SetUp() override {
- memory_.Clear();
- section_ = new TestDwarfSectionImpl<TypeParam>(&memory_);
- ResetLogs();
- }
-
- void TearDown() override { delete section_; }
-
- MemoryFake memory_;
- TestDwarfSectionImpl<TypeParam>* section_ = nullptr;
-};
-TYPED_TEST_SUITE_P(DwarfSectionImplTest);
-
-// NOTE: All test class variables need to be referenced as this->.
-
-TYPED_TEST_P(DwarfSectionImplTest, GetCieFromOffset_fail_should_not_cache) {
- ASSERT_TRUE(this->section_->GetCieFromOffset(0x4000) == nullptr);
- EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
- EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
-
- this->section_->TestClearError();
- ASSERT_TRUE(this->section_->GetCieFromOffset(0x4000) == nullptr);
- EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
- EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_fail_should_not_cache) {
- ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
- EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
- EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
-
- this->section_->TestClearError();
- ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
- EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
- EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_eval_fail) {
- DwarfCie cie{.version = 3, .return_address_register = 5};
- RegsImplFake<TypeParam> regs(10);
- dwarf_loc_regs_t loc_regs;
-
- regs.set_pc(0x100);
- regs.set_sp(0x2000);
- regs[5] = 0x20;
- regs[9] = 0x3000;
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x2, 0x5002}};
- bool finished;
- ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
- EXPECT_EQ(0x5000U, this->section_->LastErrorAddress());
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_no_stack) {
- DwarfCie cie{.version = 3, .return_address_register = 5};
- RegsImplFake<TypeParam> regs(10);
- dwarf_loc_regs_t loc_regs;
-
- regs.set_pc(0x100);
- regs.set_sp(0x2000);
- regs[5] = 0x20;
- regs[9] = 0x3000;
- this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x96, 0x96, 0x96});
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x2, 0x5002}};
- bool finished;
- ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- EXPECT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->section_->LastErrorCode());
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr) {
- DwarfCie cie{.version = 3, .return_address_register = 5};
- RegsImplFake<TypeParam> regs(10);
- dwarf_loc_regs_t loc_regs;
-
- regs.set_pc(0x100);
- regs.set_sp(0x2000);
- regs[5] = 0x20;
- regs[9] = 0x3000;
- this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
- TypeParam cfa_value = 0x12345;
- this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value));
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5004}};
- bool finished;
- ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_val_expr) {
- DwarfCie cie{.version = 3, .return_address_register = 5};
- RegsImplFake<TypeParam> regs(10);
- dwarf_loc_regs_t loc_regs;
-
- regs.set_pc(0x100);
- regs.set_sp(0x2000);
- regs[5] = 0x20;
- regs[9] = 0x3000;
- this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5004}};
- bool finished;
- ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- ASSERT_FALSE(finished);
- EXPECT_EQ(0x80000000U, regs.sp());
- EXPECT_EQ(0x20U, regs.pc());
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_is_register) {
- DwarfCie cie{.version = 3, .return_address_register = 5};
- RegsImplFake<TypeParam> regs(10);
- dwarf_loc_regs_t loc_regs;
-
- regs.set_pc(0x100);
- regs.set_sp(0x2000);
- regs[5] = 0x20;
- regs[9] = 0x3000;
- this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x50, 0x96, 0x96});
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x2, 0x5002}};
- bool finished;
- ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- EXPECT_EQ(DWARF_ERROR_NOT_IMPLEMENTED, this->section_->LastErrorCode());
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, Eval_bad_regs) {
- DwarfCie cie{.return_address_register = 60};
- RegsImplFake<TypeParam> regs(10);
- dwarf_loc_regs_t loc_regs;
-
- bool finished;
- ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, Eval_no_cfa) {
- DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10);
- dwarf_loc_regs_t loc_regs;
-
- bool finished;
- ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- EXPECT_EQ(DWARF_ERROR_CFA_NOT_DEFINED, this->section_->LastErrorCode());
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_bad) {
- DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10);
- dwarf_loc_regs_t loc_regs;
-
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {20, 0}};
- bool finished;
- ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
-
- this->section_->TestClearError();
- loc_regs.erase(CFA_REG);
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_INVALID, {0, 0}};
- ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
-
- this->section_->TestClearError();
- loc_regs.erase(CFA_REG);
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_OFFSET, {0, 0}};
- ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
-
- this->section_->TestClearError();
- loc_regs.erase(CFA_REG);
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0, 0}};
- ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_prev) {
- DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10);
- dwarf_loc_regs_t loc_regs;
-
- regs.set_pc(0x100);
- regs.set_sp(0x2000);
- regs[5] = 0x20;
- regs[9] = 0x3000;
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {9, 0}};
- bool finished;
- ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- EXPECT_FALSE(finished);
- EXPECT_EQ(0x20U, regs.pc());
- EXPECT_EQ(0x3000U, regs.sp());
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_from_value) {
- DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10);
- dwarf_loc_regs_t loc_regs;
-
- regs.set_pc(0x100);
- regs.set_sp(0x2000);
- regs[5] = 0x20;
- regs[6] = 0x4000;
- regs[9] = 0x3000;
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {6, 0}};
- bool finished;
- ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- EXPECT_FALSE(finished);
- EXPECT_EQ(0x20U, regs.pc());
- EXPECT_EQ(0x4000U, regs.sp());
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, Eval_double_indirection) {
- DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10);
- dwarf_loc_regs_t loc_regs;
-
- regs.set_pc(0x100);
- regs.set_sp(0x2000);
- regs[1] = 0x100;
- regs[3] = 0x300;
- regs[8] = 0x10;
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
- loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {3, 1}};
- loc_regs[9] = DwarfLocation{DWARF_LOCATION_REGISTER, {1, 2}};
- bool finished;
- ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- EXPECT_EQ(0x301U, regs[1]);
- EXPECT_EQ(0x300U, regs[3]);
- EXPECT_EQ(0x10U, regs[8]);
- EXPECT_EQ(0x102U, regs[9]);
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, Eval_register_reference_chain) {
- DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10);
- dwarf_loc_regs_t loc_regs;
-
- regs.set_pc(0x100);
- regs.set_sp(0x2000);
- regs[0] = 0x10;
- regs[1] = 0x20;
- regs[2] = 0x30;
- regs[3] = 0x40;
- regs[4] = 0x50;
- regs[5] = 0x60;
- regs[8] = 0x20;
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
- loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {0, 1}};
- loc_regs[2] = DwarfLocation{DWARF_LOCATION_REGISTER, {1, 2}};
- loc_regs[3] = DwarfLocation{DWARF_LOCATION_REGISTER, {2, 3}};
- loc_regs[4] = DwarfLocation{DWARF_LOCATION_REGISTER, {3, 4}};
- loc_regs[5] = DwarfLocation{DWARF_LOCATION_REGISTER, {4, 5}};
- bool finished;
- ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- EXPECT_EQ(0x10U, regs[0]);
- EXPECT_EQ(0x11U, regs[1]);
- EXPECT_EQ(0x22U, regs[2]);
- EXPECT_EQ(0x33U, regs[3]);
- EXPECT_EQ(0x44U, regs[4]);
- EXPECT_EQ(0x55U, regs[5]);
- EXPECT_EQ(0x20U, regs[8]);
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, Eval_dex_pc) {
- DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10);
- dwarf_loc_regs_t loc_regs;
-
- regs.set_pc(0x100);
- regs.set_sp(0x2000);
- regs[0] = 0x10;
- regs[8] = 0x20;
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
- loc_regs[1] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x8, 0x5008}};
- this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 'D', 'E', 'X', '1', 0x13, 0x08, 0x11});
- bool finished;
- ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- EXPECT_EQ(0x10U, regs[0]);
- EXPECT_EQ(0x20U, regs[8]);
- EXPECT_EQ(0x11U, regs.dex_pc());
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, Eval_invalid_register) {
- DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10);
- dwarf_loc_regs_t loc_regs;
-
- regs.set_pc(0x100);
- regs.set_sp(0x2000);
- regs[8] = 0x10;
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
- loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {10, 0}};
- bool finished;
- ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, Eval_different_reg_locations) {
- DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10);
- dwarf_loc_regs_t loc_regs;
-
- if (sizeof(TypeParam) == sizeof(uint64_t)) {
- this->memory_.SetData64(0x2150, 0x12345678abcdef00ULL);
- } else {
- this->memory_.SetData32(0x2150, 0x12345678);
- }
-
- regs.set_pc(0x100);
- regs.set_sp(0x2000);
- regs[3] = 0x234;
- regs[5] = 0x10;
- regs[8] = 0x2100;
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
- loc_regs[1] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0x100, 0}};
- loc_regs[2] = DwarfLocation{DWARF_LOCATION_OFFSET, {0x50, 0}};
- loc_regs[3] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}};
- bool finished;
- ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- EXPECT_FALSE(finished);
- EXPECT_EQ(0x10U, regs.pc());
- EXPECT_EQ(0x2100U, regs.sp());
- EXPECT_EQ(0x2200U, regs[1]);
- EXPECT_EQ(0x234U, regs[3]);
- if (sizeof(TypeParam) == sizeof(uint64_t)) {
- EXPECT_EQ(0x12345678abcdef00ULL, regs[2]);
- } else {
- EXPECT_EQ(0x12345678U, regs[2]);
- }
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address_undefined) {
- DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10);
- dwarf_loc_regs_t loc_regs;
-
- regs.set_pc(0x100);
- regs.set_sp(0x2000);
- regs[5] = 0x20;
- regs[8] = 0x10;
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
- loc_regs[5] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}};
- bool finished;
- ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- EXPECT_TRUE(finished);
- EXPECT_EQ(0U, regs.pc());
- EXPECT_EQ(0x10U, regs.sp());
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, Eval_pc_zero) {
- DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10);
- dwarf_loc_regs_t loc_regs;
-
- regs.set_pc(0x100);
- regs.set_sp(0x2000);
- regs[5] = 0;
- regs[8] = 0x10;
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
- bool finished;
- ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- EXPECT_TRUE(finished);
- EXPECT_EQ(0U, regs.pc());
- EXPECT_EQ(0x10U, regs.sp());
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address) {
- DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10);
- dwarf_loc_regs_t loc_regs;
-
- regs.set_pc(0x100);
- regs.set_sp(0x2000);
- regs[5] = 0x20;
- regs[8] = 0x10;
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
- bool finished;
- ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- EXPECT_FALSE(finished);
- EXPECT_EQ(0x20U, regs.pc());
- EXPECT_EQ(0x10U, regs.sp());
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, Eval_ignore_large_reg_loc) {
- DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10);
- dwarf_loc_regs_t loc_regs;
-
- regs.set_pc(0x100);
- regs.set_sp(0x2000);
- regs[5] = 0x20;
- regs[8] = 0x10;
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
- // This should not result in any errors.
- loc_regs[20] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
- bool finished;
- ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- EXPECT_FALSE(finished);
- EXPECT_EQ(0x20U, regs.pc());
- EXPECT_EQ(0x10U, regs.sp());
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_expr) {
- DwarfCie cie{.version = 3, .return_address_register = 5};
- RegsImplFake<TypeParam> regs(10);
- dwarf_loc_regs_t loc_regs;
-
- regs.set_pc(0x100);
- regs.set_sp(0x2000);
- regs[8] = 0x3000;
- this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
- TypeParam cfa_value = 0x12345;
- this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value));
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
- loc_regs[5] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5004}};
- bool finished;
- ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- EXPECT_FALSE(finished);
- EXPECT_EQ(0x3000U, regs.sp());
- EXPECT_EQ(0x12345U, regs.pc());
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) {
- DwarfCie cie{.version = 3, .return_address_register = 5};
- RegsImplFake<TypeParam> regs(10);
- dwarf_loc_regs_t loc_regs;
-
- regs.set_pc(0x100);
- regs.set_sp(0x2000);
- regs[8] = 0x3000;
- this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
- loc_regs[5] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5004}};
- bool finished;
- ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- EXPECT_FALSE(finished);
- EXPECT_EQ(0x3000U, regs.sp());
- EXPECT_EQ(0x80000000U, regs.pc());
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, Eval_pseudo_register_invalid) {
- DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10);
- regs.set_pseudo_reg(11);
- dwarf_loc_regs_t loc_regs;
-
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
- loc_regs[1] = DwarfLocation{DWARF_LOCATION_PSEUDO_REGISTER, {20, 0}};
- bool finished;
- ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
-
- loc_regs.clear();
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
- loc_regs[12] = DwarfLocation{DWARF_LOCATION_PSEUDO_REGISTER, {20, 0}};
- ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, Eval_pseudo_register) {
- DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10);
- regs.set_pseudo_reg(11);
- dwarf_loc_regs_t loc_regs;
-
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
- loc_regs[11] = DwarfLocation{DWARF_LOCATION_PSEUDO_REGISTER, {20, 0}};
- bool finished;
- ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
- uint64_t pseudo_value = 0;
- ASSERT_TRUE(regs.GetPseudoRegister(11, &pseudo_value));
- EXPECT_EQ(20U, pseudo_value);
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_not_cached) {
- DwarfCie cie{};
- cie.cfa_instructions_offset = 0x3000;
- cie.cfa_instructions_end = 0x3002;
- DwarfFde fde{};
- fde.cie = &cie;
- fde.cie_offset = 0x8000;
- fde.cfa_instructions_offset = 0x6000;
- fde.cfa_instructions_end = 0x6002;
-
- this->memory_.SetMemory(0x3000, std::vector<uint8_t>{0x09, 0x02, 0x01});
- this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0x09, 0x04, 0x03});
-
- dwarf_loc_regs_t loc_regs;
- ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs, ARCH_UNKNOWN));
- ASSERT_EQ(2U, loc_regs.size());
-
- auto entry = loc_regs.find(2);
- ASSERT_NE(entry, loc_regs.end());
- ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
- ASSERT_EQ(1U, entry->second.values[0]);
-
- entry = loc_regs.find(4);
- ASSERT_NE(entry, loc_regs.end());
- ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
- ASSERT_EQ(3U, entry->second.values[0]);
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_cached) {
- DwarfCie cie{};
- cie.cfa_instructions_offset = 0x3000;
- cie.cfa_instructions_end = 0x3002;
- DwarfFde fde{};
- fde.cie = &cie;
- fde.cie_offset = 0x8000;
- fde.cfa_instructions_offset = 0x6000;
- fde.cfa_instructions_end = 0x6002;
-
- dwarf_loc_regs_t cie_loc_regs;
- cie_loc_regs[6] = DwarfLocation{DWARF_LOCATION_REGISTER, {4, 0}};
- this->section_->TestSetCachedCieLocRegs(0x8000, cie_loc_regs);
- this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0x09, 0x04, 0x03});
-
- dwarf_loc_regs_t loc_regs;
- ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs, ARCH_UNKNOWN));
- ASSERT_EQ(2U, loc_regs.size());
-
- auto entry = loc_regs.find(6);
- ASSERT_NE(entry, loc_regs.end());
- ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
- ASSERT_EQ(4U, entry->second.values[0]);
-
- entry = loc_regs.find(4);
- ASSERT_NE(entry, loc_regs.end());
- ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
- ASSERT_EQ(3U, entry->second.values[0]);
-}
-
-TYPED_TEST_P(DwarfSectionImplTest, Log) {
- DwarfCie cie{};
- cie.cfa_instructions_offset = 0x5000;
- cie.cfa_instructions_end = 0x5001;
- DwarfFde fde{};
- fde.cie = &cie;
- fde.cfa_instructions_offset = 0x6000;
- fde.cfa_instructions_end = 0x6001;
-
- this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x00});
- this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0xc2});
- ASSERT_TRUE(this->section_->Log(2, 0x1000, &fde, ARCH_UNKNOWN));
-
- ASSERT_EQ(
- "4 unwind DW_CFA_nop\n"
- "4 unwind Raw Data: 0x00\n"
- "4 unwind DW_CFA_restore register(2)\n"
- "4 unwind Raw Data: 0xc2\n",
- GetFakeLogPrint());
- ASSERT_EQ("", GetFakeLogBuf());
-}
-
-REGISTER_TYPED_TEST_SUITE_P(DwarfSectionImplTest, GetCieFromOffset_fail_should_not_cache,
- GetFdeFromOffset_fail_should_not_cache, Eval_cfa_expr_eval_fail,
- Eval_cfa_expr_no_stack, Eval_cfa_expr_is_register, Eval_cfa_expr,
- Eval_cfa_val_expr, Eval_bad_regs, Eval_no_cfa, Eval_cfa_bad,
- Eval_cfa_register_prev, Eval_cfa_register_from_value,
- Eval_double_indirection, Eval_register_reference_chain, Eval_dex_pc,
- Eval_invalid_register, Eval_different_reg_locations,
- Eval_return_address_undefined, Eval_pc_zero, Eval_return_address,
- Eval_ignore_large_reg_loc, Eval_reg_expr, Eval_reg_val_expr,
- Eval_pseudo_register_invalid, Eval_pseudo_register,
- GetCfaLocationInfo_cie_not_cached, GetCfaLocationInfo_cie_cached, Log);
-
-typedef ::testing::Types<uint32_t, uint64_t> DwarfSectionImplTestTypes;
-INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfSectionImplTest, DwarfSectionImplTestTypes);
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/DwarfSectionTest.cpp b/libunwindstack/tests/DwarfSectionTest.cpp
deleted file mode 100644
index e5a1aed..0000000
--- a/libunwindstack/tests/DwarfSectionTest.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (C) 2016 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 <stdint.h>
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include <unwindstack/DwarfSection.h>
-#include <unwindstack/Elf.h>
-
-#include "MemoryFake.h"
-#include "RegsFake.h"
-
-namespace unwindstack {
-
-class MockDwarfSection : public DwarfSection {
- public:
- MockDwarfSection(Memory* memory) : DwarfSection(memory) {}
- virtual ~MockDwarfSection() = default;
-
- MOCK_METHOD(bool, Init, (uint64_t, uint64_t, int64_t), (override));
-
- MOCK_METHOD(bool, Eval, (const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*),
- (override));
-
- MOCK_METHOD(bool, Log, (uint8_t, uint64_t, const DwarfFde*, ArchEnum arch), (override));
-
- MOCK_METHOD(void, GetFdes, (std::vector<const DwarfFde*>*), (override));
-
- MOCK_METHOD(const DwarfFde*, GetFdeFromPc, (uint64_t), (override));
-
- MOCK_METHOD(bool, GetCfaLocationInfo,
- (uint64_t, const DwarfFde*, dwarf_loc_regs_t*, ArchEnum arch), (override));
-
- MOCK_METHOD(uint64_t, GetCieOffsetFromFde32, (uint32_t), (override));
-
- MOCK_METHOD(uint64_t, GetCieOffsetFromFde64, (uint64_t), (override));
-
- MOCK_METHOD(uint64_t, AdjustPcFromFde, (uint64_t), (override));
-};
-
-class DwarfSectionTest : public ::testing::Test {
- protected:
- void SetUp() override { section_.reset(new MockDwarfSection(&memory_)); }
-
- MemoryFake memory_;
- std::unique_ptr<MockDwarfSection> section_;
- static RegsFake regs_;
-};
-
-RegsFake DwarfSectionTest::regs_(10);
-
-TEST_F(DwarfSectionTest, Step_fail_fde) {
- EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(nullptr));
-
- bool finished;
- bool is_signal_frame;
- ASSERT_FALSE(section_->Step(0x1000, nullptr, nullptr, &finished, &is_signal_frame));
-}
-
-TEST_F(DwarfSectionTest, Step_fail_cie_null) {
- DwarfFde fde{};
- fde.pc_end = 0x2000;
- fde.cie = nullptr;
-
- EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde));
-
- bool finished;
- bool is_signal_frame;
- ASSERT_FALSE(section_->Step(0x1000, ®s_, nullptr, &finished, &is_signal_frame));
-}
-
-TEST_F(DwarfSectionTest, Step_fail_cfa_location) {
- DwarfCie cie{};
- DwarfFde fde{};
- fde.pc_end = 0x2000;
- fde.cie = &cie;
-
- EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde));
- EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde, ::testing::_, ::testing::_))
- .WillOnce(::testing::Return(false));
-
- bool finished;
- bool is_signal_frame;
- ASSERT_FALSE(section_->Step(0x1000, ®s_, nullptr, &finished, &is_signal_frame));
-}
-
-TEST_F(DwarfSectionTest, Step_pass) {
- DwarfCie cie{};
- DwarfFde fde{};
- fde.pc_end = 0x2000;
- fde.cie = &cie;
-
- EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde));
- EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde, ::testing::_, ::testing::_))
- .WillOnce(::testing::Return(true));
-
- MemoryFake process;
- EXPECT_CALL(*section_, Eval(&cie, &process, ::testing::_, ®s_, ::testing::_))
- .WillOnce(::testing::Return(true));
-
- bool finished;
- bool is_signal_frame;
- ASSERT_TRUE(section_->Step(0x1000, ®s_, &process, &finished, &is_signal_frame));
-}
-
-static bool MockGetCfaLocationInfo(::testing::Unused, const DwarfFde* fde,
- dwarf_loc_regs_t* loc_regs, ArchEnum) {
- loc_regs->pc_start = fde->pc_start;
- loc_regs->pc_end = fde->pc_end;
- return true;
-}
-
-TEST_F(DwarfSectionTest, Step_cache) {
- DwarfCie cie{};
- DwarfFde fde{};
- fde.pc_start = 0x500;
- fde.pc_end = 0x2000;
- fde.cie = &cie;
-
- EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde));
- EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde, ::testing::_, ::testing::_))
- .WillOnce(::testing::Invoke(MockGetCfaLocationInfo));
-
- MemoryFake process;
- EXPECT_CALL(*section_, Eval(&cie, &process, ::testing::_, ®s_, ::testing::_))
- .WillRepeatedly(::testing::Return(true));
-
- bool 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) {
- DwarfCie cie{};
- DwarfFde fde0{};
- fde0.pc_start = 0x1000;
- fde0.pc_end = 0x2000;
- fde0.cie = &cie;
- EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde0));
- EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde0, ::testing::_, ::testing::_))
- .WillOnce(::testing::Invoke(MockGetCfaLocationInfo));
-
- MemoryFake process;
- EXPECT_CALL(*section_, Eval(&cie, &process, ::testing::_, ®s_, ::testing::_))
- .WillRepeatedly(::testing::Return(true));
-
- bool finished;
- bool is_signal_frame;
- ASSERT_TRUE(section_->Step(0x1000, ®s_, &process, &finished, &is_signal_frame));
-
- DwarfFde fde1{};
- fde1.pc_start = 0x500;
- fde1.pc_end = 0x800;
- fde1.cie = &cie;
- EXPECT_CALL(*section_, GetFdeFromPc(0x600)).WillOnce(::testing::Return(&fde1));
- EXPECT_CALL(*section_, GetCfaLocationInfo(0x600, &fde1, ::testing::_, ::testing::_))
- .WillOnce(::testing::Invoke(MockGetCfaLocationInfo));
-
- 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/ElfCacheTest.cpp b/libunwindstack/tests/ElfCacheTest.cpp
deleted file mode 100644
index 5f13546..0000000
--- a/libunwindstack/tests/ElfCacheTest.cpp
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright (C) 2018 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 <elf.h>
-#include <unistd.h>
-
-#include <android-base/file.h>
-
-#include <gtest/gtest.h>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/MapInfo.h>
-
-#include "ElfTestUtils.h"
-#include "MemoryFake.h"
-
-namespace unwindstack {
-
-class ElfCacheTest : public ::testing::Test {
- protected:
- static void SetUpTestSuite() { memory_.reset(new MemoryFake); }
-
- void SetUp() override { Elf::SetCachingEnabled(true); }
-
- void TearDown() override { Elf::SetCachingEnabled(false); }
-
- void WriteElfFile(uint64_t offset, TemporaryFile* tf, uint32_t type) {
- ASSERT_TRUE(type == EM_ARM || type == EM_386 || type == EM_X86_64);
- size_t ehdr_size;
- Elf32_Ehdr ehdr32;
- Elf64_Ehdr ehdr64;
- void* ptr;
- if (type == EM_ARM || type == EM_386) {
- ehdr_size = sizeof(ehdr32);
- ptr = &ehdr32;
- TestInitEhdr(&ehdr32, ELFCLASS32, type);
- } else {
- ehdr_size = sizeof(ehdr64);
- ptr = &ehdr64;
- TestInitEhdr(&ehdr64, ELFCLASS64, type);
- }
-
- ASSERT_EQ(offset, static_cast<uint64_t>(lseek(tf->fd, offset, SEEK_SET)));
- ASSERT_TRUE(android::base::WriteFully(tf->fd, ptr, ehdr_size));
- }
-
- void VerifyWithinSameMap(bool cache_enabled);
- void VerifySameMap(bool cache_enabled);
- void VerifyWithinSameMapNeverReadAtZero(bool cache_enabled);
-
- static std::shared_ptr<Memory> memory_;
-};
-
-std::shared_ptr<Memory> ElfCacheTest::memory_;
-
-void ElfCacheTest::VerifySameMap(bool cache_enabled) {
- if (!cache_enabled) {
- Elf::SetCachingEnabled(false);
- }
-
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
- WriteElfFile(0, &tf, EM_ARM);
- close(tf.fd);
-
- uint64_t start = 0x1000;
- uint64_t end = 0x20000;
- MapInfo info1(nullptr, nullptr, start, end, 0, 0x5, tf.path);
- MapInfo info2(nullptr, nullptr, start, end, 0, 0x5, tf.path);
-
- Elf* elf1 = info1.GetElf(memory_, ARCH_ARM);
- ASSERT_TRUE(elf1->valid());
- Elf* elf2 = info2.GetElf(memory_, ARCH_ARM);
- ASSERT_TRUE(elf2->valid());
-
- if (cache_enabled) {
- EXPECT_EQ(elf1, elf2);
- } else {
- EXPECT_NE(elf1, elf2);
- }
-}
-
-TEST_F(ElfCacheTest, no_caching) {
- VerifySameMap(false);
-}
-
-TEST_F(ElfCacheTest, caching_invalid_elf) {
- VerifySameMap(true);
-}
-
-void ElfCacheTest::VerifyWithinSameMap(bool cache_enabled) {
- if (!cache_enabled) {
- Elf::SetCachingEnabled(false);
- }
-
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
- WriteElfFile(0, &tf, EM_ARM);
- WriteElfFile(0x100, &tf, EM_386);
- WriteElfFile(0x200, &tf, EM_X86_64);
- lseek(tf.fd, 0x500, SEEK_SET);
- uint8_t value = 0;
- write(tf.fd, &value, 1);
- close(tf.fd);
-
- uint64_t start = 0x1000;
- uint64_t end = 0x20000;
- // Will have an elf at offset 0 in file.
- MapInfo info0_1(nullptr, nullptr, start, end, 0, 0x5, tf.path);
- MapInfo info0_2(nullptr, nullptr, start, end, 0, 0x5, tf.path);
- // Will have an elf at offset 0x100 in file.
- MapInfo info100_1(nullptr, nullptr, start, end, 0x100, 0x5, tf.path);
- MapInfo info100_2(nullptr, nullptr, start, end, 0x100, 0x5, tf.path);
- // Will have an elf at offset 0x200 in file.
- MapInfo info200_1(nullptr, nullptr, start, end, 0x200, 0x5, tf.path);
- MapInfo info200_2(nullptr, nullptr, start, end, 0x200, 0x5, tf.path);
- // Will have an elf at offset 0 in file.
- MapInfo info300_1(nullptr, nullptr, start, end, 0x300, 0x5, tf.path);
- MapInfo info300_2(nullptr, nullptr, start, end, 0x300, 0x5, tf.path);
-
- Elf* elf0_1 = info0_1.GetElf(memory_, ARCH_ARM);
- ASSERT_TRUE(elf0_1->valid());
- EXPECT_EQ(ARCH_ARM, elf0_1->arch());
- Elf* elf0_2 = info0_2.GetElf(memory_, ARCH_ARM);
- ASSERT_TRUE(elf0_2->valid());
- EXPECT_EQ(ARCH_ARM, elf0_2->arch());
- EXPECT_EQ(0U, info0_1.elf_offset);
- EXPECT_EQ(0U, info0_2.elf_offset);
- if (cache_enabled) {
- EXPECT_EQ(elf0_1, elf0_2);
- } else {
- EXPECT_NE(elf0_1, elf0_2);
- }
-
- Elf* elf100_1 = info100_1.GetElf(memory_, ARCH_X86);
- ASSERT_TRUE(elf100_1->valid());
- EXPECT_EQ(ARCH_X86, elf100_1->arch());
- Elf* elf100_2 = info100_2.GetElf(memory_, ARCH_X86);
- ASSERT_TRUE(elf100_2->valid());
- EXPECT_EQ(ARCH_X86, elf100_2->arch());
- EXPECT_EQ(0U, info100_1.elf_offset);
- EXPECT_EQ(0U, info100_2.elf_offset);
- if (cache_enabled) {
- EXPECT_EQ(elf100_1, elf100_2);
- } else {
- EXPECT_NE(elf100_1, elf100_2);
- }
-
- Elf* elf200_1 = info200_1.GetElf(memory_, ARCH_X86_64);
- ASSERT_TRUE(elf200_1->valid());
- EXPECT_EQ(ARCH_X86_64, elf200_1->arch());
- Elf* elf200_2 = info200_2.GetElf(memory_, ARCH_X86_64);
- ASSERT_TRUE(elf200_2->valid());
- EXPECT_EQ(ARCH_X86_64, elf200_2->arch());
- EXPECT_EQ(0U, info200_1.elf_offset);
- EXPECT_EQ(0U, info200_2.elf_offset);
- if (cache_enabled) {
- EXPECT_EQ(elf200_1, elf200_2);
- } else {
- EXPECT_NE(elf200_1, elf200_2);
- }
-
- Elf* elf300_1 = info300_1.GetElf(memory_, ARCH_ARM);
- ASSERT_TRUE(elf300_1->valid());
- EXPECT_EQ(ARCH_ARM, elf300_1->arch());
- Elf* elf300_2 = info300_2.GetElf(memory_, ARCH_ARM);
- ASSERT_TRUE(elf300_2->valid());
- EXPECT_EQ(ARCH_ARM, elf300_2->arch());
- EXPECT_EQ(0x300U, info300_1.elf_offset);
- EXPECT_EQ(0x300U, info300_2.elf_offset);
- if (cache_enabled) {
- EXPECT_EQ(elf300_1, elf300_2);
- EXPECT_EQ(elf0_1, elf300_1);
- } else {
- EXPECT_NE(elf300_1, elf300_2);
- EXPECT_NE(elf0_1, elf300_1);
- }
-}
-
-TEST_F(ElfCacheTest, no_caching_valid_elf_offset_non_zero) {
- VerifyWithinSameMap(false);
-}
-
-TEST_F(ElfCacheTest, caching_valid_elf_offset_non_zero) {
- VerifyWithinSameMap(true);
-}
-
-// Verify that when reading from multiple non-zero offsets in the same map
-// that when cached, all of the elf objects are the same.
-void ElfCacheTest::VerifyWithinSameMapNeverReadAtZero(bool cache_enabled) {
- if (!cache_enabled) {
- Elf::SetCachingEnabled(false);
- }
-
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
- WriteElfFile(0, &tf, EM_ARM);
- lseek(tf.fd, 0x500, SEEK_SET);
- uint8_t value = 0;
- write(tf.fd, &value, 1);
- close(tf.fd);
-
- uint64_t start = 0x1000;
- uint64_t end = 0x20000;
- // Multiple info sections at different offsets will have non-zero elf offsets.
- MapInfo info300_1(nullptr, nullptr, start, end, 0x300, 0x5, tf.path);
- MapInfo info300_2(nullptr, nullptr, start, end, 0x300, 0x5, tf.path);
- MapInfo info400_1(nullptr, nullptr, start, end, 0x400, 0x5, tf.path);
- MapInfo info400_2(nullptr, nullptr, start, end, 0x400, 0x5, tf.path);
-
- Elf* elf300_1 = info300_1.GetElf(memory_, ARCH_ARM);
- ASSERT_TRUE(elf300_1->valid());
- EXPECT_EQ(ARCH_ARM, elf300_1->arch());
- Elf* elf300_2 = info300_2.GetElf(memory_, ARCH_ARM);
- ASSERT_TRUE(elf300_2->valid());
- EXPECT_EQ(ARCH_ARM, elf300_2->arch());
- EXPECT_EQ(0x300U, info300_1.elf_offset);
- EXPECT_EQ(0x300U, info300_2.elf_offset);
- if (cache_enabled) {
- EXPECT_EQ(elf300_1, elf300_2);
- } else {
- EXPECT_NE(elf300_1, elf300_2);
- }
-
- Elf* elf400_1 = info400_1.GetElf(memory_, ARCH_ARM);
- ASSERT_TRUE(elf400_1->valid());
- EXPECT_EQ(ARCH_ARM, elf400_1->arch());
- Elf* elf400_2 = info400_2.GetElf(memory_, ARCH_ARM);
- ASSERT_TRUE(elf400_2->valid());
- EXPECT_EQ(ARCH_ARM, elf400_2->arch());
- EXPECT_EQ(0x400U, info400_1.elf_offset);
- EXPECT_EQ(0x400U, info400_2.elf_offset);
- if (cache_enabled) {
- EXPECT_EQ(elf400_1, elf400_2);
- EXPECT_EQ(elf300_1, elf400_1);
- } else {
- EXPECT_NE(elf400_1, elf400_2);
- EXPECT_NE(elf300_1, elf400_1);
- }
-}
-
-TEST_F(ElfCacheTest, no_caching_valid_elf_offset_non_zero_never_read_at_zero) {
- VerifyWithinSameMapNeverReadAtZero(false);
-}
-
-TEST_F(ElfCacheTest, caching_valid_elf_offset_non_zero_never_read_at_zero) {
- VerifyWithinSameMapNeverReadAtZero(true);
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/ElfFake.cpp b/libunwindstack/tests/ElfFake.cpp
deleted file mode 100644
index b16cd53..0000000
--- a/libunwindstack/tests/ElfFake.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2017 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 <stdint.h>
-
-#include <deque>
-#include <string>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/ElfInterface.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/Regs.h>
-
-#include "ElfFake.h"
-#include "RegsFake.h"
-
-namespace unwindstack {
-
-std::deque<FunctionData> ElfInterfaceFake::functions_;
-std::deque<StepData> ElfInterfaceFake::steps_;
-
-bool ElfInterfaceFake::GetFunctionName(uint64_t, std::string* name, uint64_t* offset) {
- if (functions_.empty()) {
- return false;
- }
- auto entry = functions_.front();
- functions_.pop_front();
- *name = entry.name;
- *offset = entry.offset;
- return true;
-}
-
-bool ElfInterfaceFake::GetGlobalVariable(const std::string& global, uint64_t* offset) {
- auto entry = globals_.find(global);
- if (entry == globals_.end()) {
- return false;
- }
- *offset = entry->second;
- return true;
-}
-
-bool ElfInterfaceFake::Step(uint64_t, Regs* regs, Memory*, bool* finished, bool* is_signal_frame) {
- if (steps_.empty()) {
- return false;
- }
- auto entry = steps_.front();
- steps_.pop_front();
-
- if (entry.pc == 0 && entry.sp == 0 && !entry.finished) {
- // Pretend as though there is no frame.
- return false;
- }
-
- RegsFake* fake_regs = reinterpret_cast<RegsFake*>(regs);
- fake_regs->set_pc(entry.pc);
- fake_regs->set_sp(entry.sp);
- *finished = entry.finished;
- *is_signal_frame = false;
- return true;
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/ElfFake.h b/libunwindstack/tests/ElfFake.h
deleted file mode 100644
index abda7b8..0000000
--- a/libunwindstack/tests/ElfFake.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef _LIBUNWINDSTACK_TESTS_ELF_FAKE_H
-#define _LIBUNWINDSTACK_TESTS_ELF_FAKE_H
-
-#include <stdint.h>
-
-#include <deque>
-#include <string>
-#include <unordered_map>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/ElfInterface.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/Regs.h>
-
-#include "ElfInterfaceArm.h"
-
-namespace unwindstack {
-
-struct StepData {
- StepData(uint64_t pc, uint64_t sp, bool finished) : pc(pc), sp(sp), finished(finished) {}
- uint64_t pc;
- uint64_t sp;
- bool finished;
-};
-
-struct FunctionData {
- FunctionData(std::string name, uint64_t offset) : name(name), offset(offset) {}
-
- std::string name;
- uint64_t offset;
-};
-
-class ElfFake : public Elf {
- public:
- ElfFake(Memory* memory) : Elf(memory) { valid_ = true; }
- virtual ~ElfFake() = default;
-
- void FakeSetValid(bool valid) { valid_ = valid; }
-
- void FakeSetLoadBias(uint64_t load_bias) { load_bias_ = load_bias; }
-
- void FakeSetArch(ArchEnum arch) { arch_ = arch; }
-
- void FakeSetInterface(ElfInterface* interface) { interface_.reset(interface); }
- void FakeSetGnuDebugdataInterface(ElfInterface* interface) {
- gnu_debugdata_interface_.reset(interface);
- }
-};
-
-class ElfInterfaceFake : public ElfInterface {
- public:
- ElfInterfaceFake(Memory* memory) : ElfInterface(memory) {}
- virtual ~ElfInterfaceFake() = default;
-
- bool Init(int64_t*) override { return false; }
- void InitHeaders() override {}
- std::string GetSoname() override { return fake_soname_; }
-
- bool GetFunctionName(uint64_t, std::string*, uint64_t*) override;
- bool GetGlobalVariable(const std::string&, uint64_t*) override;
- std::string GetBuildID() override { return fake_build_id_; }
-
- bool Step(uint64_t, Regs*, Memory*, bool*, bool*) override;
-
- void FakeSetGlobalVariable(const std::string& global, uint64_t offset) {
- globals_[global] = offset;
- }
-
- void FakeSetBuildID(std::string& build_id) { fake_build_id_ = build_id; }
- void FakeSetBuildID(const char* build_id) { fake_build_id_ = build_id; }
-
- void FakeSetSoname(const char* soname) { fake_soname_ = soname; }
-
- static void FakePushFunctionData(const FunctionData data) { functions_.push_back(data); }
- static void FakePushStepData(const StepData data) { steps_.push_back(data); }
-
- static void FakeClear() {
- functions_.clear();
- steps_.clear();
- }
-
- void FakeSetErrorCode(ErrorCode code) { last_error_.code = code; }
-
- void FakeSetErrorAddress(uint64_t address) { last_error_.address = address; }
-
- void FakeSetDataOffset(uint64_t offset) { data_offset_ = offset; }
- void FakeSetDataVaddrStart(uint64_t vaddr) { data_vaddr_start_ = vaddr; }
- void FakeSetDataVaddrEnd(uint64_t vaddr) { data_vaddr_end_ = vaddr; }
-
- void FakeSetDynamicOffset(uint64_t offset) { dynamic_offset_ = offset; }
- void FakeSetDynamicVaddrStart(uint64_t vaddr) { dynamic_vaddr_start_ = vaddr; }
- void FakeSetDynamicVaddrEnd(uint64_t vaddr) { dynamic_vaddr_end_ = vaddr; }
-
- void FakeSetGnuDebugdataOffset(uint64_t offset) { gnu_debugdata_offset_ = offset; }
- void FakeSetGnuDebugdataSize(uint64_t size) { gnu_debugdata_size_ = size; }
-
- private:
- std::unordered_map<std::string, uint64_t> globals_;
- std::string fake_build_id_;
- std::string fake_soname_;
-
- static std::deque<FunctionData> functions_;
- static std::deque<StepData> steps_;
-};
-
-class ElfInterface32Fake : public ElfInterface32 {
- public:
- ElfInterface32Fake(Memory* memory) : ElfInterface32(memory) {}
- virtual ~ElfInterface32Fake() = default;
-
- void FakeSetEhFrameOffset(uint64_t offset) { eh_frame_offset_ = offset; }
- void FakeSetEhFrameSize(uint64_t size) { eh_frame_size_ = size; }
- void FakeSetDebugFrameOffset(uint64_t offset) { debug_frame_offset_ = offset; }
- void FakeSetDebugFrameSize(uint64_t size) { debug_frame_size_ = size; }
-};
-
-class ElfInterface64Fake : public ElfInterface64 {
- public:
- ElfInterface64Fake(Memory* memory) : ElfInterface64(memory) {}
- virtual ~ElfInterface64Fake() = default;
-
- void FakeSetEhFrameOffset(uint64_t offset) { eh_frame_offset_ = offset; }
- void FakeSetEhFrameSize(uint64_t size) { eh_frame_size_ = size; }
- void FakeSetDebugFrameOffset(uint64_t offset) { debug_frame_offset_ = offset; }
- void FakeSetDebugFrameSize(uint64_t size) { debug_frame_size_ = size; }
-};
-
-class ElfInterfaceArmFake : public ElfInterfaceArm {
- public:
- ElfInterfaceArmFake(Memory* memory) : ElfInterfaceArm(memory) {}
- virtual ~ElfInterfaceArmFake() = default;
-
- void FakeSetStartOffset(uint64_t offset) { start_offset_ = offset; }
- void FakeSetTotalEntries(size_t entries) { total_entries_ = entries; }
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_TESTS_ELF_FAKE_H
diff --git a/libunwindstack/tests/ElfInterfaceArmTest.cpp b/libunwindstack/tests/ElfInterfaceArmTest.cpp
deleted file mode 100644
index 43c6a97..0000000
--- a/libunwindstack/tests/ElfInterfaceArmTest.cpp
+++ /dev/null
@@ -1,422 +0,0 @@
-/*
- * Copyright (C) 2016 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 <elf.h>
-
-#include <gtest/gtest.h>
-
-#include <vector>
-
-#include <unwindstack/MachineArm.h>
-#include <unwindstack/RegsArm.h>
-
-#include "ElfInterfaceArm.h"
-
-#include "ElfFake.h"
-#include "MemoryFake.h"
-
-namespace unwindstack {
-
-class ElfInterfaceArmTest : public ::testing::Test {
- protected:
- void SetUp() override {
- memory_.Clear();
- process_memory_.Clear();
- }
-
- MemoryFake memory_;
- MemoryFake process_memory_;
-};
-
-TEST_F(ElfInterfaceArmTest, GetPrel32Addr) {
- ElfInterfaceArmFake interface(&memory_);
- memory_.SetData32(0x1000, 0x230000);
-
- uint32_t value;
- ASSERT_TRUE(interface.GetPrel31Addr(0x1000, &value));
- ASSERT_EQ(0x231000U, value);
-
- memory_.SetData32(0x1000, 0x80001000);
- ASSERT_TRUE(interface.GetPrel31Addr(0x1000, &value));
- ASSERT_EQ(0x2000U, value);
-
- memory_.SetData32(0x1000, 0x70001000);
- ASSERT_TRUE(interface.GetPrel31Addr(0x1000, &value));
- ASSERT_EQ(0xf0002000U, value);
-}
-
-TEST_F(ElfInterfaceArmTest, FindEntry_start_zero) {
- ElfInterfaceArmFake interface(&memory_);
- interface.FakeSetStartOffset(0);
- interface.FakeSetTotalEntries(10);
-
- uint64_t entry_offset;
- ASSERT_FALSE(interface.FindEntry(0x1000, &entry_offset));
-}
-
-TEST_F(ElfInterfaceArmTest, FindEntry_no_entries) {
- ElfInterfaceArmFake interface(&memory_);
- interface.FakeSetStartOffset(0x100);
- interface.FakeSetTotalEntries(0);
-
- uint64_t entry_offset;
- ASSERT_FALSE(interface.FindEntry(0x1000, &entry_offset));
-}
-
-TEST_F(ElfInterfaceArmTest, FindEntry_no_valid_memory) {
- ElfInterfaceArmFake interface(&memory_);
- interface.FakeSetStartOffset(0x100);
- interface.FakeSetTotalEntries(2);
-
- uint64_t entry_offset;
- ASSERT_FALSE(interface.FindEntry(0x1000, &entry_offset));
-}
-
-TEST_F(ElfInterfaceArmTest, FindEntry_ip_before_first) {
- ElfInterfaceArmFake interface(&memory_);
- interface.FakeSetStartOffset(0x1000);
- interface.FakeSetTotalEntries(1);
- memory_.SetData32(0x1000, 0x6000);
-
- uint64_t entry_offset;
- ASSERT_FALSE(interface.FindEntry(0x1000, &entry_offset));
-}
-
-TEST_F(ElfInterfaceArmTest, FindEntry_single_entry_negative_value) {
- ElfInterfaceArmFake interface(&memory_);
- interface.FakeSetStartOffset(0x8000);
- interface.FakeSetTotalEntries(1);
- memory_.SetData32(0x8000, 0x7fffff00);
-
- uint64_t entry_offset;
- ASSERT_TRUE(interface.FindEntry(0x7ff0, &entry_offset));
- ASSERT_EQ(0x8000U, entry_offset);
-}
-
-TEST_F(ElfInterfaceArmTest, FindEntry_two_entries) {
- ElfInterfaceArmFake interface(&memory_);
- interface.FakeSetStartOffset(0x1000);
- interface.FakeSetTotalEntries(2);
- memory_.SetData32(0x1000, 0x6000);
- memory_.SetData32(0x1008, 0x7000);
-
- uint64_t entry_offset;
- ASSERT_TRUE(interface.FindEntry(0x7000, &entry_offset));
- ASSERT_EQ(0x1000U, entry_offset);
-}
-
-TEST_F(ElfInterfaceArmTest, FindEntry_last_check_single_entry) {
- ElfInterfaceArmFake interface(&memory_);
- interface.FakeSetStartOffset(0x1000);
- interface.FakeSetTotalEntries(1);
- memory_.SetData32(0x1000, 0x6000);
-
- uint64_t entry_offset;
- ASSERT_TRUE(interface.FindEntry(0x7000, &entry_offset));
- ASSERT_EQ(0x1000U, entry_offset);
-
- // To guarantee that we are using the cache on the second run,
- // set the memory to a different value.
- memory_.SetData32(0x1000, 0x8000);
- ASSERT_TRUE(interface.FindEntry(0x7004, &entry_offset));
- ASSERT_EQ(0x1000U, entry_offset);
-}
-
-TEST_F(ElfInterfaceArmTest, FindEntry_last_check_multiple_entries) {
- ElfInterfaceArmFake interface(&memory_);
- interface.FakeSetStartOffset(0x1000);
- interface.FakeSetTotalEntries(2);
- memory_.SetData32(0x1000, 0x6000);
- memory_.SetData32(0x1008, 0x8000);
-
- uint64_t entry_offset;
- ASSERT_TRUE(interface.FindEntry(0x9008, &entry_offset));
- ASSERT_EQ(0x1008U, entry_offset);
-
- // To guarantee that we are using the cache on the second run,
- // set the memory to a different value.
- memory_.SetData32(0x1000, 0x16000);
- memory_.SetData32(0x1008, 0x18000);
- ASSERT_TRUE(interface.FindEntry(0x9100, &entry_offset));
- ASSERT_EQ(0x1008U, entry_offset);
-}
-
-TEST_F(ElfInterfaceArmTest, FindEntry_multiple_entries_even) {
- ElfInterfaceArmFake interface(&memory_);
- interface.FakeSetStartOffset(0x1000);
- interface.FakeSetTotalEntries(4);
- memory_.SetData32(0x1000, 0x6000);
- memory_.SetData32(0x1008, 0x7000);
- memory_.SetData32(0x1010, 0x8000);
- memory_.SetData32(0x1018, 0x9000);
-
- uint64_t entry_offset;
- ASSERT_TRUE(interface.FindEntry(0x9100, &entry_offset));
- ASSERT_EQ(0x1010U, entry_offset);
-
- // To guarantee that we are using the cache on the second run,
- // set the memory to a different value.
- memory_.SetData32(0x1000, 0x16000);
- memory_.SetData32(0x1008, 0x17000);
- memory_.SetData32(0x1010, 0x18000);
- memory_.SetData32(0x1018, 0x19000);
- ASSERT_TRUE(interface.FindEntry(0x9100, &entry_offset));
- ASSERT_EQ(0x1010U, entry_offset);
-}
-
-TEST_F(ElfInterfaceArmTest, FindEntry_multiple_entries_odd) {
- ElfInterfaceArmFake interface(&memory_);
- interface.FakeSetStartOffset(0x1000);
- interface.FakeSetTotalEntries(5);
- memory_.SetData32(0x1000, 0x5000);
- memory_.SetData32(0x1008, 0x6000);
- memory_.SetData32(0x1010, 0x7000);
- memory_.SetData32(0x1018, 0x8000);
- memory_.SetData32(0x1020, 0x9000);
-
- uint64_t entry_offset;
- ASSERT_TRUE(interface.FindEntry(0x8100, &entry_offset));
- ASSERT_EQ(0x1010U, entry_offset);
-
- // To guarantee that we are using the cache on the second run,
- // set the memory to a different value.
- memory_.SetData32(0x1000, 0x15000);
- memory_.SetData32(0x1008, 0x16000);
- memory_.SetData32(0x1010, 0x17000);
- memory_.SetData32(0x1018, 0x18000);
- memory_.SetData32(0x1020, 0x19000);
- ASSERT_TRUE(interface.FindEntry(0x8100, &entry_offset));
- ASSERT_EQ(0x1010U, entry_offset);
-}
-
-TEST_F(ElfInterfaceArmTest, iterate) {
- ElfInterfaceArmFake interface(&memory_);
- interface.FakeSetStartOffset(0x1000);
- interface.FakeSetTotalEntries(5);
- memory_.SetData32(0x1000, 0x5000);
- memory_.SetData32(0x1008, 0x6000);
- memory_.SetData32(0x1010, 0x7000);
- memory_.SetData32(0x1018, 0x8000);
- memory_.SetData32(0x1020, 0x9000);
-
- std::vector<uint32_t> entries;
- for (auto addr : interface) {
- entries.push_back(addr);
- }
- ASSERT_EQ(5U, entries.size());
- ASSERT_EQ(0x6000U, entries[0]);
- ASSERT_EQ(0x7008U, entries[1]);
- ASSERT_EQ(0x8010U, entries[2]);
- ASSERT_EQ(0x9018U, entries[3]);
- ASSERT_EQ(0xa020U, entries[4]);
-
- // Make sure the iterate cached the entries.
- memory_.SetData32(0x1000, 0x11000);
- memory_.SetData32(0x1008, 0x12000);
- memory_.SetData32(0x1010, 0x13000);
- memory_.SetData32(0x1018, 0x14000);
- memory_.SetData32(0x1020, 0x15000);
-
- entries.clear();
- for (auto addr : interface) {
- entries.push_back(addr);
- }
- ASSERT_EQ(5U, entries.size());
- ASSERT_EQ(0x6000U, entries[0]);
- ASSERT_EQ(0x7008U, entries[1]);
- ASSERT_EQ(0x8010U, entries[2]);
- ASSERT_EQ(0x9018U, entries[3]);
- ASSERT_EQ(0xa020U, entries[4]);
-}
-
-TEST_F(ElfInterfaceArmTest, HandleUnknownType_arm_exidx) {
- ElfInterfaceArmFake interface(&memory_);
-
- interface.FakeSetStartOffset(0x1000);
- interface.FakeSetTotalEntries(100);
-
- // Verify that if the type is not the one we want, we don't set the values.
- interface.HandleUnknownType(0x70000000, 0x2000, 320);
- ASSERT_EQ(0x1000U, interface.start_offset());
- ASSERT_EQ(100U, interface.total_entries());
-
- // Everything is correct and present.
- interface.HandleUnknownType(0x70000001, 0x2000, 320);
- ASSERT_EQ(0x2000U, interface.start_offset());
- ASSERT_EQ(40U, interface.total_entries());
-}
-
-TEST_F(ElfInterfaceArmTest, StepExidx) {
- ElfInterfaceArmFake interface(&memory_);
-
- // FindEntry fails.
- bool finished;
- ASSERT_FALSE(interface.StepExidx(0x7000, nullptr, nullptr, &finished));
- EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode());
-
- // ExtractEntry should fail.
- interface.FakeSetStartOffset(0x1000);
- interface.FakeSetTotalEntries(2);
- memory_.SetData32(0x1000, 0x6000);
- memory_.SetData32(0x1008, 0x8000);
-
- RegsArm regs;
- regs[ARM_REG_SP] = 0x1000;
- regs[ARM_REG_LR] = 0x20000;
- regs.set_sp(regs[ARM_REG_SP]);
- regs.set_pc(0x1234);
- ASSERT_FALSE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished));
- EXPECT_EQ(ERROR_MEMORY_INVALID, interface.LastErrorCode());
- EXPECT_EQ(0x1004U, interface.LastErrorAddress());
-
- // Eval should fail.
- memory_.SetData32(0x1004, 0x81000000);
- ASSERT_FALSE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished));
- EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode());
-
- // Everything should pass.
- memory_.SetData32(0x1004, 0x80b0b0b0);
- ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished));
- EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode());
- ASSERT_FALSE(finished);
- ASSERT_EQ(0x1000U, regs.sp());
- ASSERT_EQ(0x1000U, regs[ARM_REG_SP]);
- ASSERT_EQ(0x20000U, regs.pc());
- ASSERT_EQ(0x20000U, regs[ARM_REG_PC]);
-
- // Load bias is non-zero.
- interface.set_load_bias(0x1000);
- ASSERT_TRUE(interface.StepExidx(0x8000, ®s, &process_memory_, &finished));
- EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode());
-
- // Pc too small.
- interface.set_load_bias(0x9000);
- ASSERT_FALSE(interface.StepExidx(0x8000, ®s, &process_memory_, &finished));
- EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode());
-}
-
-TEST_F(ElfInterfaceArmTest, StepExidx_pc_set) {
- ElfInterfaceArmFake interface(&memory_);
-
- interface.FakeSetStartOffset(0x1000);
- interface.FakeSetTotalEntries(2);
- memory_.SetData32(0x1000, 0x6000);
- memory_.SetData32(0x1004, 0x808800b0);
- memory_.SetData32(0x1008, 0x8000);
- process_memory_.SetData32(0x10000, 0x10);
-
- RegsArm regs;
- regs[ARM_REG_SP] = 0x10000;
- regs[ARM_REG_LR] = 0x20000;
- regs.set_sp(regs[ARM_REG_SP]);
- regs.set_pc(0x1234);
-
- // Everything should pass.
- bool finished;
- ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished));
- EXPECT_EQ(ERROR_NONE, interface.LastErrorCode());
- ASSERT_FALSE(finished);
- ASSERT_EQ(0x10004U, regs.sp());
- ASSERT_EQ(0x10004U, regs[ARM_REG_SP]);
- ASSERT_EQ(0x10U, regs.pc());
- ASSERT_EQ(0x10U, regs[ARM_REG_PC]);
-}
-
-TEST_F(ElfInterfaceArmTest, StepExidx_cant_unwind) {
- ElfInterfaceArmFake interface(&memory_);
-
- interface.FakeSetStartOffset(0x1000);
- interface.FakeSetTotalEntries(1);
- memory_.SetData32(0x1000, 0x6000);
- memory_.SetData32(0x1004, 1);
-
- RegsArm regs;
- regs[ARM_REG_SP] = 0x10000;
- regs[ARM_REG_LR] = 0x20000;
- regs.set_sp(regs[ARM_REG_SP]);
- regs.set_pc(0x1234);
-
- bool finished;
- ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished));
- EXPECT_EQ(ERROR_NONE, interface.LastErrorCode());
- ASSERT_TRUE(finished);
- ASSERT_EQ(0x10000U, regs.sp());
- ASSERT_EQ(0x10000U, regs[ARM_REG_SP]);
- ASSERT_EQ(0x1234U, regs.pc());
-}
-
-TEST_F(ElfInterfaceArmTest, StepExidx_refuse_unwind) {
- ElfInterfaceArmFake interface(&memory_);
-
- interface.FakeSetStartOffset(0x1000);
- interface.FakeSetTotalEntries(1);
- memory_.SetData32(0x1000, 0x6000);
- memory_.SetData32(0x1004, 0x808000b0);
-
- RegsArm regs;
- regs[ARM_REG_SP] = 0x10000;
- regs[ARM_REG_LR] = 0x20000;
- regs.set_sp(regs[ARM_REG_SP]);
- regs.set_pc(0x1234);
-
- bool finished;
- ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished));
- EXPECT_EQ(ERROR_NONE, interface.LastErrorCode());
- ASSERT_TRUE(finished);
- ASSERT_EQ(0x10000U, regs.sp());
- ASSERT_EQ(0x10000U, regs[ARM_REG_SP]);
- ASSERT_EQ(0x1234U, regs.pc());
-}
-
-TEST_F(ElfInterfaceArmTest, StepExidx_pc_zero) {
- ElfInterfaceArmFake interface(&memory_);
-
- interface.FakeSetStartOffset(0x1000);
- interface.FakeSetTotalEntries(1);
- memory_.SetData32(0x1000, 0x6000);
- // Set the pc using a pop r15 command.
- memory_.SetData32(0x1004, 0x808800b0);
-
- // pc value of zero.
- process_memory_.SetData32(0x10000, 0);
-
- RegsArm regs;
- regs[ARM_REG_SP] = 0x10000;
- regs[ARM_REG_LR] = 0x20000;
- regs.set_sp(regs[ARM_REG_SP]);
- regs.set_pc(0x1234);
-
- bool finished;
- ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished));
- EXPECT_EQ(ERROR_NONE, interface.LastErrorCode());
- ASSERT_TRUE(finished);
- ASSERT_EQ(0U, regs.pc());
-
- // Now set the pc from the lr register (pop r14).
- memory_.SetData32(0x1004, 0x808400b0);
-
- regs[ARM_REG_SP] = 0x10000;
- regs[ARM_REG_LR] = 0x20000;
- regs.set_sp(regs[ARM_REG_SP]);
- regs.set_pc(0x1234);
-
- ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished));
- EXPECT_EQ(ERROR_NONE, interface.LastErrorCode());
- ASSERT_TRUE(finished);
- ASSERT_EQ(0U, regs.pc());
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/ElfInterfaceTest.cpp b/libunwindstack/tests/ElfInterfaceTest.cpp
deleted file mode 100644
index 3cf90fe..0000000
--- a/libunwindstack/tests/ElfInterfaceTest.cpp
+++ /dev/null
@@ -1,1966 +0,0 @@
-/*
- * Copyright (C) 2016 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 <elf.h>
-
-#include <memory>
-
-#include <gtest/gtest.h>
-
-#include <unwindstack/ElfInterface.h>
-
-#include "DwarfEncoding.h"
-#include "ElfInterfaceArm.h"
-
-#include "ElfFake.h"
-#include "MemoryFake.h"
-
-#if !defined(PT_ARM_EXIDX)
-#define PT_ARM_EXIDX 0x70000001
-#endif
-
-#if !defined(EM_AARCH64)
-#define EM_AARCH64 183
-#endif
-
-namespace unwindstack {
-
-class ElfInterfaceTest : public ::testing::Test {
- protected:
- void SetUp() override {
- memory_.Clear();
- }
-
- void SetStringMemory(uint64_t offset, const char* string) {
- memory_.SetMemory(offset, string, strlen(string) + 1);
- }
-
- template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
- void SinglePtLoad();
-
- template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
- void MultipleExecutablePtLoads();
-
- template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
- void MultipleExecutablePtLoadsIncrementsNotSizeOfPhdr();
-
- template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
- void NonExecutablePtLoads();
-
- template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
- void ManyPhdrs();
-
- enum SonameTestEnum : uint8_t {
- SONAME_NORMAL,
- SONAME_DTNULL_AFTER,
- SONAME_DTSIZE_SMALL,
- SONAME_MISSING_MAP,
- };
-
- template <typename Ehdr, typename Phdr, typename Shdr, typename Dyn>
- void SonameInit(SonameTestEnum test_type = SONAME_NORMAL);
-
- template <typename ElfInterfaceType>
- void Soname();
-
- template <typename ElfInterfaceType>
- void SonameAfterDtNull();
-
- template <typename ElfInterfaceType>
- void SonameSize();
-
- template <typename ElfInterfaceType>
- void SonameMissingMap();
-
- template <typename ElfType>
- void InitHeadersEhFrameTest();
-
- template <typename ElfType>
- void InitHeadersDebugFrame();
-
- template <typename ElfType>
- void InitHeadersEhFrameFail();
-
- template <typename ElfType>
- void InitHeadersDebugFrameFail();
-
- template <typename Ehdr, typename Phdr, typename ElfInterfaceType>
- void InitProgramHeadersMalformed();
-
- template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
- void InitSectionHeadersMalformed();
-
- template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
- void InitSectionHeadersMalformedSymData();
-
- 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 Ehdr, typename Shdr, typename ElfInterfaceType>
- void InitSectionHeadersOffsetsEhFrameSectionBias(uint64_t addr, uint64_t offset,
- int64_t expected_bias);
-
- template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
- void InitSectionHeadersOffsetsEhFrameHdrSectionBias(uint64_t addr, uint64_t offset,
- int64_t expected_bias);
-
- template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
- void InitSectionHeadersOffsetsDebugFrameSectionBias(uint64_t addr, uint64_t offset,
- int64_t expected_bias);
-
- template <typename Ehdr, typename Phdr, typename ElfInterfaceType>
- void CheckGnuEhFrame(uint64_t addr, uint64_t offset, int64_t expected_bias);
-
- 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);
-
- template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
- void BuildID();
-
- template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
- void BuildIDTwoNotes();
-
- template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
- void BuildIDSectionTooSmallForName();
-
- template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
- void BuildIDSectionTooSmallForDesc();
-
- template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
- void BuildIDSectionTooSmallForHeader();
-
- template <typename Ehdr, typename Phdr, typename ElfInterfaceType>
- void CheckLoadBiasInFirstPhdr(int64_t load_bias);
-
- template <typename Ehdr, typename Phdr, typename ElfInterfaceType>
- void CheckLoadBiasInFirstExecPhdr(uint64_t offset, uint64_t vaddr, int64_t load_bias);
-
- 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 = {};
- 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_));
-
- Ehdr ehdr = {};
- ehdr.e_phoff = 0x100;
- ehdr.e_phnum = 1;
- ehdr.e_phentsize = sizeof(Phdr);
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- Phdr phdr = {};
- phdr.p_type = PT_LOAD;
- phdr.p_vaddr = 0x2000;
- phdr.p_memsz = 0x10000;
- phdr.p_flags = PF_R | PF_X;
- phdr.p_align = 0x1000;
- memory_.SetMemory(0x100, &phdr, sizeof(phdr));
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- EXPECT_EQ(0x2000, load_bias);
-
- const std::unordered_map<uint64_t, LoadInfo>& pt_loads = elf->pt_loads();
- ASSERT_EQ(1U, pt_loads.size());
- LoadInfo load_data = pt_loads.at(0);
- ASSERT_EQ(0U, load_data.offset);
- ASSERT_EQ(0x2000U, load_data.table_offset);
- ASSERT_EQ(0x10000U, load_data.table_size);
-}
-
-TEST_F(ElfInterfaceTest, single_pt_load_32) {
- SinglePtLoad<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn, ElfInterface32>();
-}
-
-TEST_F(ElfInterfaceTest, single_pt_load_64) {
- SinglePtLoad<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn, ElfInterface64>();
-}
-
-template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
-void ElfInterfaceTest::MultipleExecutablePtLoads() {
- std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
-
- Ehdr ehdr = {};
- ehdr.e_phoff = 0x100;
- ehdr.e_phnum = 3;
- ehdr.e_phentsize = sizeof(Phdr);
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- Phdr phdr = {};
- phdr.p_type = PT_LOAD;
- phdr.p_vaddr = 0x2000;
- phdr.p_memsz = 0x10000;
- phdr.p_flags = PF_R | PF_X;
- phdr.p_align = 0x1000;
- memory_.SetMemory(0x100, &phdr, sizeof(phdr));
-
- memset(&phdr, 0, sizeof(phdr));
- phdr.p_type = PT_LOAD;
- phdr.p_offset = 0x1000;
- phdr.p_vaddr = 0x2001;
- phdr.p_memsz = 0x10001;
- phdr.p_flags = PF_R | PF_X;
- phdr.p_align = 0x1001;
- memory_.SetMemory(0x100 + sizeof(phdr), &phdr, sizeof(phdr));
-
- memset(&phdr, 0, sizeof(phdr));
- phdr.p_type = PT_LOAD;
- phdr.p_offset = 0x2000;
- phdr.p_vaddr = 0x2002;
- phdr.p_memsz = 0x10002;
- phdr.p_flags = PF_R | PF_X;
- phdr.p_align = 0x1002;
- memory_.SetMemory(0x100 + 2 * sizeof(phdr), &phdr, sizeof(phdr));
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- EXPECT_EQ(0x2000, load_bias);
-
- const std::unordered_map<uint64_t, LoadInfo>& pt_loads = elf->pt_loads();
- ASSERT_EQ(3U, pt_loads.size());
-
- LoadInfo load_data = pt_loads.at(0);
- ASSERT_EQ(0U, load_data.offset);
- ASSERT_EQ(0x2000U, load_data.table_offset);
- ASSERT_EQ(0x10000U, load_data.table_size);
-
- load_data = pt_loads.at(0x1000);
- ASSERT_EQ(0x1000U, load_data.offset);
- ASSERT_EQ(0x2001U, load_data.table_offset);
- ASSERT_EQ(0x10001U, load_data.table_size);
-
- load_data = pt_loads.at(0x2000);
- ASSERT_EQ(0x2000U, load_data.offset);
- ASSERT_EQ(0x2002U, load_data.table_offset);
- ASSERT_EQ(0x10002U, load_data.table_size);
-}
-
-TEST_F(ElfInterfaceTest, multiple_executable_pt_loads_32) {
- MultipleExecutablePtLoads<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn, ElfInterface32>();
-}
-
-TEST_F(ElfInterfaceTest, multiple_executable_pt_loads_64) {
- MultipleExecutablePtLoads<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn, ElfInterface64>();
-}
-
-template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
-void ElfInterfaceTest::MultipleExecutablePtLoadsIncrementsNotSizeOfPhdr() {
- std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
-
- Ehdr ehdr = {};
- ehdr.e_phoff = 0x100;
- ehdr.e_phnum = 3;
- ehdr.e_phentsize = sizeof(Phdr) + 100;
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- Phdr phdr = {};
- phdr.p_type = PT_LOAD;
- phdr.p_vaddr = 0x2000;
- phdr.p_memsz = 0x10000;
- phdr.p_flags = PF_R | PF_X;
- phdr.p_align = 0x1000;
- memory_.SetMemory(0x100, &phdr, sizeof(phdr));
-
- memset(&phdr, 0, sizeof(phdr));
- phdr.p_type = PT_LOAD;
- phdr.p_offset = 0x1000;
- phdr.p_vaddr = 0x2001;
- phdr.p_memsz = 0x10001;
- phdr.p_flags = PF_R | PF_X;
- phdr.p_align = 0x1001;
- memory_.SetMemory(0x100 + sizeof(phdr) + 100, &phdr, sizeof(phdr));
-
- memset(&phdr, 0, sizeof(phdr));
- phdr.p_type = PT_LOAD;
- phdr.p_offset = 0x2000;
- phdr.p_vaddr = 0x2002;
- phdr.p_memsz = 0x10002;
- phdr.p_flags = PF_R | PF_X;
- phdr.p_align = 0x1002;
- memory_.SetMemory(0x100 + 2 * (sizeof(phdr) + 100), &phdr, sizeof(phdr));
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- EXPECT_EQ(0x2000, load_bias);
-
- const std::unordered_map<uint64_t, LoadInfo>& pt_loads = elf->pt_loads();
- ASSERT_EQ(3U, pt_loads.size());
-
- LoadInfo load_data = pt_loads.at(0);
- ASSERT_EQ(0U, load_data.offset);
- ASSERT_EQ(0x2000U, load_data.table_offset);
- ASSERT_EQ(0x10000U, load_data.table_size);
-
- load_data = pt_loads.at(0x1000);
- ASSERT_EQ(0x1000U, load_data.offset);
- ASSERT_EQ(0x2001U, load_data.table_offset);
- ASSERT_EQ(0x10001U, load_data.table_size);
-
- load_data = pt_loads.at(0x2000);
- ASSERT_EQ(0x2000U, load_data.offset);
- ASSERT_EQ(0x2002U, load_data.table_offset);
- ASSERT_EQ(0x10002U, load_data.table_size);
-}
-
-TEST_F(ElfInterfaceTest, multiple_executable_pt_loads_increments_not_size_of_phdr_32) {
- MultipleExecutablePtLoadsIncrementsNotSizeOfPhdr<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn,
- ElfInterface32>();
-}
-
-TEST_F(ElfInterfaceTest, multiple_executable_pt_loads_increments_not_size_of_phdr_64) {
- MultipleExecutablePtLoadsIncrementsNotSizeOfPhdr<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn,
- ElfInterface64>();
-}
-
-template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
-void ElfInterfaceTest::NonExecutablePtLoads() {
- std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
-
- Ehdr ehdr = {};
- ehdr.e_phoff = 0x100;
- ehdr.e_phnum = 3;
- ehdr.e_phentsize = sizeof(Phdr);
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- Phdr phdr = {};
- phdr.p_type = PT_LOAD;
- phdr.p_vaddr = 0x2000;
- phdr.p_memsz = 0x10000;
- phdr.p_flags = PF_R;
- phdr.p_align = 0x1000;
- memory_.SetMemory(0x100, &phdr, sizeof(phdr));
-
- memset(&phdr, 0, sizeof(phdr));
- phdr.p_type = PT_LOAD;
- phdr.p_offset = 0x1000;
- phdr.p_vaddr = 0x2001;
- phdr.p_memsz = 0x10001;
- phdr.p_flags = PF_R | PF_X;
- phdr.p_align = 0x1001;
- memory_.SetMemory(0x100 + sizeof(phdr), &phdr, sizeof(phdr));
-
- memset(&phdr, 0, sizeof(phdr));
- phdr.p_type = PT_LOAD;
- phdr.p_offset = 0x2000;
- phdr.p_vaddr = 0x2002;
- phdr.p_memsz = 0x10002;
- phdr.p_flags = PF_R;
- phdr.p_align = 0x1002;
- memory_.SetMemory(0x100 + 2 * sizeof(phdr), &phdr, sizeof(phdr));
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- EXPECT_EQ(0x1001, load_bias);
-
- const std::unordered_map<uint64_t, LoadInfo>& pt_loads = elf->pt_loads();
- ASSERT_EQ(1U, pt_loads.size());
-
- LoadInfo load_data = pt_loads.at(0x1000);
- ASSERT_EQ(0x1000U, load_data.offset);
- ASSERT_EQ(0x2001U, load_data.table_offset);
- ASSERT_EQ(0x10001U, load_data.table_size);
-}
-
-TEST_F(ElfInterfaceTest, non_executable_pt_loads_32) {
- NonExecutablePtLoads<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn, ElfInterface32>();
-}
-
-TEST_F(ElfInterfaceTest, non_executable_pt_loads_64) {
- NonExecutablePtLoads<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn, ElfInterface64>();
-}
-
-template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
-void ElfInterfaceTest::ManyPhdrs() {
- std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
-
- Ehdr ehdr = {};
- ehdr.e_phoff = 0x100;
- ehdr.e_phnum = 7;
- ehdr.e_phentsize = sizeof(Phdr);
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- uint64_t phdr_offset = 0x100;
-
- Phdr phdr = {};
- phdr.p_type = PT_LOAD;
- phdr.p_vaddr = 0x2000;
- phdr.p_memsz = 0x10000;
- phdr.p_flags = PF_R | PF_X;
- phdr.p_align = 0x1000;
- memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr));
- phdr_offset += sizeof(phdr);
-
- memset(&phdr, 0, sizeof(phdr));
- phdr.p_type = PT_GNU_EH_FRAME;
- memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr));
- phdr_offset += sizeof(phdr);
-
- memset(&phdr, 0, sizeof(phdr));
- phdr.p_type = PT_DYNAMIC;
- memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr));
- phdr_offset += sizeof(phdr);
-
- memset(&phdr, 0, sizeof(phdr));
- phdr.p_type = PT_INTERP;
- memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr));
- phdr_offset += sizeof(phdr);
-
- memset(&phdr, 0, sizeof(phdr));
- phdr.p_type = PT_NOTE;
- memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr));
- phdr_offset += sizeof(phdr);
-
- memset(&phdr, 0, sizeof(phdr));
- phdr.p_type = PT_SHLIB;
- memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr));
- phdr_offset += sizeof(phdr);
-
- memset(&phdr, 0, sizeof(phdr));
- phdr.p_type = PT_GNU_EH_FRAME;
- memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr));
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- EXPECT_EQ(0x2000, load_bias);
-
- const std::unordered_map<uint64_t, LoadInfo>& pt_loads = elf->pt_loads();
- ASSERT_EQ(1U, pt_loads.size());
-
- LoadInfo load_data = pt_loads.at(0);
- ASSERT_EQ(0U, load_data.offset);
- ASSERT_EQ(0x2000U, load_data.table_offset);
- ASSERT_EQ(0x10000U, load_data.table_size);
-}
-
-TEST_F(ElfInterfaceTest, many_phdrs_32) {
- ElfInterfaceTest::ManyPhdrs<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn, ElfInterface32>();
-}
-
-TEST_F(ElfInterfaceTest, many_phdrs_64) {
- ElfInterfaceTest::ManyPhdrs<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn, ElfInterface64>();
-}
-
-TEST_F(ElfInterfaceTest, arm32) {
- ElfInterfaceArm elf_arm(&memory_);
-
- Elf32_Ehdr ehdr = {};
- ehdr.e_phoff = 0x100;
- ehdr.e_phnum = 1;
- ehdr.e_phentsize = sizeof(Elf32_Phdr);
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- Elf32_Phdr phdr = {};
- phdr.p_type = PT_ARM_EXIDX;
- phdr.p_offset = 0x2000;
- phdr.p_filesz = 16;
- memory_.SetMemory(0x100, &phdr, sizeof(phdr));
-
- // Add arm exidx entries.
- memory_.SetData32(0x2000, 0x1000);
- memory_.SetData32(0x2008, 0x1000);
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf_arm.Init(&load_bias));
- EXPECT_EQ(0, load_bias);
-
- std::vector<uint32_t> entries;
- for (auto addr : elf_arm) {
- entries.push_back(addr);
- }
- ASSERT_EQ(2U, entries.size());
- ASSERT_EQ(0x3000U, entries[0]);
- ASSERT_EQ(0x3008U, entries[1]);
-
- ASSERT_EQ(0x2000U, elf_arm.start_offset());
- ASSERT_EQ(2U, elf_arm.total_entries());
-}
-
-template <typename Ehdr, typename Phdr, typename Shdr, typename Dyn>
-void ElfInterfaceTest::SonameInit(SonameTestEnum test_type) {
- Ehdr ehdr = {};
- ehdr.e_shoff = 0x200;
- ehdr.e_shnum = 2;
- ehdr.e_shentsize = sizeof(Shdr);
- ehdr.e_phoff = 0x100;
- ehdr.e_phnum = 1;
- ehdr.e_phentsize = sizeof(Phdr);
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- Shdr shdr = {};
- shdr.sh_type = SHT_STRTAB;
- if (test_type == SONAME_MISSING_MAP) {
- shdr.sh_addr = 0x20100;
- } else {
- shdr.sh_addr = 0x10100;
- }
- shdr.sh_offset = 0x10000;
- memory_.SetMemory(0x200 + sizeof(shdr), &shdr, sizeof(shdr));
-
- Phdr phdr = {};
- phdr.p_type = PT_DYNAMIC;
- phdr.p_offset = 0x2000;
- phdr.p_memsz = sizeof(Dyn) * 3;
- memory_.SetMemory(0x100, &phdr, sizeof(phdr));
-
- uint64_t offset = 0x2000;
- Dyn dyn;
-
- dyn.d_tag = DT_STRTAB;
- dyn.d_un.d_ptr = 0x10100;
- memory_.SetMemory(offset, &dyn, sizeof(dyn));
- offset += sizeof(dyn);
-
- dyn.d_tag = DT_STRSZ;
- if (test_type == SONAME_DTSIZE_SMALL) {
- dyn.d_un.d_val = 0x10;
- } else {
- dyn.d_un.d_val = 0x1000;
- }
- memory_.SetMemory(offset, &dyn, sizeof(dyn));
- offset += sizeof(dyn);
-
- if (test_type == SONAME_DTNULL_AFTER) {
- dyn.d_tag = DT_NULL;
- memory_.SetMemory(offset, &dyn, sizeof(dyn));
- offset += sizeof(dyn);
- }
-
- dyn.d_tag = DT_SONAME;
- dyn.d_un.d_val = 0x10;
- memory_.SetMemory(offset, &dyn, sizeof(dyn));
- offset += sizeof(dyn);
-
- dyn.d_tag = DT_NULL;
- memory_.SetMemory(offset, &dyn, sizeof(dyn));
-
- SetStringMemory(0x10010, "fake_soname.so");
-}
-
-template <typename ElfInterfaceType>
-void ElfInterfaceTest::Soname() {
- std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- EXPECT_EQ(0, load_bias);
-
- ASSERT_EQ("fake_soname.so", elf->GetSoname());
-}
-
-TEST_F(ElfInterfaceTest, soname_32) {
- SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>();
- Soname<ElfInterface32>();
-}
-
-TEST_F(ElfInterfaceTest, soname_64) {
- SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>();
- Soname<ElfInterface64>();
-}
-
-template <typename ElfInterfaceType>
-void ElfInterfaceTest::SonameAfterDtNull() {
- std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- EXPECT_EQ(0, load_bias);
-
- ASSERT_EQ("", elf->GetSoname());
-}
-
-TEST_F(ElfInterfaceTest, soname_after_dt_null_32) {
- SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>(SONAME_DTNULL_AFTER);
- SonameAfterDtNull<ElfInterface32>();
-}
-
-TEST_F(ElfInterfaceTest, soname_after_dt_null_64) {
- SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>(SONAME_DTNULL_AFTER);
- SonameAfterDtNull<ElfInterface64>();
-}
-
-template <typename ElfInterfaceType>
-void ElfInterfaceTest::SonameSize() {
- std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- EXPECT_EQ(0, load_bias);
-
- ASSERT_EQ("", elf->GetSoname());
-}
-
-TEST_F(ElfInterfaceTest, soname_size_32) {
- SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>(SONAME_DTSIZE_SMALL);
- SonameSize<ElfInterface32>();
-}
-
-TEST_F(ElfInterfaceTest, soname_size_64) {
- SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>(SONAME_DTSIZE_SMALL);
- SonameSize<ElfInterface64>();
-}
-
-// Verify that there is no map from STRTAB in the dynamic section to a
-// STRTAB entry in the section headers.
-template <typename ElfInterfaceType>
-void ElfInterfaceTest::SonameMissingMap() {
- std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- EXPECT_EQ(0, load_bias);
-
- ASSERT_EQ("", elf->GetSoname());
-}
-
-TEST_F(ElfInterfaceTest, soname_missing_map_32) {
- SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>(SONAME_MISSING_MAP);
- SonameMissingMap<ElfInterface32>();
-}
-
-TEST_F(ElfInterfaceTest, soname_missing_map_64) {
- SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>(SONAME_MISSING_MAP);
- SonameMissingMap<ElfInterface64>();
-}
-
-template <typename ElfType>
-void ElfInterfaceTest::InitHeadersEhFrameTest() {
- ElfType elf(&memory_);
-
- elf.FakeSetEhFrameOffset(0x10000);
- elf.FakeSetEhFrameSize(0);
- elf.FakeSetDebugFrameOffset(0);
- elf.FakeSetDebugFrameSize(0);
-
- memory_.SetMemory(0x10000,
- std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata2, DW_EH_PE_udata2});
- memory_.SetData32(0x10004, 0x500);
- memory_.SetData32(0x10008, 250);
-
- elf.InitHeaders();
-
- EXPECT_FALSE(elf.eh_frame() == nullptr);
- EXPECT_TRUE(elf.debug_frame() == nullptr);
-}
-
-TEST_F(ElfInterfaceTest, init_headers_eh_frame_32) {
- InitHeadersEhFrameTest<ElfInterface32Fake>();
-}
-
-TEST_F(ElfInterfaceTest, init_headers_eh_frame_64) {
- InitHeadersEhFrameTest<ElfInterface64Fake>();
-}
-
-template <typename ElfType>
-void ElfInterfaceTest::InitHeadersDebugFrame() {
- ElfType elf(&memory_);
-
- elf.FakeSetEhFrameOffset(0);
- elf.FakeSetEhFrameSize(0);
- elf.FakeSetDebugFrameOffset(0x5000);
- elf.FakeSetDebugFrameSize(0x200);
-
- memory_.SetData32(0x5000, 0xfc);
- memory_.SetData32(0x5004, 0xffffffff);
- memory_.SetMemory(0x5008, std::vector<uint8_t>{1, '\0', 4, 8, 2});
-
- memory_.SetData32(0x5100, 0xfc);
- memory_.SetData32(0x5104, 0);
- memory_.SetData32(0x5108, 0x1500);
- memory_.SetData32(0x510c, 0x200);
-
- elf.InitHeaders();
-
- EXPECT_TRUE(elf.eh_frame() == nullptr);
- EXPECT_FALSE(elf.debug_frame() == nullptr);
-}
-
-TEST_F(ElfInterfaceTest, init_headers_debug_frame_32) {
- InitHeadersDebugFrame<ElfInterface32Fake>();
-}
-
-TEST_F(ElfInterfaceTest, init_headers_debug_frame_64) {
- InitHeadersDebugFrame<ElfInterface64Fake>();
-}
-
-template <typename Ehdr, typename Phdr, typename ElfInterfaceType>
-void ElfInterfaceTest::InitProgramHeadersMalformed() {
- std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
-
- Ehdr ehdr = {};
- ehdr.e_phoff = 0x100;
- ehdr.e_phnum = 3;
- ehdr.e_phentsize = sizeof(Phdr);
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- EXPECT_EQ(0, load_bias);
-}
-
-TEST_F(ElfInterfaceTest, init_program_headers_malformed_32) {
- InitProgramHeadersMalformed<Elf32_Ehdr, Elf32_Phdr, ElfInterface32>();
-}
-
-TEST_F(ElfInterfaceTest, init_program_headers_malformed_64) {
- InitProgramHeadersMalformed<Elf64_Ehdr, Elf64_Phdr, ElfInterface64>();
-}
-
-template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
-void ElfInterfaceTest::InitSectionHeadersMalformed() {
- std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
-
- Ehdr ehdr = {};
- ehdr.e_shoff = 0x1000;
- ehdr.e_shnum = 10;
- ehdr.e_shentsize = sizeof(Shdr);
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- EXPECT_EQ(0, load_bias);
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_malformed_32) {
- InitSectionHeadersMalformed<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>();
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_malformed_64) {
- InitSectionHeadersMalformed<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>();
-}
-
-template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
-void ElfInterfaceTest::InitSectionHeadersMalformedSymData() {
- std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
-
- uint64_t offset = 0x1000;
-
- Ehdr ehdr = {};
- ehdr.e_shoff = offset;
- ehdr.e_shnum = 5;
- ehdr.e_shentsize = sizeof(Shdr);
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- offset += ehdr.e_shentsize;
-
- Shdr shdr = {};
- shdr.sh_type = SHT_SYMTAB;
- shdr.sh_link = 4;
- shdr.sh_addr = 0x5000;
- shdr.sh_offset = 0x5000;
- shdr.sh_entsize = 0x100;
- 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 = 10;
- shdr.sh_addr = 0x6000;
- shdr.sh_offset = 0x6000;
- shdr.sh_entsize = 0x100;
- 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 = 2;
- shdr.sh_addr = 0x6000;
- shdr.sh_offset = 0x6000;
- shdr.sh_entsize = 0x100;
- shdr.sh_size = shdr.sh_entsize * 10;
- 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));
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- EXPECT_EQ(0, load_bias);
- 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());
-
- std::string name;
- uint64_t name_offset;
- ASSERT_FALSE(elf->GetFunctionName(0x90010, &name, &name_offset));
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_malformed_symdata_32) {
- InitSectionHeadersMalformedSymData<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>();
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_malformed_symdata_64) {
- InitSectionHeadersMalformedSymData<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 = {};
- ehdr.e_shoff = offset;
- ehdr.e_shnum = 5;
- ehdr.e_shentsize = entry_size;
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- offset += ehdr.e_shentsize;
-
- Shdr 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));
-
- InitSym<Sym>(0x5000, 0x90000, 0x1000, 0x100, 0xf000, "function_one");
- InitSym<Sym>(0x6000, 0xd0000, 0x1000, 0x300, 0xf000, "function_two");
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- EXPECT_EQ(0, load_bias);
- 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_headers_32) {
- InitSectionHeaders<Elf32_Ehdr, Elf32_Shdr, Elf32_Sym, ElfInterface32>(sizeof(Elf32_Shdr));
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_64) {
- InitSectionHeaders<Elf64_Ehdr, Elf64_Shdr, Elf64_Sym, ElfInterface64>(sizeof(Elf64_Shdr));
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_non_std_entry_size_32) {
- InitSectionHeaders<Elf32_Ehdr, Elf32_Shdr, Elf32_Sym, ElfInterface32>(0x100);
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_non_std_entry_size_64) {
- 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 = {};
- ehdr.e_shoff = offset;
- ehdr.e_shnum = 7;
- ehdr.e_shentsize = sizeof(Shdr);
- ehdr.e_shstrndx = 2;
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- offset += ehdr.e_shentsize;
-
- Shdr 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;
-
- memset(&shdr, 0, sizeof(shdr));
- shdr.sh_type = SHT_PROGBITS;
- shdr.sh_link = 2;
- shdr.sh_name = 0x300;
- shdr.sh_addr = 0x7000;
- shdr.sh_offset = 0x7000;
- shdr.sh_entsize = 0x100;
- shdr.sh_size = 0x800;
- 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 = 0x400;
- shdr.sh_addr = 0xa000;
- shdr.sh_offset = 0xa000;
- shdr.sh_entsize = 0x100;
- shdr.sh_size = 0xf00;
- memory_.SetMemory(offset, &shdr, sizeof(shdr));
- offset += ehdr.e_shentsize;
-
- memset(&shdr, 0, sizeof(shdr));
- shdr.sh_type = SHT_NOTE;
- shdr.sh_name = 0x500;
- shdr.sh_addr = 0xb000;
- shdr.sh_offset = 0xb000;
- shdr.sh_size = 0xf00;
- memory_.SetMemory(offset, &shdr, sizeof(shdr));
-
- memory_.SetMemory(0xf100, ".debug_frame", sizeof(".debug_frame"));
- memory_.SetMemory(0xf200, ".gnu_debugdata", sizeof(".gnu_debugdata"));
- memory_.SetMemory(0xf300, ".eh_frame", sizeof(".eh_frame"));
- memory_.SetMemory(0xf400, ".eh_frame_hdr", sizeof(".eh_frame_hdr"));
- memory_.SetMemory(0xf500, ".note.gnu.build-id", sizeof(".note.gnu.build-id"));
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- EXPECT_EQ(0, load_bias);
- EXPECT_EQ(0x6000U, elf->debug_frame_offset());
- EXPECT_EQ(0, elf->debug_frame_section_bias());
- EXPECT_EQ(0x500U, elf->debug_frame_size());
-
- EXPECT_EQ(0x5000U, elf->gnu_debugdata_offset());
- EXPECT_EQ(0x800U, elf->gnu_debugdata_size());
-
- EXPECT_EQ(0x7000U, elf->eh_frame_offset());
- EXPECT_EQ(0, elf->eh_frame_section_bias());
- EXPECT_EQ(0x800U, elf->eh_frame_size());
-
- EXPECT_EQ(0xa000U, elf->eh_frame_hdr_offset());
- EXPECT_EQ(0, elf->eh_frame_hdr_section_bias());
- EXPECT_EQ(0xf00U, elf->eh_frame_hdr_size());
-
- EXPECT_EQ(0xb000U, elf->gnu_build_id_offset());
- EXPECT_EQ(0xf00U, elf->gnu_build_id_size());
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_offsets_32) {
- InitSectionHeadersOffsets<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>();
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_offsets_64) {
- InitSectionHeadersOffsets<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>();
-}
-
-template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
-void ElfInterfaceTest::InitSectionHeadersOffsetsEhFrameSectionBias(uint64_t addr, uint64_t offset,
- int64_t expected_bias) {
- std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
-
- uint64_t elf_offset = 0x2000;
-
- Ehdr ehdr = {};
- ehdr.e_shoff = elf_offset;
- ehdr.e_shnum = 4;
- ehdr.e_shentsize = sizeof(Shdr);
- ehdr.e_shstrndx = 2;
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- elf_offset += ehdr.e_shentsize;
-
- Shdr shdr = {};
- shdr.sh_type = SHT_PROGBITS;
- shdr.sh_link = 2;
- shdr.sh_name = 0x200;
- shdr.sh_addr = 0x8000;
- shdr.sh_offset = 0x8000;
- shdr.sh_entsize = 0x100;
- shdr.sh_size = 0x800;
- memory_.SetMemory(elf_offset, &shdr, sizeof(shdr));
- elf_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(elf_offset, &shdr, sizeof(shdr));
- elf_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 = addr;
- shdr.sh_offset = offset;
- shdr.sh_entsize = 0x100;
- shdr.sh_size = 0x500;
- memory_.SetMemory(elf_offset, &shdr, sizeof(shdr));
-
- memory_.SetMemory(0xf100, ".eh_frame", sizeof(".eh_frame"));
- memory_.SetMemory(0xf200, ".eh_frame_hdr", sizeof(".eh_frame_hdr"));
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- EXPECT_EQ(0, load_bias);
- EXPECT_EQ(offset, elf->eh_frame_offset());
- EXPECT_EQ(expected_bias, elf->eh_frame_section_bias());
- EXPECT_EQ(0x500U, elf->eh_frame_size());
-
- EXPECT_EQ(0x8000U, elf->eh_frame_hdr_offset());
- EXPECT_EQ(0, elf->eh_frame_hdr_section_bias());
- EXPECT_EQ(0x800U, elf->eh_frame_hdr_size());
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_section_bias_zero_32) {
- InitSectionHeadersOffsetsEhFrameSectionBias<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>(0x4000,
- 0x4000, 0);
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_section_bias_zero_64) {
- InitSectionHeadersOffsetsEhFrameSectionBias<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>(0x6000,
- 0x6000, 0);
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_section_bias_positive_32) {
- InitSectionHeadersOffsetsEhFrameSectionBias<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>(
- 0x5000, 0x4000, 0x1000);
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_section_bias_positive_64) {
- InitSectionHeadersOffsetsEhFrameSectionBias<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>(
- 0x6000, 0x4000, 0x2000);
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_section_bias_negative_32) {
- InitSectionHeadersOffsetsEhFrameSectionBias<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>(
- 0x3000, 0x4000, -0x1000);
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_section_bias_negative_64) {
- InitSectionHeadersOffsetsEhFrameSectionBias<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>(
- 0x6000, 0x9000, -0x3000);
-}
-
-template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
-void ElfInterfaceTest::InitSectionHeadersOffsetsEhFrameHdrSectionBias(uint64_t addr,
- uint64_t offset,
- int64_t expected_bias) {
- std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
-
- uint64_t elf_offset = 0x2000;
-
- Ehdr ehdr = {};
- ehdr.e_shoff = elf_offset;
- ehdr.e_shnum = 4;
- ehdr.e_shentsize = sizeof(Shdr);
- ehdr.e_shstrndx = 2;
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- elf_offset += ehdr.e_shentsize;
-
- Shdr shdr = {};
- shdr.sh_type = SHT_PROGBITS;
- shdr.sh_link = 2;
- shdr.sh_name = 0x200;
- shdr.sh_addr = addr;
- shdr.sh_offset = offset;
- shdr.sh_entsize = 0x100;
- shdr.sh_size = 0x800;
- memory_.SetMemory(elf_offset, &shdr, sizeof(shdr));
- elf_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(elf_offset, &shdr, sizeof(shdr));
- elf_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 = 0x5000;
- shdr.sh_offset = 0x5000;
- shdr.sh_entsize = 0x100;
- shdr.sh_size = 0x500;
- memory_.SetMemory(elf_offset, &shdr, sizeof(shdr));
-
- memory_.SetMemory(0xf100, ".eh_frame", sizeof(".eh_frame"));
- memory_.SetMemory(0xf200, ".eh_frame_hdr", sizeof(".eh_frame_hdr"));
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- EXPECT_EQ(0, load_bias);
- EXPECT_EQ(0x5000U, elf->eh_frame_offset());
- EXPECT_EQ(0, elf->eh_frame_section_bias());
- EXPECT_EQ(0x500U, elf->eh_frame_size());
- EXPECT_EQ(offset, elf->eh_frame_hdr_offset());
- EXPECT_EQ(expected_bias, elf->eh_frame_hdr_section_bias());
- EXPECT_EQ(0x800U, elf->eh_frame_hdr_size());
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_hdr_section_bias_zero_32) {
- InitSectionHeadersOffsetsEhFrameHdrSectionBias<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>(0x9000,
- 0x9000, 0);
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_hdr_section_bias_zero_64) {
- InitSectionHeadersOffsetsEhFrameHdrSectionBias<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>(0xa000,
- 0xa000, 0);
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_hdr_section_bias_positive_32) {
- InitSectionHeadersOffsetsEhFrameHdrSectionBias<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>(
- 0x9000, 0x4000, 0x5000);
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_hdr_section_bias_positive_64) {
- InitSectionHeadersOffsetsEhFrameHdrSectionBias<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>(
- 0x6000, 0x1000, 0x5000);
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_hdr_section_bias_negative_32) {
- InitSectionHeadersOffsetsEhFrameHdrSectionBias<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>(
- 0x3000, 0x5000, -0x2000);
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_hdr_section_bias_negative_64) {
- InitSectionHeadersOffsetsEhFrameHdrSectionBias<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>(
- 0x5000, 0x9000, -0x4000);
-}
-
-template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
-void ElfInterfaceTest::InitSectionHeadersOffsetsDebugFrameSectionBias(uint64_t addr,
- uint64_t offset,
- int64_t expected_bias) {
- std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
-
- uint64_t elf_offset = 0x2000;
-
- Ehdr ehdr = {};
- ehdr.e_shoff = elf_offset;
- ehdr.e_shnum = 3;
- ehdr.e_shentsize = sizeof(Shdr);
- ehdr.e_shstrndx = 2;
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- elf_offset += ehdr.e_shentsize;
-
- Shdr shdr = {};
- shdr.sh_type = SHT_PROGBITS;
- shdr.sh_link = 2;
- shdr.sh_name = 0x100;
- shdr.sh_addr = addr;
- shdr.sh_offset = offset;
- shdr.sh_entsize = 0x100;
- shdr.sh_size = 0x800;
- memory_.SetMemory(elf_offset, &shdr, sizeof(shdr));
- elf_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(elf_offset, &shdr, sizeof(shdr));
-
- memory_.SetMemory(0xf100, ".debug_frame", sizeof(".debug_frame"));
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- EXPECT_EQ(0, load_bias);
- EXPECT_EQ(offset, elf->debug_frame_offset());
- EXPECT_EQ(expected_bias, elf->debug_frame_section_bias());
- EXPECT_EQ(0x800U, elf->debug_frame_size());
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_offsets_debug_frame_section_bias_zero_32) {
- InitSectionHeadersOffsetsDebugFrameSectionBias<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>(0x5000,
- 0x5000, 0);
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_offsets_debug_frame_section_bias_zero_64) {
- InitSectionHeadersOffsetsDebugFrameSectionBias<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>(0xa000,
- 0xa000, 0);
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_offsets_debug_frame_section_bias_positive_32) {
- InitSectionHeadersOffsetsDebugFrameSectionBias<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>(
- 0x5000, 0x2000, 0x3000);
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_offsets_debug_frame_section_bias_positive_64) {
- InitSectionHeadersOffsetsDebugFrameSectionBias<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>(
- 0x7000, 0x1000, 0x6000);
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_offsets_debug_frame_section_bias_negative_32) {
- InitSectionHeadersOffsetsDebugFrameSectionBias<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>(
- 0x6000, 0x7000, -0x1000);
-}
-
-TEST_F(ElfInterfaceTest, init_section_headers_offsets_debug_frame_section_bias_negative_64) {
- InitSectionHeadersOffsetsDebugFrameSectionBias<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>(
- 0x3000, 0x5000, -0x2000);
-}
-
-template <typename Ehdr, typename Phdr, typename ElfInterfaceType>
-void ElfInterfaceTest::CheckGnuEhFrame(uint64_t addr, uint64_t offset, int64_t expected_bias) {
- std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
-
- Ehdr ehdr = {};
- ehdr.e_phoff = 0x100;
- ehdr.e_phnum = 2;
- ehdr.e_phentsize = sizeof(Phdr);
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- uint64_t phdr_offset = 0x100;
-
- Phdr phdr = {};
- phdr.p_type = PT_LOAD;
- phdr.p_memsz = 0x10000;
- phdr.p_flags = PF_R | PF_X;
- phdr.p_align = 0x1000;
- memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr));
- phdr_offset += sizeof(phdr);
-
- memset(&phdr, 0, sizeof(phdr));
- phdr.p_type = PT_GNU_EH_FRAME;
- phdr.p_vaddr = addr;
- phdr.p_offset = offset;
- memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr));
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- EXPECT_EQ(0, load_bias);
- EXPECT_EQ(expected_bias, elf->eh_frame_hdr_section_bias());
-}
-
-TEST_F(ElfInterfaceTest, eh_frame_zero_section_bias_32) {
- ElfInterfaceTest::CheckGnuEhFrame<Elf32_Ehdr, Elf32_Phdr, ElfInterface32>(0x4000, 0x4000, 0);
-}
-
-TEST_F(ElfInterfaceTest, eh_frame_zero_section_bias_64) {
- ElfInterfaceTest::CheckGnuEhFrame<Elf64_Ehdr, Elf64_Phdr, ElfInterface64>(0x4000, 0x4000, 0);
-}
-
-TEST_F(ElfInterfaceTest, eh_frame_positive_section_bias_32) {
- ElfInterfaceTest::CheckGnuEhFrame<Elf32_Ehdr, Elf32_Phdr, ElfInterface32>(0x4000, 0x1000, 0x3000);
-}
-
-TEST_F(ElfInterfaceTest, eh_frame_positive_section_bias_64) {
- ElfInterfaceTest::CheckGnuEhFrame<Elf64_Ehdr, Elf64_Phdr, ElfInterface64>(0x4000, 0x1000, 0x3000);
-}
-
-TEST_F(ElfInterfaceTest, eh_frame_negative_section_bias_32) {
- ElfInterfaceTest::CheckGnuEhFrame<Elf32_Ehdr, Elf32_Phdr, ElfInterface32>(0x4000, 0x5000,
- -0x1000);
-}
-
-TEST_F(ElfInterfaceTest, eh_frame_negative_section_bias_64) {
- ElfInterfaceTest::CheckGnuEhFrame<Elf64_Ehdr, Elf64_Phdr, ElfInterface64>(0x4000, 0x5000,
- -0x1000);
-}
-
-TEST_F(ElfInterfaceTest, is_valid_pc_from_pt_load) {
- std::unique_ptr<ElfInterface> elf(new ElfInterface32(&memory_));
-
- Elf32_Ehdr ehdr = {};
- ehdr.e_phoff = 0x100;
- ehdr.e_phnum = 1;
- ehdr.e_phentsize = sizeof(Elf32_Phdr);
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- Elf32_Phdr phdr = {};
- phdr.p_type = PT_LOAD;
- phdr.p_vaddr = 0;
- phdr.p_memsz = 0x10000;
- phdr.p_flags = PF_R | PF_X;
- phdr.p_align = 0x1000;
- memory_.SetMemory(0x100, &phdr, sizeof(phdr));
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- EXPECT_EQ(0, load_bias);
- EXPECT_TRUE(elf->IsValidPc(0));
- EXPECT_TRUE(elf->IsValidPc(0x5000));
- EXPECT_TRUE(elf->IsValidPc(0xffff));
- EXPECT_FALSE(elf->IsValidPc(0x10000));
-}
-
-TEST_F(ElfInterfaceTest, is_valid_pc_from_pt_load_non_zero_load_bias) {
- std::unique_ptr<ElfInterface> elf(new ElfInterface32(&memory_));
-
- Elf32_Ehdr ehdr = {};
- ehdr.e_phoff = 0x100;
- ehdr.e_phnum = 1;
- ehdr.e_phentsize = sizeof(Elf32_Phdr);
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- Elf32_Phdr phdr = {};
- phdr.p_type = PT_LOAD;
- phdr.p_vaddr = 0x2000;
- phdr.p_memsz = 0x10000;
- phdr.p_flags = PF_R | PF_X;
- phdr.p_align = 0x1000;
- memory_.SetMemory(0x100, &phdr, sizeof(phdr));
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- EXPECT_EQ(0x2000, load_bias);
- EXPECT_FALSE(elf->IsValidPc(0));
- EXPECT_FALSE(elf->IsValidPc(0x1000));
- EXPECT_FALSE(elf->IsValidPc(0x1fff));
- EXPECT_TRUE(elf->IsValidPc(0x2000));
- EXPECT_TRUE(elf->IsValidPc(0x5000));
- EXPECT_TRUE(elf->IsValidPc(0x11fff));
- EXPECT_FALSE(elf->IsValidPc(0x12000));
-}
-
-TEST_F(ElfInterfaceTest, is_valid_pc_from_debug_frame) {
- std::unique_ptr<ElfInterface> elf(new ElfInterface32(&memory_));
-
- uint64_t sh_offset = 0x100;
-
- Elf32_Ehdr ehdr = {};
- ehdr.e_shstrndx = 1;
- ehdr.e_shoff = sh_offset;
- ehdr.e_shentsize = sizeof(Elf32_Shdr);
- ehdr.e_shnum = 3;
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- Elf32_Shdr shdr = {};
- shdr.sh_type = SHT_NULL;
- memory_.SetMemory(sh_offset, &shdr, sizeof(shdr));
-
- sh_offset += sizeof(shdr);
- memset(&shdr, 0, sizeof(shdr));
- shdr.sh_type = SHT_STRTAB;
- shdr.sh_name = 1;
- shdr.sh_offset = 0x500;
- shdr.sh_size = 0x100;
- memory_.SetMemory(sh_offset, &shdr, sizeof(shdr));
- memory_.SetMemory(0x500, ".debug_frame");
-
- sh_offset += sizeof(shdr);
- memset(&shdr, 0, sizeof(shdr));
- shdr.sh_type = SHT_PROGBITS;
- shdr.sh_name = 0;
- shdr.sh_addr = 0x600;
- shdr.sh_offset = 0x600;
- shdr.sh_size = 0x200;
- memory_.SetMemory(sh_offset, &shdr, sizeof(shdr));
-
- // CIE 32.
- memory_.SetData32(0x600, 0xfc);
- memory_.SetData32(0x604, 0xffffffff);
- memory_.SetMemory(0x608, std::vector<uint8_t>{1, '\0', 4, 4, 1});
-
- // FDE 32.
- memory_.SetData32(0x700, 0xfc);
- memory_.SetData32(0x704, 0);
- memory_.SetData32(0x708, 0x2100);
- memory_.SetData32(0x70c, 0x200);
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- elf->InitHeaders();
- EXPECT_EQ(0, load_bias);
- EXPECT_FALSE(elf->IsValidPc(0));
- EXPECT_FALSE(elf->IsValidPc(0x20ff));
- EXPECT_TRUE(elf->IsValidPc(0x2100));
- EXPECT_TRUE(elf->IsValidPc(0x2200));
- EXPECT_TRUE(elf->IsValidPc(0x22ff));
- EXPECT_FALSE(elf->IsValidPc(0x2300));
-}
-
-TEST_F(ElfInterfaceTest, is_valid_pc_from_eh_frame) {
- std::unique_ptr<ElfInterface> elf(new ElfInterface32(&memory_));
-
- uint64_t sh_offset = 0x100;
-
- Elf32_Ehdr ehdr = {};
- ehdr.e_shstrndx = 1;
- ehdr.e_shoff = sh_offset;
- ehdr.e_shentsize = sizeof(Elf32_Shdr);
- ehdr.e_shnum = 3;
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- Elf32_Shdr shdr = {};
- shdr.sh_type = SHT_NULL;
- memory_.SetMemory(sh_offset, &shdr, sizeof(shdr));
-
- sh_offset += sizeof(shdr);
- memset(&shdr, 0, sizeof(shdr));
- shdr.sh_type = SHT_STRTAB;
- shdr.sh_name = 1;
- shdr.sh_offset = 0x500;
- shdr.sh_size = 0x100;
- memory_.SetMemory(sh_offset, &shdr, sizeof(shdr));
- memory_.SetMemory(0x500, ".eh_frame");
-
- sh_offset += sizeof(shdr);
- memset(&shdr, 0, sizeof(shdr));
- shdr.sh_type = SHT_PROGBITS;
- shdr.sh_name = 0;
- shdr.sh_addr = 0x600;
- shdr.sh_offset = 0x600;
- shdr.sh_size = 0x200;
- memory_.SetMemory(sh_offset, &shdr, sizeof(shdr));
-
- // CIE 32.
- memory_.SetData32(0x600, 0xfc);
- memory_.SetData32(0x604, 0);
- memory_.SetMemory(0x608, std::vector<uint8_t>{1, '\0', 4, 4, 1});
-
- // FDE 32.
- memory_.SetData32(0x700, 0xfc);
- memory_.SetData32(0x704, 0x104);
- memory_.SetData32(0x708, 0x20f8);
- memory_.SetData32(0x70c, 0x200);
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- elf->InitHeaders();
- EXPECT_EQ(0, load_bias);
- EXPECT_FALSE(elf->IsValidPc(0));
- EXPECT_FALSE(elf->IsValidPc(0x27ff));
- EXPECT_TRUE(elf->IsValidPc(0x2800));
- EXPECT_TRUE(elf->IsValidPc(0x2900));
- EXPECT_TRUE(elf->IsValidPc(0x29ff));
- EXPECT_FALSE(elf->IsValidPc(0x2a00));
-}
-
-template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
-void ElfInterfaceTest::BuildID() {
- std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
-
- uint64_t offset = 0x2000;
-
- Ehdr ehdr = {};
- ehdr.e_shoff = offset;
- ehdr.e_shnum = 3;
- ehdr.e_shentsize = sizeof(Shdr);
- ehdr.e_shstrndx = 2;
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- offset += ehdr.e_shentsize;
-
- char note_section[128];
- Nhdr note_header = {};
- note_header.n_namesz = 4; // "GNU"
- note_header.n_descsz = 7; // "BUILDID"
- note_header.n_type = NT_GNU_BUILD_ID;
- memcpy(¬e_section, ¬e_header, sizeof(note_header));
- size_t note_offset = sizeof(note_header);
- // The note information contains the GNU and trailing '\0'.
- memcpy(¬e_section[note_offset], "GNU", sizeof("GNU"));
- note_offset += sizeof("GNU");
- // This part of the note does not contain any trailing '\0'.
- memcpy(¬e_section[note_offset], "BUILDID", 7);
-
- Shdr shdr = {};
- shdr.sh_type = SHT_NOTE;
- shdr.sh_name = 0x500;
- shdr.sh_offset = 0xb000;
- shdr.sh_size = sizeof(note_section);
- 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));
-
- memory_.SetMemory(0xf500, ".note.gnu.build-id", sizeof(".note.gnu.build-id"));
- memory_.SetMemory(0xb000, note_section, sizeof(note_section));
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- ASSERT_EQ("BUILDID", elf->GetBuildID());
-}
-
-TEST_F(ElfInterfaceTest, build_id_32) {
- BuildID<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr, ElfInterface32>();
-}
-
-TEST_F(ElfInterfaceTest, build_id_64) {
- BuildID<Elf64_Ehdr, Elf64_Shdr, Elf64_Nhdr, ElfInterface64>();
-}
-
-template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
-void ElfInterfaceTest::BuildIDTwoNotes() {
- std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
-
- uint64_t offset = 0x2000;
-
- Ehdr ehdr = {};
- ehdr.e_shoff = offset;
- ehdr.e_shnum = 3;
- ehdr.e_shentsize = sizeof(Shdr);
- ehdr.e_shstrndx = 2;
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- offset += ehdr.e_shentsize;
-
- char note_section[128];
- Nhdr note_header = {};
- note_header.n_namesz = 8; // "WRONG" aligned to 4
- note_header.n_descsz = 7; // "BUILDID"
- note_header.n_type = NT_GNU_BUILD_ID;
- memcpy(¬e_section, ¬e_header, sizeof(note_header));
- size_t note_offset = sizeof(note_header);
- memcpy(¬e_section[note_offset], "WRONG", sizeof("WRONG"));
- note_offset += 8;
- // This part of the note does not contain any trailing '\0'.
- memcpy(¬e_section[note_offset], "BUILDID", 7);
- note_offset += 8;
-
- note_header.n_namesz = 4; // "GNU"
- note_header.n_descsz = 7; // "BUILDID"
- note_header.n_type = NT_GNU_BUILD_ID;
- memcpy(¬e_section[note_offset], ¬e_header, sizeof(note_header));
- note_offset += sizeof(note_header);
- // The note information contains the GNU and trailing '\0'.
- memcpy(¬e_section[note_offset], "GNU", sizeof("GNU"));
- note_offset += sizeof("GNU");
- // This part of the note does not contain any trailing '\0'.
- memcpy(¬e_section[note_offset], "BUILDID", 7);
-
- Shdr shdr = {};
- shdr.sh_type = SHT_NOTE;
- shdr.sh_name = 0x500;
- shdr.sh_offset = 0xb000;
- shdr.sh_size = sizeof(note_section);
- 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));
-
- memory_.SetMemory(0xf500, ".note.gnu.build-id", sizeof(".note.gnu.build-id"));
- memory_.SetMemory(0xb000, note_section, sizeof(note_section));
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- ASSERT_EQ("BUILDID", elf->GetBuildID());
-}
-
-TEST_F(ElfInterfaceTest, build_id_two_notes_32) {
- BuildIDTwoNotes<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr, ElfInterface32>();
-}
-
-TEST_F(ElfInterfaceTest, build_id_two_notes_64) {
- BuildIDTwoNotes<Elf64_Ehdr, Elf64_Shdr, Elf64_Nhdr, ElfInterface64>();
-}
-
-template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
-void ElfInterfaceTest::BuildIDSectionTooSmallForName () {
- std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
-
- uint64_t offset = 0x2000;
-
- Ehdr ehdr = {};
- ehdr.e_shoff = offset;
- ehdr.e_shnum = 3;
- ehdr.e_shentsize = sizeof(Shdr);
- ehdr.e_shstrndx = 2;
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- offset += ehdr.e_shentsize;
-
- char note_section[128];
- Nhdr note_header = {};
- note_header.n_namesz = 4; // "GNU"
- note_header.n_descsz = 7; // "BUILDID"
- note_header.n_type = NT_GNU_BUILD_ID;
- memcpy(¬e_section, ¬e_header, sizeof(note_header));
- size_t note_offset = sizeof(note_header);
- // The note information contains the GNU and trailing '\0'.
- memcpy(¬e_section[note_offset], "GNU", sizeof("GNU"));
- note_offset += sizeof("GNU");
- // This part of the note does not contain any trailing '\0'.
- memcpy(¬e_section[note_offset], "BUILDID", 7);
-
- Shdr shdr = {};
- shdr.sh_type = SHT_NOTE;
- shdr.sh_name = 0x500;
- shdr.sh_offset = 0xb000;
- shdr.sh_size = sizeof(note_header) + 1;
- 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));
-
- memory_.SetMemory(0xf500, ".note.gnu.build-id", sizeof(".note.gnu.build-id"));
- memory_.SetMemory(0xb000, note_section, sizeof(note_section));
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- ASSERT_EQ("", elf->GetBuildID());
-}
-
-TEST_F(ElfInterfaceTest, build_id_section_too_small_for_name_32) {
- BuildIDSectionTooSmallForName<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr, ElfInterface32>();
-}
-
-TEST_F(ElfInterfaceTest, build_id_section_too_small_for_name_64) {
- BuildIDSectionTooSmallForName<Elf64_Ehdr, Elf64_Shdr, Elf64_Nhdr, ElfInterface64>();
-}
-
-template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
-void ElfInterfaceTest::BuildIDSectionTooSmallForDesc () {
- std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
-
- uint64_t offset = 0x2000;
-
- Ehdr ehdr = {};
- ehdr.e_shoff = offset;
- ehdr.e_shnum = 3;
- ehdr.e_shentsize = sizeof(Shdr);
- ehdr.e_shstrndx = 2;
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- offset += ehdr.e_shentsize;
-
- char note_section[128];
- Nhdr note_header = {};
- note_header.n_namesz = 4; // "GNU"
- note_header.n_descsz = 7; // "BUILDID"
- note_header.n_type = NT_GNU_BUILD_ID;
- memcpy(¬e_section, ¬e_header, sizeof(note_header));
- size_t note_offset = sizeof(note_header);
- // The note information contains the GNU and trailing '\0'.
- memcpy(¬e_section[note_offset], "GNU", sizeof("GNU"));
- note_offset += sizeof("GNU");
- // This part of the note does not contain any trailing '\0'.
- memcpy(¬e_section[note_offset], "BUILDID", 7);
-
- Shdr shdr = {};
- shdr.sh_type = SHT_NOTE;
- shdr.sh_name = 0x500;
- shdr.sh_offset = 0xb000;
- shdr.sh_size = sizeof(note_header) + sizeof("GNU") + 1;
- 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));
-
- memory_.SetMemory(0xf500, ".note.gnu.build-id", sizeof(".note.gnu.build-id"));
- memory_.SetMemory(0xb000, note_section, sizeof(note_section));
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- ASSERT_EQ("", elf->GetBuildID());
-}
-
-TEST_F(ElfInterfaceTest, build_id_section_too_small_for_desc_32) {
- BuildIDSectionTooSmallForDesc<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr, ElfInterface32>();
-}
-
-TEST_F(ElfInterfaceTest, build_id_section_too_small_for_desc_64) {
- BuildIDSectionTooSmallForDesc<Elf64_Ehdr, Elf64_Shdr, Elf64_Nhdr, ElfInterface64>();
-}
-
-template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
-void ElfInterfaceTest::BuildIDSectionTooSmallForHeader () {
- std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
-
- uint64_t offset = 0x2000;
-
- Ehdr ehdr = {};
- ehdr.e_shoff = offset;
- ehdr.e_shnum = 3;
- ehdr.e_shentsize = sizeof(Shdr);
- ehdr.e_shstrndx = 2;
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- offset += ehdr.e_shentsize;
-
- char note_section[128];
- Nhdr note_header = {};
- note_header.n_namesz = 4; // "GNU"
- note_header.n_descsz = 7; // "BUILDID"
- note_header.n_type = NT_GNU_BUILD_ID;
- memcpy(¬e_section, ¬e_header, sizeof(note_header));
- size_t note_offset = sizeof(note_header);
- // The note information contains the GNU and trailing '\0'.
- memcpy(¬e_section[note_offset], "GNU", sizeof("GNU"));
- note_offset += sizeof("GNU");
- // This part of the note does not contain any trailing '\0'.
- memcpy(¬e_section[note_offset], "BUILDID", 7);
-
- Shdr shdr = {};
- shdr.sh_type = SHT_NOTE;
- shdr.sh_name = 0x500;
- shdr.sh_offset = 0xb000;
- shdr.sh_size = sizeof(note_header) - 1;
- 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));
-
- memory_.SetMemory(0xf500, ".note.gnu.build-id", sizeof(".note.gnu.build-id"));
- memory_.SetMemory(0xb000, note_section, sizeof(note_section));
-
- int64_t load_bias = 0;
- ASSERT_TRUE(elf->Init(&load_bias));
- ASSERT_EQ("", elf->GetBuildID());
-}
-
-TEST_F(ElfInterfaceTest, build_id_section_too_small_for_header_32) {
- BuildIDSectionTooSmallForHeader<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr, ElfInterface32>();
-}
-
-TEST_F(ElfInterfaceTest, build_id_section_too_small_for_header_64) {
- BuildIDSectionTooSmallForHeader<Elf64_Ehdr, Elf64_Shdr, Elf64_Nhdr, ElfInterface64>();
-}
-
-template <typename Ehdr, typename Phdr, typename ElfInterfaceType>
-void ElfInterfaceTest::CheckLoadBiasInFirstPhdr(int64_t load_bias) {
- Ehdr ehdr = {};
- ehdr.e_phoff = 0x100;
- ehdr.e_phnum = 2;
- ehdr.e_phentsize = sizeof(Phdr);
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- Phdr phdr = {};
- phdr.p_type = PT_LOAD;
- phdr.p_offset = 0;
- phdr.p_vaddr = load_bias;
- phdr.p_memsz = 0x10000;
- phdr.p_flags = PF_R | PF_X;
- phdr.p_align = 0x1000;
- memory_.SetMemory(0x100, &phdr, sizeof(phdr));
-
- memset(&phdr, 0, sizeof(phdr));
- phdr.p_type = PT_LOAD;
- phdr.p_offset = 0x1000;
- phdr.p_memsz = 0x2000;
- phdr.p_flags = PF_R | PF_X;
- phdr.p_align = 0x1000;
- memory_.SetMemory(0x100 + sizeof(phdr), &phdr, sizeof(phdr));
-
- int64_t static_load_bias = ElfInterface::GetLoadBias<Ehdr, Phdr>(&memory_);
- ASSERT_EQ(load_bias, static_load_bias);
-
- std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
- int64_t init_load_bias = 0;
- ASSERT_TRUE(elf->Init(&init_load_bias));
- ASSERT_EQ(init_load_bias, static_load_bias);
-}
-
-TEST_F(ElfInterfaceTest, get_load_bias_zero_32) {
- CheckLoadBiasInFirstPhdr<Elf32_Ehdr, Elf32_Phdr, ElfInterface32>(0);
-}
-
-TEST_F(ElfInterfaceTest, get_load_bias_zero_64) {
- CheckLoadBiasInFirstPhdr<Elf64_Ehdr, Elf64_Phdr, ElfInterface64>(0);
-}
-
-TEST_F(ElfInterfaceTest, get_load_bias_non_zero_32) {
- CheckLoadBiasInFirstPhdr<Elf32_Ehdr, Elf32_Phdr, ElfInterface32>(0x1000);
-}
-
-TEST_F(ElfInterfaceTest, get_load_bias_non_zero_64) {
- CheckLoadBiasInFirstPhdr<Elf64_Ehdr, Elf64_Phdr, ElfInterface64>(0x1000);
-}
-
-template <typename Ehdr, typename Phdr, typename ElfInterfaceType>
-void ElfInterfaceTest::CheckLoadBiasInFirstExecPhdr(uint64_t offset, uint64_t vaddr,
- int64_t load_bias) {
- Ehdr ehdr = {};
- ehdr.e_phoff = 0x100;
- ehdr.e_phnum = 3;
- ehdr.e_phentsize = sizeof(Phdr);
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- Phdr phdr = {};
- phdr.p_type = PT_LOAD;
- phdr.p_memsz = 0x10000;
- phdr.p_flags = PF_R;
- phdr.p_align = 0x1000;
- memory_.SetMemory(0x100, &phdr, sizeof(phdr));
-
- memset(&phdr, 0, sizeof(phdr));
- phdr.p_type = PT_LOAD;
- phdr.p_offset = offset;
- phdr.p_vaddr = vaddr;
- phdr.p_memsz = 0x2000;
- phdr.p_flags = PF_R | PF_X;
- phdr.p_align = 0x1000;
- memory_.SetMemory(0x100 + sizeof(phdr), &phdr, sizeof(phdr));
-
- // Second executable load should be ignored for load bias computation.
- memset(&phdr, 0, sizeof(phdr));
- phdr.p_type = PT_LOAD;
- phdr.p_offset = 0x1234;
- phdr.p_vaddr = 0x2000;
- phdr.p_memsz = 0x2000;
- phdr.p_flags = PF_R | PF_X;
- phdr.p_align = 0x1000;
- memory_.SetMemory(0x200 + sizeof(phdr), &phdr, sizeof(phdr));
-
- int64_t static_load_bias = ElfInterface::GetLoadBias<Ehdr, Phdr>(&memory_);
- ASSERT_EQ(load_bias, static_load_bias);
-
- std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
- int64_t init_load_bias = 0;
- ASSERT_TRUE(elf->Init(&init_load_bias));
- ASSERT_EQ(init_load_bias, static_load_bias);
-}
-
-TEST_F(ElfInterfaceTest, get_load_bias_exec_zero_32) {
- CheckLoadBiasInFirstExecPhdr<Elf32_Ehdr, Elf32_Phdr, ElfInterface32>(0x1000, 0x1000, 0);
-}
-
-TEST_F(ElfInterfaceTest, get_load_bias_exec_zero_64) {
- CheckLoadBiasInFirstExecPhdr<Elf64_Ehdr, Elf64_Phdr, ElfInterface64>(0x1000, 0x1000, 0);
-}
-
-TEST_F(ElfInterfaceTest, get_load_bias_exec_positive_32) {
- CheckLoadBiasInFirstExecPhdr<Elf32_Ehdr, Elf32_Phdr, ElfInterface32>(0x1000, 0x4000, 0x3000);
-}
-
-TEST_F(ElfInterfaceTest, get_load_bias_exec_positive_64) {
- CheckLoadBiasInFirstExecPhdr<Elf64_Ehdr, Elf64_Phdr, ElfInterface64>(0x1000, 0x4000, 0x3000);
-}
-
-TEST_F(ElfInterfaceTest, get_load_bias_exec_negative_32) {
- CheckLoadBiasInFirstExecPhdr<Elf32_Ehdr, Elf32_Phdr, ElfInterface32>(0x5000, 0x1000, -0x4000);
-}
-
-TEST_F(ElfInterfaceTest, get_load_bias_exec_negative_64) {
- CheckLoadBiasInFirstExecPhdr<Elf64_Ehdr, Elf64_Phdr, ElfInterface64>(0x5000, 0x1000, -0x4000);
-}
-
-TEST_F(ElfInterfaceTest, huge_gnu_debugdata_size) {
- ElfInterfaceFake interface(nullptr);
-
- interface.FakeSetGnuDebugdataOffset(0x1000);
- interface.FakeSetGnuDebugdataSize(0xffffffffffffffffUL);
- ASSERT_TRUE(interface.CreateGnuDebugdataMemory() == nullptr);
-
- interface.FakeSetGnuDebugdataSize(0x4000000000000UL);
- ASSERT_TRUE(interface.CreateGnuDebugdataMemory() == nullptr);
-
- // This should exceed the size_t value of the first allocation.
-#if defined(__LP64__)
- interface.FakeSetGnuDebugdataSize(0x3333333333333334ULL);
-#else
- interface.FakeSetGnuDebugdataSize(0x33333334);
-#endif
- ASSERT_TRUE(interface.CreateGnuDebugdataMemory() == nullptr);
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp
deleted file mode 100644
index d81edbf..0000000
--- a/libunwindstack/tests/ElfTest.cpp
+++ /dev/null
@@ -1,546 +0,0 @@
-/*
- * Copyright (C) 2016 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 <elf.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/RegsArm.h>
-
-#include "ElfFake.h"
-#include "ElfTestUtils.h"
-#include "LogFake.h"
-#include "MemoryFake.h"
-
-#if !defined(PT_ARM_EXIDX)
-#define PT_ARM_EXIDX 0x70000001
-#endif
-
-namespace unwindstack {
-
-class ElfTest : public ::testing::Test {
- protected:
- void SetUp() override {
- memory_ = new MemoryFake;
- }
-
- void InitElf32(uint32_t machine_type) {
- Elf32_Ehdr ehdr;
- TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, machine_type);
-
- ehdr.e_phoff = 0x100;
- ehdr.e_ehsize = sizeof(ehdr);
- ehdr.e_phentsize = sizeof(Elf32_Phdr);
- ehdr.e_phnum = 1;
- ehdr.e_shentsize = sizeof(Elf32_Shdr);
- if (machine_type == EM_ARM) {
- ehdr.e_flags = 0x5000200;
- ehdr.e_phnum = 2;
- }
- memory_->SetMemory(0, &ehdr, sizeof(ehdr));
-
- Elf32_Phdr phdr;
- memset(&phdr, 0, sizeof(phdr));
- phdr.p_type = PT_LOAD;
- phdr.p_filesz = 0x10000;
- phdr.p_memsz = 0x10000;
- phdr.p_flags = PF_R | PF_X;
- phdr.p_align = 0x1000;
- memory_->SetMemory(0x100, &phdr, sizeof(phdr));
-
- if (machine_type == EM_ARM) {
- memset(&phdr, 0, sizeof(phdr));
- phdr.p_type = PT_ARM_EXIDX;
- phdr.p_offset = 0x30000;
- phdr.p_vaddr = 0x30000;
- phdr.p_paddr = 0x30000;
- phdr.p_filesz = 16;
- phdr.p_memsz = 16;
- phdr.p_flags = PF_R;
- phdr.p_align = 0x4;
- memory_->SetMemory(0x100 + sizeof(phdr), &phdr, sizeof(phdr));
- }
- }
-
- void InitElf64(uint32_t machine_type) {
- Elf64_Ehdr ehdr;
- TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, machine_type);
-
- ehdr.e_phoff = 0x100;
- ehdr.e_flags = 0x5000200;
- ehdr.e_ehsize = sizeof(ehdr);
- ehdr.e_phentsize = sizeof(Elf64_Phdr);
- ehdr.e_phnum = 1;
- ehdr.e_shentsize = sizeof(Elf64_Shdr);
- memory_->SetMemory(0, &ehdr, sizeof(ehdr));
-
- Elf64_Phdr phdr;
- memset(&phdr, 0, sizeof(phdr));
- phdr.p_type = PT_LOAD;
- phdr.p_filesz = 0x10000;
- phdr.p_memsz = 0x10000;
- phdr.p_flags = PF_R | PF_X;
- phdr.p_align = 0x1000;
- memory_->SetMemory(0x100, &phdr, sizeof(phdr));
- }
-
- void VerifyStepIfSignalHandler(uint64_t load_bias);
-
- MemoryFake* memory_;
-};
-
-TEST_F(ElfTest, invalid_memory) {
- Elf elf(memory_);
-
- ASSERT_FALSE(elf.Init());
- ASSERT_FALSE(elf.valid());
-}
-
-TEST_F(ElfTest, elf_invalid) {
- Elf elf(memory_);
-
- InitElf32(EM_386);
-
- // Corrupt the ELF signature.
- memory_->SetData32(0, 0x7f000000);
-
- ASSERT_FALSE(elf.Init());
- ASSERT_FALSE(elf.valid());
- ASSERT_TRUE(elf.interface() == nullptr);
-
- ASSERT_EQ("", elf.GetSoname());
-
- std::string name;
- uint64_t func_offset;
- ASSERT_FALSE(elf.GetFunctionName(0, &name, &func_offset));
-
- ASSERT_FALSE(elf.StepIfSignalHandler(0, nullptr, nullptr));
- EXPECT_EQ(ERROR_INVALID_ELF, elf.GetLastErrorCode());
-
- bool finished;
- bool is_signal_frame;
- ASSERT_FALSE(elf.Step(0, nullptr, nullptr, &finished, &is_signal_frame));
- EXPECT_EQ(ERROR_INVALID_ELF, elf.GetLastErrorCode());
-}
-
-TEST_F(ElfTest, elf32_invalid_machine) {
- Elf elf(memory_);
-
- InitElf32(EM_PPC);
-
- ResetLogs();
- ASSERT_FALSE(elf.Init());
-
- ASSERT_EQ("", GetFakeLogBuf());
- ASSERT_EQ("4 unwind 32 bit elf that is neither arm nor x86 nor mips: e_machine = 20\n\n",
- GetFakeLogPrint());
-}
-
-TEST_F(ElfTest, elf64_invalid_machine) {
- Elf elf(memory_);
-
- InitElf64(EM_PPC64);
-
- ResetLogs();
- ASSERT_FALSE(elf.Init());
-
- ASSERT_EQ("", GetFakeLogBuf());
- ASSERT_EQ("4 unwind 64 bit elf that is neither aarch64 nor x86_64 nor mips64: e_machine = 21\n\n",
- GetFakeLogPrint());
-}
-
-TEST_F(ElfTest, elf_arm) {
- Elf elf(memory_);
-
- InitElf32(EM_ARM);
-
- ASSERT_TRUE(elf.Init());
- ASSERT_TRUE(elf.valid());
- ASSERT_EQ(static_cast<uint32_t>(EM_ARM), elf.machine_type());
- ASSERT_EQ(ELFCLASS32, elf.class_type());
- ASSERT_TRUE(elf.interface() != nullptr);
-}
-
-TEST_F(ElfTest, elf_mips) {
- Elf elf(memory_);
-
- InitElf32(EM_MIPS);
-
- ASSERT_TRUE(elf.Init());
- ASSERT_TRUE(elf.valid());
- ASSERT_EQ(static_cast<uint32_t>(EM_MIPS), elf.machine_type());
- ASSERT_EQ(ELFCLASS32, elf.class_type());
- ASSERT_TRUE(elf.interface() != nullptr);
-}
-
-TEST_F(ElfTest, elf_x86) {
- Elf elf(memory_);
-
- InitElf32(EM_386);
-
- ASSERT_TRUE(elf.Init());
- ASSERT_TRUE(elf.valid());
- ASSERT_EQ(static_cast<uint32_t>(EM_386), elf.machine_type());
- ASSERT_EQ(ELFCLASS32, elf.class_type());
- ASSERT_TRUE(elf.interface() != nullptr);
-}
-
-TEST_F(ElfTest, elf_arm64) {
- Elf elf(memory_);
-
- InitElf64(EM_AARCH64);
-
- ASSERT_TRUE(elf.Init());
- ASSERT_TRUE(elf.valid());
- ASSERT_EQ(static_cast<uint32_t>(EM_AARCH64), elf.machine_type());
- ASSERT_EQ(ELFCLASS64, elf.class_type());
- ASSERT_TRUE(elf.interface() != nullptr);
-}
-
-TEST_F(ElfTest, elf_x86_64) {
- Elf elf(memory_);
-
- InitElf64(EM_X86_64);
-
- ASSERT_TRUE(elf.Init());
- ASSERT_TRUE(elf.valid());
- ASSERT_EQ(static_cast<uint32_t>(EM_X86_64), elf.machine_type());
- ASSERT_EQ(ELFCLASS64, elf.class_type());
- ASSERT_TRUE(elf.interface() != nullptr);
-}
-
-TEST_F(ElfTest, elf_mips64) {
- Elf elf(memory_);
-
- InitElf64(EM_MIPS);
-
- ASSERT_TRUE(elf.Init());
- ASSERT_TRUE(elf.valid());
- ASSERT_EQ(static_cast<uint32_t>(EM_MIPS), elf.machine_type());
- ASSERT_EQ(ELFCLASS64, elf.class_type());
- ASSERT_TRUE(elf.interface() != nullptr);
-}
-
-TEST_F(ElfTest, gnu_debugdata_init32) {
- TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, true,
- [&](uint64_t offset, const void* ptr, size_t size) {
- memory_->SetMemory(offset, ptr, size);
- });
-
- Elf elf(memory_);
- ASSERT_TRUE(elf.Init());
- ASSERT_TRUE(elf.interface() != nullptr);
- ASSERT_TRUE(elf.gnu_debugdata_interface() != nullptr);
- EXPECT_EQ(0x1acU, elf.interface()->gnu_debugdata_offset());
- EXPECT_EQ(0x8cU, elf.interface()->gnu_debugdata_size());
-}
-
-TEST_F(ElfTest, gnu_debugdata_init64) {
- TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, true,
- [&](uint64_t offset, const void* ptr, size_t size) {
- memory_->SetMemory(offset, ptr, size);
- });
-
- Elf elf(memory_);
- ASSERT_TRUE(elf.Init());
- ASSERT_TRUE(elf.interface() != nullptr);
- ASSERT_TRUE(elf.gnu_debugdata_interface() != nullptr);
- EXPECT_EQ(0x200U, elf.interface()->gnu_debugdata_offset());
- EXPECT_EQ(0x90U, elf.interface()->gnu_debugdata_size());
-}
-
-TEST_F(ElfTest, rel_pc) {
- ElfFake elf(memory_);
-
- ElfInterfaceFake* interface = new ElfInterfaceFake(memory_);
- elf.FakeSetInterface(interface);
-
- elf.FakeSetValid(true);
- MapInfo map_info(nullptr, nullptr, 0x1000, 0x2000, 0, 0, "");
-
- ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, &map_info));
-
- elf.FakeSetValid(false);
- ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, &map_info));
-}
-
-void ElfTest::VerifyStepIfSignalHandler(uint64_t load_bias) {
- ElfFake elf(memory_);
-
- RegsArm regs;
- regs[13] = 0x50000;
- regs[15] = 0x8000;
-
- ElfInterfaceFake* interface = new ElfInterfaceFake(memory_);
- elf.FakeSetInterface(interface);
- elf.FakeSetLoadBias(load_bias);
-
- memory_->SetData32(0x3000, 0xdf0027ad);
- MemoryFake process_memory;
- process_memory.SetData32(0x50000, 0);
- for (size_t i = 0; i < 16; i++) {
- process_memory.SetData32(0x500a0 + i * sizeof(uint32_t), i);
- }
-
- elf.FakeSetValid(true);
- ASSERT_TRUE(elf.StepIfSignalHandler(0x3000 + load_bias, ®s, &process_memory));
- EXPECT_EQ(ERROR_NONE, elf.GetLastErrorCode());
- EXPECT_EQ(15U, regs.pc());
- EXPECT_EQ(13U, regs.sp());
-}
-
-TEST_F(ElfTest, step_in_signal_map) {
- VerifyStepIfSignalHandler(0);
-}
-
-TEST_F(ElfTest, step_in_signal_map_non_zero_load_bias) {
- VerifyStepIfSignalHandler(0x1000);
-}
-
-class ElfInterfaceMock : public ElfInterface {
- public:
- ElfInterfaceMock(Memory* memory) : ElfInterface(memory) {}
- virtual ~ElfInterfaceMock() = default;
-
- bool Init(int64_t*) override { return false; }
- void InitHeaders() override {}
- std::string GetSoname() override { return ""; }
- 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*, bool*), (override));
- MOCK_METHOD(bool, GetGlobalVariable, (const std::string&, uint64_t*), (override));
- MOCK_METHOD(bool, IsValidPc, (uint64_t), (override));
-
- void MockSetDataOffset(uint64_t offset) { data_offset_ = offset; }
- void MockSetDataVaddrStart(uint64_t vaddr) { data_vaddr_start_ = vaddr; }
- void MockSetDataVaddrEnd(uint64_t vaddr) { data_vaddr_end_ = vaddr; }
-
- void MockSetDynamicOffset(uint64_t offset) { dynamic_offset_ = offset; }
- void MockSetDynamicVaddrStart(uint64_t vaddr) { dynamic_vaddr_start_ = vaddr; }
- void MockSetDynamicVaddrEnd(uint64_t vaddr) { dynamic_vaddr_end_ = vaddr; }
-};
-
-TEST_F(ElfTest, step_in_interface) {
- ElfFake elf(memory_);
- elf.FakeSetValid(true);
-
- RegsArm regs;
-
- ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
- elf.FakeSetInterface(interface);
- MemoryFake process_memory;
-
- bool 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, &is_signal_frame));
-}
-
-TEST_F(ElfTest, get_global_invalid_elf) {
- ElfFake elf(memory_);
- elf.FakeSetValid(false);
-
- std::string global("something");
- uint64_t offset;
- ASSERT_FALSE(elf.GetGlobalVariableOffset(global, &offset));
-}
-
-TEST_F(ElfTest, get_global_valid_not_in_interface) {
- ElfFake elf(memory_);
- elf.FakeSetValid(true);
-
- ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
- elf.FakeSetInterface(interface);
-
- std::string global("something");
- EXPECT_CALL(*interface, GetGlobalVariable(global, ::testing::_))
- .WillOnce(::testing::Return(false));
-
- uint64_t offset;
- ASSERT_FALSE(elf.GetGlobalVariableOffset(global, &offset));
-}
-
-TEST_F(ElfTest, get_global_vaddr_in_no_sections) {
- ElfFake elf(memory_);
- elf.FakeSetValid(true);
-
- ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
- elf.FakeSetInterface(interface);
-
- std::string global("something");
- EXPECT_CALL(*interface, GetGlobalVariable(global, ::testing::_))
- .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x300), ::testing::Return(true)));
-
- uint64_t offset;
- ASSERT_FALSE(elf.GetGlobalVariableOffset(global, &offset));
-}
-
-TEST_F(ElfTest, get_global_vaddr_in_data_section) {
- ElfFake elf(memory_);
- elf.FakeSetValid(true);
-
- ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
- elf.FakeSetInterface(interface);
- interface->MockSetDataVaddrStart(0x500);
- interface->MockSetDataVaddrEnd(0x600);
- interface->MockSetDataOffset(0xa000);
-
- std::string global("something");
- EXPECT_CALL(*interface, GetGlobalVariable(global, ::testing::_))
- .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x580), ::testing::Return(true)));
-
- uint64_t offset;
- ASSERT_TRUE(elf.GetGlobalVariableOffset(global, &offset));
- EXPECT_EQ(0xa080U, offset);
-}
-
-TEST_F(ElfTest, get_global_vaddr_in_dynamic_section) {
- ElfFake elf(memory_);
- elf.FakeSetValid(true);
-
- ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
- elf.FakeSetInterface(interface);
- interface->MockSetDataVaddrStart(0x500);
- interface->MockSetDataVaddrEnd(0x600);
- interface->MockSetDataOffset(0xa000);
-
- interface->MockSetDynamicVaddrStart(0x800);
- interface->MockSetDynamicVaddrEnd(0x900);
- interface->MockSetDynamicOffset(0xc000);
-
- std::string global("something");
- EXPECT_CALL(*interface, GetGlobalVariable(global, ::testing::_))
- .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x880), ::testing::Return(true)));
-
- uint64_t offset;
- ASSERT_TRUE(elf.GetGlobalVariableOffset(global, &offset));
- EXPECT_EQ(0xc080U, offset);
-}
-
-TEST_F(ElfTest, get_global_vaddr_with_tagged_pointer) {
- ElfFake elf(memory_);
- elf.FakeSetValid(true);
- elf.FakeSetArch(ARCH_ARM64);
-
- ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
- elf.FakeSetInterface(interface);
- interface->MockSetDataVaddrStart(0x500);
- interface->MockSetDataVaddrEnd(0x600);
- interface->MockSetDataOffset(0xa000);
-
- std::string global("something");
- EXPECT_CALL(*interface, GetGlobalVariable(global, ::testing::_))
- .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x8800000000000580),
- ::testing::Return(true)));
-
- uint64_t offset;
- ASSERT_TRUE(elf.GetGlobalVariableOffset(global, &offset));
- EXPECT_EQ(0xa080U, offset);
-}
-
-TEST_F(ElfTest, get_global_vaddr_without_tagged_pointer) {
- ElfFake elf(memory_);
- elf.FakeSetValid(true);
- elf.FakeSetArch(ARCH_X86_64);
-
- ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
- elf.FakeSetInterface(interface);
- interface->MockSetDataVaddrStart(0x8800000000000500);
- interface->MockSetDataVaddrEnd(0x8800000000000600);
- interface->MockSetDataOffset(0x880000000000a000);
-
- std::string global("something");
- EXPECT_CALL(*interface, GetGlobalVariable(global, ::testing::_))
- .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x8800000000000580),
- ::testing::Return(true)));
-
- uint64_t offset;
- ASSERT_TRUE(elf.GetGlobalVariableOffset(global, &offset));
- EXPECT_EQ(0x880000000000a080U, offset);
-}
-
-TEST_F(ElfTest, is_valid_pc_elf_invalid) {
- ElfFake elf(memory_);
- elf.FakeSetValid(false);
-
- EXPECT_FALSE(elf.IsValidPc(0x100));
- EXPECT_FALSE(elf.IsValidPc(0x200));
-}
-
-TEST_F(ElfTest, is_valid_pc_interface) {
- ElfFake elf(memory_);
- elf.FakeSetValid(true);
-
- ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
- elf.FakeSetInterface(interface);
-
- EXPECT_CALL(*interface, IsValidPc(0x1500)).WillOnce(::testing::Return(true));
-
- EXPECT_TRUE(elf.IsValidPc(0x1500));
-}
-
-TEST_F(ElfTest, is_valid_pc_from_gnu_debugdata) {
- ElfFake elf(memory_);
- elf.FakeSetValid(true);
-
- ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
- elf.FakeSetInterface(interface);
- ElfInterfaceMock* gnu_interface = new ElfInterfaceMock(memory_);
- elf.FakeSetGnuDebugdataInterface(gnu_interface);
-
- EXPECT_CALL(*interface, IsValidPc(0x1500)).WillOnce(::testing::Return(false));
- EXPECT_CALL(*gnu_interface, IsValidPc(0x1500)).WillOnce(::testing::Return(true));
-
- EXPECT_TRUE(elf.IsValidPc(0x1500));
-}
-
-TEST_F(ElfTest, error_code_not_valid) {
- ElfFake elf(memory_);
- elf.FakeSetValid(false);
-
- ErrorData error{ERROR_MEMORY_INVALID, 0x100};
- elf.GetLastError(&error);
- EXPECT_EQ(ERROR_MEMORY_INVALID, error.code);
- EXPECT_EQ(0x100U, error.address);
-}
-
-TEST_F(ElfTest, error_code_valid) {
- ElfFake elf(memory_);
- elf.FakeSetValid(true);
- ElfInterfaceFake* interface = new ElfInterfaceFake(memory_);
- elf.FakeSetInterface(interface);
- interface->FakeSetErrorCode(ERROR_MEMORY_INVALID);
- interface->FakeSetErrorAddress(0x1000);
-
- ErrorData error{ERROR_NONE, 0};
- elf.GetLastError(&error);
- EXPECT_EQ(ERROR_MEMORY_INVALID, error.code);
- EXPECT_EQ(0x1000U, error.address);
- EXPECT_EQ(ERROR_MEMORY_INVALID, elf.GetLastErrorCode());
- EXPECT_EQ(0x1000U, elf.GetLastErrorAddress());
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/ElfTestUtils.cpp b/libunwindstack/tests/ElfTestUtils.cpp
deleted file mode 100644
index 69163ac..0000000
--- a/libunwindstack/tests/ElfTestUtils.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2016 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 <elf.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/ptrace.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <string>
-#include <vector>
-
-#include <gtest/gtest.h>
-
-#include "ElfTestUtils.h"
-
-namespace unwindstack {
-
-template <typename Ehdr>
-void TestInitEhdr(Ehdr* ehdr, uint32_t elf_class, uint32_t machine_type) {
- memset(ehdr, 0, sizeof(Ehdr));
- memcpy(&ehdr->e_ident[0], ELFMAG, SELFMAG);
- ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
- ehdr->e_ident[EI_VERSION] = EV_CURRENT;
- ehdr->e_ident[EI_OSABI] = ELFOSABI_SYSV;
- ehdr->e_ident[EI_CLASS] = elf_class;
- ehdr->e_type = ET_DYN;
- ehdr->e_machine = machine_type;
- ehdr->e_version = EV_CURRENT;
- ehdr->e_ehsize = sizeof(Ehdr);
-}
-
-std::string TestGetFileDirectory() {
- std::string exec(testing::internal::GetArgvs()[0]);
- auto const value = exec.find_last_of('/');
- if (value == std::string::npos) {
- return "tests/files/";
- }
- return exec.substr(0, value + 1) + "tests/files/";
-}
-
-template <typename Ehdr, typename Shdr>
-void TestInitGnuDebugdata(uint32_t elf_class, uint32_t machine, bool init_gnu_debugdata,
- TestCopyFuncType copy_func) {
- Ehdr ehdr;
-
- TestInitEhdr(&ehdr, elf_class, machine);
-
- uint64_t offset = sizeof(Ehdr);
- ehdr.e_shoff = offset;
- ehdr.e_shnum = 3;
- ehdr.e_shentsize = sizeof(Shdr);
- ehdr.e_shstrndx = 2;
- copy_func(0, &ehdr, sizeof(ehdr));
-
- Shdr shdr;
- memset(&shdr, 0, sizeof(shdr));
- shdr.sh_type = SHT_NULL;
- copy_func(offset, &shdr, sizeof(shdr));
- offset += ehdr.e_shentsize;
-
- // Skip this header, it will contain the gnu_debugdata information.
- uint64_t gnu_offset = offset;
- offset += ehdr.e_shentsize;
-
- uint64_t symtab_offset = sizeof(ehdr) + ehdr.e_shnum * ehdr.e_shentsize;
- memset(&shdr, 0, sizeof(shdr));
- shdr.sh_name = 1;
- shdr.sh_type = SHT_STRTAB;
- shdr.sh_offset = symtab_offset;
- shdr.sh_size = 0x100;
- copy_func(offset, &shdr, sizeof(shdr));
-
- char value = '\0';
- uint64_t symname_offset = symtab_offset;
- copy_func(symname_offset, &value, 1);
- symname_offset++;
- std::string name(".shstrtab");
- copy_func(symname_offset, name.c_str(), name.size() + 1);
- symname_offset += name.size() + 1;
- name = ".gnu_debugdata";
- copy_func(symname_offset, name.c_str(), name.size() + 1);
-
- ssize_t bytes = 0x100;
- offset = symtab_offset + 0x100;
- if (init_gnu_debugdata) {
- // Read in the compressed elf data and copy it in.
- name = TestGetFileDirectory();
- if (elf_class == ELFCLASS32) {
- name += "elf32.xz";
- } else {
- name += "elf64.xz";
- }
- int fd = TEMP_FAILURE_RETRY(open(name.c_str(), O_RDONLY));
- ASSERT_NE(-1, fd) << "Cannot open " + name;
- // Assumes the file is less than 1024 bytes.
- std::vector<uint8_t> buf(1024);
- bytes = TEMP_FAILURE_RETRY(read(fd, buf.data(), buf.size()));
- ASSERT_GT(bytes, 0);
- // Make sure the file isn't too big.
- ASSERT_NE(static_cast<size_t>(bytes), buf.size())
- << "File " + name + " is too big, increase buffer size.";
- close(fd);
- buf.resize(bytes);
- copy_func(offset, buf.data(), buf.size());
- }
-
- memset(&shdr, 0, sizeof(shdr));
- shdr.sh_type = SHT_PROGBITS;
- shdr.sh_name = symname_offset - symtab_offset;
- shdr.sh_addr = offset;
- shdr.sh_offset = offset;
- shdr.sh_size = bytes;
- copy_func(gnu_offset, &shdr, sizeof(shdr));
-}
-
-template void TestInitEhdr<Elf32_Ehdr>(Elf32_Ehdr*, uint32_t, uint32_t);
-template void TestInitEhdr<Elf64_Ehdr>(Elf64_Ehdr*, uint32_t, uint32_t);
-
-template void TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(uint32_t, uint32_t, bool,
- TestCopyFuncType);
-template void TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(uint32_t, uint32_t, bool,
- TestCopyFuncType);
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/ElfTestUtils.h b/libunwindstack/tests/ElfTestUtils.h
deleted file mode 100644
index 62cd59a..0000000
--- a/libunwindstack/tests/ElfTestUtils.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef _LIBUNWINDSTACK_TESTS_ELF_TEST_UTILS_H
-#define _LIBUNWINDSTACK_TESTS_ELF_TEST_UTILS_H
-
-#include <functional>
-#include <string>
-
-namespace unwindstack {
-
-typedef std::function<void(uint64_t, const void*, size_t)> TestCopyFuncType;
-
-template <typename Ehdr>
-void TestInitEhdr(Ehdr* ehdr, uint32_t elf_class, uint32_t machine_type);
-
-template <typename Ehdr, typename Shdr>
-void TestInitGnuDebugdata(uint32_t elf_class, uint32_t machine_type, bool init_gnu_debudata,
- TestCopyFuncType copy_func);
-
-std::string TestGetFileDirectory();
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_TESTS_ELF_TEST_UTILS_H
diff --git a/libunwindstack/tests/GenGnuDebugdata.cpp b/libunwindstack/tests/GenGnuDebugdata.cpp
deleted file mode 100644
index 2644582..0000000
--- a/libunwindstack/tests/GenGnuDebugdata.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2016 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 <elf.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <string>
-
-#if !defined(EM_AARCH64)
-#define EM_AARCH64 183
-#endif
-
-template <typename Ehdr>
-void InitEhdr(Ehdr* ehdr, uint32_t elf_class, uint32_t machine) {
- memset(ehdr, 0, sizeof(Ehdr));
- memcpy(&ehdr->e_ident[0], ELFMAG, SELFMAG);
- ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
- ehdr->e_ident[EI_VERSION] = EV_CURRENT;
- ehdr->e_ident[EI_OSABI] = ELFOSABI_SYSV;
- ehdr->e_ident[EI_CLASS] = elf_class;
- ehdr->e_type = ET_DYN;
- ehdr->e_machine = machine;
- ehdr->e_version = EV_CURRENT;
- ehdr->e_ehsize = sizeof(Ehdr);
-}
-
-template <typename Ehdr, typename Shdr>
-void GenElf(Ehdr* ehdr, int fd) {
- uint64_t offset = sizeof(Ehdr);
- ehdr->e_shoff = offset;
- ehdr->e_shnum = 3;
- ehdr->e_shentsize = sizeof(Shdr);
- ehdr->e_shstrndx = 2;
- TEMP_FAILURE_RETRY(write(fd, ehdr, sizeof(Ehdr)));
-
- Shdr shdr;
- memset(&shdr, 0, sizeof(shdr));
- shdr.sh_name = 0;
- shdr.sh_type = SHT_NULL;
- TEMP_FAILURE_RETRY(write(fd, &shdr, sizeof(Shdr)));
- offset += ehdr->e_shentsize;
-
- memset(&shdr, 0, sizeof(shdr));
- shdr.sh_type = SHT_PROGBITS;
- shdr.sh_name = 11;
- shdr.sh_addr = 0x5000;
- shdr.sh_offset = 0x5000;
- shdr.sh_entsize = 0x100;
- shdr.sh_size = 0x800;
- TEMP_FAILURE_RETRY(write(fd, &shdr, sizeof(Shdr)));
- offset += ehdr->e_shentsize;
-
- memset(&shdr, 0, sizeof(shdr));
- shdr.sh_type = SHT_STRTAB;
- shdr.sh_name = 1;
- shdr.sh_offset = 0x200;
- shdr.sh_size = 24;
- TEMP_FAILURE_RETRY(write(fd, &shdr, sizeof(Shdr)));
-
- // Write out the name entries information.
- lseek(fd, 0x200, SEEK_SET);
- std::string name;
- TEMP_FAILURE_RETRY(write(fd, name.data(), name.size() + 1));
- name = ".shstrtab";
- TEMP_FAILURE_RETRY(write(fd, name.data(), name.size() + 1));
- name = ".debug_frame";
- TEMP_FAILURE_RETRY(write(fd, name.data(), name.size() + 1));
-}
-
-int main() {
- int elf32_fd = TEMP_FAILURE_RETRY(open("elf32", O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0644));
- if (elf32_fd == -1) {
- printf("Failed to create elf32: %s\n", strerror(errno));
- return 1;
- }
-
- int elf64_fd = TEMP_FAILURE_RETRY(open("elf64", O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0644));
- if (elf64_fd == -1) {
- printf("Failed to create elf64: %s\n", strerror(errno));
- return 1;
- }
-
- Elf32_Ehdr ehdr32;
- InitEhdr<Elf32_Ehdr>(&ehdr32, ELFCLASS32, EM_ARM);
- GenElf<Elf32_Ehdr, Elf32_Shdr>(&ehdr32, elf32_fd);
- close(elf32_fd);
-
- Elf64_Ehdr ehdr64;
- InitEhdr<Elf64_Ehdr>(&ehdr64, ELFCLASS64, EM_AARCH64);
- GenElf<Elf64_Ehdr, Elf64_Shdr>(&ehdr64, elf64_fd);
- close(elf64_fd);
-}
diff --git a/libunwindstack/tests/IsolatedSettings.cpp b/libunwindstack/tests/IsolatedSettings.cpp
deleted file mode 100644
index dbd8bd6..0000000
--- a/libunwindstack/tests/IsolatedSettings.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2016 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 <stdint.h>
-#include <stdio.h>
-
-extern "C" bool GetInitialArgs(const char*** args, size_t* num_args) {
- static const char* initial_args[2] = {"--slow_threshold_ms=90000",
- "--deadline_threshold_ms=120000"};
- *args = initial_args;
- *num_args = 2;
- return true;
-}
diff --git a/libunwindstack/tests/JitDebugTest.cpp b/libunwindstack/tests/JitDebugTest.cpp
deleted file mode 100644
index 9b32a3a..0000000
--- a/libunwindstack/tests/JitDebugTest.cpp
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * Copyright (C) 2018 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 <elf.h>
-#include <string.h>
-
-#include <memory>
-#include <vector>
-
-#include <gtest/gtest.h>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/JitDebug.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
-
-#include "ElfFake.h"
-#include "MemoryFake.h"
-
-namespace unwindstack {
-
-class JitDebugTest : public ::testing::Test {
- protected:
- void CreateFakeElf(MapInfo* map_info, uint64_t global_offset, uint64_t data_offset,
- uint64_t data_vaddr, uint64_t data_size) {
- MemoryFake* memory = new MemoryFake;
- ElfFake* elf = new ElfFake(memory);
- elf->FakeSetValid(true);
- ElfInterfaceFake* interface = new ElfInterfaceFake(memory);
- elf->FakeSetInterface(interface);
- interface->FakeSetGlobalVariable("__jit_debug_descriptor", global_offset);
- interface->FakeSetDataOffset(data_offset);
- interface->FakeSetDataVaddrStart(data_vaddr);
- interface->FakeSetDataVaddrEnd(data_vaddr + data_size);
- map_info->elf.reset(elf);
- }
-
- void Init(ArchEnum arch) {
- jit_debug_.reset(new JitDebug(process_memory_));
- jit_debug_->SetArch(arch);
-
- maps_.reset(
- new BufferMaps("1000-4000 ---s 00000000 00:00 0 /fake/elf1\n"
- "4000-6000 r--s 00000000 00:00 0 /fake/elf1\n"
- "6000-8000 -wxs 00002000 00:00 0 /fake/elf1\n"
- "a000-c000 --xp 00000000 00:00 0 /fake/elf2\n"
- "c000-f000 rw-p 00002000 00:00 0 /fake/elf2\n"
- "f000-11000 r--p 00000000 00:00 0 /fake/elf3\n"
- "11000-12000 rw-p 00002000 00:00 0 /fake/elf3\n"
- "12000-14000 r--p 00000000 00:00 0 /fake/elf4\n"
- "100000-110000 rw-p 00ee000 00:00 0 /fake/elf4\n"
- "200000-210000 rw-p 01ee000 00:00 0 /fake/elf4\n"));
- ASSERT_TRUE(maps_->Parse());
-
- MapInfo* map_info = maps_->Get(3);
- ASSERT_TRUE(map_info != nullptr);
- CreateFakeElf(map_info, 0x2800, 0x2000, 0x2000, 0x3000);
-
- map_info = maps_->Get(5);
- ASSERT_TRUE(map_info != nullptr);
- CreateFakeElf(map_info, 0x2800, 0x2000, 0x2000, 0x3000);
-
- map_info = maps_->Get(7);
- ASSERT_TRUE(map_info != nullptr);
- CreateFakeElf(map_info, 0xee800, 0xee000, 0xee000, 0x10000);
- }
-
- void SetUp() override {
- memory_ = new MemoryFake;
- process_memory_.reset(memory_);
-
- Init(ARCH_ARM);
- }
-
- template <typename EhdrType, typename ShdrType>
- void CreateElf(uint64_t offset, uint8_t class_type, uint8_t machine_type, uint32_t pc,
- uint32_t size) {
- EhdrType ehdr;
- memset(&ehdr, 0, sizeof(ehdr));
- uint64_t sh_offset = sizeof(ehdr);
- memcpy(ehdr.e_ident, ELFMAG, SELFMAG);
- ehdr.e_ident[EI_CLASS] = class_type;
- ehdr.e_machine = machine_type;
- ehdr.e_shstrndx = 1;
- ehdr.e_shoff = sh_offset;
- ehdr.e_shentsize = sizeof(ShdrType);
- ehdr.e_shnum = 3;
- memory_->SetMemory(offset, &ehdr, sizeof(ehdr));
-
- ShdrType shdr;
- memset(&shdr, 0, sizeof(shdr));
- shdr.sh_type = SHT_NULL;
- memory_->SetMemory(offset + sh_offset, &shdr, sizeof(shdr));
-
- sh_offset += sizeof(shdr);
- memset(&shdr, 0, sizeof(shdr));
- shdr.sh_type = SHT_STRTAB;
- shdr.sh_name = 1;
- shdr.sh_offset = 0x500;
- shdr.sh_size = 0x100;
- memory_->SetMemory(offset + sh_offset, &shdr, sizeof(shdr));
- memory_->SetMemory(offset + 0x500, ".debug_frame");
-
- sh_offset += sizeof(shdr);
- memset(&shdr, 0, sizeof(shdr));
- shdr.sh_type = SHT_PROGBITS;
- shdr.sh_name = 0;
- shdr.sh_addr = 0x600;
- shdr.sh_offset = 0x600;
- shdr.sh_size = 0x200;
- memory_->SetMemory(offset + sh_offset, &shdr, sizeof(shdr));
-
- // Now add a single cie/fde.
- uint64_t dwarf_offset = offset + 0x600;
- if (class_type == ELFCLASS32) {
- // CIE 32 information.
- memory_->SetData32(dwarf_offset, 0xfc);
- memory_->SetData32(dwarf_offset + 0x4, 0xffffffff);
- memory_->SetData8(dwarf_offset + 0x8, 1);
- memory_->SetData8(dwarf_offset + 0x9, '\0');
- memory_->SetData8(dwarf_offset + 0xa, 0x4);
- memory_->SetData8(dwarf_offset + 0xb, 0x4);
- memory_->SetData8(dwarf_offset + 0xc, 0x1);
-
- // FDE 32 information.
- memory_->SetData32(dwarf_offset + 0x100, 0xfc);
- memory_->SetData32(dwarf_offset + 0x104, 0);
- memory_->SetData32(dwarf_offset + 0x108, pc);
- memory_->SetData32(dwarf_offset + 0x10c, size);
- } else {
- // CIE 64 information.
- memory_->SetData32(dwarf_offset, 0xffffffff);
- memory_->SetData64(dwarf_offset + 4, 0xf4);
- memory_->SetData64(dwarf_offset + 0xc, 0xffffffffffffffffULL);
- memory_->SetData8(dwarf_offset + 0x14, 1);
- memory_->SetData8(dwarf_offset + 0x15, '\0');
- memory_->SetData8(dwarf_offset + 0x16, 0x4);
- memory_->SetData8(dwarf_offset + 0x17, 0x4);
- memory_->SetData8(dwarf_offset + 0x18, 0x1);
-
- // FDE 64 information.
- memory_->SetData32(dwarf_offset + 0x100, 0xffffffff);
- memory_->SetData64(dwarf_offset + 0x104, 0xf4);
- memory_->SetData64(dwarf_offset + 0x10c, 0);
- memory_->SetData64(dwarf_offset + 0x114, pc);
- memory_->SetData64(dwarf_offset + 0x11c, size);
- }
- }
-
- void WriteDescriptor32(uint64_t addr, uint32_t entry);
- void WriteDescriptor64(uint64_t addr, uint64_t entry);
- void WriteEntry32Pack(uint64_t addr, uint32_t prev, uint32_t next, uint32_t elf_addr,
- uint64_t elf_size);
- void WriteEntry32Pad(uint64_t addr, uint32_t prev, uint32_t next, uint32_t elf_addr,
- uint64_t elf_size);
- void WriteEntry64(uint64_t addr, uint64_t prev, uint64_t next, uint64_t elf_addr,
- uint64_t elf_size);
-
- std::shared_ptr<Memory> process_memory_;
- MemoryFake* memory_;
- std::unique_ptr<JitDebug> jit_debug_;
- std::unique_ptr<BufferMaps> maps_;
-};
-
-void JitDebugTest::WriteDescriptor32(uint64_t addr, uint32_t entry) {
- // Format of the 32 bit JITDescriptor structure:
- // uint32_t version
- memory_->SetData32(addr, 1);
- // uint32_t action_flag
- memory_->SetData32(addr + 4, 0);
- // uint32_t relevant_entry
- memory_->SetData32(addr + 8, 0);
- // uint32_t first_entry
- memory_->SetData32(addr + 12, entry);
-}
-
-void JitDebugTest::WriteDescriptor64(uint64_t addr, uint64_t entry) {
- // Format of the 64 bit JITDescriptor structure:
- // uint32_t version
- memory_->SetData32(addr, 1);
- // uint32_t action_flag
- memory_->SetData32(addr + 4, 0);
- // uint64_t relevant_entry
- memory_->SetData64(addr + 8, 0);
- // uint64_t first_entry
- memory_->SetData64(addr + 16, entry);
-}
-
-void JitDebugTest::WriteEntry32Pack(uint64_t addr, uint32_t prev, uint32_t next, uint32_t elf_addr,
- uint64_t elf_size) {
- // Format of the 32 bit JITCodeEntry structure:
- // uint32_t next
- memory_->SetData32(addr, next);
- // uint32_t prev
- memory_->SetData32(addr + 4, prev);
- // uint32_t symfile_addr
- memory_->SetData32(addr + 8, elf_addr);
- // uint64_t symfile_size
- memory_->SetData64(addr + 12, elf_size);
-}
-
-void JitDebugTest::WriteEntry32Pad(uint64_t addr, uint32_t prev, uint32_t next, uint32_t elf_addr,
- uint64_t elf_size) {
- // Format of the 32 bit JITCodeEntry structure:
- // uint32_t next
- memory_->SetData32(addr, next);
- // uint32_t prev
- memory_->SetData32(addr + 4, prev);
- // uint32_t symfile_addr
- memory_->SetData32(addr + 8, elf_addr);
- // uint32_t pad
- memory_->SetData32(addr + 12, 0);
- // uint64_t symfile_size
- memory_->SetData64(addr + 16, elf_size);
-}
-
-void JitDebugTest::WriteEntry64(uint64_t addr, uint64_t prev, uint64_t next, uint64_t elf_addr,
- uint64_t elf_size) {
- // Format of the 64 bit JITCodeEntry structure:
- // uint64_t next
- memory_->SetData64(addr, next);
- // uint64_t prev
- memory_->SetData64(addr + 8, prev);
- // uint64_t symfile_addr
- memory_->SetData64(addr + 16, elf_addr);
- // uint64_t symfile_size
- memory_->SetData64(addr + 24, elf_size);
-}
-
-TEST_F(JitDebugTest, get_elf_invalid) {
- Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
- ASSERT_TRUE(elf == nullptr);
-}
-
-TEST_F(JitDebugTest, get_elf_no_global_variable) {
- maps_.reset(new BufferMaps(""));
- Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
- ASSERT_TRUE(elf == nullptr);
-}
-
-TEST_F(JitDebugTest, get_elf_no_valid_descriptor_in_memory) {
- CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
-
- Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
- ASSERT_TRUE(elf == nullptr);
-}
-
-TEST_F(JitDebugTest, get_elf_no_valid_code_entry) {
- CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
-
- WriteDescriptor32(0x11800, 0x200000);
-
- Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
- ASSERT_TRUE(elf == nullptr);
-}
-
-TEST_F(JitDebugTest, get_elf_invalid_descriptor_first_entry) {
- CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
-
- WriteDescriptor32(0x11800, 0);
-
- Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
- ASSERT_TRUE(elf == nullptr);
-}
-
-TEST_F(JitDebugTest, get_elf_invalid_descriptor_version) {
- CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
-
- WriteDescriptor32(0x11800, 0x20000);
- // Set the version to an invalid value.
- memory_->SetData32(0x11800, 2);
-
- Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
- ASSERT_TRUE(elf == nullptr);
-}
-
-TEST_F(JitDebugTest, get_elf_32) {
- CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
-
- WriteDescriptor32(0x11800, 0x200000);
- WriteEntry32Pad(0x200000, 0, 0, 0x4000, 0x1000);
-
- Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
- ASSERT_TRUE(elf != nullptr);
-
- // Clear the memory and verify all of the data is cached.
- memory_->Clear();
- Elf* elf2 = jit_debug_->GetElf(maps_.get(), 0x1500);
- ASSERT_TRUE(elf2 != nullptr);
- EXPECT_EQ(elf, elf2);
-}
-
-TEST_F(JitDebugTest, get_multiple_jit_debug_descriptors_valid) {
- CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
- CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x5000, ELFCLASS32, EM_ARM, 0x2000, 0x300);
-
- WriteDescriptor32(0x11800, 0x200000);
- WriteEntry32Pad(0x200000, 0, 0, 0x4000, 0x1000);
- WriteDescriptor32(0x100800, 0x201000);
- WriteEntry32Pad(0x201000, 0, 0, 0x5000, 0x1000);
-
- ASSERT_TRUE(jit_debug_->GetElf(maps_.get(), 0x1500) != nullptr);
- ASSERT_TRUE(jit_debug_->GetElf(maps_.get(), 0x2000) == nullptr);
-
- // Now clear the descriptor entry for the first one.
- WriteDescriptor32(0x11800, 0);
- jit_debug_.reset(new JitDebug(process_memory_));
- jit_debug_->SetArch(ARCH_ARM);
-
- ASSERT_TRUE(jit_debug_->GetElf(maps_.get(), 0x1500) == nullptr);
- ASSERT_TRUE(jit_debug_->GetElf(maps_.get(), 0x2000) != nullptr);
-}
-
-TEST_F(JitDebugTest, get_elf_x86) {
- Init(ARCH_X86);
-
- CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
-
- WriteDescriptor32(0x11800, 0x200000);
- WriteEntry32Pack(0x200000, 0, 0, 0x4000, 0x1000);
-
- jit_debug_->SetArch(ARCH_X86);
- Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
- ASSERT_TRUE(elf != nullptr);
-
- // Clear the memory and verify all of the data is cached.
- memory_->Clear();
- Elf* elf2 = jit_debug_->GetElf(maps_.get(), 0x1500);
- ASSERT_TRUE(elf2 != nullptr);
- EXPECT_EQ(elf, elf2);
-}
-
-TEST_F(JitDebugTest, get_elf_64) {
- Init(ARCH_ARM64);
-
- CreateElf<Elf64_Ehdr, Elf64_Shdr>(0x4000, ELFCLASS64, EM_AARCH64, 0x1500, 0x200);
-
- WriteDescriptor64(0x11800, 0x200000);
- WriteEntry64(0x200000, 0, 0, 0x4000, 0x1000);
-
- Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
- ASSERT_TRUE(elf != nullptr);
-
- // Clear the memory and verify all of the data is cached.
- memory_->Clear();
- Elf* elf2 = jit_debug_->GetElf(maps_.get(), 0x1500);
- ASSERT_TRUE(elf2 != nullptr);
- EXPECT_EQ(elf, elf2);
-}
-
-TEST_F(JitDebugTest, get_elf_multiple_entries) {
- CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
- CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x5000, ELFCLASS32, EM_ARM, 0x2300, 0x400);
-
- WriteDescriptor32(0x11800, 0x200000);
- WriteEntry32Pad(0x200000, 0, 0x200100, 0x4000, 0x1000);
- WriteEntry32Pad(0x200100, 0x200100, 0, 0x5000, 0x1000);
-
- Elf* elf_2 = jit_debug_->GetElf(maps_.get(), 0x2400);
- ASSERT_TRUE(elf_2 != nullptr);
-
- Elf* elf_1 = jit_debug_->GetElf(maps_.get(), 0x1600);
- ASSERT_TRUE(elf_1 != nullptr);
-
- // Clear the memory and verify all of the data is cached.
- memory_->Clear();
- EXPECT_EQ(elf_1, jit_debug_->GetElf(maps_.get(), 0x1500));
- EXPECT_EQ(elf_1, jit_debug_->GetElf(maps_.get(), 0x16ff));
- EXPECT_EQ(elf_2, jit_debug_->GetElf(maps_.get(), 0x2300));
- EXPECT_EQ(elf_2, jit_debug_->GetElf(maps_.get(), 0x26ff));
- EXPECT_EQ(nullptr, jit_debug_->GetElf(maps_.get(), 0x1700));
- EXPECT_EQ(nullptr, jit_debug_->GetElf(maps_.get(), 0x2700));
-}
-
-TEST_F(JitDebugTest, get_elf_search_libs) {
- CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
-
- WriteDescriptor32(0x11800, 0x200000);
- WriteEntry32Pad(0x200000, 0, 0, 0x4000, 0x1000);
-
- // Only search a given named list of libs.
- std::vector<std::string> libs{"libart.so"};
- jit_debug_.reset(new JitDebug(process_memory_, libs));
- jit_debug_->SetArch(ARCH_ARM);
- EXPECT_TRUE(jit_debug_->GetElf(maps_.get(), 0x1500) == nullptr);
-
- // Change the name of the map that includes the value and verify this works.
- MapInfo* map_info = maps_->Get(5);
- map_info->name = "/system/lib/libart.so";
- map_info = maps_->Get(6);
- map_info->name = "/system/lib/libart.so";
- jit_debug_.reset(new JitDebug(process_memory_, libs));
- // Make sure that clearing our copy of the libs doesn't affect the
- // JitDebug object.
- libs.clear();
- jit_debug_->SetArch(ARCH_ARM);
- EXPECT_TRUE(jit_debug_->GetElf(maps_.get(), 0x1500) != nullptr);
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/LocalUnwinderTest.cpp b/libunwindstack/tests/LocalUnwinderTest.cpp
deleted file mode 100644
index 9936f7a..0000000
--- a/libunwindstack/tests/LocalUnwinderTest.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright (C) 2018 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 <dlfcn.h>
-#include <inttypes.h>
-#include <signal.h>
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <gtest/gtest.h>
-
-#include <android-base/stringprintf.h>
-
-#include <unwindstack/LocalUnwinder.h>
-
-namespace unwindstack {
-
-static std::vector<LocalFrameData>* g_frame_info;
-static LocalUnwinder* g_unwinder;
-
-extern "C" void SignalLocalInnerFunction() {
- g_unwinder->Unwind(g_frame_info, 256);
-}
-
-extern "C" void SignalLocalMiddleFunction() {
- SignalLocalInnerFunction();
-}
-
-extern "C" void SignalLocalOuterFunction() {
- SignalLocalMiddleFunction();
-}
-
-static void SignalLocalCallerHandler(int, siginfo_t*, void*) {
- SignalLocalOuterFunction();
-}
-
-static std::string ErrorMsg(const std::vector<const char*>& function_names,
- const std::vector<LocalFrameData>& frame_info) {
- std::string unwind;
- size_t i = 0;
- for (const auto& frame : frame_info) {
- unwind += android::base::StringPrintf("#%02zu pc 0x%" PRIx64 " rel_pc 0x%" PRIx64, i++,
- frame.pc, frame.rel_pc);
- if (frame.map_info != nullptr) {
- if (!frame.map_info->name.empty()) {
- unwind += " " + frame.map_info->name;
- } else {
- unwind += android::base::StringPrintf(" 0x%" PRIx64 "-0x%" PRIx64, frame.map_info->start,
- frame.map_info->end);
- }
- if (frame.map_info->offset != 0) {
- unwind += android::base::StringPrintf(" offset 0x%" PRIx64, frame.map_info->offset);
- }
- }
- if (!frame.function_name.empty()) {
- unwind += " " + frame.function_name;
- if (frame.function_offset != 0) {
- unwind += android::base::StringPrintf("+%" PRId64, frame.function_offset);
- }
- }
- unwind += '\n';
- }
-
- return std::string(
- "Unwind completed without finding all frames\n"
- " Looking for function: ") +
- function_names.front() + "\n" + "Unwind data:\n" + unwind;
-}
-
-// This test assumes that this code is compiled with optimizations turned
-// off. If this doesn't happen, then all of the calls will be optimized
-// away.
-extern "C" void LocalInnerFunction(LocalUnwinder* unwinder, bool unwind_through_signal) {
- std::vector<LocalFrameData> frame_info;
- g_frame_info = &frame_info;
- g_unwinder = unwinder;
- std::vector<const char*> expected_function_names;
-
- if (unwind_through_signal) {
- struct sigaction act, oldact;
- memset(&act, 0, sizeof(act));
- act.sa_sigaction = SignalLocalCallerHandler;
- act.sa_flags = SA_RESTART | SA_ONSTACK;
- ASSERT_EQ(0, sigaction(SIGUSR1, &act, &oldact));
-
- raise(SIGUSR1);
-
- ASSERT_EQ(0, sigaction(SIGUSR1, &oldact, nullptr));
-
- expected_function_names = {"LocalOuterFunction", "LocalMiddleFunction",
- "LocalInnerFunction", "SignalLocalOuterFunction",
- "SignalLocalMiddleFunction", "SignalLocalInnerFunction"};
- } else {
- ASSERT_TRUE(unwinder->Unwind(&frame_info, 256));
-
- expected_function_names = {"LocalOuterFunction", "LocalMiddleFunction", "LocalInnerFunction"};
- }
-
- for (auto& frame : frame_info) {
- if (frame.function_name == expected_function_names.back()) {
- expected_function_names.pop_back();
- if (expected_function_names.empty()) {
- break;
- }
- }
- }
-
- ASSERT_TRUE(expected_function_names.empty()) << ErrorMsg(expected_function_names, frame_info);
-}
-
-extern "C" void LocalMiddleFunction(LocalUnwinder* unwinder, bool unwind_through_signal) {
- LocalInnerFunction(unwinder, unwind_through_signal);
-}
-
-extern "C" void LocalOuterFunction(LocalUnwinder* unwinder, bool unwind_through_signal) {
- LocalMiddleFunction(unwinder, unwind_through_signal);
-}
-
-class LocalUnwinderTest : public ::testing::Test {
- protected:
- void SetUp() override {
- unwinder_.reset(new LocalUnwinder);
- ASSERT_TRUE(unwinder_->Init());
- }
-
- std::unique_ptr<LocalUnwinder> unwinder_;
-};
-
-TEST_F(LocalUnwinderTest, local) {
- LocalOuterFunction(unwinder_.get(), false);
-}
-
-TEST_F(LocalUnwinderTest, local_signal) {
- LocalOuterFunction(unwinder_.get(), true);
-}
-
-TEST_F(LocalUnwinderTest, local_multiple) {
- ASSERT_NO_FATAL_FAILURE(LocalOuterFunction(unwinder_.get(), false));
-
- ASSERT_NO_FATAL_FAILURE(LocalOuterFunction(unwinder_.get(), true));
-
- ASSERT_NO_FATAL_FAILURE(LocalOuterFunction(unwinder_.get(), false));
-
- ASSERT_NO_FATAL_FAILURE(LocalOuterFunction(unwinder_.get(), true));
-}
-
-// This test verifies that doing an unwind before and after a dlopen
-// works. It's verifying that the maps read during the first unwind
-// do not cause a problem when doing the unwind using the code in
-// the dlopen'd code.
-TEST_F(LocalUnwinderTest, unwind_after_dlopen) {
- // Prime the maps data.
- ASSERT_NO_FATAL_FAILURE(LocalOuterFunction(unwinder_.get(), false));
-
- std::string testlib(testing::internal::GetArgvs()[0]);
- auto const value = testlib.find_last_of('/');
- if (value != std::string::npos) {
- testlib = testlib.substr(0, value + 1);
- } else {
- testlib = "";
- }
- testlib += "libunwindstack_local.so";
-
- void* handle = dlopen(testlib.c_str(), RTLD_NOW);
- ASSERT_TRUE(handle != nullptr);
-
- void (*unwind_function)(void*, void*) =
- reinterpret_cast<void (*)(void*, void*)>(dlsym(handle, "TestlibLevel1"));
- ASSERT_TRUE(unwind_function != nullptr);
-
- std::vector<LocalFrameData> frame_info;
- unwind_function(unwinder_.get(), &frame_info);
-
- ASSERT_EQ(0, dlclose(handle));
-
- std::vector<const char*> expected_function_names{"TestlibLevel1", "TestlibLevel2",
- "TestlibLevel3", "TestlibLevel4"};
-
- for (auto& frame : frame_info) {
- if (frame.function_name == expected_function_names.back()) {
- expected_function_names.pop_back();
- if (expected_function_names.empty()) {
- break;
- }
- }
- }
-
- ASSERT_TRUE(expected_function_names.empty()) << ErrorMsg(expected_function_names, frame_info);
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/LocalUpdatableMapsTest.cpp b/libunwindstack/tests/LocalUpdatableMapsTest.cpp
deleted file mode 100644
index 99afb0b..0000000
--- a/libunwindstack/tests/LocalUpdatableMapsTest.cpp
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * Copyright (C) 2019 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 <stdint.h>
-#include <sys/mman.h>
-
-#include <string>
-#include <vector>
-
-#include <gtest/gtest.h>
-
-#include <android-base/file.h>
-#include <unwindstack/Maps.h>
-
-namespace unwindstack {
-
-class TestUpdatableMaps : public LocalUpdatableMaps {
- public:
- TestUpdatableMaps() : LocalUpdatableMaps() {}
- virtual ~TestUpdatableMaps() = default;
-
- const std::string GetMapsFile() const override { return maps_file_; }
-
- void TestSetMapsFile(const std::string& maps_file) { maps_file_ = maps_file; }
-
- const std::vector<std::unique_ptr<MapInfo>>& TestGetSavedMaps() { return saved_maps_; }
-
- private:
- std::string maps_file_;
-};
-
-class LocalUpdatableMapsTest : public ::testing::Test {
- protected:
- static const std::string GetDefaultMapString() {
- return "3000-4000 r-xp 00000 00:00 0\n8000-9000 r-xp 00000 00:00 0\n";
- }
-
- void SetUp() override {
- TemporaryFile tf;
- ASSERT_TRUE(android::base::WriteStringToFile(GetDefaultMapString(), tf.path));
-
- maps_.TestSetMapsFile(tf.path);
- ASSERT_TRUE(maps_.Parse());
- ASSERT_EQ(2U, maps_.Total());
-
- MapInfo* map_info = maps_.Get(0);
- ASSERT_TRUE(map_info != nullptr);
- EXPECT_EQ(0x3000U, map_info->start);
- EXPECT_EQ(0x4000U, map_info->end);
- EXPECT_EQ(0U, map_info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
- EXPECT_TRUE(map_info->name.empty());
-
- map_info = maps_.Get(1);
- ASSERT_TRUE(map_info != nullptr);
- EXPECT_EQ(0x8000U, map_info->start);
- EXPECT_EQ(0x9000U, map_info->end);
- EXPECT_EQ(0U, map_info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
- EXPECT_TRUE(map_info->name.empty());
- }
-
- TestUpdatableMaps maps_;
-};
-
-TEST_F(LocalUpdatableMapsTest, same_map) {
- TemporaryFile tf;
- ASSERT_TRUE(android::base::WriteStringToFile(GetDefaultMapString(), tf.path));
-
- maps_.TestSetMapsFile(tf.path);
- ASSERT_TRUE(maps_.Reparse());
- ASSERT_EQ(2U, maps_.Total());
- EXPECT_EQ(0U, maps_.TestGetSavedMaps().size());
-
- MapInfo* map_info = maps_.Get(0);
- ASSERT_TRUE(map_info != nullptr);
- EXPECT_EQ(0x3000U, map_info->start);
- EXPECT_EQ(0x4000U, map_info->end);
- EXPECT_EQ(0U, map_info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
- EXPECT_TRUE(map_info->name.empty());
-
- map_info = maps_.Get(1);
- ASSERT_TRUE(map_info != nullptr);
- EXPECT_EQ(0x8000U, map_info->start);
- EXPECT_EQ(0x9000U, map_info->end);
- EXPECT_EQ(0U, map_info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
- EXPECT_TRUE(map_info->name.empty());
-}
-
-TEST_F(LocalUpdatableMapsTest, same_map_new_perms) {
- TemporaryFile tf;
- ASSERT_TRUE(
- android::base::WriteStringToFile("3000-4000 rwxp 00000 00:00 0\n"
- "8000-9000 r-xp 00000 00:00 0\n",
- tf.path));
-
- maps_.TestSetMapsFile(tf.path);
- ASSERT_TRUE(maps_.Reparse());
- ASSERT_EQ(2U, maps_.Total());
-
- MapInfo* map_info = maps_.Get(0);
- ASSERT_TRUE(map_info != nullptr);
- EXPECT_EQ(0x3000U, map_info->start);
- EXPECT_EQ(0x4000U, map_info->end);
- EXPECT_EQ(0U, map_info->offset);
- EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, map_info->flags);
- EXPECT_TRUE(map_info->name.empty());
-
- map_info = maps_.Get(1);
- ASSERT_TRUE(map_info != nullptr);
- EXPECT_EQ(0x8000U, map_info->start);
- EXPECT_EQ(0x9000U, map_info->end);
- EXPECT_EQ(0U, map_info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
- EXPECT_TRUE(map_info->name.empty());
-
- auto& saved_maps = maps_.TestGetSavedMaps();
- ASSERT_EQ(1U, saved_maps.size());
- map_info = saved_maps[0].get();
- ASSERT_TRUE(map_info != nullptr);
- EXPECT_EQ(0x3000U, map_info->start);
- EXPECT_EQ(0x4000U, map_info->end);
- EXPECT_EQ(0U, map_info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
- EXPECT_TRUE(map_info->name.empty());
-}
-
-TEST_F(LocalUpdatableMapsTest, same_map_new_name) {
- TemporaryFile tf;
- ASSERT_TRUE(
- android::base::WriteStringToFile("3000-4000 r-xp 00000 00:00 0 /fake/lib.so\n"
- "8000-9000 r-xp 00000 00:00 0\n",
- tf.path));
-
- maps_.TestSetMapsFile(tf.path);
- ASSERT_TRUE(maps_.Reparse());
- ASSERT_EQ(2U, maps_.Total());
-
- MapInfo* map_info = maps_.Get(0);
- ASSERT_TRUE(map_info != nullptr);
- EXPECT_EQ(0x3000U, map_info->start);
- EXPECT_EQ(0x4000U, map_info->end);
- EXPECT_EQ(0U, map_info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
- EXPECT_EQ("/fake/lib.so", map_info->name);
-
- map_info = maps_.Get(1);
- ASSERT_TRUE(map_info != nullptr);
- EXPECT_EQ(0x8000U, map_info->start);
- EXPECT_EQ(0x9000U, map_info->end);
- EXPECT_EQ(0U, map_info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
- EXPECT_TRUE(map_info->name.empty());
-
- auto& saved_maps = maps_.TestGetSavedMaps();
- ASSERT_EQ(1U, saved_maps.size());
- map_info = saved_maps[0].get();
- ASSERT_TRUE(map_info != nullptr);
- EXPECT_EQ(0x3000U, map_info->start);
- EXPECT_EQ(0x4000U, map_info->end);
- EXPECT_EQ(0U, map_info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
- EXPECT_TRUE(map_info->name.empty());
-}
-
-TEST_F(LocalUpdatableMapsTest, only_add_maps) {
- TemporaryFile tf;
- ASSERT_TRUE(
- android::base::WriteStringToFile("1000-2000 r-xp 00000 00:00 0\n"
- "3000-4000 r-xp 00000 00:00 0\n"
- "8000-9000 r-xp 00000 00:00 0\n"
- "a000-f000 r-xp 00000 00:00 0\n",
- tf.path));
-
- maps_.TestSetMapsFile(tf.path);
- ASSERT_TRUE(maps_.Reparse());
- ASSERT_EQ(4U, maps_.Total());
- EXPECT_EQ(0U, maps_.TestGetSavedMaps().size());
-
- MapInfo* map_info = maps_.Get(0);
- ASSERT_TRUE(map_info != nullptr);
- EXPECT_EQ(0x1000U, map_info->start);
- EXPECT_EQ(0x2000U, map_info->end);
- EXPECT_EQ(0U, map_info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
- EXPECT_TRUE(map_info->name.empty());
-
- map_info = maps_.Get(1);
- ASSERT_TRUE(map_info != nullptr);
- EXPECT_EQ(0x3000U, map_info->start);
- EXPECT_EQ(0x4000U, map_info->end);
- EXPECT_EQ(0U, map_info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
- EXPECT_TRUE(map_info->name.empty());
-
- map_info = maps_.Get(2);
- ASSERT_TRUE(map_info != nullptr);
- EXPECT_EQ(0x8000U, map_info->start);
- EXPECT_EQ(0x9000U, map_info->end);
- EXPECT_EQ(0U, map_info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
- EXPECT_TRUE(map_info->name.empty());
-
- map_info = maps_.Get(3);
- ASSERT_TRUE(map_info != nullptr);
- EXPECT_EQ(0xa000U, map_info->start);
- EXPECT_EQ(0xf000U, map_info->end);
- EXPECT_EQ(0U, map_info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
- EXPECT_TRUE(map_info->name.empty());
-}
-
-TEST_F(LocalUpdatableMapsTest, all_new_maps) {
- TemporaryFile tf;
- ASSERT_TRUE(
- android::base::WriteStringToFile("1000-2000 r-xp 00000 00:00 0\n"
- "a000-f000 r-xp 00000 00:00 0\n",
- tf.path));
-
- maps_.TestSetMapsFile(tf.path);
- ASSERT_TRUE(maps_.Reparse());
- ASSERT_EQ(2U, maps_.Total());
-
- MapInfo* map_info = maps_.Get(0);
- ASSERT_TRUE(map_info != nullptr);
- EXPECT_EQ(0x1000U, map_info->start);
- EXPECT_EQ(0x2000U, map_info->end);
- EXPECT_EQ(0U, map_info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
- EXPECT_TRUE(map_info->name.empty());
-
- map_info = maps_.Get(1);
- ASSERT_TRUE(map_info != nullptr);
- EXPECT_EQ(0xa000U, map_info->start);
- EXPECT_EQ(0xf000U, map_info->end);
- EXPECT_EQ(0U, map_info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
- EXPECT_TRUE(map_info->name.empty());
-
- auto& saved_maps = maps_.TestGetSavedMaps();
- ASSERT_EQ(2U, saved_maps.size());
- map_info = saved_maps[0].get();
- ASSERT_TRUE(map_info != nullptr);
- EXPECT_EQ(0x3000U, map_info->start);
- EXPECT_EQ(0x4000U, map_info->end);
- EXPECT_EQ(0U, map_info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
- EXPECT_TRUE(map_info->name.empty());
-
- map_info = saved_maps[1].get();
- ASSERT_TRUE(map_info != nullptr);
- EXPECT_EQ(0x8000U, map_info->start);
- EXPECT_EQ(0x9000U, map_info->end);
- EXPECT_EQ(0U, map_info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
- EXPECT_TRUE(map_info->name.empty());
-}
-
-TEST_F(LocalUpdatableMapsTest, add_map_prev_name_updated) {
- TemporaryFile tf;
- ASSERT_TRUE(
- android::base::WriteStringToFile("3000-4000 rwxp 00000 00:00 0\n"
- "8000-9000 r-xp 00000 00:00 0\n"
- "9000-a000 r-xp 00000 00:00 0\n",
- tf.path));
-
- maps_.TestSetMapsFile(tf.path);
- ASSERT_TRUE(maps_.Reparse());
- ASSERT_EQ(3U, maps_.Total());
-
- MapInfo* map_info = maps_.Get(2);
- ASSERT_TRUE(map_info != nullptr);
- EXPECT_EQ(0x9000U, map_info->start);
- EXPECT_EQ(0xA000U, map_info->end);
- EXPECT_EQ(0U, map_info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
- EXPECT_TRUE(map_info->name.empty());
- EXPECT_EQ(maps_.Get(1), map_info->prev_map);
-}
-
-TEST_F(LocalUpdatableMapsTest, add_map_prev_real_name_updated) {
- TemporaryFile tf;
- ASSERT_TRUE(
- android::base::WriteStringToFile("3000-4000 r-xp 00000 00:00 0 /fake/lib.so\n"
- "4000-5000 ---p 00000 00:00 0\n"
- "7000-8000 r-xp 00000 00:00 0 /fake/lib1.so\n"
- "8000-9000 ---p 00000 00:00 0\n",
- tf.path));
-
- maps_.TestSetMapsFile(tf.path);
- ASSERT_TRUE(maps_.Reparse());
- ASSERT_EQ(4U, maps_.Total());
-
- MapInfo* map_info = maps_.Get(2);
- ASSERT_TRUE(map_info != nullptr);
- EXPECT_EQ(0x7000U, map_info->start);
- EXPECT_EQ(0x8000U, map_info->end);
- EXPECT_EQ(0U, map_info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
- EXPECT_EQ(maps_.Get(0), map_info->prev_real_map);
- EXPECT_EQ(maps_.Get(1), map_info->prev_map);
- EXPECT_EQ("/fake/lib1.so", map_info->name);
-
- map_info = maps_.Get(3);
- ASSERT_TRUE(map_info != nullptr);
- EXPECT_EQ(0x8000U, map_info->start);
- EXPECT_EQ(0x9000U, map_info->end);
- EXPECT_EQ(0U, map_info->offset);
- EXPECT_TRUE(map_info->IsBlank());
- EXPECT_EQ(maps_.Get(2), map_info->prev_real_map);
- EXPECT_EQ(maps_.Get(2), map_info->prev_map);
- EXPECT_TRUE(map_info->name.empty());
-
- ASSERT_TRUE(
- android::base::WriteStringToFile("3000-4000 r-xp 00000 00:00 0 /fake/lib.so\n"
- "4000-5000 ---p 00000 00:00 0\n"
- "7000-8000 r-xp 00000 00:00 0 /fake/lib1.so\n"
- "8000-9000 ---p 00000 00:00 0\n"
- "9000-a000 r-xp 00000 00:00 0 /fake/lib2.so\n"
- "a000-b000 r-xp 00000 00:00 0 /fake/lib3.so\n",
- tf.path));
-
- maps_.TestSetMapsFile(tf.path);
- ASSERT_TRUE(maps_.Reparse());
- ASSERT_EQ(6U, maps_.Total());
-
- map_info = maps_.Get(2);
- ASSERT_TRUE(map_info != nullptr);
- EXPECT_EQ(0x7000U, map_info->start);
- EXPECT_EQ(0x8000U, map_info->end);
- EXPECT_EQ(0U, map_info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
- EXPECT_EQ("/fake/lib1.so", map_info->name);
- EXPECT_EQ(maps_.Get(1), map_info->prev_map);
- EXPECT_EQ(maps_.Get(0), map_info->prev_real_map);
-
- map_info = maps_.Get(4);
- ASSERT_TRUE(map_info != nullptr);
- EXPECT_EQ(0x9000U, map_info->start);
- EXPECT_EQ(0xA000U, map_info->end);
- EXPECT_EQ(0U, map_info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
- EXPECT_EQ("/fake/lib2.so", map_info->name);
- EXPECT_EQ(maps_.Get(3), map_info->prev_map);
- EXPECT_EQ(maps_.Get(2), map_info->prev_real_map);
-
- map_info = maps_.Get(5);
- ASSERT_TRUE(map_info != nullptr);
- EXPECT_EQ(0xA000U, map_info->start);
- EXPECT_EQ(0xB000U, map_info->end);
- EXPECT_EQ(0U, map_info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
- EXPECT_EQ("/fake/lib3.so", map_info->name);
- EXPECT_EQ(maps_.Get(4), map_info->prev_map);
- EXPECT_EQ(maps_.Get(4), map_info->prev_real_map);
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/LogFake.cpp b/libunwindstack/tests/LogFake.cpp
deleted file mode 100644
index 537ccaf..0000000
--- a/libunwindstack/tests/LogFake.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2015 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 <errno.h>
-#include <stdarg.h>
-
-#include <string>
-
-#include <android-base/stringprintf.h>
-#include <log/log.h>
-
-#include "LogFake.h"
-
-// Forward declarations.
-struct EventTagMap;
-struct AndroidLogEntry;
-
-std::string g_fake_log_buf;
-
-std::string g_fake_log_print;
-
-namespace unwindstack {
-
-void ResetLogs() {
- g_fake_log_buf = "";
- g_fake_log_print = "";
-}
-
-std::string GetFakeLogBuf() {
- return g_fake_log_buf;
-}
-
-std::string GetFakeLogPrint() {
- return g_fake_log_print;
-}
-
-} // namespace unwindstack
-
-extern "C" int __android_log_buf_write(int bufId, int prio, const char* tag, const char* msg) {
- g_fake_log_buf += std::to_string(bufId) + ' ' + std::to_string(prio) + ' ';
- g_fake_log_buf += tag;
- g_fake_log_buf += ' ';
- g_fake_log_buf += msg;
- return 1;
-}
-
-extern "C" int __android_log_print(int prio, const char* tag, const char* fmt, ...) {
- va_list ap;
- va_start(ap, fmt);
- int val = __android_log_vprint(prio, tag, fmt, ap);
- va_end(ap);
-
- return val;
-}
-
-extern "C" int __android_log_vprint(int prio, const char* tag, const char* fmt, va_list ap) {
- g_fake_log_print += std::to_string(prio) + ' ';
- g_fake_log_print += tag;
- g_fake_log_print += ' ';
-
- android::base::StringAppendV(&g_fake_log_print, fmt, ap);
-
- g_fake_log_print += '\n';
-
- return 1;
-}
-
-extern "C" log_id_t android_name_to_log_id(const char*) {
- return LOG_ID_SYSTEM;
-}
-
-extern "C" struct logger_list* android_logger_list_open(log_id_t, int, unsigned int, pid_t) {
- errno = EACCES;
- return nullptr;
-}
-
-extern "C" int android_logger_list_read(struct logger_list*, struct log_msg*) {
- return 0;
-}
-
-extern "C" EventTagMap* android_openEventTagMap(const char*) {
- return nullptr;
-}
-
-extern "C" int android_log_processBinaryLogBuffer(
- struct logger_entry*,
- AndroidLogEntry*, const EventTagMap*, char*, int) {
- return 0;
-}
-
-extern "C" void android_logger_list_free(struct logger_list*) {
-}
diff --git a/libunwindstack/tests/LogFake.h b/libunwindstack/tests/LogFake.h
deleted file mode 100644
index e1dc50d..0000000
--- a/libunwindstack/tests/LogFake.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef _LIBUNWINDSTACK_TESTS_LOG_FAKE_H
-#define _LIBUNWINDSTACK_TESTS_LOG_FAKE_H
-
-#include <string>
-
-namespace unwindstack {
-
-void ResetLogs();
-std::string GetFakeLogBuf();
-std::string GetFakeLogPrint();
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_TESTS_LOG_FAKE_H
diff --git a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
deleted file mode 100644
index 6d8d58e..0000000
--- a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * Copyright (C) 2016 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 <elf.h>
-#include <errno.h>
-#include <signal.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/ptrace.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <memory>
-#include <vector>
-
-#include <android-base/file.h>
-#include <gtest/gtest.h>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
-
-#include "ElfTestUtils.h"
-#include "MemoryFake.h"
-
-namespace unwindstack {
-
-class MapInfoCreateMemoryTest : public ::testing::Test {
- protected:
- template <typename Ehdr, typename Shdr>
- static void InitElf(int fd, uint64_t file_offset, uint64_t sh_offset, uint8_t class_type) {
- std::vector<uint8_t> buffer(20000);
- memset(buffer.data(), 0, buffer.size());
-
- Ehdr ehdr;
- memset(&ehdr, 0, sizeof(ehdr));
- memcpy(ehdr.e_ident, ELFMAG, SELFMAG);
- ehdr.e_ident[EI_CLASS] = class_type;
- ehdr.e_shoff = sh_offset;
- ehdr.e_shentsize = sizeof(Shdr) + 100;
- ehdr.e_shnum = 4;
- memcpy(&buffer[file_offset], &ehdr, sizeof(ehdr));
-
- ASSERT_TRUE(android::base::WriteFully(fd, buffer.data(), buffer.size()));
- }
-
- void SetUp() override {
- std::vector<uint8_t> buffer(12288, 0);
- memcpy(buffer.data(), ELFMAG, SELFMAG);
- buffer[EI_CLASS] = ELFCLASS32;
- ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), 1024));
-
- memset(buffer.data(), 0, buffer.size());
- memcpy(&buffer[0x1000], ELFMAG, SELFMAG);
- buffer[0x1000 + EI_CLASS] = ELFCLASS64;
- buffer[0x2000] = 0xff;
- ASSERT_TRUE(android::base::WriteFully(elf_at_1000_.fd, buffer.data(), buffer.size()));
-
- InitElf<Elf32_Ehdr, Elf32_Shdr>(elf32_at_map_.fd, 0x1000, 0x2000, ELFCLASS32);
- InitElf<Elf64_Ehdr, Elf64_Shdr>(elf64_at_map_.fd, 0x2000, 0x3000, ELFCLASS64);
-
- memory_ = new MemoryFake;
- process_memory_.reset(memory_);
- }
-
- MemoryFake* memory_;
- std::shared_ptr<Memory> process_memory_;
-
- TemporaryFile elf_;
-
- TemporaryFile elf_at_1000_;
-
- TemporaryFile elf32_at_map_;
- TemporaryFile elf64_at_map_;
-};
-
-TEST_F(MapInfoCreateMemoryTest, end_le_start) {
- MapInfo info(nullptr, nullptr, 0x100, 0x100, 0, 0, elf_.path);
-
- std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
- ASSERT_TRUE(memory.get() == nullptr);
-
- info.end = 0xff;
- memory.reset(info.CreateMemory(process_memory_));
- ASSERT_TRUE(memory.get() == nullptr);
-
- // Make sure this test is valid.
- info.end = 0x101;
- memory.reset(info.CreateMemory(process_memory_));
- ASSERT_TRUE(memory.get() != nullptr);
- EXPECT_FALSE(info.memory_backed_elf);
-}
-
-// Verify that if the offset is non-zero but there is no elf at the offset,
-// that the full file is used.
-TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_full_file) {
- MapInfo info(nullptr, nullptr, 0x100, 0x200, 0x100, 0, elf_.path);
-
- std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
- ASSERT_TRUE(memory.get() != nullptr);
- EXPECT_FALSE(info.memory_backed_elf);
- ASSERT_EQ(0x100U, info.elf_offset);
- EXPECT_EQ(0x100U, info.elf_start_offset);
-
- // Read the entire file.
- std::vector<uint8_t> buffer(1024);
- ASSERT_TRUE(memory->ReadFully(0, buffer.data(), 1024));
- ASSERT_TRUE(memcmp(buffer.data(), ELFMAG, SELFMAG) == 0);
- ASSERT_EQ(ELFCLASS32, buffer[EI_CLASS]);
- for (size_t i = EI_CLASS + 1; i < buffer.size(); i++) {
- ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i;
- }
-
- ASSERT_FALSE(memory->ReadFully(1024, buffer.data(), 1));
-
- // Now verify the elf start offset is set correctly based on the previous
- // info.
- MapInfo prev_info(nullptr, nullptr, 0, 0x100, 0x10, 0, "");
- info.prev_map = &prev_info;
- info.prev_real_map = &prev_info;
-
- // No preconditions met, change each one until it should set the elf start
- // offset to zero.
- info.elf_offset = 0;
- info.elf_start_offset = 0;
- info.memory_backed_elf = false;
- memory.reset(info.CreateMemory(process_memory_));
- ASSERT_TRUE(memory.get() != nullptr);
- EXPECT_FALSE(info.memory_backed_elf);
- ASSERT_EQ(0x100U, info.elf_offset);
- EXPECT_EQ(0x100U, info.elf_start_offset);
-
- prev_info.offset = 0;
- info.elf_offset = 0;
- info.elf_start_offset = 0;
- info.memory_backed_elf = false;
- memory.reset(info.CreateMemory(process_memory_));
- ASSERT_TRUE(memory.get() != nullptr);
- EXPECT_FALSE(info.memory_backed_elf);
- ASSERT_EQ(0x100U, info.elf_offset);
- EXPECT_EQ(0x100U, info.elf_start_offset);
-
- prev_info.flags = PROT_READ;
- info.elf_offset = 0;
- info.elf_start_offset = 0;
- info.memory_backed_elf = false;
- memory.reset(info.CreateMemory(process_memory_));
- ASSERT_TRUE(memory.get() != nullptr);
- EXPECT_FALSE(info.memory_backed_elf);
- ASSERT_EQ(0x100U, info.elf_offset);
- EXPECT_EQ(0x100U, info.elf_start_offset);
-
- prev_info.name = info.name;
- info.elf_offset = 0;
- info.elf_start_offset = 0;
- info.memory_backed_elf = false;
- memory.reset(info.CreateMemory(process_memory_));
- ASSERT_TRUE(memory.get() != nullptr);
- EXPECT_FALSE(info.memory_backed_elf);
- ASSERT_EQ(0x100U, info.elf_offset);
- EXPECT_EQ(0U, info.elf_start_offset);
-}
-
-// Verify that if the offset is non-zero and there is an elf at that
-// offset, that only part of the file is used.
-TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file) {
- MapInfo info(nullptr, nullptr, 0x100, 0x200, 0x1000, 0, elf_at_1000_.path);
-
- std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
- ASSERT_TRUE(memory.get() != nullptr);
- EXPECT_FALSE(info.memory_backed_elf);
- ASSERT_EQ(0U, info.elf_offset);
- EXPECT_EQ(0x1000U, info.elf_start_offset);
-
- // Read the valid part of the file.
- std::vector<uint8_t> buffer(0x100);
- ASSERT_TRUE(memory->ReadFully(0, buffer.data(), 0x100));
- ASSERT_TRUE(memcmp(buffer.data(), ELFMAG, SELFMAG) == 0);
- ASSERT_EQ(ELFCLASS64, buffer[EI_CLASS]);
- for (size_t i = EI_CLASS + 1; i < buffer.size(); i++) {
- ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i;
- }
-
- ASSERT_FALSE(memory->ReadFully(0x100, buffer.data(), 1));
-}
-
-// Verify that if the offset is non-zero and there is an elf at that
-// offset, that only part of the file is used. Further verify that if the
-// embedded elf is bigger than the initial map, the new object is larger
-// than the original map size. Do this for a 32 bit elf and a 64 bit elf.
-TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_elf32) {
- MapInfo info(nullptr, nullptr, 0x5000, 0x6000, 0x1000, 0, elf32_at_map_.path);
-
- std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
- ASSERT_TRUE(memory.get() != nullptr);
- EXPECT_FALSE(info.memory_backed_elf);
- ASSERT_EQ(0U, info.elf_offset);
- EXPECT_EQ(0x1000U, info.elf_start_offset);
-
- // Verify the memory is a valid elf.
- uint8_t e_ident[SELFMAG + 1];
- ASSERT_TRUE(memory->ReadFully(0, e_ident, SELFMAG));
- ASSERT_EQ(0, memcmp(e_ident, ELFMAG, SELFMAG));
-
- // Read past the end of what would normally be the size of the map.
- ASSERT_TRUE(memory->ReadFully(0x1000, e_ident, 1));
-}
-
-TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_elf64) {
- MapInfo info(nullptr, nullptr, 0x7000, 0x8000, 0x2000, 0, elf64_at_map_.path);
-
- std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
- ASSERT_TRUE(memory.get() != nullptr);
- EXPECT_FALSE(info.memory_backed_elf);
- ASSERT_EQ(0U, info.elf_offset);
- EXPECT_EQ(0x2000U, info.elf_start_offset);
-
- // Verify the memory is a valid elf.
- uint8_t e_ident[SELFMAG + 1];
- ASSERT_TRUE(memory->ReadFully(0, e_ident, SELFMAG));
- ASSERT_EQ(0, memcmp(e_ident, ELFMAG, SELFMAG));
-
- // Read past the end of what would normally be the size of the map.
- ASSERT_TRUE(memory->ReadFully(0x1000, e_ident, 1));
-}
-
-// Verify that device file names will never result in Memory object creation.
-TEST_F(MapInfoCreateMemoryTest, check_device_maps) {
- // Set up some memory so that a valid local memory object would
- // be returned if the file mapping fails, but the device check is incorrect.
- std::vector<uint8_t> buffer(1024);
- uint64_t start = reinterpret_cast<uint64_t>(buffer.data());
- MapInfo info(nullptr, nullptr, start, start + buffer.size(), 0, 0x8000, "/dev/something");
-
- std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
- ASSERT_TRUE(memory.get() == nullptr);
-}
-
-TEST_F(MapInfoCreateMemoryTest, process_memory) {
- MapInfo info(nullptr, nullptr, 0x2000, 0x3000, 0, PROT_READ, "");
-
- Elf32_Ehdr ehdr = {};
- TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
- std::vector<uint8_t> buffer(1024);
- memcpy(buffer.data(), &ehdr, sizeof(ehdr));
-
- // Verify that the the process_memory object is used, so seed it
- // with memory.
- for (size_t i = sizeof(ehdr); i < buffer.size(); i++) {
- buffer[i] = i % 256;
- }
- memory_->SetMemory(info.start, buffer.data(), buffer.size());
-
- std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
- ASSERT_TRUE(memory.get() != nullptr);
- EXPECT_TRUE(info.memory_backed_elf);
-
- memset(buffer.data(), 0, buffer.size());
- ASSERT_TRUE(memory->ReadFully(0, buffer.data(), buffer.size()));
- ASSERT_EQ(0, memcmp(&ehdr, buffer.data(), sizeof(ehdr)));
- for (size_t i = sizeof(ehdr); i < buffer.size(); i++) {
- ASSERT_EQ(i % 256, buffer[i]) << "Failed at byte " << i;
- }
-
- // Try to read outside of the map size.
- ASSERT_FALSE(memory->ReadFully(buffer.size(), buffer.data(), 1));
-}
-
-TEST_F(MapInfoCreateMemoryTest, valid_rosegment_zero_offset) {
- Maps maps;
- maps.Add(0x500, 0x600, 0, PROT_READ, "something_else", 0);
- maps.Add(0x1000, 0x2600, 0, PROT_READ, "/only/in/memory.so", 0);
- maps.Add(0x3000, 0x5000, 0x4000, PROT_READ | PROT_EXEC, "/only/in/memory.so", 0);
-
- Elf32_Ehdr ehdr = {};
- TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
- memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr));
- memory_->SetMemoryBlock(0x1000 + sizeof(ehdr), 0x1600 - sizeof(ehdr), 0xab);
-
- // Set the memory in the r-x map.
- memory_->SetMemoryBlock(0x3000, 0x2000, 0x5d);
-
- MapInfo* map_info = maps.Find(0x3000);
- ASSERT_TRUE(map_info != nullptr);
-
- std::unique_ptr<Memory> mem(map_info->CreateMemory(process_memory_));
- ASSERT_TRUE(mem.get() != nullptr);
- EXPECT_TRUE(map_info->memory_backed_elf);
- EXPECT_EQ(0x4000UL, map_info->elf_offset);
- EXPECT_EQ(0x4000UL, map_info->offset);
- EXPECT_EQ(0U, map_info->elf_start_offset);
-
- // Verify that reading values from this memory works properly.
- std::vector<uint8_t> buffer(0x4000);
- size_t bytes = mem->Read(0, buffer.data(), buffer.size());
- ASSERT_EQ(0x1600UL, bytes);
- ASSERT_EQ(0, memcmp(&ehdr, buffer.data(), sizeof(ehdr)));
- for (size_t i = sizeof(ehdr); i < bytes; i++) {
- ASSERT_EQ(0xab, buffer[i]) << "Failed at byte " << i;
- }
-
- bytes = mem->Read(0x4000, buffer.data(), buffer.size());
- ASSERT_EQ(0x2000UL, bytes);
- for (size_t i = 0; i < bytes; i++) {
- ASSERT_EQ(0x5d, buffer[i]) << "Failed at byte " << i;
- }
-}
-
-TEST_F(MapInfoCreateMemoryTest, valid_rosegment_non_zero_offset) {
- Maps maps;
- maps.Add(0x500, 0x600, 0, PROT_READ, "something_else", 0);
- maps.Add(0x1000, 0x2000, 0, PROT_READ, "/only/in/memory.apk", 0);
- maps.Add(0x2000, 0x3000, 0x1000, PROT_READ | PROT_EXEC, "/only/in/memory.apk", 0);
- maps.Add(0x3000, 0x4000, 0xa000, PROT_READ, "/only/in/memory.apk", 0);
- maps.Add(0x4000, 0x5000, 0xb000, PROT_READ | PROT_EXEC, "/only/in/memory.apk", 0);
-
- Elf32_Ehdr ehdr = {};
- TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
-
- // Setup an elf at offset 0x1000 in memory.
- memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr));
- memory_->SetMemoryBlock(0x1000 + sizeof(ehdr), 0x2000 - sizeof(ehdr), 0x12);
- memory_->SetMemoryBlock(0x2000, 0x1000, 0x23);
-
- // Setup an elf at offset 0x3000 in memory..
- memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr));
- memory_->SetMemoryBlock(0x3000 + sizeof(ehdr), 0x4000 - sizeof(ehdr), 0x34);
- memory_->SetMemoryBlock(0x4000, 0x1000, 0x43);
-
- MapInfo* map_info = maps.Find(0x4000);
- ASSERT_TRUE(map_info != nullptr);
-
- std::unique_ptr<Memory> mem(map_info->CreateMemory(process_memory_));
- ASSERT_TRUE(mem.get() != nullptr);
- EXPECT_TRUE(map_info->memory_backed_elf);
- EXPECT_EQ(0x1000UL, map_info->elf_offset);
- EXPECT_EQ(0xb000UL, map_info->offset);
- EXPECT_EQ(0xa000UL, map_info->elf_start_offset);
-
- // Verify that reading values from this memory works properly.
- std::vector<uint8_t> buffer(0x4000);
- size_t bytes = mem->Read(0, buffer.data(), buffer.size());
- ASSERT_EQ(0x1000UL, bytes);
- ASSERT_EQ(0, memcmp(&ehdr, buffer.data(), sizeof(ehdr)));
- for (size_t i = sizeof(ehdr); i < bytes; i++) {
- ASSERT_EQ(0x34, buffer[i]) << "Failed at byte " << i;
- }
-
- bytes = mem->Read(0x1000, buffer.data(), buffer.size());
- ASSERT_EQ(0x1000UL, bytes);
- for (size_t i = 0; i < bytes; i++) {
- ASSERT_EQ(0x43, buffer[i]) << "Failed at byte " << i;
- }
-}
-
-TEST_F(MapInfoCreateMemoryTest, rosegment_from_file) {
- Maps maps;
- maps.Add(0x500, 0x600, 0, PROT_READ, "something_else", 0);
- maps.Add(0x1000, 0x2000, 0x1000, PROT_READ, elf_at_1000_.path, 0);
- maps.Add(0x2000, 0x3000, 0x2000, PROT_READ | PROT_EXEC, elf_at_1000_.path, 0);
-
- MapInfo* map_info = maps.Find(0x2000);
- ASSERT_TRUE(map_info != nullptr);
-
- // Set up the size
- Elf64_Ehdr ehdr;
- ASSERT_EQ(0x1000, lseek(elf_at_1000_.fd, 0x1000, SEEK_SET));
- ASSERT_TRUE(android::base::ReadFully(elf_at_1000_.fd, &ehdr, sizeof(ehdr)));
-
- // Will not give the elf memory, because the read-only entry does not
- // extend over the executable segment.
- std::unique_ptr<Memory> memory(map_info->CreateMemory(process_memory_));
- ASSERT_TRUE(memory.get() != nullptr);
- EXPECT_FALSE(map_info->memory_backed_elf);
- std::vector<uint8_t> buffer(0x100);
- EXPECT_EQ(0x2000U, map_info->offset);
- EXPECT_EQ(0U, map_info->elf_offset);
- EXPECT_EQ(0U, map_info->elf_start_offset);
- ASSERT_TRUE(memory->ReadFully(0, buffer.data(), 0x100));
- EXPECT_EQ(0xffU, buffer[0]);
-
- // Now init the elf data enough so that the file memory object will be used.
- ehdr.e_shoff = 0x4000;
- ehdr.e_shnum = 1;
- ehdr.e_shentsize = 0x100;
- ASSERT_EQ(0x1000, lseek(elf_at_1000_.fd, 0x1000, SEEK_SET));
- ASSERT_TRUE(android::base::WriteFully(elf_at_1000_.fd, &ehdr, sizeof(ehdr)));
-
- map_info->memory_backed_elf = false;
- memory.reset(map_info->CreateMemory(process_memory_));
- EXPECT_FALSE(map_info->memory_backed_elf);
- EXPECT_EQ(0x2000U, map_info->offset);
- EXPECT_EQ(0x1000U, map_info->elf_offset);
- EXPECT_EQ(0x1000U, map_info->elf_start_offset);
- Elf64_Ehdr ehdr_mem;
- ASSERT_TRUE(memory->ReadFully(0, &ehdr_mem, sizeof(ehdr_mem)));
- EXPECT_TRUE(memcmp(&ehdr, &ehdr_mem, sizeof(ehdr)) == 0);
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/MapInfoGetBuildIDTest.cpp b/libunwindstack/tests/MapInfoGetBuildIDTest.cpp
deleted file mode 100644
index 70e136b..0000000
--- a/libunwindstack/tests/MapInfoGetBuildIDTest.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (C) 2019 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 <elf.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <unistd.h>
-
-#include <atomic>
-#include <memory>
-#include <string>
-#include <thread>
-#include <vector>
-
-#include <android-base/test_utils.h>
-
-#include <gtest/gtest.h>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
-
-#include "ElfFake.h"
-#include "ElfTestUtils.h"
-#include "MemoryFake.h"
-
-namespace unwindstack {
-
-class MapInfoGetBuildIDTest : public ::testing::Test {
- protected:
- void SetUp() override {
- tf_.reset(new TemporaryFile);
-
- memory_ = new MemoryFake;
- elf_ = new ElfFake(new MemoryFake);
- elf_interface_ = new ElfInterfaceFake(memory_);
- elf_->FakeSetInterface(elf_interface_);
- elf_container_.reset(elf_);
- map_info_.reset(
- new MapInfo(nullptr, nullptr, 0x1000, 0x20000, 0, PROT_READ | PROT_WRITE, tf_->path));
- }
-
- void MultipleThreadTest(std::string expected_build_id);
-
- MemoryFake* memory_;
- ElfFake* elf_;
- ElfInterfaceFake* elf_interface_;
- std::unique_ptr<ElfFake> elf_container_;
- std::unique_ptr<MapInfo> map_info_;
- std::unique_ptr<TemporaryFile> tf_;
-};
-
-TEST_F(MapInfoGetBuildIDTest, no_elf_and_no_valid_elf_in_memory) {
- MapInfo info(nullptr, nullptr, 0x1000, 0x2000, 0, PROT_READ, "");
-
- EXPECT_EQ("", info.GetBuildID());
- EXPECT_EQ("", info.GetPrintableBuildID());
-}
-
-TEST_F(MapInfoGetBuildIDTest, from_elf) {
- map_info_->elf.reset(elf_container_.release());
- elf_interface_->FakeSetBuildID("FAKE_BUILD_ID");
-
- EXPECT_EQ("FAKE_BUILD_ID", map_info_->GetBuildID());
- EXPECT_EQ("46414b455f4255494c445f4944", map_info_->GetPrintableBuildID());
-}
-
-TEST_F(MapInfoGetBuildIDTest, from_elf_no_sign_extension) {
- map_info_->elf.reset(elf_container_.release());
-
- std::string build_id = {static_cast<char>(0xfa), static_cast<char>(0xab), static_cast<char>(0x12),
- static_cast<char>(0x02)};
- elf_interface_->FakeSetBuildID(build_id);
-
- EXPECT_EQ("\xFA\xAB\x12\x2", map_info_->GetBuildID());
- EXPECT_EQ("faab1202", map_info_->GetPrintableBuildID());
-}
-
-void MapInfoGetBuildIDTest::MultipleThreadTest(std::string expected_build_id) {
- static constexpr size_t kNumConcurrentThreads = 100;
-
- std::string build_id_values[kNumConcurrentThreads];
- std::vector<std::thread*> threads;
-
- std::atomic_bool wait;
- wait = true;
- // Create all of the threads and have them do the GetLoadBias at the same time
- // to make it likely that a race will occur.
- for (size_t i = 0; i < kNumConcurrentThreads; i++) {
- std::thread* thread = new std::thread([i, this, &wait, &build_id_values]() {
- while (wait)
- ;
- build_id_values[i] = map_info_->GetBuildID();
- });
- threads.push_back(thread);
- }
-
- // Set them all going and wait for the threads to finish.
- wait = false;
- for (auto thread : threads) {
- thread->join();
- delete thread;
- }
-
- // Now verify that all of the elf files are exactly the same and valid.
- for (size_t i = 0; i < kNumConcurrentThreads; i++) {
- EXPECT_EQ(expected_build_id, build_id_values[i]) << "Thread " << i << " mismatched.";
- }
-}
-
-TEST_F(MapInfoGetBuildIDTest, multiple_thread_elf_exists) {
- map_info_->elf.reset(elf_container_.release());
- elf_interface_->FakeSetBuildID("FAKE_BUILD_ID");
-
- MultipleThreadTest("FAKE_BUILD_ID");
-}
-
-static void InitElfData(int fd) {
- Elf32_Ehdr ehdr;
- TestInitEhdr(&ehdr, ELFCLASS32, EM_ARM);
- ehdr.e_shoff = 0x2000;
- ehdr.e_shnum = 3;
- ehdr.e_shentsize = sizeof(Elf32_Shdr);
- ehdr.e_shstrndx = 2;
- off_t offset = 0;
- ASSERT_EQ(offset, lseek(fd, offset, SEEK_SET));
- ASSERT_EQ(static_cast<ssize_t>(sizeof(ehdr)), write(fd, &ehdr, sizeof(ehdr)));
-
- char note_section[128];
- Elf32_Nhdr note_header = {};
- note_header.n_namesz = sizeof("GNU");
- note_header.n_descsz = sizeof("ELF_BUILDID") - 1;
- note_header.n_type = NT_GNU_BUILD_ID;
- memcpy(¬e_section, ¬e_header, sizeof(note_header));
- size_t note_offset = sizeof(note_header);
- memcpy(¬e_section[note_offset], "GNU", note_header.n_namesz);
- note_offset += note_header.n_namesz;
- memcpy(¬e_section[note_offset], "ELF_BUILDID", note_header.n_descsz);
-
- Elf32_Shdr shdr = {};
- shdr.sh_type = SHT_NOTE;
- shdr.sh_name = 0x500;
- shdr.sh_offset = 0xb000;
- shdr.sh_size = sizeof(note_section);
- offset += ehdr.e_shoff + sizeof(shdr);
- ASSERT_EQ(offset, lseek(fd, offset, SEEK_SET));
- ASSERT_EQ(static_cast<ssize_t>(sizeof(shdr)), write(fd, &shdr, sizeof(shdr)));
-
- // 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;
- offset += sizeof(shdr);
- ASSERT_EQ(offset, lseek(fd, offset, SEEK_SET));
- ASSERT_EQ(static_cast<ssize_t>(sizeof(shdr)), write(fd, &shdr, sizeof(shdr)));
-
- offset = 0xf500;
- ASSERT_EQ(offset, lseek(fd, offset, SEEK_SET));
- ASSERT_EQ(static_cast<ssize_t>(sizeof(".note.gnu.build-id")),
- write(fd, ".note.gnu.build-id", sizeof(".note.gnu.build-id")));
-
- offset = 0xb000;
- ASSERT_EQ(offset, lseek(fd, offset, SEEK_SET));
- ASSERT_EQ(static_cast<ssize_t>(sizeof(note_section)),
- write(fd, note_section, sizeof(note_section)));
-}
-
-TEST_F(MapInfoGetBuildIDTest, from_memory) {
- InitElfData(tf_->fd);
-
- EXPECT_EQ("ELF_BUILDID", map_info_->GetBuildID());
- EXPECT_EQ("454c465f4255494c444944", map_info_->GetPrintableBuildID());
-}
-
-TEST_F(MapInfoGetBuildIDTest, multiple_thread_elf_exists_in_memory) {
- InitElfData(tf_->fd);
-
- MultipleThreadTest("ELF_BUILDID");
-}
-
-TEST_F(MapInfoGetBuildIDTest, real_elf) {
- MapInfo map_info(nullptr, nullptr, 0x1000, 0x20000, 0, PROT_READ | PROT_WRITE,
- TestGetFileDirectory() + "offline/empty_arm64/libc.so");
- EXPECT_EQ("6df0590c4920f4c7b9f34fe833f37d54", map_info.GetPrintableBuildID());
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/MapInfoGetElfTest.cpp b/libunwindstack/tests/MapInfoGetElfTest.cpp
deleted file mode 100644
index 7f97814..0000000
--- a/libunwindstack/tests/MapInfoGetElfTest.cpp
+++ /dev/null
@@ -1,422 +0,0 @@
-/*
- * Copyright (C) 2016 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 <elf.h>
-#include <errno.h>
-#include <signal.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/ptrace.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <atomic>
-#include <memory>
-#include <thread>
-#include <vector>
-
-#include <android-base/file.h>
-#include <gtest/gtest.h>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
-
-#include "ElfTestUtils.h"
-#include "MemoryFake.h"
-
-namespace unwindstack {
-
-class MapInfoGetElfTest : public ::testing::Test {
- protected:
- void SetUp() override {
- memory_ = new MemoryFake;
- process_memory_.reset(memory_);
- }
-
- template <typename Ehdr, typename Shdr>
- static void InitElf(uint64_t sh_offset, Ehdr* ehdr, uint8_t class_type, uint8_t machine_type) {
- memset(ehdr, 0, sizeof(*ehdr));
- memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
- ehdr->e_ident[EI_CLASS] = class_type;
- ehdr->e_machine = machine_type;
- ehdr->e_shoff = sh_offset;
- ehdr->e_shentsize = sizeof(Shdr) + 100;
- ehdr->e_shnum = 4;
- }
-
- const size_t kMapSize = 4096;
-
- std::shared_ptr<Memory> process_memory_;
- MemoryFake* memory_;
-
- TemporaryFile elf_;
-};
-
-TEST_F(MapInfoGetElfTest, invalid) {
- MapInfo info(nullptr, nullptr, 0x1000, 0x2000, 0, PROT_READ, "");
-
- // The map is empty, but this should still create an invalid elf object.
- Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
- ASSERT_TRUE(elf != nullptr);
- ASSERT_FALSE(elf->valid());
-}
-
-TEST_F(MapInfoGetElfTest, valid32) {
- MapInfo info(nullptr, nullptr, 0x3000, 0x4000, 0, PROT_READ, "");
-
- Elf32_Ehdr ehdr;
- TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
- memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr));
-
- Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
- ASSERT_TRUE(elf != nullptr);
- ASSERT_TRUE(elf->valid());
- EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
- EXPECT_EQ(ELFCLASS32, elf->class_type());
-
- // Now verify that an empty process memory returns an invalid elf object.
- info.elf.reset();
- elf = info.GetElf(std::shared_ptr<Memory>(), ARCH_ARM);
- ASSERT_TRUE(elf != nullptr);
- ASSERT_FALSE(elf->valid());
-}
-
-TEST_F(MapInfoGetElfTest, valid64) {
- MapInfo info(nullptr, nullptr, 0x8000, 0x9000, 0, PROT_READ, "");
-
- Elf64_Ehdr ehdr;
- TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
- memory_->SetMemory(0x8000, &ehdr, sizeof(ehdr));
-
- Elf* elf = info.GetElf(process_memory_, ARCH_ARM64);
- ASSERT_TRUE(elf != nullptr);
- ASSERT_TRUE(elf->valid());
- EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
- EXPECT_EQ(ELFCLASS64, elf->class_type());
-}
-
-TEST_F(MapInfoGetElfTest, invalid_arch_mismatch) {
- MapInfo info(nullptr, nullptr, 0x3000, 0x4000, 0, PROT_READ, "");
-
- Elf32_Ehdr ehdr;
- TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
- memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr));
-
- Elf* elf = info.GetElf(process_memory_, ARCH_X86);
- ASSERT_TRUE(elf != nullptr);
- ASSERT_FALSE(elf->valid());
-}
-
-TEST_F(MapInfoGetElfTest, gnu_debugdata_init32) {
- MapInfo info(nullptr, nullptr, 0x2000, 0x3000, 0, PROT_READ, "");
-
- TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, true,
- [&](uint64_t offset, const void* ptr, size_t size) {
- memory_->SetMemory(0x2000 + offset, ptr, size);
- });
-
- Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
- ASSERT_TRUE(elf != nullptr);
- ASSERT_TRUE(elf->valid());
- EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
- EXPECT_EQ(ELFCLASS32, elf->class_type());
- EXPECT_TRUE(elf->gnu_debugdata_interface() != nullptr);
-}
-
-TEST_F(MapInfoGetElfTest, gnu_debugdata_init64) {
- MapInfo info(nullptr, nullptr, 0x5000, 0x8000, 0, PROT_READ, "");
-
- TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, true,
- [&](uint64_t offset, const void* ptr, size_t size) {
- memory_->SetMemory(0x5000 + offset, ptr, size);
- });
-
- Elf* elf = info.GetElf(process_memory_, ARCH_ARM64);
- ASSERT_TRUE(elf != nullptr);
- ASSERT_TRUE(elf->valid());
- EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
- EXPECT_EQ(ELFCLASS64, elf->class_type());
- EXPECT_TRUE(elf->gnu_debugdata_interface() != nullptr);
-}
-
-TEST_F(MapInfoGetElfTest, end_le_start) {
- MapInfo info(nullptr, nullptr, 0x1000, 0x1000, 0, PROT_READ, elf_.path);
-
- Elf32_Ehdr ehdr;
- TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
- ASSERT_TRUE(android::base::WriteFully(elf_.fd, &ehdr, sizeof(ehdr)));
-
- Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
- ASSERT_TRUE(elf != nullptr);
- ASSERT_FALSE(elf->valid());
-
- info.elf.reset();
- info.end = 0xfff;
- elf = info.GetElf(process_memory_, ARCH_ARM);
- ASSERT_TRUE(elf != nullptr);
- ASSERT_FALSE(elf->valid());
-
- // Make sure this test is valid.
- info.elf.reset();
- info.end = 0x2000;
- elf = info.GetElf(process_memory_, ARCH_ARM);
- ASSERT_TRUE(elf != nullptr);
- ASSERT_TRUE(elf->valid());
-}
-
-// Verify that if the offset is non-zero but there is no elf at the offset,
-// that the full file is used.
-TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_full_file) {
- MapInfo info(nullptr, nullptr, 0x1000, 0x2000, 0x100, PROT_READ, elf_.path);
-
- std::vector<uint8_t> buffer(0x1000);
- memset(buffer.data(), 0, buffer.size());
- Elf32_Ehdr ehdr;
- TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
- memcpy(buffer.data(), &ehdr, sizeof(ehdr));
- ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
-
- Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
- ASSERT_TRUE(elf != nullptr);
- ASSERT_TRUE(elf->valid());
- ASSERT_TRUE(elf->memory() != nullptr);
- ASSERT_EQ(0x100U, info.elf_offset);
-
- // Read the entire file.
- memset(buffer.data(), 0, buffer.size());
- ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), buffer.size()));
- ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
- for (size_t i = sizeof(ehdr); i < buffer.size(); i++) {
- ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i;
- }
-
- ASSERT_FALSE(elf->memory()->ReadFully(buffer.size(), buffer.data(), 1));
-}
-
-// Verify that if the offset is non-zero and there is an elf at that
-// offset, that only part of the file is used.
-TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file) {
- MapInfo info(nullptr, nullptr, 0x1000, 0x2000, 0x2000, PROT_READ, elf_.path);
-
- std::vector<uint8_t> buffer(0x4000);
- memset(buffer.data(), 0, buffer.size());
- Elf32_Ehdr ehdr;
- TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
- memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr));
- ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
-
- Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
- ASSERT_TRUE(elf != nullptr);
- ASSERT_TRUE(elf->valid());
- ASSERT_TRUE(elf->memory() != nullptr);
- ASSERT_EQ(0U, info.elf_offset);
-
- // Read the valid part of the file.
- ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), 0x1000));
- ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
- for (size_t i = sizeof(ehdr); i < 0x1000; i++) {
- ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i;
- }
-
- ASSERT_FALSE(elf->memory()->ReadFully(0x1000, buffer.data(), 1));
-}
-
-// Verify that if the offset is non-zero and there is an elf at that
-// offset, that only part of the file is used. Further verify that if the
-// embedded elf is bigger than the initial map, the new object is larger
-// than the original map size. Do this for a 32 bit elf and a 64 bit elf.
-TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf32) {
- MapInfo info(nullptr, nullptr, 0x5000, 0x6000, 0x1000, PROT_READ, elf_.path);
-
- std::vector<uint8_t> buffer(0x4000);
- memset(buffer.data(), 0, buffer.size());
- Elf32_Ehdr ehdr;
- TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
- ehdr.e_shoff = 0x2000;
- ehdr.e_shentsize = sizeof(Elf32_Shdr) + 100;
- ehdr.e_shnum = 4;
- memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr));
- ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
-
- Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
- ASSERT_TRUE(elf != nullptr);
- ASSERT_TRUE(elf->valid());
- ASSERT_TRUE(elf->memory() != nullptr);
- ASSERT_EQ(0U, info.elf_offset);
-
- // Verify the memory is a valid elf.
- memset(buffer.data(), 0, buffer.size());
- ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), 0x1000));
- ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
-
- // Read past the end of what would normally be the size of the map.
- ASSERT_TRUE(elf->memory()->ReadFully(0x1000, buffer.data(), 1));
-}
-
-TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf64) {
- MapInfo info(nullptr, nullptr, 0x7000, 0x8000, 0x1000, PROT_READ, elf_.path);
-
- std::vector<uint8_t> buffer(0x4000);
- memset(buffer.data(), 0, buffer.size());
- Elf64_Ehdr ehdr;
- TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
- ehdr.e_shoff = 0x2000;
- ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
- ehdr.e_shnum = 4;
- memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr));
- ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
-
- Elf* elf = info.GetElf(process_memory_, ARCH_ARM64);
- ASSERT_TRUE(elf != nullptr);
- ASSERT_TRUE(elf->valid());
- ASSERT_TRUE(elf->memory() != nullptr);
- ASSERT_EQ(0U, info.elf_offset);
-
- // Verify the memory is a valid elf.
- memset(buffer.data(), 0, buffer.size());
- ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), 0x1000));
- ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
-
- // Read past the end of what would normally be the size of the map.
- ASSERT_TRUE(elf->memory()->ReadFully(0x1000, buffer.data(), 1));
-}
-
-TEST_F(MapInfoGetElfTest, check_device_maps) {
- MapInfo info(nullptr, nullptr, 0x7000, 0x8000, 0x1000, PROT_READ | MAPS_FLAGS_DEVICE_MAP,
- "/dev/something");
-
- // Create valid elf data in process memory for this to verify that only
- // the name is causing invalid elf data.
- Elf64_Ehdr ehdr;
- TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_X86_64);
- ehdr.e_shoff = 0x2000;
- ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
- ehdr.e_shnum = 0;
- memory_->SetMemory(0x7000, &ehdr, sizeof(ehdr));
-
- Elf* elf = info.GetElf(process_memory_, ARCH_X86_64);
- ASSERT_TRUE(elf != nullptr);
- ASSERT_FALSE(elf->valid());
-
- // Set the name to nothing to verify that it still fails.
- info.elf.reset();
- info.name = "";
- elf = info.GetElf(process_memory_, ARCH_X86_64);
- ASSERT_FALSE(elf->valid());
-
- // Change the flags and verify the elf is valid now.
- info.elf.reset();
- info.flags = PROT_READ;
- elf = info.GetElf(process_memory_, ARCH_X86_64);
- ASSERT_TRUE(elf->valid());
-}
-
-TEST_F(MapInfoGetElfTest, multiple_thread_get_elf) {
- static constexpr size_t kNumConcurrentThreads = 100;
-
- Elf64_Ehdr ehdr;
- TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_X86_64);
- ehdr.e_shoff = 0x2000;
- ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
- ehdr.e_shnum = 0;
- memory_->SetMemory(0x7000, &ehdr, sizeof(ehdr));
-
- Elf* elf_in_threads[kNumConcurrentThreads];
- std::vector<std::thread*> threads;
-
- std::atomic_bool wait;
- wait = true;
- // Create all of the threads and have them do the GetElf at the same time
- // to make it likely that a race will occur.
- MapInfo info(nullptr, nullptr, 0x7000, 0x8000, 0x1000, PROT_READ, "");
- for (size_t i = 0; i < kNumConcurrentThreads; i++) {
- std::thread* thread = new std::thread([i, this, &wait, &info, &elf_in_threads]() {
- while (wait)
- ;
- Elf* elf = info.GetElf(process_memory_, ARCH_X86_64);
- elf_in_threads[i] = elf;
- });
- threads.push_back(thread);
- }
- ASSERT_TRUE(info.elf == nullptr);
-
- // Set them all going and wait for the threads to finish.
- wait = false;
- for (auto thread : threads) {
- thread->join();
- delete thread;
- }
-
- // Now verify that all of the elf files are exactly the same and valid.
- Elf* elf = info.elf.get();
- ASSERT_TRUE(elf != nullptr);
- EXPECT_TRUE(elf->valid());
- for (size_t i = 0; i < kNumConcurrentThreads; i++) {
- EXPECT_EQ(elf, elf_in_threads[i]) << "Thread " << i << " mismatched.";
- }
-}
-
-// Verify that previous maps don't automatically get the same elf object.
-TEST_F(MapInfoGetElfTest, prev_map_elf_not_set) {
- MapInfo info1(nullptr, nullptr, 0x1000, 0x2000, 0, PROT_READ, "/not/present");
- MapInfo info2(&info1, &info1, 0x2000, 0x3000, 0, PROT_READ, elf_.path);
-
- Elf32_Ehdr ehdr;
- TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
- memory_->SetMemory(0x2000, &ehdr, sizeof(ehdr));
- Elf* elf = info2.GetElf(process_memory_, ARCH_ARM);
- ASSERT_TRUE(elf != nullptr);
- ASSERT_TRUE(elf->valid());
-
- ASSERT_NE(elf, info1.GetElf(process_memory_, ARCH_ARM));
-}
-
-// Verify that a read-only map followed by a read-execute map will result
-// in the same elf object in both maps.
-TEST_F(MapInfoGetElfTest, read_only_followed_by_read_exec_share_elf) {
- MapInfo r_info(nullptr, nullptr, 0x1000, 0x2000, 0, PROT_READ, elf_.path);
- MapInfo rw_info(&r_info, &r_info, 0x2000, 0x3000, 0x1000, PROT_READ | PROT_EXEC, elf_.path);
-
- Elf32_Ehdr ehdr;
- TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
- memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr));
- Elf* elf = rw_info.GetElf(process_memory_, ARCH_ARM);
- ASSERT_TRUE(elf != nullptr);
- ASSERT_TRUE(elf->valid());
-
- ASSERT_EQ(elf, r_info.GetElf(process_memory_, ARCH_ARM));
-}
-
-// Verify that a read-only map followed by an empty map, then followed by
-// a read-execute map will result in the same elf object in both maps.
-TEST_F(MapInfoGetElfTest, read_only_followed_by_empty_then_read_exec_share_elf) {
- MapInfo r_info(nullptr, nullptr, 0x1000, 0x2000, 0, PROT_READ, elf_.path);
- MapInfo empty(&r_info, &r_info, 0x2000, 0x3000, 0, 0, "");
- MapInfo rw_info(&empty, &r_info, 0x3000, 0x4000, 0x2000, PROT_READ | PROT_EXEC, elf_.path);
-
- Elf32_Ehdr ehdr;
- TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
- memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr));
- Elf* elf = rw_info.GetElf(process_memory_, ARCH_ARM);
- ASSERT_TRUE(elf != nullptr);
- ASSERT_TRUE(elf->valid());
-
- ASSERT_EQ(elf, r_info.GetElf(process_memory_, ARCH_ARM));
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp b/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp
deleted file mode 100644
index 971d452..0000000
--- a/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2016 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 <elf.h>
-#include <errno.h>
-#include <signal.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/ptrace.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <atomic>
-#include <memory>
-#include <thread>
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/test_utils.h>
-#include <gtest/gtest.h>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
-
-#include "ElfFake.h"
-#include "ElfTestUtils.h"
-#include "MemoryFake.h"
-
-namespace unwindstack {
-
-class MapInfoGetLoadBiasTest : public ::testing::Test {
- protected:
- void SetUp() override {
- memory_ = new MemoryFake;
- process_memory_.reset(memory_);
- elf_ = new ElfFake(new MemoryFake);
- elf_container_.reset(elf_);
- map_info_.reset(new MapInfo(nullptr, nullptr, 0x1000, 0x20000, 0, PROT_READ | PROT_WRITE, ""));
- }
-
- void MultipleThreadTest(uint64_t expected_load_bias);
-
- std::shared_ptr<Memory> process_memory_;
- MemoryFake* memory_;
- ElfFake* elf_;
- std::unique_ptr<ElfFake> elf_container_;
- std::unique_ptr<MapInfo> map_info_;
-};
-
-TEST_F(MapInfoGetLoadBiasTest, no_elf_and_no_valid_elf_in_memory) {
- MapInfo info(nullptr, nullptr, 0x1000, 0x2000, 0, PROT_READ, "");
-
- EXPECT_EQ(0U, info.GetLoadBias(process_memory_));
-}
-
-TEST_F(MapInfoGetLoadBiasTest, load_bias_cached_from_elf) {
- map_info_->elf.reset(elf_container_.release());
-
- elf_->FakeSetLoadBias(0);
- EXPECT_EQ(0U, map_info_->GetLoadBias(process_memory_));
-
- elf_->FakeSetLoadBias(0x1000);
- EXPECT_EQ(0U, map_info_->GetLoadBias(process_memory_));
-}
-
-TEST_F(MapInfoGetLoadBiasTest, elf_exists) {
- map_info_->elf.reset(elf_container_.release());
-
- elf_->FakeSetLoadBias(0);
- EXPECT_EQ(0U, map_info_->GetLoadBias(process_memory_));
-
- map_info_->load_bias = INT64_MAX;
- elf_->FakeSetLoadBias(0x1000);
- EXPECT_EQ(0x1000U, map_info_->GetLoadBias(process_memory_));
-}
-
-void MapInfoGetLoadBiasTest::MultipleThreadTest(uint64_t expected_load_bias) {
- static constexpr size_t kNumConcurrentThreads = 100;
-
- uint64_t load_bias_values[kNumConcurrentThreads];
- std::vector<std::thread*> threads;
-
- std::atomic_bool wait;
- wait = true;
- // Create all of the threads and have them do the GetLoadBias at the same time
- // to make it likely that a race will occur.
- for (size_t i = 0; i < kNumConcurrentThreads; i++) {
- std::thread* thread = new std::thread([i, this, &wait, &load_bias_values]() {
- while (wait)
- ;
- load_bias_values[i] = map_info_->GetLoadBias(process_memory_);
- });
- threads.push_back(thread);
- }
-
- // Set them all going and wait for the threads to finish.
- wait = false;
- for (auto thread : threads) {
- thread->join();
- delete thread;
- }
-
- // Now verify that all of the elf files are exactly the same and valid.
- for (size_t i = 0; i < kNumConcurrentThreads; i++) {
- EXPECT_EQ(expected_load_bias, load_bias_values[i]) << "Thread " << i << " mismatched.";
- }
-}
-
-TEST_F(MapInfoGetLoadBiasTest, multiple_thread_elf_exists) {
- map_info_->elf.reset(elf_container_.release());
- elf_->FakeSetLoadBias(0x1000);
-
- MultipleThreadTest(0x1000);
-}
-
-static void InitElfData(MemoryFake* memory, uint64_t offset) {
- Elf32_Ehdr ehdr;
- TestInitEhdr(&ehdr, ELFCLASS32, EM_ARM);
- ehdr.e_phoff = 0x5000;
- ehdr.e_phnum = 2;
- ehdr.e_phentsize = sizeof(Elf32_Phdr);
- memory->SetMemory(offset, &ehdr, sizeof(ehdr));
-
- Elf32_Phdr phdr;
- memset(&phdr, 0, sizeof(phdr));
- phdr.p_type = PT_NULL;
- memory->SetMemory(offset + 0x5000, &phdr, sizeof(phdr));
- phdr.p_type = PT_LOAD;
- phdr.p_flags = PF_X;
- phdr.p_offset = 0;
- phdr.p_vaddr = 0xe000;
- memory->SetMemory(offset + 0x5000 + sizeof(phdr), &phdr, sizeof(phdr));
-}
-
-TEST_F(MapInfoGetLoadBiasTest, elf_exists_in_memory) {
- InitElfData(memory_, map_info_->start);
-
- EXPECT_EQ(0xe000U, map_info_->GetLoadBias(process_memory_));
-}
-
-TEST_F(MapInfoGetLoadBiasTest, elf_exists_in_memory_cached) {
- InitElfData(memory_, map_info_->start);
-
- EXPECT_EQ(0xe000U, map_info_->GetLoadBias(process_memory_));
-
- memory_->Clear();
- EXPECT_EQ(0xe000U, map_info_->GetLoadBias(process_memory_));
-}
-
-TEST_F(MapInfoGetLoadBiasTest, multiple_thread_elf_exists_in_memory) {
- InitElfData(memory_, map_info_->start);
-
- MultipleThreadTest(0xe000);
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/MapInfoTest.cpp b/libunwindstack/tests/MapInfoTest.cpp
deleted file mode 100644
index 98edc0e..0000000
--- a/libunwindstack/tests/MapInfoTest.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2018 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 <stdint.h>
-
-#include <gtest/gtest.h>
-
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Maps.h>
-
-#include "ElfFake.h"
-
-namespace unwindstack {
-
-TEST(MapInfoTest, maps_constructor_const_char) {
- MapInfo prev_map(nullptr, nullptr, 0, 0, 0, 0, "");
- MapInfo map_info(&prev_map, &prev_map, 1, 2, 3, 4, "map");
-
- EXPECT_EQ(&prev_map, map_info.prev_map);
- EXPECT_EQ(1UL, map_info.start);
- EXPECT_EQ(2UL, map_info.end);
- EXPECT_EQ(3UL, map_info.offset);
- EXPECT_EQ(4UL, map_info.flags);
- EXPECT_EQ("map", map_info.name);
- EXPECT_EQ(INT64_MAX, map_info.load_bias);
- EXPECT_EQ(0UL, map_info.elf_offset);
- EXPECT_TRUE(map_info.elf.get() == nullptr);
-}
-
-TEST(MapInfoTest, maps_constructor_string) {
- std::string name("string_map");
- MapInfo prev_map(nullptr, nullptr, 0, 0, 0, 0, "");
- MapInfo map_info(&prev_map, &prev_map, 1, 2, 3, 4, name);
-
- EXPECT_EQ(&prev_map, map_info.prev_map);
- EXPECT_EQ(1UL, map_info.start);
- EXPECT_EQ(2UL, map_info.end);
- EXPECT_EQ(3UL, map_info.offset);
- EXPECT_EQ(4UL, map_info.flags);
- EXPECT_EQ("string_map", map_info.name);
- EXPECT_EQ(INT64_MAX, map_info.load_bias);
- EXPECT_EQ(0UL, map_info.elf_offset);
- EXPECT_TRUE(map_info.elf.get() == nullptr);
-}
-
-TEST(MapInfoTest, get_function_name) {
- ElfFake* elf = new ElfFake(nullptr);
- ElfInterfaceFake* interface = new ElfInterfaceFake(nullptr);
- elf->FakeSetInterface(interface);
- interface->FakePushFunctionData(FunctionData("function", 1000));
-
- MapInfo map_info(nullptr, nullptr, 1, 2, 3, 4, "");
- map_info.elf.reset(elf);
-
- std::string name;
- uint64_t offset;
- ASSERT_TRUE(map_info.GetFunctionName(1000, &name, &offset));
- EXPECT_EQ("function", name);
- EXPECT_EQ(1000UL, offset);
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/MapsTest.cpp b/libunwindstack/tests/MapsTest.cpp
deleted file mode 100644
index 724eeb5..0000000
--- a/libunwindstack/tests/MapsTest.cpp
+++ /dev/null
@@ -1,618 +0,0 @@
-/*
- * Copyright (C) 2016 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 <inttypes.h>
-#include <sys/mman.h>
-
-#include <android-base/file.h>
-#include <android-base/stringprintf.h>
-#include <gtest/gtest.h>
-
-#include <unwindstack/Maps.h>
-
-namespace unwindstack {
-
-static void VerifyLine(std::string line, MapInfo* info) {
- BufferMaps maps(line.c_str());
-
- if (info == nullptr) {
- ASSERT_FALSE(maps.Parse()) << "Failed on: " + line;
- } else {
- ASSERT_TRUE(maps.Parse()) << "Failed on: " + line;
- MapInfo* element = maps.Get(0);
- ASSERT_TRUE(element != nullptr) << "Failed on: " + line;
- info->start = element->start;
- info->end = element->end;
- info->offset = element->offset;
- info->flags = element->flags;
- info->name = element->name;
- info->elf_offset = element->elf_offset;
- }
-}
-
-TEST(MapsTest, map_add) {
- Maps maps;
-
- maps.Add(0x1000, 0x2000, 0, PROT_READ, "fake_map", 0);
- maps.Add(0x3000, 0x4000, 0x10, 0, "", 0x1234);
- maps.Add(0x5000, 0x6000, 1, 2, "fake_map2", static_cast<uint64_t>(-1));
-
- ASSERT_EQ(3U, maps.Total());
- MapInfo* info = maps.Get(0);
- ASSERT_EQ(0x1000U, info->start);
- ASSERT_EQ(0x2000U, info->end);
- ASSERT_EQ(0U, info->offset);
- ASSERT_EQ(PROT_READ, info->flags);
- ASSERT_EQ("fake_map", info->name);
- ASSERT_EQ(0U, info->elf_offset);
- ASSERT_EQ(0U, info->load_bias.load());
-}
-
-TEST(MapsTest, map_move) {
- Maps maps;
-
- maps.Add(0x1000, 0x2000, 0, PROT_READ, "fake_map", 0);
- maps.Add(0x3000, 0x4000, 0x10, 0, "", 0x1234);
- maps.Add(0x5000, 0x6000, 1, 2, "fake_map2", static_cast<uint64_t>(-1));
-
- Maps maps2 = std::move(maps);
-
- ASSERT_EQ(3U, maps2.Total());
- MapInfo* info = maps2.Get(0);
- ASSERT_EQ(0x1000U, info->start);
- ASSERT_EQ(0x2000U, info->end);
- ASSERT_EQ(0U, info->offset);
- ASSERT_EQ(PROT_READ, info->flags);
- ASSERT_EQ("fake_map", info->name);
- ASSERT_EQ(0U, info->elf_offset);
- ASSERT_EQ(0U, info->load_bias.load());
-}
-
-TEST(MapsTest, verify_parse_line) {
- MapInfo info(nullptr, nullptr, 0, 0, 0, 0, "");
-
- VerifyLine("01-02 rwxp 03 04:05 06\n", &info);
- EXPECT_EQ(1U, info.start);
- EXPECT_EQ(2U, info.end);
- EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info.flags);
- EXPECT_EQ(3U, info.offset);
- EXPECT_EQ("", info.name);
-
- VerifyLine("0a-0b ---s 0c 0d:0e 06 /fake/name\n", &info);
- EXPECT_EQ(0xaU, info.start);
- EXPECT_EQ(0xbU, info.end);
- EXPECT_EQ(0U, info.flags);
- EXPECT_EQ(0xcU, info.offset);
- EXPECT_EQ("/fake/name", info.name);
-
- VerifyLine("01-02 rwxp 03 04:05 06 /fake/name/again\n", &info);
- EXPECT_EQ(1U, info.start);
- EXPECT_EQ(2U, info.end);
- EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info.flags);
- EXPECT_EQ(3U, info.offset);
- EXPECT_EQ("/fake/name/again", info.name);
-
- VerifyLine("-00 rwxp 00 00:00 0\n", nullptr);
- VerifyLine("00- rwxp 00 00:00 0\n", nullptr);
- VerifyLine("00-00 rwxp 00 :00 0\n", nullptr);
- VerifyLine("00-00 rwxp 00 00:00 \n", nullptr);
- VerifyLine("x-00 rwxp 00 00:00 0\n", nullptr);
- VerifyLine("00 -00 rwxp 00 00:00 0\n", nullptr);
- VerifyLine("00-x rwxp 00 00:00 0\n", nullptr);
- VerifyLine("00-x rwxp 00 00:00 0\n", nullptr);
- VerifyLine("00-00x rwxp 00 00:00 0\n", nullptr);
- VerifyLine("00-00 rwxp0 00 00:00 0\n", nullptr);
- VerifyLine("00-00 rwxp0 00 00:00 0\n", nullptr);
- VerifyLine("00-00 rwp 00 00:00 0\n", nullptr);
- VerifyLine("00-00 rwxp 0000:00 0\n", nullptr);
- VerifyLine("00-00 rwxp 00 00 :00 0\n", nullptr);
- VerifyLine("00-00 rwxp 00 00: 00 0\n", nullptr);
- VerifyLine("00-00 rwxp 00 00:000\n", nullptr);
- VerifyLine("00-00 rwxp 00 00:00 0/fake\n", nullptr);
- VerifyLine("00-00 xxxx 00 00:00 0 /fake\n", nullptr);
- VerifyLine("00-00 ywxp 00 00:00 0 /fake\n", nullptr);
- VerifyLine("00-00 ryxp 00 00:00 0 /fake\n", nullptr);
- VerifyLine("00-00 rwyp 00 00:00 0 /fake\n", nullptr);
- VerifyLine("00-00 rwx- 00 00:00 0 /fake\n", nullptr);
- VerifyLine("0\n", nullptr);
- VerifyLine("00\n", nullptr);
- VerifyLine("00-\n", nullptr);
- VerifyLine("00-0\n", nullptr);
- VerifyLine("00-00\n", nullptr);
- VerifyLine("00-00 \n", nullptr);
- VerifyLine("00-00 -\n", nullptr);
- VerifyLine("00-00 r\n", nullptr);
- VerifyLine("00-00 --\n", nullptr);
- VerifyLine("00-00 rw\n", nullptr);
- VerifyLine("00-00 ---\n", nullptr);
- VerifyLine("00-00 rwx\n", nullptr);
- VerifyLine("00-00 ---s\n", nullptr);
- VerifyLine("00-00 ---p\n", nullptr);
- VerifyLine("00-00 ---s 0\n", nullptr);
- VerifyLine("00-00 ---p 0 \n", nullptr);
- VerifyLine("00-00 ---p 0 0\n", nullptr);
- VerifyLine("00-00 ---p 0 0:\n", nullptr);
- VerifyLine("00-00 ---p 0 0:0\n", nullptr);
- VerifyLine("00-00 ---p 0 0:0 \n", nullptr);
-
- // Line to verify that the parser will detect a completely malformed line
- // properly.
- VerifyLine("7ffff7dda000-7ffff7dfd7ffff7ff3000-7ffff7ff4000 ---p 0000f000 fc:02 44171565\n",
- nullptr);
-}
-
-TEST(MapsTest, verify_large_values) {
- MapInfo info(nullptr, nullptr, 0, 0, 0, 0, "");
-#if defined(__LP64__)
- VerifyLine("fabcdef012345678-f12345678abcdef8 rwxp f0b0d0f010305070 00:00 0\n", &info);
- EXPECT_EQ(0xfabcdef012345678UL, info.start);
- EXPECT_EQ(0xf12345678abcdef8UL, info.end);
- EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info.flags);
- EXPECT_EQ(0xf0b0d0f010305070UL, info.offset);
-#else
- VerifyLine("f2345678-fabcdef8 rwxp f0305070 00:00 0\n", &info);
- EXPECT_EQ(0xf2345678UL, info.start);
- EXPECT_EQ(0xfabcdef8UL, info.end);
- EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info.flags);
- EXPECT_EQ(0xf0305070UL, info.offset);
-#endif
-}
-
-TEST(MapsTest, parse_permissions) {
- BufferMaps maps(
- "1000-2000 ---s 00000000 00:00 0\n"
- "2000-3000 r--s 00000000 00:00 0\n"
- "3000-4000 -w-s 00000000 00:00 0\n"
- "4000-5000 --xp 00000000 00:00 0\n"
- "5000-6000 rwxp 00000000 00:00 0\n");
-
- ASSERT_TRUE(maps.Parse());
- ASSERT_EQ(5U, maps.Total());
-
- MapInfo* info = maps.Get(0);
- ASSERT_TRUE(info != nullptr);
- EXPECT_EQ(PROT_NONE, info->flags);
- EXPECT_EQ(0x1000U, info->start);
- EXPECT_EQ(0x2000U, info->end);
- EXPECT_EQ(0U, info->offset);
- EXPECT_EQ("", info->name);
-
- info = maps.Get(1);
- ASSERT_TRUE(info != nullptr);
- EXPECT_EQ(PROT_READ, info->flags);
- EXPECT_EQ(0x2000U, info->start);
- EXPECT_EQ(0x3000U, info->end);
- EXPECT_EQ(0U, info->offset);
- EXPECT_EQ("", info->name);
-
- info = maps.Get(2);
- ASSERT_TRUE(info != nullptr);
- EXPECT_EQ(PROT_WRITE, info->flags);
- EXPECT_EQ(0x3000U, info->start);
- EXPECT_EQ(0x4000U, info->end);
- EXPECT_EQ(0U, info->offset);
- EXPECT_EQ("", info->name);
-
- info = maps.Get(3);
- ASSERT_TRUE(info != nullptr);
- EXPECT_EQ(PROT_EXEC, info->flags);
- EXPECT_EQ(0x4000U, info->start);
- EXPECT_EQ(0x5000U, info->end);
- EXPECT_EQ(0U, info->offset);
- EXPECT_EQ("", info->name);
-
- info = maps.Get(4);
- ASSERT_TRUE(info != nullptr);
- EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info->flags);
- EXPECT_EQ(0x5000U, info->start);
- EXPECT_EQ(0x6000U, info->end);
- EXPECT_EQ(0U, info->offset);
- EXPECT_EQ("", info->name);
-
- ASSERT_TRUE(maps.Get(5) == nullptr);
-}
-
-TEST(MapsTest, parse_name) {
- BufferMaps maps(
- "7b29b000-7b29e000 rw-p 00000000 00:00 0\n"
- "7b29e000-7b29f000 rw-p 00000000 00:00 0 /system/lib/fake.so\n"
- "7b29f000-7b2a0000 rw-p 00000000 00:00 0");
-
- ASSERT_TRUE(maps.Parse());
- ASSERT_EQ(3U, maps.Total());
-
- MapInfo* info = maps.Get(0);
- ASSERT_TRUE(info != nullptr);
- EXPECT_EQ("", info->name);
- EXPECT_EQ(0x7b29b000U, info->start);
- EXPECT_EQ(0x7b29e000U, info->end);
- EXPECT_EQ(0U, info->offset);
- EXPECT_EQ(PROT_READ | PROT_WRITE, info->flags);
-
- info = maps.Get(1);
- ASSERT_TRUE(info != nullptr);
- EXPECT_EQ("/system/lib/fake.so", info->name);
- EXPECT_EQ(0x7b29e000U, info->start);
- EXPECT_EQ(0x7b29f000U, info->end);
- EXPECT_EQ(0U, info->offset);
- EXPECT_EQ(PROT_READ | PROT_WRITE, info->flags);
-
- info = maps.Get(2);
- ASSERT_TRUE(info != nullptr);
- EXPECT_EQ("", info->name);
- EXPECT_EQ(0x7b29f000U, info->start);
- EXPECT_EQ(0x7b2a0000U, info->end);
- EXPECT_EQ(0U, info->offset);
- EXPECT_EQ(PROT_READ | PROT_WRITE, info->flags);
-
- ASSERT_TRUE(maps.Get(3) == nullptr);
-}
-
-TEST(MapsTest, parse_offset) {
- BufferMaps maps(
- "a000-e000 rw-p 00000000 00:00 0 /system/lib/fake.so\n"
- "e000-f000 rw-p 00a12345 00:00 0 /system/lib/fake.so\n");
-
- ASSERT_TRUE(maps.Parse());
- ASSERT_EQ(2U, maps.Total());
-
- MapInfo* info = maps.Get(0);
- ASSERT_TRUE(info != nullptr);
- EXPECT_EQ(0U, info->offset);
- EXPECT_EQ(0xa000U, info->start);
- EXPECT_EQ(0xe000U, info->end);
- EXPECT_EQ(PROT_READ | PROT_WRITE, info->flags);
- EXPECT_EQ("/system/lib/fake.so", info->name);
-
- info = maps.Get(1);
- ASSERT_TRUE(info != nullptr);
- EXPECT_EQ(0xa12345U, info->offset);
- EXPECT_EQ(0xe000U, info->start);
- EXPECT_EQ(0xf000U, info->end);
- EXPECT_EQ(PROT_READ | PROT_WRITE, info->flags);
- EXPECT_EQ("/system/lib/fake.so", info->name);
-
- ASSERT_TRUE(maps.Get(2) == nullptr);
-}
-
-TEST(MapsTest, iterate) {
- BufferMaps maps(
- "a000-e000 rw-p 00000000 00:00 0 /system/lib/fake.so\n"
- "e000-f000 rw-p 00a12345 00:00 0 /system/lib/fake.so\n");
-
- ASSERT_TRUE(maps.Parse());
- ASSERT_EQ(2U, maps.Total());
-
- Maps::iterator it = maps.begin();
- EXPECT_EQ(0xa000U, (*it)->start);
- EXPECT_EQ(0xe000U, (*it)->end);
- ++it;
- EXPECT_EQ(0xe000U, (*it)->start);
- EXPECT_EQ(0xf000U, (*it)->end);
- ++it;
- EXPECT_EQ(maps.end(), it);
-}
-
-TEST(MapsTest, const_iterate) {
- BufferMaps maps(
- "a000-e000 rw-p 00000000 00:00 0 /system/lib/fake.so\n"
- "e000-f000 rw-p 00a12345 00:00 0 /system/lib/fake.so\n");
-
- ASSERT_TRUE(maps.Parse());
- ASSERT_EQ(2U, maps.Total());
-
- Maps::const_iterator it = maps.begin();
- EXPECT_EQ(0xa000U, (*it)->start);
- EXPECT_EQ(0xe000U, (*it)->end);
- ++it;
- EXPECT_EQ(0xe000U, (*it)->start);
- EXPECT_EQ(0xf000U, (*it)->end);
- ++it;
- EXPECT_EQ(maps.end(), it);
-}
-
-TEST(MapsTest, device) {
- BufferMaps maps(
- "a000-e000 rw-p 00000000 00:00 0 /dev/\n"
- "f000-f100 rw-p 00000000 00:00 0 /dev/does_not_exist\n"
- "f100-f200 rw-p 00000000 00:00 0 /dev/ashmem/does_not_exist\n"
- "f200-f300 rw-p 00000000 00:00 0 /devsomething/does_not_exist\n");
-
- ASSERT_TRUE(maps.Parse());
- ASSERT_EQ(4U, maps.Total());
-
- MapInfo* info = maps.Get(0);
- ASSERT_TRUE(info != nullptr);
- EXPECT_TRUE(info->flags & 0x8000);
- EXPECT_EQ("/dev/", info->name);
-
- info = maps.Get(1);
- EXPECT_TRUE(info->flags & 0x8000);
- EXPECT_EQ("/dev/does_not_exist", info->name);
-
- info = maps.Get(2);
- EXPECT_FALSE(info->flags & 0x8000);
- EXPECT_EQ("/dev/ashmem/does_not_exist", info->name);
-
- info = maps.Get(3);
- EXPECT_FALSE(info->flags & 0x8000);
- EXPECT_EQ("/devsomething/does_not_exist", info->name);
-}
-
-TEST(MapsTest, file_smoke) {
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
-
- ASSERT_TRUE(
- android::base::WriteStringToFile("7b29b000-7b29e000 r-xp a0000000 00:00 0 /fake.so\n"
- "7b2b0000-7b2e0000 r-xp b0000000 00:00 0 /fake2.so\n"
- "7b2e0000-7b2f0000 r-xp c0000000 00:00 0 /fake3.so\n",
- tf.path, 0660, getuid(), getgid()));
-
- FileMaps maps(tf.path);
-
- ASSERT_TRUE(maps.Parse());
- ASSERT_EQ(3U, maps.Total());
-
- MapInfo* info = maps.Get(0);
- ASSERT_TRUE(info != nullptr);
- EXPECT_EQ(0x7b29b000U, info->start);
- EXPECT_EQ(0x7b29e000U, info->end);
- EXPECT_EQ(0xa0000000U, info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, info->flags);
- EXPECT_EQ("/fake.so", info->name);
-
- info = maps.Get(1);
- ASSERT_TRUE(info != nullptr);
- EXPECT_EQ(0x7b2b0000U, info->start);
- EXPECT_EQ(0x7b2e0000U, info->end);
- EXPECT_EQ(0xb0000000U, info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, info->flags);
- EXPECT_EQ("/fake2.so", info->name);
-
- info = maps.Get(2);
- ASSERT_TRUE(info != nullptr);
- EXPECT_EQ(0x7b2e0000U, info->start);
- EXPECT_EQ(0x7b2f0000U, info->end);
- EXPECT_EQ(0xc0000000U, info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, info->flags);
- EXPECT_EQ("/fake3.so", info->name);
-
- ASSERT_TRUE(maps.Get(3) == nullptr);
-}
-
-TEST(MapsTest, file_no_map_name) {
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
-
- ASSERT_TRUE(
- android::base::WriteStringToFile("7b29b000-7b29e000 r-xp a0000000 00:00 0\n"
- "7b2b0000-7b2e0000 r-xp b0000000 00:00 0 /fake2.so\n"
- "7b2e0000-7b2f0000 r-xp c0000000 00:00 0 \n",
- tf.path, 0660, getuid(), getgid()));
-
- FileMaps maps(tf.path);
-
- ASSERT_TRUE(maps.Parse());
- ASSERT_EQ(3U, maps.Total());
-
- MapInfo* info = maps.Get(0);
- ASSERT_TRUE(info != nullptr);
- EXPECT_EQ(0x7b29b000U, info->start);
- EXPECT_EQ(0x7b29e000U, info->end);
- EXPECT_EQ(0xa0000000U, info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, info->flags);
- EXPECT_EQ("", info->name);
-
- info = maps.Get(1);
- ASSERT_TRUE(info != nullptr);
- EXPECT_EQ(0x7b2b0000U, info->start);
- EXPECT_EQ(0x7b2e0000U, info->end);
- EXPECT_EQ(0xb0000000U, info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, info->flags);
- EXPECT_EQ("/fake2.so", info->name);
-
- info = maps.Get(2);
- ASSERT_TRUE(info != nullptr);
- EXPECT_EQ(0x7b2e0000U, info->start);
- EXPECT_EQ(0x7b2f0000U, info->end);
- EXPECT_EQ(0xc0000000U, info->offset);
- EXPECT_EQ(PROT_READ | PROT_EXEC, info->flags);
- EXPECT_EQ("", info->name);
-
- ASSERT_TRUE(maps.Get(3) == nullptr);
-}
-
-// Verify that a file that crosses a buffer is parsed correctly.
-static std::string CreateEntry(size_t index) {
- return android::base::StringPrintf("%08zx-%08zx rwxp 0000 00:00 0\n", index * 4096,
- (index + 1) * 4096);
-}
-
-TEST(MapsTest, file_buffer_cross) {
- constexpr size_t kBufferSize = 2048;
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
-
- // Compute how many to add in the first buffer.
- size_t entry_len = CreateEntry(0).size();
- size_t index;
- std::string file_data;
- for (index = 0; index < kBufferSize / entry_len; index++) {
- file_data += CreateEntry(index);
- }
- // Add a long name to make sure that the first buffer does not contain a
- // complete line.
- // Remove the last newline.
- size_t extra = 0;
- size_t leftover = kBufferSize % entry_len;
- size_t overlap1_index = 0;
- std::string overlap1_name;
- if (leftover == 0) {
- // Exact match, add a long name to cross over the value.
- overlap1_name = "/fake/name/is/long/on/purpose";
- file_data.erase(file_data.size() - 1);
- file_data += ' ' + overlap1_name + '\n';
- extra = entry_len + overlap1_name.size() + 1;
- overlap1_index = index;
- }
-
- // Compute how many need to go in to hit the buffer boundary exactly.
- size_t bytes_left_in_buffer = kBufferSize - extra;
- size_t entries_to_add = bytes_left_in_buffer / entry_len + index;
- for (; index < entries_to_add; index++) {
- file_data += CreateEntry(index);
- }
-
- // Now figure out how many bytes to add to get exactly to the buffer boundary.
- leftover = bytes_left_in_buffer % entry_len;
- std::string overlap2_name;
- size_t overlap2_index = 0;
- if (leftover != 0) {
- file_data.erase(file_data.size() - 1);
- file_data += ' ';
- overlap2_name = std::string(leftover - 1, 'x');
- file_data += overlap2_name + '\n';
- overlap2_index = index - 1;
- }
-
- // Now add a few entries on the next page.
- for (size_t start = index; index < start + 10; index++) {
- file_data += CreateEntry(index);
- }
-
- ASSERT_TRUE(android::base::WriteStringToFile(file_data, tf.path, 0660, getuid(), getgid()));
-
- FileMaps maps(tf.path);
- ASSERT_TRUE(maps.Parse());
- EXPECT_EQ(index, maps.Total());
- // Verify all of the maps.
- for (size_t i = 0; i < index; i++) {
- MapInfo* info = maps.Get(i);
- ASSERT_TRUE(info != nullptr) << "Failed verifying index " + std::to_string(i);
- EXPECT_EQ(i * 4096, info->start) << "Failed verifying index " + std::to_string(i);
- EXPECT_EQ((i + 1) * 4096, info->end) << "Failed verifying index " + std::to_string(i);
- EXPECT_EQ(0U, info->offset) << "Failed verifying index " + std::to_string(i);
- if (overlap1_index != 0 && i == overlap1_index) {
- EXPECT_EQ(overlap1_name, info->name) << "Failed verifying overlap1 name " + std::to_string(i);
- } else if (overlap2_index != 0 && i == overlap2_index) {
- EXPECT_EQ(overlap2_name, info->name) << "Failed verifying overlap2 name " + std::to_string(i);
- } else {
- EXPECT_EQ("", info->name) << "Failed verifying index " + std::to_string(i);
- }
- }
-}
-
-TEST(MapsTest, file_should_fail) {
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
-
- ASSERT_TRUE(android::base::WriteStringToFile(
- "7ffff7dda000-7ffff7dfd7ffff7ff3000-7ffff7ff4000 ---p 0000f000 fc:02 44171565\n", tf.path,
- 0660, getuid(), getgid()));
-
- FileMaps maps(tf.path);
-
- ASSERT_FALSE(maps.Parse());
-}
-
-// Create a maps file that is extremely large.
-TEST(MapsTest, large_file) {
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
-
- std::string file_data;
- uint64_t start = 0x700000;
- for (size_t i = 0; i < 5000; i++) {
- file_data +=
- android::base::StringPrintf("%" PRIx64 "-%" PRIx64 " r-xp 1000 00:0 0 /fake%zu.so\n",
- start + i * 4096, start + (i + 1) * 4096, i);
- }
-
- ASSERT_TRUE(android::base::WriteStringToFile(file_data, tf.path, 0660, getuid(), getgid()));
-
- FileMaps maps(tf.path);
-
- ASSERT_TRUE(maps.Parse());
- ASSERT_EQ(5000U, maps.Total());
- for (size_t i = 0; i < 5000; i++) {
- MapInfo* info = maps.Get(i);
- EXPECT_EQ(start + i * 4096, info->start) << "Failed at map " + std::to_string(i);
- EXPECT_EQ(start + (i + 1) * 4096, info->end) << "Failed at map " + std::to_string(i);
- std::string name = "/fake" + std::to_string(i) + ".so";
- EXPECT_EQ(name, info->name) << "Failed at map " + std::to_string(i);
- }
-}
-
-TEST(MapsTest, find) {
- BufferMaps maps(
- "1000-2000 r--p 00000010 00:00 0 /system/lib/fake1.so\n"
- "3000-4000 -w-p 00000020 00:00 0 /system/lib/fake2.so\n"
- "6000-8000 --xp 00000030 00:00 0 /system/lib/fake3.so\n"
- "a000-b000 rw-p 00000040 00:00 0 /system/lib/fake4.so\n"
- "e000-f000 rwxp 00000050 00:00 0 /system/lib/fake5.so\n");
- ASSERT_TRUE(maps.Parse());
- ASSERT_EQ(5U, maps.Total());
-
- EXPECT_TRUE(maps.Find(0x500) == nullptr);
- EXPECT_TRUE(maps.Find(0x2000) == nullptr);
- EXPECT_TRUE(maps.Find(0x5010) == nullptr);
- EXPECT_TRUE(maps.Find(0x9a00) == nullptr);
- EXPECT_TRUE(maps.Find(0xf000) == nullptr);
- EXPECT_TRUE(maps.Find(0xf010) == nullptr);
-
- MapInfo* info = maps.Find(0x1000);
- ASSERT_TRUE(info != nullptr);
- EXPECT_EQ(0x1000U, info->start);
- EXPECT_EQ(0x2000U, info->end);
- EXPECT_EQ(0x10U, info->offset);
- EXPECT_EQ(PROT_READ, info->flags);
- EXPECT_EQ("/system/lib/fake1.so", info->name);
-
- info = maps.Find(0x3020);
- ASSERT_TRUE(info != nullptr);
- EXPECT_EQ(0x3000U, info->start);
- EXPECT_EQ(0x4000U, info->end);
- EXPECT_EQ(0x20U, info->offset);
- EXPECT_EQ(PROT_WRITE, info->flags);
- EXPECT_EQ("/system/lib/fake2.so", info->name);
-
- info = maps.Find(0x6020);
- ASSERT_TRUE(info != nullptr);
- EXPECT_EQ(0x6000U, info->start);
- EXPECT_EQ(0x8000U, info->end);
- EXPECT_EQ(0x30U, info->offset);
- EXPECT_EQ(PROT_EXEC, info->flags);
- EXPECT_EQ("/system/lib/fake3.so", info->name);
-
- info = maps.Find(0xafff);
- ASSERT_TRUE(info != nullptr);
- EXPECT_EQ(0xa000U, info->start);
- EXPECT_EQ(0xb000U, info->end);
- EXPECT_EQ(0x40U, info->offset);
- EXPECT_EQ(PROT_READ | PROT_WRITE, info->flags);
- EXPECT_EQ("/system/lib/fake4.so", info->name);
-
- info = maps.Find(0xe500);
- ASSERT_TRUE(info != nullptr);
- EXPECT_EQ(0xe000U, info->start);
- EXPECT_EQ(0xf000U, info->end);
- EXPECT_EQ(0x50U, info->offset);
- EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info->flags);
- EXPECT_EQ("/system/lib/fake5.so", info->name);
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/MemoryBufferTest.cpp b/libunwindstack/tests/MemoryBufferTest.cpp
deleted file mode 100644
index a6c12aa..0000000
--- a/libunwindstack/tests/MemoryBufferTest.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2016 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 <vector>
-
-#include <gtest/gtest.h>
-
-#include "LogFake.h"
-#include "MemoryBuffer.h"
-
-namespace unwindstack {
-
-class MemoryBufferTest : public ::testing::Test {
- protected:
- void SetUp() override {
- ResetLogs();
- memory_.reset(new MemoryBuffer);
- }
- std::unique_ptr<MemoryBuffer> memory_;
-};
-
-TEST_F(MemoryBufferTest, empty) {
- ASSERT_EQ(0U, memory_->Size());
- std::vector<uint8_t> buffer(1024);
- ASSERT_FALSE(memory_->ReadFully(0, buffer.data(), 1));
- ASSERT_EQ(nullptr, memory_->GetPtr(0));
- ASSERT_EQ(nullptr, memory_->GetPtr(1));
-}
-
-TEST_F(MemoryBufferTest, write_read) {
- memory_->Resize(256);
- ASSERT_EQ(256U, memory_->Size());
- ASSERT_TRUE(memory_->GetPtr(0) != nullptr);
- ASSERT_TRUE(memory_->GetPtr(1) != nullptr);
- ASSERT_TRUE(memory_->GetPtr(255) != nullptr);
- ASSERT_TRUE(memory_->GetPtr(256) == nullptr);
-
- uint8_t* data = memory_->GetPtr(0);
- for (size_t i = 0; i < memory_->Size(); i++) {
- data[i] = i;
- }
-
- std::vector<uint8_t> buffer(memory_->Size());
- ASSERT_TRUE(memory_->ReadFully(0, buffer.data(), buffer.size()));
- for (size_t i = 0; i < buffer.size(); i++) {
- ASSERT_EQ(i, buffer[i]) << "Failed at byte " << i;
- }
-}
-
-TEST_F(MemoryBufferTest, read_failures) {
- memory_->Resize(100);
- std::vector<uint8_t> buffer(200);
- ASSERT_FALSE(memory_->ReadFully(0, buffer.data(), 101));
- ASSERT_FALSE(memory_->ReadFully(100, buffer.data(), 1));
- ASSERT_FALSE(memory_->ReadFully(101, buffer.data(), 2));
- ASSERT_FALSE(memory_->ReadFully(99, buffer.data(), 2));
- ASSERT_TRUE(memory_->ReadFully(99, buffer.data(), 1));
-}
-
-TEST_F(MemoryBufferTest, read_failure_overflow) {
- memory_->Resize(100);
- std::vector<uint8_t> buffer(200);
-
- ASSERT_FALSE(memory_->ReadFully(UINT64_MAX - 100, buffer.data(), 200));
-}
-
-TEST_F(MemoryBufferTest, Read) {
- memory_->Resize(256);
- ASSERT_EQ(256U, memory_->Size());
- ASSERT_TRUE(memory_->GetPtr(0) != nullptr);
- ASSERT_TRUE(memory_->GetPtr(1) != nullptr);
- ASSERT_TRUE(memory_->GetPtr(255) != nullptr);
- ASSERT_TRUE(memory_->GetPtr(256) == nullptr);
-
- uint8_t* data = memory_->GetPtr(0);
- for (size_t i = 0; i < memory_->Size(); i++) {
- data[i] = i;
- }
-
- std::vector<uint8_t> buffer(memory_->Size());
- ASSERT_EQ(128U, memory_->Read(128, buffer.data(), buffer.size()));
- for (size_t i = 0; i < 128; i++) {
- ASSERT_EQ(128 + i, buffer[i]) << "Failed at byte " << i;
- }
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/MemoryCacheTest.cpp b/libunwindstack/tests/MemoryCacheTest.cpp
deleted file mode 100644
index 3bd3e4d..0000000
--- a/libunwindstack/tests/MemoryCacheTest.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2018 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 <stdint.h>
-
-#include <vector>
-
-#include <gtest/gtest.h>
-
-#include "MemoryCache.h"
-#include "MemoryFake.h"
-
-namespace unwindstack {
-
-class MemoryCacheTest : public ::testing::Test {
- protected:
- void SetUp() override {
- memory_ = new MemoryFake;
- memory_cache_.reset(new MemoryCache(memory_));
-
- memory_->SetMemoryBlock(0x8000, 4096, 0xab);
- memory_->SetMemoryBlock(0x9000, 4096, 0xde);
- memory_->SetMemoryBlock(0xa000, 3000, 0x50);
- }
-
- MemoryFake* memory_;
- std::unique_ptr<MemoryCache> memory_cache_;
-
- constexpr static size_t kMaxCachedSize = 64;
-};
-
-TEST_F(MemoryCacheTest, cached_read) {
- for (size_t i = 1; i <= kMaxCachedSize; i++) {
- std::vector<uint8_t> buffer(i);
- ASSERT_TRUE(memory_cache_->ReadFully(0x8000 + i, buffer.data(), i))
- << "Read failed at size " << i;
- ASSERT_EQ(std::vector<uint8_t>(i, 0xab), buffer) << "Failed at size " << i;
- }
-
- // Verify the cached data is used.
- memory_->SetMemoryBlock(0x8000, 4096, 0xff);
- for (size_t i = 1; i <= kMaxCachedSize; i++) {
- std::vector<uint8_t> buffer(i);
- ASSERT_TRUE(memory_cache_->ReadFully(0x8000 + i, buffer.data(), i))
- << "Read failed at size " << i;
- ASSERT_EQ(std::vector<uint8_t>(i, 0xab), buffer) << "Failed at size " << i;
- }
-}
-
-TEST_F(MemoryCacheTest, no_cached_read_after_clear) {
- for (size_t i = 1; i <= kMaxCachedSize; i++) {
- std::vector<uint8_t> buffer(i);
- ASSERT_TRUE(memory_cache_->ReadFully(0x8000 + i, buffer.data(), i))
- << "Read failed at size " << i;
- ASSERT_EQ(std::vector<uint8_t>(i, 0xab), buffer) << "Failed at size " << i;
- }
-
- // Verify the cached data is not used after a reset.
- memory_cache_->Clear();
- memory_->SetMemoryBlock(0x8000, 4096, 0xff);
- for (size_t i = 1; i <= kMaxCachedSize; i++) {
- std::vector<uint8_t> buffer(i);
- ASSERT_TRUE(memory_cache_->ReadFully(0x8000 + i, buffer.data(), i))
- << "Read failed at size " << i;
- ASSERT_EQ(std::vector<uint8_t>(i, 0xff), buffer) << "Failed at size " << i;
- }
-}
-
-TEST_F(MemoryCacheTest, cached_read_across_caches) {
- std::vector<uint8_t> expect(16, 0xab);
- expect.resize(32, 0xde);
-
- std::vector<uint8_t> buffer(32);
- ASSERT_TRUE(memory_cache_->ReadFully(0x8ff0, buffer.data(), 32));
- ASSERT_EQ(expect, buffer);
-
- // Verify the cached data is used.
- memory_->SetMemoryBlock(0x8000, 4096, 0xff);
- memory_->SetMemoryBlock(0x9000, 4096, 0xff);
- ASSERT_TRUE(memory_cache_->ReadFully(0x8ff0, buffer.data(), 32));
- ASSERT_EQ(expect, buffer);
-}
-
-TEST_F(MemoryCacheTest, no_cache_read) {
- for (size_t i = kMaxCachedSize + 1; i < 2 * kMaxCachedSize; i++) {
- std::vector<uint8_t> buffer(i);
- ASSERT_TRUE(memory_cache_->ReadFully(0x8000 + i, buffer.data(), i))
- << "Read failed at size " << i;
- ASSERT_EQ(std::vector<uint8_t>(i, 0xab), buffer) << "Failed at size " << i;
- }
-
- // Verify the cached data is not used.
- memory_->SetMemoryBlock(0x8000, 4096, 0xff);
- for (size_t i = kMaxCachedSize + 1; i < 2 * kMaxCachedSize; i++) {
- std::vector<uint8_t> buffer(i);
- ASSERT_TRUE(memory_cache_->ReadFully(0x8000 + i, buffer.data(), i))
- << "Read failed at size " << i;
- ASSERT_EQ(std::vector<uint8_t>(i, 0xff), buffer) << "Failed at size " << i;
- }
-}
-
-TEST_F(MemoryCacheTest, read_for_cache_fail) {
- std::vector<uint8_t> buffer(kMaxCachedSize);
- ASSERT_TRUE(memory_cache_->ReadFully(0xa010, buffer.data(), kMaxCachedSize));
- ASSERT_EQ(std::vector<uint8_t>(kMaxCachedSize, 0x50), buffer);
-
- // Verify the cached data is not used.
- memory_->SetMemoryBlock(0xa000, 3000, 0xff);
- ASSERT_TRUE(memory_cache_->ReadFully(0xa010, buffer.data(), kMaxCachedSize));
- ASSERT_EQ(std::vector<uint8_t>(kMaxCachedSize, 0xff), buffer);
-}
-
-TEST_F(MemoryCacheTest, read_for_cache_fail_cross) {
- std::vector<uint8_t> expect(16, 0xde);
- expect.resize(32, 0x50);
-
- std::vector<uint8_t> buffer(32);
- ASSERT_TRUE(memory_cache_->ReadFully(0x9ff0, buffer.data(), 32));
- ASSERT_EQ(expect, buffer);
-
- // Verify the cached data is not used for the second half but for the first.
- memory_->SetMemoryBlock(0xa000, 3000, 0xff);
- ASSERT_TRUE(memory_cache_->ReadFully(0x9ff0, buffer.data(), 32));
- expect.resize(16);
- expect.resize(32, 0xff);
- ASSERT_EQ(expect, buffer);
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/MemoryFake.cpp b/libunwindstack/tests/MemoryFake.cpp
deleted file mode 100644
index 5695dfc..0000000
--- a/libunwindstack/tests/MemoryFake.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2016 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 <inttypes.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "MemoryFake.h"
-
-namespace unwindstack {
-
-void MemoryFake::SetMemoryBlock(uint64_t addr, size_t length, uint8_t value) {
- for (size_t i = 0; i < length; i++, addr++) {
- auto entry = data_.find(addr);
- if (entry != data_.end()) {
- entry->second = value;
- } else {
- data_.insert({addr, value});
- }
- }
-}
-
-void MemoryFake::SetMemory(uint64_t addr, const void* memory, size_t length) {
- const uint8_t* src = reinterpret_cast<const uint8_t*>(memory);
- for (size_t i = 0; i < length; i++, addr++) {
- auto value = data_.find(addr);
- if (value != data_.end()) {
- value->second = src[i];
- } else {
- data_.insert({ addr, src[i] });
- }
- }
-}
-
-size_t MemoryFake::Read(uint64_t addr, void* memory, size_t size) {
- uint8_t* dst = reinterpret_cast<uint8_t*>(memory);
- for (size_t i = 0; i < size; i++, addr++) {
- auto value = data_.find(addr);
- if (value == data_.end()) {
- return i;
- }
- dst[i] = value->second;
- }
- return size;
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/MemoryFake.h b/libunwindstack/tests/MemoryFake.h
deleted file mode 100644
index 20610a5..0000000
--- a/libunwindstack/tests/MemoryFake.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_TESTS_MEMORY_FAKE_H
-#define _LIBUNWINDSTACK_TESTS_MEMORY_FAKE_H
-
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-#include <unordered_map>
-
-#include <unwindstack/Memory.h>
-
-namespace unwindstack {
-
-class MemoryFake : public Memory {
- public:
- MemoryFake() = default;
- virtual ~MemoryFake() = default;
-
- size_t Read(uint64_t addr, void* buffer, size_t size) override;
-
- void SetMemory(uint64_t addr, const void* memory, size_t length);
-
- void SetMemoryBlock(uint64_t addr, size_t length, uint8_t value);
-
- void SetData8(uint64_t addr, uint8_t value) {
- SetMemory(addr, &value, sizeof(value));
- }
-
- void SetData16(uint64_t addr, uint16_t value) {
- SetMemory(addr, &value, sizeof(value));
- }
-
- void SetData32(uint64_t addr, uint32_t value) {
- SetMemory(addr, &value, sizeof(value));
- }
-
- void SetData64(uint64_t addr, uint64_t value) {
- SetMemory(addr, &value, sizeof(value));
- }
-
- void SetMemory(uint64_t addr, std::vector<uint8_t> values) {
- SetMemory(addr, values.data(), values.size());
- }
-
- void SetMemory(uint64_t addr, std::string string) {
- SetMemory(addr, string.c_str(), string.size() + 1);
- }
-
- void Clear() { data_.clear(); }
-
- private:
- std::unordered_map<uint64_t, uint8_t> data_;
-};
-
-class MemoryFakeAlwaysReadZero : public Memory {
- public:
- MemoryFakeAlwaysReadZero() = default;
- virtual ~MemoryFakeAlwaysReadZero() = default;
-
- size_t Read(uint64_t, void* buffer, size_t size) override {
- memset(buffer, 0, size);
- return size;
- }
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_TESTS_MEMORY_FAKE_H
diff --git a/libunwindstack/tests/MemoryFileTest.cpp b/libunwindstack/tests/MemoryFileTest.cpp
deleted file mode 100644
index 4124a49..0000000
--- a/libunwindstack/tests/MemoryFileTest.cpp
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright (C) 2016 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 <string>
-#include <vector>
-
-#include <android-base/test_utils.h>
-#include <android-base/file.h>
-#include <gtest/gtest.h>
-
-#include "MemoryFileAtOffset.h"
-
-namespace unwindstack {
-
-class MemoryFileTest : public ::testing::Test {
- protected:
- void SetUp() override {
- tf_ = new TemporaryFile;
- }
-
- void TearDown() override {
- delete tf_;
- }
-
- void WriteTestData() {
- ASSERT_TRUE(android::base::WriteStringToFd("0123456789abcdefghijklmnopqrstuvxyz", tf_->fd));
- }
-
- MemoryFileAtOffset memory_;
-
- TemporaryFile* tf_ = nullptr;
-};
-
-TEST_F(MemoryFileTest, init_offset_0) {
- WriteTestData();
-
- ASSERT_TRUE(memory_.Init(tf_->path, 0));
- std::vector<char> buffer(11);
- ASSERT_TRUE(memory_.ReadFully(0, buffer.data(), 10));
- buffer[10] = '\0';
- ASSERT_STREQ("0123456789", buffer.data());
-}
-
-TEST_F(MemoryFileTest, init_offset_non_zero) {
- WriteTestData();
-
- ASSERT_TRUE(memory_.Init(tf_->path, 10));
- std::vector<char> buffer(11);
- ASSERT_TRUE(memory_.ReadFully(0, buffer.data(), 10));
- buffer[10] = '\0';
- ASSERT_STREQ("abcdefghij", buffer.data());
-}
-
-TEST_F(MemoryFileTest, init_offset_non_zero_larger_than_pagesize) {
- size_t pagesize = getpagesize();
- std::string large_string;
- for (size_t i = 0; i < pagesize; i++) {
- large_string += '1';
- }
- large_string += "012345678901234abcdefgh";
- ASSERT_TRUE(android::base::WriteStringToFd(large_string, tf_->fd));
-
- ASSERT_TRUE(memory_.Init(tf_->path, pagesize + 15));
- std::vector<char> buffer(9);
- ASSERT_TRUE(memory_.ReadFully(0, buffer.data(), 8));
- buffer[8] = '\0';
- ASSERT_STREQ("abcdefgh", buffer.data());
-}
-
-TEST_F(MemoryFileTest, init_offset_pagesize_aligned) {
- size_t pagesize = getpagesize();
- std::string data;
- for (size_t i = 0; i < 2 * pagesize; i++) {
- data += static_cast<char>((i / pagesize) + '0');
- data += static_cast<char>((i % 10) + '0');
- }
- ASSERT_TRUE(android::base::WriteStringToFd(data, tf_->fd));
-
- ASSERT_TRUE(memory_.Init(tf_->path, 2 * pagesize));
- std::vector<char> buffer(11);
- ASSERT_TRUE(memory_.ReadFully(0, buffer.data(), 10));
- buffer[10] = '\0';
- std::string expected_str;
- for (size_t i = 0; i < 5; i++) {
- expected_str += '1';
- expected_str += static_cast<char>(((i + pagesize) % 10) + '0');
- }
- ASSERT_STREQ(expected_str.c_str(), buffer.data());
-}
-
-TEST_F(MemoryFileTest, init_offset_pagesize_aligned_plus_extra) {
- size_t pagesize = getpagesize();
- std::string data;
- for (size_t i = 0; i < 2 * pagesize; i++) {
- data += static_cast<char>((i / pagesize) + '0');
- data += static_cast<char>((i % 10) + '0');
- }
- ASSERT_TRUE(android::base::WriteStringToFd(data, tf_->fd));
-
- ASSERT_TRUE(memory_.Init(tf_->path, 2 * pagesize + 10));
- std::vector<char> buffer(11);
- ASSERT_TRUE(memory_.ReadFully(0, buffer.data(), 10));
- buffer[10] = '\0';
- std::string expected_str;
- for (size_t i = 0; i < 5; i++) {
- expected_str += '1';
- expected_str += static_cast<char>(((i + pagesize + 5) % 10) + '0');
- }
- ASSERT_STREQ(expected_str.c_str(), buffer.data());
-}
-
-TEST_F(MemoryFileTest, init_offset_greater_than_filesize) {
- size_t pagesize = getpagesize();
- std::string data;
- uint64_t file_size = 2 * pagesize + pagesize / 2;
- for (size_t i = 0; i < file_size; i++) {
- data += static_cast<char>((i / pagesize) + '0');
- }
- ASSERT_TRUE(android::base::WriteStringToFd(data, tf_->fd));
-
- // Check offset > file size fails and aligned_offset > file size.
- ASSERT_FALSE(memory_.Init(tf_->path, file_size + 2 * pagesize));
- // Check offset == filesize fails.
- ASSERT_FALSE(memory_.Init(tf_->path, file_size));
- // Check aligned_offset < filesize, but offset > filesize fails.
- ASSERT_FALSE(memory_.Init(tf_->path, 2 * pagesize + pagesize / 2 + pagesize / 4));
-}
-
-TEST_F(MemoryFileTest, read_error) {
- std::string data;
- for (size_t i = 0; i < 5000; i++) {
- data += static_cast<char>((i % 10) + '0');
- }
- ASSERT_TRUE(android::base::WriteStringToFd(data, tf_->fd));
-
- std::vector<char> buffer(100);
-
- // Read before init.
- ASSERT_FALSE(memory_.ReadFully(0, buffer.data(), 10));
-
- ASSERT_TRUE(memory_.Init(tf_->path, 0));
-
- ASSERT_FALSE(memory_.ReadFully(10000, buffer.data(), 10));
- ASSERT_FALSE(memory_.ReadFully(5000, buffer.data(), 10));
- ASSERT_FALSE(memory_.ReadFully(4990, buffer.data(), 11));
- ASSERT_TRUE(memory_.ReadFully(4990, buffer.data(), 10));
- ASSERT_FALSE(memory_.ReadFully(4999, buffer.data(), 2));
- ASSERT_TRUE(memory_.ReadFully(4999, buffer.data(), 1));
-
- // Check that overflow fails properly.
- ASSERT_FALSE(memory_.ReadFully(UINT64_MAX - 100, buffer.data(), 200));
-}
-
-TEST_F(MemoryFileTest, read_past_file_within_mapping) {
- size_t pagesize = getpagesize();
-
- ASSERT_TRUE(pagesize > 100);
- std::vector<uint8_t> buffer(pagesize - 100);
- for (size_t i = 0; i < pagesize - 100; i++) {
- buffer[i] = static_cast<uint8_t>((i % 0x5e) + 0x20);
- }
- ASSERT_TRUE(android::base::WriteFully(tf_->fd, buffer.data(), buffer.size()));
-
- ASSERT_TRUE(memory_.Init(tf_->path, 0));
-
- for (size_t i = 0; i < 100; i++) {
- uint8_t value;
- ASSERT_FALSE(memory_.ReadFully(buffer.size() + i, &value, 1))
- << "Should have failed at value " << i;
- }
-}
-
-TEST_F(MemoryFileTest, map_partial_offset_aligned) {
- size_t pagesize = getpagesize();
- std::vector<uint8_t> buffer(pagesize * 10);
- for (size_t i = 0; i < pagesize * 10; i++) {
- buffer[i] = i / pagesize + 1;
- }
- ASSERT_TRUE(android::base::WriteFully(tf_->fd, buffer.data(), buffer.size()));
-
- // Map in only two pages of the data, and after the first page.
- ASSERT_TRUE(memory_.Init(tf_->path, pagesize, pagesize * 2));
-
- std::vector<uint8_t> read_buffer(pagesize * 2);
- // Make sure that reading after mapped data is a failure.
- ASSERT_FALSE(memory_.ReadFully(pagesize * 2, read_buffer.data(), 1));
- ASSERT_TRUE(memory_.ReadFully(0, read_buffer.data(), pagesize * 2));
- for (size_t i = 0; i < pagesize; i++) {
- ASSERT_EQ(2, read_buffer[i]) << "Failed at byte " << i;
- }
- for (size_t i = pagesize; i < pagesize * 2; i++) {
- ASSERT_EQ(3, read_buffer[i]) << "Failed at byte " << i;
- }
-}
-
-TEST_F(MemoryFileTest, map_partial_offset_unaligned) {
- size_t pagesize = getpagesize();
- ASSERT_TRUE(pagesize > 0x100);
- std::vector<uint8_t> buffer(pagesize * 10);
- for (size_t i = 0; i < buffer.size(); i++) {
- buffer[i] = i / pagesize + 1;
- }
- ASSERT_TRUE(android::base::WriteFully(tf_->fd, buffer.data(), buffer.size()));
-
- // Map in only two pages of the data, and after the first page.
- ASSERT_TRUE(memory_.Init(tf_->path, pagesize + 0x100, pagesize * 2));
-
- std::vector<uint8_t> read_buffer(pagesize * 2);
- // Make sure that reading after mapped data is a failure.
- ASSERT_FALSE(memory_.ReadFully(pagesize * 2, read_buffer.data(), 1));
- ASSERT_TRUE(memory_.ReadFully(0, read_buffer.data(), pagesize * 2));
- for (size_t i = 0; i < pagesize - 0x100; i++) {
- ASSERT_EQ(2, read_buffer[i]) << "Failed at byte " << i;
- }
- for (size_t i = pagesize - 0x100; i < 2 * pagesize - 0x100; i++) {
- ASSERT_EQ(3, read_buffer[i]) << "Failed at byte " << i;
- }
- for (size_t i = 2 * pagesize - 0x100; i < pagesize * 2; i++) {
- ASSERT_EQ(4, read_buffer[i]) << "Failed at byte " << i;
- }
-}
-
-TEST_F(MemoryFileTest, map_overflow) {
- size_t pagesize = getpagesize();
- ASSERT_TRUE(pagesize > 0x100);
- std::vector<uint8_t> buffer(pagesize * 10);
- for (size_t i = 0; i < buffer.size(); i++) {
- buffer[i] = i / pagesize + 1;
- }
- ASSERT_TRUE(android::base::WriteFully(tf_->fd, buffer.data(), buffer.size()));
-
- // Map in only two pages of the data, and after the first page.
- ASSERT_TRUE(memory_.Init(tf_->path, pagesize + 0x100, UINT64_MAX));
-
- std::vector<uint8_t> read_buffer(pagesize * 10);
- ASSERT_FALSE(memory_.ReadFully(pagesize * 9 - 0x100 + 1, read_buffer.data(), 1));
- ASSERT_TRUE(memory_.ReadFully(0, read_buffer.data(), pagesize * 9 - 0x100));
-}
-
-TEST_F(MemoryFileTest, init_reinit) {
- size_t pagesize = getpagesize();
- std::vector<uint8_t> buffer(pagesize * 2);
- for (size_t i = 0; i < buffer.size(); i++) {
- buffer[i] = i / pagesize + 1;
- }
- ASSERT_TRUE(android::base::WriteFully(tf_->fd, buffer.data(), buffer.size()));
-
- ASSERT_TRUE(memory_.Init(tf_->path, 0));
- std::vector<uint8_t> read_buffer(buffer.size());
- ASSERT_TRUE(memory_.ReadFully(0, read_buffer.data(), pagesize));
- for (size_t i = 0; i < pagesize; i++) {
- ASSERT_EQ(1, read_buffer[i]) << "Failed at byte " << i;
- }
-
- // Now reinit.
- ASSERT_TRUE(memory_.Init(tf_->path, pagesize));
- ASSERT_TRUE(memory_.ReadFully(0, read_buffer.data(), pagesize));
- for (size_t i = 0; i < pagesize; i++) {
- ASSERT_EQ(2, read_buffer[i]) << "Failed at byte " << i;
- }
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/MemoryLocalTest.cpp b/libunwindstack/tests/MemoryLocalTest.cpp
deleted file mode 100644
index c9e5dc0..0000000
--- a/libunwindstack/tests/MemoryLocalTest.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2017 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 <stdint.h>
-#include <string.h>
-#include <sys/mman.h>
-
-#include <vector>
-
-#include <gtest/gtest.h>
-
-#include "MemoryLocal.h"
-
-namespace unwindstack {
-
-TEST(MemoryLocalTest, read) {
- std::vector<uint8_t> src(1024);
- memset(src.data(), 0x4c, 1024);
-
- MemoryLocal local;
-
- std::vector<uint8_t> dst(1024);
- ASSERT_TRUE(local.ReadFully(reinterpret_cast<uint64_t>(src.data()), dst.data(), 1024));
- ASSERT_EQ(0, memcmp(src.data(), dst.data(), 1024));
- for (size_t i = 0; i < 1024; i++) {
- ASSERT_EQ(0x4cU, dst[i]);
- }
-
- memset(src.data(), 0x23, 512);
- ASSERT_TRUE(local.ReadFully(reinterpret_cast<uint64_t>(src.data()), dst.data(), 1024));
- ASSERT_EQ(0, memcmp(src.data(), dst.data(), 1024));
- for (size_t i = 0; i < 512; i++) {
- ASSERT_EQ(0x23U, dst[i]);
- }
- for (size_t i = 512; i < 1024; i++) {
- ASSERT_EQ(0x4cU, dst[i]);
- }
-}
-
-TEST(MemoryLocalTest, read_illegal) {
- MemoryLocal local;
-
- std::vector<uint8_t> dst(100);
- ASSERT_FALSE(local.ReadFully(0, dst.data(), 1));
- ASSERT_FALSE(local.ReadFully(0, dst.data(), 100));
-}
-
-TEST(MemoryLocalTest, read_overflow) {
- MemoryLocal local;
-
- // On 32 bit this test doesn't necessarily cause an overflow. The 64 bit
- // version will always go through the overflow check.
- std::vector<uint8_t> dst(100);
- uint64_t value;
- ASSERT_FALSE(local.ReadFully(reinterpret_cast<uint64_t>(&value), dst.data(), SIZE_MAX));
-}
-
-TEST(MemoryLocalTest, Read) {
- char* mapping = static_cast<char*>(
- mmap(nullptr, 2 * getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
-
- ASSERT_NE(MAP_FAILED, mapping);
-
- mprotect(mapping + getpagesize(), getpagesize(), PROT_NONE);
- memset(mapping + getpagesize() - 1024, 0x4c, 1024);
-
- MemoryLocal local;
-
- std::vector<uint8_t> dst(4096);
- ASSERT_EQ(1024U, local.Read(reinterpret_cast<uint64_t>(mapping + getpagesize() - 1024),
- dst.data(), 4096));
- for (size_t i = 0; i < 1024; i++) {
- ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
- }
-
- ASSERT_EQ(0, munmap(mapping, 2 * getpagesize()));
-}
-
-TEST(MemoryLocalTest, read_hole) {
- void* mapping =
- mmap(nullptr, 3 * 4096, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
- ASSERT_NE(MAP_FAILED, mapping);
- memset(mapping, 0xFF, 3 * 4096);
- mprotect(static_cast<char*>(mapping) + 4096, 4096, PROT_NONE);
-
- MemoryLocal local;
- std::vector<uint8_t> dst(4096 * 3, 0xCC);
- ASSERT_EQ(4096U, local.Read(reinterpret_cast<uintptr_t>(mapping), dst.data(), 4096 * 3));
- for (size_t i = 0; i < 4096; ++i) {
- ASSERT_EQ(0xFF, dst[i]);
- }
- for (size_t i = 4096; i < 4096 * 3; ++i) {
- ASSERT_EQ(0xCC, dst[i]);
- }
- ASSERT_EQ(0, munmap(mapping, 3 * 4096));
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/MemoryMteTest.cpp b/libunwindstack/tests/MemoryMteTest.cpp
deleted file mode 100644
index 3ae322e..0000000
--- a/libunwindstack/tests/MemoryMteTest.cpp
+++ /dev/null
@@ -1,99 +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.
- */
-
-#if defined(ANDROID_EXPERIMENTAL_MTE)
-
-#include <sys/mman.h>
-#include <sys/types.h>
-
-#include <gtest/gtest.h>
-
-#include <bionic/mte.h>
-
-#include "MemoryLocal.h"
-#include "MemoryRemote.h"
-#include "TestUtils.h"
-
-namespace unwindstack {
-
-static uintptr_t CreateTagMapping() {
- uintptr_t mapping =
- reinterpret_cast<uintptr_t>(mmap(nullptr, getpagesize(), PROT_READ | PROT_WRITE | PROT_MTE,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
- if (reinterpret_cast<void*>(mapping) == MAP_FAILED) {
- return 0;
- }
-#if defined(__aarch64__)
- __asm__ __volatile__(".arch_extension mte; stg %0, [%0]"
- :
- : "r"(mapping + (1ULL << 56))
- : "memory");
-#endif
- return mapping;
-}
-
-TEST(MemoryMteTest, remote_read_tag) {
-#if !defined(__aarch64__)
- GTEST_SKIP() << "Requires aarch64";
-#else
- if (!mte_supported()) {
- GTEST_SKIP() << "Requires MTE";
- }
-#endif
-
- uintptr_t mapping = CreateTagMapping();
- ASSERT_NE(0U, mapping);
-
- pid_t pid;
- if ((pid = fork()) == 0) {
- while (true)
- ;
- exit(1);
- }
- ASSERT_LT(0, pid);
- TestScopedPidReaper reap(pid);
-
- ASSERT_TRUE(TestAttach(pid));
-
- MemoryRemote remote(pid);
-
- EXPECT_EQ(1, remote.ReadTag(mapping));
- EXPECT_EQ(0, remote.ReadTag(mapping + 16));
-
- ASSERT_TRUE(TestDetach(pid));
-}
-
-TEST(MemoryMteTest, local_read_tag) {
-#if !defined(__aarch64__)
- GTEST_SKIP() << "Requires aarch64";
-#else
- if (!mte_supported()) {
- GTEST_SKIP() << "Requires MTE";
- }
-#endif
-
- uintptr_t mapping = CreateTagMapping();
- ASSERT_NE(0U, mapping);
-
- MemoryLocal local;
-
- EXPECT_EQ(1, local.ReadTag(mapping));
- EXPECT_EQ(0, local.ReadTag(mapping + 16));
-}
-
-} // namespace unwindstack
-
-#endif
diff --git a/libunwindstack/tests/MemoryOfflineBufferTest.cpp b/libunwindstack/tests/MemoryOfflineBufferTest.cpp
deleted file mode 100644
index 9531708..0000000
--- a/libunwindstack/tests/MemoryOfflineBufferTest.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2018 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 <vector>
-
-#include <gtest/gtest.h>
-
-#include "LogFake.h"
-#include "MemoryOfflineBuffer.h"
-
-namespace unwindstack {
-
-class MemoryOfflineBufferTest : public ::testing::Test {
- protected:
- void SetUp() override {
- ResetLogs();
- memory_.reset(new MemoryOfflineBuffer(buffer_.data(), kStart, kEnd));
- }
-
- static void SetUpTestSuite() {
- buffer_.resize(kLength);
- for (size_t i = 0; i < kLength; i++) {
- buffer_[i] = i % 189;
- }
- }
-
- std::unique_ptr<MemoryOfflineBuffer> memory_;
-
- static constexpr size_t kLength = 0x2000;
- static constexpr uint64_t kStart = 0x1000;
- static constexpr uint64_t kEnd = kStart + kLength;
- static std::vector<uint8_t> buffer_;
-};
-
-std::vector<uint8_t> MemoryOfflineBufferTest::buffer_;
-
-static void VerifyBuffer(uint8_t* buffer, size_t start_value, size_t length) {
- for (size_t i = 0; i < length; i++) {
- ASSERT_EQ((start_value + i) % 189, buffer[i]) << "Failed at byte " << i;
- }
-}
-
-TEST_F(MemoryOfflineBufferTest, read_out_of_bounds) {
- std::vector<uint8_t> buffer(1024);
- ASSERT_FALSE(memory_->ReadFully(0, buffer.data(), 1));
- ASSERT_FALSE(memory_->ReadFully(0xfff, buffer.data(), 1));
- ASSERT_FALSE(memory_->ReadFully(0xfff, buffer.data(), 2));
- ASSERT_FALSE(memory_->ReadFully(0x3000, buffer.data(), 1));
- ASSERT_FALSE(memory_->ReadFully(0x3001, buffer.data(), 1));
-}
-
-TEST_F(MemoryOfflineBufferTest, read) {
- std::vector<uint8_t> buffer(1024);
- ASSERT_TRUE(memory_->ReadFully(kStart, buffer.data(), 10));
- ASSERT_NO_FATAL_FAILURE(VerifyBuffer(buffer.data(), 0, 10));
-
- ASSERT_TRUE(memory_->ReadFully(kStart + 555, buffer.data(), 40));
- ASSERT_NO_FATAL_FAILURE(VerifyBuffer(buffer.data(), 555, 40));
-
- ASSERT_TRUE(memory_->ReadFully(kStart + kLength - 105, buffer.data(), 105));
- ASSERT_NO_FATAL_FAILURE(VerifyBuffer(buffer.data(), kLength - 105, 105));
-}
-
-TEST_F(MemoryOfflineBufferTest, read_past_end) {
- std::vector<uint8_t> buffer(1024);
- ASSERT_EQ(100U, memory_->Read(kStart + kLength - 100, buffer.data(), buffer.size()));
- VerifyBuffer(buffer.data(), kLength - 100, 100);
-}
-
-TEST_F(MemoryOfflineBufferTest, read_after_reset) {
- std::vector<uint8_t> buffer(1024);
- ASSERT_TRUE(memory_->ReadFully(kStart, buffer.data(), 100));
- ASSERT_NO_FATAL_FAILURE(VerifyBuffer(buffer.data(), 0, 100));
-
- memory_->Reset(&buffer_[10], 0x12000, 0x13000);
- ASSERT_TRUE(memory_->ReadFully(0x12000, buffer.data(), 100));
- ASSERT_NO_FATAL_FAILURE(VerifyBuffer(buffer.data(), 10, 100));
-
- ASSERT_EQ(50U, memory_->Read(0x13000 - 50, buffer.data(), buffer.size()));
- ASSERT_NO_FATAL_FAILURE(VerifyBuffer(buffer.data(), 0x1000 - 50 + 10, 50));
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/MemoryOfflineTest.cpp b/libunwindstack/tests/MemoryOfflineTest.cpp
deleted file mode 100644
index d0c441b..0000000
--- a/libunwindstack/tests/MemoryOfflineTest.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2017 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 <vector>
-
-#include <gtest/gtest.h>
-
-#include <android-base/file.h>
-
-#include "MemoryOffline.h"
-
-namespace unwindstack {
-
-class MemoryOfflineTest : public ::testing::Test {
- protected:
- void SetUp() override {
- for (size_t i = 0; i < 1024; ++i) {
- data.push_back(i & 0xff);
- }
-
- ASSERT_TRUE(android::base::WriteFully(temp_file.fd, &offset, sizeof(offset)));
- ASSERT_TRUE(android::base::WriteFully(temp_file.fd, data.data(), data.size()));
-
- memory = std::make_unique<MemoryOffline>();
- ASSERT_TRUE(memory != nullptr);
-
- ASSERT_TRUE(memory->Init(temp_file.path, 0));
- }
-
- TemporaryFile temp_file;
- uint64_t offset = 4096;
- std::vector<char> data;
- std::unique_ptr<MemoryOffline> memory;
-};
-
-TEST_F(MemoryOfflineTest, read_boundaries) {
- char buf = '\0';
- ASSERT_EQ(0U, memory->Read(offset - 1, &buf, 1));
- ASSERT_EQ(0U, memory->Read(offset + data.size(), &buf, 1));
- ASSERT_EQ(1U, memory->Read(offset, &buf, 1));
- ASSERT_EQ(buf, data.front());
- ASSERT_EQ(1U, memory->Read(offset + data.size() - 1, &buf, 1));
- ASSERT_EQ(buf, data.back());
-}
-
-TEST_F(MemoryOfflineTest, read_values) {
- std::vector<char> buf;
- buf.resize(2 * data.size());
- ASSERT_EQ(data.size(), memory->Read(offset, buf.data(), buf.size()));
- buf.resize(data.size());
- ASSERT_EQ(buf, data);
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/MemoryRangeTest.cpp b/libunwindstack/tests/MemoryRangeTest.cpp
deleted file mode 100644
index 2d4f141..0000000
--- a/libunwindstack/tests/MemoryRangeTest.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2017 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 <stdint.h>
-
-#include <memory>
-#include <vector>
-
-#include <gtest/gtest.h>
-
-#include "MemoryFake.h"
-#include "MemoryRange.h"
-
-namespace unwindstack {
-
-class MemoryRangeTest : public ::testing::Test {
- protected:
- void SetUp() override {
- process_memory_.reset();
- memory_fake_ = new MemoryFake;
- process_memory_.reset(memory_fake_);
- }
-
- std::shared_ptr<Memory> process_memory_;
- MemoryFake* memory_fake_ = nullptr;
-};
-
-TEST_F(MemoryRangeTest, read_fully) {
- memory_fake_->SetMemoryBlock(9000, 2048, 0x4c);
-
- MemoryRange range(process_memory_, 9001, 1024, 0);
-
- std::vector<uint8_t> dst(1024);
- ASSERT_TRUE(range.ReadFully(0, dst.data(), dst.size()));
- for (size_t i = 0; i < dst.size(); i++) {
- ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
- }
-}
-
-TEST_F(MemoryRangeTest, read_fully_near_limit) {
- memory_fake_->SetMemoryBlock(0, 8192, 0x4c);
-
- MemoryRange range(process_memory_, 1000, 1024, 0);
-
- std::vector<uint8_t> dst(1024);
- ASSERT_TRUE(range.ReadFully(1020, dst.data(), 4));
- for (size_t i = 0; i < 4; i++) {
- ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
- }
-
- // Verify that reads outside of the range will fail.
- ASSERT_FALSE(range.ReadFully(1020, dst.data(), 5));
- ASSERT_FALSE(range.ReadFully(1024, dst.data(), 1));
- ASSERT_FALSE(range.ReadFully(1024, dst.data(), 1024));
-
- // Verify that reading up to the end works.
- ASSERT_TRUE(range.ReadFully(1020, dst.data(), 4));
-}
-
-TEST_F(MemoryRangeTest, read_fully_overflow) {
- std::vector<uint8_t> buffer(100);
-
- std::shared_ptr<Memory> process_memory(new MemoryFakeAlwaysReadZero);
- std::unique_ptr<MemoryRange> overflow(new MemoryRange(process_memory, 100, 200, 0));
- ASSERT_FALSE(overflow->ReadFully(UINT64_MAX - 10, buffer.data(), 100));
-}
-
-TEST_F(MemoryRangeTest, read) {
- memory_fake_->SetMemoryBlock(0, 4096, 0x4c);
-
- MemoryRange range(process_memory_, 1000, 1024, 0);
-
- std::vector<uint8_t> dst(1024);
- ASSERT_EQ(4U, range.Read(1020, dst.data(), dst.size()));
- for (size_t i = 0; i < 4; i++) {
- ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
- }
-}
-
-TEST_F(MemoryRangeTest, read_non_zero_offset) {
- memory_fake_->SetMemoryBlock(1000, 1024, 0x12);
-
- MemoryRange range(process_memory_, 1000, 1024, 400);
-
- std::vector<uint8_t> dst(1024);
- ASSERT_EQ(1024U, range.Read(400, dst.data(), dst.size()));
- for (size_t i = 0; i < dst.size(); i++) {
- ASSERT_EQ(0x12U, dst[i]) << "Failed at byte " << i;
- }
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/MemoryRangesTest.cpp b/libunwindstack/tests/MemoryRangesTest.cpp
deleted file mode 100644
index e4e9fc4..0000000
--- a/libunwindstack/tests/MemoryRangesTest.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2018 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 <stdint.h>
-
-#include <vector>
-
-#include <gtest/gtest.h>
-
-#include "MemoryFake.h"
-#include "MemoryRange.h"
-
-namespace unwindstack {
-
-class MemoryRangesTest : public ::testing::Test {
- protected:
- void SetUp() override {
- MemoryFake* memory = new MemoryFake;
- process_memory_.reset(memory);
- memory->SetMemoryBlock(1000, 5000, 0x15);
- memory->SetMemoryBlock(6000, 12000, 0x26);
- memory->SetMemoryBlock(14000, 20000, 0x37);
- memory->SetMemoryBlock(20000, 22000, 0x48);
-
- ranges_.reset(new MemoryRanges);
- ranges_->Insert(new MemoryRange(process_memory_, 15000, 100, 4000));
- ranges_->Insert(new MemoryRange(process_memory_, 10000, 2000, 2000));
- ranges_->Insert(new MemoryRange(process_memory_, 3000, 1000, 0));
- ranges_->Insert(new MemoryRange(process_memory_, 19000, 1000, 6000));
- ranges_->Insert(new MemoryRange(process_memory_, 20000, 1000, 7000));
- }
-
- std::shared_ptr<Memory> process_memory_;
- std::unique_ptr<MemoryRanges> ranges_;
-};
-
-TEST_F(MemoryRangesTest, read) {
- std::vector<uint8_t> dst(2000);
- size_t bytes = ranges_->Read(0, dst.data(), dst.size());
- ASSERT_EQ(1000UL, bytes);
- for (size_t i = 0; i < bytes; i++) {
- ASSERT_EQ(0x15U, dst[i]) << "Failed at byte " << i;
- }
-
- bytes = ranges_->Read(2000, dst.data(), dst.size());
- ASSERT_EQ(2000UL, bytes);
- for (size_t i = 0; i < bytes; i++) {
- ASSERT_EQ(0x26U, dst[i]) << "Failed at byte " << i;
- }
-
- bytes = ranges_->Read(4000, dst.data(), dst.size());
- ASSERT_EQ(100UL, bytes);
- for (size_t i = 0; i < bytes; i++) {
- ASSERT_EQ(0x37U, dst[i]) << "Failed at byte " << i;
- }
-}
-
-TEST_F(MemoryRangesTest, read_fail) {
- std::vector<uint8_t> dst(4096);
- ASSERT_EQ(0UL, ranges_->Read(1000, dst.data(), dst.size()));
- ASSERT_EQ(0UL, ranges_->Read(5000, dst.data(), dst.size()));
- ASSERT_EQ(0UL, ranges_->Read(8000, dst.data(), dst.size()));
-}
-
-TEST_F(MemoryRangesTest, read_across_ranges) {
- // The MemoryRanges object does not support reading across a range,
- // so this will only read in the first range.
- std::vector<uint8_t> dst(4096);
- size_t bytes = ranges_->Read(6000, dst.data(), dst.size());
- ASSERT_EQ(1000UL, bytes);
- for (size_t i = 0; i < bytes; i++) {
- ASSERT_EQ(0x37U, dst[i]) << "Failed at byte " << i;
- }
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/MemoryRemoteTest.cpp b/libunwindstack/tests/MemoryRemoteTest.cpp
deleted file mode 100644
index 621893b..0000000
--- a/libunwindstack/tests/MemoryRemoteTest.cpp
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * Copyright (C) 2016 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 <errno.h>
-#include <signal.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/ptrace.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/test_utils.h>
-#include <gtest/gtest.h>
-
-#include "MemoryRemote.h"
-
-#include "MemoryFake.h"
-#include "TestUtils.h"
-
-namespace unwindstack {
-
-TEST(MemoryRemoteTest, read) {
- std::vector<uint8_t> src(1024);
- memset(src.data(), 0x4c, 1024);
-
- pid_t pid;
- if ((pid = fork()) == 0) {
- while (true);
- exit(1);
- }
- ASSERT_LT(0, pid);
- TestScopedPidReaper reap(pid);
-
- ASSERT_TRUE(TestAttach(pid));
-
- MemoryRemote remote(pid);
-
- std::vector<uint8_t> dst(1024);
- ASSERT_TRUE(remote.ReadFully(reinterpret_cast<uint64_t>(src.data()), dst.data(), 1024));
- for (size_t i = 0; i < 1024; i++) {
- ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
- }
-
- ASSERT_TRUE(TestDetach(pid));
-}
-
-TEST(MemoryRemoteTest, read_large) {
- static constexpr size_t kTotalPages = 245;
- std::vector<uint8_t> src(kTotalPages * getpagesize());
- for (size_t i = 0; i < kTotalPages; i++) {
- memset(&src[i * getpagesize()], i, getpagesize());
- }
-
- pid_t pid;
- if ((pid = fork()) == 0) {
- while (true)
- ;
- exit(1);
- }
- ASSERT_LT(0, pid);
- TestScopedPidReaper reap(pid);
-
- ASSERT_TRUE(TestAttach(pid));
-
- MemoryRemote remote(pid);
-
- std::vector<uint8_t> dst(kTotalPages * getpagesize());
- ASSERT_TRUE(remote.ReadFully(reinterpret_cast<uint64_t>(src.data()), dst.data(), src.size()));
- for (size_t i = 0; i < kTotalPages * getpagesize(); i++) {
- ASSERT_EQ(i / getpagesize(), dst[i]) << "Failed at byte " << i;
- }
-
- ASSERT_TRUE(TestDetach(pid));
-}
-
-TEST(MemoryRemoteTest, read_partial) {
- char* mapping = static_cast<char*>(
- mmap(nullptr, 4 * getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
- ASSERT_NE(MAP_FAILED, mapping);
- memset(mapping, 0x4c, 4 * getpagesize());
- ASSERT_EQ(0, mprotect(mapping + getpagesize(), getpagesize(), PROT_NONE));
- ASSERT_EQ(0, munmap(mapping + 3 * getpagesize(), getpagesize()));
-
- pid_t pid;
- if ((pid = fork()) == 0) {
- while (true)
- ;
- exit(1);
- }
- ASSERT_LT(0, pid);
- TestScopedPidReaper reap(pid);
-
- // Unmap from our process.
- ASSERT_EQ(0, munmap(mapping, 3 * getpagesize()));
-
- ASSERT_TRUE(TestAttach(pid));
-
- MemoryRemote remote(pid);
-
- std::vector<uint8_t> dst(4096);
- size_t bytes =
- remote.Read(reinterpret_cast<uint64_t>(mapping + getpagesize() - 1024), dst.data(), 4096);
- // Some read methods can read PROT_NONE maps, allow that.
- ASSERT_LE(1024U, bytes);
- for (size_t i = 0; i < bytes; i++) {
- ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
- }
-
- // Now verify that reading stops at the end of a map.
- bytes =
- remote.Read(reinterpret_cast<uint64_t>(mapping + 3 * getpagesize() - 1024), dst.data(), 4096);
- ASSERT_EQ(1024U, bytes);
- for (size_t i = 0; i < bytes; i++) {
- ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
- }
-
- ASSERT_TRUE(TestDetach(pid));
-}
-
-TEST(MemoryRemoteTest, read_fail) {
- int pagesize = getpagesize();
- void* src = mmap(nullptr, pagesize * 2, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE,-1, 0);
- memset(src, 0x4c, pagesize * 2);
- ASSERT_NE(MAP_FAILED, src);
- // Put a hole right after the first page.
- ASSERT_EQ(0, munmap(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(src) + pagesize),
- pagesize));
-
- pid_t pid;
- if ((pid = fork()) == 0) {
- while (true);
- exit(1);
- }
- ASSERT_LT(0, pid);
- TestScopedPidReaper reap(pid);
-
- ASSERT_TRUE(TestAttach(pid));
-
- MemoryRemote remote(pid);
-
- std::vector<uint8_t> dst(pagesize);
- ASSERT_TRUE(remote.ReadFully(reinterpret_cast<uint64_t>(src), dst.data(), pagesize));
- for (size_t i = 0; i < 1024; i++) {
- ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
- }
-
- ASSERT_FALSE(remote.ReadFully(reinterpret_cast<uint64_t>(src) + pagesize, dst.data(), 1));
- ASSERT_TRUE(remote.ReadFully(reinterpret_cast<uint64_t>(src) + pagesize - 1, dst.data(), 1));
- ASSERT_FALSE(remote.ReadFully(reinterpret_cast<uint64_t>(src) + pagesize - 4, dst.data(), 8));
-
- // Check overflow condition is caught properly.
- ASSERT_FALSE(remote.ReadFully(UINT64_MAX - 100, dst.data(), 200));
-
- ASSERT_EQ(0, munmap(src, pagesize));
-
- ASSERT_TRUE(TestDetach(pid));
-}
-
-TEST(MemoryRemoteTest, read_overflow) {
- pid_t pid;
- if ((pid = fork()) == 0) {
- while (true)
- ;
- exit(1);
- }
- ASSERT_LT(0, pid);
- TestScopedPidReaper reap(pid);
-
- ASSERT_TRUE(TestAttach(pid));
-
- MemoryRemote remote(pid);
-
- // Check overflow condition is caught properly.
- std::vector<uint8_t> dst(200);
- ASSERT_FALSE(remote.ReadFully(UINT64_MAX - 100, dst.data(), 200));
-
- ASSERT_TRUE(TestDetach(pid));
-}
-
-TEST(MemoryRemoteTest, read_illegal) {
- pid_t pid;
- if ((pid = fork()) == 0) {
- while (true);
- exit(1);
- }
- ASSERT_LT(0, pid);
- TestScopedPidReaper reap(pid);
-
- ASSERT_TRUE(TestAttach(pid));
-
- MemoryRemote remote(pid);
-
- std::vector<uint8_t> dst(100);
- ASSERT_FALSE(remote.ReadFully(0, dst.data(), 1));
- ASSERT_FALSE(remote.ReadFully(0, dst.data(), 100));
-
- ASSERT_TRUE(TestDetach(pid));
-}
-
-TEST(MemoryRemoteTest, read_mprotect_hole) {
- size_t page_size = getpagesize();
- void* mapping =
- mmap(nullptr, 3 * getpagesize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
- ASSERT_NE(MAP_FAILED, mapping);
- memset(mapping, 0xFF, 3 * page_size);
- ASSERT_EQ(0, mprotect(static_cast<char*>(mapping) + page_size, page_size, PROT_NONE));
-
- pid_t pid;
- if ((pid = fork()) == 0) {
- while (true);
- exit(1);
- }
- ASSERT_LT(0, pid);
- TestScopedPidReaper reap(pid);
-
- ASSERT_EQ(0, munmap(mapping, 3 * page_size));
-
- ASSERT_TRUE(TestAttach(pid));
-
- MemoryRemote remote(pid);
- std::vector<uint8_t> dst(getpagesize() * 4, 0xCC);
- size_t read_size = remote.Read(reinterpret_cast<uint64_t>(mapping), dst.data(), page_size * 3);
- // Some read methods can read PROT_NONE maps, allow that.
- ASSERT_LE(page_size, read_size);
- for (size_t i = 0; i < read_size; ++i) {
- ASSERT_EQ(0xFF, dst[i]);
- }
- for (size_t i = read_size; i < dst.size(); ++i) {
- ASSERT_EQ(0xCC, dst[i]);
- }
-
- ASSERT_TRUE(TestDetach(pid));
-}
-
-TEST(MemoryRemoteTest, read_munmap_hole) {
- size_t page_size = getpagesize();
- void* mapping =
- mmap(nullptr, 3 * getpagesize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
- ASSERT_NE(MAP_FAILED, mapping);
- memset(mapping, 0xFF, 3 * page_size);
- ASSERT_EQ(0, munmap(static_cast<char*>(mapping) + page_size, page_size));
-
- pid_t pid;
- if ((pid = fork()) == 0) {
- while (true)
- ;
- exit(1);
- }
- ASSERT_LT(0, pid);
- TestScopedPidReaper reap(pid);
-
- ASSERT_EQ(0, munmap(mapping, page_size));
- ASSERT_EQ(0, munmap(static_cast<char*>(mapping) + 2 * page_size, page_size));
-
- ASSERT_TRUE(TestAttach(pid));
-
- MemoryRemote remote(pid);
- std::vector<uint8_t> dst(getpagesize() * 4, 0xCC);
- size_t read_size = remote.Read(reinterpret_cast<uint64_t>(mapping), dst.data(), page_size * 3);
- ASSERT_EQ(page_size, read_size);
- for (size_t i = 0; i < read_size; ++i) {
- ASSERT_EQ(0xFF, dst[i]);
- }
- for (size_t i = read_size; i < dst.size(); ++i) {
- ASSERT_EQ(0xCC, dst[i]);
- }
-
- ASSERT_TRUE(TestDetach(pid));
-}
-
-// Verify that the memory remote object chooses a memory read function
-// properly. Either process_vm_readv or ptrace.
-TEST(MemoryRemoteTest, read_choose_correctly) {
- size_t page_size = getpagesize();
- void* mapping =
- mmap(nullptr, 2 * getpagesize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
- ASSERT_NE(MAP_FAILED, mapping);
- memset(mapping, 0xFC, 2 * page_size);
- ASSERT_EQ(0, mprotect(static_cast<char*>(mapping), page_size, PROT_NONE));
-
- pid_t pid;
- if ((pid = fork()) == 0) {
- while (true)
- ;
- exit(1);
- }
- ASSERT_LT(0, pid);
- TestScopedPidReaper reap(pid);
-
- ASSERT_EQ(0, munmap(mapping, 2 * page_size));
-
- ASSERT_TRUE(TestAttach(pid));
-
- // We know that process_vm_readv of a mprotect'd PROT_NONE region will fail.
- // Read from the PROT_NONE area first to force the choice of ptrace.
- MemoryRemote remote_ptrace(pid);
- uint32_t value;
- size_t bytes = remote_ptrace.Read(reinterpret_cast<uint64_t>(mapping), &value, sizeof(value));
- ASSERT_EQ(sizeof(value), bytes);
- ASSERT_EQ(0xfcfcfcfcU, value);
- bytes = remote_ptrace.Read(reinterpret_cast<uint64_t>(mapping) + page_size, &value, sizeof(value));
- ASSERT_EQ(sizeof(value), bytes);
- ASSERT_EQ(0xfcfcfcfcU, value);
- bytes = remote_ptrace.Read(reinterpret_cast<uint64_t>(mapping), &value, sizeof(value));
- ASSERT_EQ(sizeof(value), bytes);
- ASSERT_EQ(0xfcfcfcfcU, value);
-
- // Now verify that choosing process_vm_readv results in failing reads of
- // the PROT_NONE part of the map. Read from a valid map first which
- // should prefer process_vm_readv, and keep that as the read function.
- MemoryRemote remote_readv(pid);
- bytes = remote_readv.Read(reinterpret_cast<uint64_t>(mapping) + page_size, &value, sizeof(value));
- ASSERT_EQ(sizeof(value), bytes);
- ASSERT_EQ(0xfcfcfcfcU, value);
- bytes = remote_readv.Read(reinterpret_cast<uint64_t>(mapping), &value, sizeof(value));
- ASSERT_EQ(0U, bytes);
- bytes = remote_readv.Read(reinterpret_cast<uint64_t>(mapping) + page_size, &value, sizeof(value));
- ASSERT_EQ(sizeof(value), bytes);
- ASSERT_EQ(0xfcfcfcfcU, value);
-
- ASSERT_TRUE(TestDetach(pid));
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/MemoryTest.cpp b/libunwindstack/tests/MemoryTest.cpp
deleted file mode 100644
index 8a8eb24..0000000
--- a/libunwindstack/tests/MemoryTest.cpp
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (C) 2017 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 <stdint.h>
-#include <string.h>
-
-#include <string>
-#include <vector>
-
-#include <gtest/gtest.h>
-
-#include <unwindstack/Memory.h>
-
-#include "MemoryFake.h"
-
-namespace unwindstack {
-
-TEST(MemoryTest, read32) {
- MemoryFakeAlwaysReadZero memory;
-
- uint32_t data = 0xffffffff;
- ASSERT_TRUE(memory.Read32(0, &data));
- ASSERT_EQ(0U, data);
-}
-
-TEST(MemoryTest, read64) {
- MemoryFakeAlwaysReadZero memory;
-
- uint64_t data = 0xffffffffffffffffULL;
- ASSERT_TRUE(memory.Read64(0, &data));
- ASSERT_EQ(0U, data);
-}
-
-struct FakeStruct {
- int one;
- bool two;
- uint32_t three;
- uint64_t four;
-};
-
-TEST(MemoryTest, read_string) {
- std::string name("string_in_memory");
-
- MemoryFake memory;
-
- memory.SetMemory(100, name.c_str(), name.size() + 1);
-
- std::string dst_name;
- ASSERT_TRUE(memory.ReadString(100, &dst_name, 100));
- ASSERT_EQ("string_in_memory", dst_name);
-
- ASSERT_TRUE(memory.ReadString(107, &dst_name, 100));
- ASSERT_EQ("in_memory", dst_name);
-
- // Set size greater than string.
- ASSERT_TRUE(memory.ReadString(107, &dst_name, 10));
- ASSERT_EQ("in_memory", dst_name);
-
- ASSERT_FALSE(memory.ReadString(107, &dst_name, 9));
-}
-
-TEST(MemoryTest, read_string_error) {
- std::string name("short");
-
- MemoryFake memory;
-
- // Save everything except the terminating '\0'.
- memory.SetMemory(0, name.c_str(), name.size());
-
- std::string dst_name;
- // Read from a non-existant address.
- ASSERT_FALSE(memory.ReadString(100, &dst_name, 100));
-
- // This should fail because there is no terminating '\0'.
- ASSERT_FALSE(memory.ReadString(0, &dst_name, 100));
-
- // This should pass because there is a terminating '\0'.
- memory.SetData8(name.size(), '\0');
- ASSERT_TRUE(memory.ReadString(0, &dst_name, 100));
- ASSERT_EQ("short", dst_name);
-}
-
-TEST(MemoryTest, read_string_long) {
- // This string should be greater than 768 characters long (greater than 3 times
- // the buffer in the ReadString function) to read multiple blocks.
- static constexpr char kLongString[] =
- "one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen "
- "sixteen seventeen eightteen nineteen twenty twenty-one twenty-two twenty-three twenty-four "
- "twenty-five twenty-six twenty-seven twenty-eight twenty-nine thirty thirty-one thirty-two "
- "thirty-three thirty-four thirty-five thirty-six thirty-seven thirty-eight thirty-nine forty "
- "forty-one forty-two forty-three forty-four forty-five forty-size forty-seven forty-eight "
- "forty-nine fifty fifty-one fifty-two fifty-three fifty-four fifty-five fifty-six "
- "fifty-seven fifty-eight fifty-nine sixty sixty-one sixty-two sixty-three sixty-four "
- "sixty-five sixty-six sixty-seven sixty-eight sixty-nine seventy seventy-one seventy-two "
- "seventy-three seventy-four seventy-five seventy-six seventy-seven seventy-eight "
- "seventy-nine eighty";
-
- MemoryFake memory;
-
- memory.SetMemory(100, kLongString, sizeof(kLongString));
-
- std::string dst_name;
- ASSERT_TRUE(memory.ReadString(100, &dst_name, sizeof(kLongString)));
- ASSERT_EQ(kLongString, dst_name);
-
- std::string expected_str(kLongString, 255);
- memory.SetMemory(100, expected_str.data(), expected_str.length() + 1);
- ASSERT_TRUE(memory.ReadString(100, &dst_name, 256));
- ASSERT_EQ(expected_str, dst_name);
- ASSERT_FALSE(memory.ReadString(100, &dst_name, 255));
-
- expected_str = std::string(kLongString, 256);
- memory.SetMemory(100, expected_str.data(), expected_str.length() + 1);
- ASSERT_TRUE(memory.ReadString(100, &dst_name, 257));
- ASSERT_EQ(expected_str, dst_name);
- ASSERT_FALSE(memory.ReadString(100, &dst_name, 256));
-
- expected_str = std::string(kLongString, 299);
- memory.SetMemory(100, expected_str.data(), expected_str.length() + 1);
- ASSERT_TRUE(memory.ReadString(100, &dst_name, 300));
- ASSERT_EQ(expected_str, dst_name);
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/RegsFake.h b/libunwindstack/tests/RegsFake.h
deleted file mode 100644
index f67d7dc..0000000
--- a/libunwindstack/tests/RegsFake.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _LIBUNWINDSTACK_TESTS_REGS_FAKE_H
-#define _LIBUNWINDSTACK_TESTS_REGS_FAKE_H
-
-#include <stdint.h>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/Regs.h>
-
-#include "Check.h"
-
-namespace unwindstack {
-
-class RegsFake : public Regs {
- public:
- RegsFake(uint16_t total_regs) : Regs(total_regs, Regs::Location(Regs::LOCATION_UNKNOWN, 0)) {}
- virtual ~RegsFake() = default;
-
- ArchEnum Arch() override { return fake_arch_; }
- void* RawData() override { return nullptr; }
- uint64_t pc() override { return fake_pc_; }
- uint64_t sp() override { return fake_sp_; }
- void set_pc(uint64_t pc) override { fake_pc_ = pc; }
- void set_sp(uint64_t sp) override { fake_sp_ = sp; }
-
- bool SetPcFromReturnAddress(Memory*) override {
- if (!fake_return_address_valid_) {
- return false;
- }
- fake_pc_ = fake_return_address_;
- return true;
- }
-
- void IterateRegisters(std::function<void(const char*, uint64_t)>) override {}
-
- bool Is32Bit() {
- CHECK(fake_arch_ != ARCH_UNKNOWN);
- return fake_arch_ == ARCH_ARM || fake_arch_ == ARCH_X86 || fake_arch_ == ARCH_MIPS;
- }
-
- bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; }
-
- void FakeSetArch(ArchEnum arch) { fake_arch_ = arch; }
- void FakeSetDexPc(uint64_t dex_pc) { dex_pc_ = dex_pc; }
- void FakeSetReturnAddress(uint64_t return_address) { fake_return_address_ = return_address; }
- void FakeSetReturnAddressValid(bool valid) { fake_return_address_valid_ = valid; }
-
- Regs* Clone() override { return nullptr; }
-
- private:
- ArchEnum fake_arch_ = ARCH_UNKNOWN;
- uint64_t fake_pc_ = 0;
- uint64_t fake_sp_ = 0;
- bool fake_return_address_valid_ = false;
- uint64_t fake_return_address_ = 0;
-};
-
-template <typename TypeParam>
-class RegsImplFake : public RegsImpl<TypeParam> {
- public:
- RegsImplFake(uint16_t total_regs)
- : RegsImpl<TypeParam>(total_regs, Regs::Location(Regs::LOCATION_UNKNOWN, 0)) {}
- virtual ~RegsImplFake() = default;
-
- ArchEnum Arch() override { return ARCH_UNKNOWN; }
- uint64_t pc() override { return fake_pc_; }
- uint64_t sp() override { return fake_sp_; }
- void set_pc(uint64_t pc) override { fake_pc_ = pc; }
- void set_sp(uint64_t sp) override { fake_sp_ = sp; }
- void set_pseudo_reg(uint64_t reg) { fake_pseudo_reg_ = reg; }
-
- bool SetPcFromReturnAddress(Memory*) override { return false; }
- bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; }
-
- bool SetPseudoRegister(uint16_t reg, uint64_t value) override {
- if (fake_pseudo_reg_ != reg) {
- return false;
- }
- fake_pseudo_reg_value_ = value;
- return true;
- }
- bool GetPseudoRegister(uint16_t reg, uint64_t* value) override {
- if (fake_pseudo_reg_ != reg) {
- return false;
- }
- *value = fake_pseudo_reg_value_;
- return true;
- }
-
- Regs* Clone() override { return nullptr; }
-
- private:
- uint64_t fake_pc_ = 0;
- uint64_t fake_sp_ = 0;
- uint16_t fake_pseudo_reg_ = 0;
- uint64_t fake_pseudo_reg_value_ = 0;
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_TESTS_REGS_FAKE_H
diff --git a/libunwindstack/tests/RegsInfoTest.cpp b/libunwindstack/tests/RegsInfoTest.cpp
deleted file mode 100644
index a6bc2c5..0000000
--- a/libunwindstack/tests/RegsInfoTest.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2018 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 <stdint.h>
-
-#include <gtest/gtest.h>
-
-#include <unwindstack/Regs.h>
-
-#include "RegsFake.h"
-#include "RegsInfo.h"
-
-namespace unwindstack {
-
-TEST(RegsInfoTest, single_uint32_t) {
- RegsImplFake<uint32_t> regs(10);
- RegsInfo<uint32_t> info(®s);
-
- regs[1] = 0x100;
- ASSERT_FALSE(info.IsSaved(1));
- ASSERT_EQ(0x100U, info.Get(1));
- ASSERT_EQ(10, info.Total());
-
- uint32_t* value = info.Save(1);
- ASSERT_EQ(value, ®s[1]);
- regs[1] = 0x200;
- ASSERT_TRUE(info.IsSaved(1));
- ASSERT_EQ(0x100U, info.Get(1));
- ASSERT_EQ(0x200U, regs[1]);
-}
-
-TEST(RegsInfoTest, single_uint64_t) {
- RegsImplFake<uint64_t> regs(20);
- RegsInfo<uint64_t> info(®s);
-
- regs[3] = 0x300;
- ASSERT_FALSE(info.IsSaved(3));
- ASSERT_EQ(0x300U, info.Get(3));
- ASSERT_EQ(20, info.Total());
-
- uint64_t* value = info.Save(3);
- ASSERT_EQ(value, ®s[3]);
- regs[3] = 0x400;
- ASSERT_TRUE(info.IsSaved(3));
- ASSERT_EQ(0x300U, info.Get(3));
- ASSERT_EQ(0x400U, regs[3]);
-}
-
-TEST(RegsInfoTest, all) {
- RegsImplFake<uint64_t> regs(64);
- RegsInfo<uint64_t> info(®s);
-
- for (uint32_t i = 0; i < 64; i++) {
- regs[i] = i * 0x100;
- ASSERT_EQ(i * 0x100, info.Get(i)) << "Reg " + std::to_string(i) + " failed.";
- }
-
- for (uint32_t i = 0; i < 64; i++) {
- ASSERT_FALSE(info.IsSaved(i)) << "Reg " + std::to_string(i) + " failed.";
- uint64_t* reg = info.Save(i);
- ASSERT_EQ(reg, ®s[i]) << "Reg " + std::to_string(i) + " failed.";
- *reg = i * 0x1000 + 0x100;
- ASSERT_EQ(i * 0x1000 + 0x100, regs[i]) << "Reg " + std::to_string(i) + " failed.";
- }
-
- for (uint32_t i = 0; i < 64; i++) {
- ASSERT_TRUE(info.IsSaved(i)) << "Reg " + std::to_string(i) + " failed.";
- ASSERT_EQ(i * 0x100, info.Get(i)) << "Reg " + std::to_string(i) + " failed.";
- }
-}
-
-TEST(RegsInfoTest, invalid_register) {
- RegsImplFake<uint64_t> regs(64);
- RegsInfo<uint64_t> info(®s);
-
- EXPECT_DEATH(info.Save(RegsInfo<uint64_t>::MAX_REGISTERS), "");
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/RegsIterateTest.cpp b/libunwindstack/tests/RegsIterateTest.cpp
deleted file mode 100644
index 47e605a..0000000
--- a/libunwindstack/tests/RegsIterateTest.cpp
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * Copyright (C) 2017 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 <stdint.h>
-
-#include <utility>
-#include <type_traits>
-#include <vector>
-
-#include <gtest/gtest.h>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/ElfInterface.h>
-#include <unwindstack/MachineArm.h>
-#include <unwindstack/MachineArm64.h>
-#include <unwindstack/MachineMips.h>
-#include <unwindstack/MachineMips64.h>
-#include <unwindstack/MachineX86.h>
-#include <unwindstack/MachineX86_64.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/RegsArm.h>
-#include <unwindstack/RegsArm64.h>
-#include <unwindstack/RegsMips.h>
-#include <unwindstack/RegsMips64.h>
-#include <unwindstack/RegsX86.h>
-#include <unwindstack/RegsX86_64.h>
-
-namespace unwindstack {
-
-struct Register {
- std::string expected_name;
- uint64_t offset;
-
- bool operator==(const Register& rhs) const {
- return std::tie(expected_name, offset) == std::tie(rhs.expected_name, rhs.offset);
- }
-};
-
-template<typename T>
-class RegsIterateTest : public ::testing::Test {
-};
-
-template<typename RegsType>
-std::vector<Register> ExpectedRegisters();
-
-template<>
-std::vector<Register> ExpectedRegisters<RegsArm>() {
- std::vector<Register> result;
- result.push_back({"r0", ARM_REG_R0});
- result.push_back({"r1", ARM_REG_R1});
- result.push_back({"r2", ARM_REG_R2});
- result.push_back({"r3", ARM_REG_R3});
- result.push_back({"r4", ARM_REG_R4});
- result.push_back({"r5", ARM_REG_R5});
- result.push_back({"r6", ARM_REG_R6});
- result.push_back({"r7", ARM_REG_R7});
- result.push_back({"r8", ARM_REG_R8});
- result.push_back({"r9", ARM_REG_R9});
- result.push_back({"r10", ARM_REG_R10});
- result.push_back({"r11", ARM_REG_R11});
- result.push_back({"ip", ARM_REG_R12});
- result.push_back({"sp", ARM_REG_SP});
- result.push_back({"lr", ARM_REG_LR});
- result.push_back({"pc", ARM_REG_PC});
- return result;
-}
-
-template<>
-std::vector<Register> ExpectedRegisters<RegsArm64>() {
- std::vector<Register> result;
- result.push_back({"x0", ARM64_REG_R0});
- result.push_back({"x1", ARM64_REG_R1});
- result.push_back({"x2", ARM64_REG_R2});
- result.push_back({"x3", ARM64_REG_R3});
- result.push_back({"x4", ARM64_REG_R4});
- result.push_back({"x5", ARM64_REG_R5});
- result.push_back({"x6", ARM64_REG_R6});
- result.push_back({"x7", ARM64_REG_R7});
- result.push_back({"x8", ARM64_REG_R8});
- result.push_back({"x9", ARM64_REG_R9});
- result.push_back({"x10", ARM64_REG_R10});
- result.push_back({"x11", ARM64_REG_R11});
- result.push_back({"x12", ARM64_REG_R12});
- result.push_back({"x13", ARM64_REG_R13});
- result.push_back({"x14", ARM64_REG_R14});
- result.push_back({"x15", ARM64_REG_R15});
- result.push_back({"x16", ARM64_REG_R16});
- result.push_back({"x17", ARM64_REG_R17});
- result.push_back({"x18", ARM64_REG_R18});
- result.push_back({"x19", ARM64_REG_R19});
- result.push_back({"x20", ARM64_REG_R20});
- result.push_back({"x21", ARM64_REG_R21});
- result.push_back({"x22", ARM64_REG_R22});
- result.push_back({"x23", ARM64_REG_R23});
- result.push_back({"x24", ARM64_REG_R24});
- result.push_back({"x25", ARM64_REG_R25});
- result.push_back({"x26", ARM64_REG_R26});
- result.push_back({"x27", ARM64_REG_R27});
- result.push_back({"x28", ARM64_REG_R28});
- result.push_back({"x29", ARM64_REG_R29});
- result.push_back({"lr", ARM64_REG_LR});
- result.push_back({"sp", ARM64_REG_SP});
- result.push_back({"pc", ARM64_REG_PC});
- result.push_back({"pst", ARM64_REG_PSTATE});
- return result;
-}
-
-template<>
-std::vector<Register> ExpectedRegisters<RegsX86>() {
- std::vector<Register> result;
- result.push_back({"eax", X86_REG_EAX});
- result.push_back({"ebx", X86_REG_EBX});
- result.push_back({"ecx", X86_REG_ECX});
- result.push_back({"edx", X86_REG_EDX});
- result.push_back({"ebp", X86_REG_EBP});
- result.push_back({"edi", X86_REG_EDI});
- result.push_back({"esi", X86_REG_ESI});
- result.push_back({"esp", X86_REG_ESP});
- result.push_back({"eip", X86_REG_EIP});
- return result;
-}
-
-template<>
-std::vector<Register> ExpectedRegisters<RegsX86_64>() {
- std::vector<Register> result;
- result.push_back({"rax", X86_64_REG_RAX});
- result.push_back({"rbx", X86_64_REG_RBX});
- result.push_back({"rcx", X86_64_REG_RCX});
- result.push_back({"rdx", X86_64_REG_RDX});
- result.push_back({"r8", X86_64_REG_R8});
- result.push_back({"r9", X86_64_REG_R9});
- result.push_back({"r10", X86_64_REG_R10});
- result.push_back({"r11", X86_64_REG_R11});
- result.push_back({"r12", X86_64_REG_R12});
- result.push_back({"r13", X86_64_REG_R13});
- result.push_back({"r14", X86_64_REG_R14});
- result.push_back({"r15", X86_64_REG_R15});
- result.push_back({"rdi", X86_64_REG_RDI});
- result.push_back({"rsi", X86_64_REG_RSI});
- result.push_back({"rbp", X86_64_REG_RBP});
- result.push_back({"rsp", X86_64_REG_RSP});
- result.push_back({"rip", X86_64_REG_RIP});
- return result;
-}
-
-template<>
-std::vector<Register> ExpectedRegisters<RegsMips>() {
- std::vector<Register> result;
- result.push_back({"r0", MIPS_REG_R0});
- result.push_back({"r1", MIPS_REG_R1});
- result.push_back({"r2", MIPS_REG_R2});
- result.push_back({"r3", MIPS_REG_R3});
- result.push_back({"r4", MIPS_REG_R4});
- result.push_back({"r5", MIPS_REG_R5});
- result.push_back({"r6", MIPS_REG_R6});
- result.push_back({"r7", MIPS_REG_R7});
- result.push_back({"r8", MIPS_REG_R8});
- result.push_back({"r9", MIPS_REG_R9});
- result.push_back({"r10", MIPS_REG_R10});
- result.push_back({"r11", MIPS_REG_R11});
- result.push_back({"r12", MIPS_REG_R12});
- result.push_back({"r13", MIPS_REG_R13});
- result.push_back({"r14", MIPS_REG_R14});
- result.push_back({"r15", MIPS_REG_R15});
- result.push_back({"r16", MIPS_REG_R16});
- result.push_back({"r17", MIPS_REG_R17});
- result.push_back({"r18", MIPS_REG_R18});
- result.push_back({"r19", MIPS_REG_R19});
- result.push_back({"r20", MIPS_REG_R20});
- result.push_back({"r21", MIPS_REG_R21});
- result.push_back({"r22", MIPS_REG_R22});
- result.push_back({"r23", MIPS_REG_R23});
- result.push_back({"r24", MIPS_REG_R24});
- result.push_back({"r25", MIPS_REG_R25});
- result.push_back({"r26", MIPS_REG_R26});
- result.push_back({"r27", MIPS_REG_R27});
- result.push_back({"r28", MIPS_REG_R28});
- result.push_back({"sp", MIPS_REG_SP});
- result.push_back({"r30", MIPS_REG_R30});
- result.push_back({"ra", MIPS_REG_RA});
- result.push_back({"pc", MIPS_REG_PC});
-
- return result;
-}
-
-template<>
-std::vector<Register> ExpectedRegisters<RegsMips64>() {
- std::vector<Register> result;
- result.push_back({"r0", MIPS64_REG_R0});
- result.push_back({"r1", MIPS64_REG_R1});
- result.push_back({"r2", MIPS64_REG_R2});
- result.push_back({"r3", MIPS64_REG_R3});
- result.push_back({"r4", MIPS64_REG_R4});
- result.push_back({"r5", MIPS64_REG_R5});
- result.push_back({"r6", MIPS64_REG_R6});
- result.push_back({"r7", MIPS64_REG_R7});
- result.push_back({"r8", MIPS64_REG_R8});
- result.push_back({"r9", MIPS64_REG_R9});
- result.push_back({"r10", MIPS64_REG_R10});
- result.push_back({"r11", MIPS64_REG_R11});
- result.push_back({"r12", MIPS64_REG_R12});
- result.push_back({"r13", MIPS64_REG_R13});
- result.push_back({"r14", MIPS64_REG_R14});
- result.push_back({"r15", MIPS64_REG_R15});
- result.push_back({"r16", MIPS64_REG_R16});
- result.push_back({"r17", MIPS64_REG_R17});
- result.push_back({"r18", MIPS64_REG_R18});
- result.push_back({"r19", MIPS64_REG_R19});
- result.push_back({"r20", MIPS64_REG_R20});
- result.push_back({"r21", MIPS64_REG_R21});
- result.push_back({"r22", MIPS64_REG_R22});
- result.push_back({"r23", MIPS64_REG_R23});
- result.push_back({"r24", MIPS64_REG_R24});
- result.push_back({"r25", MIPS64_REG_R25});
- result.push_back({"r26", MIPS64_REG_R26});
- result.push_back({"r27", MIPS64_REG_R27});
- result.push_back({"r28", MIPS64_REG_R28});
- result.push_back({"sp", MIPS64_REG_SP});
- result.push_back({"r30", MIPS64_REG_R30});
- result.push_back({"ra", MIPS64_REG_RA});
- result.push_back({"pc", MIPS64_REG_PC});
-
- return result;
-}
-
-using RegTypes = ::testing::Types<RegsArm, RegsArm64, RegsX86, RegsX86_64, RegsMips, RegsMips64>;
-TYPED_TEST_SUITE(RegsIterateTest, RegTypes);
-
-TYPED_TEST(RegsIterateTest, iterate) {
- std::vector<Register> expected = ExpectedRegisters<TypeParam>();
- TypeParam regs;
- for (const auto& reg : expected) {
- regs[reg.offset] = reg.offset;
- }
-
- std::vector<Register> actual;
- regs.IterateRegisters([&actual](const char* name, uint64_t value) {
- actual.push_back({name, value});
- });
-
- ASSERT_EQ(expected, actual);
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp b/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp
deleted file mode 100644
index eac12ca..0000000
--- a/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Copyright (C) 2017 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 <stdint.h>
-
-#include <gtest/gtest.h>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/MachineArm.h>
-#include <unwindstack/MachineArm64.h>
-#include <unwindstack/MachineMips.h>
-#include <unwindstack/MachineMips64.h>
-#include <unwindstack/MachineX86.h>
-#include <unwindstack/MachineX86_64.h>
-#include <unwindstack/RegsArm.h>
-#include <unwindstack/RegsArm64.h>
-#include <unwindstack/RegsMips.h>
-#include <unwindstack/RegsMips64.h>
-#include <unwindstack/RegsX86.h>
-#include <unwindstack/RegsX86_64.h>
-
-#include "MemoryFake.h"
-
-namespace unwindstack {
-
-class RegsStepIfSignalHandlerTest : public ::testing::Test {
- protected:
- void SetUp() override {
- elf_memory_ = new MemoryFake;
- elf_.reset(new Elf(elf_memory_));
- }
-
- void ArmStepIfSignalHandlerNonRt(uint32_t pc_data);
- void ArmStepIfSignalHandlerRt(uint32_t pc_data);
-
- MemoryFake* elf_memory_;
- MemoryFake process_memory_;
- std::unique_ptr<Elf> elf_;
-};
-
-void RegsStepIfSignalHandlerTest::ArmStepIfSignalHandlerNonRt(uint32_t pc_data) {
- uint64_t addr = 0x1000;
- RegsArm regs;
- regs[ARM_REG_PC] = 0x5000;
- regs[ARM_REG_SP] = addr;
-
- elf_memory_->SetData32(0x5000, pc_data);
-
- for (uint64_t index = 0; index <= 30; index++) {
- process_memory_.SetData32(addr + index * 4, index * 0x10);
- }
-
- ASSERT_TRUE(regs.StepIfSignalHandler(0x5000, elf_.get(), &process_memory_));
- EXPECT_EQ(0x100U, regs[ARM_REG_SP]);
- EXPECT_EQ(0x120U, regs[ARM_REG_PC]);
- EXPECT_EQ(0x100U, regs.sp());
- EXPECT_EQ(0x120U, regs.pc());
-}
-
-TEST_F(RegsStepIfSignalHandlerTest, arm_step_if_signal_handler_non_rt) {
- // Form 1
- ArmStepIfSignalHandlerNonRt(0xe3a07077);
-
- // Form 2
- ArmStepIfSignalHandlerNonRt(0xef900077);
-
- // Form 3
- ArmStepIfSignalHandlerNonRt(0xdf002777);
-}
-
-void RegsStepIfSignalHandlerTest::ArmStepIfSignalHandlerRt(uint32_t pc_data) {
- uint64_t addr = 0x1000;
- RegsArm regs;
- regs[ARM_REG_PC] = 0x5000;
- regs[ARM_REG_SP] = addr;
-
- elf_memory_->SetData32(0x5000, pc_data);
-
- for (uint64_t index = 0; index <= 100; index++) {
- process_memory_.SetData32(addr + index * 4, index * 0x10);
- }
-
- ASSERT_TRUE(regs.StepIfSignalHandler(0x5000, elf_.get(), &process_memory_));
- EXPECT_EQ(0x350U, regs[ARM_REG_SP]);
- EXPECT_EQ(0x370U, regs[ARM_REG_PC]);
- EXPECT_EQ(0x350U, regs.sp());
- EXPECT_EQ(0x370U, regs.pc());
-}
-
-TEST_F(RegsStepIfSignalHandlerTest, arm_step_if_signal_handler_rt) {
- // Form 1
- ArmStepIfSignalHandlerRt(0xe3a070ad);
-
- // Form 2
- ArmStepIfSignalHandlerRt(0xef9000ad);
-
- // Form 3
- ArmStepIfSignalHandlerRt(0xdf0027ad);
-}
-
-TEST_F(RegsStepIfSignalHandlerTest, arm64_step_if_signal_handler) {
- uint64_t addr = 0x1000;
- RegsArm64 regs;
- regs[ARM64_REG_PC] = 0x8000;
- regs[ARM64_REG_SP] = addr;
-
- elf_memory_->SetData64(0x8000, 0xd4000001d2801168ULL);
-
- for (uint64_t index = 0; index <= 100; index++) {
- process_memory_.SetData64(addr + index * 8, index * 0x10);
- }
-
- ASSERT_TRUE(regs.StepIfSignalHandler(0x8000, elf_.get(), &process_memory_));
- EXPECT_EQ(0x460U, regs[ARM64_REG_SP]);
- EXPECT_EQ(0x470U, regs[ARM64_REG_PC]);
- EXPECT_EQ(0x460U, regs.sp());
- EXPECT_EQ(0x470U, regs.pc());
-}
-
-TEST_F(RegsStepIfSignalHandlerTest, x86_step_if_signal_handler_no_siginfo) {
- uint64_t addr = 0xa00;
- RegsX86 regs;
- regs[X86_REG_EIP] = 0x4100;
- regs[X86_REG_ESP] = addr;
-
- elf_memory_->SetData64(0x4100, 0x80cd00000077b858ULL);
- for (uint64_t index = 0; index <= 25; index++) {
- process_memory_.SetData32(addr + index * 4, index * 0x10);
- }
-
- ASSERT_TRUE(regs.StepIfSignalHandler(0x4100, elf_.get(), &process_memory_));
- EXPECT_EQ(0x70U, regs[X86_REG_EBP]);
- EXPECT_EQ(0x80U, regs[X86_REG_ESP]);
- EXPECT_EQ(0x90U, regs[X86_REG_EBX]);
- EXPECT_EQ(0xa0U, regs[X86_REG_EDX]);
- EXPECT_EQ(0xb0U, regs[X86_REG_ECX]);
- EXPECT_EQ(0xc0U, regs[X86_REG_EAX]);
- EXPECT_EQ(0xf0U, regs[X86_REG_EIP]);
- EXPECT_EQ(0x80U, regs.sp());
- EXPECT_EQ(0xf0U, regs.pc());
-}
-
-TEST_F(RegsStepIfSignalHandlerTest, x86_step_if_signal_handler_siginfo) {
- uint64_t addr = 0xa00;
- RegsX86 regs;
- regs[X86_REG_EIP] = 0x4100;
- regs[X86_REG_ESP] = addr;
-
- elf_memory_->SetData64(0x4100, 0x0080cd000000adb8ULL);
- addr += 8;
- // Pointer to ucontext data.
- process_memory_.SetData32(addr, 0x8100);
-
- addr = 0x8100;
- for (uint64_t index = 0; index <= 30; index++) {
- process_memory_.SetData32(addr + index * 4, index * 0x10);
- }
-
- ASSERT_TRUE(regs.StepIfSignalHandler(0x4100, elf_.get(), &process_memory_));
- EXPECT_EQ(0xb0U, regs[X86_REG_EBP]);
- EXPECT_EQ(0xc0U, regs[X86_REG_ESP]);
- EXPECT_EQ(0xd0U, regs[X86_REG_EBX]);
- EXPECT_EQ(0xe0U, regs[X86_REG_EDX]);
- EXPECT_EQ(0xf0U, regs[X86_REG_ECX]);
- EXPECT_EQ(0x100U, regs[X86_REG_EAX]);
- EXPECT_EQ(0x130U, regs[X86_REG_EIP]);
- EXPECT_EQ(0xc0U, regs.sp());
- EXPECT_EQ(0x130U, regs.pc());
-}
-
-TEST_F(RegsStepIfSignalHandlerTest, x86_64_step_if_signal_handler) {
- uint64_t addr = 0x500;
- RegsX86_64 regs;
- regs[X86_64_REG_RIP] = 0x7000;
- regs[X86_64_REG_RSP] = addr;
-
- elf_memory_->SetData64(0x7000, 0x0f0000000fc0c748);
- elf_memory_->SetData16(0x7008, 0x0f05);
-
- for (uint64_t index = 0; index <= 30; index++) {
- process_memory_.SetData64(addr + index * 8, index * 0x10);
- }
-
- ASSERT_TRUE(regs.StepIfSignalHandler(0x7000, elf_.get(), &process_memory_));
- EXPECT_EQ(0x140U, regs[X86_64_REG_RSP]);
- EXPECT_EQ(0x150U, regs[X86_64_REG_RIP]);
- EXPECT_EQ(0x140U, regs.sp());
- EXPECT_EQ(0x150U, regs.pc());
-}
-
-TEST_F(RegsStepIfSignalHandlerTest, mips_step_if_signal_handler_non_rt) {
- uint64_t addr = 0x1000;
- RegsMips regs;
- regs[MIPS_REG_PC] = 0x8000;
- regs[MIPS_REG_SP] = addr;
-
- elf_memory_->SetData64(0x8000, 0x0000000c24021017ULL);
-
- for (uint64_t index = 0; index <= 50; index++) {
- process_memory_.SetData64(addr + index * 8, index * 0x10);
- }
-
- ASSERT_TRUE(regs.StepIfSignalHandler(0x8000, elf_.get(), &process_memory_));
- EXPECT_EQ(0x220U, regs[MIPS_REG_SP]);
- EXPECT_EQ(0x040U, regs[MIPS_REG_PC]);
- EXPECT_EQ(0x220U, regs.sp());
- EXPECT_EQ(0x040U, regs.pc());
-}
-
-TEST_F(RegsStepIfSignalHandlerTest, mips_step_if_signal_handler_rt) {
- uint64_t addr = 0x1000;
- RegsMips regs;
- regs[MIPS_REG_PC] = 0x8000;
- regs[MIPS_REG_SP] = addr;
-
- elf_memory_->SetData64(0x8000, 0x0000000c24021061ULL);
-
- for (uint64_t index = 0; index <= 100; index++) {
- process_memory_.SetData64(addr + index * 8, index * 0x10);
- }
-
- ASSERT_TRUE(regs.StepIfSignalHandler(0x8000, elf_.get(), &process_memory_));
- EXPECT_EQ(0x350U, regs[MIPS_REG_SP]);
- EXPECT_EQ(0x170U, regs[MIPS_REG_PC]);
- EXPECT_EQ(0x350U, regs.sp());
- EXPECT_EQ(0x170U, regs.pc());
-}
-
-TEST_F(RegsStepIfSignalHandlerTest, mips64_step_if_signal_handler) {
- uint64_t addr = 0x1000;
- RegsMips64 regs;
- regs[MIPS64_REG_PC] = 0x8000;
- regs[MIPS64_REG_SP] = addr;
-
- elf_memory_->SetData64(0x8000, 0x0000000c2402145bULL);
-
- for (uint64_t index = 0; index <= 100; index++) {
- process_memory_.SetData64(addr + index * 8, index * 0x10);
- }
-
- ASSERT_TRUE(regs.StepIfSignalHandler(0x8000, elf_.get(), &process_memory_));
- EXPECT_EQ(0x350U, regs[MIPS64_REG_SP]);
- EXPECT_EQ(0x600U, regs[MIPS64_REG_PC]);
- EXPECT_EQ(0x350U, regs.sp());
- EXPECT_EQ(0x600U, regs.pc());
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/RegsTest.cpp b/libunwindstack/tests/RegsTest.cpp
deleted file mode 100644
index acf72de..0000000
--- a/libunwindstack/tests/RegsTest.cpp
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * Copyright (C) 2017 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 <stdint.h>
-
-#include <gtest/gtest.h>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/ElfInterface.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/RegsArm.h>
-#include <unwindstack/RegsArm64.h>
-#include <unwindstack/RegsX86.h>
-#include <unwindstack/RegsX86_64.h>
-#include <unwindstack/RegsMips.h>
-#include <unwindstack/RegsMips64.h>
-
-#include "ElfFake.h"
-#include "MemoryFake.h"
-#include "RegsFake.h"
-
-namespace unwindstack {
-
-class RegsTest : public ::testing::Test {
- protected:
- void SetUp() override {
- memory_ = new MemoryFake;
- elf_.reset(new ElfFake(memory_));
- elf_interface_ = new ElfInterfaceFake(elf_->memory());
- elf_->FakeSetInterface(elf_interface_);
- }
-
- ElfInterfaceFake* elf_interface_;
- MemoryFake* memory_;
- std::unique_ptr<ElfFake> elf_;
-};
-
-TEST_F(RegsTest, regs32) {
- RegsImplFake<uint32_t> regs32(50);
- ASSERT_EQ(50U, regs32.total_regs());
-
- uint32_t* raw = reinterpret_cast<uint32_t*>(regs32.RawData());
- for (size_t i = 0; i < 50; i++) {
- raw[i] = 0xf0000000 + i;
- }
- regs32.set_pc(0xf0120340);
- regs32.set_sp(0xa0ab0cd0);
-
- for (size_t i = 0; i < 50; i++) {
- ASSERT_EQ(0xf0000000U + i, regs32[i]) << "Failed comparing register " << i;
- }
-
- ASSERT_EQ(0xf0120340U, regs32.pc());
- ASSERT_EQ(0xa0ab0cd0U, regs32.sp());
-
- regs32[32] = 10;
- ASSERT_EQ(10U, regs32[32]);
-}
-
-TEST_F(RegsTest, regs64) {
- RegsImplFake<uint64_t> regs64(30);
- ASSERT_EQ(30U, regs64.total_regs());
-
- uint64_t* raw = reinterpret_cast<uint64_t*>(regs64.RawData());
- for (size_t i = 0; i < 30; i++) {
- raw[i] = 0xf123456780000000UL + i;
- }
- regs64.set_pc(0xf123456780102030UL);
- regs64.set_sp(0xa123456780a0b0c0UL);
-
- for (size_t i = 0; i < 30; i++) {
- ASSERT_EQ(0xf123456780000000U + i, regs64[i]) << "Failed reading register " << i;
- }
-
- ASSERT_EQ(0xf123456780102030UL, regs64.pc());
- ASSERT_EQ(0xa123456780a0b0c0UL, regs64.sp());
-
- regs64[8] = 10;
- ASSERT_EQ(10U, regs64[8]);
-}
-
-TEST_F(RegsTest, rel_pc) {
- EXPECT_EQ(4U, GetPcAdjustment(0x10, elf_.get(), ARCH_ARM64));
- EXPECT_EQ(4U, GetPcAdjustment(0x4, elf_.get(), ARCH_ARM64));
- EXPECT_EQ(0U, GetPcAdjustment(0x3, elf_.get(), ARCH_ARM64));
- EXPECT_EQ(0U, GetPcAdjustment(0x2, elf_.get(), ARCH_ARM64));
- EXPECT_EQ(0U, GetPcAdjustment(0x1, elf_.get(), ARCH_ARM64));
- EXPECT_EQ(0U, GetPcAdjustment(0x0, elf_.get(), ARCH_ARM64));
-
- EXPECT_EQ(1U, GetPcAdjustment(0x100, elf_.get(), ARCH_X86));
- EXPECT_EQ(1U, GetPcAdjustment(0x2, elf_.get(), ARCH_X86));
- EXPECT_EQ(1U, GetPcAdjustment(0x1, elf_.get(), ARCH_X86));
- EXPECT_EQ(0U, GetPcAdjustment(0x0, elf_.get(), ARCH_X86));
-
- EXPECT_EQ(1U, GetPcAdjustment(0x100, elf_.get(), ARCH_X86_64));
- EXPECT_EQ(1U, GetPcAdjustment(0x2, elf_.get(), ARCH_X86_64));
- EXPECT_EQ(1U, GetPcAdjustment(0x1, elf_.get(), ARCH_X86_64));
- EXPECT_EQ(0U, GetPcAdjustment(0x0, elf_.get(), ARCH_X86_64));
-
- EXPECT_EQ(8U, GetPcAdjustment(0x10, elf_.get(), ARCH_MIPS));
- EXPECT_EQ(8U, GetPcAdjustment(0x8, elf_.get(), ARCH_MIPS));
- EXPECT_EQ(0U, GetPcAdjustment(0x7, elf_.get(), ARCH_MIPS));
- EXPECT_EQ(0U, GetPcAdjustment(0x6, elf_.get(), ARCH_MIPS));
- EXPECT_EQ(0U, GetPcAdjustment(0x5, elf_.get(), ARCH_MIPS));
- EXPECT_EQ(0U, GetPcAdjustment(0x4, elf_.get(), ARCH_MIPS));
- EXPECT_EQ(0U, GetPcAdjustment(0x3, elf_.get(), ARCH_MIPS));
- EXPECT_EQ(0U, GetPcAdjustment(0x2, elf_.get(), ARCH_MIPS));
- EXPECT_EQ(0U, GetPcAdjustment(0x1, elf_.get(), ARCH_MIPS));
- EXPECT_EQ(0U, GetPcAdjustment(0x0, elf_.get(), ARCH_MIPS));
-
- EXPECT_EQ(8U, GetPcAdjustment(0x10, elf_.get(), ARCH_MIPS64));
- EXPECT_EQ(8U, GetPcAdjustment(0x8, elf_.get(), ARCH_MIPS64));
- EXPECT_EQ(0U, GetPcAdjustment(0x7, elf_.get(), ARCH_MIPS64));
- EXPECT_EQ(0U, GetPcAdjustment(0x6, elf_.get(), ARCH_MIPS64));
- EXPECT_EQ(0U, GetPcAdjustment(0x5, elf_.get(), ARCH_MIPS64));
- EXPECT_EQ(0U, GetPcAdjustment(0x4, elf_.get(), ARCH_MIPS64));
- EXPECT_EQ(0U, GetPcAdjustment(0x3, elf_.get(), ARCH_MIPS64));
- EXPECT_EQ(0U, GetPcAdjustment(0x2, elf_.get(), ARCH_MIPS64));
- EXPECT_EQ(0U, GetPcAdjustment(0x1, elf_.get(), ARCH_MIPS64));
- EXPECT_EQ(0U, GetPcAdjustment(0x0, elf_.get(), ARCH_MIPS64));
-}
-
-TEST_F(RegsTest, rel_pc_arm) {
- // Check fence posts.
- elf_->FakeSetLoadBias(0);
- EXPECT_EQ(2U, GetPcAdjustment(0x5, elf_.get(), ARCH_ARM));
- EXPECT_EQ(2U, GetPcAdjustment(0x4, elf_.get(), ARCH_ARM));
- EXPECT_EQ(2U, GetPcAdjustment(0x3, elf_.get(), ARCH_ARM));
- EXPECT_EQ(2U, GetPcAdjustment(0x2, elf_.get(), ARCH_ARM));
- EXPECT_EQ(0U, GetPcAdjustment(0x1, elf_.get(), ARCH_ARM));
- EXPECT_EQ(0U, GetPcAdjustment(0x0, elf_.get(), ARCH_ARM));
-
- elf_->FakeSetLoadBias(0x100);
- EXPECT_EQ(0U, GetPcAdjustment(0x1, elf_.get(), ARCH_ARM));
- EXPECT_EQ(2U, GetPcAdjustment(0x2, elf_.get(), ARCH_ARM));
- EXPECT_EQ(2U, GetPcAdjustment(0xff, elf_.get(), ARCH_ARM));
- EXPECT_EQ(2U, GetPcAdjustment(0x105, elf_.get(), ARCH_ARM));
- EXPECT_EQ(2U, GetPcAdjustment(0x104, elf_.get(), ARCH_ARM));
- EXPECT_EQ(2U, GetPcAdjustment(0x103, elf_.get(), ARCH_ARM));
- EXPECT_EQ(2U, GetPcAdjustment(0x102, elf_.get(), ARCH_ARM));
- EXPECT_EQ(0U, GetPcAdjustment(0x101, elf_.get(), ARCH_ARM));
- EXPECT_EQ(0U, GetPcAdjustment(0x100, elf_.get(), ARCH_ARM));
-
- // Check thumb instructions handling.
- elf_->FakeSetLoadBias(0);
- memory_->SetData32(0x2000, 0);
- EXPECT_EQ(2U, GetPcAdjustment(0x2005, elf_.get(), ARCH_ARM));
- memory_->SetData32(0x2000, 0xe000f000);
- EXPECT_EQ(4U, GetPcAdjustment(0x2005, elf_.get(), ARCH_ARM));
-
- elf_->FakeSetLoadBias(0x400);
- memory_->SetData32(0x2100, 0);
- EXPECT_EQ(2U, GetPcAdjustment(0x2505, elf_.get(), ARCH_ARM));
- memory_->SetData32(0x2100, 0xf111f111);
- EXPECT_EQ(4U, GetPcAdjustment(0x2505, elf_.get(), ARCH_ARM));
-}
-
-TEST_F(RegsTest, elf_invalid) {
- MapInfo map_info(nullptr, nullptr, 0x1000, 0x2000, 0, 0, "");
- Elf* invalid_elf = new Elf(nullptr);
- map_info.elf.reset(invalid_elf);
-
- EXPECT_EQ(0x500U, invalid_elf->GetRelPc(0x1500, &map_info));
- EXPECT_EQ(2U, GetPcAdjustment(0x500U, invalid_elf, ARCH_ARM));
- EXPECT_EQ(2U, GetPcAdjustment(0x511U, invalid_elf, ARCH_ARM));
-
- EXPECT_EQ(0x600U, invalid_elf->GetRelPc(0x1600, &map_info));
- EXPECT_EQ(4U, GetPcAdjustment(0x600U, invalid_elf, ARCH_ARM64));
-
- EXPECT_EQ(0x700U, invalid_elf->GetRelPc(0x1700, &map_info));
- EXPECT_EQ(1U, GetPcAdjustment(0x700U, invalid_elf, ARCH_X86));
-
- EXPECT_EQ(0x800U, invalid_elf->GetRelPc(0x1800, &map_info));
- EXPECT_EQ(1U, GetPcAdjustment(0x800U, invalid_elf, ARCH_X86_64));
-
- EXPECT_EQ(0x900U, invalid_elf->GetRelPc(0x1900, &map_info));
- EXPECT_EQ(8U, GetPcAdjustment(0x900U, invalid_elf, ARCH_MIPS));
-
- EXPECT_EQ(0xa00U, invalid_elf->GetRelPc(0x1a00, &map_info));
- EXPECT_EQ(8U, GetPcAdjustment(0xa00U, invalid_elf, ARCH_MIPS64));
-}
-
-TEST_F(RegsTest, arm_verify_sp_pc) {
- RegsArm arm;
- uint32_t* regs = reinterpret_cast<uint32_t*>(arm.RawData());
- regs[13] = 0x100;
- regs[15] = 0x200;
- EXPECT_EQ(0x100U, arm.sp());
- EXPECT_EQ(0x200U, arm.pc());
-}
-
-TEST_F(RegsTest, arm64_verify_sp_pc) {
- RegsArm64 arm64;
- uint64_t* regs = reinterpret_cast<uint64_t*>(arm64.RawData());
- regs[31] = 0xb100000000ULL;
- regs[32] = 0xc200000000ULL;
- EXPECT_EQ(0xb100000000U, arm64.sp());
- EXPECT_EQ(0xc200000000U, arm64.pc());
-}
-
-TEST_F(RegsTest, x86_verify_sp_pc) {
- RegsX86 x86;
- uint32_t* regs = reinterpret_cast<uint32_t*>(x86.RawData());
- regs[4] = 0x23450000;
- regs[8] = 0xabcd0000;
- EXPECT_EQ(0x23450000U, x86.sp());
- EXPECT_EQ(0xabcd0000U, x86.pc());
-}
-
-TEST_F(RegsTest, x86_64_verify_sp_pc) {
- RegsX86_64 x86_64;
- uint64_t* regs = reinterpret_cast<uint64_t*>(x86_64.RawData());
- regs[7] = 0x1200000000ULL;
- regs[16] = 0x4900000000ULL;
- EXPECT_EQ(0x1200000000U, x86_64.sp());
- EXPECT_EQ(0x4900000000U, x86_64.pc());
-}
-
-TEST_F(RegsTest, mips_verify_sp_pc) {
- RegsMips mips;
- uint32_t* regs = reinterpret_cast<uint32_t*>(mips.RawData());
- regs[29] = 0x100;
- regs[32] = 0x200;
- EXPECT_EQ(0x100U, mips.sp());
- EXPECT_EQ(0x200U, mips.pc());
-}
-
-TEST_F(RegsTest, mips64_verify_sp_pc) {
- RegsMips64 mips64;
- uint64_t* regs = reinterpret_cast<uint64_t*>(mips64.RawData());
- regs[29] = 0xb100000000ULL;
- regs[32] = 0xc200000000ULL;
- EXPECT_EQ(0xb100000000U, mips64.sp());
- EXPECT_EQ(0xc200000000U, mips64.pc());
-}
-
-TEST_F(RegsTest, arm64_strip_pac_mask) {
- RegsArm64 arm64;
- arm64.SetPseudoRegister(Arm64Reg::ARM64_PREG_RA_SIGN_STATE, 1);
- arm64.SetPACMask(0x007fff8000000000ULL);
- arm64.set_pc(0x0020007214bb3a04ULL);
- EXPECT_EQ(0x0000007214bb3a04ULL, arm64.pc());
-}
-
-TEST_F(RegsTest, machine_type) {
- RegsArm arm_regs;
- EXPECT_EQ(ARCH_ARM, arm_regs.Arch());
-
- RegsArm64 arm64_regs;
- EXPECT_EQ(ARCH_ARM64, arm64_regs.Arch());
-
- RegsX86 x86_regs;
- EXPECT_EQ(ARCH_X86, x86_regs.Arch());
-
- RegsX86_64 x86_64_regs;
- EXPECT_EQ(ARCH_X86_64, x86_64_regs.Arch());
-
- RegsMips mips_regs;
- EXPECT_EQ(ARCH_MIPS, mips_regs.Arch());
-
- RegsMips64 mips64_regs;
- EXPECT_EQ(ARCH_MIPS64, mips64_regs.Arch());
-}
-
-template <typename RegisterType>
-void clone_test(Regs* regs) {
- RegisterType* register_values = reinterpret_cast<RegisterType*>(regs->RawData());
- int num_regs = regs->total_regs();
- for (int i = 0; i < num_regs; ++i) {
- register_values[i] = i;
- }
-
- std::unique_ptr<Regs> clone(regs->Clone());
- ASSERT_EQ(regs->total_regs(), clone->total_regs());
- RegisterType* clone_values = reinterpret_cast<RegisterType*>(clone->RawData());
- for (int i = 0; i < num_regs; ++i) {
- EXPECT_EQ(register_values[i], clone_values[i]);
- EXPECT_NE(®ister_values[i], &clone_values[i]);
- }
-}
-
-TEST_F(RegsTest, clone) {
- std::vector<std::unique_ptr<Regs>> regs;
- regs.emplace_back(new RegsArm());
- regs.emplace_back(new RegsArm64());
- regs.emplace_back(new RegsX86());
- regs.emplace_back(new RegsX86_64());
- regs.emplace_back(new RegsMips());
- regs.emplace_back(new RegsMips64());
-
- for (auto& r : regs) {
- if (r->Is32Bit()) {
- clone_test<uint32_t>(r.get());
- } else {
- clone_test<uint64_t>(r.get());
- }
- }
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/SymbolsTest.cpp b/libunwindstack/tests/SymbolsTest.cpp
deleted file mode 100644
index 9afbeec..0000000
--- a/libunwindstack/tests/SymbolsTest.cpp
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Copyright (C) 2016 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 <elf.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/ptrace.h>
-#include <sys/types.h>
-#include <time.h>
-#include <unistd.h>
-
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/test_utils.h>
-#include <gtest/gtest.h>
-
-#include <unwindstack/Memory.h>
-
-#include "MemoryFake.h"
-#include "Symbols.h"
-
-namespace unwindstack {
-
-template <typename TypeParam>
-class SymbolsTest : public ::testing::Test {
- protected:
- void SetUp() override { memory_.Clear(); }
-
- void InitSym(TypeParam* sym, uint32_t st_value, uint32_t st_size, uint32_t st_name) {
- memset(sym, 0, sizeof(*sym));
- sym->st_info = STT_FUNC;
- sym->st_value = st_value;
- sym->st_size = st_size;
- sym->st_name = st_name;
- sym->st_shndx = SHN_COMMON;
- }
-
- MemoryFake memory_;
-};
-TYPED_TEST_SUITE_P(SymbolsTest);
-
-TYPED_TEST_P(SymbolsTest, function_bounds_check) {
- Symbols symbols(0x1000, sizeof(TypeParam), sizeof(TypeParam), 0x2000, 0x100);
-
- TypeParam sym;
- this->InitSym(&sym, 0x5000, 0x10, 0x40);
- uint64_t offset = 0x1000;
- this->memory_.SetMemory(offset, &sym, sizeof(sym));
-
- std::string fake_name("fake_function");
- this->memory_.SetMemory(0x2040, fake_name.c_str(), fake_name.size() + 1);
-
- std::string name;
- uint64_t func_offset;
- ASSERT_TRUE(symbols.GetName<TypeParam>(0x5000, &this->memory_, &name, &func_offset));
- ASSERT_EQ("fake_function", name);
- ASSERT_EQ(0U, func_offset);
-
- name.clear();
- ASSERT_TRUE(symbols.GetName<TypeParam>(0x500f, &this->memory_, &name, &func_offset));
- ASSERT_EQ("fake_function", name);
- ASSERT_EQ(0xfU, func_offset);
-
- // Check one before and one after the function.
- ASSERT_FALSE(symbols.GetName<TypeParam>(0x4fff, &this->memory_, &name, &func_offset));
- ASSERT_FALSE(symbols.GetName<TypeParam>(0x5010, &this->memory_, &name, &func_offset));
-}
-
-TYPED_TEST_P(SymbolsTest, no_symbol) {
- Symbols symbols(0x1000, sizeof(TypeParam), sizeof(TypeParam), 0x2000, 0x100);
-
- TypeParam sym;
- this->InitSym(&sym, 0x5000, 0x10, 0x40);
- uint64_t offset = 0x1000;
- this->memory_.SetMemory(offset, &sym, sizeof(sym));
-
- std::string fake_name("fake_function");
- this->memory_.SetMemory(0x2040, fake_name.c_str(), fake_name.size() + 1);
-
- // First verify that we can get the name.
- std::string name;
- uint64_t func_offset;
- ASSERT_TRUE(symbols.GetName<TypeParam>(0x5000, &this->memory_, &name, &func_offset));
- ASSERT_EQ("fake_function", name);
- ASSERT_EQ(0U, func_offset);
-
- // Now modify the info field so it's no longer a function.
- sym.st_info = 0;
- this->memory_.SetMemory(offset, &sym, sizeof(sym));
- // Clear the cache to force the symbol data to be re-read.
- symbols.ClearCache();
- ASSERT_FALSE(symbols.GetName<TypeParam>(0x5000, &this->memory_, &name, &func_offset));
-
- // Set the function back, and set the shndx to UNDEF.
- sym.st_info = STT_FUNC;
- sym.st_shndx = SHN_UNDEF;
- this->memory_.SetMemory(offset, &sym, sizeof(sym));
- // Clear the cache to force the symbol data to be re-read.
- symbols.ClearCache();
- ASSERT_FALSE(symbols.GetName<TypeParam>(0x5000, &this->memory_, &name, &func_offset));
-}
-
-TYPED_TEST_P(SymbolsTest, multiple_entries) {
- Symbols symbols(0x1000, sizeof(TypeParam) * 3, sizeof(TypeParam), 0x2000, 0x500);
-
- TypeParam sym;
- uint64_t offset = 0x1000;
- std::string fake_name;
-
- this->InitSym(&sym, 0x5000, 0x10, 0x40);
- this->memory_.SetMemory(offset, &sym, sizeof(sym));
- fake_name = "function_one";
- this->memory_.SetMemory(0x2040, fake_name.c_str(), fake_name.size() + 1);
- offset += sizeof(sym);
-
- this->InitSym(&sym, 0x3004, 0x200, 0x100);
- this->memory_.SetMemory(offset, &sym, sizeof(sym));
- fake_name = "function_two";
- this->memory_.SetMemory(0x2100, fake_name.c_str(), fake_name.size() + 1);
- offset += sizeof(sym);
-
- this->InitSym(&sym, 0xa010, 0x20, 0x230);
- this->memory_.SetMemory(offset, &sym, sizeof(sym));
- fake_name = "function_three";
- this->memory_.SetMemory(0x2230, fake_name.c_str(), fake_name.size() + 1);
-
- std::string name;
- uint64_t func_offset;
- ASSERT_TRUE(symbols.GetName<TypeParam>(0x3005, &this->memory_, &name, &func_offset));
- ASSERT_EQ("function_two", name);
- ASSERT_EQ(1U, func_offset);
-
- name.clear();
- ASSERT_TRUE(symbols.GetName<TypeParam>(0x5004, &this->memory_, &name, &func_offset));
- ASSERT_EQ("function_one", name);
- ASSERT_EQ(4U, func_offset);
-
- name.clear();
- ASSERT_TRUE(symbols.GetName<TypeParam>(0xa011, &this->memory_, &name, &func_offset));
- ASSERT_EQ("function_three", name);
- ASSERT_EQ(1U, func_offset);
-
- // Reget some of the others to verify getting one function name doesn't
- // affect any of the next calls.
- name.clear();
- ASSERT_TRUE(symbols.GetName<TypeParam>(0x5008, &this->memory_, &name, &func_offset));
- ASSERT_EQ("function_one", name);
- ASSERT_EQ(8U, func_offset);
-
- name.clear();
- ASSERT_TRUE(symbols.GetName<TypeParam>(0x3008, &this->memory_, &name, &func_offset));
- ASSERT_EQ("function_two", name);
- ASSERT_EQ(4U, func_offset);
-
- name.clear();
- ASSERT_TRUE(symbols.GetName<TypeParam>(0xa01a, &this->memory_, &name, &func_offset));
- ASSERT_EQ("function_three", name);
- ASSERT_EQ(0xaU, func_offset);
-}
-
-TYPED_TEST_P(SymbolsTest, multiple_entries_nonstandard_size) {
- uint64_t entry_size = sizeof(TypeParam) + 5;
- Symbols symbols(0x1000, entry_size * 3, entry_size, 0x2000, 0x500);
-
- TypeParam sym;
- uint64_t offset = 0x1000;
- std::string fake_name;
-
- this->InitSym(&sym, 0x5000, 0x10, 0x40);
- this->memory_.SetMemoryBlock(offset, entry_size, 0);
- this->memory_.SetMemory(offset, &sym, sizeof(sym));
- fake_name = "function_one";
- this->memory_.SetMemory(0x2040, fake_name.c_str(), fake_name.size() + 1);
- offset += entry_size;
-
- this->InitSym(&sym, 0x3004, 0x200, 0x100);
- this->memory_.SetMemoryBlock(offset, entry_size, 0);
- this->memory_.SetMemory(offset, &sym, sizeof(sym));
- fake_name = "function_two";
- this->memory_.SetMemory(0x2100, fake_name.c_str(), fake_name.size() + 1);
- offset += entry_size;
-
- this->InitSym(&sym, 0xa010, 0x20, 0x230);
- this->memory_.SetMemoryBlock(offset, entry_size, 0);
- this->memory_.SetMemory(offset, &sym, sizeof(sym));
- fake_name = "function_three";
- this->memory_.SetMemory(0x2230, fake_name.c_str(), fake_name.size() + 1);
-
- std::string name;
- uint64_t func_offset;
- ASSERT_TRUE(symbols.GetName<TypeParam>(0x3005, &this->memory_, &name, &func_offset));
- ASSERT_EQ("function_two", name);
- ASSERT_EQ(1U, func_offset);
-
- name.clear();
- ASSERT_TRUE(symbols.GetName<TypeParam>(0x5004, &this->memory_, &name, &func_offset));
- ASSERT_EQ("function_one", name);
- ASSERT_EQ(4U, func_offset);
-
- name.clear();
- ASSERT_TRUE(symbols.GetName<TypeParam>(0xa011, &this->memory_, &name, &func_offset));
- ASSERT_EQ("function_three", name);
- ASSERT_EQ(1U, func_offset);
-}
-
-TYPED_TEST_P(SymbolsTest, symtab_value_out_of_bounds) {
- Symbols symbols_end_at_100(0x1000, sizeof(TypeParam) * 2, sizeof(TypeParam), 0x2000, 0x100);
- Symbols symbols_end_at_200(0x1000, sizeof(TypeParam) * 2, sizeof(TypeParam), 0x2000, 0x200);
-
- TypeParam sym;
- uint64_t offset = 0x1000;
-
- this->InitSym(&sym, 0x5000, 0x10, 0xfb);
- this->memory_.SetMemory(offset, &sym, sizeof(sym));
- offset += sizeof(sym);
-
- this->InitSym(&sym, 0x3000, 0x10, 0x100);
- this->memory_.SetMemory(offset, &sym, sizeof(sym));
-
- // Put the name across the end of the tab.
- std::string fake_name("fake_function");
- this->memory_.SetMemory(0x20fb, fake_name.c_str(), fake_name.size() + 1);
-
- std::string name;
- uint64_t func_offset;
- // Verify that we can get the function name properly for both entries.
- ASSERT_TRUE(symbols_end_at_200.GetName<TypeParam>(0x5000, &this->memory_, &name, &func_offset));
- ASSERT_EQ("fake_function", name);
- ASSERT_EQ(0U, func_offset);
- ASSERT_TRUE(symbols_end_at_200.GetName<TypeParam>(0x3000, &this->memory_, &name, &func_offset));
- ASSERT_EQ("function", name);
- ASSERT_EQ(0U, func_offset);
-
- // Now use the symbol table that ends at 0x100.
- ASSERT_FALSE(symbols_end_at_100.GetName<TypeParam>(0x5000, &this->memory_, &name, &func_offset));
- ASSERT_FALSE(symbols_end_at_100.GetName<TypeParam>(0x3000, &this->memory_, &name, &func_offset));
-}
-
-// Verify the entire func table is cached.
-TYPED_TEST_P(SymbolsTest, symtab_read_cached) {
- Symbols symbols(0x1000, 3 * sizeof(TypeParam), sizeof(TypeParam), 0xa000, 0x1000);
-
- TypeParam sym;
- uint64_t offset = 0x1000;
-
- // Make sure that these entries are not in ascending order.
- this->InitSym(&sym, 0x5000, 0x10, 0x100);
- this->memory_.SetMemory(offset, &sym, sizeof(sym));
- offset += sizeof(sym);
-
- this->InitSym(&sym, 0x2000, 0x300, 0x200);
- this->memory_.SetMemory(offset, &sym, sizeof(sym));
- offset += sizeof(sym);
-
- this->InitSym(&sym, 0x1000, 0x100, 0x300);
- this->memory_.SetMemory(offset, &sym, sizeof(sym));
- offset += sizeof(sym);
-
- // Do call that should cache all of the entries (except the string data).
- std::string name;
- uint64_t func_offset;
- ASSERT_FALSE(symbols.GetName<TypeParam>(0x5000, &this->memory_, &name, &func_offset));
- ASSERT_FALSE(symbols.GetName<TypeParam>(0x2000, &this->memory_, &name, &func_offset));
- ASSERT_FALSE(symbols.GetName<TypeParam>(0x1000, &this->memory_, &name, &func_offset));
- this->memory_.Clear();
- ASSERT_FALSE(symbols.GetName<TypeParam>(0x6000, &this->memory_, &name, &func_offset));
-
- // Clear the memory and only put the symbol data string data in memory.
- this->memory_.Clear();
-
- std::string fake_name;
- fake_name = "first_entry";
- this->memory_.SetMemory(0xa100, fake_name.c_str(), fake_name.size() + 1);
- fake_name = "second_entry";
- this->memory_.SetMemory(0xa200, fake_name.c_str(), fake_name.size() + 1);
- fake_name = "third_entry";
- this->memory_.SetMemory(0xa300, fake_name.c_str(), fake_name.size() + 1);
-
- ASSERT_TRUE(symbols.GetName<TypeParam>(0x5001, &this->memory_, &name, &func_offset));
- ASSERT_EQ("first_entry", name);
- ASSERT_EQ(1U, func_offset);
-
- ASSERT_TRUE(symbols.GetName<TypeParam>(0x2002, &this->memory_, &name, &func_offset));
- ASSERT_EQ("second_entry", name);
- ASSERT_EQ(2U, func_offset);
-
- ASSERT_TRUE(symbols.GetName<TypeParam>(0x1003, &this->memory_, &name, &func_offset));
- ASSERT_EQ("third_entry", name);
- ASSERT_EQ(3U, func_offset);
-}
-
-TYPED_TEST_P(SymbolsTest, get_global) {
- uint64_t start_offset = 0x1000;
- uint64_t str_offset = 0xa000;
- Symbols symbols(start_offset, 4 * sizeof(TypeParam), sizeof(TypeParam), str_offset, 0x1000);
-
- TypeParam sym;
- memset(&sym, 0, sizeof(sym));
- sym.st_shndx = SHN_COMMON;
- sym.st_info = STT_OBJECT | (STB_GLOBAL << 4);
- sym.st_name = 0x100;
- this->memory_.SetMemory(start_offset, &sym, sizeof(sym));
- this->memory_.SetMemory(str_offset + 0x100, "global_0");
-
- start_offset += sizeof(sym);
- memset(&sym, 0, sizeof(sym));
- sym.st_shndx = SHN_COMMON;
- sym.st_info = STT_FUNC;
- sym.st_name = 0x200;
- sym.st_value = 0x10000;
- sym.st_size = 0x100;
- this->memory_.SetMemory(start_offset, &sym, sizeof(sym));
- this->memory_.SetMemory(str_offset + 0x200, "function_0");
-
- start_offset += sizeof(sym);
- memset(&sym, 0, sizeof(sym));
- sym.st_shndx = SHN_COMMON;
- sym.st_info = STT_OBJECT | (STB_GLOBAL << 4);
- sym.st_name = 0x300;
- this->memory_.SetMemory(start_offset, &sym, sizeof(sym));
- this->memory_.SetMemory(str_offset + 0x300, "global_1");
-
- start_offset += sizeof(sym);
- memset(&sym, 0, sizeof(sym));
- sym.st_shndx = SHN_COMMON;
- sym.st_info = STT_FUNC;
- sym.st_name = 0x400;
- sym.st_value = 0x12000;
- sym.st_size = 0x100;
- this->memory_.SetMemory(start_offset, &sym, sizeof(sym));
- this->memory_.SetMemory(str_offset + 0x400, "function_1");
-
- uint64_t offset;
- EXPECT_TRUE(symbols.GetGlobal<TypeParam>(&this->memory_, "global_0", &offset));
- EXPECT_TRUE(symbols.GetGlobal<TypeParam>(&this->memory_, "global_1", &offset));
- EXPECT_TRUE(symbols.GetGlobal<TypeParam>(&this->memory_, "global_0", &offset));
- EXPECT_TRUE(symbols.GetGlobal<TypeParam>(&this->memory_, "global_1", &offset));
-
- EXPECT_FALSE(symbols.GetGlobal<TypeParam>(&this->memory_, "function_0", &offset));
- EXPECT_FALSE(symbols.GetGlobal<TypeParam>(&this->memory_, "function_1", &offset));
-
- std::string name;
- EXPECT_TRUE(symbols.GetName<TypeParam>(0x10002, &this->memory_, &name, &offset));
- EXPECT_EQ("function_0", name);
- EXPECT_EQ(2U, offset);
-
- EXPECT_TRUE(symbols.GetName<TypeParam>(0x12004, &this->memory_, &name, &offset));
- EXPECT_EQ("function_1", name);
- EXPECT_EQ(4U, offset);
-}
-
-REGISTER_TYPED_TEST_SUITE_P(SymbolsTest, function_bounds_check, no_symbol, multiple_entries,
- multiple_entries_nonstandard_size, symtab_value_out_of_bounds,
- symtab_read_cached, get_global);
-
-typedef ::testing::Types<Elf32_Sym, Elf64_Sym> SymbolsTestTypes;
-INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, SymbolsTest, SymbolsTestTypes);
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/TestLocal.cpp b/libunwindstack/tests/TestLocal.cpp
deleted file mode 100644
index fa0baff..0000000
--- a/libunwindstack/tests/TestLocal.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2018 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 <unwindstack/LocalUnwinder.h>
-
-#include <vector>
-
-extern "C" void TestlibLevel4(void* unwinder_data, void* frame_data) {
- unwindstack::LocalUnwinder* unwinder =
- reinterpret_cast<unwindstack::LocalUnwinder*>(unwinder_data);
- std::vector<unwindstack::LocalFrameData>* frame_info =
- reinterpret_cast<std::vector<unwindstack::LocalFrameData>*>(frame_data);
- unwinder->Unwind(frame_info, 256);
-}
-
-extern "C" void TestlibLevel3(void* unwinder_data, void* frame_data) {
- TestlibLevel4(unwinder_data, frame_data);
-}
-
-extern "C" void TestlibLevel2(void* unwinder_data, void* frame_data) {
- TestlibLevel3(unwinder_data, frame_data);
-}
-
-extern "C" void TestlibLevel1(void* unwinder_data, void* frame_data) {
- TestlibLevel2(unwinder_data, frame_data);
-}
diff --git a/libunwindstack/tests/TestUtils.cpp b/libunwindstack/tests/TestUtils.cpp
deleted file mode 100644
index e76f5f8..0000000
--- a/libunwindstack/tests/TestUtils.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2019 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 <malloc.h>
-#include <stdint.h>
-
-#include <gtest/gtest.h>
-
-namespace unwindstack {
-
-void TestCheckForLeaks(void (*unwind_func)(void*), void* data) {
- static constexpr size_t kNumLeakLoops = 200;
- static constexpr size_t kMaxAllowedLeakBytes = 32 * 1024;
-
- size_t first_allocated_bytes = 0;
- size_t last_allocated_bytes = 0;
- for (size_t i = 0; i < kNumLeakLoops; i++) {
- unwind_func(data);
-
- size_t allocated_bytes = mallinfo().uordblks;
- if (first_allocated_bytes == 0) {
- first_allocated_bytes = allocated_bytes;
- } else if (last_allocated_bytes > first_allocated_bytes) {
- // Check that the memory did not increase too much over the first loop.
- ASSERT_LE(last_allocated_bytes - first_allocated_bytes, kMaxAllowedLeakBytes);
- }
- last_allocated_bytes = allocated_bytes;
- }
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/TestUtils.h b/libunwindstack/tests/TestUtils.h
deleted file mode 100644
index 0685006..0000000
--- a/libunwindstack/tests/TestUtils.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef _LIBUNWINDSTACK_TESTS_TEST_UTILS_H
-#define _LIBUNWINDSTACK_TESTS_TEST_UTILS_H
-
-#include <signal.h>
-#include <sys/ptrace.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-namespace unwindstack {
-
-class TestScopedPidReaper {
- public:
- TestScopedPidReaper(pid_t pid) : pid_(pid) {}
- ~TestScopedPidReaper() {
- kill(pid_, SIGKILL);
- waitpid(pid_, nullptr, 0);
- }
-
- private:
- pid_t pid_;
-};
-
-inline bool TestQuiescePid(pid_t pid) {
- siginfo_t si;
- bool ready = false;
- // Wait for up to 5 seconds.
- for (size_t i = 0; i < 5000; i++) {
- if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
- ready = true;
- break;
- }
- usleep(1000);
- }
- return ready;
-}
-
-inline bool TestAttach(pid_t pid) {
- if (ptrace(PTRACE_ATTACH, pid, 0, 0) == -1) {
- return false;
- }
-
- return TestQuiescePid(pid);
-}
-
-inline bool TestDetach(pid_t pid) {
- return ptrace(PTRACE_DETACH, pid, 0, 0) == 0;
-}
-
-void TestCheckForLeaks(void (*unwind_func)(void*), void* data);
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_TESTS_TEST_UTILS_H
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp
deleted file mode 100644
index ab427b5..0000000
--- a/libunwindstack/tests/UnwindOfflineTest.cpp
+++ /dev/null
@@ -1,1893 +0,0 @@
-/*
- * Copyright (C) 2017 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 <inttypes.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/mman.h>
-#include <unistd.h>
-
-#include <gtest/gtest.h>
-
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-#include <android-base/file.h>
-
-#include <unwindstack/JitDebug.h>
-#include <unwindstack/MachineArm.h>
-#include <unwindstack/MachineArm64.h>
-#include <unwindstack/MachineX86.h>
-#include <unwindstack/MachineX86_64.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/RegsArm.h>
-#include <unwindstack/RegsArm64.h>
-#include <unwindstack/RegsX86.h>
-#include <unwindstack/RegsX86_64.h>
-#include <unwindstack/Unwinder.h>
-
-#include "ElfTestUtils.h"
-#include "MemoryOffline.h"
-#include "TestUtils.h"
-
-namespace unwindstack {
-
-static void AddMemory(std::string file_name, MemoryOfflineParts* parts) {
- MemoryOffline* memory = new MemoryOffline;
- ASSERT_TRUE(memory->Init(file_name.c_str(), 0));
- parts->Add(memory);
-}
-
-class UnwindOfflineTest : public ::testing::Test {
- protected:
- void TearDown() override {
- if (cwd_ != nullptr) {
- ASSERT_EQ(0, chdir(cwd_));
- }
- free(cwd_);
- }
-
- void Init(const char* file_dir, ArchEnum arch, bool add_stack = true) {
- dir_ = TestGetFileDirectory() + "offline/" + file_dir;
-
- std::string data;
- ASSERT_TRUE(android::base::ReadFileToString((dir_ + "maps.txt"), &data));
-
- maps_.reset(new BufferMaps(data.c_str()));
- ASSERT_TRUE(maps_->Parse());
-
- if (add_stack) {
- std::string stack_name(dir_ + "stack.data");
- struct stat st;
- if (stat(stack_name.c_str(), &st) == 0 && S_ISREG(st.st_mode)) {
- std::unique_ptr<MemoryOffline> stack_memory(new MemoryOffline);
- ASSERT_TRUE(stack_memory->Init((dir_ + "stack.data").c_str(), 0));
- process_memory_.reset(stack_memory.release());
- } else {
- std::unique_ptr<MemoryOfflineParts> stack_memory(new MemoryOfflineParts);
- for (size_t i = 0;; i++) {
- stack_name = dir_ + "stack" + std::to_string(i) + ".data";
- if (stat(stack_name.c_str(), &st) == -1 || !S_ISREG(st.st_mode)) {
- ASSERT_TRUE(i != 0) << "No stack data files found.";
- break;
- }
- AddMemory(stack_name, stack_memory.get());
- }
- process_memory_.reset(stack_memory.release());
- }
- }
-
- switch (arch) {
- case ARCH_ARM: {
- RegsArm* regs = new RegsArm;
- regs_.reset(regs);
- ReadRegs<uint32_t>(regs, arm_regs_);
- break;
- }
- case ARCH_ARM64: {
- RegsArm64* regs = new RegsArm64;
- regs_.reset(regs);
- ReadRegs<uint64_t>(regs, arm64_regs_);
- break;
- }
- case ARCH_X86: {
- RegsX86* regs = new RegsX86;
- regs_.reset(regs);
- ReadRegs<uint32_t>(regs, x86_regs_);
- break;
- }
- case ARCH_X86_64: {
- RegsX86_64* regs = new RegsX86_64;
- regs_.reset(regs);
- ReadRegs<uint64_t>(regs, x86_64_regs_);
- break;
- }
- default:
- ASSERT_TRUE(false) << "Unknown arch " << std::to_string(arch);
- }
- cwd_ = getcwd(nullptr, 0);
- // Make dir_ an absolute directory.
- if (dir_.empty() || dir_[0] != '/') {
- dir_ = std::string(cwd_) + '/' + dir_;
- }
- ASSERT_EQ(0, chdir(dir_.c_str()));
- }
-
- template <typename AddressType>
- void ReadRegs(RegsImpl<AddressType>* regs,
- const std::unordered_map<std::string, uint32_t>& name_to_reg) {
- FILE* fp = fopen((dir_ + "regs.txt").c_str(), "r");
- ASSERT_TRUE(fp != nullptr);
- while (!feof(fp)) {
- uint64_t value;
- char reg_name[100];
- ASSERT_EQ(2, fscanf(fp, "%s %" SCNx64 "\n", reg_name, &value));
- std::string name(reg_name);
- if (!name.empty()) {
- // Remove the : from the end.
- name.resize(name.size() - 1);
- }
- auto entry = name_to_reg.find(name);
- ASSERT_TRUE(entry != name_to_reg.end()) << "Unknown register named " << name;
- (*regs)[entry->second] = value;
- }
- fclose(fp);
- }
-
- static std::unordered_map<std::string, uint32_t> arm_regs_;
- static std::unordered_map<std::string, uint32_t> arm64_regs_;
- static std::unordered_map<std::string, uint32_t> x86_regs_;
- static std::unordered_map<std::string, uint32_t> x86_64_regs_;
-
- char* cwd_ = nullptr;
- std::string dir_;
- std::unique_ptr<Regs> regs_;
- std::unique_ptr<Maps> maps_;
- std::shared_ptr<Memory> process_memory_;
-};
-
-std::unordered_map<std::string, uint32_t> UnwindOfflineTest::arm_regs_ = {
- {"r0", ARM_REG_R0}, {"r1", ARM_REG_R1}, {"r2", ARM_REG_R2}, {"r3", ARM_REG_R3},
- {"r4", ARM_REG_R4}, {"r5", ARM_REG_R5}, {"r6", ARM_REG_R6}, {"r7", ARM_REG_R7},
- {"r8", ARM_REG_R8}, {"r9", ARM_REG_R9}, {"r10", ARM_REG_R10}, {"r11", ARM_REG_R11},
- {"ip", ARM_REG_R12}, {"sp", ARM_REG_SP}, {"lr", ARM_REG_LR}, {"pc", ARM_REG_PC},
-};
-
-std::unordered_map<std::string, uint32_t> UnwindOfflineTest::arm64_regs_ = {
- {"x0", ARM64_REG_R0}, {"x1", ARM64_REG_R1}, {"x2", ARM64_REG_R2},
- {"x3", ARM64_REG_R3}, {"x4", ARM64_REG_R4}, {"x5", ARM64_REG_R5},
- {"x6", ARM64_REG_R6}, {"x7", ARM64_REG_R7}, {"x8", ARM64_REG_R8},
- {"x9", ARM64_REG_R9}, {"x10", ARM64_REG_R10}, {"x11", ARM64_REG_R11},
- {"x12", ARM64_REG_R12}, {"x13", ARM64_REG_R13}, {"x14", ARM64_REG_R14},
- {"x15", ARM64_REG_R15}, {"x16", ARM64_REG_R16}, {"x17", ARM64_REG_R17},
- {"x18", ARM64_REG_R18}, {"x19", ARM64_REG_R19}, {"x20", ARM64_REG_R20},
- {"x21", ARM64_REG_R21}, {"x22", ARM64_REG_R22}, {"x23", ARM64_REG_R23},
- {"x24", ARM64_REG_R24}, {"x25", ARM64_REG_R25}, {"x26", ARM64_REG_R26},
- {"x27", ARM64_REG_R27}, {"x28", ARM64_REG_R28}, {"x29", ARM64_REG_R29},
- {"sp", ARM64_REG_SP}, {"lr", ARM64_REG_LR}, {"pc", ARM64_REG_PC},
- {"pst", ARM64_REG_PSTATE},
-};
-
-std::unordered_map<std::string, uint32_t> UnwindOfflineTest::x86_regs_ = {
- {"eax", X86_REG_EAX}, {"ebx", X86_REG_EBX}, {"ecx", X86_REG_ECX},
- {"edx", X86_REG_EDX}, {"ebp", X86_REG_EBP}, {"edi", X86_REG_EDI},
- {"esi", X86_REG_ESI}, {"esp", X86_REG_ESP}, {"eip", X86_REG_EIP},
-};
-
-std::unordered_map<std::string, uint32_t> UnwindOfflineTest::x86_64_regs_ = {
- {"rax", X86_64_REG_RAX}, {"rbx", X86_64_REG_RBX}, {"rcx", X86_64_REG_RCX},
- {"rdx", X86_64_REG_RDX}, {"r8", X86_64_REG_R8}, {"r9", X86_64_REG_R9},
- {"r10", X86_64_REG_R10}, {"r11", X86_64_REG_R11}, {"r12", X86_64_REG_R12},
- {"r13", X86_64_REG_R13}, {"r14", X86_64_REG_R14}, {"r15", X86_64_REG_R15},
- {"rdi", X86_64_REG_RDI}, {"rsi", X86_64_REG_RSI}, {"rbp", X86_64_REG_RBP},
- {"rsp", X86_64_REG_RSP}, {"rip", X86_64_REG_RIP},
-};
-
-static std::string DumpFrames(Unwinder& unwinder) {
- std::string str;
- for (size_t i = 0; i < unwinder.NumFrames(); i++) {
- str += unwinder.FormatFrame(i) + "\n";
- }
- return str;
-}
-
-TEST_F(UnwindOfflineTest, pc_straddle_arm) {
- ASSERT_NO_FATAL_FAILURE(Init("straddle_arm/", ARCH_ARM));
-
- std::unique_ptr<Regs> regs_copy(regs_->Clone());
- Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
- unwinder.Unwind();
-
- std::string frame_info(DumpFrames(unwinder));
- ASSERT_EQ(4U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
- EXPECT_EQ(
- " #00 pc 0001a9f8 libc.so (abort+64)\n"
- " #01 pc 00006a1b libbase.so (android::base::DefaultAborter(char const*)+6)\n"
- " #02 pc 00007441 libbase.so (android::base::LogMessage::~LogMessage()+748)\n"
- " #03 pc 00015147 /does/not/exist/libhidlbase.so\n",
- frame_info);
- EXPECT_EQ(0xf31ea9f8U, unwinder.frames()[0].pc);
- EXPECT_EQ(0xe9c866f8U, unwinder.frames()[0].sp);
- EXPECT_EQ(0xf2da0a1bU, unwinder.frames()[1].pc);
- EXPECT_EQ(0xe9c86728U, unwinder.frames()[1].sp);
- EXPECT_EQ(0xf2da1441U, unwinder.frames()[2].pc);
- EXPECT_EQ(0xe9c86730U, unwinder.frames()[2].sp);
- EXPECT_EQ(0xf3367147U, unwinder.frames()[3].pc);
- EXPECT_EQ(0xe9c86778U, unwinder.frames()[3].sp);
-
- // Display build ids now.
- unwinder.SetRegs(regs_copy.get());
- unwinder.SetDisplayBuildID(true);
- unwinder.Unwind();
-
- frame_info = DumpFrames(unwinder);
- ASSERT_EQ(4U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
- EXPECT_EQ(
- " #00 pc 0001a9f8 libc.so (abort+64) (BuildId: 2dd0d4ba881322a0edabeed94808048c)\n"
- " #01 pc 00006a1b libbase.so (android::base::DefaultAborter(char const*)+6) (BuildId: "
- "ed43842c239cac1a618e600ea91c4cbd)\n"
- " #02 pc 00007441 libbase.so (android::base::LogMessage::~LogMessage()+748) (BuildId: "
- "ed43842c239cac1a618e600ea91c4cbd)\n"
- " #03 pc 00015147 /does/not/exist/libhidlbase.so\n",
- frame_info);
-}
-
-TEST_F(UnwindOfflineTest, pc_in_gnu_debugdata_arm) {
- ASSERT_NO_FATAL_FAILURE(Init("gnu_debugdata_arm/", ARCH_ARM));
-
- Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
- unwinder.Unwind();
-
- std::string frame_info(DumpFrames(unwinder));
- ASSERT_EQ(2U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
- EXPECT_EQ(
- " #00 pc 0006dc49 libandroid_runtime.so "
- "(android::AndroidRuntime::javaThreadShell(void*)+80)\n"
- " #01 pc 0006dce5 libandroid_runtime.so "
- "(android::AndroidRuntime::javaCreateThreadEtc(int (*)(void*), void*, char const*, int, "
- "unsigned int, void**))\n",
- frame_info);
- EXPECT_EQ(0xf1f6dc49U, unwinder.frames()[0].pc);
- EXPECT_EQ(0xd8fe6930U, unwinder.frames()[0].sp);
- EXPECT_EQ(0xf1f6dce5U, unwinder.frames()[1].pc);
- EXPECT_EQ(0xd8fe6958U, unwinder.frames()[1].sp);
-}
-
-TEST_F(UnwindOfflineTest, pc_straddle_arm64) {
- ASSERT_NO_FATAL_FAILURE(Init("straddle_arm64/", ARCH_ARM64));
-
- Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
- unwinder.Unwind();
-
- std::string frame_info(DumpFrames(unwinder));
- ASSERT_EQ(6U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
- EXPECT_EQ(
- " #00 pc 0000000000429fd8 libunwindstack_test (SignalInnerFunction+24)\n"
- " #01 pc 000000000042a078 libunwindstack_test (SignalMiddleFunction+8)\n"
- " #02 pc 000000000042a08c libunwindstack_test (SignalOuterFunction+8)\n"
- " #03 pc 000000000042d8fc libunwindstack_test "
- "(unwindstack::RemoteThroughSignal(int, unsigned int)+20)\n"
- " #04 pc 000000000042d8d8 libunwindstack_test "
- "(unwindstack::UnwindTest_remote_through_signal_Test::TestBody()+32)\n"
- " #05 pc 0000000000455d70 libunwindstack_test (testing::Test::Run()+392)\n",
- frame_info);
- EXPECT_EQ(0x64d09d4fd8U, unwinder.frames()[0].pc);
- EXPECT_EQ(0x7fe0d84040U, unwinder.frames()[0].sp);
- EXPECT_EQ(0x64d09d5078U, unwinder.frames()[1].pc);
- EXPECT_EQ(0x7fe0d84070U, unwinder.frames()[1].sp);
- EXPECT_EQ(0x64d09d508cU, unwinder.frames()[2].pc);
- EXPECT_EQ(0x7fe0d84080U, unwinder.frames()[2].sp);
- EXPECT_EQ(0x64d09d88fcU, unwinder.frames()[3].pc);
- EXPECT_EQ(0x7fe0d84090U, unwinder.frames()[3].sp);
- EXPECT_EQ(0x64d09d88d8U, unwinder.frames()[4].pc);
- EXPECT_EQ(0x7fe0d840f0U, unwinder.frames()[4].sp);
- EXPECT_EQ(0x64d0a00d70U, unwinder.frames()[5].pc);
- EXPECT_EQ(0x7fe0d84110U, unwinder.frames()[5].sp);
-}
-
-TEST_F(UnwindOfflineTest, jit_debug_x86) {
- ASSERT_NO_FATAL_FAILURE(Init("jit_debug_x86/", ARCH_X86));
-
- MemoryOfflineParts* memory = new MemoryOfflineParts;
- AddMemory(dir_ + "descriptor.data", memory);
- AddMemory(dir_ + "stack.data", memory);
- for (size_t i = 0; i < 7; i++) {
- AddMemory(dir_ + "entry" + std::to_string(i) + ".data", memory);
- AddMemory(dir_ + "jit" + std::to_string(i) + ".data", memory);
- }
- process_memory_.reset(memory);
-
- JitDebug jit_debug(process_memory_);
- Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
- unwinder.SetJitDebug(&jit_debug);
- unwinder.Unwind();
-
- std::string frame_info(DumpFrames(unwinder));
- ASSERT_EQ(69U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
- EXPECT_EQ(
- " #00 pc 00068fb8 libarttestd.so (art::CauseSegfault()+72)\n"
- " #01 pc 00067f00 libarttestd.so (Java_Main_unwindInProcess+10032)\n"
- " #02 pc 000021a8 137-cfi.odex (boolean Main.unwindInProcess(boolean, int, "
- "boolean)+136)\n"
- " #03 pc 0000fe80 anonymous:ee74c000 (boolean Main.bar(boolean)+64)\n"
- " #04 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n"
- " #05 pc 00146ab5 libartd.so "
- "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
- "const*)+885)\n"
- " #06 pc 0039cf0d libartd.so "
- "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
- "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
- " #07 pc 00392552 libartd.so "
- "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
- "art::ShadowFrame&, art::JValue, bool)+354)\n"
- " #08 pc 0039399a libartd.so "
- "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
- "const&, art::ShadowFrame*)+234)\n"
- " #09 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
- " #10 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
- " #11 pc 0000fe03 anonymous:ee74c000 (int Main.compare(Main, Main)+51)\n"
- " #12 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n"
- " #13 pc 00146ab5 libartd.so "
- "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
- "const*)+885)\n"
- " #14 pc 0039cf0d libartd.so "
- "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
- "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
- " #15 pc 00392552 libartd.so "
- "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
- "art::ShadowFrame&, art::JValue, bool)+354)\n"
- " #16 pc 0039399a libartd.so "
- "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
- "const&, art::ShadowFrame*)+234)\n"
- " #17 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
- " #18 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
- " #19 pc 0000fd3b anonymous:ee74c000 (int Main.compare(java.lang.Object, "
- "java.lang.Object)+107)\n"
- " #20 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n"
- " #21 pc 00146ab5 libartd.so "
- "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
- "const*)+885)\n"
- " #22 pc 0039cf0d libartd.so "
- "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
- "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
- " #23 pc 00392552 libartd.so "
- "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
- "art::ShadowFrame&, art::JValue, bool)+354)\n"
- " #24 pc 0039399a libartd.so "
- "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
- "const&, art::ShadowFrame*)+234)\n"
- " #25 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
- " #26 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
- " #27 pc 0000fbdb anonymous:ee74c000 (int "
- "java.util.Arrays.binarySearch0(java.lang.Object[], int, int, java.lang.Object, "
- "java.util.Comparator)+331)\n"
- " #28 pc 006ad6a2 libartd.so (art_quick_invoke_static_stub+418)\n"
- " #29 pc 00146acb libartd.so "
- "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
- "const*)+907)\n"
- " #30 pc 0039cf0d libartd.so "
- "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
- "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
- " #31 pc 00392552 libartd.so "
- "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
- "art::ShadowFrame&, art::JValue, bool)+354)\n"
- " #32 pc 0039399a libartd.so "
- "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
- "const&, art::ShadowFrame*)+234)\n"
- " #33 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
- " #34 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
- " #35 pc 0000f624 anonymous:ee74c000 (boolean Main.foo()+164)\n"
- " #36 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n"
- " #37 pc 00146ab5 libartd.so "
- "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
- "const*)+885)\n"
- " #38 pc 0039cf0d libartd.so "
- "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
- "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
- " #39 pc 00392552 libartd.so "
- "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
- "art::ShadowFrame&, art::JValue, bool)+354)\n"
- " #40 pc 0039399a libartd.so "
- "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
- "const&, art::ShadowFrame*)+234)\n"
- " #41 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
- " #42 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
- " #43 pc 0000eedb anonymous:ee74c000 (void Main.runPrimary()+59)\n"
- " #44 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n"
- " #45 pc 00146ab5 libartd.so "
- "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
- "const*)+885)\n"
- " #46 pc 0039cf0d libartd.so "
- "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
- "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
- " #47 pc 00392552 libartd.so "
- "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
- "art::ShadowFrame&, art::JValue, bool)+354)\n"
- " #48 pc 0039399a libartd.so "
- "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
- "const&, art::ShadowFrame*)+234)\n"
- " #49 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
- " #50 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
- " #51 pc 0000ac21 anonymous:ee74c000 (void Main.main(java.lang.String[])+97)\n"
- " #52 pc 006ad6a2 libartd.so (art_quick_invoke_static_stub+418)\n"
- " #53 pc 00146acb libartd.so "
- "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
- "const*)+907)\n"
- " #54 pc 0039cf0d libartd.so "
- "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
- "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
- " #55 pc 00392552 libartd.so "
- "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
- "art::ShadowFrame&, art::JValue, bool)+354)\n"
- " #56 pc 0039399a libartd.so "
- "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
- "const&, art::ShadowFrame*)+234)\n"
- " #57 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
- " #58 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
- " #59 pc 006ad6a2 libartd.so (art_quick_invoke_static_stub+418)\n"
- " #60 pc 00146acb libartd.so "
- "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
- "const*)+907)\n"
- " #61 pc 005aac95 libartd.so "
- "(art::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, "
- "art::ArgArray*, art::JValue*, char const*)+85)\n"
- " #62 pc 005aab5a libartd.so "
- "(art::InvokeWithVarArgs(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, "
- "_jmethodID*, char*)+362)\n"
- " #63 pc 0048a3dd libartd.so "
- "(art::JNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, char*)+125)\n"
- " #64 pc 0018448c libartd.so "
- "(art::CheckJNI::CallMethodV(char const*, _JNIEnv*, _jobject*, _jclass*, _jmethodID*, char*, "
- "art::Primitive::Type, art::InvokeType)+1964)\n"
- " #65 pc 0017cf06 libartd.so "
- "(art::CheckJNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, char*)+70)\n"
- " #66 pc 00001d8c dalvikvm32 "
- "(_JNIEnv::CallStaticVoidMethod(_jclass*, _jmethodID*, ...)+60)\n"
- " #67 pc 00001a80 dalvikvm32 (main+1312)\n"
- " #68 pc 00018275 libc.so\n",
- frame_info);
- EXPECT_EQ(0xeb89bfb8U, unwinder.frames()[0].pc);
- EXPECT_EQ(0xffeb5280U, unwinder.frames()[0].sp);
- EXPECT_EQ(0xeb89af00U, unwinder.frames()[1].pc);
- EXPECT_EQ(0xffeb52a0U, unwinder.frames()[1].sp);
- EXPECT_EQ(0xec6061a8U, unwinder.frames()[2].pc);
- EXPECT_EQ(0xffeb5ce0U, unwinder.frames()[2].sp);
- EXPECT_EQ(0xee75be80U, unwinder.frames()[3].pc);
- EXPECT_EQ(0xffeb5d30U, unwinder.frames()[3].sp);
- EXPECT_EQ(0xf728e4d2U, unwinder.frames()[4].pc);
- EXPECT_EQ(0xffeb5d60U, unwinder.frames()[4].sp);
- EXPECT_EQ(0xf6d27ab5U, unwinder.frames()[5].pc);
- EXPECT_EQ(0xffeb5d80U, unwinder.frames()[5].sp);
- EXPECT_EQ(0xf6f7df0dU, unwinder.frames()[6].pc);
- EXPECT_EQ(0xffeb5e20U, unwinder.frames()[6].sp);
- EXPECT_EQ(0xf6f73552U, unwinder.frames()[7].pc);
- EXPECT_EQ(0xffeb5ec0U, unwinder.frames()[7].sp);
- EXPECT_EQ(0xf6f7499aU, unwinder.frames()[8].pc);
- EXPECT_EQ(0xffeb5f40U, unwinder.frames()[8].sp);
- EXPECT_EQ(0xf7265362U, unwinder.frames()[9].pc);
- EXPECT_EQ(0xffeb5fb0U, unwinder.frames()[9].sp);
- EXPECT_EQ(0xf72945bdU, unwinder.frames()[10].pc);
- EXPECT_EQ(0xffeb6110U, unwinder.frames()[10].sp);
- EXPECT_EQ(0xee75be03U, unwinder.frames()[11].pc);
- EXPECT_EQ(0xffeb6160U, unwinder.frames()[11].sp);
- EXPECT_EQ(0xf728e4d2U, unwinder.frames()[12].pc);
- EXPECT_EQ(0xffeb6180U, unwinder.frames()[12].sp);
- EXPECT_EQ(0xf6d27ab5U, unwinder.frames()[13].pc);
- EXPECT_EQ(0xffeb61b0U, unwinder.frames()[13].sp);
- EXPECT_EQ(0xf6f7df0dU, unwinder.frames()[14].pc);
- EXPECT_EQ(0xffeb6250U, unwinder.frames()[14].sp);
- EXPECT_EQ(0xf6f73552U, unwinder.frames()[15].pc);
- EXPECT_EQ(0xffeb62f0U, unwinder.frames()[15].sp);
- EXPECT_EQ(0xf6f7499aU, unwinder.frames()[16].pc);
- EXPECT_EQ(0xffeb6370U, unwinder.frames()[16].sp);
- EXPECT_EQ(0xf7265362U, unwinder.frames()[17].pc);
- EXPECT_EQ(0xffeb63e0U, unwinder.frames()[17].sp);
- EXPECT_EQ(0xf72945bdU, unwinder.frames()[18].pc);
- EXPECT_EQ(0xffeb6530U, unwinder.frames()[18].sp);
- EXPECT_EQ(0xee75bd3bU, unwinder.frames()[19].pc);
- EXPECT_EQ(0xffeb6580U, unwinder.frames()[19].sp);
- EXPECT_EQ(0xf728e4d2U, unwinder.frames()[20].pc);
- EXPECT_EQ(0xffeb65b0U, unwinder.frames()[20].sp);
- EXPECT_EQ(0xf6d27ab5U, unwinder.frames()[21].pc);
- EXPECT_EQ(0xffeb65e0U, unwinder.frames()[21].sp);
- EXPECT_EQ(0xf6f7df0dU, unwinder.frames()[22].pc);
- EXPECT_EQ(0xffeb6680U, unwinder.frames()[22].sp);
- EXPECT_EQ(0xf6f73552U, unwinder.frames()[23].pc);
- EXPECT_EQ(0xffeb6720U, unwinder.frames()[23].sp);
- EXPECT_EQ(0xf6f7499aU, unwinder.frames()[24].pc);
- EXPECT_EQ(0xffeb67a0U, unwinder.frames()[24].sp);
- EXPECT_EQ(0xf7265362U, unwinder.frames()[25].pc);
- EXPECT_EQ(0xffeb6810U, unwinder.frames()[25].sp);
- EXPECT_EQ(0xf72945bdU, unwinder.frames()[26].pc);
- EXPECT_EQ(0xffeb6960U, unwinder.frames()[26].sp);
- EXPECT_EQ(0xee75bbdbU, unwinder.frames()[27].pc);
- EXPECT_EQ(0xffeb69b0U, unwinder.frames()[27].sp);
- EXPECT_EQ(0xf728e6a2U, unwinder.frames()[28].pc);
- EXPECT_EQ(0xffeb69f0U, unwinder.frames()[28].sp);
- EXPECT_EQ(0xf6d27acbU, unwinder.frames()[29].pc);
- EXPECT_EQ(0xffeb6a20U, unwinder.frames()[29].sp);
- EXPECT_EQ(0xf6f7df0dU, unwinder.frames()[30].pc);
- EXPECT_EQ(0xffeb6ac0U, unwinder.frames()[30].sp);
- EXPECT_EQ(0xf6f73552U, unwinder.frames()[31].pc);
- EXPECT_EQ(0xffeb6b60U, unwinder.frames()[31].sp);
- EXPECT_EQ(0xf6f7499aU, unwinder.frames()[32].pc);
- EXPECT_EQ(0xffeb6be0U, unwinder.frames()[32].sp);
- EXPECT_EQ(0xf7265362U, unwinder.frames()[33].pc);
- EXPECT_EQ(0xffeb6c50U, unwinder.frames()[33].sp);
- EXPECT_EQ(0xf72945bdU, unwinder.frames()[34].pc);
- EXPECT_EQ(0xffeb6dd0U, unwinder.frames()[34].sp);
- EXPECT_EQ(0xee75b624U, unwinder.frames()[35].pc);
- EXPECT_EQ(0xffeb6e20U, unwinder.frames()[35].sp);
- EXPECT_EQ(0xf728e4d2U, unwinder.frames()[36].pc);
- EXPECT_EQ(0xffeb6e50U, unwinder.frames()[36].sp);
- EXPECT_EQ(0xf6d27ab5U, unwinder.frames()[37].pc);
- EXPECT_EQ(0xffeb6e70U, unwinder.frames()[37].sp);
- EXPECT_EQ(0xf6f7df0dU, unwinder.frames()[38].pc);
- EXPECT_EQ(0xffeb6f10U, unwinder.frames()[38].sp);
- EXPECT_EQ(0xf6f73552U, unwinder.frames()[39].pc);
- EXPECT_EQ(0xffeb6fb0U, unwinder.frames()[39].sp);
- EXPECT_EQ(0xf6f7499aU, unwinder.frames()[40].pc);
- EXPECT_EQ(0xffeb7030U, unwinder.frames()[40].sp);
- EXPECT_EQ(0xf7265362U, unwinder.frames()[41].pc);
- EXPECT_EQ(0xffeb70a0U, unwinder.frames()[41].sp);
- EXPECT_EQ(0xf72945bdU, unwinder.frames()[42].pc);
- EXPECT_EQ(0xffeb71f0U, unwinder.frames()[42].sp);
- EXPECT_EQ(0xee75aedbU, unwinder.frames()[43].pc);
- EXPECT_EQ(0xffeb7240U, unwinder.frames()[43].sp);
- EXPECT_EQ(0xf728e4d2U, unwinder.frames()[44].pc);
- EXPECT_EQ(0xffeb72a0U, unwinder.frames()[44].sp);
- EXPECT_EQ(0xf6d27ab5U, unwinder.frames()[45].pc);
- EXPECT_EQ(0xffeb72c0U, unwinder.frames()[45].sp);
- EXPECT_EQ(0xf6f7df0dU, unwinder.frames()[46].pc);
- EXPECT_EQ(0xffeb7360U, unwinder.frames()[46].sp);
- EXPECT_EQ(0xf6f73552U, unwinder.frames()[47].pc);
- EXPECT_EQ(0xffeb7400U, unwinder.frames()[47].sp);
- EXPECT_EQ(0xf6f7499aU, unwinder.frames()[48].pc);
- EXPECT_EQ(0xffeb7480U, unwinder.frames()[48].sp);
- EXPECT_EQ(0xf7265362U, unwinder.frames()[49].pc);
- EXPECT_EQ(0xffeb74f0U, unwinder.frames()[49].sp);
- EXPECT_EQ(0xf72945bdU, unwinder.frames()[50].pc);
- EXPECT_EQ(0xffeb7680U, unwinder.frames()[50].sp);
- EXPECT_EQ(0xee756c21U, unwinder.frames()[51].pc);
- EXPECT_EQ(0xffeb76d0U, unwinder.frames()[51].sp);
- EXPECT_EQ(0xf728e6a2U, unwinder.frames()[52].pc);
- EXPECT_EQ(0xffeb76f0U, unwinder.frames()[52].sp);
- EXPECT_EQ(0xf6d27acbU, unwinder.frames()[53].pc);
- EXPECT_EQ(0xffeb7710U, unwinder.frames()[53].sp);
- EXPECT_EQ(0xf6f7df0dU, unwinder.frames()[54].pc);
- EXPECT_EQ(0xffeb77b0U, unwinder.frames()[54].sp);
- EXPECT_EQ(0xf6f73552U, unwinder.frames()[55].pc);
- EXPECT_EQ(0xffeb7850U, unwinder.frames()[55].sp);
- EXPECT_EQ(0xf6f7499aU, unwinder.frames()[56].pc);
- EXPECT_EQ(0xffeb78d0U, unwinder.frames()[56].sp);
- EXPECT_EQ(0xf7265362U, unwinder.frames()[57].pc);
- EXPECT_EQ(0xffeb7940U, unwinder.frames()[57].sp);
- EXPECT_EQ(0xf72945bdU, unwinder.frames()[58].pc);
- EXPECT_EQ(0xffeb7a80U, unwinder.frames()[58].sp);
- EXPECT_EQ(0xf728e6a2U, unwinder.frames()[59].pc);
- EXPECT_EQ(0xffeb7ad0U, unwinder.frames()[59].sp);
- EXPECT_EQ(0xf6d27acbU, unwinder.frames()[60].pc);
- EXPECT_EQ(0xffeb7af0U, unwinder.frames()[60].sp);
- EXPECT_EQ(0xf718bc95U, unwinder.frames()[61].pc);
- EXPECT_EQ(0xffeb7b90U, unwinder.frames()[61].sp);
- EXPECT_EQ(0xf718bb5aU, unwinder.frames()[62].pc);
- EXPECT_EQ(0xffeb7c50U, unwinder.frames()[62].sp);
- EXPECT_EQ(0xf706b3ddU, unwinder.frames()[63].pc);
- EXPECT_EQ(0xffeb7d10U, unwinder.frames()[63].sp);
- EXPECT_EQ(0xf6d6548cU, unwinder.frames()[64].pc);
- EXPECT_EQ(0xffeb7d70U, unwinder.frames()[64].sp);
- EXPECT_EQ(0xf6d5df06U, unwinder.frames()[65].pc);
- EXPECT_EQ(0xffeb7df0U, unwinder.frames()[65].sp);
- EXPECT_EQ(0x56574d8cU, unwinder.frames()[66].pc);
- EXPECT_EQ(0xffeb7e40U, unwinder.frames()[66].sp);
- EXPECT_EQ(0x56574a80U, unwinder.frames()[67].pc);
- EXPECT_EQ(0xffeb7e70U, unwinder.frames()[67].sp);
- EXPECT_EQ(0xf7363275U, unwinder.frames()[68].pc);
- EXPECT_EQ(0xffeb7ef0U, unwinder.frames()[68].sp);
-}
-
-TEST_F(UnwindOfflineTest, jit_debug_arm) {
- ASSERT_NO_FATAL_FAILURE(Init("jit_debug_arm/", ARCH_ARM));
-
- MemoryOfflineParts* memory = new MemoryOfflineParts;
- AddMemory(dir_ + "descriptor.data", memory);
- AddMemory(dir_ + "descriptor1.data", memory);
- AddMemory(dir_ + "stack.data", memory);
- for (size_t i = 0; i < 7; i++) {
- AddMemory(dir_ + "entry" + std::to_string(i) + ".data", memory);
- AddMemory(dir_ + "jit" + std::to_string(i) + ".data", memory);
- }
- process_memory_.reset(memory);
-
- JitDebug jit_debug(process_memory_);
- Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
- unwinder.SetJitDebug(&jit_debug);
- unwinder.Unwind();
-
- std::string frame_info(DumpFrames(unwinder));
- ASSERT_EQ(76U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
- EXPECT_EQ(
- " #00 pc 00018a5e libarttestd.so (Java_Main_unwindInProcess+866)\n"
- " #01 pc 0000212d 137-cfi.odex (boolean Main.unwindInProcess(boolean, int, "
- "boolean)+92)\n"
- " #02 pc 00011cb1 anonymous:e2796000 (boolean Main.bar(boolean)+72)\n"
- " #03 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
- " #04 pc 00467129 libartd.so (art_quick_invoke_stub+228)\n"
- " #05 pc 000bf7a9 libartd.so "
- "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
- "const*)+864)\n"
- " #06 pc 00247833 libartd.so "
- "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
- "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
- " #07 pc 0022e935 libartd.so "
- "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
- "art::ShadowFrame&, art::JValue, bool)+244)\n"
- " #08 pc 0022f71d libartd.so "
- "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
- "const&, art::ShadowFrame*)+128)\n"
- " #09 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
- " #10 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
- " #11 pc 00011c31 anonymous:e2796000 (int Main.compare(Main, Main)+64)\n"
- " #12 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
- " #13 pc 00467129 libartd.so (art_quick_invoke_stub+228)\n"
- " #14 pc 000bf7a9 libartd.so "
- "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
- "const*)+864)\n"
- " #15 pc 00247833 libartd.so "
- "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
- "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
- " #16 pc 0022e935 libartd.so "
- "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
- "art::ShadowFrame&, art::JValue, bool)+244)\n"
- " #17 pc 0022f71d libartd.so "
- "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
- "const&, art::ShadowFrame*)+128)\n"
- " #18 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
- " #19 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
- " #20 pc 00011b77 anonymous:e2796000 (int Main.compare(java.lang.Object, "
- "java.lang.Object)+118)\n"
- " #21 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
- " #22 pc 00467129 libartd.so (art_quick_invoke_stub+228)\n"
- " #23 pc 000bf7a9 libartd.so "
- "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
- "const*)+864)\n"
- " #24 pc 00247833 libartd.so "
- "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
- "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
- " #25 pc 0022e935 libartd.so "
- "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
- "art::ShadowFrame&, art::JValue, bool)+244)\n"
- " #26 pc 0022f71d libartd.so "
- "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
- "const&, art::ShadowFrame*)+128)\n"
- " #27 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
- " #28 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
- " #29 pc 00011a29 anonymous:e2796000 (int "
- "java.util.Arrays.binarySearch0(java.lang.Object[], int, int, java.lang.Object, "
- "java.util.Comparator)+304)\n"
- " #30 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
- " #31 pc 0046722f libartd.so (art_quick_invoke_static_stub+226)\n"
- " #32 pc 000bf7bb libartd.so "
- "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
- "const*)+882)\n"
- " #33 pc 00247833 libartd.so "
- "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
- "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
- " #34 pc 0022e935 libartd.so "
- "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
- "art::ShadowFrame&, art::JValue, bool)+244)\n"
- " #35 pc 0022f71d libartd.so "
- "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
- "const&, art::ShadowFrame*)+128)\n"
- " #36 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
- " #37 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
- " #38 pc 0001139b anonymous:e2796000 (boolean Main.foo()+178)\n"
- " #39 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
- " #40 pc 00467129 libartd.so (art_quick_invoke_stub+228)\n"
- " #41 pc 000bf7a9 libartd.so "
- "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
- "const*)+864)\n"
- " #42 pc 00247833 libartd.so "
- "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
- "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
- " #43 pc 0022e935 libartd.so "
- "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
- "art::ShadowFrame&, art::JValue, bool)+244)\n"
- " #44 pc 0022f71d libartd.so "
- "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
- "const&, art::ShadowFrame*)+128)\n"
- " #45 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
- " #46 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
- " #47 pc 00010aa7 anonymous:e2796000 (void Main.runPrimary()+70)\n"
- " #48 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
- " #49 pc 00467129 libartd.so (art_quick_invoke_stub+228)\n"
- " #50 pc 000bf7a9 libartd.so "
- "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
- "const*)+864)\n"
- " #51 pc 00247833 libartd.so "
- "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
- "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
- " #52 pc 0022e935 libartd.so "
- "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
- "art::ShadowFrame&, art::JValue, bool)+244)\n"
- " #53 pc 0022f71d libartd.so "
- "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
- "const&, art::ShadowFrame*)+128)\n"
- " #54 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
- " #55 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
- " #56 pc 0000ba99 anonymous:e2796000 (void Main.main(java.lang.String[])+144)\n"
- " #57 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
- " #58 pc 0046722f libartd.so (art_quick_invoke_static_stub+226)\n"
- " #59 pc 000bf7bb libartd.so "
- "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
- "const*)+882)\n"
- " #60 pc 00247833 libartd.so "
- "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
- "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
- " #61 pc 0022e935 libartd.so "
- "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
- "art::ShadowFrame&, art::JValue, bool)+244)\n"
- " #62 pc 0022f71d libartd.so "
- "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
- "const&, art::ShadowFrame*)+128)\n"
- " #63 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
- " #64 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
- " #65 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
- " #66 pc 0046722f libartd.so (art_quick_invoke_static_stub+226)\n"
- " #67 pc 000bf7bb libartd.so "
- "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
- "const*)+882)\n"
- " #68 pc 003b292d libartd.so "
- "(art::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, "
- "art::ArgArray*, art::JValue*, char const*)+52)\n"
- " #69 pc 003b26c3 libartd.so "
- "(art::InvokeWithVarArgs(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, "
- "_jmethodID*, std::__va_list)+210)\n"
- " #70 pc 00308411 libartd.so "
- "(art::JNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, std::__va_list)+76)\n"
- " #71 pc 000e6a9f libartd.so "
- "(art::CheckJNI::CallMethodV(char const*, _JNIEnv*, _jobject*, _jclass*, _jmethodID*, "
- "std::__va_list, art::Primitive::Type, art::InvokeType)+1486)\n"
- " #72 pc 000e19b9 libartd.so "
- "(art::CheckJNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, std::__va_list)+40)\n"
- " #73 pc 0000159f dalvikvm32 "
- "(_JNIEnv::CallStaticVoidMethod(_jclass*, _jmethodID*, ...)+30)\n"
- " #74 pc 00001349 dalvikvm32 (main+896)\n"
- " #75 pc 000850c9 libc.so\n",
- frame_info);
- EXPECT_EQ(0xdfe66a5eU, unwinder.frames()[0].pc);
- EXPECT_EQ(0xff85d180U, unwinder.frames()[0].sp);
- EXPECT_EQ(0xe044712dU, unwinder.frames()[1].pc);
- EXPECT_EQ(0xff85d200U, unwinder.frames()[1].sp);
- EXPECT_EQ(0xe27a7cb1U, unwinder.frames()[2].pc);
- EXPECT_EQ(0xff85d290U, unwinder.frames()[2].sp);
- EXPECT_EQ(0xed75c175U, unwinder.frames()[3].pc);
- EXPECT_EQ(0xff85d2b0U, unwinder.frames()[3].sp);
- EXPECT_EQ(0xed761129U, unwinder.frames()[4].pc);
- EXPECT_EQ(0xff85d2e8U, unwinder.frames()[4].sp);
- EXPECT_EQ(0xed3b97a9U, unwinder.frames()[5].pc);
- EXPECT_EQ(0xff85d370U, unwinder.frames()[5].sp);
- EXPECT_EQ(0xed541833U, unwinder.frames()[6].pc);
- EXPECT_EQ(0xff85d3d8U, unwinder.frames()[6].sp);
- EXPECT_EQ(0xed528935U, unwinder.frames()[7].pc);
- EXPECT_EQ(0xff85d428U, unwinder.frames()[7].sp);
- EXPECT_EQ(0xed52971dU, unwinder.frames()[8].pc);
- EXPECT_EQ(0xff85d470U, unwinder.frames()[8].sp);
- EXPECT_EQ(0xed73c865U, unwinder.frames()[9].pc);
- EXPECT_EQ(0xff85d4b0U, unwinder.frames()[9].sp);
- EXPECT_EQ(0xed7606ffU, unwinder.frames()[10].pc);
- EXPECT_EQ(0xff85d5d0U, unwinder.frames()[10].sp);
- EXPECT_EQ(0xe27a7c31U, unwinder.frames()[11].pc);
- EXPECT_EQ(0xff85d640U, unwinder.frames()[11].sp);
- EXPECT_EQ(0xed75c175U, unwinder.frames()[12].pc);
- EXPECT_EQ(0xff85d660U, unwinder.frames()[12].sp);
- EXPECT_EQ(0xed761129U, unwinder.frames()[13].pc);
- EXPECT_EQ(0xff85d698U, unwinder.frames()[13].sp);
- EXPECT_EQ(0xed3b97a9U, unwinder.frames()[14].pc);
- EXPECT_EQ(0xff85d720U, unwinder.frames()[14].sp);
- EXPECT_EQ(0xed541833U, unwinder.frames()[15].pc);
- EXPECT_EQ(0xff85d788U, unwinder.frames()[15].sp);
- EXPECT_EQ(0xed528935U, unwinder.frames()[16].pc);
- EXPECT_EQ(0xff85d7d8U, unwinder.frames()[16].sp);
- EXPECT_EQ(0xed52971dU, unwinder.frames()[17].pc);
- EXPECT_EQ(0xff85d820U, unwinder.frames()[17].sp);
- EXPECT_EQ(0xed73c865U, unwinder.frames()[18].pc);
- EXPECT_EQ(0xff85d860U, unwinder.frames()[18].sp);
- EXPECT_EQ(0xed7606ffU, unwinder.frames()[19].pc);
- EXPECT_EQ(0xff85d970U, unwinder.frames()[19].sp);
- EXPECT_EQ(0xe27a7b77U, unwinder.frames()[20].pc);
- EXPECT_EQ(0xff85d9e0U, unwinder.frames()[20].sp);
- EXPECT_EQ(0xed75c175U, unwinder.frames()[21].pc);
- EXPECT_EQ(0xff85da10U, unwinder.frames()[21].sp);
- EXPECT_EQ(0xed761129U, unwinder.frames()[22].pc);
- EXPECT_EQ(0xff85da48U, unwinder.frames()[22].sp);
- EXPECT_EQ(0xed3b97a9U, unwinder.frames()[23].pc);
- EXPECT_EQ(0xff85dad0U, unwinder.frames()[23].sp);
- EXPECT_EQ(0xed541833U, unwinder.frames()[24].pc);
- EXPECT_EQ(0xff85db38U, unwinder.frames()[24].sp);
- EXPECT_EQ(0xed528935U, unwinder.frames()[25].pc);
- EXPECT_EQ(0xff85db88U, unwinder.frames()[25].sp);
- EXPECT_EQ(0xed52971dU, unwinder.frames()[26].pc);
- EXPECT_EQ(0xff85dbd0U, unwinder.frames()[26].sp);
- EXPECT_EQ(0xed73c865U, unwinder.frames()[27].pc);
- EXPECT_EQ(0xff85dc10U, unwinder.frames()[27].sp);
- EXPECT_EQ(0xed7606ffU, unwinder.frames()[28].pc);
- EXPECT_EQ(0xff85dd20U, unwinder.frames()[28].sp);
- EXPECT_EQ(0xe27a7a29U, unwinder.frames()[29].pc);
- EXPECT_EQ(0xff85dd90U, unwinder.frames()[29].sp);
- EXPECT_EQ(0xed75c175U, unwinder.frames()[30].pc);
- EXPECT_EQ(0xff85ddc0U, unwinder.frames()[30].sp);
- EXPECT_EQ(0xed76122fU, unwinder.frames()[31].pc);
- EXPECT_EQ(0xff85de08U, unwinder.frames()[31].sp);
- EXPECT_EQ(0xed3b97bbU, unwinder.frames()[32].pc);
- EXPECT_EQ(0xff85de90U, unwinder.frames()[32].sp);
- EXPECT_EQ(0xed541833U, unwinder.frames()[33].pc);
- EXPECT_EQ(0xff85def8U, unwinder.frames()[33].sp);
- EXPECT_EQ(0xed528935U, unwinder.frames()[34].pc);
- EXPECT_EQ(0xff85df48U, unwinder.frames()[34].sp);
- EXPECT_EQ(0xed52971dU, unwinder.frames()[35].pc);
- EXPECT_EQ(0xff85df90U, unwinder.frames()[35].sp);
- EXPECT_EQ(0xed73c865U, unwinder.frames()[36].pc);
- EXPECT_EQ(0xff85dfd0U, unwinder.frames()[36].sp);
- EXPECT_EQ(0xed7606ffU, unwinder.frames()[37].pc);
- EXPECT_EQ(0xff85e110U, unwinder.frames()[37].sp);
- EXPECT_EQ(0xe27a739bU, unwinder.frames()[38].pc);
- EXPECT_EQ(0xff85e180U, unwinder.frames()[38].sp);
- EXPECT_EQ(0xed75c175U, unwinder.frames()[39].pc);
- EXPECT_EQ(0xff85e1b0U, unwinder.frames()[39].sp);
- EXPECT_EQ(0xed761129U, unwinder.frames()[40].pc);
- EXPECT_EQ(0xff85e1e0U, unwinder.frames()[40].sp);
- EXPECT_EQ(0xed3b97a9U, unwinder.frames()[41].pc);
- EXPECT_EQ(0xff85e268U, unwinder.frames()[41].sp);
- EXPECT_EQ(0xed541833U, unwinder.frames()[42].pc);
- EXPECT_EQ(0xff85e2d0U, unwinder.frames()[42].sp);
- EXPECT_EQ(0xed528935U, unwinder.frames()[43].pc);
- EXPECT_EQ(0xff85e320U, unwinder.frames()[43].sp);
- EXPECT_EQ(0xed52971dU, unwinder.frames()[44].pc);
- EXPECT_EQ(0xff85e368U, unwinder.frames()[44].sp);
- EXPECT_EQ(0xed73c865U, unwinder.frames()[45].pc);
- EXPECT_EQ(0xff85e3a8U, unwinder.frames()[45].sp);
- EXPECT_EQ(0xed7606ffU, unwinder.frames()[46].pc);
- EXPECT_EQ(0xff85e4c0U, unwinder.frames()[46].sp);
- EXPECT_EQ(0xe27a6aa7U, unwinder.frames()[47].pc);
- EXPECT_EQ(0xff85e530U, unwinder.frames()[47].sp);
- EXPECT_EQ(0xed75c175U, unwinder.frames()[48].pc);
- EXPECT_EQ(0xff85e5a0U, unwinder.frames()[48].sp);
- EXPECT_EQ(0xed761129U, unwinder.frames()[49].pc);
- EXPECT_EQ(0xff85e5d8U, unwinder.frames()[49].sp);
- EXPECT_EQ(0xed3b97a9U, unwinder.frames()[50].pc);
- EXPECT_EQ(0xff85e660U, unwinder.frames()[50].sp);
- EXPECT_EQ(0xed541833U, unwinder.frames()[51].pc);
- EXPECT_EQ(0xff85e6c8U, unwinder.frames()[51].sp);
- EXPECT_EQ(0xed528935U, unwinder.frames()[52].pc);
- EXPECT_EQ(0xff85e718U, unwinder.frames()[52].sp);
- EXPECT_EQ(0xed52971dU, unwinder.frames()[53].pc);
- EXPECT_EQ(0xff85e760U, unwinder.frames()[53].sp);
- EXPECT_EQ(0xed73c865U, unwinder.frames()[54].pc);
- EXPECT_EQ(0xff85e7a0U, unwinder.frames()[54].sp);
- EXPECT_EQ(0xed7606ffU, unwinder.frames()[55].pc);
- EXPECT_EQ(0xff85e8f0U, unwinder.frames()[55].sp);
- EXPECT_EQ(0xe27a1a99U, unwinder.frames()[56].pc);
- EXPECT_EQ(0xff85e960U, unwinder.frames()[56].sp);
- EXPECT_EQ(0xed75c175U, unwinder.frames()[57].pc);
- EXPECT_EQ(0xff85e990U, unwinder.frames()[57].sp);
- EXPECT_EQ(0xed76122fU, unwinder.frames()[58].pc);
- EXPECT_EQ(0xff85e9c8U, unwinder.frames()[58].sp);
- EXPECT_EQ(0xed3b97bbU, unwinder.frames()[59].pc);
- EXPECT_EQ(0xff85ea50U, unwinder.frames()[59].sp);
- EXPECT_EQ(0xed541833U, unwinder.frames()[60].pc);
- EXPECT_EQ(0xff85eab8U, unwinder.frames()[60].sp);
- EXPECT_EQ(0xed528935U, unwinder.frames()[61].pc);
- EXPECT_EQ(0xff85eb08U, unwinder.frames()[61].sp);
- EXPECT_EQ(0xed52971dU, unwinder.frames()[62].pc);
- EXPECT_EQ(0xff85eb50U, unwinder.frames()[62].sp);
- EXPECT_EQ(0xed73c865U, unwinder.frames()[63].pc);
- EXPECT_EQ(0xff85eb90U, unwinder.frames()[63].sp);
- EXPECT_EQ(0xed7606ffU, unwinder.frames()[64].pc);
- EXPECT_EQ(0xff85ec90U, unwinder.frames()[64].sp);
- EXPECT_EQ(0xed75c175U, unwinder.frames()[65].pc);
- EXPECT_EQ(0xff85ed00U, unwinder.frames()[65].sp);
- EXPECT_EQ(0xed76122fU, unwinder.frames()[66].pc);
- EXPECT_EQ(0xff85ed38U, unwinder.frames()[66].sp);
- EXPECT_EQ(0xed3b97bbU, unwinder.frames()[67].pc);
- EXPECT_EQ(0xff85edc0U, unwinder.frames()[67].sp);
- EXPECT_EQ(0xed6ac92dU, unwinder.frames()[68].pc);
- EXPECT_EQ(0xff85ee28U, unwinder.frames()[68].sp);
- EXPECT_EQ(0xed6ac6c3U, unwinder.frames()[69].pc);
- EXPECT_EQ(0xff85eeb8U, unwinder.frames()[69].sp);
- EXPECT_EQ(0xed602411U, unwinder.frames()[70].pc);
- EXPECT_EQ(0xff85ef48U, unwinder.frames()[70].sp);
- EXPECT_EQ(0xed3e0a9fU, unwinder.frames()[71].pc);
- EXPECT_EQ(0xff85ef90U, unwinder.frames()[71].sp);
- EXPECT_EQ(0xed3db9b9U, unwinder.frames()[72].pc);
- EXPECT_EQ(0xff85f008U, unwinder.frames()[72].sp);
- EXPECT_EQ(0xab0d459fU, unwinder.frames()[73].pc);
- EXPECT_EQ(0xff85f038U, unwinder.frames()[73].sp);
- EXPECT_EQ(0xab0d4349U, unwinder.frames()[74].pc);
- EXPECT_EQ(0xff85f050U, unwinder.frames()[74].sp);
- EXPECT_EQ(0xedb0d0c9U, unwinder.frames()[75].pc);
- EXPECT_EQ(0xff85f0c0U, unwinder.frames()[75].sp);
-}
-
-struct LeakType {
- LeakType(Maps* maps, Regs* regs, std::shared_ptr<Memory>& process_memory)
- : maps(maps), regs(regs), process_memory(process_memory) {}
-
- Maps* maps;
- Regs* regs;
- std::shared_ptr<Memory>& process_memory;
-};
-
-static void OfflineUnwind(void* data) {
- LeakType* leak_data = reinterpret_cast<LeakType*>(data);
-
- std::unique_ptr<Regs> regs_copy(leak_data->regs->Clone());
- JitDebug jit_debug(leak_data->process_memory);
- Unwinder unwinder(128, leak_data->maps, regs_copy.get(), leak_data->process_memory);
- unwinder.SetJitDebug(&jit_debug);
- unwinder.Unwind();
- ASSERT_EQ(76U, unwinder.NumFrames());
-}
-
-TEST_F(UnwindOfflineTest, unwind_offline_check_for_leaks) {
- ASSERT_NO_FATAL_FAILURE(Init("jit_debug_arm/", ARCH_ARM));
-
- MemoryOfflineParts* memory = new MemoryOfflineParts;
- AddMemory(dir_ + "descriptor.data", memory);
- AddMemory(dir_ + "descriptor1.data", memory);
- AddMemory(dir_ + "stack.data", memory);
- for (size_t i = 0; i < 7; i++) {
- AddMemory(dir_ + "entry" + std::to_string(i) + ".data", memory);
- AddMemory(dir_ + "jit" + std::to_string(i) + ".data", memory);
- }
- process_memory_.reset(memory);
-
- LeakType data(maps_.get(), regs_.get(), process_memory_);
- TestCheckForLeaks(OfflineUnwind, &data);
-}
-
-// The eh_frame_hdr data is present but set to zero fdes. This should
-// fallback to iterating over the cies/fdes and ignore the eh_frame_hdr.
-// No .gnu_debugdata section in the elf file, so no symbols.
-TEST_F(UnwindOfflineTest, bad_eh_frame_hdr_arm64) {
- ASSERT_NO_FATAL_FAILURE(Init("bad_eh_frame_hdr_arm64/", ARCH_ARM64));
-
- Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
- unwinder.Unwind();
-
- std::string frame_info(DumpFrames(unwinder));
- ASSERT_EQ(5U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
- EXPECT_EQ(
- " #00 pc 0000000000000550 waiter64\n"
- " #01 pc 0000000000000568 waiter64\n"
- " #02 pc 000000000000057c waiter64\n"
- " #03 pc 0000000000000590 waiter64\n"
- " #04 pc 00000000000a8e98 libc.so (__libc_init+88)\n",
- frame_info);
- EXPECT_EQ(0x60a9fdf550U, unwinder.frames()[0].pc);
- EXPECT_EQ(0x7fdd141990U, unwinder.frames()[0].sp);
- EXPECT_EQ(0x60a9fdf568U, unwinder.frames()[1].pc);
- EXPECT_EQ(0x7fdd1419a0U, unwinder.frames()[1].sp);
- EXPECT_EQ(0x60a9fdf57cU, unwinder.frames()[2].pc);
- EXPECT_EQ(0x7fdd1419b0U, unwinder.frames()[2].sp);
- EXPECT_EQ(0x60a9fdf590U, unwinder.frames()[3].pc);
- EXPECT_EQ(0x7fdd1419c0U, unwinder.frames()[3].sp);
- EXPECT_EQ(0x7542d68e98U, unwinder.frames()[4].pc);
- EXPECT_EQ(0x7fdd1419d0U, unwinder.frames()[4].sp);
-}
-
-// The elf has bad eh_frame unwind information for the pcs. If eh_frame
-// is used first, the unwind will not match the expected output.
-TEST_F(UnwindOfflineTest, debug_frame_first_x86) {
- ASSERT_NO_FATAL_FAILURE(Init("debug_frame_first_x86/", ARCH_X86));
-
- Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
- unwinder.Unwind();
-
- std::string frame_info(DumpFrames(unwinder));
- ASSERT_EQ(5U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
- EXPECT_EQ(
- " #00 pc 00000685 waiter (call_level3+53)\n"
- " #01 pc 000006b7 waiter (call_level2+23)\n"
- " #02 pc 000006d7 waiter (call_level1+23)\n"
- " #03 pc 000006f7 waiter (main+23)\n"
- " #04 pc 00018275 libc.so\n",
- frame_info);
- EXPECT_EQ(0x56598685U, unwinder.frames()[0].pc);
- EXPECT_EQ(0xffcf9e38U, unwinder.frames()[0].sp);
- EXPECT_EQ(0x565986b7U, unwinder.frames()[1].pc);
- EXPECT_EQ(0xffcf9e50U, unwinder.frames()[1].sp);
- EXPECT_EQ(0x565986d7U, unwinder.frames()[2].pc);
- EXPECT_EQ(0xffcf9e60U, unwinder.frames()[2].sp);
- EXPECT_EQ(0x565986f7U, unwinder.frames()[3].pc);
- EXPECT_EQ(0xffcf9e70U, unwinder.frames()[3].sp);
- EXPECT_EQ(0xf744a275U, unwinder.frames()[4].pc);
- EXPECT_EQ(0xffcf9e80U, unwinder.frames()[4].sp);
-}
-
-// Make sure that a pc that is at the beginning of an fde unwinds correctly.
-TEST_F(UnwindOfflineTest, eh_frame_hdr_begin_x86_64) {
- ASSERT_NO_FATAL_FAILURE(Init("eh_frame_hdr_begin_x86_64/", ARCH_X86_64));
-
- Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
- unwinder.Unwind();
-
- std::string frame_info(DumpFrames(unwinder));
- ASSERT_EQ(5U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
- EXPECT_EQ(
- " #00 pc 0000000000000a80 unwind_test64 (calling3)\n"
- " #01 pc 0000000000000dd9 unwind_test64 (calling2+633)\n"
- " #02 pc 000000000000121e unwind_test64 (calling1+638)\n"
- " #03 pc 00000000000013ed unwind_test64 (main+13)\n"
- " #04 pc 00000000000202b0 libc.so\n",
- frame_info);
- EXPECT_EQ(0x561550b17a80U, unwinder.frames()[0].pc);
- EXPECT_EQ(0x7ffcc8596ce8U, unwinder.frames()[0].sp);
- EXPECT_EQ(0x561550b17dd9U, unwinder.frames()[1].pc);
- EXPECT_EQ(0x7ffcc8596cf0U, unwinder.frames()[1].sp);
- EXPECT_EQ(0x561550b1821eU, unwinder.frames()[2].pc);
- EXPECT_EQ(0x7ffcc8596f40U, unwinder.frames()[2].sp);
- EXPECT_EQ(0x561550b183edU, unwinder.frames()[3].pc);
- EXPECT_EQ(0x7ffcc8597190U, unwinder.frames()[3].sp);
- EXPECT_EQ(0x7f4de62162b0U, unwinder.frames()[4].pc);
- EXPECT_EQ(0x7ffcc85971a0U, unwinder.frames()[4].sp);
-}
-
-TEST_F(UnwindOfflineTest, art_quick_osr_stub_arm) {
- ASSERT_NO_FATAL_FAILURE(Init("art_quick_osr_stub_arm/", ARCH_ARM));
-
- MemoryOfflineParts* memory = new MemoryOfflineParts;
- AddMemory(dir_ + "descriptor.data", memory);
- AddMemory(dir_ + "stack.data", memory);
- for (size_t i = 0; i < 2; i++) {
- AddMemory(dir_ + "entry" + std::to_string(i) + ".data", memory);
- AddMemory(dir_ + "jit" + std::to_string(i) + ".data", memory);
- }
- process_memory_.reset(memory);
-
- JitDebug jit_debug(process_memory_);
- Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
- unwinder.SetJitDebug(&jit_debug);
- unwinder.Unwind();
-
- std::string frame_info(DumpFrames(unwinder));
- ASSERT_EQ(25U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
- EXPECT_EQ(
- " #00 pc 0000c788 <anonymous:d0250000> "
- "(com.example.simpleperf.simpleperfexamplewithnative.MixActivity.access$000)\n"
- " #01 pc 0000cdd5 <anonymous:d0250000> "
- "(com.example.simpleperf.simpleperfexamplewithnative.MixActivity$1.run+60)\n"
- " #02 pc 004135bb libart.so (art_quick_osr_stub+42)\n"
- " #03 pc 002657a5 libart.so "
- "(art::jit::Jit::MaybeDoOnStackReplacement(art::Thread*, art::ArtMethod*, unsigned int, int, "
- "art::JValue*)+876)\n"
- " #04 pc 004021a7 libart.so (MterpMaybeDoOnStackReplacement+86)\n"
- " #05 pc 00412474 libart.so (ExecuteMterpImpl+66164)\n"
- " #06 pc cd8365b0 <unknown>\n" // symbol in dex file
- " #07 pc 001d7f1b libart.so "
- "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
- "art::ShadowFrame&, art::JValue, bool)+374)\n"
- " #08 pc 001dc593 libart.so "
- "(art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, "
- "art::CodeItemDataAccessor const&, art::ShadowFrame*, art::JValue*)+154)\n"
- " #09 pc 001f4d01 libart.so "
- "(bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, "
- "art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+732)\n"
- " #10 pc 003fe427 libart.so (MterpInvokeInterface+1354)\n"
- " #11 pc 00405b94 libart.so (ExecuteMterpImpl+14740)\n"
- " #12 pc 7004873e <unknown>\n" // symbol in dex file
- " #13 pc 001d7f1b libart.so "
- "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
- "art::ShadowFrame&, art::JValue, bool)+374)\n"
- " #14 pc 001dc4d5 libart.so "
- "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
- "const&, art::ShadowFrame*)+92)\n"
- " #15 pc 003f25ab libart.so (artQuickToInterpreterBridge+970)\n"
- " #16 pc 00417aff libart.so (art_quick_to_interpreter_bridge+30)\n"
- " #17 pc 00413575 libart.so (art_quick_invoke_stub_internal+68)\n"
- " #18 pc 00418531 libart.so (art_quick_invoke_stub+236)\n"
- " #19 pc 000b468d libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned "
- "int, art::JValue*, char const*)+136)\n"
- " #20 pc 00362f49 libart.so "
- "(art::(anonymous namespace)::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable "
- "const&, art::ArtMethod*, art::(anonymous namespace)::ArgArray*, art::JValue*, char "
- "const*)+52)\n"
- " #21 pc 00363cd9 libart.so "
- "(art::InvokeVirtualOrInterfaceWithJValues(art::ScopedObjectAccessAlreadyRunnable const&, "
- "_jobject*, _jmethodID*, jvalue*)+332)\n"
- " #22 pc 003851dd libart.so (art::Thread::CreateCallback(void*)+868)\n"
- " #23 pc 00062925 libc.so (__pthread_start(void*)+22)\n"
- " #24 pc 0001de39 libc.so (__start_thread+24)\n",
- frame_info);
- EXPECT_EQ(0xd025c788U, unwinder.frames()[0].pc);
- EXPECT_EQ(0xcd4ff140U, unwinder.frames()[0].sp);
- EXPECT_EQ(0xd025cdd5U, unwinder.frames()[1].pc);
- EXPECT_EQ(0xcd4ff140U, unwinder.frames()[1].sp);
- EXPECT_EQ(0xe4a755bbU, unwinder.frames()[2].pc);
- EXPECT_EQ(0xcd4ff160U, unwinder.frames()[2].sp);
- EXPECT_EQ(0xe48c77a5U, unwinder.frames()[3].pc);
- EXPECT_EQ(0xcd4ff190U, unwinder.frames()[3].sp);
- EXPECT_EQ(0xe4a641a7U, unwinder.frames()[4].pc);
- EXPECT_EQ(0xcd4ff298U, unwinder.frames()[4].sp);
- EXPECT_EQ(0xe4a74474U, unwinder.frames()[5].pc);
- EXPECT_EQ(0xcd4ff2b8U, unwinder.frames()[5].sp);
- EXPECT_EQ(0xcd8365b0U, unwinder.frames()[6].pc);
- EXPECT_EQ(0xcd4ff2e0U, unwinder.frames()[6].sp);
- EXPECT_EQ(0xe4839f1bU, unwinder.frames()[7].pc);
- EXPECT_EQ(0xcd4ff2e0U, unwinder.frames()[7].sp);
- EXPECT_EQ(0xe483e593U, unwinder.frames()[8].pc);
- EXPECT_EQ(0xcd4ff330U, unwinder.frames()[8].sp);
- EXPECT_EQ(0xe4856d01U, unwinder.frames()[9].pc);
- EXPECT_EQ(0xcd4ff380U, unwinder.frames()[9].sp);
- EXPECT_EQ(0xe4a60427U, unwinder.frames()[10].pc);
- EXPECT_EQ(0xcd4ff430U, unwinder.frames()[10].sp);
- EXPECT_EQ(0xe4a67b94U, unwinder.frames()[11].pc);
- EXPECT_EQ(0xcd4ff498U, unwinder.frames()[11].sp);
- EXPECT_EQ(0x7004873eU, unwinder.frames()[12].pc);
- EXPECT_EQ(0xcd4ff4c0U, unwinder.frames()[12].sp);
- EXPECT_EQ(0xe4839f1bU, unwinder.frames()[13].pc);
- EXPECT_EQ(0xcd4ff4c0U, unwinder.frames()[13].sp);
- EXPECT_EQ(0xe483e4d5U, unwinder.frames()[14].pc);
- EXPECT_EQ(0xcd4ff510U, unwinder.frames()[14].sp);
- EXPECT_EQ(0xe4a545abU, unwinder.frames()[15].pc);
- EXPECT_EQ(0xcd4ff538U, unwinder.frames()[15].sp);
- EXPECT_EQ(0xe4a79affU, unwinder.frames()[16].pc);
- EXPECT_EQ(0xcd4ff640U, unwinder.frames()[16].sp);
- EXPECT_EQ(0xe4a75575U, unwinder.frames()[17].pc);
- EXPECT_EQ(0xcd4ff6b0U, unwinder.frames()[17].sp);
- EXPECT_EQ(0xe4a7a531U, unwinder.frames()[18].pc);
- EXPECT_EQ(0xcd4ff6e8U, unwinder.frames()[18].sp);
- EXPECT_EQ(0xe471668dU, unwinder.frames()[19].pc);
- EXPECT_EQ(0xcd4ff770U, unwinder.frames()[19].sp);
- EXPECT_EQ(0xe49c4f49U, unwinder.frames()[20].pc);
- EXPECT_EQ(0xcd4ff7c8U, unwinder.frames()[20].sp);
- EXPECT_EQ(0xe49c5cd9U, unwinder.frames()[21].pc);
- EXPECT_EQ(0xcd4ff850U, unwinder.frames()[21].sp);
- EXPECT_EQ(0xe49e71ddU, unwinder.frames()[22].pc);
- EXPECT_EQ(0xcd4ff8e8U, unwinder.frames()[22].sp);
- EXPECT_EQ(0xe7df3925U, unwinder.frames()[23].pc);
- EXPECT_EQ(0xcd4ff958U, unwinder.frames()[23].sp);
- EXPECT_EQ(0xe7daee39U, unwinder.frames()[24].pc);
- EXPECT_EQ(0xcd4ff960U, unwinder.frames()[24].sp);
-}
-
-TEST_F(UnwindOfflineTest, jit_map_arm) {
- ASSERT_NO_FATAL_FAILURE(Init("jit_map_arm/", ARCH_ARM));
-
- maps_->Add(0xd025c788, 0xd025c9f0, 0, PROT_READ | PROT_EXEC | MAPS_FLAGS_JIT_SYMFILE_MAP,
- "jit_map0.so", 0);
- maps_->Add(0xd025cd98, 0xd025cff4, 0, PROT_READ | PROT_EXEC | MAPS_FLAGS_JIT_SYMFILE_MAP,
- "jit_map1.so", 0);
- maps_->Sort();
-
- Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
- unwinder.Unwind();
-
- std::string frame_info(DumpFrames(unwinder));
- ASSERT_EQ(6U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
- EXPECT_EQ(
- " #00 pc 00000000 jit_map0.so "
- "(com.example.simpleperf.simpleperfexamplewithnative.MixActivity.access$000)\n"
- " #01 pc 0000003d jit_map1.so "
- "(com.example.simpleperf.simpleperfexamplewithnative.MixActivity$1.run+60)\n"
- " #02 pc 004135bb libart.so (art_quick_osr_stub+42)\n"
-
- " #03 pc 003851dd libart.so (art::Thread::CreateCallback(void*)+868)\n"
- " #04 pc 00062925 libc.so (__pthread_start(void*)+22)\n"
- " #05 pc 0001de39 libc.so (__start_thread+24)\n",
- frame_info);
-
- EXPECT_EQ(0xd025c788U, unwinder.frames()[0].pc);
- EXPECT_EQ(0xcd4ff140U, unwinder.frames()[0].sp);
- EXPECT_EQ(0xd025cdd5U, unwinder.frames()[1].pc);
- EXPECT_EQ(0xcd4ff140U, unwinder.frames()[1].sp);
- EXPECT_EQ(0xe4a755bbU, unwinder.frames()[2].pc);
- EXPECT_EQ(0xcd4ff160U, unwinder.frames()[2].sp);
- EXPECT_EQ(0xe49e71ddU, unwinder.frames()[3].pc);
- EXPECT_EQ(0xcd4ff8e8U, unwinder.frames()[3].sp);
- EXPECT_EQ(0xe7df3925U, unwinder.frames()[4].pc);
- EXPECT_EQ(0xcd4ff958U, unwinder.frames()[4].sp);
- EXPECT_EQ(0xe7daee39U, unwinder.frames()[5].pc);
- EXPECT_EQ(0xcd4ff960U, unwinder.frames()[5].sp);
-}
-
-TEST_F(UnwindOfflineTest, offset_arm) {
- ASSERT_NO_FATAL_FAILURE(Init("offset_arm/", ARCH_ARM));
-
- Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
- unwinder.Unwind();
-
- std::string frame_info(DumpFrames(unwinder));
- ASSERT_EQ(19U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
- EXPECT_EQ(
- " #00 pc 0032bfa0 libunwindstack_test (SignalInnerFunction+40)\n"
- " #01 pc 0032bfeb libunwindstack_test (SignalMiddleFunction+2)\n"
- " #02 pc 0032bff3 libunwindstack_test (SignalOuterFunction+2)\n"
- " #03 pc 0032fed3 libunwindstack_test "
- "(unwindstack::SignalCallerHandler(int, siginfo*, void*)+26)\n"
- " #04 pc 0002652c libc.so (__restore)\n"
- " #05 pc 00000000 <unknown>\n"
- " #06 pc 0032c2d9 libunwindstack_test (InnerFunction+736)\n"
- " #07 pc 0032cc4f libunwindstack_test (MiddleFunction+42)\n"
- " #08 pc 0032cc81 libunwindstack_test (OuterFunction+42)\n"
- " #09 pc 0032e547 libunwindstack_test "
- "(unwindstack::RemoteThroughSignal(int, unsigned int)+270)\n"
- " #10 pc 0032ed99 libunwindstack_test "
- "(unwindstack::UnwindTest_remote_through_signal_with_invalid_func_Test::TestBody()+16)\n"
- " #11 pc 00354453 libunwindstack_test (testing::Test::Run()+154)\n"
- " #12 pc 00354de7 libunwindstack_test (testing::TestInfo::Run()+194)\n"
- " #13 pc 00355105 libunwindstack_test (testing::TestCase::Run()+180)\n"
- " #14 pc 0035a215 libunwindstack_test "
- "(testing::internal::UnitTestImpl::RunAllTests()+664)\n"
- " #15 pc 00359f4f libunwindstack_test (testing::UnitTest::Run()+110)\n"
- " #16 pc 0034d3db libunwindstack_test (main+38)\n"
- " #17 pc 00092c0d libc.so (__libc_init+48)\n"
- " #18 pc 0004202f libunwindstack_test (_start_main+38)\n",
- frame_info);
-
- EXPECT_EQ(0x2e55fa0U, unwinder.frames()[0].pc);
- EXPECT_EQ(0xf43d2cccU, unwinder.frames()[0].sp);
- EXPECT_EQ(0x2e55febU, unwinder.frames()[1].pc);
- EXPECT_EQ(0xf43d2ce0U, unwinder.frames()[1].sp);
- EXPECT_EQ(0x2e55ff3U, unwinder.frames()[2].pc);
- EXPECT_EQ(0xf43d2ce8U, unwinder.frames()[2].sp);
- EXPECT_EQ(0x2e59ed3U, unwinder.frames()[3].pc);
- EXPECT_EQ(0xf43d2cf0U, unwinder.frames()[3].sp);
- EXPECT_EQ(0xf413652cU, unwinder.frames()[4].pc);
- EXPECT_EQ(0xf43d2d10U, unwinder.frames()[4].sp);
- EXPECT_EQ(0U, unwinder.frames()[5].pc);
- EXPECT_EQ(0xffcc0ee0U, unwinder.frames()[5].sp);
- EXPECT_EQ(0x2e562d9U, unwinder.frames()[6].pc);
- EXPECT_EQ(0xffcc0ee0U, unwinder.frames()[6].sp);
- EXPECT_EQ(0x2e56c4fU, unwinder.frames()[7].pc);
- EXPECT_EQ(0xffcc1060U, unwinder.frames()[7].sp);
- EXPECT_EQ(0x2e56c81U, unwinder.frames()[8].pc);
- EXPECT_EQ(0xffcc1078U, unwinder.frames()[8].sp);
- EXPECT_EQ(0x2e58547U, unwinder.frames()[9].pc);
- EXPECT_EQ(0xffcc1090U, unwinder.frames()[9].sp);
- EXPECT_EQ(0x2e58d99U, unwinder.frames()[10].pc);
- EXPECT_EQ(0xffcc1438U, unwinder.frames()[10].sp);
- EXPECT_EQ(0x2e7e453U, unwinder.frames()[11].pc);
- EXPECT_EQ(0xffcc1448U, unwinder.frames()[11].sp);
- EXPECT_EQ(0x2e7ede7U, unwinder.frames()[12].pc);
- EXPECT_EQ(0xffcc1458U, unwinder.frames()[12].sp);
- EXPECT_EQ(0x2e7f105U, unwinder.frames()[13].pc);
- EXPECT_EQ(0xffcc1490U, unwinder.frames()[13].sp);
- EXPECT_EQ(0x2e84215U, unwinder.frames()[14].pc);
- EXPECT_EQ(0xffcc14c0U, unwinder.frames()[14].sp);
- EXPECT_EQ(0x2e83f4fU, unwinder.frames()[15].pc);
- EXPECT_EQ(0xffcc1510U, unwinder.frames()[15].sp);
- EXPECT_EQ(0x2e773dbU, unwinder.frames()[16].pc);
- EXPECT_EQ(0xffcc1528U, unwinder.frames()[16].sp);
- EXPECT_EQ(0xf41a2c0dU, unwinder.frames()[17].pc);
- EXPECT_EQ(0xffcc1540U, unwinder.frames()[17].sp);
- EXPECT_EQ(0x2b6c02fU, unwinder.frames()[18].pc);
- EXPECT_EQ(0xffcc1558U, unwinder.frames()[18].sp);
-}
-
-// Test using a non-zero load bias library that has the fde entries
-// encoded as 0xb, which is not set as pc relative.
-TEST_F(UnwindOfflineTest, debug_frame_load_bias_arm) {
- ASSERT_NO_FATAL_FAILURE(Init("debug_frame_load_bias_arm/", ARCH_ARM));
-
- Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
- unwinder.Unwind();
-
- std::string frame_info(DumpFrames(unwinder));
- ASSERT_EQ(8U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
- EXPECT_EQ(
- " #00 pc 0005138c libc.so (__ioctl+8)\n"
- " #01 pc 0002140f libc.so (ioctl+30)\n"
- " #02 pc 00039535 libbinder.so (android::IPCThreadState::talkWithDriver(bool)+204)\n"
- " #03 pc 00039633 libbinder.so (android::IPCThreadState::getAndExecuteCommand()+10)\n"
- " #04 pc 00039b57 libbinder.so (android::IPCThreadState::joinThreadPool(bool)+38)\n"
- " #05 pc 00000c21 mediaserver (main+104)\n"
- " #06 pc 00084b89 libc.so (__libc_init+48)\n"
- " #07 pc 00000b77 mediaserver (_start_main+38)\n",
- frame_info);
-
- EXPECT_EQ(0xf0be238cU, unwinder.frames()[0].pc);
- EXPECT_EQ(0xffd4a638U, unwinder.frames()[0].sp);
- EXPECT_EQ(0xf0bb240fU, unwinder.frames()[1].pc);
- EXPECT_EQ(0xffd4a638U, unwinder.frames()[1].sp);
- EXPECT_EQ(0xf1a75535U, unwinder.frames()[2].pc);
- EXPECT_EQ(0xffd4a650U, unwinder.frames()[2].sp);
- EXPECT_EQ(0xf1a75633U, unwinder.frames()[3].pc);
- EXPECT_EQ(0xffd4a6b0U, unwinder.frames()[3].sp);
- EXPECT_EQ(0xf1a75b57U, unwinder.frames()[4].pc);
- EXPECT_EQ(0xffd4a6d0U, unwinder.frames()[4].sp);
- EXPECT_EQ(0x8d1cc21U, unwinder.frames()[5].pc);
- EXPECT_EQ(0xffd4a6e8U, unwinder.frames()[5].sp);
- EXPECT_EQ(0xf0c15b89U, unwinder.frames()[6].pc);
- EXPECT_EQ(0xffd4a700U, unwinder.frames()[6].sp);
- EXPECT_EQ(0x8d1cb77U, unwinder.frames()[7].pc);
- EXPECT_EQ(0xffd4a718U, unwinder.frames()[7].sp);
-}
-
-TEST_F(UnwindOfflineTest, shared_lib_in_apk_arm64) {
- ASSERT_NO_FATAL_FAILURE(Init("shared_lib_in_apk_arm64/", ARCH_ARM64));
-
- Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
- unwinder.Unwind();
-
- std::string frame_info(DumpFrames(unwinder));
- ASSERT_EQ(7U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
- EXPECT_EQ(
- " #00 pc 000000000014ccbc linker64 (__dl_syscall+28)\n"
- " #01 pc 000000000005426c linker64 "
- "(__dl__ZL24debuggerd_signal_handleriP7siginfoPv+1128)\n"
- " #02 pc 00000000000008c0 vdso.so (__kernel_rt_sigreturn)\n"
- " #03 pc 00000000000846f4 libc.so (abort+172)\n"
- " #04 pc 0000000000084ad4 libc.so (__assert2+36)\n"
- " #05 pc 000000000003d5b4 ANGLEPrebuilt.apk!libfeature_support_angle.so (offset 0x4000) "
- "(ANGLEGetUtilityAPI+56)\n"
- " #06 pc 000000000007fe68 libc.so (__libc_init)\n",
- frame_info);
-
- EXPECT_EQ(0x7e82c4fcbcULL, unwinder.frames()[0].pc);
- EXPECT_EQ(0x7df8ca3bf0ULL, unwinder.frames()[0].sp);
- EXPECT_EQ(0x7e82b5726cULL, unwinder.frames()[1].pc);
- EXPECT_EQ(0x7df8ca3bf0ULL, unwinder.frames()[1].sp);
- EXPECT_EQ(0x7e82b018c0ULL, unwinder.frames()[2].pc);
- EXPECT_EQ(0x7df8ca3da0ULL, unwinder.frames()[2].sp);
- EXPECT_EQ(0x7e7eecc6f4ULL, unwinder.frames()[3].pc);
- EXPECT_EQ(0x7dabf3db60ULL, unwinder.frames()[3].sp);
- EXPECT_EQ(0x7e7eeccad4ULL, unwinder.frames()[4].pc);
- EXPECT_EQ(0x7dabf3dc40ULL, unwinder.frames()[4].sp);
- EXPECT_EQ(0x7dabc405b4ULL, unwinder.frames()[5].pc);
- EXPECT_EQ(0x7dabf3dc50ULL, unwinder.frames()[5].sp);
- EXPECT_EQ(0x7e7eec7e68ULL, unwinder.frames()[6].pc);
- EXPECT_EQ(0x7dabf3dc70ULL, unwinder.frames()[6].sp);
- // Ignore top frame since the test code was modified to end in __libc_init.
-}
-
-TEST_F(UnwindOfflineTest, shared_lib_in_apk_memory_only_arm64) {
- ASSERT_NO_FATAL_FAILURE(Init("shared_lib_in_apk_memory_only_arm64/", ARCH_ARM64));
- // Add the memory that represents the shared library.
- MemoryOfflineParts* memory = reinterpret_cast<MemoryOfflineParts*>(process_memory_.get());
- AddMemory(dir_ + "lib_mem.data", memory);
-
- Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
- unwinder.Unwind();
-
- std::string frame_info(DumpFrames(unwinder));
- ASSERT_EQ(7U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
- EXPECT_EQ(
- " #00 pc 000000000014ccbc linker64 (__dl_syscall+28)\n"
- " #01 pc 000000000005426c linker64 "
- "(__dl__ZL24debuggerd_signal_handleriP7siginfoPv+1128)\n"
- " #02 pc 00000000000008c0 vdso.so (__kernel_rt_sigreturn)\n"
- " #03 pc 00000000000846f4 libc.so (abort+172)\n"
- " #04 pc 0000000000084ad4 libc.so (__assert2+36)\n"
- " #05 pc 000000000003d5b4 ANGLEPrebuilt.apk (offset 0x21d5000)\n"
- " #06 pc 000000000007fe68 libc.so (__libc_init)\n",
- frame_info);
-
- EXPECT_EQ(0x7e82c4fcbcULL, unwinder.frames()[0].pc);
- EXPECT_EQ(0x7df8ca3bf0ULL, unwinder.frames()[0].sp);
- EXPECT_EQ(0x7e82b5726cULL, unwinder.frames()[1].pc);
- EXPECT_EQ(0x7df8ca3bf0ULL, unwinder.frames()[1].sp);
- EXPECT_EQ(0x7e82b018c0ULL, unwinder.frames()[2].pc);
- EXPECT_EQ(0x7df8ca3da0ULL, unwinder.frames()[2].sp);
- EXPECT_EQ(0x7e7eecc6f4ULL, unwinder.frames()[3].pc);
- EXPECT_EQ(0x7dabf3db60ULL, unwinder.frames()[3].sp);
- EXPECT_EQ(0x7e7eeccad4ULL, unwinder.frames()[4].pc);
- EXPECT_EQ(0x7dabf3dc40ULL, unwinder.frames()[4].sp);
- EXPECT_EQ(0x7dabc405b4ULL, unwinder.frames()[5].pc);
- EXPECT_EQ(0x7dabf3dc50ULL, unwinder.frames()[5].sp);
- EXPECT_EQ(0x7e7eec7e68ULL, unwinder.frames()[6].pc);
- EXPECT_EQ(0x7dabf3dc70ULL, unwinder.frames()[6].sp);
- // Ignore top frame since the test code was modified to end in __libc_init.
-}
-
-TEST_F(UnwindOfflineTest, shared_lib_in_apk_single_map_arm64) {
- ASSERT_NO_FATAL_FAILURE(Init("shared_lib_in_apk_single_map_arm64/", ARCH_ARM64));
-
- Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
- unwinder.Unwind();
-
- std::string frame_info(DumpFrames(unwinder));
- ASSERT_EQ(13U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
- EXPECT_EQ(
- " #00 pc 00000000000814bc libc.so (syscall+28)\n"
- " #01 pc 00000000008cdf5c test.apk (offset 0x5000)\n"
- " #02 pc 00000000008cde9c test.apk (offset 0x5000)\n"
- " #03 pc 00000000008cdd70 test.apk (offset 0x5000)\n"
- " #04 pc 00000000008ce408 test.apk (offset 0x5000)\n"
- " #05 pc 00000000008ce8d8 test.apk (offset 0x5000)\n"
- " #06 pc 00000000008ce814 test.apk (offset 0x5000)\n"
- " #07 pc 00000000008bcf60 test.apk (offset 0x5000)\n"
- " #08 pc 0000000000133024 test.apk (offset 0x5000)\n"
- " #09 pc 0000000000134ad0 test.apk (offset 0x5000)\n"
- " #10 pc 0000000000134b64 test.apk (offset 0x5000)\n"
- " #11 pc 00000000000e406c libc.so (__pthread_start(void*)+36)\n"
- " #12 pc 0000000000085e18 libc.so (__start_thread+64)\n",
- frame_info);
-
- EXPECT_EQ(0x7cbe0b14bcULL, unwinder.frames()[0].pc);
- EXPECT_EQ(0x7be4f077d0ULL, unwinder.frames()[0].sp);
- EXPECT_EQ(0x7be6715f5cULL, unwinder.frames()[1].pc);
- EXPECT_EQ(0x7be4f077d0ULL, unwinder.frames()[1].sp);
- EXPECT_EQ(0x7be6715e9cULL, unwinder.frames()[2].pc);
- EXPECT_EQ(0x7be4f07800ULL, unwinder.frames()[2].sp);
- EXPECT_EQ(0x7be6715d70ULL, unwinder.frames()[3].pc);
- EXPECT_EQ(0x7be4f07840ULL, unwinder.frames()[3].sp);
- EXPECT_EQ(0x7be6716408ULL, unwinder.frames()[4].pc);
- EXPECT_EQ(0x7be4f07860ULL, unwinder.frames()[4].sp);
- EXPECT_EQ(0x7be67168d8ULL, unwinder.frames()[5].pc);
- EXPECT_EQ(0x7be4f07880ULL, unwinder.frames()[5].sp);
- EXPECT_EQ(0x7be6716814ULL, unwinder.frames()[6].pc);
- EXPECT_EQ(0x7be4f078f0ULL, unwinder.frames()[6].sp);
- EXPECT_EQ(0x7be6704f60ULL, unwinder.frames()[7].pc);
- EXPECT_EQ(0x7be4f07910ULL, unwinder.frames()[7].sp);
- EXPECT_EQ(0x7be5f7b024ULL, unwinder.frames()[8].pc);
- EXPECT_EQ(0x7be4f07950ULL, unwinder.frames()[8].sp);
- EXPECT_EQ(0x7be5f7cad0ULL, unwinder.frames()[9].pc);
- EXPECT_EQ(0x7be4f07aa0ULL, unwinder.frames()[9].sp);
- EXPECT_EQ(0x7be5f7cb64ULL, unwinder.frames()[10].pc);
- EXPECT_EQ(0x7be4f07ce0ULL, unwinder.frames()[10].sp);
- EXPECT_EQ(0x7cbe11406cULL, unwinder.frames()[11].pc);
- EXPECT_EQ(0x7be4f07d00ULL, unwinder.frames()[11].sp);
- EXPECT_EQ(0x7cbe0b5e18ULL, unwinder.frames()[12].pc);
- EXPECT_EQ(0x7be4f07d20ULL, unwinder.frames()[12].sp);
-}
-
-TEST_F(UnwindOfflineTest, invalid_elf_offset_arm) {
- ASSERT_NO_FATAL_FAILURE(Init("invalid_elf_offset_arm/", ARCH_ARM, false));
-
- Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
- unwinder.Unwind();
-
- std::string frame_info(DumpFrames(unwinder));
- ASSERT_EQ(1U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
- EXPECT_EQ(" #00 pc 00aa7508 invalid.apk (offset 0x12e4000)\n", frame_info);
- EXPECT_EQ(0xc898f508, unwinder.frames()[0].pc);
- EXPECT_EQ(0xc2044218, unwinder.frames()[0].sp);
-}
-
-TEST_F(UnwindOfflineTest, load_bias_ro_rx_x86_64) {
- ASSERT_NO_FATAL_FAILURE(Init("load_bias_ro_rx_x86_64/", ARCH_X86_64));
-
- Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
- unwinder.Unwind();
-
- std::string frame_info(DumpFrames(unwinder));
- ASSERT_EQ(17U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
- EXPECT_EQ(
- " #00 pc 00000000000e9dd4 libc.so (__write+20)\n"
- " #01 pc 000000000007ab9c libc.so (_IO_file_write+44)\n"
- " #02 pc 0000000000079f3e libc.so\n"
- " #03 pc 000000000007bce8 libc.so (_IO_do_write+24)\n"
- " #04 pc 000000000007b26e libc.so (_IO_file_xsputn+270)\n"
- " #05 pc 000000000004f7f9 libc.so (_IO_vfprintf+1945)\n"
- " #06 pc 0000000000057cb5 libc.so (_IO_printf+165)\n"
- " #07 pc 0000000000ed1796 perfetto_unittests "
- "(testing::internal::PrettyUnitTestResultPrinter::OnTestIterationStart(testing::UnitTest "
- "const&, int)+374)\n"
- " #08 pc 0000000000ed30fd perfetto_unittests "
- "(testing::internal::TestEventRepeater::OnTestIterationStart(testing::UnitTest const&, "
- "int)+125)\n"
- " #09 pc 0000000000ed5e25 perfetto_unittests "
- "(testing::internal::UnitTestImpl::RunAllTests()+581)\n"
- " #10 pc 0000000000ef63f3 perfetto_unittests "
- "(bool "
- "testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, "
- "bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char "
- "const*)+131)\n"
- " #11 pc 0000000000ee2a21 perfetto_unittests "
- "(bool "
- "testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, "
- "bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char "
- "const*)+113)\n"
- " #12 pc 0000000000ed5bb9 perfetto_unittests (testing::UnitTest::Run()+185)\n"
- " #13 pc 0000000000e900f0 perfetto_unittests (RUN_ALL_TESTS()+16)\n"
- " #14 pc 0000000000e900d8 perfetto_unittests (main+56)\n"
- " #15 pc 000000000002352a libc.so (__libc_start_main+234)\n"
- " #16 pc 0000000000919029 perfetto_unittests (_start+41)\n",
- frame_info);
-
- EXPECT_EQ(0x7f9326a57dd4ULL, unwinder.frames()[0].pc);
- EXPECT_EQ(0x7ffd224153c8ULL, unwinder.frames()[0].sp);
- EXPECT_EQ(0x7f93269e8b9cULL, unwinder.frames()[1].pc);
- EXPECT_EQ(0x7ffd224153d0ULL, unwinder.frames()[1].sp);
- EXPECT_EQ(0x7f93269e7f3eULL, unwinder.frames()[2].pc);
- EXPECT_EQ(0x7ffd22415400ULL, unwinder.frames()[2].sp);
- EXPECT_EQ(0x7f93269e9ce8ULL, unwinder.frames()[3].pc);
- EXPECT_EQ(0x7ffd22415440ULL, unwinder.frames()[3].sp);
- EXPECT_EQ(0x7f93269e926eULL, unwinder.frames()[4].pc);
- EXPECT_EQ(0x7ffd22415450ULL, unwinder.frames()[4].sp);
- EXPECT_EQ(0x7f93269bd7f9ULL, unwinder.frames()[5].pc);
- EXPECT_EQ(0x7ffd22415490ULL, unwinder.frames()[5].sp);
- EXPECT_EQ(0x7f93269c5cb5ULL, unwinder.frames()[6].pc);
- EXPECT_EQ(0x7ffd22415a10ULL, unwinder.frames()[6].sp);
- EXPECT_EQ(0xed1796ULL, unwinder.frames()[7].pc);
- EXPECT_EQ(0x7ffd22415af0ULL, unwinder.frames()[7].sp);
- EXPECT_EQ(0xed30fdULL, unwinder.frames()[8].pc);
- EXPECT_EQ(0x7ffd22415b70ULL, unwinder.frames()[8].sp);
- EXPECT_EQ(0xed5e25ULL, unwinder.frames()[9].pc);
- EXPECT_EQ(0x7ffd22415bb0ULL, unwinder.frames()[9].sp);
- EXPECT_EQ(0xef63f3ULL, unwinder.frames()[10].pc);
- EXPECT_EQ(0x7ffd22415c60ULL, unwinder.frames()[10].sp);
- EXPECT_EQ(0xee2a21ULL, unwinder.frames()[11].pc);
- EXPECT_EQ(0x7ffd22415cc0ULL, unwinder.frames()[11].sp);
- EXPECT_EQ(0xed5bb9ULL, unwinder.frames()[12].pc);
- EXPECT_EQ(0x7ffd22415d40ULL, unwinder.frames()[12].sp);
- EXPECT_EQ(0xe900f0ULL, unwinder.frames()[13].pc);
- EXPECT_EQ(0x7ffd22415d90ULL, unwinder.frames()[13].sp);
- EXPECT_EQ(0xe900d8ULL, unwinder.frames()[14].pc);
- EXPECT_EQ(0x7ffd22415da0ULL, unwinder.frames()[14].sp);
- EXPECT_EQ(0x7f932699152aULL, unwinder.frames()[15].pc);
- EXPECT_EQ(0x7ffd22415dd0ULL, unwinder.frames()[15].sp);
- EXPECT_EQ(0x919029ULL, unwinder.frames()[16].pc);
- EXPECT_EQ(0x7ffd22415e90ULL, unwinder.frames()[16].sp);
-}
-
-TEST_F(UnwindOfflineTest, load_bias_different_section_bias_arm64) {
- ASSERT_NO_FATAL_FAILURE(Init("load_bias_different_section_bias_arm64/", ARCH_ARM64));
-
- Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
- unwinder.Unwind();
-
- std::string frame_info(DumpFrames(unwinder));
- ASSERT_EQ(12U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
- EXPECT_EQ(
- " #00 pc 00000000000d59bc linker64 (__dl_syscall+28)\n"
- " #01 pc 00000000000554e8 linker64 (__dl__ZL24debuggerd_signal_handleriP7siginfoPv+1148)\n"
- " #02 pc 00000000000008c0 vdso (__kernel_rt_sigreturn)\n"
- " #03 pc 000000000007f3e8 libc.so (abort+168)\n"
- " #04 pc 00000000000459fc test (std::__ndk1::__throw_bad_cast()+4)\n"
- " #05 pc 0000000000056d80 test (testing::Test::Run()+88)\n"
- " #06 pc 000000000005724c test (testing::TestInfo::Run()+112)\n"
- " #07 pc 0000000000057558 test (testing::TestSuite::Run()+116)\n"
- " #08 pc 000000000005bffc test (testing::internal::UnitTestImpl::RunAllTests()+464)\n"
- " #09 pc 000000000005bd9c test (testing::UnitTest::Run()+116)\n"
- " #10 pc 00000000000464e4 test (main+144)\n"
- " #11 pc 000000000007aa34 libc.so (__libc_init+108)\n",
- frame_info);
-
- EXPECT_EQ(0x7112cb99bcULL, unwinder.frames()[0].pc);
- EXPECT_EQ(0x7112bdbbf0ULL, unwinder.frames()[0].sp);
- EXPECT_EQ(0x7112c394e8ULL, unwinder.frames()[1].pc);
- EXPECT_EQ(0x7112bdbbf0ULL, unwinder.frames()[1].sp);
- EXPECT_EQ(0x7112be28c0ULL, unwinder.frames()[2].pc);
- EXPECT_EQ(0x7112bdbda0ULL, unwinder.frames()[2].sp);
- EXPECT_EQ(0x71115ab3e8ULL, unwinder.frames()[3].pc);
- EXPECT_EQ(0x7fdd4a3f00ULL, unwinder.frames()[3].sp);
- EXPECT_EQ(0x5f739dc9fcULL, unwinder.frames()[4].pc);
- EXPECT_EQ(0x7fdd4a3fe0ULL, unwinder.frames()[4].sp);
- EXPECT_EQ(0x5f739edd80ULL, unwinder.frames()[5].pc);
- EXPECT_EQ(0x7fdd4a3ff0ULL, unwinder.frames()[5].sp);
- EXPECT_EQ(0x5f739ee24cULL, unwinder.frames()[6].pc);
- EXPECT_EQ(0x7fdd4a4010ULL, unwinder.frames()[6].sp);
- EXPECT_EQ(0x5f739ee558ULL, unwinder.frames()[7].pc);
- EXPECT_EQ(0x7fdd4a4040ULL, unwinder.frames()[7].sp);
- EXPECT_EQ(0x5f739f2ffcULL, unwinder.frames()[8].pc);
- EXPECT_EQ(0x7fdd4a4070ULL, unwinder.frames()[8].sp);
- EXPECT_EQ(0x5f739f2d9cULL, unwinder.frames()[9].pc);
- EXPECT_EQ(0x7fdd4a4100ULL, unwinder.frames()[9].sp);
- EXPECT_EQ(0x5f739dd4e4ULL, unwinder.frames()[10].pc);
- EXPECT_EQ(0x7fdd4a4130ULL, unwinder.frames()[10].sp);
- EXPECT_EQ(0x71115a6a34ULL, unwinder.frames()[11].pc);
- EXPECT_EQ(0x7fdd4a4170ULL, unwinder.frames()[11].sp);
-}
-
-TEST_F(UnwindOfflineTest, eh_frame_bias_x86) {
- ASSERT_NO_FATAL_FAILURE(Init("eh_frame_bias_x86/", ARCH_X86));
-
- Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
- unwinder.Unwind();
-
- std::string frame_info(DumpFrames(unwinder));
- ASSERT_EQ(11U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
- EXPECT_EQ(
- " #00 pc ffffe430 vdso.so (__kernel_vsyscall+16)\n"
- " #01 pc 00082a4b libc.so (__epoll_pwait+43)\n"
- " #02 pc 000303a3 libc.so (epoll_pwait+115)\n"
- " #03 pc 000303ed libc.so (epoll_wait+45)\n"
- " #04 pc 00010ea2 tombstoned (epoll_dispatch+226)\n"
- " #05 pc 0000c5e7 tombstoned (event_base_loop+1095)\n"
- " #06 pc 0000c193 tombstoned (event_base_dispatch+35)\n"
- " #07 pc 00005c77 tombstoned (main+884)\n"
- " #08 pc 00015f66 libc.so (__libc_init+102)\n"
- " #09 pc 0000360e tombstoned (_start+98)\n"
- " #10 pc 00000001 <unknown>\n",
- frame_info);
-
- EXPECT_EQ(0xffffe430ULL, unwinder.frames()[0].pc);
- EXPECT_EQ(0xfffe1a30ULL, unwinder.frames()[0].sp);
- EXPECT_EQ(0xeb585a4bULL, unwinder.frames()[1].pc);
- EXPECT_EQ(0xfffe1a40ULL, unwinder.frames()[1].sp);
- EXPECT_EQ(0xeb5333a3ULL, unwinder.frames()[2].pc);
- EXPECT_EQ(0xfffe1a60ULL, unwinder.frames()[2].sp);
- EXPECT_EQ(0xeb5333edULL, unwinder.frames()[3].pc);
- EXPECT_EQ(0xfffe1ab0ULL, unwinder.frames()[3].sp);
- EXPECT_EQ(0xeb841ea2ULL, unwinder.frames()[4].pc);
- EXPECT_EQ(0xfffe1ae0ULL, unwinder.frames()[4].sp);
- EXPECT_EQ(0xeb83d5e7ULL, unwinder.frames()[5].pc);
- EXPECT_EQ(0xfffe1b30ULL, unwinder.frames()[5].sp);
- EXPECT_EQ(0xeb83d193ULL, unwinder.frames()[6].pc);
- EXPECT_EQ(0xfffe1bd0ULL, unwinder.frames()[6].sp);
- EXPECT_EQ(0xeb836c77ULL, unwinder.frames()[7].pc);
- EXPECT_EQ(0xfffe1c00ULL, unwinder.frames()[7].sp);
- EXPECT_EQ(0xeb518f66ULL, unwinder.frames()[8].pc);
- EXPECT_EQ(0xfffe1d00ULL, unwinder.frames()[8].sp);
- EXPECT_EQ(0xeb83460eULL, unwinder.frames()[9].pc);
- EXPECT_EQ(0xfffe1d40ULL, unwinder.frames()[9].sp);
- EXPECT_EQ(0x00000001ULL, unwinder.frames()[10].pc);
- EXPECT_EQ(0xfffe1d74ULL, unwinder.frames()[10].sp);
-}
-
-TEST_F(UnwindOfflineTest, signal_load_bias_arm) {
- ASSERT_NO_FATAL_FAILURE(Init("signal_load_bias_arm/", ARCH_ARM));
-
- Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
- unwinder.Unwind();
-
- std::string frame_info(DumpFrames(unwinder));
- ASSERT_EQ(17U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
- EXPECT_EQ(
- " #00 pc 0029ef9e libunwindstack_unit_test (SignalInnerFunction+10)\n"
- " #01 pc 0029efa7 libunwindstack_unit_test (SignalMiddleFunction+2)\n"
- " #02 pc 0029efaf libunwindstack_unit_test (SignalOuterFunction+2)\n"
- " #03 pc 002a280b libunwindstack_unit_test (unwindstack::SignalCallerHandler(int, "
- "siginfo*, void*)+10)\n"
- " #04 pc 00058bd4 libc.so (__restore)\n"
- " #05 pc 0029f01e libunwindstack_unit_test (InnerFunction+106)\n"
- " #06 pc 0029f633 libunwindstack_unit_test (MiddleFunction+16)\n"
- " #07 pc 0029f64b libunwindstack_unit_test (OuterFunction+16)\n"
- " #08 pc 002a1711 libunwindstack_unit_test (unwindstack::RemoteThroughSignal(int, unsigned "
- "int)+260)\n"
- " #09 pc 002a1603 libunwindstack_unit_test "
- "(unwindstack::UnwindTest_remote_through_signal_Test::TestBody()+10)\n"
- " #10 pc 002c8fe3 libunwindstack_unit_test (testing::Test::Run()+130)\n"
- " #11 pc 002c9b25 libunwindstack_unit_test (testing::TestInfo::Run()+184)\n"
- " #12 pc 002c9e27 libunwindstack_unit_test (testing::TestSuite::Run()+202)\n"
- " #13 pc 002d193d libunwindstack_unit_test "
- "(testing::internal::UnitTestImpl::RunAllTests()+660)\n"
- " #14 pc 002d160b libunwindstack_unit_test (testing::UnitTest::Run()+134)\n"
- " #15 pc 002de035 libunwindstack_unit_test (IsolateMain+680)\n"
- " #16 pc 00058155 libc.so (__libc_init+68)\n",
- frame_info);
-
- EXPECT_EQ(0xb6955f9eULL, unwinder.frames()[0].pc);
- EXPECT_EQ(0xf2790ce8ULL, unwinder.frames()[0].sp);
- EXPECT_EQ(0xb6955fa7ULL, unwinder.frames()[1].pc);
- EXPECT_EQ(0xf2790ce8ULL, unwinder.frames()[1].sp);
- EXPECT_EQ(0xb6955fafULL, unwinder.frames()[2].pc);
- EXPECT_EQ(0xf2790cf0ULL, unwinder.frames()[2].sp);
- EXPECT_EQ(0xb695980bULL, unwinder.frames()[3].pc);
- EXPECT_EQ(0xf2790cf8ULL, unwinder.frames()[3].sp);
- EXPECT_EQ(0xf23febd4ULL, unwinder.frames()[4].pc);
- EXPECT_EQ(0xf2790d10ULL, unwinder.frames()[4].sp);
- EXPECT_EQ(0xb695601eULL, unwinder.frames()[5].pc);
- EXPECT_EQ(0xffe67798ULL, unwinder.frames()[5].sp);
- EXPECT_EQ(0xb6956633ULL, unwinder.frames()[6].pc);
- EXPECT_EQ(0xffe67890ULL, unwinder.frames()[6].sp);
- EXPECT_EQ(0xb695664bULL, unwinder.frames()[7].pc);
- EXPECT_EQ(0xffe678a0ULL, unwinder.frames()[7].sp);
- EXPECT_EQ(0xb6958711ULL, unwinder.frames()[8].pc);
- EXPECT_EQ(0xffe678b0ULL, unwinder.frames()[8].sp);
- EXPECT_EQ(0xb6958603ULL, unwinder.frames()[9].pc);
- EXPECT_EQ(0xffe67ac8ULL, unwinder.frames()[9].sp);
- EXPECT_EQ(0xb697ffe3ULL, unwinder.frames()[10].pc);
- EXPECT_EQ(0xffe67ad8ULL, unwinder.frames()[10].sp);
- EXPECT_EQ(0xb6980b25ULL, unwinder.frames()[11].pc);
- EXPECT_EQ(0xffe67ae8ULL, unwinder.frames()[11].sp);
- EXPECT_EQ(0xb6980e27ULL, unwinder.frames()[12].pc);
- EXPECT_EQ(0xffe67b18ULL, unwinder.frames()[12].sp);
- EXPECT_EQ(0xb698893dULL, unwinder.frames()[13].pc);
- EXPECT_EQ(0xffe67b48ULL, unwinder.frames()[13].sp);
- EXPECT_EQ(0xb698860bULL, unwinder.frames()[14].pc);
- EXPECT_EQ(0xffe67bb0ULL, unwinder.frames()[14].sp);
- EXPECT_EQ(0xb6995035ULL, unwinder.frames()[15].pc);
- EXPECT_EQ(0xffe67bd0ULL, unwinder.frames()[15].sp);
- EXPECT_EQ(0xf23fe155ULL, unwinder.frames()[16].pc);
- EXPECT_EQ(0xffe67d10ULL, unwinder.frames()[16].sp);
-}
-
-TEST_F(UnwindOfflineTest, empty_arm64) {
- ASSERT_NO_FATAL_FAILURE(Init("empty_arm64/", ARCH_ARM64));
-
- Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
- unwinder.Unwind();
-
- std::string frame_info(DumpFrames(unwinder));
- ASSERT_EQ(7U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
- EXPECT_EQ(
- " #00 pc 00000000000963a4 libc.so (__ioctl+4)\n"
- " #01 pc 000000000005344c libc.so (ioctl+140)\n"
- " #02 pc 0000000000050ce4 libbinder.so "
- "(android::IPCThreadState::talkWithDriver(bool)+308)\n"
- " #03 pc 0000000000050e98 libbinder.so "
- "(android::IPCThreadState::getAndExecuteCommand()+24)\n"
- " #04 pc 00000000000516ac libbinder.so (android::IPCThreadState::joinThreadPool(bool)+60)\n"
- " #05 pc 00000000000443b0 netd (main+1056)\n"
- " #06 pc 0000000000045594 libc.so (__libc_init+108)\n",
- frame_info);
-
- EXPECT_EQ(0x72a02203a4U, unwinder.frames()[0].pc);
- EXPECT_EQ(0x7ffb6c0b50U, unwinder.frames()[0].sp);
- EXPECT_EQ(0x72a01dd44cU, unwinder.frames()[1].pc);
- EXPECT_EQ(0x7ffb6c0b50U, unwinder.frames()[1].sp);
- EXPECT_EQ(0x729f759ce4U, unwinder.frames()[2].pc);
- EXPECT_EQ(0x7ffb6c0c50U, unwinder.frames()[2].sp);
- EXPECT_EQ(0x729f759e98U, unwinder.frames()[3].pc);
- EXPECT_EQ(0x7ffb6c0ce0U, unwinder.frames()[3].sp);
- EXPECT_EQ(0x729f75a6acU, unwinder.frames()[4].pc);
- EXPECT_EQ(0x7ffb6c0d10U, unwinder.frames()[4].sp);
- EXPECT_EQ(0x5d478af3b0U, unwinder.frames()[5].pc);
- EXPECT_EQ(0x7ffb6c0d40U, unwinder.frames()[5].sp);
- EXPECT_EQ(0x72a01cf594U, unwinder.frames()[6].pc);
- 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/UnwindTest.cpp b/libunwindstack/tests/UnwindTest.cpp
deleted file mode 100644
index b11d213..0000000
--- a/libunwindstack/tests/UnwindTest.cpp
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- * Copyright (C) 2017 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 <errno.h>
-#include <signal.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/ptrace.h>
-#include <sys/syscall.h>
-#include <unistd.h>
-
-#include <gtest/gtest.h>
-
-#include <atomic>
-#include <memory>
-#include <sstream>
-#include <string>
-#include <thread>
-#include <vector>
-
-#include <android-base/stringprintf.h>
-#include <android-base/threads.h>
-
-#include <unwindstack/Maps.h>
-#include <unwindstack/Regs.h>
-#include <unwindstack/RegsGetLocal.h>
-#include <unwindstack/Unwinder.h>
-
-#include "MemoryRemote.h"
-#include "TestUtils.h"
-
-namespace unwindstack {
-
-enum TestTypeEnum : uint8_t {
- TEST_TYPE_LOCAL_UNWINDER = 0,
- TEST_TYPE_LOCAL_UNWINDER_FROM_PID,
- TEST_TYPE_LOCAL_WAIT_FOR_FINISH,
- TEST_TYPE_REMOTE,
- TEST_TYPE_REMOTE_WITH_INVALID_CALL,
-};
-
-static std::atomic_bool g_ready;
-static volatile bool g_ready_for_remote;
-static volatile bool g_signal_ready_for_remote;
-static std::atomic_bool g_finish;
-static std::atomic_uintptr_t g_ucontext;
-
-static void ResetGlobals() {
- g_ready = false;
- g_ready_for_remote = false;
- g_signal_ready_for_remote = false;
- g_finish = false;
- g_ucontext = 0;
-}
-
-static std::vector<const char*> kFunctionOrder{"OuterFunction", "MiddleFunction", "InnerFunction"};
-
-static std::vector<const char*> kFunctionSignalOrder{"OuterFunction", "MiddleFunction",
- "InnerFunction", "SignalOuterFunction",
- "SignalMiddleFunction", "SignalInnerFunction"};
-
-static void SignalHandler(int, siginfo_t*, void* sigcontext) {
- g_ucontext = reinterpret_cast<uintptr_t>(sigcontext);
- while (!g_finish.load()) {
- }
-}
-
-extern "C" void SignalInnerFunction() {
- g_signal_ready_for_remote = true;
- // Avoid any function calls because not every instruction will be
- // unwindable.
- // This method of looping is only used when testing a remote unwind.
- while (true) {
- }
-}
-
-extern "C" void SignalMiddleFunction() {
- SignalInnerFunction();
-}
-
-extern "C" void SignalOuterFunction() {
- SignalMiddleFunction();
-}
-
-static void SignalCallerHandler(int, siginfo_t*, void*) {
- SignalOuterFunction();
-}
-
-static std::string ErrorMsg(const std::vector<const char*>& function_names, Unwinder* unwinder) {
- std::string unwind;
- for (size_t i = 0; i < unwinder->NumFrames(); i++) {
- unwind += unwinder->FormatFrame(i) + '\n';
- }
-
- return std::string(
- "Unwind completed without finding all frames\n"
- " Looking for function: ") +
- function_names.front() + "\n" + "Unwind data:\n" + unwind;
-}
-
-static void VerifyUnwind(Unwinder* unwinder, std::vector<const char*> expected_function_names) {
- unwinder->Unwind();
-
- for (auto& frame : unwinder->frames()) {
- if (frame.function_name == expected_function_names.back()) {
- expected_function_names.pop_back();
- if (expected_function_names.empty()) {
- break;
- }
- }
- }
-
- ASSERT_TRUE(expected_function_names.empty()) << ErrorMsg(expected_function_names, unwinder);
-}
-
-static void VerifyUnwind(pid_t pid, Maps* maps, Regs* regs,
- std::vector<const char*> expected_function_names) {
- auto process_memory(Memory::CreateProcessMemory(pid));
-
- Unwinder unwinder(512, maps, regs, process_memory);
- VerifyUnwind(&unwinder, expected_function_names);
-}
-
-// This test assumes that this code is compiled with optimizations turned
-// off. If this doesn't happen, then all of the calls will be optimized
-// away.
-extern "C" void InnerFunction(TestTypeEnum test_type) {
- if (test_type == TEST_TYPE_LOCAL_WAIT_FOR_FINISH) {
- while (!g_finish.load()) {
- }
- return;
- }
- if (test_type == TEST_TYPE_REMOTE || test_type == TEST_TYPE_REMOTE_WITH_INVALID_CALL) {
- g_ready_for_remote = true;
- g_ready = true;
- if (test_type == TEST_TYPE_REMOTE_WITH_INVALID_CALL) {
- void (*crash_func)() = nullptr;
- crash_func();
- }
- // Avoid any function calls because not every instruction will be
- // unwindable.
- // This method of looping is only used when testing a remote unwind.
- while (true) {
- }
- return;
- }
-
- std::unique_ptr<Unwinder> unwinder;
- std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
- RegsGetLocal(regs.get());
- std::unique_ptr<Maps> maps;
-
- if (test_type == TEST_TYPE_LOCAL_UNWINDER) {
- maps.reset(new LocalMaps());
- ASSERT_TRUE(maps->Parse());
- auto process_memory(Memory::CreateProcessMemory(getpid()));
- unwinder.reset(new Unwinder(512, maps.get(), regs.get(), process_memory));
- } else {
- UnwinderFromPid* unwinder_from_pid = new UnwinderFromPid(512, getpid());
- unwinder_from_pid->SetRegs(regs.get());
- unwinder.reset(unwinder_from_pid);
- }
- VerifyUnwind(unwinder.get(), kFunctionOrder);
-}
-
-extern "C" void MiddleFunction(TestTypeEnum test_type) {
- InnerFunction(test_type);
-}
-
-extern "C" void OuterFunction(TestTypeEnum test_type) {
- MiddleFunction(test_type);
-}
-
-class UnwindTest : public ::testing::Test {
- public:
- void SetUp() override { ResetGlobals(); }
-};
-
-TEST_F(UnwindTest, local) {
- OuterFunction(TEST_TYPE_LOCAL_UNWINDER);
-}
-
-TEST_F(UnwindTest, local_use_from_pid) {
- OuterFunction(TEST_TYPE_LOCAL_UNWINDER_FROM_PID);
-}
-
-static void LocalUnwind(void* data) {
- TestTypeEnum* test_type = reinterpret_cast<TestTypeEnum*>(data);
- OuterFunction(*test_type);
-}
-
-TEST_F(UnwindTest, local_check_for_leak) {
- TestTypeEnum test_type = TEST_TYPE_LOCAL_UNWINDER;
- TestCheckForLeaks(LocalUnwind, &test_type);
-}
-
-TEST_F(UnwindTest, local_use_from_pid_check_for_leak) {
- TestTypeEnum test_type = TEST_TYPE_LOCAL_UNWINDER_FROM_PID;
- TestCheckForLeaks(LocalUnwind, &test_type);
-}
-
-void WaitForRemote(pid_t pid, uint64_t addr, bool leave_attached, bool* completed) {
- *completed = false;
- // Need to sleep before attempting first ptrace. Without this, on the
- // host it becomes impossible to attach and ptrace sets errno to EPERM.
- usleep(1000);
- for (size_t i = 0; i < 1000; i++) {
- if (ptrace(PTRACE_ATTACH, pid, 0, 0) == 0) {
- ASSERT_TRUE(TestQuiescePid(pid))
- << "Waiting for process to quiesce failed: " << strerror(errno);
-
- MemoryRemote memory(pid);
- // Read the remote value to see if we are ready.
- bool value;
- if (memory.ReadFully(addr, &value, sizeof(value)) && value) {
- *completed = true;
- }
- if (!*completed || !leave_attached) {
- ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0));
- }
- if (*completed) {
- break;
- }
- } else {
- ASSERT_EQ(ESRCH, errno) << "ptrace attach failed with unexpected error: " << strerror(errno);
- }
- usleep(5000);
- }
-}
-
-TEST_F(UnwindTest, remote) {
- pid_t pid;
- if ((pid = fork()) == 0) {
- OuterFunction(TEST_TYPE_REMOTE);
- exit(0);
- }
- ASSERT_NE(-1, pid);
- TestScopedPidReaper reap(pid);
-
- bool completed;
- WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_ready_for_remote), true, &completed);
- ASSERT_TRUE(completed) << "Timed out waiting for remote process to be ready.";
-
- RemoteMaps maps(pid);
- ASSERT_TRUE(maps.Parse());
- std::unique_ptr<Regs> regs(Regs::RemoteGet(pid));
- ASSERT_TRUE(regs.get() != nullptr);
-
- VerifyUnwind(pid, &maps, regs.get(), kFunctionOrder);
-
- ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0))
- << "ptrace detach failed with unexpected error: " << strerror(errno);
-}
-
-TEST_F(UnwindTest, unwind_from_pid_remote) {
- pid_t pid;
- if ((pid = fork()) == 0) {
- OuterFunction(TEST_TYPE_REMOTE);
- exit(0);
- }
- ASSERT_NE(-1, pid);
- TestScopedPidReaper reap(pid);
-
- bool completed;
- WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_ready_for_remote), true, &completed);
- ASSERT_TRUE(completed) << "Timed out waiting for remote process to be ready.";
-
- std::unique_ptr<Regs> regs(Regs::RemoteGet(pid));
- ASSERT_TRUE(regs.get() != nullptr);
-
- UnwinderFromPid unwinder(512, pid);
- unwinder.SetRegs(regs.get());
-
- VerifyUnwind(&unwinder, kFunctionOrder);
-
- // Verify that calling the same object works again.
-
- ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0))
- << "ptrace detach failed with unexpected error: " << strerror(errno);
-}
-
-static void RemoteCheckForLeaks(void (*unwind_func)(void*)) {
- pid_t pid;
- if ((pid = fork()) == 0) {
- OuterFunction(TEST_TYPE_REMOTE);
- exit(0);
- }
- ASSERT_NE(-1, pid);
- TestScopedPidReaper reap(pid);
-
- bool completed;
- WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_ready_for_remote), true, &completed);
- ASSERT_TRUE(completed) << "Timed out waiting for remote process to be ready.";
-
- TestCheckForLeaks(unwind_func, &pid);
-
- ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0))
- << "ptrace detach failed with unexpected error: " << strerror(errno);
-}
-
-static void RemoteUnwind(void* data) {
- pid_t* pid = reinterpret_cast<pid_t*>(data);
-
- RemoteMaps maps(*pid);
- ASSERT_TRUE(maps.Parse());
- std::unique_ptr<Regs> regs(Regs::RemoteGet(*pid));
- ASSERT_TRUE(regs.get() != nullptr);
-
- VerifyUnwind(*pid, &maps, regs.get(), kFunctionOrder);
-}
-
-TEST_F(UnwindTest, remote_check_for_leaks) {
- RemoteCheckForLeaks(RemoteUnwind);
-}
-
-static void RemoteUnwindFromPid(void* data) {
- pid_t* pid = reinterpret_cast<pid_t*>(data);
-
- std::unique_ptr<Regs> regs(Regs::RemoteGet(*pid));
- ASSERT_TRUE(regs.get() != nullptr);
-
- UnwinderFromPid unwinder(512, *pid);
- unwinder.SetRegs(regs.get());
-
- VerifyUnwind(&unwinder, kFunctionOrder);
-}
-
-TEST_F(UnwindTest, remote_unwind_for_pid_check_for_leaks) {
- RemoteCheckForLeaks(RemoteUnwindFromPid);
-}
-
-TEST_F(UnwindTest, from_context) {
- std::atomic_int tid(0);
- std::thread thread([&]() {
- tid = syscall(__NR_gettid);
- OuterFunction(TEST_TYPE_LOCAL_WAIT_FOR_FINISH);
- });
-
- struct sigaction act, oldact;
- memset(&act, 0, sizeof(act));
- act.sa_sigaction = SignalHandler;
- act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
- ASSERT_EQ(0, sigaction(SIGUSR1, &act, &oldact));
- // Wait for the tid to get set.
- for (size_t i = 0; i < 100; i++) {
- if (tid.load() != 0) {
- break;
- }
- usleep(1000);
- }
- ASSERT_NE(0, tid.load());
- ASSERT_EQ(0, tgkill(getpid(), tid.load(), SIGUSR1)) << "Error: " << strerror(errno);
-
- // Wait for context data.
- void* ucontext;
- for (size_t i = 0; i < 2000; i++) {
- ucontext = reinterpret_cast<void*>(g_ucontext.load());
- if (ucontext != nullptr) {
- break;
- }
- usleep(1000);
- }
- ASSERT_TRUE(ucontext != nullptr) << "Timed out waiting for thread to respond to signal.";
-
- LocalMaps maps;
- ASSERT_TRUE(maps.Parse());
- std::unique_ptr<Regs> regs(Regs::CreateFromUcontext(Regs::CurrentArch(), ucontext));
-
- VerifyUnwind(getpid(), &maps, regs.get(), kFunctionOrder);
-
- ASSERT_EQ(0, sigaction(SIGUSR1, &oldact, nullptr));
-
- g_finish = true;
- thread.join();
-}
-
-static void RemoteThroughSignal(int signal, unsigned int sa_flags) {
- pid_t pid;
- if ((pid = fork()) == 0) {
- struct sigaction act, oldact;
- memset(&act, 0, sizeof(act));
- act.sa_sigaction = SignalCallerHandler;
- act.sa_flags = SA_RESTART | SA_ONSTACK | sa_flags;
- ASSERT_EQ(0, sigaction(signal, &act, &oldact));
-
- OuterFunction(signal != SIGSEGV ? TEST_TYPE_REMOTE : TEST_TYPE_REMOTE_WITH_INVALID_CALL);
- exit(0);
- }
- ASSERT_NE(-1, pid);
- TestScopedPidReaper reap(pid);
-
- bool completed;
- if (signal != SIGSEGV) {
- WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_ready_for_remote), false, &completed);
- ASSERT_TRUE(completed) << "Timed out waiting for remote process to be ready.";
- ASSERT_EQ(0, kill(pid, SIGUSR1));
- }
- WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_signal_ready_for_remote), true, &completed);
- ASSERT_TRUE(completed) << "Timed out waiting for remote process to be in signal handler.";
-
- RemoteMaps maps(pid);
- ASSERT_TRUE(maps.Parse());
- std::unique_ptr<Regs> regs(Regs::RemoteGet(pid));
- ASSERT_TRUE(regs.get() != nullptr);
-
- VerifyUnwind(pid, &maps, regs.get(), kFunctionSignalOrder);
-
- ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0))
- << "ptrace detach failed with unexpected error: " << strerror(errno);
-}
-
-TEST_F(UnwindTest, remote_through_signal) {
- RemoteThroughSignal(SIGUSR1, 0);
-}
-
-TEST_F(UnwindTest, remote_through_signal_sa_siginfo) {
- RemoteThroughSignal(SIGUSR1, SA_SIGINFO);
-}
-
-TEST_F(UnwindTest, remote_through_signal_with_invalid_func) {
- RemoteThroughSignal(SIGSEGV, 0);
-}
-
-TEST_F(UnwindTest, remote_through_signal_sa_siginfo_with_invalid_func) {
- RemoteThroughSignal(SIGSEGV, SA_SIGINFO);
-}
-
-// Verify that using the same map while unwinding multiple threads at the
-// same time doesn't cause problems.
-TEST_F(UnwindTest, multiple_threads_unwind_same_map) {
- static constexpr size_t kNumConcurrentThreads = 100;
-
- LocalMaps maps;
- ASSERT_TRUE(maps.Parse());
- auto process_memory(Memory::CreateProcessMemory(getpid()));
-
- std::vector<std::thread*> threads;
-
- std::atomic_bool wait;
- wait = true;
- size_t frames[kNumConcurrentThreads];
- for (size_t i = 0; i < kNumConcurrentThreads; i++) {
- std::thread* thread = new std::thread([i, &frames, &maps, &process_memory, &wait]() {
- while (wait)
- ;
- std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
- RegsGetLocal(regs.get());
-
- Unwinder unwinder(512, &maps, regs.get(), process_memory);
- unwinder.Unwind();
- frames[i] = unwinder.NumFrames();
- ASSERT_LE(3U, frames[i]) << "Failed for thread " << i;
- });
- threads.push_back(thread);
- }
- wait = false;
- for (auto thread : threads) {
- thread->join();
- delete thread;
- }
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp
deleted file mode 100644
index 8bae242..0000000
--- a/libunwindstack/tests/UnwinderTest.cpp
+++ /dev/null
@@ -1,1771 +0,0 @@
-/*
- * Copyright (C) 2017 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 <elf.h>
-#include <stdint.h>
-#include <sys/mman.h>
-
-#include <memory>
-#include <set>
-#include <string>
-
-#include <gtest/gtest.h>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/Regs.h>
-#include <unwindstack/RegsArm.h>
-#include <unwindstack/RegsArm64.h>
-#include <unwindstack/RegsX86.h>
-#include <unwindstack/RegsX86_64.h>
-#include <unwindstack/RegsMips.h>
-#include <unwindstack/RegsMips64.h>
-#include <unwindstack/Unwinder.h>
-
-#include "ElfFake.h"
-#include "ElfTestUtils.h"
-#include "MemoryFake.h"
-#include "RegsFake.h"
-
-namespace unwindstack {
-
-class UnwinderTest : public ::testing::Test {
- protected:
- static MapInfo* AddMapInfo(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
- const char* name, Elf* elf = nullptr) {
- std::string str_name(name);
- maps_->Add(start, end, offset, flags, name, static_cast<uint64_t>(-1));
- MapInfo* map_info = maps_->Find(start);
- if (elf != nullptr) {
- map_info->elf.reset(elf);
- }
- return map_info;
- }
-
- static void SetUpTestSuite() {
- maps_.reset(new Maps);
-
- memory_ = new MemoryFake;
- process_memory_.reset(memory_);
-
- ElfFake* elf;
- ElfInterfaceFake* interface;
- MapInfo* map_info;
-
- elf = new ElfFake(new MemoryFake);
- interface = new ElfInterfaceFake(nullptr);
- interface->FakeSetBuildID("FAKE");
- elf->FakeSetInterface(interface);
- AddMapInfo(0x1000, 0x8000, 0, PROT_READ | PROT_WRITE, "/system/fake/libc.so", elf);
-
- AddMapInfo(0x10000, 0x12000, 0, PROT_READ | PROT_WRITE, "[stack]");
-
- AddMapInfo(0x13000, 0x15000, 0, PROT_READ | PROT_WRITE | MAPS_FLAGS_DEVICE_MAP,
- "/dev/fake_device");
-
- elf = new ElfFake(new MemoryFake);
- elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
- AddMapInfo(0x20000, 0x22000, 0, PROT_READ | PROT_WRITE, "/system/fake/libunwind.so", elf);
-
- elf = new ElfFake(new MemoryFake);
- elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
- AddMapInfo(0x23000, 0x24000, 0, PROT_READ | PROT_WRITE, "/fake/libanother.so", elf);
-
- elf = new ElfFake(new MemoryFake);
- elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
- AddMapInfo(0x33000, 0x34000, 0, PROT_READ | PROT_WRITE, "/fake/compressed.so", elf);
-
- elf = new ElfFake(new MemoryFake);
- interface = new ElfInterfaceFake(nullptr);
- interface->FakeSetSoname("lib_fake.so");
- elf->FakeSetInterface(interface);
- map_info = AddMapInfo(0x43000, 0x44000, 0x1d000, PROT_READ | PROT_WRITE, "/fake/fake.apk", elf);
- map_info->elf_start_offset = 0x1d000;
-
- AddMapInfo(0x53000, 0x54000, 0, PROT_READ | PROT_WRITE, "/fake/fake.oat");
-
- map_info =
- AddMapInfo(0xa3000, 0xa4000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/fake.vdex");
- map_info->load_bias = 0;
-
- elf = new ElfFake(new MemoryFake);
- elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
- elf->FakeSetLoadBias(0x5000);
- AddMapInfo(0xa5000, 0xa6000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/fake_load_bias.so",
- elf);
-
- elf = new ElfFake(new MemoryFake);
- elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
- map_info = AddMapInfo(0xa7000, 0xa8000, 0, PROT_READ | PROT_WRITE | PROT_EXEC,
- "/fake/fake_offset.oat", elf);
- map_info->elf_offset = 0x8000;
-
- elf = new ElfFake(new MemoryFake);
- elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
- map_info = AddMapInfo(0xc0000, 0xc1000, 0, PROT_READ | PROT_WRITE | PROT_EXEC,
- "/fake/unreadable.so", elf);
- map_info->memory_backed_elf = true;
-
- elf = new ElfFake(new MemoryFake);
- elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
- map_info = AddMapInfo(0xc1000, 0xc2000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "[vdso]", elf);
- map_info->memory_backed_elf = true;
-
- elf = new ElfFake(new MemoryFake);
- elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
- map_info = AddMapInfo(0xc2000, 0xc3000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "", elf);
- map_info->memory_backed_elf = true;
-
- elf = new ElfFake(new MemoryFake);
- elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
- map_info = AddMapInfo(0xc3000, 0xc4000, 0, PROT_READ | PROT_WRITE | PROT_EXEC,
- "/memfd:/jit-cache", elf);
- map_info->memory_backed_elf = true;
-
- map_info =
- AddMapInfo(0xd0000, 0xd1000, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/fake.apk");
- map_info->load_bias = 0;
-
- elf = new ElfFake(new MemoryFake);
- interface = new ElfInterfaceFake(nullptr);
- elf->FakeSetInterface(interface);
- interface->FakeSetGlobalVariable("__dex_debug_descriptor", 0x1800);
- interface->FakeSetGlobalVariable("__jit_debug_descriptor", 0x1900);
- interface->FakeSetDataOffset(0x1000);
- interface->FakeSetDataVaddrStart(0x1000);
- interface->FakeSetDataVaddrEnd(0x8000);
- AddMapInfo(0xf0000, 0xf1000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/global.so", elf);
- AddMapInfo(0xf1000, 0xf9000, 0x1000, PROT_READ | PROT_WRITE, "/fake/global.so");
- // dex debug data
- memory_->SetData32(0xf180c, 0xf3000);
- memory_->SetData32(0xf3000, 0xf4000);
- memory_->SetData32(0xf3004, 0xf4000);
- memory_->SetData32(0xf3008, 0xf5000);
- // jit debug data
- memory_->SetData32(0xf1900, 1);
- memory_->SetData32(0xf1904, 0);
- memory_->SetData32(0xf1908, 0xf6000);
- memory_->SetData32(0xf190c, 0xf6000);
- memory_->SetData32(0xf6000, 0);
- memory_->SetData32(0xf6004, 0);
- memory_->SetData32(0xf6008, 0xf7000);
- memory_->SetData32(0xf600c, 0);
- memory_->SetData64(0xf6010, 0x1000);
-
- elf = new ElfFake(new MemoryFake);
- elf->FakeSetValid(false);
- elf->FakeSetLoadBias(0x300);
- map_info = AddMapInfo(0x100000, 0x101000, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC,
- "/fake/jit.so", elf);
- map_info->elf_start_offset = 0x100;
- map_info->offset = 0x200;
-
-#if 0
- elf = new ElfFake(new MemoryFake);
- interface = new ElfInterfaceFake(nullptr);
- interface->FakePushFunctionData(FunctionData("Fake0", 10));
- AddMapInfo(0x110000, 0x111000, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/elf.so", elf);
-#endif
- }
-
- void SetUp() override {
- ElfInterfaceFake::FakeClear();
- regs_.FakeSetArch(ARCH_ARM);
- regs_.FakeSetReturnAddressValid(false);
- }
-
- static std::unique_ptr<Maps> maps_;
- static RegsFake regs_;
- static MemoryFake* memory_;
- static std::shared_ptr<Memory> process_memory_;
-};
-
-std::unique_ptr<Maps> UnwinderTest::maps_;
-RegsFake UnwinderTest::regs_(5);
-MemoryFake* UnwinderTest::memory_;
-std::shared_ptr<Memory> UnwinderTest::process_memory_(nullptr);
-
-TEST_F(UnwinderTest, multiple_frames) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
-
- regs_.set_pc(0x1000);
- regs_.set_sp(0x10000);
- ElfInterfaceFake::FakePushStepData(StepData(0x1104, 0x10010, false));
- ElfInterfaceFake::FakePushStepData(StepData(0x1204, 0x10020, false));
- ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(3U, unwinder.NumFrames());
-
- auto* frame = &unwinder.frames()[0];
- EXPECT_EQ(0U, frame->num);
- EXPECT_EQ(0U, frame->rel_pc);
- EXPECT_EQ(0x1000U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("Frame0", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("/system/fake/libc.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x1000U, frame->map_start);
- EXPECT_EQ(0x8000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-
- frame = &unwinder.frames()[1];
- EXPECT_EQ(1U, frame->num);
- EXPECT_EQ(0x100U, frame->rel_pc);
- EXPECT_EQ(0x1100U, frame->pc);
- EXPECT_EQ(0x10010U, frame->sp);
- EXPECT_EQ("Frame1", frame->function_name);
- EXPECT_EQ(1U, frame->function_offset);
- EXPECT_EQ("/system/fake/libc.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x1000U, frame->map_start);
- EXPECT_EQ(0x8000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-
- frame = &unwinder.frames()[2];
- EXPECT_EQ(2U, frame->num);
- EXPECT_EQ(0x200U, frame->rel_pc);
- EXPECT_EQ(0x1200U, frame->pc);
- EXPECT_EQ(0x10020U, frame->sp);
- EXPECT_EQ("Frame2", frame->function_name);
- EXPECT_EQ(2U, frame->function_offset);
- EXPECT_EQ("/system/fake/libc.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x1000U, frame->map_start);
- EXPECT_EQ(0x8000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-}
-
-TEST_F(UnwinderTest, multiple_frames_dont_resolve_names) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
-
- regs_.set_pc(0x1000);
- regs_.set_sp(0x10000);
- ElfInterfaceFake::FakePushStepData(StepData(0x1104, 0x10010, false));
- ElfInterfaceFake::FakePushStepData(StepData(0x1204, 0x10020, false));
- ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- unwinder.SetResolveNames(false);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(3U, unwinder.NumFrames());
-
- auto* frame = &unwinder.frames()[0];
- EXPECT_EQ(0U, frame->num);
- EXPECT_EQ(0U, frame->rel_pc);
- EXPECT_EQ(0x1000U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x1000U, frame->map_start);
- EXPECT_EQ(0x8000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-
- frame = &unwinder.frames()[1];
- EXPECT_EQ(1U, frame->num);
- EXPECT_EQ(0x100U, frame->rel_pc);
- EXPECT_EQ(0x1100U, frame->pc);
- EXPECT_EQ(0x10010U, frame->sp);
- EXPECT_EQ("", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x1000U, frame->map_start);
- EXPECT_EQ(0x8000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-
- frame = &unwinder.frames()[2];
- EXPECT_EQ(2U, frame->num);
- EXPECT_EQ(0x200U, frame->rel_pc);
- EXPECT_EQ(0x1200U, frame->pc);
- EXPECT_EQ(0x10020U, frame->sp);
- EXPECT_EQ("", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x1000U, frame->map_start);
- EXPECT_EQ(0x8000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-}
-
-TEST_F(UnwinderTest, non_zero_load_bias) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
-
- regs_.set_pc(0xa5500);
- regs_.set_sp(0x10000);
- ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(1U, unwinder.NumFrames());
-
- auto* frame = &unwinder.frames()[0];
- EXPECT_EQ(0U, frame->num);
- EXPECT_EQ(0x5500U, frame->rel_pc);
- EXPECT_EQ(0xa5500U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("Frame0", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("/fake/fake_load_bias.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0xa5000U, frame->map_start);
- EXPECT_EQ(0xa6000U, frame->map_end);
- EXPECT_EQ(0x5000U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
-}
-
-TEST_F(UnwinderTest, non_zero_elf_offset) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
-
- regs_.set_pc(0xa7500);
- regs_.set_sp(0x10000);
- ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(1U, unwinder.NumFrames());
-
- auto* frame = &unwinder.frames()[0];
- EXPECT_EQ(0U, frame->num);
- EXPECT_EQ(0x8500U, frame->rel_pc);
- EXPECT_EQ(0xa7500U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("Frame0", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("/fake/fake_offset.oat", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0xa7000U, frame->map_start);
- EXPECT_EQ(0xa8000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
-}
-
-TEST_F(UnwinderTest, non_zero_map_offset) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
-
- regs_.set_pc(0x43000);
- regs_.set_sp(0x10000);
- ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(1U, unwinder.NumFrames());
-
- auto* frame = &unwinder.frames()[0];
- EXPECT_EQ(0U, frame->num);
- EXPECT_EQ(0U, frame->rel_pc);
- EXPECT_EQ(0x43000U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("Frame0", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("/fake/fake.apk!lib_fake.so", frame->map_name);
- EXPECT_EQ(0x1d000U, frame->map_elf_start_offset);
- EXPECT_EQ(0x1d000U, frame->map_exact_offset);
- EXPECT_EQ(0x43000U, frame->map_start);
- EXPECT_EQ(0x44000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-}
-
-TEST_F(UnwinderTest, disable_embedded_soname) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
-
- regs_.set_pc(0x43000);
- regs_.set_sp(0x10000);
- ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- unwinder.SetEmbeddedSoname(false);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(1U, unwinder.NumFrames());
-
- auto* frame = &unwinder.frames()[0];
- EXPECT_EQ(0U, frame->num);
- EXPECT_EQ(0U, frame->rel_pc);
- EXPECT_EQ(0x43000U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("Frame0", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("/fake/fake.apk", frame->map_name);
- EXPECT_EQ(0x1d000U, frame->map_elf_start_offset);
- EXPECT_EQ(0x1d000U, frame->map_exact_offset);
- EXPECT_EQ(0x43000U, frame->map_start);
- EXPECT_EQ(0x44000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-}
-
-// Verify that no attempt to continue after the step indicates it is done.
-TEST_F(UnwinderTest, no_frames_after_finished) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame3", 3));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame4", 4));
-
- regs_.set_pc(0x1000);
- regs_.set_sp(0x10000);
- ElfInterfaceFake::FakePushStepData(StepData(0x1000, 0x10000, true));
- ElfInterfaceFake::FakePushStepData(StepData(0x1102, 0x10010, false));
- ElfInterfaceFake::FakePushStepData(StepData(0x1202, 0x10020, false));
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(1U, unwinder.NumFrames());
-
- auto* frame = &unwinder.frames()[0];
- EXPECT_EQ(0U, frame->num);
- EXPECT_EQ(0U, frame->rel_pc);
- EXPECT_EQ(0x1000U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("Frame0", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("/system/fake/libc.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x1000U, frame->map_start);
- EXPECT_EQ(0x8000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-}
-
-// Verify the maximum frames to save.
-TEST_F(UnwinderTest, max_frames) {
- for (size_t i = 0; i < 30; i++) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame" + std::to_string(i), i));
- ElfInterfaceFake::FakePushStepData(StepData(0x1104 + i * 0x100, 0x10010 + i * 0x10, false));
- }
-
- regs_.set_pc(0x1000);
- regs_.set_sp(0x10000);
-
- Unwinder unwinder(20, maps_.get(), ®s_, process_memory_);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_MAX_FRAMES_EXCEEDED, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(20U, unwinder.NumFrames());
-
- for (size_t i = 0; i < 20; i++) {
- auto* frame = &unwinder.frames()[i];
- EXPECT_EQ(i, frame->num);
- EXPECT_EQ(i * 0x100, frame->rel_pc) << "Failed at frame " << i;
- EXPECT_EQ(0x1000 + i * 0x100, frame->pc) << "Failed at frame " << i;
- EXPECT_EQ(0x10000 + 0x10 * i, frame->sp) << "Failed at frame " << i;
- EXPECT_EQ("Frame" + std::to_string(i), frame->function_name) << "Failed at frame " << i;
- EXPECT_EQ(i, frame->function_offset) << "Failed at frame " << i;
- EXPECT_EQ("/system/fake/libc.so", frame->map_name) << "Failed at frame " << i;
- EXPECT_EQ(0U, frame->map_elf_start_offset) << "Failed at frame " << i;
- EXPECT_EQ(0U, frame->map_exact_offset) << "Failed at frame " << i;
- EXPECT_EQ(0x1000U, frame->map_start) << "Failed at frame " << i;
- EXPECT_EQ(0x8000U, frame->map_end) << "Failed at frame " << i;
- EXPECT_EQ(0U, frame->map_load_bias) << "Failed at frame " << i;
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags) << "Failed at frame " << i;
- }
-}
-
-// Verify that initial map names frames are removed.
-TEST_F(UnwinderTest, verify_frames_skipped) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
-
- regs_.set_pc(0x20000);
- regs_.set_sp(0x10000);
- ElfInterfaceFake::FakePushStepData(StepData(0x23004, 0x10010, false));
- ElfInterfaceFake::FakePushStepData(StepData(0x23104, 0x10020, false));
- ElfInterfaceFake::FakePushStepData(StepData(0x20004, 0x10030, false));
- ElfInterfaceFake::FakePushStepData(StepData(0x21004, 0x10040, false));
- ElfInterfaceFake::FakePushStepData(StepData(0x1002, 0x10050, false));
- ElfInterfaceFake::FakePushStepData(StepData(0x21004, 0x10060, false));
- ElfInterfaceFake::FakePushStepData(StepData(0x23002, 0x10070, false));
- ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- std::vector<std::string> skip_libs{"libunwind.so", "libanother.so"};
- unwinder.Unwind(&skip_libs);
- EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(3U, unwinder.NumFrames());
-
- auto* frame = &unwinder.frames()[0];
- EXPECT_EQ(0U, frame->num);
- EXPECT_EQ(0U, frame->rel_pc);
- EXPECT_EQ(0x1000U, frame->pc);
- EXPECT_EQ(0x10050U, frame->sp);
- EXPECT_EQ("Frame0", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("/system/fake/libc.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x1000U, frame->map_start);
- EXPECT_EQ(0x8000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-
- frame = &unwinder.frames()[1];
- EXPECT_EQ(1U, frame->num);
- EXPECT_EQ(0x1000U, frame->rel_pc);
- EXPECT_EQ(0x21000U, frame->pc);
- EXPECT_EQ(0x10060U, frame->sp);
- EXPECT_EQ("Frame1", frame->function_name);
- EXPECT_EQ(1U, frame->function_offset);
- EXPECT_EQ("/system/fake/libunwind.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x20000U, frame->map_start);
- EXPECT_EQ(0x22000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-
- frame = &unwinder.frames()[2];
- EXPECT_EQ(2U, frame->num);
- EXPECT_EQ(0U, frame->rel_pc);
- EXPECT_EQ(0x23000U, frame->pc);
- EXPECT_EQ(0x10070U, frame->sp);
- EXPECT_EQ("Frame2", frame->function_name);
- EXPECT_EQ(2U, frame->function_offset);
- EXPECT_EQ("/fake/libanother.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x23000U, frame->map_start);
- EXPECT_EQ(0x24000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-}
-
-// Verify SP in a non-existant map is okay.
-TEST_F(UnwinderTest, sp_not_in_map) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
-
- regs_.set_pc(0x1000);
- regs_.set_sp(0x63000);
- ElfInterfaceFake::FakePushStepData(StepData(0x21004, 0x50020, false));
- ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(2U, unwinder.NumFrames());
-
- auto* frame = &unwinder.frames()[0];
- EXPECT_EQ(0U, frame->num);
- EXPECT_EQ(0U, frame->rel_pc);
- EXPECT_EQ(0x1000U, frame->pc);
- EXPECT_EQ(0x63000U, frame->sp);
- EXPECT_EQ("Frame0", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("/system/fake/libc.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x1000U, frame->map_start);
- EXPECT_EQ(0x8000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-
- frame = &unwinder.frames()[1];
- EXPECT_EQ(1U, frame->num);
- EXPECT_EQ(0x1000U, frame->rel_pc);
- EXPECT_EQ(0x21000U, frame->pc);
- EXPECT_EQ(0x50020U, frame->sp);
- EXPECT_EQ("Frame1", frame->function_name);
- EXPECT_EQ(1U, frame->function_offset);
- EXPECT_EQ("/system/fake/libunwind.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x20000U, frame->map_start);
- EXPECT_EQ(0x22000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-}
-
-// Verify PC in a device stops the unwind.
-TEST_F(UnwinderTest, pc_in_device_stops_unwind) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
-
- regs_.set_pc(0x13000);
- regs_.set_sp(0x10000);
- ElfInterfaceFake::FakePushStepData(StepData(0x23002, 0x10010, false));
- ElfInterfaceFake::FakePushStepData(StepData(0x23102, 0x10020, false));
- ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(1U, unwinder.NumFrames());
-}
-
-// Verify SP in a device stops the unwind.
-TEST_F(UnwinderTest, sp_in_device_stops_unwind) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
-
- regs_.set_pc(0x1000);
- regs_.set_sp(0x13000);
- ElfInterfaceFake::FakePushStepData(StepData(0x23002, 0x10010, false));
- ElfInterfaceFake::FakePushStepData(StepData(0x23102, 0x10020, false));
- ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(1U, unwinder.NumFrames());
-}
-
-// Verify a no map info frame gets a frame.
-TEST_F(UnwinderTest, pc_without_map) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
-
- regs_.set_pc(0x41000);
- regs_.set_sp(0x13000);
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_INVALID_MAP, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(1U, unwinder.NumFrames());
-
- auto* frame = &unwinder.frames()[0];
- EXPECT_EQ(0U, frame->num);
- EXPECT_EQ(0x41000U, frame->rel_pc);
- EXPECT_EQ(0x41000U, frame->pc);
- EXPECT_EQ(0x13000U, frame->sp);
- EXPECT_EQ("", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0U, frame->map_start);
- EXPECT_EQ(0U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(0, frame->map_flags);
-}
-
-// Verify that a speculative frame is added.
-TEST_F(UnwinderTest, speculative_frame) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
-
- // Fake as if code called a nullptr function.
- regs_.set_pc(0);
- regs_.set_sp(0x10000);
- regs_.FakeSetReturnAddress(0x1204);
- regs_.FakeSetReturnAddressValid(true);
-
- ElfInterfaceFake::FakePushStepData(StepData(0x23104, 0x10020, false));
- ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(3U, unwinder.NumFrames());
-
- auto* frame = &unwinder.frames()[0];
- EXPECT_EQ(0U, frame->num);
- EXPECT_EQ(0U, frame->rel_pc);
- EXPECT_EQ(0U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0U, frame->map_start);
- EXPECT_EQ(0U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(0, frame->map_flags);
-
- frame = &unwinder.frames()[1];
- EXPECT_EQ(1U, frame->num);
- EXPECT_EQ(0x200U, frame->rel_pc);
- EXPECT_EQ(0x1200U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("Frame0", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("/system/fake/libc.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x1000U, frame->map_start);
- EXPECT_EQ(0x8000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-
- frame = &unwinder.frames()[2];
- EXPECT_EQ(2U, frame->num);
- EXPECT_EQ(0x100U, frame->rel_pc);
- EXPECT_EQ(0x23100U, frame->pc);
- EXPECT_EQ(0x10020U, frame->sp);
- EXPECT_EQ("Frame1", frame->function_name);
- EXPECT_EQ(1U, frame->function_offset);
- EXPECT_EQ("/fake/libanother.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x23000U, frame->map_start);
- EXPECT_EQ(0x24000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-}
-
-// Verify that a speculative frame is added then removed because no other
-// frames are added.
-TEST_F(UnwinderTest, speculative_frame_removed) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
-
- // Fake as if code called a nullptr function.
- regs_.set_pc(0x20000);
- regs_.set_sp(0x10000);
- ElfInterfaceFake::FakePushStepData(StepData(0, 0x10010, false));
- regs_.FakeSetReturnAddress(0x12);
- regs_.FakeSetReturnAddressValid(true);
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_INVALID_MAP, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(2U, unwinder.NumFrames());
-
- auto* frame = &unwinder.frames()[0];
- EXPECT_EQ(0U, frame->num);
- EXPECT_EQ(0U, frame->rel_pc);
- EXPECT_EQ(0x20000U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("Frame0", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("/system/fake/libunwind.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x20000U, frame->map_start);
- EXPECT_EQ(0x22000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-
- frame = &unwinder.frames()[1];
- EXPECT_EQ(1U, frame->num);
- EXPECT_EQ(0U, frame->rel_pc);
- EXPECT_EQ(0U, frame->pc);
- EXPECT_EQ(0x10010U, frame->sp);
- EXPECT_EQ("", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0U, frame->map_start);
- EXPECT_EQ(0U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(0, frame->map_flags);
-}
-
-// Verify that a speculative frame is added and left if there are only
-// two frames and the pc is in the middle nowhere.
-TEST_F(UnwinderTest, speculative_frame_not_removed_pc_bad) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
-
- // Fake as if code called a nullptr function.
- regs_.set_pc(0);
- regs_.set_sp(0x10000);
- regs_.FakeSetReturnAddress(0x1204);
- regs_.FakeSetReturnAddressValid(true);
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(2U, unwinder.NumFrames());
-
- auto* frame = &unwinder.frames()[0];
- EXPECT_EQ(0U, frame->num);
- EXPECT_EQ(0U, frame->rel_pc);
- EXPECT_EQ(0U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0U, frame->map_start);
- EXPECT_EQ(0U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(0, frame->map_flags);
-
- frame = &unwinder.frames()[1];
- EXPECT_EQ(1U, frame->num);
- EXPECT_EQ(0x200U, frame->rel_pc);
- EXPECT_EQ(0x1200U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("Frame0", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("/system/fake/libc.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x1000U, frame->map_start);
- EXPECT_EQ(0x8000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-}
-
-// Verify that a speculative frame does not cause a crash when it wasn't
-// really added due to a filter.
-TEST_F(UnwinderTest, speculative_frame_check_with_no_frames) {
- regs_.set_pc(0x23000);
- regs_.set_sp(0x10000);
- regs_.FakeSetReturnAddress(0x23100);
- regs_.FakeSetReturnAddressValid(true);
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
-
- std::vector<std::string> skip_names{"libanother.so"};
- unwinder.Unwind(&skip_names);
- EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(0U, unwinder.NumFrames());
-}
-
-// Verify that an unwind stops when a frame is in given suffix.
-TEST_F(UnwinderTest, map_ignore_suffixes) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame3", 3));
-
- // Fake as if code called a nullptr function.
- regs_.set_pc(0x1000);
- regs_.set_sp(0x10000);
- ElfInterfaceFake::FakePushStepData(StepData(0x43404, 0x10010, false));
- ElfInterfaceFake::FakePushStepData(StepData(0x53504, 0x10020, false));
- ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- std::vector<std::string> suffixes{"oat"};
- unwinder.Unwind(nullptr, &suffixes);
- EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(2U, unwinder.NumFrames());
- // Make sure the elf was not initialized.
- MapInfo* map_info = maps_->Find(0x53000);
- ASSERT_TRUE(map_info != nullptr);
- EXPECT_TRUE(map_info->elf == nullptr);
-
- auto* frame = &unwinder.frames()[0];
- EXPECT_EQ(0U, frame->num);
- EXPECT_EQ(0U, frame->rel_pc);
- EXPECT_EQ(0x1000U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("Frame0", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("/system/fake/libc.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x1000U, frame->map_start);
- EXPECT_EQ(0x8000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-
- frame = &unwinder.frames()[1];
- EXPECT_EQ(1U, frame->num);
- EXPECT_EQ(0x400U, frame->rel_pc);
- EXPECT_EQ(0x43400U, frame->pc);
- EXPECT_EQ(0x10010U, frame->sp);
- EXPECT_EQ("Frame1", frame->function_name);
- EXPECT_EQ(1U, frame->function_offset);
- EXPECT_EQ("/fake/fake.apk!lib_fake.so", frame->map_name);
- EXPECT_EQ(0x1d000U, frame->map_elf_start_offset);
- EXPECT_EQ(0x1d000U, frame->map_exact_offset);
- EXPECT_EQ(0x43000U, frame->map_start);
- EXPECT_EQ(0x44000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-}
-
-// Verify that an unwind stops when the sp and pc don't change.
-TEST_F(UnwinderTest, sp_pc_do_not_change) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame3", 3));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame4", 4));
-
- regs_.set_pc(0x1000);
- regs_.set_sp(0x10000);
- ElfInterfaceFake::FakePushStepData(StepData(0x33404, 0x10010, false));
- ElfInterfaceFake::FakePushStepData(StepData(0x33504, 0x10020, false));
- ElfInterfaceFake::FakePushStepData(StepData(0x33504, 0x10020, false));
- ElfInterfaceFake::FakePushStepData(StepData(0x33504, 0x10020, false));
- ElfInterfaceFake::FakePushStepData(StepData(0x33504, 0x10020, false));
- ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_REPEATED_FRAME, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(3U, unwinder.NumFrames());
-
- auto* frame = &unwinder.frames()[0];
- EXPECT_EQ(0U, frame->num);
- EXPECT_EQ(0U, frame->rel_pc);
- EXPECT_EQ(0x1000U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("Frame0", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("/system/fake/libc.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x1000U, frame->map_start);
- EXPECT_EQ(0x8000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-
- frame = &unwinder.frames()[1];
- EXPECT_EQ(1U, frame->num);
- EXPECT_EQ(0x400U, frame->rel_pc);
- EXPECT_EQ(0x33400U, frame->pc);
- EXPECT_EQ(0x10010U, frame->sp);
- EXPECT_EQ("Frame1", frame->function_name);
- EXPECT_EQ(1U, frame->function_offset);
- EXPECT_EQ("/fake/compressed.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x33000U, frame->map_start);
- EXPECT_EQ(0x34000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-
- frame = &unwinder.frames()[2];
- EXPECT_EQ(2U, frame->num);
- EXPECT_EQ(0x500U, frame->rel_pc);
- EXPECT_EQ(0x33500U, frame->pc);
- EXPECT_EQ(0x10020U, frame->sp);
- EXPECT_EQ("Frame2", frame->function_name);
- EXPECT_EQ(2U, frame->function_offset);
- EXPECT_EQ("/fake/compressed.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x33000U, frame->map_start);
- EXPECT_EQ(0x34000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-}
-
-TEST_F(UnwinderTest, dex_pc_in_map) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
- regs_.set_pc(0x1000);
- regs_.set_sp(0x10000);
- regs_.FakeSetDexPc(0xa3400);
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(2U, unwinder.NumFrames());
-
- auto* frame = &unwinder.frames()[0];
- EXPECT_EQ(0U, frame->num);
- EXPECT_EQ(0x400U, frame->rel_pc);
- EXPECT_EQ(0xa3400U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("/fake/fake.vdex", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0xa3000U, frame->map_start);
- EXPECT_EQ(0xa4000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
-
- frame = &unwinder.frames()[1];
- EXPECT_EQ(1U, frame->num);
- EXPECT_EQ(0U, frame->rel_pc);
- EXPECT_EQ(0x1000U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("Frame0", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("/system/fake/libc.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x1000U, frame->map_start);
- EXPECT_EQ(0x8000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-}
-
-TEST_F(UnwinderTest, dex_pc_in_map_non_zero_offset) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
- regs_.set_pc(0x1000);
- regs_.set_sp(0x10000);
- regs_.FakeSetDexPc(0xd0400);
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(2U, unwinder.NumFrames());
-
- auto* frame = &unwinder.frames()[0];
- EXPECT_EQ(0U, frame->num);
- EXPECT_EQ(0x400U, frame->rel_pc);
- EXPECT_EQ(0xd0400U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("/fake/fake.apk", frame->map_name);
- EXPECT_EQ(0x1000U, frame->map_elf_start_offset);
- EXPECT_EQ(0x1000U, frame->map_exact_offset);
- EXPECT_EQ(0xd0000U, frame->map_start);
- EXPECT_EQ(0xd1000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
-
- frame = &unwinder.frames()[1];
- EXPECT_EQ(1U, frame->num);
- EXPECT_EQ(0U, frame->rel_pc);
- EXPECT_EQ(0x1000U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("Frame0", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("/system/fake/libc.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x1000U, frame->map_start);
- EXPECT_EQ(0x8000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-}
-
-TEST_F(UnwinderTest, dex_pc_not_in_map) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
- regs_.set_pc(0x1000);
- regs_.set_sp(0x10000);
- regs_.FakeSetDexPc(0x50000);
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_DEX_PC_NOT_IN_MAP, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(2U, unwinder.NumFrames());
-
- auto* frame = &unwinder.frames()[0];
- EXPECT_EQ(0U, frame->num);
- EXPECT_EQ(0x50000U, frame->rel_pc);
- EXPECT_EQ(0x50000U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0U, frame->map_start);
- EXPECT_EQ(0U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(0, frame->map_flags);
-
- frame = &unwinder.frames()[1];
- EXPECT_EQ(1U, frame->num);
- EXPECT_EQ(0U, frame->rel_pc);
- EXPECT_EQ(0x1000U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("Frame0", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("/system/fake/libc.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x1000U, frame->map_start);
- EXPECT_EQ(0x8000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-}
-
-TEST_F(UnwinderTest, dex_pc_not_in_map_valid_dex_files) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
- regs_.set_pc(0x1000);
- regs_.set_sp(0x10000);
- regs_.FakeSetDexPc(0x50000);
-
- DexFiles dex_files(process_memory_);
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- unwinder.SetDexFiles(&dex_files);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_DEX_PC_NOT_IN_MAP, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(2U, unwinder.NumFrames());
-
- auto* frame = &unwinder.frames()[0];
- EXPECT_EQ(0U, frame->num);
- EXPECT_EQ(0x50000U, frame->rel_pc);
- EXPECT_EQ(0x50000U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0U, frame->map_start);
- EXPECT_EQ(0U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(0, frame->map_flags);
-
- frame = &unwinder.frames()[1];
- EXPECT_EQ(1U, frame->num);
- EXPECT_EQ(0U, frame->rel_pc);
- EXPECT_EQ(0x1000U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("Frame0", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("/system/fake/libc.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x1000U, frame->map_start);
- EXPECT_EQ(0x8000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-}
-
-TEST_F(UnwinderTest, dex_pc_multiple_frames) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
- regs_.set_pc(0x1000);
- regs_.set_sp(0x10000);
- regs_.FakeSetDexPc(0xa3400);
- ElfInterfaceFake::FakePushStepData(StepData(0x33404, 0x10010, false));
- ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(3U, unwinder.NumFrames());
-
- auto* frame = &unwinder.frames()[0];
- EXPECT_EQ(0U, frame->num);
- EXPECT_EQ(0x400U, frame->rel_pc);
- EXPECT_EQ(0xa3400U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("/fake/fake.vdex", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0xa3000U, frame->map_start);
- EXPECT_EQ(0xa4000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
-
- frame = &unwinder.frames()[1];
- EXPECT_EQ(1U, frame->num);
- EXPECT_EQ(0U, frame->rel_pc);
- EXPECT_EQ(0x1000U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("Frame0", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("/system/fake/libc.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x1000U, frame->map_start);
- EXPECT_EQ(0x8000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-
- frame = &unwinder.frames()[2];
- EXPECT_EQ(2U, frame->num);
- EXPECT_EQ(0x400U, frame->rel_pc);
- EXPECT_EQ(0x33400U, frame->pc);
- EXPECT_EQ(0x10010U, frame->sp);
- EXPECT_EQ("Frame1", frame->function_name);
- EXPECT_EQ(1U, frame->function_offset);
- EXPECT_EQ("/fake/compressed.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0x33000U, frame->map_start);
- EXPECT_EQ(0x34000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
-}
-
-TEST_F(UnwinderTest, dex_pc_max_frames) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
- regs_.set_pc(0x1000);
- regs_.set_sp(0x10000);
- regs_.FakeSetDexPc(0xa3400);
-
- Unwinder unwinder(1, maps_.get(), ®s_, process_memory_);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_MAX_FRAMES_EXCEEDED, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(1U, unwinder.NumFrames());
-
- auto* frame = &unwinder.frames()[0];
- EXPECT_EQ(0U, frame->num);
- EXPECT_EQ(0x400U, frame->rel_pc);
- EXPECT_EQ(0xa3400U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("/fake/fake.vdex", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0xa3000U, frame->map_start);
- EXPECT_EQ(0xa4000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
-}
-
-TEST_F(UnwinderTest, elf_from_memory_not_file) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
-
- regs_.set_pc(0xc0050);
- regs_.set_sp(0x10000);
- ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_TRUE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(1U, unwinder.NumFrames());
-
- auto* frame = &unwinder.frames()[0];
- EXPECT_EQ(0U, frame->num);
- EXPECT_EQ(0x50U, frame->rel_pc);
- EXPECT_EQ(0xc0050U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("Frame0", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("/fake/unreadable.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0xc0000U, frame->map_start);
- EXPECT_EQ(0xc1000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
-}
-
-TEST_F(UnwinderTest, elf_from_memory_but_no_valid_file_with_bracket) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
-
- regs_.set_pc(0xc1050);
- regs_.set_sp(0x10000);
- ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(1U, unwinder.NumFrames());
-
- auto* frame = &unwinder.frames()[0];
- EXPECT_EQ(0U, frame->num);
- EXPECT_EQ(0x50U, frame->rel_pc);
- EXPECT_EQ(0xc1050U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("Frame0", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("[vdso]", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0xc1000U, frame->map_start);
- EXPECT_EQ(0xc2000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
-}
-
-TEST_F(UnwinderTest, elf_from_memory_but_empty_filename) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
-
- regs_.set_pc(0xc2050);
- regs_.set_sp(0x10000);
- ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(1U, unwinder.NumFrames());
-
- auto* frame = &unwinder.frames()[0];
- EXPECT_EQ(0U, frame->num);
- EXPECT_EQ(0x50U, frame->rel_pc);
- EXPECT_EQ(0xc2050U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("Frame0", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0xc2000U, frame->map_start);
- EXPECT_EQ(0xc3000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
-}
-
-TEST_F(UnwinderTest, elf_from_memory_but_from_memfd) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
-
- regs_.set_pc(0xc3050);
- regs_.set_sp(0x10000);
- ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
-
- Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
- unwinder.Unwind();
- EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
- EXPECT_EQ(WARNING_NONE, unwinder.warnings());
- EXPECT_FALSE(unwinder.elf_from_memory_not_file());
-
- ASSERT_EQ(1U, unwinder.NumFrames());
-
- auto* frame = &unwinder.frames()[0];
- EXPECT_EQ(0U, frame->num);
- EXPECT_EQ(0x50U, frame->rel_pc);
- EXPECT_EQ(0xc3050U, frame->pc);
- EXPECT_EQ(0x10000U, frame->sp);
- EXPECT_EQ("Frame0", frame->function_name);
- EXPECT_EQ(0U, frame->function_offset);
- EXPECT_EQ("/memfd:/jit-cache", frame->map_name);
- EXPECT_EQ(0U, frame->map_elf_start_offset);
- EXPECT_EQ(0U, frame->map_exact_offset);
- EXPECT_EQ(0xc3000U, frame->map_start);
- EXPECT_EQ(0xc4000U, frame->map_end);
- EXPECT_EQ(0U, frame->map_load_bias);
- EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
-}
-
-// Verify format frame code.
-TEST_F(UnwinderTest, format_frame) {
- RegsFake regs_arm(10);
- regs_arm.FakeSetArch(ARCH_ARM);
- Unwinder unwinder32(10, maps_.get(), ®s_arm, process_memory_);
-
- RegsFake regs_arm64(10);
- regs_arm64.FakeSetArch(ARCH_ARM64);
- Unwinder unwinder64(10, maps_.get(), ®s_arm64, process_memory_);
-
- FrameData frame;
- frame.num = 1;
- frame.rel_pc = 0x1000;
- frame.pc = 0x4000;
- frame.sp = 0x1000;
- frame.function_name = "function";
- frame.function_offset = 100;
- frame.map_name = "/fake/libfake.so";
- frame.map_elf_start_offset = 0x2000;
- frame.map_start = 0x3000;
- frame.map_end = 0x6000;
- frame.map_flags = PROT_READ;
-
- EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so (offset 0x2000) (function+100)",
- unwinder64.FormatFrame(frame));
- EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (offset 0x2000) (function+100)",
- unwinder32.FormatFrame(frame));
-
- frame.map_elf_start_offset = 0;
- EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so (function+100)",
- unwinder64.FormatFrame(frame));
- EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (function+100)", unwinder32.FormatFrame(frame));
-
- frame.function_offset = 0;
- EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so (function)",
- unwinder64.FormatFrame(frame));
- EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (function)", unwinder32.FormatFrame(frame));
-
- // Verify the function name is demangled.
- frame.function_name = "_ZN4funcEv";
- EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so (func())", unwinder64.FormatFrame(frame));
- EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (func())", unwinder32.FormatFrame(frame));
-
- frame.function_name = "";
- EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so", unwinder64.FormatFrame(frame));
- EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so", unwinder32.FormatFrame(frame));
-
- frame.map_name = "";
- EXPECT_EQ(" #01 pc 0000000000001000 <anonymous:3000>", unwinder64.FormatFrame(frame));
- EXPECT_EQ(" #01 pc 00001000 <anonymous:3000>", unwinder32.FormatFrame(frame));
-
- frame.map_start = 0;
- frame.map_end = 0;
- EXPECT_EQ(" #01 pc 0000000000001000 <unknown>", unwinder64.FormatFrame(frame));
- EXPECT_EQ(" #01 pc 00001000 <unknown>", unwinder32.FormatFrame(frame));
-}
-
-TEST_F(UnwinderTest, format_frame_build_id) {
- RegsFake regs(10);
- regs.FakeSetArch(ARCH_ARM);
- Unwinder unwinder(10, maps_.get(), ®s, process_memory_);
-
- FrameData frame;
- frame.num = 1;
- frame.rel_pc = 0x1000;
- frame.pc = 0x4000;
- frame.sp = 0x1000;
- frame.function_name = "function";
- frame.function_offset = 100;
- frame.map_name = "/fake/libfake.so";
- frame.map_elf_start_offset = 0;
- frame.map_start = 0x3000;
- frame.map_end = 0x6000;
- frame.map_flags = PROT_READ;
-
- EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (function+100)", unwinder.FormatFrame(frame));
- unwinder.SetDisplayBuildID(true);
- EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (function+100) (BuildId: 46414b45)",
- unwinder.FormatFrame(frame));
-}
-
-static std::string ArchToString(ArchEnum arch) {
- if (arch == ARCH_ARM) {
- return "Arm";
- } else if (arch == ARCH_ARM64) {
- return "Arm64";
- } else if (arch == ARCH_X86) {
- return "X86";
- } else if (arch == ARCH_X86_64) {
- return "X86_64";
- } else {
- return "Unknown";
- }
-}
-
-// Verify format frame code.
-TEST_F(UnwinderTest, format_frame_by_arch) {
- std::vector<Regs*> reg_list;
- RegsArm* arm = new RegsArm;
- arm->set_pc(0x2300);
- arm->set_sp(0x10000);
- reg_list.push_back(arm);
-
- RegsArm64* arm64 = new RegsArm64;
- arm64->set_pc(0x2300);
- arm64->set_sp(0x10000);
- reg_list.push_back(arm64);
-
- RegsX86* x86 = new RegsX86;
- x86->set_pc(0x2300);
- x86->set_sp(0x10000);
- reg_list.push_back(x86);
-
- RegsX86_64* x86_64 = new RegsX86_64;
- x86_64->set_pc(0x2300);
- x86_64->set_sp(0x10000);
- reg_list.push_back(x86_64);
-
- RegsMips* mips = new RegsMips;
- mips->set_pc(0x2300);
- mips->set_sp(0x10000);
- reg_list.push_back(mips);
-
- RegsMips64* mips64 = new RegsMips64;
- mips64->set_pc(0x2300);
- mips64->set_sp(0x10000);
- reg_list.push_back(mips64);
-
- for (auto regs : reg_list) {
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 10));
-
- Unwinder unwinder(64, maps_.get(), regs, process_memory_);
- unwinder.Unwind();
-
- ASSERT_EQ(1U, unwinder.NumFrames());
- std::string expected;
- switch (regs->Arch()) {
- case ARCH_ARM:
- case ARCH_X86:
- case ARCH_MIPS:
- expected = " #00 pc 00001300 /system/fake/libc.so (Frame0+10)";
- break;
- case ARCH_ARM64:
- case ARCH_X86_64:
- case ARCH_MIPS64:
- expected = " #00 pc 0000000000001300 /system/fake/libc.so (Frame0+10)";
- break;
- default:
- expected = "";
- }
- EXPECT_EQ(expected, unwinder.FormatFrame(0))
- << "Mismatch of frame format for regs arch " << ArchToString(regs->Arch());
- delete regs;
- }
-}
-
-TEST_F(UnwinderTest, build_frame_pc_only_errors) {
- RegsFake regs(10);
- regs.FakeSetArch(ARCH_ARM);
- Unwinder unwinder(10, maps_.get(), ®s, process_memory_);
-
- FrameData frame;
-
- // Pc not in map
- frame = unwinder.BuildFrameFromPcOnly(0x10);
- EXPECT_EQ(0x10U, frame.pc);
- EXPECT_EQ(0x10U, frame.rel_pc);
-
- // No regs set
- unwinder.SetRegs(nullptr);
- frame = unwinder.BuildFrameFromPcOnly(0x100310);
- EXPECT_EQ(0x100310U, frame.pc);
- EXPECT_EQ(0x100310U, frame.rel_pc);
- unwinder.SetRegs(®s);
-
- // Invalid elf
- frame = unwinder.BuildFrameFromPcOnly(0x100310);
- EXPECT_EQ(0x10030eU, frame.pc);
- EXPECT_EQ(0x60eU, frame.rel_pc);
- EXPECT_EQ("/fake/jit.so", frame.map_name);
- EXPECT_EQ(0x100U, frame.map_elf_start_offset);
- EXPECT_EQ(0x200U, frame.map_exact_offset);
- EXPECT_EQ(0x100000U, frame.map_start);
- EXPECT_EQ(0x101000U, frame.map_end);
- EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame.map_flags);
- EXPECT_EQ(0x300U, frame.map_load_bias);
- EXPECT_EQ("", frame.function_name);
- EXPECT_EQ(0U, frame.function_offset);
-}
-
-TEST_F(UnwinderTest, build_frame_pc_valid_elf) {
- RegsFake regs(10);
- regs.FakeSetArch(ARCH_ARM);
- Unwinder unwinder(10, maps_.get(), ®s, process_memory_);
-
- FrameData frame;
-
- // Valid elf, no function data.
- frame = unwinder.BuildFrameFromPcOnly(0x1010);
- EXPECT_EQ(0x100cU, frame.pc);
- EXPECT_EQ(0xcU, frame.rel_pc);
- EXPECT_EQ("/system/fake/libc.so", frame.map_name);
- EXPECT_EQ(0U, frame.map_elf_start_offset);
- EXPECT_EQ(0U, frame.map_exact_offset);
- EXPECT_EQ(0x1000U, frame.map_start);
- EXPECT_EQ(0x8000U, frame.map_end);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame.map_flags);
- EXPECT_EQ(0U, frame.map_load_bias);
- EXPECT_EQ("", frame.function_name);
- EXPECT_EQ(0U, frame.function_offset);
-
- // Valid elf, function data present, but do not resolve.
- ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 10));
- unwinder.SetResolveNames(false);
-
- frame = unwinder.BuildFrameFromPcOnly(0x1010);
- EXPECT_EQ(0x100cU, frame.pc);
- EXPECT_EQ(0xcU, frame.rel_pc);
- EXPECT_EQ("/system/fake/libc.so", frame.map_name);
- EXPECT_EQ(0U, frame.map_elf_start_offset);
- EXPECT_EQ(0U, frame.map_exact_offset);
- EXPECT_EQ(0x1000U, frame.map_start);
- EXPECT_EQ(0x8000U, frame.map_end);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame.map_flags);
- EXPECT_EQ(0U, frame.map_load_bias);
- EXPECT_EQ("", frame.function_name);
- EXPECT_EQ(0U, frame.function_offset);
-
- // Valid elf, function data present.
- unwinder.SetResolveNames(true);
-
- frame = unwinder.BuildFrameFromPcOnly(0x1010);
- EXPECT_EQ(0x100cU, frame.pc);
- EXPECT_EQ(0xcU, frame.rel_pc);
- EXPECT_EQ("/system/fake/libc.so", frame.map_name);
- EXPECT_EQ(0U, frame.map_elf_start_offset);
- EXPECT_EQ(0U, frame.map_exact_offset);
- EXPECT_EQ(0x1000U, frame.map_start);
- EXPECT_EQ(0x8000U, frame.map_end);
- EXPECT_EQ(PROT_READ | PROT_WRITE, frame.map_flags);
- EXPECT_EQ(0U, frame.map_load_bias);
- EXPECT_EQ("Frame0", frame.function_name);
- EXPECT_EQ(10U, frame.function_offset);
-}
-
-TEST_F(UnwinderTest, build_frame_pc_in_jit) {
- // Create the elf data for the jit debug information.
- Elf32_Ehdr ehdr = {};
- TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
- ehdr.e_phoff = 0x50;
- ehdr.e_phnum = 1;
- ehdr.e_phentsize = sizeof(Elf32_Phdr);
- ehdr.e_shoff = 0x100;
- ehdr.e_shstrndx = 1;
- ehdr.e_shentsize = sizeof(Elf32_Shdr);
- ehdr.e_shnum = 3;
- memory_->SetMemory(0xf7000, &ehdr, sizeof(ehdr));
-
- Elf32_Phdr phdr = {};
- phdr.p_flags = PF_X;
- phdr.p_type = PT_LOAD;
- phdr.p_offset = 0x100000;
- phdr.p_vaddr = 0x100000;
- phdr.p_memsz = 0x1000;
- memory_->SetMemory(0xf7050, &phdr, sizeof(phdr));
-
- Elf32_Shdr shdr = {};
- shdr.sh_type = SHT_NULL;
- memory_->SetMemory(0xf7100, &shdr, sizeof(shdr));
-
- shdr.sh_type = SHT_SYMTAB;
- shdr.sh_link = 2;
- shdr.sh_addr = 0x300;
- shdr.sh_offset = 0x300;
- shdr.sh_entsize = sizeof(Elf32_Sym);
- shdr.sh_size = shdr.sh_entsize;
- memory_->SetMemory(0xf7100 + sizeof(shdr), &shdr, sizeof(shdr));
-
- memset(&shdr, 0, sizeof(shdr));
- shdr.sh_type = SHT_STRTAB;
- shdr.sh_name = 0x500;
- shdr.sh_offset = 0x400;
- shdr.sh_size = 0x100;
- memory_->SetMemory(0xf7100 + 2 * sizeof(shdr), &shdr, sizeof(shdr));
-
- Elf32_Sym sym = {};
- sym.st_shndx = 2;
- sym.st_info = STT_FUNC;
- sym.st_value = 0x100300;
- sym.st_size = 0x100;
- memory_->SetMemory(0xf7300, &sym, sizeof(sym));
- memory_->SetMemory(0xf7400, "FakeJitFunction");
-
- RegsFake regs(10);
- regs.FakeSetArch(ARCH_ARM);
- JitDebug jit_debug(process_memory_);
- Unwinder unwinder(10, maps_.get(), ®s, process_memory_);
- unwinder.SetJitDebug(&jit_debug);
-
- FrameData frame = unwinder.BuildFrameFromPcOnly(0x100310);
- EXPECT_EQ(0x10030eU, frame.pc);
- EXPECT_EQ(0x60eU, frame.rel_pc);
- EXPECT_EQ("/fake/jit.so", frame.map_name);
- EXPECT_EQ(0x100U, frame.map_elf_start_offset);
- EXPECT_EQ(0x200U, frame.map_exact_offset);
- EXPECT_EQ(0x100000U, frame.map_start);
- EXPECT_EQ(0x101000U, frame.map_end);
- EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame.map_flags);
- EXPECT_EQ(0U, frame.map_load_bias);
- EXPECT_EQ("FakeJitFunction", frame.function_name);
- EXPECT_EQ(0xeU, frame.function_offset);
-}
-
-TEST_F(UnwinderTest, unwinder_from_pid_init_error) {
- UnwinderFromPid unwinder(10, getpid());
- ASSERT_DEATH(unwinder.Init(), "");
-}
-
-TEST_F(UnwinderTest, set_jit_debug_error) {
- Unwinder unwinder(10, maps_.get(), process_memory_);
- JitDebug jit_debug(process_memory_);
- ASSERT_DEATH(unwinder.SetJitDebug(&jit_debug), "");
-}
-
-TEST_F(UnwinderTest, set_dex_files_error) {
- Unwinder unwinder(10, maps_.get(), process_memory_);
- DexFiles dex_files(process_memory_);
- ASSERT_DEATH(unwinder.SetDexFiles(&dex_files), "");
-}
-
-} // namespace unwindstack
diff --git a/libunwindstack/tests/VerifyBionicTerminationTest.cpp b/libunwindstack/tests/VerifyBionicTerminationTest.cpp
deleted file mode 100644
index 3e67dc9..0000000
--- a/libunwindstack/tests/VerifyBionicTerminationTest.cpp
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-#define _GNU_SOURCE 1
-#include <stdint.h>
-#include <string.h>
-
-#include <string>
-
-#if defined(__BIONIC__)
-
-#include <gtest/gtest.h>
-
-#include <unwindstack/DwarfSection.h>
-#include <unwindstack/Elf.h>
-#include <unwindstack/ElfInterface.h>
-#include <unwindstack/Regs.h>
-#include <unwindstack/RegsGetLocal.h>
-#include <unwindstack/Unwinder.h>
-
-// This test is specific to bionic to verify that __libc_init is
-// properly setting the return address to undefined so that the
-// unwind properly terminates.
-
-namespace unwindstack {
-
-static std::string DumpFrames(const UnwinderFromPid& unwinder) {
- std::string unwind;
- for (size_t i = 0; i < unwinder.NumFrames(); i++) {
- unwind += unwinder.FormatFrame(i) + '\n';
- }
- return unwind;
-}
-
-static DwarfLocationEnum GetReturnAddressLocation(uint64_t rel_pc, DwarfSection* section) {
- if (section == nullptr) {
- return DWARF_LOCATION_INVALID;
- }
-
- const DwarfFde* fde = section->GetFdeFromPc(rel_pc);
- if (fde == nullptr || fde->cie == nullptr) {
- return DWARF_LOCATION_INVALID;
- }
- dwarf_loc_regs_t regs;
- if (!section->GetCfaLocationInfo(rel_pc, fde, ®s, ARCH_UNKNOWN)) {
- return DWARF_LOCATION_INVALID;
- }
-
- auto reg_entry = regs.find(fde->cie->return_address_register);
- if (reg_entry == regs.end()) {
- return DWARF_LOCATION_INVALID;
- }
- return reg_entry->second.type;
-}
-
-static void VerifyReturnAddress(const FrameData& frame) {
- // Now go and find information about the register data and verify that the relative pc results in
- // an undefined register.
- Elf elf(Memory::CreateFileMemory(frame.map_name, 0).release());
- ASSERT_TRUE(elf.Init()) << "Failed to init elf object from " << frame.map_name;
- ASSERT_TRUE(elf.valid()) << "Elf " << frame.map_name << " is not valid.";
- ElfInterface* interface = elf.interface();
-
- // Only check the eh_frame and the debug_frame since the undefined register
- // is set using a cfi directive.
- // Check debug_frame first, then eh_frame since debug_frame always
- // contains the most specific data.
- DwarfLocationEnum location = GetReturnAddressLocation(frame.rel_pc, interface->debug_frame());
- if (location == DWARF_LOCATION_UNDEFINED) {
- return;
- }
-
- location = GetReturnAddressLocation(frame.rel_pc, interface->eh_frame());
- ASSERT_EQ(DWARF_LOCATION_UNDEFINED, location);
-}
-
-// This test assumes that it starts from the main thread, and that the
-// libc.so on device will include symbols so that function names can
-// be resolved.
-TEST(VerifyBionicTermination, local_terminate) {
- std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
-
- UnwinderFromPid unwinder(512, getpid());
- unwinder.SetRegs(regs.get());
-
- RegsGetLocal(regs.get());
- unwinder.Unwind();
- ASSERT_LT(0U, unwinder.NumFrames());
-
- SCOPED_TRACE(DumpFrames(unwinder));
-
- // Look for the frame that includes __libc_init, there should only
- // be one and it should be the last.
- bool found = false;
- const std::vector<FrameData>& frames = unwinder.frames();
- for (size_t i = 0; i < unwinder.NumFrames(); i++) {
- const FrameData& frame = frames[i];
- if (frame.function_name == "__libc_init" && !frame.map_name.empty() &&
- std::string("libc.so") == basename(frame.map_name.c_str())) {
- ASSERT_EQ(unwinder.NumFrames(), i + 1) << "__libc_init is not last frame.";
- ASSERT_NO_FATAL_FAILURE(VerifyReturnAddress(frame));
- found = true;
- }
- }
- ASSERT_TRUE(found) << "Unable to find libc.so:__libc_init frame\n";
-}
-
-} // namespace unwindstack
-
-#endif
diff --git a/libunwindstack/tests/files/elf32.xz b/libunwindstack/tests/files/elf32.xz
deleted file mode 100644
index f25d433..0000000
--- a/libunwindstack/tests/files/elf32.xz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/elf64.xz b/libunwindstack/tests/files/elf64.xz
deleted file mode 100644
index eb1618e..0000000
--- a/libunwindstack/tests/files/elf64.xz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/descriptor.data b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/descriptor.data
deleted file mode 100644
index 300646b..0000000
--- a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/descriptor.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry0.data b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry0.data
deleted file mode 100644
index 999cb79..0000000
--- a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry0.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry1.data b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry1.data
deleted file mode 100644
index 6aa1c82..0000000
--- a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry1.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit0.data b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit0.data
deleted file mode 100644
index 19d7b65..0000000
--- a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit0.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit1.data b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit1.data
deleted file mode 100644
index edcd3e1..0000000
--- a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit1.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libart.so b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libart.so
deleted file mode 100644
index 09ba495..0000000
--- a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libart.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libc.so b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libc.so
deleted file mode 100644
index 39c9025..0000000
--- a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libc.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/maps.txt b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/maps.txt
deleted file mode 100644
index 1ff12db..0000000
--- a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/maps.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-d0250000-d2600000 r-xp 0 00:00 0 <anonymous:d0250000>
-e466e000-e4ae8000 r-xp 0 00:00 0 libart.so
-e4af1000-e4af2000 rw-p 482000 00:00 0 libart.so
-e7d91000-e7e31000 r-xp 0 00:00 0 libc.so
diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/regs.txt b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/regs.txt
deleted file mode 100644
index 0b51814..0000000
--- a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/regs.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-r0: e814103c
-r1: 12dcf218
-r2: 1a90df75
-r3: ffffffbf
-r4: 0
-r5: 12dc0800
-r6: 12dcf218
-r7: 1a90df75
-r8: 0
-r9: dd23cc00
-r10: 1c
-r11: cd4ff16c
-ip: 0
-sp: cd4ff140
-lr: d025cdd7
-pc: d025c788
diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/stack.data b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/stack.data
deleted file mode 100644
index f00917b..0000000
--- a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/libc.so b/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/libc.so
deleted file mode 100644
index 78449bf..0000000
--- a/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/libc.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/maps.txt b/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/maps.txt
deleted file mode 100644
index 7cada15..0000000
--- a/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/maps.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-60a9fdf000-60a9fe0000 r-xp 0 00:00 0 waiter64
-7542cc0000-7542d8e000 r-xp 0 00:00 0 libc.so
diff --git a/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/regs.txt b/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/regs.txt
deleted file mode 100644
index c24adbe..0000000
--- a/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/regs.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-pc: 60a9fdf550
-sp: 7fdd141990
-lr: 60a9fdf56c
-x29: 7fdd1419a0
diff --git a/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/stack.data b/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/stack.data
deleted file mode 100644
index b56d420..0000000
--- a/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/waiter64 b/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/waiter64
deleted file mode 100644
index 81bda1d..0000000
--- a/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/waiter64
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/debug_frame_first_x86/libc.so b/libunwindstack/tests/files/offline/debug_frame_first_x86/libc.so
deleted file mode 100644
index 9c78790..0000000
--- a/libunwindstack/tests/files/offline/debug_frame_first_x86/libc.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/debug_frame_first_x86/maps.txt b/libunwindstack/tests/files/offline/debug_frame_first_x86/maps.txt
deleted file mode 100644
index 74fc89f..0000000
--- a/libunwindstack/tests/files/offline/debug_frame_first_x86/maps.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-56598000-56599000 r-xp 0 00:00 0 waiter
-f7432000-f75e3000 r-xp 0 00:00 0 libc.so
diff --git a/libunwindstack/tests/files/offline/debug_frame_first_x86/regs.txt b/libunwindstack/tests/files/offline/debug_frame_first_x86/regs.txt
deleted file mode 100644
index 48f4440..0000000
--- a/libunwindstack/tests/files/offline/debug_frame_first_x86/regs.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-eax: 1d88ef8c
-ebx: 56599fe8
-ecx: 3
-edx: ffcf9ea4
-ebp: ffcf9e48
-edi: f75e5000
-esi: 1
-esp: ffcf9e38
-eip: 56598685
diff --git a/libunwindstack/tests/files/offline/debug_frame_first_x86/stack.data b/libunwindstack/tests/files/offline/debug_frame_first_x86/stack.data
deleted file mode 100644
index 0cf7d55..0000000
--- a/libunwindstack/tests/files/offline/debug_frame_first_x86/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/debug_frame_first_x86/waiter b/libunwindstack/tests/files/offline/debug_frame_first_x86/waiter
deleted file mode 100644
index b1fc024..0000000
--- a/libunwindstack/tests/files/offline/debug_frame_first_x86/waiter
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libbinder.so b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libbinder.so
deleted file mode 100644
index 4b7bf44..0000000
--- a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libbinder.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libc.so b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libc.so
deleted file mode 100644
index 013858e..0000000
--- a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libc.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/maps.txt b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/maps.txt
deleted file mode 100644
index 10f1325..0000000
--- a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/maps.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-8d1c000-8d1f000 r-xp 0 00:00 0 mediaserver
-f0b91000-f0c2c000 r-xp 0 00:00 0 libc.so
-f1a41000-f1a97000 r-xp 0 00:00 0 libbinder.so
diff --git a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/mediaserver b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/mediaserver
deleted file mode 100644
index 9e4a83f..0000000
--- a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/mediaserver
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/regs.txt b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/regs.txt
deleted file mode 100644
index f147247..0000000
--- a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/regs.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-r0: 3
-r1: c0306201
-r2: ffd4a658
-r3: 0
-r4: f0c36d8c
-r5: ffd4a658
-r6: f0168000
-r7: 36
-r8: ffd4a678
-r9: f016802c
-r10: ffd4a660
-r11: 0
-ip: 0
-sp: ffd4a638
-lr: f0bb2413
-pc: f0be238c
diff --git a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/stack.data b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/stack.data
deleted file mode 100644
index 847c819..0000000
--- a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/libc.so b/libunwindstack/tests/files/offline/eh_frame_bias_x86/libc.so
deleted file mode 100644
index f3eb615..0000000
--- a/libunwindstack/tests/files/offline/eh_frame_bias_x86/libc.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/maps.txt b/libunwindstack/tests/files/offline/eh_frame_bias_x86/maps.txt
deleted file mode 100644
index 7d52483..0000000
--- a/libunwindstack/tests/files/offline/eh_frame_bias_x86/maps.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-eb503000-eb5e8000 r-xp 0 00:00 0 libc.so
-eb831000-eb852000 r-xp 0 00:00 0 tombstoned
-ffffe000-fffff000 r-xp 0 00:00 0 vdso.so
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/regs.txt b/libunwindstack/tests/files/offline/eh_frame_bias_x86/regs.txt
deleted file mode 100644
index 821928e..0000000
--- a/libunwindstack/tests/files/offline/eh_frame_bias_x86/regs.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-eax: fffffffc
-ebx: 4
-ecx: eb290180
-edx: 20
-ebp: 8
-edi: 0
-esi: ffffffff
-esp: fffe1a30
-eip: ffffe430
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/stack.data b/libunwindstack/tests/files/offline/eh_frame_bias_x86/stack.data
deleted file mode 100644
index b95bfac..0000000
--- a/libunwindstack/tests/files/offline/eh_frame_bias_x86/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/tombstoned b/libunwindstack/tests/files/offline/eh_frame_bias_x86/tombstoned
deleted file mode 100644
index aefdb6b..0000000
--- a/libunwindstack/tests/files/offline/eh_frame_bias_x86/tombstoned
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/vdso.so b/libunwindstack/tests/files/offline/eh_frame_bias_x86/vdso.so
deleted file mode 100644
index c71dcfb..0000000
--- a/libunwindstack/tests/files/offline/eh_frame_bias_x86/vdso.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/libc.so b/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/libc.so
deleted file mode 100644
index 46b6f45..0000000
--- a/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/libc.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/maps.txt b/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/maps.txt
deleted file mode 100644
index ac2e564..0000000
--- a/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/maps.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-561550b17000-561550b1a000 r-xp 0 00:00 0 unwind_test64
-7f4de61f6000-7f4de638b000 r-xp 0 00:00 0 libc.so
diff --git a/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/regs.txt b/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/regs.txt
deleted file mode 100644
index 38af274..0000000
--- a/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/regs.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-rax: 92134c6fbbdc12ff
-rbx: 0
-rcx: 92134c6fbbdc1200
-rdx: 92134c6fbbdc1200
-r8: 561552153034
-r12: 561550b17930
-r13: 7ffcc8597270
-rsi: 561552153034
-rbp: 7ffcc8596f30
-rsp: 7ffcc8596ce8
-rip: 561550b17a80
diff --git a/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/stack.data b/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/stack.data
deleted file mode 100644
index cc7882b..0000000
--- a/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/unwind_test64 b/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/unwind_test64
deleted file mode 100644
index ab0ef8f..0000000
--- a/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/unwind_test64
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/empty_arm64/libbinder.so b/libunwindstack/tests/files/offline/empty_arm64/libbinder.so
deleted file mode 100644
index f30384c..0000000
--- a/libunwindstack/tests/files/offline/empty_arm64/libbinder.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/empty_arm64/libc.so b/libunwindstack/tests/files/offline/empty_arm64/libc.so
deleted file mode 100644
index b05dcaf..0000000
--- a/libunwindstack/tests/files/offline/empty_arm64/libc.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/empty_arm64/maps.txt b/libunwindstack/tests/files/offline/empty_arm64/maps.txt
deleted file mode 100644
index edb83c6..0000000
--- a/libunwindstack/tests/files/offline/empty_arm64/maps.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-5d4786b000-5d47893000 r--p 0 00:00 0 netd
-5d47893000-5d47894000 ---p 0 00:00 0
-5d47894000-5d47901000 --xp 29000 00:00 0 netd
-729f709000-729f750000 r--p 0 00:00 0 libbinder.so
-729f750000-729f751000 ---p 0 00:00 0
-729f751000-729f794000 --xp 48000 00:00 0 libbinder.so
-72a018a000-72a01c2000 r--p 0 00:00 0 libc.so
-72a01c2000-72a01c3000 ---p 0 00:00 0
-72a01c3000-72a023b000 --xp 39000 00:00 0 libc.so
diff --git a/libunwindstack/tests/files/offline/empty_arm64/netd b/libunwindstack/tests/files/offline/empty_arm64/netd
deleted file mode 100644
index 8a72e94..0000000
--- a/libunwindstack/tests/files/offline/empty_arm64/netd
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/empty_arm64/regs.txt b/libunwindstack/tests/files/offline/empty_arm64/regs.txt
deleted file mode 100644
index 3d4279f..0000000
--- a/libunwindstack/tests/files/offline/empty_arm64/regs.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-x0: 1d
-x1: c0306201
-x2: 7ffb6c0c50
-x3: 0
-x4: 0
-x5: 0
-x6: 0
-x7: 0
-x8: 1d
-x9: 7ffb6c0c00
-x10: 7ffb6c0c50
-x11: 7ffb6c0bd0
-x12: ffffff80ffffffd0
-x13: 0
-x14: 72a0240ce2
-x15: 20
-x16: 729f7a54e8
-x17: 72a01dd3c0
-x18: 72a0ac2000
-x19: 72a0666000
-x20: 719769b610
-x21: 719769b730
-x22: c0306201
-x23: fffffff7
-x24: 72a0666000
-x25: 0
-x26: 0
-x27: 0
-x28: 0
-x29: 7ffb6c0c30
-sp: 7ffb6c0b50
-lr: 72a01dd450
-pc: 72a02203a4
-pst: a0000000
diff --git a/libunwindstack/tests/files/offline/empty_arm64/stack.data b/libunwindstack/tests/files/offline/empty_arm64/stack.data
deleted file mode 100644
index 6d6108c..0000000
--- a/libunwindstack/tests/files/offline/empty_arm64/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/gnu_debugdata_arm/libandroid_runtime.so b/libunwindstack/tests/files/offline/gnu_debugdata_arm/libandroid_runtime.so
deleted file mode 100644
index e4283e6..0000000
--- a/libunwindstack/tests/files/offline/gnu_debugdata_arm/libandroid_runtime.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/gnu_debugdata_arm/maps.txt b/libunwindstack/tests/files/offline/gnu_debugdata_arm/maps.txt
deleted file mode 100644
index 1bcddb6..0000000
--- a/libunwindstack/tests/files/offline/gnu_debugdata_arm/maps.txt
+++ /dev/null
@@ -1 +0,0 @@
-f1f10000-f2049000 r-xp 00000000 00:00 0 libandroid_runtime.so
diff --git a/libunwindstack/tests/files/offline/gnu_debugdata_arm/regs.txt b/libunwindstack/tests/files/offline/gnu_debugdata_arm/regs.txt
deleted file mode 100644
index c6a93dc..0000000
--- a/libunwindstack/tests/files/offline/gnu_debugdata_arm/regs.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-pc: f1f6dc49
-sp: d8fe6930
diff --git a/libunwindstack/tests/files/offline/gnu_debugdata_arm/stack.data b/libunwindstack/tests/files/offline/gnu_debugdata_arm/stack.data
deleted file mode 100644
index 19cdf2d..0000000
--- a/libunwindstack/tests/files/offline/gnu_debugdata_arm/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/invalid_elf_offset_arm/maps.txt b/libunwindstack/tests/files/offline/invalid_elf_offset_arm/maps.txt
deleted file mode 100644
index 022404c..0000000
--- a/libunwindstack/tests/files/offline/invalid_elf_offset_arm/maps.txt
+++ /dev/null
@@ -1 +0,0 @@
-c7ee8000-c8c52fff r-xp 12e4000 00:00 0 invalid.apk
diff --git a/libunwindstack/tests/files/offline/invalid_elf_offset_arm/regs.txt b/libunwindstack/tests/files/offline/invalid_elf_offset_arm/regs.txt
deleted file mode 100644
index b7f10ef..0000000
--- a/libunwindstack/tests/files/offline/invalid_elf_offset_arm/regs.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-r0: c0434c00
-r1: 2a4c9fbc
-r2: 00000000
-r3: c83ef1f9
-r4: 00000004
-r5: c2044904
-r6: 00000000
-r7: c20443b8
-r8: 000b33ff
-r9: c20444b0
-r10: cac90740
-r11: 00000000
-ip: ed891ca4
-sp: c2044218
-lr: ed807265
-pc: c898f508
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/137-cfi.odex b/libunwindstack/tests/files/offline/jit_debug_arm/137-cfi.odex
deleted file mode 100644
index 35a6bc5..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_arm/137-cfi.odex
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/dalvikvm32 b/libunwindstack/tests/files/offline/jit_debug_arm/dalvikvm32
deleted file mode 100644
index def299e..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_arm/dalvikvm32
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/descriptor.data b/libunwindstack/tests/files/offline/jit_debug_arm/descriptor.data
deleted file mode 100644
index 7b876b5..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_arm/descriptor.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/descriptor1.data b/libunwindstack/tests/files/offline/jit_debug_arm/descriptor1.data
deleted file mode 100644
index 3c468d6..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_arm/descriptor1.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/entry0.data b/libunwindstack/tests/files/offline/jit_debug_arm/entry0.data
deleted file mode 100644
index 2c7689b..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_arm/entry0.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/entry1.data b/libunwindstack/tests/files/offline/jit_debug_arm/entry1.data
deleted file mode 100644
index 22a35b8..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_arm/entry1.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/entry2.data b/libunwindstack/tests/files/offline/jit_debug_arm/entry2.data
deleted file mode 100644
index 61f3927..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_arm/entry2.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/entry3.data b/libunwindstack/tests/files/offline/jit_debug_arm/entry3.data
deleted file mode 100644
index 1a37628..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_arm/entry3.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/entry4.data b/libunwindstack/tests/files/offline/jit_debug_arm/entry4.data
deleted file mode 100644
index 7ef62ca..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_arm/entry4.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/entry5.data b/libunwindstack/tests/files/offline/jit_debug_arm/entry5.data
deleted file mode 100644
index 6d27c89..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_arm/entry5.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/entry6.data b/libunwindstack/tests/files/offline/jit_debug_arm/entry6.data
deleted file mode 100644
index bfbceea..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_arm/entry6.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/jit0.data b/libunwindstack/tests/files/offline/jit_debug_arm/jit0.data
deleted file mode 100644
index b78848e..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_arm/jit0.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/jit1.data b/libunwindstack/tests/files/offline/jit_debug_arm/jit1.data
deleted file mode 100644
index 8f927ac..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_arm/jit1.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/jit2.data b/libunwindstack/tests/files/offline/jit_debug_arm/jit2.data
deleted file mode 100644
index 1d1dfca..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_arm/jit2.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/jit3.data b/libunwindstack/tests/files/offline/jit_debug_arm/jit3.data
deleted file mode 100644
index 89aeb43..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_arm/jit3.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/jit4.data b/libunwindstack/tests/files/offline/jit_debug_arm/jit4.data
deleted file mode 100644
index e076934..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_arm/jit4.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/jit5.data b/libunwindstack/tests/files/offline/jit_debug_arm/jit5.data
deleted file mode 100644
index 17d6041..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_arm/jit5.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/jit6.data b/libunwindstack/tests/files/offline/jit_debug_arm/jit6.data
deleted file mode 100644
index aaff037..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_arm/jit6.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/libart.so b/libunwindstack/tests/files/offline/jit_debug_arm/libart.so
deleted file mode 100644
index 0527893..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_arm/libart.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/libartd.so b/libunwindstack/tests/files/offline/jit_debug_arm/libartd.so
deleted file mode 100644
index 8559056..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_arm/libartd.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/libarttestd.so b/libunwindstack/tests/files/offline/jit_debug_arm/libarttestd.so
deleted file mode 100644
index 06dbf10..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_arm/libarttestd.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/libc.so b/libunwindstack/tests/files/offline/jit_debug_arm/libc.so
deleted file mode 100644
index 9894e66..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_arm/libc.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt b/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt
deleted file mode 100644
index 3b87f2f..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-ab0d3000-ab0d8000 r-xp 0 00:00 0 dalvikvm32
-dfe4e000-dfe7b000 r-xp 0 00:00 0 libarttestd.so
-e0445000-e0447000 r--p 0 00:00 0 137-cfi.odex
-e0447000-e0448000 r-xp 2000 00:00 0 137-cfi.odex
-e2796000-e4796000 r-xp 0 00:00 0 anonymous:e2796000
-e648e000-e690f000 r-xp 0 00:00 0 libart.so
-e6918000-e6919000 rw-p 489000 00:00 0 libart.so
-ed306000-ed801000 r-xp 0 00:00 0 libartd.so
-ed80a000-ed80b000 rw-p 503000 00:00 0 libartd.so
-eda88000-edb23000 r-xp 0 00:00 0 libc.so
-ede4e000-ede50000 r-xp 0 00:00 0 anonymous:ede4e000
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/regs.txt b/libunwindstack/tests/files/offline/jit_debug_arm/regs.txt
deleted file mode 100644
index 0e20066..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_arm/regs.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-r0: dfe7c0f8
-r1: 0
-r2: 0
-r3: 40000000
-r4: e051ffb4
-r5: 0
-r6: e051ffc0
-r7: ede514e8
-r8: ff85d1a8
-r9: ed9210c0
-r10: 58
-r11: 0
-ip: edb26d04
-sp: ff85d180
-lr: edaff5af
-pc: dfe66a5e
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/stack.data b/libunwindstack/tests/files/offline/jit_debug_arm/stack.data
deleted file mode 100644
index b2ff14e..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_arm/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/137-cfi.odex b/libunwindstack/tests/files/offline/jit_debug_x86/137-cfi.odex
deleted file mode 100644
index 870ac0a..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_x86/137-cfi.odex
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/dalvikvm32 b/libunwindstack/tests/files/offline/jit_debug_x86/dalvikvm32
deleted file mode 100644
index 76ffad9..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_x86/dalvikvm32
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/descriptor.data b/libunwindstack/tests/files/offline/jit_debug_x86/descriptor.data
deleted file mode 100644
index 466dae2..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_x86/descriptor.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/entry0.data b/libunwindstack/tests/files/offline/jit_debug_x86/entry0.data
deleted file mode 100644
index 3a725e8..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_x86/entry0.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/entry1.data b/libunwindstack/tests/files/offline/jit_debug_x86/entry1.data
deleted file mode 100644
index 767550f..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_x86/entry1.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/entry2.data b/libunwindstack/tests/files/offline/jit_debug_x86/entry2.data
deleted file mode 100644
index e7e492e..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_x86/entry2.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/entry3.data b/libunwindstack/tests/files/offline/jit_debug_x86/entry3.data
deleted file mode 100644
index 65f9cd4..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_x86/entry3.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/entry4.data b/libunwindstack/tests/files/offline/jit_debug_x86/entry4.data
deleted file mode 100644
index 30aa28c..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_x86/entry4.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/entry5.data b/libunwindstack/tests/files/offline/jit_debug_x86/entry5.data
deleted file mode 100644
index 3c89673..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_x86/entry5.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/entry6.data b/libunwindstack/tests/files/offline/jit_debug_x86/entry6.data
deleted file mode 100644
index 9c9b83c..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_x86/entry6.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/jit0.data b/libunwindstack/tests/files/offline/jit_debug_x86/jit0.data
deleted file mode 100644
index eaad142..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_x86/jit0.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/jit1.data b/libunwindstack/tests/files/offline/jit_debug_x86/jit1.data
deleted file mode 100644
index d534816..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_x86/jit1.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/jit2.data b/libunwindstack/tests/files/offline/jit_debug_x86/jit2.data
deleted file mode 100644
index dbeb886..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_x86/jit2.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/jit3.data b/libunwindstack/tests/files/offline/jit_debug_x86/jit3.data
deleted file mode 100644
index bf2142d..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_x86/jit3.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/jit4.data b/libunwindstack/tests/files/offline/jit_debug_x86/jit4.data
deleted file mode 100644
index e2ba1b0..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_x86/jit4.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/jit5.data b/libunwindstack/tests/files/offline/jit_debug_x86/jit5.data
deleted file mode 100644
index c27ba54..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_x86/jit5.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/jit6.data b/libunwindstack/tests/files/offline/jit_debug_x86/jit6.data
deleted file mode 100644
index 5fc8fae..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_x86/jit6.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/libartd.so b/libunwindstack/tests/files/offline/jit_debug_x86/libartd.so
deleted file mode 100644
index 92ed991..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_x86/libartd.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/libarttestd.so b/libunwindstack/tests/files/offline/jit_debug_x86/libarttestd.so
deleted file mode 100644
index 5efae02..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_x86/libarttestd.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/libc.so b/libunwindstack/tests/files/offline/jit_debug_x86/libc.so
deleted file mode 100644
index 9c78790..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_x86/libc.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/maps.txt b/libunwindstack/tests/files/offline/jit_debug_x86/maps.txt
deleted file mode 100644
index c22b5de..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_x86/maps.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-56573000-56577000 r-xp 0 00:00 0 dalvikvm32
-eb833000-eb8cc000 r-xp 0 00:00 0 libarttestd.so
-ec604000-ec606000 r--p 0 00:00 0 137-cfi.odex
-ec606000-ec607000 r-xp 2000 00:00 0 137-cfi.odex
-ee74c000-f074c000 r-xp 0 00:00 0 anonymous:ee74c000
-f6be1000-f732b000 r-xp 0 00:00 0 libartd.so
-f7334000-f7335000 rw-p 752000 00:00 0 libartd.so
-f734b000-f74fc000 r-xp 0 00:00 0 libc.so
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/regs.txt b/libunwindstack/tests/files/offline/jit_debug_x86/regs.txt
deleted file mode 100644
index f68305b..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_x86/regs.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-eax: eb8cccd0
-ebx: eb8cccd0
-ecx: ff
-edx: ffeb2ca8
-ebp: ffeb5298
-edi: ffeb5c08
-esi: ffeb5c00
-esp: ffeb5280
-eip: eb89bfb8
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/stack.data b/libunwindstack/tests/files/offline/jit_debug_x86/stack.data
deleted file mode 100644
index c345762..0000000
--- a/libunwindstack/tests/files/offline/jit_debug_x86/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_map_arm/jit_map0.so b/libunwindstack/tests/files/offline/jit_map_arm/jit_map0.so
deleted file mode 100644
index e667883..0000000
--- a/libunwindstack/tests/files/offline/jit_map_arm/jit_map0.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_map_arm/jit_map1.so b/libunwindstack/tests/files/offline/jit_map_arm/jit_map1.so
deleted file mode 100644
index 9a1d714..0000000
--- a/libunwindstack/tests/files/offline/jit_map_arm/jit_map1.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_map_arm/libart.so b/libunwindstack/tests/files/offline/jit_map_arm/libart.so
deleted file mode 100644
index 09ba495..0000000
--- a/libunwindstack/tests/files/offline/jit_map_arm/libart.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_map_arm/libc.so b/libunwindstack/tests/files/offline/jit_map_arm/libc.so
deleted file mode 100644
index 39c9025..0000000
--- a/libunwindstack/tests/files/offline/jit_map_arm/libc.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_map_arm/maps.txt b/libunwindstack/tests/files/offline/jit_map_arm/maps.txt
deleted file mode 100644
index 5aaec54..0000000
--- a/libunwindstack/tests/files/offline/jit_map_arm/maps.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-e466e000-e4ae8000 r-xp 0 00:00 0 libart.so
-e7d91000-e7e31000 r-xp 0 00:00 0 libc.so
diff --git a/libunwindstack/tests/files/offline/jit_map_arm/regs.txt b/libunwindstack/tests/files/offline/jit_map_arm/regs.txt
deleted file mode 100644
index 0b51814..0000000
--- a/libunwindstack/tests/files/offline/jit_map_arm/regs.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-r0: e814103c
-r1: 12dcf218
-r2: 1a90df75
-r3: ffffffbf
-r4: 0
-r5: 12dc0800
-r6: 12dcf218
-r7: 1a90df75
-r8: 0
-r9: dd23cc00
-r10: 1c
-r11: cd4ff16c
-ip: 0
-sp: cd4ff140
-lr: d025cdd7
-pc: d025c788
diff --git a/libunwindstack/tests/files/offline/jit_map_arm/stack.data b/libunwindstack/tests/files/offline/jit_map_arm/stack.data
deleted file mode 100644
index fb8feeb..0000000
--- a/libunwindstack/tests/files/offline/jit_map_arm/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/libc.so b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/libc.so
deleted file mode 100644
index 7bb7156..0000000
--- a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/libc.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/linker64 b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/linker64
deleted file mode 100644
index 00a3896..0000000
--- a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/linker64
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/maps.txt b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/maps.txt
deleted file mode 100644
index a2babee..0000000
--- a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/maps.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-5f73997000-5f739dc000 r--p 0 00:00 0 test
-5f739dc000-5f73a43000 r-xp 44000 00:00 0 test
-711152c000-711156e000 r--p 0 00:00 0 libc.so
-711156e000-7111611000 --xp 42000 00:00 0 libc.so
-7112be2000-7112be4000 r-xp 0 00:00 0 vdso
-7112be4000-7112c1c000 r--p 0 00:00 0 linker64
-7112c1c000-7112ce1000 r-xp 38000 00:00 0 linker64
diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/regs.txt b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/regs.txt
deleted file mode 100644
index 3c601e1..0000000
--- a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/regs.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-x0: 7112bdbc24
-x1: 0
-x2: ffffffff
-x3: 0
-x4: 0
-x5: 0
-x6: 0
-x7: 7f7f7f7f7f7f7f7f
-x8: 62
-x9: a78826643b37f4a1
-x10: 7112bdbc20
-x11: 4100
-x12: 7112bdbb70
-x13: 18
-x14: 1d6518077
-x15: 2a43148faf732a
-x16: 16fc0
-x17: 71115f61a0
-x18: 7111d6a000
-x19: 7112cef1b0
-x20: 7112bdbda0
-x21: 59616d61
-x22: 1
-x23: 7112bdbc24
-x24: 4b0e
-x25: 62
-x26: 2
-x27: 0
-x28: 7111934020
-x29: 7112bdbd90
-sp: 7112bdbbf0
-lr: 7112c394ec
-pc: 7112cb99bc
diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack0.data b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack0.data
deleted file mode 100644
index 1674733..0000000
--- a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack0.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack1.data b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack1.data
deleted file mode 100644
index 6d7b48a..0000000
--- a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack1.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/test b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/test
deleted file mode 100644
index 3a75b8f..0000000
--- a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/test
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/vdso b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/vdso
deleted file mode 100644
index 4940916..0000000
--- a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/vdso
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/libc.so b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/libc.so
deleted file mode 100644
index 63383d0..0000000
--- a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/libc.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/maps.txt b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/maps.txt
deleted file mode 100644
index ba5a31b..0000000
--- a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/maps.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-200000-919000 r--p 0 00:00 0 perfetto_unittests
-919000-1a0c000 r-xp 719000 00:00 0 perfetto_unittests
-7f932696e000-7f9326b23000 r-xp 0 00:00 0 libc.so
diff --git a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/perfetto_unittests b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/perfetto_unittests
deleted file mode 100644
index a30e599..0000000
--- a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/perfetto_unittests
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/regs.txt b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/regs.txt
deleted file mode 100644
index 6cb4055..0000000
--- a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/regs.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-rax: 3b
-rbx: 3b
-rcx: 7f9326a57dd4
-rdx: 3b
-r8: 7ffd22415b09
-r9: 7ffd224155e0
-r10: 0
-r11: 246
-r12: 7f9326d28760
-r13: 3b
-r14: 7f9326d23760
-r15: 3b
-rdi: 1
-rsi: 2678850
-rbp: 2678850
-rsp: 7ffd224153c8
-rip: 7f9326a57dd4
diff --git a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/stack.data b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/stack.data
deleted file mode 100644
index 4edfe07..0000000
--- a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/offset_arm/libc.so b/libunwindstack/tests/files/offline/offset_arm/libc.so
deleted file mode 100644
index 9f5c8ca..0000000
--- a/libunwindstack/tests/files/offline/offset_arm/libc.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/offset_arm/libunwindstack_test b/libunwindstack/tests/files/offline/offset_arm/libunwindstack_test
deleted file mode 100644
index 7a30bfa..0000000
--- a/libunwindstack/tests/files/offline/offset_arm/libunwindstack_test
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/offset_arm/maps.txt b/libunwindstack/tests/files/offline/offset_arm/maps.txt
deleted file mode 100644
index 768dd9f..0000000
--- a/libunwindstack/tests/files/offline/offset_arm/maps.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-2b2a000-2b6c000 r--p 0 00:00 0 libunwindstack_test
-2b6c000-2e92000 r-xp 42000 00:00 0 libunwindstack_test
-f4110000-f4135000 r--p 0 00:00 0 libc.so
-f4135000-f41a9000 r-xp 25000 00:00 0 libc.so
diff --git a/libunwindstack/tests/files/offline/offset_arm/regs.txt b/libunwindstack/tests/files/offline/offset_arm/regs.txt
deleted file mode 100644
index 1f4ac8f..0000000
--- a/libunwindstack/tests/files/offline/offset_arm/regs.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-r0: 5
-r1: 5
-r2: 4
-r3: 1
-r4: 73804b6b
-r5: f3c9c000
-r6: 2ea09ac
-r7: 10624dd3
-r8: f41b5d8c
-r9: f3c9c000
-r10: 6f17
-r11: f3c94048
-ip: 2ea0807
-sp: f43d2ccc
-lr: 2e55fef
-pc: 2e55fa0
diff --git a/libunwindstack/tests/files/offline/offset_arm/stack0.data b/libunwindstack/tests/files/offline/offset_arm/stack0.data
deleted file mode 100644
index 23a9874..0000000
--- a/libunwindstack/tests/files/offline/offset_arm/stack0.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/offset_arm/stack1.data b/libunwindstack/tests/files/offline/offset_arm/stack1.data
deleted file mode 100644
index 49bdd1e..0000000
--- a/libunwindstack/tests/files/offline/offset_arm/stack1.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/ANGLEPrebuilt.apk b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/ANGLEPrebuilt.apk
deleted file mode 100644
index 0277359..0000000
--- a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/ANGLEPrebuilt.apk
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/libc.so b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/libc.so
deleted file mode 100644
index 20008fd..0000000
--- a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/libc.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/linker64 b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/linker64
deleted file mode 100644
index b90933b..0000000
--- a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/linker64
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/maps.txt b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/maps.txt
deleted file mode 100644
index c4fc067..0000000
--- a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/maps.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-7dabc03000-7dabc3f000 r--p 4000 00:00 0 ANGLEPrebuilt.apk
-7dabc3f000-7dabcf0000 r-xp 40000 00:00 0 ANGLEPrebuilt.apk
-7e7ee48000-7e7ee88000 r--p 0 00:00 0 libc.so
-7e7ee88000-7e7ef32000 r-xp 40000 00:00 0 libc.so
-7e82b01000-7e82b03000 r-xp 0 00:00 0 vdso.so
-7e82b03000-7e82b3c000 r--p 0 00:00 0 linker64
-7e82b3c000-7e82c77000 r-xp 39000 00:00 0 linker64
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/regs.txt b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/regs.txt
deleted file mode 100644
index 1e2ea32..0000000
--- a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/regs.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-x0: 7df8ca3c24
-x1: 0
-x2: ffffffff
-x3: 0
-x4: 0
-x5: 0
-x6: 0
-x7: 7f7f7f7f7f7f7f7f
-x8: 62
-x9: 20dd5829922a93ac
-x10: 7e82b57420
-x11: 4100
-x12: 7df8ca3b70
-x13: 7df8ca3b98
-x14: 73d015e5
-x15: 39a36122467299
-x16: 76ac
-x17: 0
-x18: 7df8cfc000
-x19: 7dabf3e7a0
-x20: 7df8ca3da0
-x21: 59616d61
-x22: 1
-x23: 7df8ca3c24
-x24: 1894
-x25: 62
-x26: 2
-x27: 0
-x28: 7dabf3e790
-x29: 7df8ca3d90
-sp: 7df8ca3bf0
-lr: 7e82b57270
-pc: 7e82c4fcbc
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/stack0.data b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/stack0.data
deleted file mode 100644
index ec07e15..0000000
--- a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/stack0.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/stack1.data b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/stack1.data
deleted file mode 100644
index 825bb1a..0000000
--- a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/stack1.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/vdso.so b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/vdso.so
deleted file mode 100644
index 205ebd4..0000000
--- a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/vdso.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/lib_mem.data b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/lib_mem.data
deleted file mode 100644
index f39d127..0000000
--- a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/lib_mem.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/libc.so b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/libc.so
deleted file mode 100644
index 20008fd..0000000
--- a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/libc.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/linker64 b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/linker64
deleted file mode 100644
index b90933b..0000000
--- a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/linker64
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/maps.txt b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/maps.txt
deleted file mode 100644
index 386d57a..0000000
--- a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/maps.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-7dabc03000-7dabc3f000 r--p 21d5000 00:00 0 ANGLEPrebuilt.apk
-7dabc3f000-7dabcf0000 r-xp 2211000 00:00 0 ANGLEPrebuilt.apk
-7e7ee48000-7e7ee88000 r--p 0 00:00 0 libc.so
-7e7ee88000-7e7ef32000 r-xp 40000 00:00 0 libc.so
-7e82b01000-7e82b03000 r-xp 0 00:00 0 vdso.so
-7e82b03000-7e82b3c000 r--p 0 00:00 0 linker64
-7e82b3c000-7e82c77000 r-xp 39000 00:00 0 linker64
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/regs.txt b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/regs.txt
deleted file mode 100644
index 1e2ea32..0000000
--- a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/regs.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-x0: 7df8ca3c24
-x1: 0
-x2: ffffffff
-x3: 0
-x4: 0
-x5: 0
-x6: 0
-x7: 7f7f7f7f7f7f7f7f
-x8: 62
-x9: 20dd5829922a93ac
-x10: 7e82b57420
-x11: 4100
-x12: 7df8ca3b70
-x13: 7df8ca3b98
-x14: 73d015e5
-x15: 39a36122467299
-x16: 76ac
-x17: 0
-x18: 7df8cfc000
-x19: 7dabf3e7a0
-x20: 7df8ca3da0
-x21: 59616d61
-x22: 1
-x23: 7df8ca3c24
-x24: 1894
-x25: 62
-x26: 2
-x27: 0
-x28: 7dabf3e790
-x29: 7df8ca3d90
-sp: 7df8ca3bf0
-lr: 7e82b57270
-pc: 7e82c4fcbc
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/stack0.data b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/stack0.data
deleted file mode 100644
index ec07e15..0000000
--- a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/stack0.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/stack1.data b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/stack1.data
deleted file mode 100644
index 825bb1a..0000000
--- a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/stack1.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/vdso.so b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/vdso.so
deleted file mode 100644
index 205ebd4..0000000
--- a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/vdso.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/libc.so b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/libc.so
deleted file mode 100644
index cac1dd9..0000000
--- a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/libc.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/maps.txt b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/maps.txt
deleted file mode 100644
index 2c5ca62..0000000
--- a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/maps.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-7be5e48000-7be6b2b000 r-xp 5000 00:00 0 test.apk
-7cbe030000-7cbe070000 r--p 0 00:00 0 libc.so
-7cbe070000-7cbe11a000 r-xp 40000 00:00 0 libc.so
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/regs.txt b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/regs.txt
deleted file mode 100644
index 090aeda..0000000
--- a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/regs.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-x0: 7c326f6568
-x1: 80
-x2: 0
-x3: 0
-x4: 0
-x5: 0
-x6: 0
-x7: 7f7f7f7f7f7f7f7f
-x8: 62
-x9: 1
-x10: 1
-x11: 0
-x12: ffffffffc4653600
-x13: 17645696f
-x14: 2742ed97ca77a3
-x15: 3ab49084
-x16: 7be6b6bdb8
-x17: 7cbe0b14a0
-x18: 7c2b02a000
-x19: 0
-x20: 7c326f6568
-x21: 7be69c827c
-x22: 7be69c8272
-x23: 1
-x24: 7be74f7100
-x25: 881
-x26: 7be4f07a00
-x27: c479c000
-x28: 7be4f07998
-x29: 7be4f079b4
-sp: 7be4f077d0
-lr: 7be6715f60
-pc: 7cbe0b14bc
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/stack.data b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/stack.data
deleted file mode 100644
index 27d5bf3..0000000
--- a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/test.apk b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/test.apk
deleted file mode 100644
index 70a9c71..0000000
--- a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/test.apk
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/signal_fde_x86/libc.so b/libunwindstack/tests/files/offline/signal_fde_x86/libc.so
deleted file mode 100644
index 5c882e4..0000000
--- a/libunwindstack/tests/files/offline/signal_fde_x86/libc.so
+++ /dev/null
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
deleted file mode 100644
index 8dcff67..0000000
--- a/libunwindstack/tests/files/offline/signal_fde_x86/libunwindstack_test
+++ /dev/null
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
deleted file mode 100644
index 6166a9d..0000000
--- a/libunwindstack/tests/files/offline/signal_fde_x86/maps.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-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
deleted file mode 100644
index 456b212..0000000
--- a/libunwindstack/tests/files/offline/signal_fde_x86/regs.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-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
deleted file mode 100644
index 0bbbe22..0000000
--- a/libunwindstack/tests/files/offline/signal_fde_x86/stack0.data
+++ /dev/null
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
deleted file mode 100644
index 0873046..0000000
--- a/libunwindstack/tests/files/offline/signal_fde_x86/stack1.data
+++ /dev/null
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
deleted file mode 100644
index cea7336..0000000
--- a/libunwindstack/tests/files/offline/signal_fde_x86_64/libc.so
+++ /dev/null
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
deleted file mode 100644
index c48e84e..0000000
--- a/libunwindstack/tests/files/offline/signal_fde_x86_64/libunwindstack_test
+++ /dev/null
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
deleted file mode 100644
index 514aa71..0000000
--- a/libunwindstack/tests/files/offline/signal_fde_x86_64/maps.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-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
deleted file mode 100644
index 8da7b4e..0000000
--- a/libunwindstack/tests/files/offline/signal_fde_x86_64/regs.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-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
deleted file mode 100644
index e19a016..0000000
--- a/libunwindstack/tests/files/offline/signal_fde_x86_64/stack0.data
+++ /dev/null
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
deleted file mode 100644
index 3435f7c..0000000
--- a/libunwindstack/tests/files/offline/signal_fde_x86_64/stack1.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/signal_load_bias_arm/libc.so b/libunwindstack/tests/files/offline/signal_load_bias_arm/libc.so
deleted file mode 100644
index f046624..0000000
--- a/libunwindstack/tests/files/offline/signal_load_bias_arm/libc.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/signal_load_bias_arm/libunwindstack_unit_test b/libunwindstack/tests/files/offline/signal_load_bias_arm/libunwindstack_unit_test
deleted file mode 100644
index f460dd6..0000000
--- a/libunwindstack/tests/files/offline/signal_load_bias_arm/libunwindstack_unit_test
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/signal_load_bias_arm/maps.txt b/libunwindstack/tests/files/offline/signal_load_bias_arm/maps.txt
deleted file mode 100644
index 165ae49..0000000
--- a/libunwindstack/tests/files/offline/signal_load_bias_arm/maps.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-b66b7000-b670c000 r--p 0 00:00 0 libunwindstack_unit_test
-b670c000-b69a8000 r-xp 54000 00:00 0 libunwindstack_unit_test
-f23a6000-f23d0000 r--p 0 00:00 0 libc.so
-f23d0000-f2451000 r-xp 29000 00:00 0 libc.so
diff --git a/libunwindstack/tests/files/offline/signal_load_bias_arm/regs.txt b/libunwindstack/tests/files/offline/signal_load_bias_arm/regs.txt
deleted file mode 100644
index e03f8fd..0000000
--- a/libunwindstack/tests/files/offline/signal_load_bias_arm/regs.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-r0: b69b7c84
-r1: 1
-r2: 1
-r3: 1
-r4: f1e52bd0
-r5: f1e11000
-r6: f1e52bd0
-r7: f1e52a38
-r8: f1e11000
-r9: 5de82a8f
-r10: f1e06030
-r11: f1e6d080
-ip: ffe67a88
-sp: f2790ce8
-lr: b6955fab
-pc: b6955f9e
diff --git a/libunwindstack/tests/files/offline/signal_load_bias_arm/stack0.data b/libunwindstack/tests/files/offline/signal_load_bias_arm/stack0.data
deleted file mode 100644
index d9f23f8..0000000
--- a/libunwindstack/tests/files/offline/signal_load_bias_arm/stack0.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/signal_load_bias_arm/stack1.data b/libunwindstack/tests/files/offline/signal_load_bias_arm/stack1.data
deleted file mode 100644
index 6011883..0000000
--- a/libunwindstack/tests/files/offline/signal_load_bias_arm/stack1.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/straddle_arm/libbase.so b/libunwindstack/tests/files/offline/straddle_arm/libbase.so
deleted file mode 100644
index d1f16ee..0000000
--- a/libunwindstack/tests/files/offline/straddle_arm/libbase.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/straddle_arm/libc.so b/libunwindstack/tests/files/offline/straddle_arm/libc.so
deleted file mode 100644
index 4dc19ca..0000000
--- a/libunwindstack/tests/files/offline/straddle_arm/libc.so
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/straddle_arm/maps.txt b/libunwindstack/tests/files/offline/straddle_arm/maps.txt
deleted file mode 100644
index 8c26479..0000000
--- a/libunwindstack/tests/files/offline/straddle_arm/maps.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-f2d9a000-f2da7fff r-xp 00000000 00:00 0 libbase.so
-f3002000-f3005fff rw-p 00000000 00:00 0 [stack:25941]
-f31d0000-f326bfff r-xp 00000000 00:00 0 libc.so
-f3352000-f336bfff r-xp 00000000 00:00 0 /does/not/exist/libhidlbase.so
diff --git a/libunwindstack/tests/files/offline/straddle_arm/regs.txt b/libunwindstack/tests/files/offline/straddle_arm/regs.txt
deleted file mode 100644
index 3baedf3..0000000
--- a/libunwindstack/tests/files/offline/straddle_arm/regs.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-pc: f31ea9f8
-sp: e9c866f8
-lr: f31f179f
diff --git a/libunwindstack/tests/files/offline/straddle_arm/stack.data b/libunwindstack/tests/files/offline/straddle_arm/stack.data
deleted file mode 100644
index 83aeb4a..0000000
--- a/libunwindstack/tests/files/offline/straddle_arm/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/straddle_arm64/libunwindstack_test b/libunwindstack/tests/files/offline/straddle_arm64/libunwindstack_test
deleted file mode 100644
index 092fc3a..0000000
--- a/libunwindstack/tests/files/offline/straddle_arm64/libunwindstack_test
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/files/offline/straddle_arm64/maps.txt b/libunwindstack/tests/files/offline/straddle_arm64/maps.txt
deleted file mode 100644
index bdf29b5..0000000
--- a/libunwindstack/tests/files/offline/straddle_arm64/maps.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-00000064d05ab000-00000064d0a6cfff r-xp 00000000 00:00 0 libunwindstack_test
-0000007fe0d64000-0000007fe0d84fff rw-p 00000000 00:00 0 [stack]
diff --git a/libunwindstack/tests/files/offline/straddle_arm64/regs.txt b/libunwindstack/tests/files/offline/straddle_arm64/regs.txt
deleted file mode 100644
index ff8a936..0000000
--- a/libunwindstack/tests/files/offline/straddle_arm64/regs.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-pc: 00000064d09d4fd8
-sp: 0000007fe0d84040
-lr: 00000064d09d507c
-x29: 0000007fe0d84070
diff --git a/libunwindstack/tests/files/offline/straddle_arm64/stack.data b/libunwindstack/tests/files/offline/straddle_arm64/stack.data
deleted file mode 100644
index 824d0e2..0000000
--- a/libunwindstack/tests/files/offline/straddle_arm64/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/fuzz/UnwinderComponentCreator.cpp b/libunwindstack/tests/fuzz/UnwinderComponentCreator.cpp
deleted file mode 100644
index 65052b6..0000000
--- a/libunwindstack/tests/fuzz/UnwinderComponentCreator.cpp
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- * Copyright 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 "UnwinderComponentCreator.h"
-
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-std::unique_ptr<Regs> GetRegisters(ArchEnum arch) {
- switch (arch) {
- case unwindstack::ARCH_ARM: {
- std::unique_ptr<unwindstack::RegsArm> regs = std::make_unique<unwindstack::RegsArm>();
- return regs;
- }
- case unwindstack::ARCH_ARM64: {
- std::unique_ptr<unwindstack::RegsArm64> regs = std::make_unique<unwindstack::RegsArm64>();
- return regs;
- }
- case unwindstack::ARCH_X86: {
- std::unique_ptr<unwindstack::RegsX86> regs = std::make_unique<unwindstack::RegsX86>();
- return regs;
- }
- case unwindstack::ARCH_X86_64: {
- std::unique_ptr<unwindstack::RegsX86_64> regs = std::make_unique<unwindstack::RegsX86_64>();
- return regs;
- }
- case unwindstack::ARCH_MIPS: {
- std::unique_ptr<unwindstack::RegsMips> regs = std::make_unique<unwindstack::RegsMips>();
- return regs;
- }
- case unwindstack::ARCH_MIPS64: {
- std::unique_ptr<unwindstack::RegsMips64> regs = std::make_unique<unwindstack::RegsMips64>();
- return regs;
- }
- case unwindstack::ARCH_UNKNOWN:
- default: {
- std::unique_ptr<unwindstack::RegsX86_64> regs = std::make_unique<unwindstack::RegsX86_64>();
- return regs;
- }
- }
-}
-
-ArchEnum GetArch(FuzzedDataProvider* data_provider) {
- uint8_t arch = data_provider->ConsumeIntegralInRange<uint8_t>(1, kArchCount);
- return static_cast<ArchEnum>(arch);
-}
-
-void ElfAddMapInfo(Maps* maps, uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
- const char* name, Elf* elf = nullptr) {
- std::string str_name(name);
- maps->Add(start, end, offset, flags, name, static_cast<uint64_t>(-1));
- if (elf != nullptr) {
- const auto& map_info = *--maps->end();
- map_info->elf.reset(elf);
- }
-}
-
-void ElfPushFakeFunctionData(FuzzedDataProvider* data_provider, ElfInterfaceFake* elf) {
- uint8_t func_count = data_provider->ConsumeIntegralInRange<uint>(0, kMaxFuncCount);
- for (uint8_t i = 0; i < func_count; i++) {
- std::string func_name = data_provider->ConsumeRandomLengthString(kMaxFuncNameLen);
- bool global = data_provider->ConsumeBool();
- if (global) {
- elf->FakeSetGlobalVariable(func_name, data_provider->ConsumeIntegral<uint64_t>());
- } else {
- ElfInterfaceFake::FakePushFunctionData(FunctionData(func_name, i));
- }
- }
-}
-void ElfPushFakeStepData(FuzzedDataProvider* data_provider) {
- uint8_t step_count = data_provider->ConsumeIntegralInRange<uint>(0, kMaxStepCount);
- for (uint8_t i = 0; i < step_count; i++) {
- uint64_t pc = data_provider->ConsumeIntegral<uint64_t>();
- uint64_t sp = data_provider->ConsumeIntegral<uint64_t>();
- bool finished = i + 1 == step_count;
- ElfInterfaceFake::FakePushStepData(StepData(pc, sp, finished));
- }
-}
-
-ElfFake* PopulateElfFake(FuzzedDataProvider* data_provider) {
- // This will be passed to a smart pointer in ElfAddMapInfo.
- ElfFake* elf = new ElfFake(new MemoryFake);
-
- // This will be handled by a smart pointer within Elf.
- ElfInterfaceFake* interface_fake = new ElfInterfaceFake(nullptr);
- std::string build_id = data_provider->ConsumeRandomLengthString(kMaxBuildIdLen);
- interface_fake->FakeSetBuildID(build_id);
- std::string so_name = data_provider->ConsumeRandomLengthString(kMaxSoNameLen);
- interface_fake->FakeSetSoname(so_name.c_str());
-
- elf->FakeSetArch(GetArch(data_provider));
- elf->FakeSetLoadBias(data_provider->ConsumeIntegral<uint64_t>());
-
- ElfPushFakeFunctionData(data_provider, interface_fake);
- ElfPushFakeStepData(data_provider);
-
- elf->FakeSetInterface(interface_fake);
- ElfInterfaceFake::FakeClear();
- return elf;
-}
-
-static constexpr size_t kPageSize = 4096;
-
-static inline bool AlignToPage(uint64_t address, uint64_t* aligned_address) {
- if (__builtin_add_overflow(address, kPageSize - 1, aligned_address)) {
- return false;
- }
- *aligned_address &= ~(kPageSize - 1);
- return true;
-}
-
-std::unique_ptr<Maps> GetMaps(FuzzedDataProvider* data_provider) {
- std::unique_ptr<Maps> maps = std::make_unique<Maps>();
- std::map<uint64_t, uint64_t> map_ends;
- uint8_t entry_count = data_provider->ConsumeIntegralInRange<uint8_t>(0, kMaxMapEntryCount);
- for (uint8_t i = 0; i < entry_count; i++) {
- uint64_t start;
- if (!AlignToPage(data_provider->ConsumeIntegral<uint64_t>(), &start)) {
- // Overflowed.
- continue;
- }
- uint64_t end;
- if (!AlignToPage(data_provider->ConsumeIntegralInRange<uint64_t>(start, UINT64_MAX), &end)) {
- // Overflowed.
- continue;
- }
- if (start == end) {
- // It's impossible to see start == end in the real world, so
- // make sure the map contains at least one page of data.
- if (__builtin_add_overflow(end, 0x1000, &end)) {
- continue;
- }
- }
- // Make sure not to add overlapping maps, that is not something that can
- // happen in the real world.
- auto entry = map_ends.upper_bound(start);
- if (entry != map_ends.end() && end > entry->second) {
- continue;
- }
- map_ends[end] = start;
-
- uint64_t offset;
- if (!AlignToPage(data_provider->ConsumeIntegral<uint64_t>(), &offset)) {
- // Overflowed.
- continue;
- }
- std::string map_info_name = data_provider->ConsumeRandomLengthString(kMaxMapInfoNameLen);
- uint8_t flags = PROT_READ | PROT_WRITE;
-
- bool exec = data_provider->ConsumeBool();
- if (exec) {
- flags |= PROT_EXEC;
- }
-
- bool shouldAddElf = data_provider->ConsumeBool();
- if (shouldAddElf) {
- ElfAddMapInfo(maps.get(), start, end, offset, flags, map_info_name.c_str(),
- PopulateElfFake(data_provider));
- } else {
- ElfAddMapInfo(maps.get(), start, end, offset, flags, map_info_name.c_str());
- }
- }
- maps->Sort();
- return maps;
-}
-
-// This code (until PutElfFilesInMemory) is pretty much directly copied from JitDebugTest.cpp
-// There's a few minor modifications, most notably, all methods accept a MemoryFake pointer, and
-// PutElfInMemory inserts JIT data when called.
-void WriteDescriptor32(MemoryFake* memory, uint64_t addr, uint32_t entry) {
- // Format of the 32 bit JITDescriptor structure:
- // uint32_t version
- memory->SetData32(addr, 1);
- // uint32_t action_flag
- memory->SetData32(addr + 4, 0);
- // uint32_t relevant_entry
- memory->SetData32(addr + 8, 0);
- // uint32_t first_entry
- memory->SetData32(addr + 12, entry);
-}
-
-void WriteDescriptor64(MemoryFake* memory, uint64_t addr, uint64_t entry) {
- // Format of the 64 bit JITDescriptor structure:
- // uint32_t version
- memory->SetData32(addr, 1);
- // uint32_t action_flag
- memory->SetData32(addr + 4, 0);
- // uint64_t relevant_entry
- memory->SetData64(addr + 8, 0);
- // uint64_t first_entry
- memory->SetData64(addr + 16, entry);
-}
-
-void WriteEntry32Pack(MemoryFake* memory, uint64_t addr, uint32_t prev, uint32_t next,
- uint32_t elf_addr, uint64_t elf_size) {
- // Format of the 32 bit JITCodeEntry structure:
- // uint32_t next
- memory->SetData32(addr, next);
- // uint32_t prev
- memory->SetData32(addr + 4, prev);
- // uint32_t symfile_addr
- memory->SetData32(addr + 8, elf_addr);
- // uint64_t symfile_size
- memory->SetData64(addr + 12, elf_size);
-}
-
-void WriteEntry32Pad(MemoryFake* memory, uint64_t addr, uint32_t prev, uint32_t next,
- uint32_t elf_addr, uint64_t elf_size) {
- // Format of the 32 bit JITCodeEntry structure:
- // uint32_t next
- memory->SetData32(addr, next);
- // uint32_t prev
- memory->SetData32(addr + 4, prev);
- // uint32_t symfile_addr
- memory->SetData32(addr + 8, elf_addr);
- // uint32_t pad
- memory->SetData32(addr + 12, 0);
- // uint64_t symfile_size
- memory->SetData64(addr + 16, elf_size);
-}
-
-void WriteEntry64(MemoryFake* memory, uint64_t addr, uint64_t prev, uint64_t next,
- uint64_t elf_addr, uint64_t elf_size) {
- // Format of the 64 bit JITCodeEntry structure:
- // uint64_t next
- memory->SetData64(addr, next);
- // uint64_t prev
- memory->SetData64(addr + 8, prev);
- // uint64_t symfile_addr
- memory->SetData64(addr + 16, elf_addr);
- // uint64_t symfile_size
- memory->SetData64(addr + 24, elf_size);
-}
-
-template <typename EhdrType, typename ShdrType>
-void PutElfInMemory(MemoryFake* memory, uint64_t offset, uint8_t class_type, uint8_t machine_type,
- uint32_t pc, uint32_t size) {
- EhdrType ehdr;
- memset(&ehdr, 0, sizeof(ehdr));
- uint64_t sh_offset = sizeof(ehdr);
- memcpy(ehdr.e_ident, ELFMAG, SELFMAG);
- ehdr.e_ident[EI_CLASS] = class_type;
- ehdr.e_machine = machine_type;
- ehdr.e_shstrndx = 1;
- ehdr.e_shoff = sh_offset;
- ehdr.e_shentsize = sizeof(ShdrType);
- ehdr.e_shnum = 3;
- memory->SetMemory(offset, &ehdr, sizeof(ehdr));
-
- ShdrType shdr;
- memset(&shdr, 0, sizeof(shdr));
- shdr.sh_type = SHT_NULL;
- memory->SetMemory(offset + sh_offset, &shdr, sizeof(shdr));
-
- sh_offset += sizeof(shdr);
- memset(&shdr, 0, sizeof(shdr));
- shdr.sh_type = SHT_STRTAB;
- shdr.sh_name = 1;
- shdr.sh_offset = 0x500;
- shdr.sh_size = 0x100;
- memory->SetMemory(offset + sh_offset, &shdr, sizeof(shdr));
- memory->SetMemory(offset + 0x500, ".debug_frame");
-
- sh_offset += sizeof(shdr);
- memset(&shdr, 0, sizeof(shdr));
- shdr.sh_type = SHT_PROGBITS;
- shdr.sh_name = 0;
- shdr.sh_addr = 0x600;
- shdr.sh_offset = 0x600;
- shdr.sh_size = 0x200;
- memory->SetMemory(offset + sh_offset, &shdr, sizeof(shdr));
-
- // Now add a single cie/fde.
- uint64_t dwarf_offset = offset + 0x600;
- if (class_type == ELFCLASS32) {
- // CIE 32 information.
- memory->SetData32(dwarf_offset, 0xfc);
- memory->SetData32(dwarf_offset + 0x4, 0xffffffff);
- memory->SetData8(dwarf_offset + 0x8, 1);
- memory->SetData8(dwarf_offset + 0x9, '\0');
- memory->SetData8(dwarf_offset + 0xa, 0x4);
- memory->SetData8(dwarf_offset + 0xb, 0x4);
- memory->SetData8(dwarf_offset + 0xc, 0x1);
-
- // FDE 32 information.
- memory->SetData32(dwarf_offset + 0x100, 0xfc);
- memory->SetData32(dwarf_offset + 0x104, 0);
- memory->SetData32(dwarf_offset + 0x108, pc);
- memory->SetData32(dwarf_offset + 0x10c, size);
- } else {
- // CIE 64 information.
- memory->SetData32(dwarf_offset, 0xffffffff);
- memory->SetData64(dwarf_offset + 4, 0xf4);
- memory->SetData64(dwarf_offset + 0xc, 0xffffffffffffffffULL);
- memory->SetData8(dwarf_offset + 0x14, 1);
- memory->SetData8(dwarf_offset + 0x15, '\0');
- memory->SetData8(dwarf_offset + 0x16, 0x4);
- memory->SetData8(dwarf_offset + 0x17, 0x4);
- memory->SetData8(dwarf_offset + 0x18, 0x1);
-
- // FDE 64 information.
- memory->SetData32(dwarf_offset + 0x100, 0xffffffff);
- memory->SetData64(dwarf_offset + 0x104, 0xf4);
- memory->SetData64(dwarf_offset + 0x10c, 0);
- memory->SetData64(dwarf_offset + 0x114, pc);
- memory->SetData64(dwarf_offset + 0x11c, size);
- }
-}
-
-void PutElfFilesInMemory(MemoryFake* memory, FuzzedDataProvider* data_provider) {
- uint8_t elf_file_count = data_provider->ConsumeIntegralInRange<uint8_t>(0, kMaxJitElfFiles);
- int entry_offset = 0;
- int prev_jit_addr = 0;
- for (uint8_t i = 0; i < elf_file_count; i++) {
- uint64_t offset = data_provider->ConsumeIntegral<uint64_t>();
- // Technically the max valid value is ELFCLASSNUM - 1 (2), but
- // we want to test values outside of that range.
- uint8_t class_type = data_provider->ConsumeIntegral<uint8_t>();
- // Same here, EM_NUM is 253, max valid machine type is 252
- uint8_t machine_type = data_provider->ConsumeIntegral<uint8_t>();
- uint32_t pc = data_provider->ConsumeIntegral<uint32_t>();
- uint32_t size = data_provider->ConsumeIntegral<uint32_t>();
- bool sixty_four_bit = data_provider->ConsumeBool();
- bool write_jit = data_provider->ConsumeBool();
- if (sixty_four_bit) {
- PutElfInMemory<Elf64_Ehdr, Elf64_Shdr>(memory, offset, class_type, machine_type, pc, size);
- } else {
- PutElfInMemory<Elf32_Ehdr, Elf32_Shdr>(memory, offset, class_type, machine_type, pc, size);
- }
- if (write_jit) {
- bool use_pad = data_provider->ConsumeBool();
- // It is possible this will overwrite part of the ELF.
- // This provides an interesting test of how malformed ELF
- // data is handled.
- uint64_t cur_descriptor_addr = 0x11800 + entry_offset;
- uint64_t cur_jit_addr = 0x200000 + entry_offset;
- uint64_t next_jit_addr = cur_jit_addr + size;
- if (sixty_four_bit) {
- WriteDescriptor64(memory, 0x11800, cur_jit_addr);
- WriteEntry64(memory, cur_jit_addr, prev_jit_addr, next_jit_addr, pc, size);
- } else {
- // Loop back. Again, this may corrupt data,
- // but that will allow for testing edge cases with
- // malformed JIT data.
- if (cur_jit_addr > UINT32_MAX) {
- entry_offset = 0;
- cur_jit_addr = 0x200000;
- cur_descriptor_addr = 0x11800;
- next_jit_addr = cur_jit_addr + size;
- }
- WriteDescriptor32(memory, cur_descriptor_addr, cur_jit_addr);
- if (use_pad) {
- WriteEntry32Pad(memory, cur_jit_addr, prev_jit_addr, next_jit_addr, pc, size);
- } else {
- WriteEntry32Pack(memory, cur_jit_addr, prev_jit_addr, next_jit_addr, pc, size);
- }
- }
- entry_offset += size;
- prev_jit_addr = cur_jit_addr;
- }
- }
-}
-
-std::vector<std::string> GetStringList(FuzzedDataProvider* data_provider, uint max_str_len,
- uint max_strings) {
- uint str_count = data_provider->ConsumeIntegralInRange<uint>(0, max_strings);
- std::vector<std::string> strings;
- for (uint i = 0; i < str_count; i++) {
- strings.push_back(data_provider->ConsumeRandomLengthString(max_str_len));
- }
- return strings;
-}
-
-std::unique_ptr<DexFiles> GetDexFiles(FuzzedDataProvider* data_provider,
- std::shared_ptr<Memory> memory, uint max_library_length,
- uint max_libraries) {
- std::vector<std::string> search_libs =
- GetStringList(data_provider, max_library_length, max_libraries);
- if (search_libs.size() <= 0) {
- return std::make_unique<DexFiles>(memory);
- }
-
- return std::make_unique<DexFiles>(memory, search_libs);
-}
diff --git a/libunwindstack/tests/fuzz/UnwinderComponentCreator.h b/libunwindstack/tests/fuzz/UnwinderComponentCreator.h
deleted file mode 100644
index 09b3379..0000000
--- a/libunwindstack/tests/fuzz/UnwinderComponentCreator.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#ifndef _LIBUNWINDSTACK_UNWINDERCOMPONENTCREATOR_H
-#define _LIBUNWINDSTACK_UNWINDERCOMPONENTCREATOR_H
-
-#include <elf.h>
-#include <sys/mman.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <fuzzer/FuzzedDataProvider.h>
-#include <unwindstack/DexFiles.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Regs.h>
-#include <unwindstack/RegsArm.h>
-#include <unwindstack/RegsArm64.h>
-#include <unwindstack/RegsMips.h>
-#include <unwindstack/RegsMips64.h>
-#include <unwindstack/RegsX86.h>
-#include <unwindstack/RegsX86_64.h>
-
-#include "../ElfFake.h"
-#include "../MemoryFake.h"
-
-#include "fuzzer/FuzzedDataProvider.h"
-
-using unwindstack::ArchEnum;
-using unwindstack::DexFiles;
-using unwindstack::Elf;
-using unwindstack::ElfFake;
-using unwindstack::ElfInterfaceFake;
-using unwindstack::FunctionData;
-using unwindstack::Maps;
-using unwindstack::Memory;
-using unwindstack::MemoryFake;
-using unwindstack::Regs;
-using unwindstack::StepData;
-
-static constexpr uint8_t kArchCount = 6;
-
-static constexpr uint8_t kMaxSoNameLen = 150;
-
-static constexpr uint8_t kMaxFuncNameLen = 50;
-static constexpr uint8_t kMaxFuncCount = 100;
-
-static constexpr uint8_t kMaxJitElfFiles = 20;
-static constexpr uint8_t kJitElfPadding = 32;
-
-static constexpr uint8_t kMaxStepCount = 100;
-static constexpr uint8_t kMaxMapEntryCount = 50;
-static constexpr uint8_t kMaxBuildIdLen = 100;
-static constexpr uint8_t kMaxMapInfoNameLen = 150;
-
-std::unique_ptr<unwindstack::Regs> GetRegisters(unwindstack::ArchEnum arch);
-std::unique_ptr<unwindstack::Maps> GetMaps(FuzzedDataProvider* data_provider);
-std::vector<std::string> GetStringList(FuzzedDataProvider* data_provider, uint max_str_len,
- uint max_strings);
-unwindstack::ArchEnum GetArch(FuzzedDataProvider* data_provider);
-
-void AddMapInfo(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags, const char* name,
- Elf* elf = nullptr);
-void PutElfFilesInMemory(MemoryFake* memory, FuzzedDataProvider* data_provider);
-
-std::unique_ptr<unwindstack::DexFiles> GetDexFiles(FuzzedDataProvider* data_provider,
- std::shared_ptr<unwindstack::Memory> memory,
- uint max_libraries, uint max_library_length);
-#endif // _LIBUNWINDSTACK_UNWINDERCOMPONENTCREATOR_H
diff --git a/libunwindstack/tests/fuzz/UnwinderFuzz.cpp b/libunwindstack/tests/fuzz/UnwinderFuzz.cpp
deleted file mode 100644
index 1600547..0000000
--- a/libunwindstack/tests/fuzz/UnwinderFuzz.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 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 <functional>
-#include <iostream>
-#include <vector>
-
-#include <unwindstack/JitDebug.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/Unwinder.h>
-
-#include "../MemoryFake.h"
-#include "UnwinderComponentCreator.h"
-#include "fuzzer/FuzzedDataProvider.h"
-
-namespace unwindstack {
-
-static constexpr int kMaxUnwindStringLen = 50;
-static constexpr int kMaxUnwindStrings = 50;
-
-void PerformUnwind(FuzzedDataProvider* data_provider, Unwinder* unwinder) {
- // 0 = don't set any values
- // 1 = set initial_map_names_to_skip
- // 2 = set map_suffixes_to_ignore
- // 3 = set both
- uint8_t set_values = data_provider->ConsumeIntegral<uint8_t>() % 4;
- if (set_values == 0) {
- unwinder->Unwind();
- } else if (set_values == 1) {
- // Only setting initial_map_names_to_skip
- std::vector<std::string> skip_names =
- GetStringList(data_provider, kMaxUnwindStringLen, kMaxUnwindStrings);
-
- unwinder->Unwind(&skip_names, nullptr);
- } else if (set_values == 2) {
- // Only setting map_suffixes_to_ignore
- std::vector<std::string> ignore_suffixes =
- GetStringList(data_provider, kMaxUnwindStringLen, kMaxUnwindStrings);
-
- unwinder->Unwind(nullptr, &ignore_suffixes);
- } else if (set_values == 3) {
- // Setting both values
- std::vector<std::string> skip_names =
- GetStringList(data_provider, kMaxUnwindStringLen, kMaxUnwindStrings);
- std::vector<std::string> ignore_suffixes =
- GetStringList(data_provider, kMaxUnwindStringLen, kMaxUnwindStrings);
-
- unwinder->Unwind(&skip_names, &ignore_suffixes);
- }
-}
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- FuzzedDataProvider data_provider(data, size);
-
- // We need to construct an unwinder.
- // Generate the Maps:
- std::unique_ptr<Maps> maps = GetMaps(&data_provider);
-
- // Generate the Regs:
- uint8_t arch_val = data_provider.ConsumeIntegralInRange<uint8_t>(1, kArchCount);
- ArchEnum arch = static_cast<ArchEnum>(arch_val);
- std::unique_ptr<Regs> regs = GetRegisters(arch);
-
- // Generate memory:
- std::shared_ptr<Memory> memory = std::make_shared<MemoryFake>();
- PutElfFilesInMemory(reinterpret_cast<MemoryFake*>(memory.get()), &data_provider);
-
- size_t max_frames = data_provider.ConsumeIntegralInRange<size_t>(0, 5000);
-
- std::unique_ptr<JitDebug> jit_debug_ptr = std::make_unique<JitDebug>(memory);
-
- // Create instance
- Unwinder unwinder(max_frames, maps.get(), regs.get(), memory);
- unwinder.SetJitDebug(jit_debug_ptr.get());
- unwinder.SetResolveNames(data_provider.ConsumeBool());
- // Call unwind
- PerformUnwind(&data_provider, &unwinder);
-
- // Run some additional logic that changes after unwind
- uint64_t pc = data_provider.ConsumeIntegral<uint64_t>();
- unwinder.BuildFrameFromPcOnly(pc);
- unwinder.ConsumeFrames();
- return 0;
-}
-} // namespace unwindstack
diff --git a/libunwindstack/tools/unwind.cpp b/libunwindstack/tools/unwind.cpp
deleted file mode 100644
index ae45f06..0000000
--- a/libunwindstack/tools/unwind.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2016 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 <elf.h>
-#include <errno.h>
-#include <inttypes.h>
-#include <signal.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ptrace.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <unwindstack/DexFiles.h>
-#include <unwindstack/Elf.h>
-#include <unwindstack/JitDebug.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/Regs.h>
-#include <unwindstack/Unwinder.h>
-
-static bool Attach(pid_t pid) {
- if (ptrace(PTRACE_SEIZE, pid, 0, 0) == -1) {
- return false;
- }
-
- if (ptrace(PTRACE_INTERRUPT, pid, 0, 0) == -1) {
- ptrace(PTRACE_DETACH, pid, 0, 0);
- return false;
- }
-
- // Allow at least 1 second to attach properly.
- for (size_t i = 0; i < 1000; i++) {
- siginfo_t si;
- if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
- return true;
- }
- usleep(1000);
- }
- printf("%d: Failed to stop.\n", pid);
- return false;
-}
-
-void DoUnwind(pid_t pid) {
- unwindstack::Regs* regs = unwindstack::Regs::RemoteGet(pid);
- if (regs == nullptr) {
- printf("Unable to get remote reg data\n");
- return;
- }
-
- printf("ABI: ");
- switch (regs->Arch()) {
- case unwindstack::ARCH_ARM:
- printf("arm");
- break;
- case unwindstack::ARCH_X86:
- printf("x86");
- break;
- case unwindstack::ARCH_ARM64:
- printf("arm64");
- break;
- case unwindstack::ARCH_X86_64:
- printf("x86_64");
- break;
- case unwindstack::ARCH_MIPS:
- printf("mips");
- break;
- case unwindstack::ARCH_MIPS64:
- printf("mips64");
- break;
- default:
- printf("unknown\n");
- return;
- }
- printf("\n");
-
- unwindstack::UnwinderFromPid unwinder(1024, pid);
- unwinder.SetRegs(regs);
- unwinder.Unwind();
-
- // Print the frames.
- for (size_t i = 0; i < unwinder.NumFrames(); i++) {
- printf("%s\n", unwinder.FormatFrame(i).c_str());
- }
-}
-
-int main(int argc, char** argv) {
- if (argc != 2) {
- printf("Usage: unwind <PID>\n");
- return 1;
- }
-
- pid_t pid = atoi(argv[1]);
- if (!Attach(pid)) {
- printf("Failed to attach to pid %d: %s\n", pid, strerror(errno));
- return 1;
- }
-
- DoUnwind(pid);
-
- ptrace(PTRACE_DETACH, pid, 0, 0);
-
- return 0;
-}
diff --git a/libunwindstack/tools/unwind_for_offline.cpp b/libunwindstack/tools/unwind_for_offline.cpp
deleted file mode 100644
index c44a121..0000000
--- a/libunwindstack/tools/unwind_for_offline.cpp
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#define _GNU_SOURCE 1
-#include <errno.h>
-#include <inttypes.h>
-#include <signal.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/ptrace.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <algorithm>
-#include <memory>
-#include <string>
-#include <unordered_map>
-#include <utility>
-#include <vector>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/JitDebug.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/Regs.h>
-#include <unwindstack/Unwinder.h>
-
-#include <android-base/stringprintf.h>
-
-struct map_info_t {
- uint64_t start;
- uint64_t end;
- uint64_t offset;
- uint64_t flags;
- std::string name;
-};
-
-static bool Attach(pid_t pid) {
- if (ptrace(PTRACE_SEIZE, pid, 0, 0) == -1) {
- return false;
- }
-
- if (ptrace(PTRACE_INTERRUPT, pid, 0, 0) == -1) {
- ptrace(PTRACE_DETACH, pid, 0, 0);
- return false;
- }
-
- // Allow at least 1 second to attach properly.
- for (size_t i = 0; i < 1000; i++) {
- siginfo_t si;
- if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
- return true;
- }
- usleep(1000);
- }
- printf("%d: Failed to stop.\n", pid);
- return false;
-}
-
-bool SaveRegs(unwindstack::Regs* regs) {
- std::unique_ptr<FILE, decltype(&fclose)> fp(fopen("regs.txt", "w+"), &fclose);
- if (fp == nullptr) {
- perror("Failed to create file regs.txt");
- return false;
- }
- regs->IterateRegisters([&fp](const char* name, uint64_t value) {
- fprintf(fp.get(), "%s: %" PRIx64 "\n", name, value);
- });
-
- return true;
-}
-
-bool SaveStack(pid_t pid, const std::vector<std::pair<uint64_t, uint64_t>>& stacks) {
- for (size_t i = 0; i < stacks.size(); i++) {
- std::string file_name;
- if (stacks.size() != 1) {
- file_name = "stack" + std::to_string(i) + ".data";
- } else {
- file_name = "stack.data";
- }
-
- // Do this first, so if it fails, we don't create the file.
- uint64_t sp_start = stacks[i].first;
- uint64_t sp_end = stacks[i].second;
- std::vector<uint8_t> buffer(sp_end - sp_start);
- auto process_memory = unwindstack::Memory::CreateProcessMemory(pid);
- if (!process_memory->Read(sp_start, buffer.data(), buffer.size())) {
- printf("Unable to read stack data.\n");
- return false;
- }
-
- printf("Saving the stack 0x%" PRIx64 "-0x%" PRIx64 "\n", sp_start, sp_end);
-
- std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(file_name.c_str(), "w+"), &fclose);
- if (fp == nullptr) {
- perror("Failed to create stack.data");
- return false;
- }
-
- size_t bytes = fwrite(&sp_start, 1, sizeof(sp_start), fp.get());
- if (bytes != sizeof(sp_start)) {
- printf("Failed to write sp_start data: sizeof(sp_start) %zu, written %zu\n", sizeof(sp_start),
- bytes);
- return false;
- }
-
- bytes = fwrite(buffer.data(), 1, buffer.size(), fp.get());
- if (bytes != buffer.size()) {
- printf("Failed to write all stack data: stack size %zu, written %zu\n", buffer.size(), bytes);
- return false;
- }
- }
-
- return true;
-}
-
-bool CreateElfFromMemory(std::shared_ptr<unwindstack::Memory>& memory, map_info_t* info) {
- std::string cur_name;
- if (info->name.empty()) {
- cur_name = android::base::StringPrintf("anonymous_%" PRIx64, info->start);
- } else {
- cur_name = android::base::StringPrintf("%s_%" PRIx64, basename(info->name.c_str()), info->start);
- }
-
- std::vector<uint8_t> buffer(info->end - info->start);
- // If this is a mapped in file, it might not be possible to read the entire
- // map, so read all that is readable.
- size_t bytes = memory->Read(info->start, buffer.data(), buffer.size());
- if (bytes == 0) {
- printf("Cannot read data from address %" PRIx64 " length %zu\n", info->start, buffer.size());
- return false;
- }
-
- std::unique_ptr<FILE, decltype(&fclose)> output(fopen(cur_name.c_str(), "w+"), &fclose);
- if (output == nullptr) {
- perror((std::string("Cannot create ") + cur_name).c_str());
- return false;
- }
-
- size_t bytes_written = fwrite(buffer.data(), 1, bytes, output.get());
- if (bytes_written != bytes) {
- printf("Failed to write all data to file: bytes read %zu, written %zu\n", bytes, bytes_written);
- return false;
- }
-
- // Replace the name with the new name.
- info->name = cur_name;
-
- return true;
-}
-
-bool CopyElfFromFile(map_info_t* info, bool* file_copied) {
- std::string cur_name = basename(info->name.c_str());
- if (*file_copied) {
- info->name = cur_name;
- return true;
- }
-
- std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(info->name.c_str(), "r"), &fclose);
- if (fp == nullptr) {
- perror((std::string("Cannot open ") + info->name).c_str());
- return false;
- }
-
- std::unique_ptr<FILE, decltype(&fclose)> output(fopen(cur_name.c_str(), "w+"), &fclose);
- if (output == nullptr) {
- perror((std::string("Cannot create file " + cur_name)).c_str());
- return false;
- }
- std::vector<uint8_t> buffer(10000);
- size_t bytes;
- while ((bytes = fread(buffer.data(), 1, buffer.size(), fp.get())) > 0) {
- size_t bytes_written = fwrite(buffer.data(), 1, bytes, output.get());
- if (bytes_written != bytes) {
- printf("Bytes written doesn't match bytes read: read %zu, written %zu\n", bytes,
- bytes_written);
- return false;
- }
- }
-
- // Replace the name with the new name.
- info->name = cur_name;
-
- return true;
-}
-
-map_info_t* FillInAndGetMapInfo(std::unordered_map<uint64_t, map_info_t>& maps_by_start,
- unwindstack::MapInfo* map_info) {
- auto info = &maps_by_start[map_info->start];
- info->start = map_info->start;
- info->end = map_info->end;
- info->offset = map_info->offset;
- info->name = map_info->name;
- info->flags = map_info->flags;
-
- return info;
-}
-
-void SaveMapInformation(std::shared_ptr<unwindstack::Memory>& process_memory, map_info_t* info,
- bool* file_copied) {
- if (CopyElfFromFile(info, file_copied)) {
- return;
- }
- *file_copied = false;
-
- // Try to create the elf from memory, this will handle cases where
- // the data only exists in memory such as vdso data on x86.
- if (CreateElfFromMemory(process_memory, info)) {
- return;
- }
-
- printf("Cannot save memory or file for map ");
- if (!info->name.empty()) {
- printf("%s\n", info->name.c_str());
- } else {
- printf("anonymous:%" PRIx64 "\n", info->start);
- }
-}
-
-int SaveData(pid_t pid) {
- unwindstack::Regs* regs = unwindstack::Regs::RemoteGet(pid);
- if (regs == nullptr) {
- printf("Unable to get remote reg data.\n");
- return 1;
- }
-
- // Save the current state of the registers.
- if (!SaveRegs(regs)) {
- return 1;
- }
-
- // Do an unwind so we know how much of the stack to save, and what
- // elf files are involved.
- unwindstack::UnwinderFromPid unwinder(1024, pid);
- unwinder.SetRegs(regs);
- uint64_t sp = regs->sp();
- unwinder.Unwind();
-
- std::unordered_map<uint64_t, map_info_t> maps_by_start;
- std::vector<std::pair<uint64_t, uint64_t>> stacks;
- unwindstack::Maps* maps = unwinder.GetMaps();
- uint64_t sp_map_start = 0;
- unwindstack::MapInfo* map_info = maps->Find(sp);
- if (map_info != nullptr) {
- stacks.emplace_back(std::make_pair(sp, map_info->end));
- sp_map_start = map_info->start;
- }
-
- for (const auto& frame : unwinder.frames()) {
- map_info = maps->Find(frame.sp);
- if (map_info != nullptr && sp_map_start != map_info->start) {
- stacks.emplace_back(std::make_pair(frame.sp, map_info->end));
- sp_map_start = map_info->start;
- }
-
- if (maps_by_start.count(frame.map_start) == 0) {
- map_info = maps->Find(frame.map_start);
- if (map_info == nullptr) {
- continue;
- }
-
- auto info = FillInAndGetMapInfo(maps_by_start, map_info);
- bool file_copied = false;
- SaveMapInformation(unwinder.GetProcessMemory(), info, &file_copied);
-
- // If you are using a a linker that creates two maps (one read-only, one
- // read-executable), it's necessary to capture the previous map
- // information if needed.
- unwindstack::MapInfo* prev_map = map_info->prev_map;
- if (prev_map != nullptr && map_info->offset != 0 && prev_map->offset == 0 &&
- prev_map->flags == PROT_READ && map_info->name == prev_map->name &&
- maps_by_start.count(prev_map->start) == 0) {
- info = FillInAndGetMapInfo(maps_by_start, prev_map);
- SaveMapInformation(unwinder.GetProcessMemory(), info, &file_copied);
- }
- }
- }
-
- for (size_t i = 0; i < unwinder.NumFrames(); i++) {
- printf("%s\n", unwinder.FormatFrame(i).c_str());
- }
-
- if (!SaveStack(pid, stacks)) {
- return 1;
- }
-
- std::vector<std::pair<uint64_t, map_info_t>> sorted_maps(maps_by_start.begin(),
- maps_by_start.end());
- std::sort(sorted_maps.begin(), sorted_maps.end(),
- [](auto& a, auto& b) { return a.first < b.first; });
-
- std::unique_ptr<FILE, decltype(&fclose)> fp(fopen("maps.txt", "w+"), &fclose);
- if (fp == nullptr) {
- perror("Failed to create maps.txt");
- return false;
- }
-
- for (auto& element : sorted_maps) {
- char perms[5] = {"---p"};
- map_info_t& map = element.second;
- if (map.flags & PROT_READ) {
- perms[0] = 'r';
- }
- if (map.flags & PROT_WRITE) {
- perms[1] = 'w';
- }
- if (map.flags & PROT_EXEC) {
- perms[2] = 'x';
- }
- fprintf(fp.get(), "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " 00:00 0", map.start, map.end, perms,
- map.offset);
- if (!map.name.empty()) {
- fprintf(fp.get(), " %s", map.name.c_str());
- }
- fprintf(fp.get(), "\n");
- }
-
- return 0;
-}
-
-int main(int argc, char** argv) {
- if (argc != 2) {
- printf("Usage: unwind_for_offline <PID>\n");
- return 1;
- }
-
- pid_t pid = atoi(argv[1]);
- if (!Attach(pid)) {
- printf("Failed to attach to pid %d: %s\n", pid, strerror(errno));
- return 1;
- }
-
- int return_code = SaveData(pid);
-
- ptrace(PTRACE_DETACH, pid, 0, 0);
-
- return return_code;
-}
diff --git a/libunwindstack/tools/unwind_info.cpp b/libunwindstack/tools/unwind_info.cpp
deleted file mode 100644
index a5002f2..0000000
--- a/libunwindstack/tools/unwind_info.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (C) 2016 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 <elf.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <unwindstack/DwarfSection.h>
-#include <unwindstack/DwarfStructs.h>
-#include <unwindstack/Elf.h>
-#include <unwindstack/ElfInterface.h>
-#include <unwindstack/Log.h>
-#include <unwindstack/Memory.h>
-
-#include "ArmExidx.h"
-#include "ElfInterfaceArm.h"
-
-namespace unwindstack {
-
-void DumpArm(Elf* elf, ElfInterfaceArm* interface) {
- if (interface == nullptr) {
- printf("No ARM Unwind Information.\n\n");
- return;
- }
-
- printf("ARM Unwind Information:\n");
- uint64_t load_bias = elf->GetLoadBias();
- for (const auto& entry : interface->pt_loads()) {
- printf(" PC Range 0x%" PRIx64 " - 0x%" PRIx64 "\n", entry.second.offset + load_bias,
- entry.second.offset + entry.second.table_size + load_bias);
- for (auto pc : *interface) {
- std::string name;
- printf(" PC 0x%" PRIx64, pc + load_bias);
- uint64_t func_offset;
- if (elf->GetFunctionName(pc + load_bias, &name, &func_offset) && !name.empty()) {
- printf(" <%s>", name.c_str());
- }
- printf("\n");
- uint64_t entry;
- if (!interface->FindEntry(pc, &entry)) {
- printf(" Cannot find entry for address.\n");
- continue;
- }
- ArmExidx arm(nullptr, interface->memory(), nullptr);
- arm.set_log(ARM_LOG_FULL);
- arm.set_log_skip_execution(true);
- arm.set_log_indent(2);
- if (!arm.ExtractEntryData(entry)) {
- if (arm.status() != ARM_STATUS_NO_UNWIND) {
- printf(" Error trying to extract data.\n");
- }
- continue;
- }
- if (arm.data()->size() > 0) {
- if (!arm.Eval() && arm.status() != ARM_STATUS_NO_UNWIND) {
- printf(" Error trying to evaluate dwarf data.\n");
- }
- }
- }
- }
- printf("\n");
-}
-
-void DumpDwarfSection(Elf* elf, DwarfSection* section, uint64_t) {
- for (const DwarfFde* fde : *section) {
- // Sometimes there are entries that have empty length, skip those since
- // they don't contain any interesting information.
- if (fde == nullptr || fde->pc_start == fde->pc_end) {
- continue;
- }
- printf("\n PC 0x%" PRIx64 "-0x%" PRIx64, fde->pc_start, fde->pc_end);
- std::string name;
- uint64_t func_offset;
- if (elf->GetFunctionName(fde->pc_start, &name, &func_offset) && !name.empty()) {
- printf(" <%s>", name.c_str());
- }
- printf("\n");
- if (!section->Log(2, UINT64_MAX, fde, elf->arch())) {
- printf("Failed to process cfa information for entry at 0x%" PRIx64 "\n", fde->pc_start);
- }
- }
-}
-
-int GetElfInfo(const char* file, uint64_t offset) {
- // Send all log messages to stdout.
- log_to_stdout(true);
-
- Elf elf(Memory::CreateFileMemory(file, offset).release());
- if (!elf.Init() || !elf.valid()) {
- printf("%s is not a valid elf file.\n", file);
- return 1;
- }
-
- std::string soname(elf.GetSoname());
- if (!soname.empty()) {
- printf("Soname: %s\n", soname.c_str());
- }
-
- std::string build_id = elf.GetBuildID();
- if (!build_id.empty()) {
- printf("Build ID: ");
- for (size_t i = 0; i < build_id.size(); ++i) {
- printf("%02hhx", build_id[i]);
- }
- printf("\n");
- }
-
- ElfInterface* interface = elf.interface();
- if (elf.machine_type() == EM_ARM) {
- DumpArm(&elf, reinterpret_cast<ElfInterfaceArm*>(interface));
- printf("\n");
- }
-
- if (interface->eh_frame() != nullptr) {
- printf("eh_frame information:\n");
- DumpDwarfSection(&elf, interface->eh_frame(), elf.GetLoadBias());
- printf("\n");
- } else {
- printf("\nno eh_frame information\n");
- }
-
- if (interface->debug_frame() != nullptr) {
- printf("\ndebug_frame information:\n");
- DumpDwarfSection(&elf, interface->debug_frame(), elf.GetLoadBias());
- printf("\n");
- } else {
- printf("\nno debug_frame information\n");
- }
-
- // If there is a gnu_debugdata interface, dump the information for that.
- ElfInterface* gnu_debugdata_interface = elf.gnu_debugdata_interface();
- if (gnu_debugdata_interface != nullptr) {
- if (gnu_debugdata_interface->eh_frame() != nullptr) {
- printf("\ngnu_debugdata (eh_frame):\n");
- DumpDwarfSection(&elf, gnu_debugdata_interface->eh_frame(), 0);
- printf("\n");
- }
- if (gnu_debugdata_interface->debug_frame() != nullptr) {
- printf("\ngnu_debugdata (debug_frame):\n");
- DumpDwarfSection(&elf, gnu_debugdata_interface->debug_frame(), 0);
- printf("\n");
- }
- } else {
- printf("\nno valid gnu_debugdata information\n");
- }
-
- return 0;
-}
-
-} // namespace unwindstack
-
-int main(int argc, char** argv) {
- if (argc != 2 && argc != 3) {
- printf("Usage: unwind_info ELF_FILE [OFFSET]\n");
- printf(" ELF_FILE\n");
- printf(" The path to an elf file.\n");
- printf(" OFFSET\n");
- printf(" Use the offset into the ELF file as the beginning of the elf.\n");
- return 1;
- }
-
- struct stat st;
- if (stat(argv[1], &st) == -1) {
- printf("Cannot stat %s: %s\n", argv[1], strerror(errno));
- return 1;
- }
- if (!S_ISREG(st.st_mode)) {
- printf("%s is not a regular file.\n", argv[1]);
- return 1;
- }
-
- uint64_t offset = 0;
- if (argc == 3) {
- char* end;
- offset = strtoull(argv[2], &end, 16);
- if (*end != '\0') {
- printf("Malformed OFFSET value: %s\n", argv[2]);
- return 1;
- }
- }
-
- return unwindstack::GetElfInfo(argv[1], offset);
-}
diff --git a/libunwindstack/tools/unwind_reg_info.cpp b/libunwindstack/tools/unwind_reg_info.cpp
deleted file mode 100644
index 68e0273..0000000
--- a/libunwindstack/tools/unwind_reg_info.cpp
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright (C) 2018 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 <elf.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <unwindstack/DwarfLocation.h>
-#include <unwindstack/DwarfMemory.h>
-#include <unwindstack/DwarfSection.h>
-#include <unwindstack/DwarfStructs.h>
-#include <unwindstack/Elf.h>
-#include <unwindstack/ElfInterface.h>
-#include <unwindstack/Log.h>
-#include <unwindstack/Memory.h>
-
-#include "ArmExidx.h"
-#include "DwarfOp.h"
-#include "ElfInterfaceArm.h"
-
-namespace unwindstack {
-
-void PrintSignedValue(int64_t value) {
- if (value < 0) {
- printf("- %" PRId64, -value);
- } else if (value > 0) {
- printf("+ %" PRId64, value);
- }
-}
-
-void PrintExpression(Memory* memory, uint8_t class_type, uint64_t end, uint64_t length) {
- std::vector<std::string> lines;
- DwarfMemory dwarf_memory(memory);
- if (class_type == ELFCLASS32) {
- DwarfOp<uint32_t> op(&dwarf_memory, nullptr);
- op.GetLogInfo(end - length, end, &lines);
- } else {
- DwarfOp<uint64_t> op(&dwarf_memory, nullptr);
- op.GetLogInfo(end - length, end, &lines);
- }
- for (auto& line : lines) {
- printf(" %s\n", line.c_str());
- }
-}
-
-void PrintRegInformation(DwarfSection* section, Memory* memory, uint64_t pc, uint8_t class_type,
- ArchEnum arch) {
- const DwarfFde* fde = section->GetFdeFromPc(pc);
- if (fde == nullptr) {
- printf(" No fde found.\n");
- return;
- }
-
- dwarf_loc_regs_t regs;
- if (!section->GetCfaLocationInfo(pc, fde, ®s, arch)) {
- printf(" Cannot get location information.\n");
- return;
- }
-
- std::vector<std::pair<uint32_t, DwarfLocation>> loc_regs;
- for (auto& loc : regs) {
- loc_regs.push_back(loc);
- }
- std::sort(loc_regs.begin(), loc_regs.end(), [](auto a, auto b) {
- if (a.first == CFA_REG) {
- return true;
- } else if (b.first == CFA_REG) {
- return false;
- }
- return a.first < b.first;
- });
-
- for (auto& entry : loc_regs) {
- const DwarfLocation* loc = &entry.second;
- if (entry.first == CFA_REG) {
- printf(" cfa = ");
- } else {
- printf(" r%d = ", entry.first);
- }
- switch (loc->type) {
- case DWARF_LOCATION_OFFSET:
- printf("[cfa ");
- PrintSignedValue(loc->values[0]);
- printf("]\n");
- break;
-
- case DWARF_LOCATION_VAL_OFFSET:
- printf("cfa ");
- PrintSignedValue(loc->values[0]);
- printf("\n");
- break;
-
- case DWARF_LOCATION_REGISTER:
- printf("r%" PRId64 " ", loc->values[0]);
- PrintSignedValue(loc->values[1]);
- printf("\n");
- break;
-
- case DWARF_LOCATION_EXPRESSION: {
- printf("EXPRESSION\n");
- PrintExpression(memory, class_type, loc->values[1], loc->values[0]);
- break;
- }
-
- case DWARF_LOCATION_VAL_EXPRESSION: {
- printf("VAL EXPRESSION\n");
- PrintExpression(memory, class_type, loc->values[1], loc->values[0]);
- break;
- }
-
- case DWARF_LOCATION_PSEUDO_REGISTER: {
- printf("%" PRId64 " (pseudo)\n", loc->values[0]);
- break;
- }
-
- case DWARF_LOCATION_UNDEFINED:
- printf("undefine\n");
- break;
-
- case DWARF_LOCATION_INVALID:
- printf("INVALID\n");
- break;
- }
- }
-}
-
-void PrintArmRegInformation(ElfInterfaceArm* interface, uint64_t pc) {
- printf("\nArm exidx:\n");
- uint64_t entry_offset;
- if (!interface->FindEntry(pc, &entry_offset)) {
- return;
- }
-
- ArmExidx arm(nullptr, interface->memory(), nullptr);
-
- log_to_stdout(true);
- arm.set_log(ARM_LOG_BY_REG);
- arm.set_log_skip_execution(true);
- arm.set_log_indent(1);
- if (!arm.ExtractEntryData(entry_offset)) {
- if (arm.status() != ARM_STATUS_NO_UNWIND) {
- printf(" Error trying to extract data.\n");
- }
- return;
- }
- if (arm.data()->size() != 0 && arm.Eval()) {
- arm.LogByReg();
- } else {
- printf(" Error tring to evaluate exidx data.\n");
- }
-}
-
-int GetInfo(const char* file, uint64_t offset, uint64_t pc) {
- Elf elf(Memory::CreateFileMemory(file, offset).release());
- if (!elf.Init() || !elf.valid()) {
- printf("%s is not a valid elf file.\n", file);
- return 1;
- }
-
- ElfInterface* interface = elf.interface();
- uint64_t load_bias = elf.GetLoadBias();
- if (pc < load_bias) {
- printf("PC is less than load bias.\n");
- return 1;
- }
-
- std::string soname(elf.GetSoname());
- if (!soname.empty()) {
- printf("Soname: %s\n\n", soname.c_str());
- }
-
- printf("PC 0x%" PRIx64, pc);
- std::string function_name;
- uint64_t function_offset;
- if (elf.GetFunctionName(pc, &function_name, &function_offset)) {
- printf(" (%s)", function_name.c_str());
- }
- printf(":\n");
-
- if (elf.machine_type() == EM_ARM) {
- PrintArmRegInformation(reinterpret_cast<ElfInterfaceArm*>(interface), pc - load_bias);
- }
-
- DwarfSection* section = interface->eh_frame();
- if (section != nullptr) {
- printf("\neh_frame:\n");
- PrintRegInformation(section, elf.memory(), pc, elf.class_type(), elf.arch());
- } else {
- printf("\nno eh_frame information\n");
- }
-
- section = interface->debug_frame();
- if (section != nullptr) {
- printf("\ndebug_frame:\n");
- PrintRegInformation(section, elf.memory(), pc, elf.class_type(), elf.arch());
- printf("\n");
- } else {
- printf("\nno debug_frame information\n");
- }
-
- // If there is a gnu_debugdata interface, dump the information for that.
- ElfInterface* gnu_debugdata_interface = elf.gnu_debugdata_interface();
- if (gnu_debugdata_interface != nullptr) {
- section = gnu_debugdata_interface->eh_frame();
- if (section != nullptr) {
- printf("\ngnu_debugdata (eh_frame):\n");
- PrintRegInformation(section, gnu_debugdata_interface->memory(), pc, elf.class_type(),
- elf.arch());
- printf("\n");
- } else {
- printf("\nno gnu_debugdata (eh_frame)\n");
- }
-
- section = gnu_debugdata_interface->debug_frame();
- if (section != nullptr) {
- printf("\ngnu_debugdata (debug_frame):\n");
- PrintRegInformation(section, gnu_debugdata_interface->memory(), pc, elf.class_type(),
- elf.arch());
- printf("\n");
- } else {
- printf("\nno gnu_debugdata (debug_frame)\n");
- }
- } else {
- printf("\nno valid gnu_debugdata information\n");
- }
-
- return 0;
-}
-
-} // namespace unwindstack
-
-int main(int argc, char** argv) {
- if (argc != 3 && argc != 4) {
- printf("Usage: unwind_reg_info ELF_FILE PC [OFFSET]\n");
- printf(" ELF_FILE\n");
- printf(" The path to an elf file.\n");
- printf(" PC\n");
- printf(" The pc for which the register information should be obtained.\n");
- printf(" OFFSET\n");
- printf(" Use the offset into the ELF file as the beginning of the elf.\n");
- return 1;
- }
-
- struct stat st;
- if (stat(argv[1], &st) == -1) {
- printf("Cannot stat %s: %s\n", argv[1], strerror(errno));
- return 1;
- }
- if (!S_ISREG(st.st_mode)) {
- printf("%s is not a regular file.\n", argv[1]);
- return 1;
- }
-
- uint64_t pc = 0;
- char* end;
- pc = strtoull(argv[2], &end, 16);
- if (*end != '\0') {
- printf("Malformed OFFSET value: %s\n", argv[2]);
- return 1;
- }
-
- uint64_t offset = 0;
- if (argc == 4) {
- char* end;
- offset = strtoull(argv[3], &end, 16);
- if (*end != '\0') {
- printf("Malformed OFFSET value: %s\n", argv[3]);
- return 1;
- }
- }
-
- return unwindstack::GetInfo(argv[1], offset, pc);
-}
diff --git a/libunwindstack/tools/unwind_symbols.cpp b/libunwindstack/tools/unwind_symbols.cpp
deleted file mode 100644
index 8df2284..0000000
--- a/libunwindstack/tools/unwind_symbols.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2016 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 <elf.h>
-#include <errno.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/Log.h>
-#include <unwindstack/Memory.h>
-
-int main(int argc, char** argv) {
- if (argc != 2 && argc != 3) {
- printf("Usage: unwind_symbols <ELF_FILE> [<FUNC_ADDRESS>]\n");
- printf(" Dump all function symbols in ELF_FILE. If FUNC_ADDRESS is\n");
- printf(" specified, then get the function at that address.\n");
- printf(" FUNC_ADDRESS must be a hex number.\n");
- return 1;
- }
-
- struct stat st;
- if (stat(argv[1], &st) == -1) {
- printf("Cannot stat %s: %s\n", argv[1], strerror(errno));
- return 1;
- }
- if (!S_ISREG(st.st_mode)) {
- printf("%s is not a regular file.\n", argv[1]);
- return 1;
- }
-
- uint64_t func_addr;
- if (argc == 3) {
- char* name;
- func_addr = strtoull(argv[2], &name, 16);
- if (*name != '\0') {
- printf("%s is not a hex number.\n", argv[2]);
- return 1;
- }
- }
-
- // Send all log messages to stdout.
- unwindstack::log_to_stdout(true);
-
- unwindstack::Elf elf(unwindstack::Memory::CreateFileMemory(argv[1], 0).release());
- if (!elf.Init() || !elf.valid()) {
- printf("%s is not a valid elf file.\n", argv[1]);
- return 1;
- }
-
- std::string soname(elf.GetSoname());
- if (!soname.empty()) {
- printf("Soname: %s\n\n", soname.c_str());
- }
-
- switch (elf.machine_type()) {
- case EM_ARM:
- printf("ABI: arm\n");
- break;
- case EM_AARCH64:
- printf("ABI: arm64\n");
- break;
- case EM_386:
- printf("ABI: x86\n");
- break;
- case EM_X86_64:
- printf("ABI: x86_64\n");
- break;
- default:
- printf("ABI: unknown\n");
- return 1;
- }
-
- std::string name;
- if (argc == 3) {
- std::string cur_name;
- uint64_t func_offset;
- if (!elf.GetFunctionName(func_addr, &cur_name, &func_offset)) {
- printf("No known function at 0x%" PRIx64 "\n", func_addr);
- return 1;
- }
- printf("<0x%" PRIx64 ">", func_addr - func_offset);
- if (func_offset != 0) {
- printf("+%" PRId64, func_offset);
- }
- printf(": %s\n", cur_name.c_str());
- return 0;
- }
-
- // This is a crude way to get the symbols in order.
- for (const auto& entry : elf.interface()->pt_loads()) {
- uint64_t start = entry.second.offset;
- uint64_t end = entry.second.table_size;
- for (uint64_t addr = start; addr < end; addr += 4) {
- std::string cur_name;
- uint64_t func_offset;
- if (elf.GetFunctionName(addr, &cur_name, &func_offset)) {
- if (cur_name != name) {
- printf("<0x%" PRIx64 "> Function: %s\n", addr - func_offset, cur_name.c_str());
- }
- name = cur_name;
- }
- }
- }
-
- return 0;
-}
diff --git a/logcat b/logcat
deleted file mode 120000
index 6c27286..0000000
--- a/logcat
+++ /dev/null
@@ -1 +0,0 @@
-../logging/logcat
\ No newline at end of file
diff --git a/logd b/logd
deleted file mode 120000
index bb2232f..0000000
--- a/logd
+++ /dev/null
@@ -1 +0,0 @@
-../logging/logd
\ No newline at end of file
diff --git a/logwrapper b/logwrapper
deleted file mode 120000
index a65ffdf..0000000
--- a/logwrapper
+++ /dev/null
@@ -1 +0,0 @@
-../logging/logwrapper
\ No newline at end of file
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 77fa94e..2bceb75 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -78,7 +78,7 @@
# create some directories (some are mount points) and symlinks
LOCAL_POST_INSTALL_CMD := mkdir -p $(addprefix $(TARGET_ROOT_OUT)/, \
dev proc sys system data data_mirror odm oem acct config storage mnt apex debug_ramdisk \
- linkerconfig $(BOARD_ROOT_EXTRA_FOLDERS)); \
+ linkerconfig second_stage_resources $(BOARD_ROOT_EXTRA_FOLDERS)); \
ln -sf /system/bin $(TARGET_ROOT_OUT)/bin; \
ln -sf /system/etc $(TARGET_ROOT_OUT)/etc; \
ln -sf /data/user_de/0/com.android.shell/files/bugreports $(TARGET_ROOT_OUT)/bugreports; \
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 6e6aa1f..3146f36 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -561,6 +561,11 @@
# Make sure that apexd is started in the default namespace
enter_default_mount_ns
+ mkdir /data/vendor 0771 root root encryption=Require
+ mkdir /data/vendor_ce 0771 root root encryption=None
+ mkdir /data/vendor_de 0771 root root encryption=None
+ mkdir /data/vendor/hardware 0771 root root
+
# Start tombstoned early to be able to store tombstones.
mkdir /data/tombstones 0771 system system encryption=Require
mkdir /data/vendor/tombstones 0771 root root
@@ -601,6 +606,8 @@
chown bluetooth bluetooth /data/misc/bluedroid/bt_config.conf
mkdir /data/misc/bluetooth 0770 bluetooth bluetooth
mkdir /data/misc/bluetooth/logs 0770 bluetooth bluetooth
+ mkdir /data/misc/nfc 0770 nfc nfc
+ mkdir /data/misc/nfc/logs 0770 nfc nfc
mkdir /data/misc/credstore 0700 credstore credstore
mkdir /data/misc/keystore 0700 keystore keystore
mkdir /data/misc/gatekeeper 0700 system system
@@ -651,11 +658,6 @@
mkdir /data/preloads 0775 system system encryption=None
- mkdir /data/vendor 0771 root root encryption=Require
- mkdir /data/vendor_ce 0771 root root encryption=None
- mkdir /data/vendor_de 0771 root root encryption=None
- mkdir /data/vendor/hardware 0771 root root
-
# For security reasons, /data/local/tmp should always be empty.
# Do not place files or directories in /data/local/tmp
mkdir /data/local/tmp 0771 shell shell