Merge changes Iea270320,Ib9063185
* changes:
init: allow properties to be used for the keycodes option
init: use rvalues references for callees of ParseLineSection()
diff --git a/adb/Android.bp b/adb/Android.bp
index 2a88de5..9f16c40 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -41,7 +41,10 @@
target: {
android: {
- cflags: ["-DADB_HOST=0"],
+ cflags: [
+ "-DADB_HOST=0",
+ "-Wthread-safety",
+ ],
},
host: {
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index 35017f0..437720e 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -186,6 +186,48 @@
return line;
}
+std::string dump_header(const amessage* msg) {
+ unsigned command = msg->command;
+ int len = msg->data_length;
+ char cmd[9];
+ char arg0[12], arg1[12];
+ int n;
+
+ for (n = 0; n < 4; n++) {
+ int b = (command >> (n * 8)) & 255;
+ if (b < 32 || b >= 127) break;
+ cmd[n] = (char)b;
+ }
+ if (n == 4) {
+ cmd[4] = 0;
+ } else {
+ // There is some non-ASCII name in the command, so dump the hexadecimal value instead
+ snprintf(cmd, sizeof cmd, "%08x", command);
+ }
+
+ if (msg->arg0 < 256U)
+ snprintf(arg0, sizeof arg0, "%d", msg->arg0);
+ else
+ snprintf(arg0, sizeof arg0, "0x%x", msg->arg0);
+
+ if (msg->arg1 < 256U)
+ snprintf(arg1, sizeof arg1, "%d", msg->arg1);
+ else
+ snprintf(arg1, sizeof arg1, "0x%x", msg->arg1);
+
+ return android::base::StringPrintf("[%s] arg0=%s arg1=%s (len=%d) ", cmd, arg0, arg1, len);
+}
+
+std::string dump_packet(const char* name, const char* func, const apacket* p) {
+ std::string result = name;
+ result += ": ";
+ result += func;
+ result += ": ";
+ result += dump_header(&p->msg);
+ result += dump_hex(p->payload.data(), p->payload.size());
+ return result;
+}
+
std::string perror_str(const char* msg) {
return android::base::StringPrintf("%s: %s", msg, strerror(errno));
}
diff --git a/adb/adb_utils.h b/adb/adb_utils.h
index f6ce8e2..ad83302 100644
--- a/adb/adb_utils.h
+++ b/adb/adb_utils.h
@@ -24,6 +24,8 @@
#include <android-base/macros.h>
+#include "adb.h"
+
int syntax_error(const char*, ...) __attribute__((__format__(__printf__, 1, 2)));
void close_stdin();
@@ -42,6 +44,8 @@
std::string escape_arg(const std::string& s);
std::string dump_hex(const void* ptr, size_t byte_count);
+std::string dump_header(const amessage* msg);
+std::string dump_packet(const char* name, const char* func, const apacket* p);
std::string perror_str(const char* msg);
diff --git a/adb/benchmark_device.py b/adb/benchmark_device.py
index 00c2315..e56ef5a 100755
--- a/adb/benchmark_device.py
+++ b/adb/benchmark_device.py
@@ -60,8 +60,6 @@
if device == None:
device = adb.get_device()
- lock_max(device)
-
remote_path = "/dev/null"
local_path = "/tmp/adb_benchmark_temp"
@@ -69,7 +67,7 @@
f.truncate(file_size_mb * 1024 * 1024)
speeds = list()
- for _ in range(0, 5):
+ for _ in range(0, 10):
begin = time.time()
device.push(local=local_path, remote=remote_path)
end = time.time()
@@ -81,15 +79,13 @@
if device == None:
device = adb.get_device()
- lock_max(device)
-
remote_path = "/data/local/tmp/adb_benchmark_temp"
local_path = "/tmp/adb_benchmark_temp"
device.shell(["dd", "if=/dev/zero", "of=" + remote_path, "bs=1m",
"count=" + str(file_size_mb)])
speeds = list()
- for _ in range(0, 5):
+ for _ in range(0, 10):
begin = time.time()
device.pull(remote=remote_path, local=local_path)
end = time.time()
@@ -101,10 +97,8 @@
if device == None:
device = adb.get_device()
- lock_max(device)
-
speeds = list()
- for _ in range(0, 5):
+ for _ in range(0, 10):
begin = time.time()
device.shell(["dd", "if=/dev/zero", "bs=1m",
"count=" + str(file_size_mb)])
@@ -114,7 +108,10 @@
analyze("shell %dMiB" % file_size_mb, speeds)
def main():
- benchmark_pull()
+ device = adb.get_device()
+ unlock(device)
+ benchmark_push(device)
+ benchmark_pull(device)
if __name__ == "__main__":
main()
diff --git a/adb/test_adb.py b/adb/test_adb.py
index 7e73818..430fc3d 100755
--- a/adb/test_adb.py
+++ b/adb/test_adb.py
@@ -31,6 +31,7 @@
import threading
import time
import unittest
+import warnings
@contextlib.contextmanager
@@ -229,6 +230,10 @@
stderr=subprocess.STDOUT)
try:
+ # We get warnings for unclosed files for the subprocess's pipes,
+ # and it's somewhat cumbersome to close them, so just ignore this.
+ warnings.simplefilter("ignore", ResourceWarning)
+
# Run the adb client and have it start the adb server.
proc = subprocess.Popen(["adb", "-P", str(port), "start-server"],
stdin=subprocess.PIPE,
diff --git a/adb/transport.cpp b/adb/transport.cpp
index cabd279..d41f9c8 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -408,42 +408,6 @@
fd_.reset();
}
-static std::string dump_packet(const char* name, const char* func, apacket* p) {
- unsigned command = p->msg.command;
- int len = p->msg.data_length;
- char cmd[9];
- char arg0[12], arg1[12];
- int n;
-
- for (n = 0; n < 4; n++) {
- int b = (command >> (n * 8)) & 255;
- if (b < 32 || b >= 127) break;
- cmd[n] = (char)b;
- }
- if (n == 4) {
- cmd[4] = 0;
- } else {
- /* There is some non-ASCII name in the command, so dump
- * the hexadecimal value instead */
- snprintf(cmd, sizeof cmd, "%08x", command);
- }
-
- if (p->msg.arg0 < 256U)
- snprintf(arg0, sizeof arg0, "%d", p->msg.arg0);
- else
- snprintf(arg0, sizeof arg0, "0x%x", p->msg.arg0);
-
- if (p->msg.arg1 < 256U)
- snprintf(arg1, sizeof arg1, "%d", p->msg.arg1);
- else
- snprintf(arg1, sizeof arg1, "0x%x", p->msg.arg1);
-
- std::string result = android::base::StringPrintf("%s: %s: [%s] arg0=%s arg1=%s (len=%d) ", name,
- func, cmd, arg0, arg1, len);
- result += dump_hex(p->payload.data(), p->payload.size());
- return result;
-}
-
void send_packet(apacket* p, atransport* t) {
p->msg.magic = p->msg.command ^ 0xffffffff;
// compute a checksum for connection/auth packets for compatibility reasons
diff --git a/fastboot/device/fastboot_device.cpp b/fastboot/device/fastboot_device.cpp
index 6cb4892..7be721a 100644
--- a/fastboot/device/fastboot_device.cpp
+++ b/fastboot/device/fastboot_device.cpp
@@ -137,7 +137,7 @@
std::string cmd_name;
if (android::base::StartsWith(command, "oem ")) {
args = {command};
- cmd_name = "oem";
+ cmd_name = FB_CMD_OEM;
} else {
args = android::base::Split(command, ":");
cmd_name = args[0];
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index e27a897..6b6e659 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -64,6 +64,7 @@
#include <ziparchive/zip_archive.h>
#include "bootimg_utils.h"
+#include "constants.h"
#include "diagnose_usb.h"
#include "fastboot_driver.h"
#include "fs.h"
@@ -1697,10 +1698,10 @@
while (!args.empty()) {
std::string command = next_arg(&args);
- if (command == "getvar") {
+ if (command == FB_CMD_GETVAR) {
std::string variable = next_arg(&args);
DisplayVarOrError(variable, variable);
- } else if (command == "erase") {
+ } else if (command == FB_CMD_ERASE) {
std::string partition = next_arg(&args);
auto erase = [&](const std::string& partition) {
std::string partition_type;
@@ -1742,7 +1743,7 @@
if (data.size() != 256) die("signature must be 256 bytes (got %zu)", data.size());
fb->Download("signature", data);
fb->RawCommand("signature", "installing signature");
- } else if (command == "reboot") {
+ } else if (command == FB_CMD_REBOOT) {
wants_reboot = true;
if (args.size() == 1) {
@@ -1762,15 +1763,15 @@
}
if (!args.empty()) syntax_error("junk after reboot command");
- } else if (command == "reboot-bootloader") {
+ } else if (command == FB_CMD_REBOOT_BOOTLOADER) {
wants_reboot_bootloader = true;
- } else if (command == "reboot-recovery") {
+ } else if (command == FB_CMD_REBOOT_RECOVERY) {
wants_reboot_recovery = true;
- } else if (command == "reboot-fastboot") {
+ } else if (command == FB_CMD_REBOOT_FASTBOOT) {
wants_reboot_fastboot = true;
- } else if (command == "continue") {
+ } else if (command == FB_CMD_CONTINUE) {
fb->Continue();
- } else if (command == "boot") {
+ } else if (command == FB_CMD_BOOT) {
std::string kernel = next_arg(&args);
std::string ramdisk;
if (!args.empty()) ramdisk = next_arg(&args);
@@ -1780,7 +1781,7 @@
auto data = LoadBootableImage(kernel, ramdisk, second_stage);
fb->Download("boot.img", data);
fb->Boot();
- } else if (command == "flash") {
+ } else if (command == FB_CMD_FLASH) {
std::string pname = next_arg(&args);
std::string fname;
@@ -1827,7 +1828,7 @@
}
do_update(filename.c_str(), slot_override, skip_secondary || slot_all);
wants_reboot = true;
- } else if (command == "set_active") {
+ } else if (command == FB_CMD_SET_ACTIVE) {
std::string slot = verify_slot(next_arg(&args), false);
fb->SetActive(slot);
} else if (command == "stage") {
@@ -1841,8 +1842,8 @@
} else if (command == "get_staged") {
std::string filename = next_arg(&args);
fb->Upload(filename);
- } else if (command == "oem") {
- do_oem_command("oem", &args);
+ } else if (command == FB_CMD_OEM) {
+ do_oem_command(FB_CMD_OEM, &args);
} else if (command == "flashing") {
if (args.empty()) {
syntax_error("missing 'flashing' command");
@@ -1854,14 +1855,14 @@
} else {
syntax_error("unknown 'flashing' command %s", args[0].c_str());
}
- } else if (command == "create-logical-partition") {
+ } else if (command == FB_CMD_CREATE_PARTITION) {
std::string partition = next_arg(&args);
std::string size = next_arg(&args);
fb->CreatePartition(partition, size);
- } else if (command == "delete-logical-partition") {
+ } else if (command == FB_CMD_DELETE_PARTITION) {
std::string partition = next_arg(&args);
fb->DeletePartition(partition);
- } else if (command == "resize-logical-partition") {
+ } else if (command == FB_CMD_RESIZE_PARTITION) {
std::string partition = next_arg(&args);
std::string size = next_arg(&args);
fb->ResizePartition(partition, size);
diff --git a/fastboot/fastboot_driver.h b/fastboot/fastboot_driver.h
index 62bbe52..af02637 100644
--- a/fastboot/fastboot_driver.h
+++ b/fastboot/fastboot_driver.h
@@ -37,15 +37,14 @@
#include <bootimg.h>
#include <inttypes.h>
#include <sparse/sparse.h>
+
+#include "constants.h"
#include "transport.h"
class Transport;
namespace fastboot {
-static constexpr int FB_COMMAND_SZ = 64;
-static constexpr int FB_RESPONSE_SZ = 64;
-
enum RetCode : int {
SUCCESS = 0,
BAD_ARG,
diff --git a/fastboot/fuzzy_fastboot/main.cpp b/fastboot/fuzzy_fastboot/main.cpp
index c02ab1c..479a06a 100644
--- a/fastboot/fuzzy_fastboot/main.cpp
+++ b/fastboot/fuzzy_fastboot/main.cpp
@@ -747,7 +747,7 @@
}
TEST_F(Fuzz, BadCommandTooLarge) {
- std::string s = RandomString(fastboot::FB_COMMAND_SZ + 1, rand_legal);
+ std::string s = RandomString(FB_COMMAND_SZ + 1, rand_legal);
EXPECT_EQ(fb->RawCommand(s), DEVICE_FAIL)
<< "Device did not respond with failure after sending length " << s.size()
<< " string of random ASCII chars";
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 4934f5a..6067a7d 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -163,7 +163,7 @@
auto candidate = fs_mgr_get_overlayfs_candidate(mount_point);
if (candidate.empty()) return "";
- return "override_creds=off,"s + kLowerdirOption + mount_point + "," + kUpperdirOption +
+ return "override_creds=off," + kLowerdirOption + mount_point + "," + kUpperdirOption +
candidate + kUpperName + ",workdir=" + candidate + kWorkName;
}
@@ -261,7 +261,7 @@
return true;
}
-bool fs_mgr_rm_all(const std::string& path, bool* change = nullptr) {
+bool fs_mgr_rm_all(const std::string& path, bool* change = nullptr, int level = 0) {
auto save_errno = errno;
std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir);
if (!dir) {
@@ -269,7 +269,11 @@
errno = save_errno;
return true;
}
- PERROR << "opendir " << path;
+ PERROR << "opendir " << path << " depth=" << level;
+ if ((errno == EPERM) && (level != 0)) {
+ errno = save_errno;
+ return true;
+ }
return false;
}
dirent* entry;
@@ -279,23 +283,25 @@
auto file = path + "/" + entry->d_name;
if (entry->d_type == DT_UNKNOWN) {
struct stat st;
+ save_errno = errno;
if (!lstat(file.c_str(), &st) && (st.st_mode & S_IFDIR)) entry->d_type = DT_DIR;
+ errno = save_errno;
}
if (entry->d_type == DT_DIR) {
- ret &= fs_mgr_rm_all(file, change);
+ ret &= fs_mgr_rm_all(file, change, level + 1);
if (!rmdir(file.c_str())) {
if (change) *change = true;
} else {
- ret = false;
- PERROR << "rmdir " << file;
+ if (errno != ENOENT) ret = false;
+ PERROR << "rmdir " << file << " depth=" << level;
}
continue;
}
if (!unlink(file.c_str())) {
if (change) *change = true;
} else {
- ret = false;
- PERROR << "rm " << file;
+ if (errno != ENOENT) ret = false;
+ PERROR << "rm " << file << " depth=" << level;
}
}
return ret;
@@ -440,10 +446,10 @@
bool* change) {
const auto top = overlay + kOverlayTopDir;
- if (!fs_mgr_access(top)) return false;
+ if (!fs_mgr_access(top)) return fs_mgr_overlayfs_teardown_scratch(overlay, change);
auto cleanup_all = mount_point.empty();
- const auto oldpath = top + (cleanup_all ? "" : ("/"s + mount_point));
+ const auto oldpath = top + (cleanup_all ? "" : ("/" + mount_point));
const auto newpath = oldpath + ".teardown";
auto ret = fs_mgr_rm_all(newpath);
auto save_errno = errno;
@@ -583,8 +589,18 @@
fsrec->fs_type = strdup(mnt_type.c_str());
fsrec->flags = MS_RELATIME;
fsrec->fs_options = strdup("");
- auto mounted = fs_mgr_do_mount_one(fsrec) == 0;
auto save_errno = errno;
+ auto mounted = fs_mgr_do_mount_one(fsrec) == 0;
+ if (!mounted) {
+ free(fsrec->fs_type);
+ if (mnt_type == "f2fs") {
+ fsrec->fs_type = strdup("ext4");
+ } else {
+ fsrec->fs_type = strdup("f2fs");
+ }
+ mounted = fs_mgr_do_mount_one(fsrec) == 0;
+ if (!mounted) save_errno = errno;
+ }
setfscreatecon(nullptr);
if (!mounted) rmdir(kScratchMountPoint.c_str());
errno = save_errno;
@@ -594,6 +610,7 @@
const std::string kMkF2fs("/system/bin/make_f2fs");
const std::string kMkExt4("/system/bin/mke2fs");
+// Only a suggestion for _first_ try during mounting
std::string fs_mgr_overlayfs_scratch_mount_type() {
if (!access(kMkF2fs.c_str(), X_OK)) return "f2fs";
if (!access(kMkExt4.c_str(), X_OK)) return "ext4";
@@ -671,7 +688,7 @@
auto ret = system((mnt_type == "f2fs")
? ((kMkF2fs + " -d1 " + scratch_device).c_str())
- : ((kMkExt4 + " -b 4096 -t ext4 -m 0 -M "s + kScratchMountPoint +
+ : ((kMkExt4 + " -b 4096 -t ext4 -m 0 -M " + kScratchMountPoint +
" -O has_journal " + scratch_device)
.c_str()));
if (ret) {
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index 03fd5f9..80257fe 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -261,15 +261,20 @@
// we store a backup copy of everything.
uint64_t reserved =
LP_METADATA_GEOMETRY_SIZE + (uint64_t(metadata_max_size) * metadata_slot_count);
- uint64_t total_reserved = reserved * 2;
+ uint64_t total_reserved = LP_PARTITION_RESERVED_BYTES + reserved * 2;
if (device_info.size < total_reserved) {
LERROR << "Attempting to create metadata on a block device that is too small.";
return false;
}
// Compute the first free sector, factoring in alignment.
- uint64_t free_area_start =
- AlignTo(total_reserved, device_info.alignment, device_info.alignment_offset);
+ uint64_t free_area_start = total_reserved;
+ if (device_info.alignment || device_info.alignment_offset) {
+ free_area_start =
+ AlignTo(free_area_start, device_info.alignment, device_info.alignment_offset);
+ } else {
+ free_area_start = AlignTo(free_area_start, device_info.logical_block_size);
+ }
uint64_t first_sector = free_area_start / LP_SECTOR_SIZE;
// There must be one logical block of free space remaining (enough for one partition).
diff --git a/fs_mgr/liblp/builder_test.cpp b/fs_mgr/liblp/builder_test.cpp
index eb65f89..f5d39a8 100644
--- a/fs_mgr/liblp/builder_test.cpp
+++ b/fs_mgr/liblp/builder_test.cpp
@@ -48,8 +48,11 @@
LinearExtent* extent = system->extents()[0]->AsLinearExtent();
ASSERT_NE(extent, nullptr);
EXPECT_EQ(extent->num_sectors(), 65536 / LP_SECTOR_SIZE);
- // The first logical sector will be (8192+1024*4)/512 = 12.
- EXPECT_EQ(extent->physical_sector(), 24);
+ // The first logical sector will be:
+ // (LP_PARTITION_RESERVED_BYTES + 4096*2 + 1024*4) / 512
+ // Or, in terms of sectors (reserved + geometry + metadata):
+ // (8 + 16 + 8) = 32
+ EXPECT_EQ(extent->physical_sector(), 32);
// Test resizing to the same size.
EXPECT_EQ(builder->ResizePartition(system, 65536), true);
@@ -78,7 +81,7 @@
extent = system->extents()[0]->AsLinearExtent();
ASSERT_NE(extent, nullptr);
EXPECT_EQ(extent->num_sectors(), 32768 / LP_SECTOR_SIZE);
- EXPECT_EQ(extent->physical_sector(), 24);
+ EXPECT_EQ(extent->physical_sector(), 32);
// Test shrinking to 0.
builder->ResizePartition(system, 0);
@@ -148,7 +151,7 @@
ASSERT_NE(builder, nullptr);
exported = builder->Export();
ASSERT_NE(exported, nullptr);
- EXPECT_EQ(exported->geometry.first_logical_sector, 150);
+ EXPECT_EQ(exported->geometry.first_logical_sector, 174);
// Test a small alignment with no alignment offset.
device_info.alignment = 11 * 1024;
@@ -202,7 +205,8 @@
// maximum size of a metadata blob. Then, we double that space since
// we store a backup copy of everything.
static constexpr uint64_t geometry = 4 * 1024;
- static constexpr uint64_t allocatable = total - (metadata * slots + geometry) * 2;
+ static constexpr uint64_t allocatable =
+ total - (metadata * slots + geometry) * 2 - LP_PARTITION_RESERVED_BYTES;
EXPECT_EQ(builder->AllocatableSpace(), allocatable);
EXPECT_EQ(builder->UsedSpace(), 0);
@@ -243,11 +247,11 @@
ASSERT_NE(system2, nullptr);
ASSERT_NE(vendor1, nullptr);
EXPECT_EQ(system1->num_sectors(), 65536 / LP_SECTOR_SIZE);
- EXPECT_EQ(system1->physical_sector(), 24);
+ EXPECT_EQ(system1->physical_sector(), 32);
EXPECT_EQ(system2->num_sectors(), 32768 / LP_SECTOR_SIZE);
- EXPECT_EQ(system2->physical_sector(), 216);
+ EXPECT_EQ(system2->physical_sector(), 224);
EXPECT_EQ(vendor1->num_sectors(), 32768 / LP_SECTOR_SIZE);
- EXPECT_EQ(vendor1->physical_sector(), 152);
+ EXPECT_EQ(vendor1->physical_sector(), 160);
EXPECT_EQ(system1->physical_sector() + system1->num_sectors(), vendor1->physical_sector());
EXPECT_EQ(vendor1->physical_sector() + vendor1->num_sectors(), system2->physical_sector());
}
@@ -293,7 +297,7 @@
EXPECT_EQ(geometry.struct_size, sizeof(geometry));
EXPECT_EQ(geometry.metadata_max_size, 1024);
EXPECT_EQ(geometry.metadata_slot_count, 2);
- EXPECT_EQ(geometry.first_logical_sector, 24);
+ EXPECT_EQ(geometry.first_logical_sector, 32);
static const size_t kMetadataSpace =
((kMetadataSize * kMetadataSlots) + LP_METADATA_GEOMETRY_SIZE) * 2;
@@ -354,9 +358,9 @@
LinearExtent* system2 = system->extents()[1]->AsLinearExtent();
LinearExtent* vendor1 = vendor->extents()[0]->AsLinearExtent();
EXPECT_EQ(system1->num_sectors(), 65536 / LP_SECTOR_SIZE);
- EXPECT_EQ(system1->physical_sector(), 24);
+ EXPECT_EQ(system1->physical_sector(), 32);
EXPECT_EQ(system2->num_sectors(), 32768 / LP_SECTOR_SIZE);
- EXPECT_EQ(system2->physical_sector(), 216);
+ EXPECT_EQ(system2->physical_sector(), 224);
EXPECT_EQ(vendor1->num_sectors(), 32768 / LP_SECTOR_SIZE);
}
@@ -381,7 +385,7 @@
EXPECT_EQ(builder, nullptr);
// No space to store metadata + geometry + one free sector.
- device_info.size += LP_METADATA_GEOMETRY_SIZE * 2;
+ device_info.size += LP_PARTITION_RESERVED_BYTES + (LP_METADATA_GEOMETRY_SIZE * 2);
builder = MetadataBuilder::New(device_info, kMetadataSize, 1);
EXPECT_EQ(builder, nullptr);
diff --git a/fs_mgr/liblp/images.cpp b/fs_mgr/liblp/images.cpp
index 8716988..dfa37fe 100644
--- a/fs_mgr/liblp/images.cpp
+++ b/fs_mgr/liblp/images.cpp
@@ -28,12 +28,17 @@
namespace fs_mgr {
std::unique_ptr<LpMetadata> ReadFromImageFile(int fd) {
- LpMetadataGeometry geometry;
- if (!ReadLogicalPartitionGeometry(fd, &geometry)) {
+ std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(LP_METADATA_GEOMETRY_SIZE);
+ if (SeekFile64(fd, 0, SEEK_SET) < 0) {
+ PERROR << __PRETTY_FUNCTION__ << " lseek failed";
return nullptr;
}
- if (SeekFile64(fd, LP_METADATA_GEOMETRY_SIZE, SEEK_SET) < 0) {
- PERROR << __PRETTY_FUNCTION__ << "lseek failed: offset " << LP_METADATA_GEOMETRY_SIZE;
+ if (!android::base::ReadFully(fd, buffer.get(), LP_METADATA_GEOMETRY_SIZE)) {
+ PERROR << __PRETTY_FUNCTION__ << " read failed";
+ return nullptr;
+ }
+ LpMetadataGeometry geometry;
+ if (!ParseGeometry(buffer.get(), &geometry)) {
return nullptr;
}
return ParseMetadata(geometry, fd);
@@ -59,7 +64,7 @@
std::unique_ptr<LpMetadata> ReadFromImageFile(const char* file) {
android::base::unique_fd fd(open(file, O_RDONLY));
if (fd < 0) {
- PERROR << __PRETTY_FUNCTION__ << "open failed: " << file;
+ PERROR << __PRETTY_FUNCTION__ << " open failed: " << file;
return nullptr;
}
return ReadFromImageFile(fd);
@@ -72,7 +77,7 @@
std::string everything = geometry + metadata;
if (!android::base::WriteFully(fd, everything.data(), everything.size())) {
- PERROR << __PRETTY_FUNCTION__ << "write " << everything.size() << " bytes failed";
+ PERROR << __PRETTY_FUNCTION__ << " write " << everything.size() << " bytes failed";
return false;
}
return true;
@@ -81,7 +86,7 @@
bool WriteToImageFile(const char* file, const LpMetadata& input) {
android::base::unique_fd fd(open(file, O_CREAT | O_RDWR | O_TRUNC, 0644));
if (fd < 0) {
- PERROR << __PRETTY_FUNCTION__ << "open failed: " << file;
+ PERROR << __PRETTY_FUNCTION__ << " open failed: " << file;
return false;
}
return WriteToImageFile(fd, input);
@@ -106,6 +111,14 @@
LERROR << "Metadata max size must be a multiple of the block size, " << block_size;
return;
}
+ if (LP_METADATA_GEOMETRY_SIZE % block_size != 0) {
+ LERROR << "Geometry size is not a multiple of the block size, " << block_size;
+ return;
+ }
+ if (LP_PARTITION_RESERVED_BYTES % block_size != 0) {
+ LERROR << "Reserved size is not a multiple of the block size, " << block_size;
+ return;
+ }
uint64_t num_blocks = metadata.geometry.block_device_size % block_size;
if (num_blocks >= UINT_MAX) {
@@ -163,6 +176,11 @@
}
bool SparseBuilder::Build() {
+ if (sparse_file_add_fill(file_.get(), 0, LP_PARTITION_RESERVED_BYTES, 0) < 0) {
+ LERROR << "Could not add initial sparse block for reserved zeroes";
+ return false;
+ }
+
std::string geometry_blob = SerializeGeometry(geometry_);
std::string metadata_blob = SerializeMetadata(metadata_);
metadata_blob.resize(geometry_.metadata_max_size);
diff --git a/fs_mgr/liblp/include/liblp/metadata_format.h b/fs_mgr/liblp/include/liblp/metadata_format.h
index 711ff95..89b219c 100644
--- a/fs_mgr/liblp/include/liblp/metadata_format.h
+++ b/fs_mgr/liblp/include/liblp/metadata_format.h
@@ -38,7 +38,7 @@
#define LP_METADATA_HEADER_MAGIC 0x414C5030
/* Current metadata version. */
-#define LP_METADATA_MAJOR_VERSION 5
+#define LP_METADATA_MAJOR_VERSION 6
#define LP_METADATA_MINOR_VERSION 0
/* Attributes for the LpMetadataPartition::attributes field.
@@ -72,6 +72,11 @@
/* Size of a sector is always 512 bytes for compatibility with the Linux kernel. */
#define LP_SECTOR_SIZE 512
+/* Amount of space reserved at the start of every super partition to avoid
+ * creating an accidental boot sector.
+ */
+#define LP_PARTITION_RESERVED_BYTES 4096
+
/* This structure is stored at block 0 in the first 4096 bytes of the
* partition, and again in the following block. It is never modified and
* describes how logical partition information can be located.
diff --git a/fs_mgr/liblp/io_test.cpp b/fs_mgr/liblp/io_test.cpp
index 92696f5..2aa41f3 100644
--- a/fs_mgr/liblp/io_test.cpp
+++ b/fs_mgr/liblp/io_test.cpp
@@ -376,6 +376,7 @@
ASSERT_NE(builder, nullptr);
ASSERT_TRUE(AddDefaultPartitions(builder.get()));
unique_ptr<LpMetadata> exported = builder->Export();
+ ASSERT_NE(exported, nullptr);
unique_fd fd(syscall(__NR_memfd_create, "image_file", 0));
ASSERT_GE(fd, 0);
diff --git a/fs_mgr/liblp/reader.cpp b/fs_mgr/liblp/reader.cpp
index 835df9b..43d8076 100644
--- a/fs_mgr/liblp/reader.cpp
+++ b/fs_mgr/liblp/reader.cpp
@@ -123,11 +123,11 @@
bool ReadPrimaryGeometry(int fd, LpMetadataGeometry* geometry) {
std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(LP_METADATA_GEOMETRY_SIZE);
if (SeekFile64(fd, GetPrimaryGeometryOffset(), SEEK_SET) < 0) {
- PERROR << __PRETTY_FUNCTION__ << "lseek failed";
+ PERROR << __PRETTY_FUNCTION__ << " lseek failed";
return false;
}
if (!android::base::ReadFully(fd, buffer.get(), LP_METADATA_GEOMETRY_SIZE)) {
- PERROR << __PRETTY_FUNCTION__ << "read " << LP_METADATA_GEOMETRY_SIZE << " bytes failed";
+ PERROR << __PRETTY_FUNCTION__ << " read " << LP_METADATA_GEOMETRY_SIZE << " bytes failed";
return false;
}
return ParseGeometry(buffer.get(), geometry);
@@ -136,11 +136,11 @@
bool ReadBackupGeometry(int fd, LpMetadataGeometry* geometry) {
std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(LP_METADATA_GEOMETRY_SIZE);
if (SeekFile64(fd, GetBackupGeometryOffset(), SEEK_SET) < 0) {
- PERROR << __PRETTY_FUNCTION__ << "lseek failed, offset " << -LP_METADATA_GEOMETRY_SIZE;
+ PERROR << __PRETTY_FUNCTION__ << " lseek failed";
return false;
}
if (!android::base::ReadFully(fd, buffer.get(), LP_METADATA_GEOMETRY_SIZE)) {
- PERROR << __PRETTY_FUNCTION__ << "backup read " << LP_METADATA_GEOMETRY_SIZE
+ PERROR << __PRETTY_FUNCTION__ << " backup read " << LP_METADATA_GEOMETRY_SIZE
<< " bytes failed";
return false;
}
@@ -223,7 +223,7 @@
// First read and validate the header.
std::unique_ptr<LpMetadata> metadata = std::make_unique<LpMetadata>();
if (!reader->ReadFully(&metadata->header, sizeof(metadata->header))) {
- PERROR << __PRETTY_FUNCTION__ << "read " << sizeof(metadata->header) << "bytes failed";
+ PERROR << __PRETTY_FUNCTION__ << " read " << sizeof(metadata->header) << "bytes failed";
return nullptr;
}
if (!ValidateMetadataHeader(metadata->header)) {
@@ -241,7 +241,7 @@
return nullptr;
}
if (!reader->ReadFully(buffer.get(), header.tables_size)) {
- PERROR << __PRETTY_FUNCTION__ << "read " << header.tables_size << "bytes failed";
+ PERROR << __PRETTY_FUNCTION__ << " read " << header.tables_size << "bytes failed";
return nullptr;
}
@@ -312,7 +312,7 @@
uint32_t slot_number) {
int64_t offset = GetPrimaryMetadataOffset(geometry, slot_number);
if (SeekFile64(fd, offset, SEEK_SET) < 0) {
- PERROR << __PRETTY_FUNCTION__ << "lseek failed: offset " << offset;
+ PERROR << __PRETTY_FUNCTION__ << " lseek failed: offset " << offset;
return nullptr;
}
return ParseMetadata(geometry, fd);
@@ -322,7 +322,7 @@
uint32_t slot_number) {
int64_t offset = GetBackupMetadataOffset(geometry, slot_number);
if (SeekFile64(fd, offset, SEEK_SET) < 0) {
- PERROR << __PRETTY_FUNCTION__ << "lseek failed: offset " << offset;
+ PERROR << __PRETTY_FUNCTION__ << " lseek failed: offset " << offset;
return nullptr;
}
return ParseMetadata(geometry, fd);
@@ -335,7 +335,7 @@
}
if (slot_number >= geometry.metadata_slot_count) {
- LERROR << __PRETTY_FUNCTION__ << "invalid metadata slot number";
+ LERROR << __PRETTY_FUNCTION__ << " invalid metadata slot number";
return nullptr;
}
@@ -350,7 +350,7 @@
std::unique_ptr<LpMetadata> ReadMetadata(const char* block_device, uint32_t slot_number) {
android::base::unique_fd fd(open(block_device, O_RDONLY));
if (fd < 0) {
- PERROR << __PRETTY_FUNCTION__ << "open failed: " << block_device;
+ PERROR << __PRETTY_FUNCTION__ << " open failed: " << block_device;
return nullptr;
}
return ReadMetadata(fd, slot_number);
diff --git a/fs_mgr/liblp/utility.cpp b/fs_mgr/liblp/utility.cpp
index 2f7692f..0556833 100644
--- a/fs_mgr/liblp/utility.cpp
+++ b/fs_mgr/liblp/utility.cpp
@@ -57,17 +57,18 @@
}
int64_t GetPrimaryGeometryOffset() {
- return 0;
+ return LP_PARTITION_RESERVED_BYTES;
}
int64_t GetBackupGeometryOffset() {
- return LP_METADATA_GEOMETRY_SIZE;
+ return GetPrimaryGeometryOffset() + LP_METADATA_GEOMETRY_SIZE;
}
int64_t GetPrimaryMetadataOffset(const LpMetadataGeometry& geometry, uint32_t slot_number) {
CHECK(slot_number < geometry.metadata_slot_count);
- int64_t offset = (LP_METADATA_GEOMETRY_SIZE * 2) + geometry.metadata_max_size * slot_number;
+ int64_t offset = LP_PARTITION_RESERVED_BYTES + (LP_METADATA_GEOMETRY_SIZE * 2) +
+ geometry.metadata_max_size * slot_number;
CHECK(offset + geometry.metadata_max_size <=
int64_t(geometry.first_logical_sector * LP_SECTOR_SIZE));
return offset;
@@ -75,7 +76,7 @@
int64_t GetBackupMetadataOffset(const LpMetadataGeometry& geometry, uint32_t slot_number) {
CHECK(slot_number < geometry.metadata_slot_count);
- int64_t start = LP_METADATA_GEOMETRY_SIZE * 2 +
+ int64_t start = LP_PARTITION_RESERVED_BYTES + (LP_METADATA_GEOMETRY_SIZE * 2) +
int64_t(geometry.metadata_max_size) * geometry.metadata_slot_count;
return start + int64_t(geometry.metadata_max_size * slot_number);
}
diff --git a/fs_mgr/liblp/utility_test.cpp b/fs_mgr/liblp/utility_test.cpp
index 46ed2e6..8baf9e7 100644
--- a/fs_mgr/liblp/utility_test.cpp
+++ b/fs_mgr/liblp/utility_test.cpp
@@ -41,13 +41,13 @@
0,
1024 * 1024,
4096};
- EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 0), 8192);
- EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 1), 8192 + 16384);
- EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 2), 8192 + 16384 * 2);
- EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 3), 8192 + 16384 * 3);
+ static const uint64_t start = LP_PARTITION_RESERVED_BYTES;
+ EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 0), start + 8192);
+ EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 1), start + 8192 + 16384);
+ EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 2), start + 8192 + 16384 * 2);
+ EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 3), start + 8192 + 16384 * 3);
- static const uint64_t backup_start = 8192 + 16384 * 4;
-
+ static const uint64_t backup_start = start + 8192 + 16384 * 4;
EXPECT_EQ(GetBackupMetadataOffset(geometry, 3), backup_start + 16384 * 3);
EXPECT_EQ(GetBackupMetadataOffset(geometry, 2), backup_start + 16384 * 2);
EXPECT_EQ(GetBackupMetadataOffset(geometry, 1), backup_start + 16384 * 1);
diff --git a/fs_mgr/liblp/writer.cpp b/fs_mgr/liblp/writer.cpp
index 5cf1a2c..f857d8c 100644
--- a/fs_mgr/liblp/writer.cpp
+++ b/fs_mgr/liblp/writer.cpp
@@ -144,11 +144,11 @@
const std::function<bool(int, const std::string&)>& writer) {
int64_t primary_offset = GetPrimaryMetadataOffset(geometry, slot_number);
if (SeekFile64(fd, primary_offset, SEEK_SET) < 0) {
- PERROR << __PRETTY_FUNCTION__ << "lseek failed: offset " << primary_offset;
+ PERROR << __PRETTY_FUNCTION__ << " lseek failed: offset " << primary_offset;
return false;
}
if (!writer(fd, blob)) {
- PERROR << __PRETTY_FUNCTION__ << "write " << blob.size() << " bytes failed";
+ PERROR << __PRETTY_FUNCTION__ << " write " << blob.size() << " bytes failed";
return false;
}
return true;
@@ -160,16 +160,16 @@
int64_t backup_offset = GetBackupMetadataOffset(geometry, slot_number);
int64_t abs_offset = SeekFile64(fd, backup_offset, SEEK_SET);
if (abs_offset == (int64_t)-1) {
- PERROR << __PRETTY_FUNCTION__ << "lseek failed: offset " << backup_offset;
+ PERROR << __PRETTY_FUNCTION__ << " lseek failed: offset " << backup_offset;
return false;
}
if (abs_offset >= int64_t(geometry.first_logical_sector) * LP_SECTOR_SIZE) {
- PERROR << __PRETTY_FUNCTION__ << "backup offset " << abs_offset
+ PERROR << __PRETTY_FUNCTION__ << " backup offset " << abs_offset
<< " is within logical partition bounds, sector " << geometry.first_logical_sector;
return false;
}
if (!writer(fd, blob)) {
- PERROR << __PRETTY_FUNCTION__ << "backup write " << blob.size() << " bytes failed";
+ PERROR << __PRETTY_FUNCTION__ << " backup write " << blob.size() << " bytes failed";
return false;
}
return true;
@@ -205,22 +205,33 @@
return false;
}
- // Write geometry to the first and last 4096 bytes of the device.
+ // Write zeroes to the first block.
+ std::string zeroes(LP_PARTITION_RESERVED_BYTES, 0);
+ if (SeekFile64(fd, 0, SEEK_SET) < 0) {
+ PERROR << __PRETTY_FUNCTION__ << " lseek failed: offset 0";
+ return false;
+ }
+ if (!android::base::WriteFully(fd, zeroes.data(), zeroes.size())) {
+ PERROR << __PRETTY_FUNCTION__ << " write " << zeroes.size() << " bytes failed";
+ return false;
+ }
+
+ // Write geometry to the primary and backup locations.
std::string blob = SerializeGeometry(metadata.geometry);
if (SeekFile64(fd, GetPrimaryGeometryOffset(), SEEK_SET) < 0) {
- PERROR << __PRETTY_FUNCTION__ << "lseek failed: offset 0";
+ PERROR << __PRETTY_FUNCTION__ << " lseek failed: primary geometry";
return false;
}
if (!android::base::WriteFully(fd, blob.data(), blob.size())) {
- PERROR << __PRETTY_FUNCTION__ << "write " << blob.size() << " bytes failed";
+ PERROR << __PRETTY_FUNCTION__ << " write " << blob.size() << " bytes failed";
return false;
}
if (SeekFile64(fd, GetBackupGeometryOffset(), SEEK_SET) < 0) {
- PERROR << __PRETTY_FUNCTION__ << "lseek failed: offset " << -LP_METADATA_GEOMETRY_SIZE;
+ PERROR << __PRETTY_FUNCTION__ << " lseek failed: backup geometry";
return false;
}
if (!android::base::WriteFully(fd, blob.data(), blob.size())) {
- PERROR << __PRETTY_FUNCTION__ << "backup write " << blob.size() << " bytes failed";
+ PERROR << __PRETTY_FUNCTION__ << " backup write " << blob.size() << " bytes failed";
return false;
}
@@ -303,7 +314,7 @@
bool FlashPartitionTable(const std::string& block_device, const LpMetadata& metadata) {
android::base::unique_fd fd(open(block_device.c_str(), O_RDWR | O_SYNC));
if (fd < 0) {
- PERROR << __PRETTY_FUNCTION__ << "open failed: " << block_device;
+ PERROR << __PRETTY_FUNCTION__ << " open failed: " << block_device;
return false;
}
if (!FlashPartitionTable(fd, metadata)) {
@@ -317,7 +328,7 @@
uint32_t slot_number) {
android::base::unique_fd fd(open(block_device.c_str(), O_RDWR | O_SYNC));
if (fd < 0) {
- PERROR << __PRETTY_FUNCTION__ << "open failed: " << block_device;
+ PERROR << __PRETTY_FUNCTION__ << " open failed: " << block_device;
return false;
}
if (!UpdatePartitionTable(fd, metadata, slot_number)) {
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 5c8b92a..6aed0a3 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -746,7 +746,7 @@
return;
}
- int fd = open(rec->blk_device, O_RDONLY);
+ int fd = open(rec->blk_device, O_RDONLY | O_CLOEXEC);
if (fd == -1) {
PLOG(ERROR) << "error opening block device " << rec->blk_device;
return;
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index 970e05c..14f82c7 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -58,6 +58,7 @@
"Elf.cpp",
"ElfInterface.cpp",
"ElfInterfaceArm.cpp",
+ "Global.cpp",
"JitDebug.cpp",
"Log.cpp",
"MapInfo.cpp",
diff --git a/libunwindstack/DexFiles.cpp b/libunwindstack/DexFiles.cpp
index 17e2526..ac55fee 100644
--- a/libunwindstack/DexFiles.cpp
+++ b/libunwindstack/DexFiles.cpp
@@ -43,10 +43,10 @@
uint64_t dex_file;
};
-DexFiles::DexFiles(std::shared_ptr<Memory>& memory) : memory_(memory) {}
+DexFiles::DexFiles(std::shared_ptr<Memory>& memory) : Global(memory) {}
DexFiles::DexFiles(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs)
- : memory_(memory), search_libs_(search_libs) {}
+ : Global(memory, search_libs) {}
DexFiles::~DexFiles() {
for (auto& entry : files_) {
@@ -117,6 +117,11 @@
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;
@@ -124,36 +129,7 @@
initialized_ = true;
entry_addr_ = 0;
- const std::string dex_debug_name("__dex_debug_descriptor");
- for (MapInfo* info : *maps) {
- if (!(info->flags & PROT_READ) || info->offset != 0) {
- continue;
- }
-
- if (!search_libs_.empty()) {
- bool found = false;
- const char* lib = basename(info->name.c_str());
- for (const std::string& name : search_libs_) {
- if (name == lib) {
- found = true;
- break;
- }
- }
- if (!found) {
- continue;
- }
- }
-
- Elf* elf = info->GetElf(memory_, true);
- uint64_t ptr;
- // Find first non-empty list (libart might be loaded multiple times).
- if (elf->GetGlobalVariable(dex_debug_name, &ptr) && ptr != 0) {
- entry_addr_ = (this->*read_entry_ptr_func_)(ptr + info->start);
- if (entry_addr_ != 0) {
- break;
- }
- }
- }
+ FindAndReadVariable(maps, "__dex_debug_descriptor");
}
DexFile* DexFiles::GetDexFile(uint64_t dex_file_offset, MapInfo* info) {
diff --git a/libunwindstack/Global.cpp b/libunwindstack/Global.cpp
new file mode 100644
index 0000000..b449c7e
--- /dev/null
+++ b/libunwindstack/Global.cpp
@@ -0,0 +1,96 @@
+/*
+ * 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 <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) {}
+
+uint64_t Global::GetVariableOffset(MapInfo* info, const std::string& variable) {
+ if (!search_libs_.empty()) {
+ bool found = false;
+ const char* lib = basename(info->name.c_str());
+ for (const std::string& name : search_libs_) {
+ if (name == lib) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ return 0;
+ }
+ }
+
+ Elf* elf = info->GetElf(memory_, true);
+ uint64_t ptr;
+ // Find first non-empty list (libraries might be loaded multiple times).
+ if (elf->GetGlobalVariable(variable, &ptr) && ptr != 0) {
+ return ptr + info->start;
+ }
+ return 0;
+}
+
+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
+ MapInfo* map_start = nullptr;
+ for (MapInfo* info : *maps) {
+ if (map_start != nullptr) {
+ if (map_start->name == info->name) {
+ if (info->offset != 0 &&
+ (info->flags & (PROT_READ | PROT_WRITE)) == (PROT_READ | PROT_WRITE)) {
+ uint64_t ptr = GetVariableOffset(map_start, variable);
+ if (ptr != 0 && ReadVariableData(ptr)) {
+ break;
+ } else {
+ // Failed to find the global variable, do not bother trying again.
+ map_start = nullptr;
+ }
+ }
+ } else {
+ map_start = nullptr;
+ }
+ }
+ if (map_start == nullptr && (info->flags & PROT_READ) && info->offset == 0 &&
+ !info->name.empty()) {
+ map_start = info;
+ }
+ }
+}
+
+} // namespace unwindstack
diff --git a/libunwindstack/JitDebug.cpp b/libunwindstack/JitDebug.cpp
index 821aacf..fe680d7 100644
--- a/libunwindstack/JitDebug.cpp
+++ b/libunwindstack/JitDebug.cpp
@@ -69,10 +69,10 @@
uint64_t first_entry;
};
-JitDebug::JitDebug(std::shared_ptr<Memory>& memory) : memory_(memory) {}
+JitDebug::JitDebug(std::shared_ptr<Memory>& memory) : Global(memory) {}
JitDebug::JitDebug(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs)
- : memory_(memory), search_libs_(search_libs) {}
+ : Global(memory, search_libs) {}
JitDebug::~JitDebug() {
for (auto* elf : elf_list_) {
@@ -165,6 +165,11 @@
}
}
+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;
@@ -172,36 +177,7 @@
// Regardless of what happens below, consider the init finished.
initialized_ = true;
- const std::string descriptor_name("__jit_debug_descriptor");
- for (MapInfo* info : *maps) {
- if (!(info->flags & PROT_READ) || info->offset != 0) {
- continue;
- }
-
- if (!search_libs_.empty()) {
- bool found = false;
- const char* lib = basename(info->name.c_str());
- for (std::string& name : search_libs_) {
- if (strcmp(name.c_str(), lib) == 0) {
- found = true;
- break;
- }
- }
- if (!found) {
- continue;
- }
- }
-
- Elf* elf = info->GetElf(memory_, true);
- uint64_t descriptor_addr;
- // Find first non-empty entry (libart might be loaded multiple times).
- if (elf->GetGlobalVariable(descriptor_name, &descriptor_addr) && descriptor_addr != 0) {
- entry_addr_ = (this->*read_descriptor_func_)(descriptor_addr + info->start);
- if (entry_addr_ != 0) {
- break;
- }
- }
- }
+ FindAndReadVariable(maps, "__jit_debug_descriptor");
}
Elf* JitDebug::GetElf(Maps* maps, uint64_t pc) {
diff --git a/libunwindstack/include/unwindstack/DexFiles.h b/libunwindstack/include/unwindstack/DexFiles.h
index 26f5d35..c2fde74 100644
--- a/libunwindstack/include/unwindstack/DexFiles.h
+++ b/libunwindstack/include/unwindstack/DexFiles.h
@@ -25,16 +25,18 @@
#include <unordered_map>
#include <vector>
+#include <unwindstack/Global.h>
+#include <unwindstack/Memory.h>
+
namespace unwindstack {
// Forward declarations.
class DexFile;
class Maps;
struct MapInfo;
-class Memory;
enum ArchEnum : uint8_t;
-class DexFiles {
+class DexFiles : public Global {
public:
explicit DexFiles(std::shared_ptr<Memory>& memory);
DexFiles(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs);
@@ -60,8 +62,7 @@
bool ReadEntry64();
- std::shared_ptr<Memory> memory_;
- std::vector<std::string> search_libs_;
+ bool ReadVariableData(uint64_t ptr_offset) override;
std::mutex lock_;
bool initialized_ = false;
diff --git a/libunwindstack/include/unwindstack/Global.h b/libunwindstack/include/unwindstack/Global.h
new file mode 100644
index 0000000..70e3ddd
--- /dev/null
+++ b/libunwindstack/include/unwindstack/Global.h
@@ -0,0 +1,54 @@
+/*
+ * 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/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;
+
+ protected:
+ uint64_t GetVariableOffset(MapInfo* info, const std::string& variable);
+ void FindAndReadVariable(Maps* maps, const char* variable);
+
+ virtual bool ReadVariableData(uint64_t offset) = 0;
+
+ 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
index 0bcd0b0..ccb473f 100644
--- a/libunwindstack/include/unwindstack/JitDebug.h
+++ b/libunwindstack/include/unwindstack/JitDebug.h
@@ -24,15 +24,17 @@
#include <string>
#include <vector>
+#include <unwindstack/Global.h>
+#include <unwindstack/Memory.h>
+
namespace unwindstack {
// Forward declarations.
class Elf;
class Maps;
-class Memory;
enum ArchEnum : uint8_t;
-class JitDebug {
+class JitDebug : public Global {
public:
explicit JitDebug(std::shared_ptr<Memory>& memory);
JitDebug(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs);
@@ -45,11 +47,9 @@
private:
void Init(Maps* maps);
- std::shared_ptr<Memory> memory_;
uint64_t entry_addr_ = 0;
bool initialized_ = false;
std::vector<Elf*> elf_list_;
- std::vector<std::string> search_libs_;
std::mutex lock_;
@@ -62,6 +62,8 @@
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;
};
} // namespace unwindstack
diff --git a/libunwindstack/tests/DexFilesTest.cpp b/libunwindstack/tests/DexFilesTest.cpp
index c6d7f33..3ac3ca6 100644
--- a/libunwindstack/tests/DexFilesTest.cpp
+++ b/libunwindstack/tests/DexFilesTest.cpp
@@ -44,15 +44,15 @@
dex_files_->SetArch(ARCH_ARM);
maps_.reset(
- new BufferMaps("1000-4000 ---s 00000000 00:00 0\n"
- "4000-6000 r--s 00000000 00:00 0\n"
- "6000-8000 -wxs 00000000 00:00 0\n"
- "a000-c000 r--p 00000000 00:00 0\n"
- "c000-f000 rw-p 00000000 00:00 0\n"
- "f000-11000 r--p 00000000 00:00 0\n"
- "100000-110000 rw-p 0000000 00:00 0\n"
- "200000-210000 rw-p 0000000 00:00 0\n"
- "300000-400000 rw-p 0000000 00:00 0\n"));
+ 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 00000000 00:00 0 /fake/elf\n"
+ "a000-c000 r--p 00000000 00:00 0 /fake/elf2\n"
+ "c000-f000 rw-p 00001000 00:00 0 /fake/elf2\n"
+ "f000-11000 r--p 00000000 00:00 0 /fake/elf3\n"
+ "100000-110000 rw-p 0001000 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"));
ASSERT_TRUE(maps_->Parse());
// Global variable in a section that is not readable.
@@ -96,8 +96,9 @@
void WriteDex(uint64_t dex_file);
static constexpr size_t kMapGlobalNonReadable = 2;
- static constexpr size_t kMapGlobalSetToZero = 4;
+ 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;
@@ -256,6 +257,9 @@
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();
@@ -271,7 +275,7 @@
MapInfo* info = maps_->Get(kMapDexFiles);
// First global variable found, but value is zero.
- WriteDescriptor32(0xc800, 0);
+ WriteDescriptor32(0xa800, 0);
WriteDescriptor32(0xf800, 0x200000);
WriteEntry32(0x200000, 0, 0, 0x300000);
@@ -286,7 +290,7 @@
dex_files_->SetArch(ARCH_ARM);
method_name = "fail";
method_offset = 0x123;
- WriteDescriptor32(0xc800, 0x100000);
+ WriteDescriptor32(0xa800, 0x100000);
dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
EXPECT_EQ("fail", method_name);
EXPECT_EQ(0x123U, method_offset);
@@ -298,7 +302,7 @@
MapInfo* info = maps_->Get(kMapDexFiles);
// First global variable found, but value is zero.
- WriteDescriptor64(0xc800, 0);
+ WriteDescriptor64(0xa800, 0);
WriteDescriptor64(0xf800, 0x200000);
WriteEntry64(0x200000, 0, 0, 0x300000);
@@ -314,7 +318,7 @@
dex_files_->SetArch(ARCH_ARM64);
method_name = "fail";
method_offset = 0x123;
- WriteDescriptor64(0xc800, 0x100000);
+ WriteDescriptor64(0xa800, 0x100000);
dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
EXPECT_EQ("fail", method_name);
EXPECT_EQ(0x123U, method_offset);
diff --git a/libunwindstack/tests/JitDebugTest.cpp b/libunwindstack/tests/JitDebugTest.cpp
index 66f0859..4598526 100644
--- a/libunwindstack/tests/JitDebugTest.cpp
+++ b/libunwindstack/tests/JitDebugTest.cpp
@@ -43,15 +43,16 @@
jit_debug_->SetArch(ARCH_ARM);
maps_.reset(
- new BufferMaps("1000-4000 ---s 00000000 00:00 0\n"
- "4000-6000 r--s 00000000 00:00 0\n"
- "6000-8000 -wxs 00000000 00:00 0\n"
- "a000-c000 --xp 00000000 00:00 0\n"
- "c000-f000 rw-p 00000000 00:00 0\n"
- "f000-11000 r--p 00000000 00:00 0\n"
- "12000-14000 r--p 00000000 00:00 0\n"
- "100000-110000 rw-p 0000000 00:00 0\n"
- "200000-210000 rw-p 0000000 00:00 0\n"));
+ 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 00000000 00:00 0 /fake/elf1\n"
+ "a000-c000 --xp 00000000 00:00 0 /fake/elf2\n"
+ "c000-f000 rw-p 00001000 00:00 0 /fake/elf2\n"
+ "f000-11000 r--p 00000000 00:00 0 /fake/elf3\n"
+ "11000-12000 rw-p 00001000 00:00 0 /fake/elf3\n"
+ "12000-14000 r--p 00000000 00:00 0 /fake/elf4\n"
+ "100000-110000 rw-p 0001000 00:00 0 /fake/elf4\n"
+ "200000-210000 rw-p 0002000 00:00 0 /fake/elf4\n"));
ASSERT_TRUE(maps_->Parse());
MapInfo* map_info = maps_->Get(3);
@@ -74,7 +75,7 @@
interface->FakeSetGlobalVariable("__jit_debug_descriptor", 0x800);
map_info->elf.reset(elf);
- map_info = maps_->Get(6);
+ map_info = maps_->Get(7);
ASSERT_TRUE(map_info != nullptr);
memory = new MemoryFake;
elf = new ElfFake(memory);
@@ -397,6 +398,8 @@
// 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.
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
index 55aaaf6..5657373 100644
--- a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/maps.txt
+++ b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/maps.txt
@@ -1,3 +1,4 @@
d0250000-d2600000 r-xp 0 00:00 0 <anonymous:d0250000>
e466e000-e4ae8000 r-xp 0 00:00 0 libart.so
+e4ae8000-e4ae9000 rw-p 1000 00:00 0 libart.so
e7d91000-e7e31000 r-xp 0 00:00 0 libc.so
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt b/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt
index f25c781..3cd9d40 100644
--- a/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt
+++ b/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt
@@ -2,7 +2,9 @@
dfe4e000-dfe7b000 r-xp 0 00:00 0 libarttestd.so
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 00000000 00:00 0 libart.so
+e648e000-e690f000 r-xp 0 00:00 0 libart.so
+e690f000-e6910000 rw-p 1000 00:00 0 libart.so
ed306000-ed801000 r-xp 0 00:00 0 libartd.so
+ed801000-ed802000 rw-p 1000 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_x86/maps.txt b/libunwindstack/tests/files/offline/jit_debug_x86/maps.txt
index db4f9f7..a8d215c 100644
--- a/libunwindstack/tests/files/offline/jit_debug_x86/maps.txt
+++ b/libunwindstack/tests/files/offline/jit_debug_x86/maps.txt
@@ -3,4 +3,5 @@
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
+f732b000-f732c000 rw-p 1000 00:00 0 libartd.so
f734b000-f74fc000 r-xp 0 00:00 0 libc.so
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 21d234f..ea83ef9 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -275,6 +275,13 @@
chown root root /apex
restorecon /apex
+ # Start logd before any other services run to ensure we capture all of their logs.
+ start logd
+ # Start essential services.
+ start servicemanager
+ start hwservicemanager
+ start vndservicemanager
+
# Healthd can trigger a full boot from charger mode by signaling this
# property when the power button is held.
on property:sys.boot_from_charger_mode=1
@@ -331,11 +338,6 @@
# /vendor/build.prop and
# /factory/factory.prop
load_system_props
- # start essential services
- start logd
- start servicemanager
- start hwservicemanager
- start vndservicemanager
start vold
exec - system system -- /system/bin/vdc checkpoint markBootAttempt