Merge "Modernize fastboot output format."
diff --git a/adb/Android.mk b/adb/Android.mk
new file mode 100644
index 0000000..8b2d558
--- /dev/null
+++ b/adb/Android.mk
@@ -0,0 +1,8 @@
+LOCAL_PATH := $(call my-dir)
+
+# Archive adb, adb.exe.
+$(call dist-for-goals,dist_files sdk win_sdk,$(HOST_OUT_EXECUTABLES)/adb)
+
+ifdef HOST_CROSS_OS
+$(call dist-for-goals,dist_files sdk win_sdk,$(ALL_MODULES.host_cross_adb.BUILT))
+endif
diff --git a/adb/daemon/shell_service.cpp b/adb/daemon/shell_service.cpp
index 17c7eba..401c99c 100644
--- a/adb/daemon/shell_service.cpp
+++ b/adb/daemon/shell_service.cpp
@@ -334,8 +334,18 @@
// processes, so we need to manually reset back to SIG_DFL here (http://b/35209888).
signal(SIGPIPE, SIG_DFL);
+ // Increase oom_score_adj from -1000, so that the child is visible to the OOM-killer.
+ // Don't treat failure as an error, because old Android kernels explicitly disabled this.
+ int oom_score_adj_fd = adb_open("/proc/self/oom_score_adj", O_WRONLY | O_CLOEXEC);
+ if (oom_score_adj_fd != -1) {
+ const char* oom_score_adj_value = "-950";
+ TEMP_FAILURE_RETRY(
+ adb_write(oom_score_adj_fd, oom_score_adj_value, strlen(oom_score_adj_value)));
+ }
+
if (command_.empty()) {
- execle(_PATH_BSHELL, _PATH_BSHELL, "-", nullptr, cenv.data());
+ // Spawn a login shell if we don't have a command.
+ execle(_PATH_BSHELL, "-" _PATH_BSHELL, nullptr, cenv.data());
} else {
execle(_PATH_BSHELL, _PATH_BSHELL, "-c", command_.c_str(), nullptr, cenv.data());
}
diff --git a/adb/socket_test.cpp b/adb/socket_test.cpp
index 6b40056..f587fdb 100644
--- a/adb/socket_test.cpp
+++ b/adb/socket_test.cpp
@@ -42,7 +42,9 @@
class LocalSocketTest : public FdeventTest {};
-constexpr auto SLEEP_FOR_FDEVENT = 100ms;
+static void WaitForFdeventLoop() {
+ std::this_thread::sleep_for(100ms);
+}
TEST_F(LocalSocketTest, smoke) {
// Join two socketpairs with a chain of intermediate socketpairs.
@@ -98,7 +100,7 @@
ASSERT_EQ(0, adb_close(last[1]));
// Wait until the local sockets are closed.
- std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+ WaitForFdeventLoop();
ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
TerminateThread(thread);
}
@@ -144,13 +146,15 @@
PrepareThread();
std::thread thread(CloseWithPacketThreadFunc, &arg);
- // Wait until the fdevent_loop() starts.
- std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+
+ WaitForFdeventLoop();
ASSERT_EQ(0, adb_close(cause_close_fd[0]));
- std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+
+ WaitForFdeventLoop();
EXPECT_EQ(1u + GetAdditionalLocalSocketCount(), fdevent_installed_count());
ASSERT_EQ(0, adb_close(socket_fd[0]));
- std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+
+ WaitForFdeventLoop();
ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
TerminateThread(thread);
}
@@ -167,10 +171,11 @@
PrepareThread();
std::thread thread(CloseWithPacketThreadFunc, &arg);
- // Wait until the fdevent_loop() starts.
- std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+
+ WaitForFdeventLoop();
ASSERT_EQ(0, adb_close(cause_close_fd[0]));
- std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+
+ WaitForFdeventLoop();
EXPECT_EQ(1u + GetAdditionalLocalSocketCount(), fdevent_installed_count());
// Verify if we can read successfully.
@@ -179,7 +184,7 @@
ASSERT_EQ(true, ReadFdExactly(socket_fd[0], buf.data(), buf.size()));
ASSERT_EQ(0, adb_close(socket_fd[0]));
- std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+ WaitForFdeventLoop();
ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
TerminateThread(thread);
}
@@ -199,12 +204,12 @@
PrepareThread();
std::thread thread(CloseWithPacketThreadFunc, &arg);
- // Wait until the fdevent_loop() starts.
- std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+
+ WaitForFdeventLoop();
EXPECT_EQ(2u + GetAdditionalLocalSocketCount(), fdevent_installed_count());
ASSERT_EQ(0, adb_close(socket_fd[0]));
- std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+ WaitForFdeventLoop();
ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
TerminateThread(thread);
}
@@ -242,8 +247,7 @@
adb_close(head_fd[0]);
adb_close(tail_fd[0]);
- // Wait until the local sockets are closed.
- std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+ WaitForFdeventLoop();
ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
TerminateThread(thread);
}
@@ -285,14 +289,13 @@
PrepareThread();
std::thread thread(CloseRdHupSocketThreadFunc, &arg);
- // Wait until the fdevent_loop() starts.
- std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+ WaitForFdeventLoop();
EXPECT_EQ(1u + GetAdditionalLocalSocketCount(), fdevent_installed_count());
// Wait until the client closes its socket.
client_thread.join();
- std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+ WaitForFdeventLoop();
ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
TerminateThread(thread);
}
diff --git a/adb/sysdeps_test.cpp b/adb/sysdeps_test.cpp
index fd19882..79cebe6 100644
--- a/adb/sysdeps_test.cpp
+++ b/adb/sysdeps_test.cpp
@@ -121,10 +121,13 @@
adb_pollfd pfd[3] = {};
pfd[0].fd = fds[0];
pfd[0].events = POLLRDNORM;
+ pfd[0].revents = ~0;
pfd[1].fd = INT_MAX;
pfd[1].events = POLLRDNORM;
+ pfd[1].revents = ~0;
pfd[2].fd = fds[1];
pfd[2].events = POLLWRNORM;
+ pfd[2].revents = ~0;
ASSERT_TRUE(WriteFdExactly(fds[1], "foo", 4));
@@ -136,6 +139,17 @@
EXPECT_EQ(POLLRDNORM, pfd[0].revents);
EXPECT_EQ(POLLNVAL, pfd[1].revents);
EXPECT_EQ(POLLWRNORM, pfd[2].revents);
+
+ // Make sure that we return immediately if an invalid FD is given.
+ pfd[0].fd = fds[0];
+ pfd[0].events = POLLRDNORM;
+ pfd[0].revents = ~0;
+ pfd[1].fd = INT_MAX;
+ pfd[1].events = POLLRDNORM;
+ pfd[1].revents = ~0;
+ EXPECT_EQ(2, adb_poll(pfd, 2, -1));
+ EXPECT_EQ(POLLRDNORM, pfd[0].revents);
+ EXPECT_EQ(POLLNVAL, pfd[1].revents);
}
TEST_F(sysdeps_poll, duplicate_fd) {
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index 62f4ac8..7d35fb6 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -529,6 +529,7 @@
int skipped = 0;
std::vector<WSAPOLLFD> sockets;
std::vector<adb_pollfd*> original;
+
for (size_t i = 0; i < nfds; ++i) {
FH fh = _fh_from_int(fds[i].fd, __func__);
if (!fh || !fh->used || fh->clazz != &_fh_socket_class) {
@@ -549,6 +550,11 @@
return skipped;
}
+ // If we have any invalid FDs in our FD set, make sure to return immediately.
+ if (skipped > 0) {
+ timeout = 0;
+ }
+
int result = WSAPoll(sockets.data(), sockets.size(), timeout);
if (result == SOCKET_ERROR) {
_socket_set_errno(WSAGetLastError());
@@ -560,7 +566,7 @@
original[i]->revents = sockets[i].revents;
}
- // WSAPoll appears to return the number of unique FDs with avaiable events, instead of how many
+ // WSAPoll appears to return the number of unique FDs with available events, instead of how many
// of the pollfd elements have a non-zero revents field, which is what it and poll are specified
// to do. Ignore its result and calculate the proper return value.
result = 0;
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index f5bcc26..944b00b 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -22,7 +22,8 @@
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/../adb \
- $(LOCAL_PATH)/../mkbootimg \
+
+LOCAL_HEADER_LIBRARIES := bootimg_headers
LOCAL_SRC_FILES := \
bootimg_utils.cpp \
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 72a65d2..3fbef9f 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -116,17 +116,21 @@
#define EM_ICE 2
#define EM_AES_256_CTS 3
#define EM_AES_256_HEH 4
+#define EM_SPECK_128_256_XTS 5
+#define EM_SPECK_128_256_CTS 6
static const struct flag_list file_contents_encryption_modes[] = {
{"aes-256-xts", EM_AES_256_XTS},
+ {"speck128/256-xts", EM_SPECK_128_256_XTS},
{"software", EM_AES_256_XTS}, /* alias for backwards compatibility */
- {"ice", EM_ICE}, /* hardware-specific inline cryptographic engine */
+ {"ice", EM_ICE}, /* hardware-specific inline cryptographic engine */
{0, 0},
};
static const struct flag_list file_names_encryption_modes[] = {
{"aes-256-cts", EM_AES_256_CTS},
{"aes-256-heh", EM_AES_256_HEH},
+ {"speck128/256-cts", EM_SPECK_128_256_CTS},
{0, 0},
};
diff --git a/init/Android.bp b/init/Android.bp
index 31c8efb..70a4ac6 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -127,9 +127,7 @@
"watchdogd.cpp",
],
whole_static_libs: ["libcap"],
- include_dirs: [
- "system/core/mkbootimg",
- ],
+ header_libs: ["bootimg_headers"],
proto: {
type: "lite",
export_proto_headers: true,
diff --git a/init/stable_properties.h b/init/stable_properties.h
index c8bdaa4..4714b57 100644
--- a/init/stable_properties.h
+++ b/init/stable_properties.h
@@ -35,10 +35,12 @@
"persist.bluetooth.btsnoopenable",
"persist.sys.crash_rcu",
"persist.sys.zram_enabled",
+ "ro.board.platform",
"ro.bootmode",
"ro.build.type",
"ro.debuggable",
"sys.boot_completed",
+ "sys.boot_from_charger_mode",
"sys.retaildemo.enabled",
"sys.shutdown.requested",
"sys.usb.config",
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index 5ea981f..f6f7128 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -199,8 +199,9 @@
// Support wifi_hal_legacy administering a network interface.
{ 00755, AID_WIFI, AID_WIFI, CAP_MASK_LONG(CAP_NET_ADMIN) |
- CAP_MASK_LONG(CAP_NET_RAW),
- "vendor/bin/hw/android.hardware.wifi@1.0-service" },
+ CAP_MASK_LONG(CAP_NET_RAW) |
+ CAP_MASK_LONG(CAP_SYS_MODULE),
+ "vendor/bin/hw/android.hardware.wifi@1.0-service" },
// generic defaults
{ 00755, AID_ROOT, AID_ROOT, 0, "bin/*" },
diff --git a/libunwindstack/DwarfCfa.cpp b/libunwindstack/DwarfCfa.cpp
index aa8cd3a..6ecedce 100644
--- a/libunwindstack/DwarfCfa.cpp
+++ b/libunwindstack/DwarfCfa.cpp
@@ -50,7 +50,17 @@
memory_->set_cur_offset(start_offset);
uint64_t cfa_offset;
cur_pc_ = fde_->pc_start;
- while ((cfa_offset = memory_->cur_offset()) < end_offset && cur_pc_ <= pc) {
+ 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;
@@ -129,7 +139,6 @@
}
}
}
- return true;
}
template <typename AddressType>
diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp
index 5586e72..65eec65 100644
--- a/libunwindstack/DwarfSection.cpp
+++ b/libunwindstack/DwarfSection.cpp
@@ -55,21 +55,29 @@
}
bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) {
- 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;
- }
+ // 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)) {
- return false;
+ // Now get the location information for this pc.
+ dwarf_loc_regs_t loc_regs;
+ if (!GetCfaLocationInfo(pc, fde, &loc_regs)) {
+ 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;
}
// Now eval the actual registers.
- return Eval(fde->cie, process_memory, loc_regs, regs, finished);
+ return Eval(it->second.cie, process_memory, it->second, regs, finished);
}
template <typename AddressType>
diff --git a/libunwindstack/RegsArm.cpp b/libunwindstack/RegsArm.cpp
index e2a9cb0..27cab43 100644
--- a/libunwindstack/RegsArm.cpp
+++ b/libunwindstack/RegsArm.cpp
@@ -51,13 +51,23 @@
}
uint64_t RegsArm::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
+ if (!elf->valid()) {
+ return 2;
+ }
+
uint64_t load_bias = elf->GetLoadBias();
if (rel_pc < load_bias) {
- return 0;
+ if (rel_pc < 2) {
+ return 0;
+ }
+ return 2;
}
uint64_t adjusted_rel_pc = rel_pc - load_bias;
if (adjusted_rel_pc < 5) {
- return 0;
+ if (adjusted_rel_pc < 2) {
+ return 0;
+ }
+ return 2;
}
if (adjusted_rel_pc & 1) {
diff --git a/libunwindstack/RegsArm64.cpp b/libunwindstack/RegsArm64.cpp
index fe24c80..4a2a6c4 100644
--- a/libunwindstack/RegsArm64.cpp
+++ b/libunwindstack/RegsArm64.cpp
@@ -51,8 +51,8 @@
regs_[ARM64_REG_SP] = sp;
}
-uint64_t RegsArm64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
- if (!elf->valid() || rel_pc < 4) {
+uint64_t RegsArm64::GetPcAdjustment(uint64_t rel_pc, Elf*) {
+ if (rel_pc < 4) {
return 0;
}
return 4;
diff --git a/libunwindstack/RegsMips.cpp b/libunwindstack/RegsMips.cpp
index 0b10e21..c87e69b 100644
--- a/libunwindstack/RegsMips.cpp
+++ b/libunwindstack/RegsMips.cpp
@@ -51,8 +51,8 @@
regs_[MIPS_REG_SP] = static_cast<uint32_t>(sp);
}
-uint64_t RegsMips::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
- if (!elf->valid() || rel_pc < 8) {
+uint64_t RegsMips::GetPcAdjustment(uint64_t rel_pc, Elf*) {
+ if (rel_pc < 8) {
return 0;
}
// For now, just assume no compact branches
diff --git a/libunwindstack/RegsMips64.cpp b/libunwindstack/RegsMips64.cpp
index 8848e3b..236a922 100644
--- a/libunwindstack/RegsMips64.cpp
+++ b/libunwindstack/RegsMips64.cpp
@@ -51,8 +51,8 @@
regs_[MIPS64_REG_SP] = sp;
}
-uint64_t RegsMips64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
- if (!elf->valid() || rel_pc < 8) {
+uint64_t RegsMips64::GetPcAdjustment(uint64_t rel_pc, Elf*) {
+ if (rel_pc < 8) {
return 0;
}
// For now, just assume no compact branches
diff --git a/libunwindstack/RegsX86.cpp b/libunwindstack/RegsX86.cpp
index bb95a13..f7e0614 100644
--- a/libunwindstack/RegsX86.cpp
+++ b/libunwindstack/RegsX86.cpp
@@ -50,8 +50,8 @@
regs_[X86_REG_SP] = static_cast<uint32_t>(sp);
}
-uint64_t RegsX86::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
- if (!elf->valid() || rel_pc == 0) {
+uint64_t RegsX86::GetPcAdjustment(uint64_t rel_pc, Elf*) {
+ if (rel_pc == 0) {
return 0;
}
return 1;
diff --git a/libunwindstack/RegsX86_64.cpp b/libunwindstack/RegsX86_64.cpp
index e57e2bc..7d6ad86 100644
--- a/libunwindstack/RegsX86_64.cpp
+++ b/libunwindstack/RegsX86_64.cpp
@@ -50,8 +50,8 @@
regs_[X86_64_REG_SP] = sp;
}
-uint64_t RegsX86_64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
- if (!elf->valid() || rel_pc == 0) {
+uint64_t RegsX86_64::GetPcAdjustment(uint64_t rel_pc, Elf*) {
+ if (rel_pc == 0) {
return 0;
}
return 1;
diff --git a/libunwindstack/include/unwindstack/DwarfLocation.h b/libunwindstack/include/unwindstack/DwarfLocation.h
index 0881182..3d50ccf 100644
--- a/libunwindstack/include/unwindstack/DwarfLocation.h
+++ b/libunwindstack/include/unwindstack/DwarfLocation.h
@@ -23,6 +23,8 @@
namespace unwindstack {
+struct DwarfCie;
+
enum DwarfLocationEnum : uint8_t {
DWARF_LOCATION_INVALID = 0,
DWARF_LOCATION_UNDEFINED,
@@ -38,7 +40,13 @@
uint64_t values[2];
};
-typedef std::unordered_map<uint32_t, DwarfLocation> dwarf_loc_regs_t;
+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
diff --git a/libunwindstack/include/unwindstack/DwarfSection.h b/libunwindstack/include/unwindstack/DwarfSection.h
index da91fd0..209c54a 100644
--- a/libunwindstack/include/unwindstack/DwarfSection.h
+++ b/libunwindstack/include/unwindstack/DwarfSection.h
@@ -20,6 +20,7 @@
#include <stdint.h>
#include <iterator>
+#include <map>
#include <unordered_map>
#include <unwindstack/DwarfError.h>
@@ -112,6 +113,7 @@
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>
diff --git a/libunwindstack/tests/DwarfSectionImplTest.cpp b/libunwindstack/tests/DwarfSectionImplTest.cpp
index c85764c..c340291 100644
--- a/libunwindstack/tests/DwarfSectionImplTest.cpp
+++ b/libunwindstack/tests/DwarfSectionImplTest.cpp
@@ -853,7 +853,8 @@
fde.cfa_instructions_offset = 0x6000;
fde.cfa_instructions_end = 0x6002;
- dwarf_loc_regs_t cie_loc_regs{{6, {DWARF_LOCATION_REGISTER, {4, 0}}}};
+ 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});
diff --git a/libunwindstack/tests/DwarfSectionTest.cpp b/libunwindstack/tests/DwarfSectionTest.cpp
index 3fcd2b6..071d2df 100644
--- a/libunwindstack/tests/DwarfSectionTest.cpp
+++ b/libunwindstack/tests/DwarfSectionTest.cpp
@@ -165,4 +165,72 @@
ASSERT_TRUE(mock_section.Step(0x1000, nullptr, &process, &finished));
}
+static bool MockGetCfaLocationInfo(::testing::Unused, const DwarfFde* fde,
+ dwarf_loc_regs_t* loc_regs) {
+ loc_regs->pc_start = fde->pc_start;
+ loc_regs->pc_end = fde->pc_end;
+ return true;
+}
+
+TEST_F(DwarfSectionTest, Step_cache) {
+ MockDwarfSection mock_section(&memory_);
+
+ DwarfCie cie{};
+ DwarfFde fde{};
+ fde.pc_start = 0x500;
+ fde.pc_end = 0x2000;
+ fde.cie = &cie;
+
+ EXPECT_CALL(mock_section, GetFdeOffsetFromPc(0x1000, ::testing::_))
+ .WillOnce(::testing::Return(true));
+ EXPECT_CALL(mock_section, GetFdeFromOffset(::testing::_)).WillOnce(::testing::Return(&fde));
+
+ EXPECT_CALL(mock_section, GetCfaLocationInfo(0x1000, &fde, ::testing::_))
+ .WillOnce(::testing::Invoke(MockGetCfaLocationInfo));
+
+ MemoryFake process;
+ EXPECT_CALL(mock_section, Eval(&cie, &process, ::testing::_, nullptr, ::testing::_))
+ .WillRepeatedly(::testing::Return(true));
+
+ bool finished;
+ ASSERT_TRUE(mock_section.Step(0x1000, nullptr, &process, &finished));
+ ASSERT_TRUE(mock_section.Step(0x1000, nullptr, &process, &finished));
+ ASSERT_TRUE(mock_section.Step(0x1500, nullptr, &process, &finished));
+}
+
+TEST_F(DwarfSectionTest, Step_cache_not_in_pc) {
+ MockDwarfSection mock_section(&memory_);
+
+ DwarfCie cie{};
+ DwarfFde fde0{};
+ fde0.pc_start = 0x1000;
+ fde0.pc_end = 0x2000;
+ fde0.cie = &cie;
+ EXPECT_CALL(mock_section, GetFdeOffsetFromPc(0x1000, ::testing::_))
+ .WillOnce(::testing::Return(true));
+ EXPECT_CALL(mock_section, GetFdeFromOffset(::testing::_)).WillOnce(::testing::Return(&fde0));
+ EXPECT_CALL(mock_section, GetCfaLocationInfo(0x1000, &fde0, ::testing::_))
+ .WillOnce(::testing::Invoke(MockGetCfaLocationInfo));
+
+ MemoryFake process;
+ EXPECT_CALL(mock_section, Eval(&cie, &process, ::testing::_, nullptr, ::testing::_))
+ .WillRepeatedly(::testing::Return(true));
+
+ bool finished;
+ ASSERT_TRUE(mock_section.Step(0x1000, nullptr, &process, &finished));
+
+ DwarfFde fde1{};
+ fde1.pc_start = 0x500;
+ fde1.pc_end = 0x800;
+ fde1.cie = &cie;
+ EXPECT_CALL(mock_section, GetFdeOffsetFromPc(0x600, ::testing::_))
+ .WillOnce(::testing::Return(true));
+ EXPECT_CALL(mock_section, GetFdeFromOffset(::testing::_)).WillOnce(::testing::Return(&fde1));
+ EXPECT_CALL(mock_section, GetCfaLocationInfo(0x600, &fde1, ::testing::_))
+ .WillOnce(::testing::Invoke(MockGetCfaLocationInfo));
+
+ ASSERT_TRUE(mock_section.Step(0x600, nullptr, &process, &finished));
+ ASSERT_TRUE(mock_section.Step(0x700, nullptr, &process, &finished));
+}
+
} // namespace unwindstack
diff --git a/libunwindstack/tests/RegsTest.cpp b/libunwindstack/tests/RegsTest.cpp
index 3e80733..d15823e 100644
--- a/libunwindstack/tests/RegsTest.cpp
+++ b/libunwindstack/tests/RegsTest.cpp
@@ -94,48 +94,48 @@
TEST_F(RegsTest, rel_pc) {
RegsArm64 arm64;
- ASSERT_EQ(4U, arm64.GetPcAdjustment(0x10, elf_.get()));
- ASSERT_EQ(4U, arm64.GetPcAdjustment(0x4, elf_.get()));
- ASSERT_EQ(0U, arm64.GetPcAdjustment(0x3, elf_.get()));
- ASSERT_EQ(0U, arm64.GetPcAdjustment(0x2, elf_.get()));
- ASSERT_EQ(0U, arm64.GetPcAdjustment(0x1, elf_.get()));
- ASSERT_EQ(0U, arm64.GetPcAdjustment(0x0, elf_.get()));
+ EXPECT_EQ(4U, arm64.GetPcAdjustment(0x10, elf_.get()));
+ EXPECT_EQ(4U, arm64.GetPcAdjustment(0x4, elf_.get()));
+ EXPECT_EQ(0U, arm64.GetPcAdjustment(0x3, elf_.get()));
+ EXPECT_EQ(0U, arm64.GetPcAdjustment(0x2, elf_.get()));
+ EXPECT_EQ(0U, arm64.GetPcAdjustment(0x1, elf_.get()));
+ EXPECT_EQ(0U, arm64.GetPcAdjustment(0x0, elf_.get()));
RegsX86 x86;
- ASSERT_EQ(1U, x86.GetPcAdjustment(0x100, elf_.get()));
- ASSERT_EQ(1U, x86.GetPcAdjustment(0x2, elf_.get()));
- ASSERT_EQ(1U, x86.GetPcAdjustment(0x1, elf_.get()));
- ASSERT_EQ(0U, x86.GetPcAdjustment(0x0, elf_.get()));
+ EXPECT_EQ(1U, x86.GetPcAdjustment(0x100, elf_.get()));
+ EXPECT_EQ(1U, x86.GetPcAdjustment(0x2, elf_.get()));
+ EXPECT_EQ(1U, x86.GetPcAdjustment(0x1, elf_.get()));
+ EXPECT_EQ(0U, x86.GetPcAdjustment(0x0, elf_.get()));
RegsX86_64 x86_64;
- ASSERT_EQ(1U, x86_64.GetPcAdjustment(0x100, elf_.get()));
- ASSERT_EQ(1U, x86_64.GetPcAdjustment(0x2, elf_.get()));
- ASSERT_EQ(1U, x86_64.GetPcAdjustment(0x1, elf_.get()));
- ASSERT_EQ(0U, x86_64.GetPcAdjustment(0x0, elf_.get()));
+ EXPECT_EQ(1U, x86_64.GetPcAdjustment(0x100, elf_.get()));
+ EXPECT_EQ(1U, x86_64.GetPcAdjustment(0x2, elf_.get()));
+ EXPECT_EQ(1U, x86_64.GetPcAdjustment(0x1, elf_.get()));
+ EXPECT_EQ(0U, x86_64.GetPcAdjustment(0x0, elf_.get()));
RegsMips mips;
- ASSERT_EQ(8U, mips.GetPcAdjustment(0x10, elf_.get()));
- ASSERT_EQ(8U, mips.GetPcAdjustment(0x8, elf_.get()));
- ASSERT_EQ(0U, mips.GetPcAdjustment(0x7, elf_.get()));
- ASSERT_EQ(0U, mips.GetPcAdjustment(0x6, elf_.get()));
- ASSERT_EQ(0U, mips.GetPcAdjustment(0x5, elf_.get()));
- ASSERT_EQ(0U, mips.GetPcAdjustment(0x4, elf_.get()));
- ASSERT_EQ(0U, mips.GetPcAdjustment(0x3, elf_.get()));
- ASSERT_EQ(0U, mips.GetPcAdjustment(0x2, elf_.get()));
- ASSERT_EQ(0U, mips.GetPcAdjustment(0x1, elf_.get()));
- ASSERT_EQ(0U, mips.GetPcAdjustment(0x0, elf_.get()));
+ EXPECT_EQ(8U, mips.GetPcAdjustment(0x10, elf_.get()));
+ EXPECT_EQ(8U, mips.GetPcAdjustment(0x8, elf_.get()));
+ EXPECT_EQ(0U, mips.GetPcAdjustment(0x7, elf_.get()));
+ EXPECT_EQ(0U, mips.GetPcAdjustment(0x6, elf_.get()));
+ EXPECT_EQ(0U, mips.GetPcAdjustment(0x5, elf_.get()));
+ EXPECT_EQ(0U, mips.GetPcAdjustment(0x4, elf_.get()));
+ EXPECT_EQ(0U, mips.GetPcAdjustment(0x3, elf_.get()));
+ EXPECT_EQ(0U, mips.GetPcAdjustment(0x2, elf_.get()));
+ EXPECT_EQ(0U, mips.GetPcAdjustment(0x1, elf_.get()));
+ EXPECT_EQ(0U, mips.GetPcAdjustment(0x0, elf_.get()));
RegsMips64 mips64;
- ASSERT_EQ(8U, mips64.GetPcAdjustment(0x10, elf_.get()));
- ASSERT_EQ(8U, mips64.GetPcAdjustment(0x8, elf_.get()));
- ASSERT_EQ(0U, mips64.GetPcAdjustment(0x7, elf_.get()));
- ASSERT_EQ(0U, mips64.GetPcAdjustment(0x6, elf_.get()));
- ASSERT_EQ(0U, mips64.GetPcAdjustment(0x5, elf_.get()));
- ASSERT_EQ(0U, mips64.GetPcAdjustment(0x4, elf_.get()));
- ASSERT_EQ(0U, mips64.GetPcAdjustment(0x3, elf_.get()));
- ASSERT_EQ(0U, mips64.GetPcAdjustment(0x2, elf_.get()));
- ASSERT_EQ(0U, mips64.GetPcAdjustment(0x1, elf_.get()));
- ASSERT_EQ(0U, mips64.GetPcAdjustment(0x0, elf_.get()));
+ EXPECT_EQ(8U, mips64.GetPcAdjustment(0x10, elf_.get()));
+ EXPECT_EQ(8U, mips64.GetPcAdjustment(0x8, elf_.get()));
+ EXPECT_EQ(0U, mips64.GetPcAdjustment(0x7, elf_.get()));
+ EXPECT_EQ(0U, mips64.GetPcAdjustment(0x6, elf_.get()));
+ EXPECT_EQ(0U, mips64.GetPcAdjustment(0x5, elf_.get()));
+ EXPECT_EQ(0U, mips64.GetPcAdjustment(0x4, elf_.get()));
+ EXPECT_EQ(0U, mips64.GetPcAdjustment(0x3, elf_.get()));
+ EXPECT_EQ(0U, mips64.GetPcAdjustment(0x2, elf_.get()));
+ EXPECT_EQ(0U, mips64.GetPcAdjustment(0x1, elf_.get()));
+ EXPECT_EQ(0U, mips64.GetPcAdjustment(0x0, elf_.get()));
}
TEST_F(RegsTest, rel_pc_arm) {
@@ -143,34 +143,36 @@
// Check fence posts.
elf_->FakeSetLoadBias(0);
- ASSERT_EQ(2U, arm.GetPcAdjustment(0x5, elf_.get()));
- ASSERT_EQ(0U, arm.GetPcAdjustment(0x4, elf_.get()));
- ASSERT_EQ(0U, arm.GetPcAdjustment(0x3, elf_.get()));
- ASSERT_EQ(0U, arm.GetPcAdjustment(0x2, elf_.get()));
- ASSERT_EQ(0U, arm.GetPcAdjustment(0x1, elf_.get()));
- ASSERT_EQ(0U, arm.GetPcAdjustment(0x0, elf_.get()));
+ EXPECT_EQ(2U, arm.GetPcAdjustment(0x5, elf_.get()));
+ EXPECT_EQ(2U, arm.GetPcAdjustment(0x4, elf_.get()));
+ EXPECT_EQ(2U, arm.GetPcAdjustment(0x3, elf_.get()));
+ EXPECT_EQ(2U, arm.GetPcAdjustment(0x2, elf_.get()));
+ EXPECT_EQ(0U, arm.GetPcAdjustment(0x1, elf_.get()));
+ EXPECT_EQ(0U, arm.GetPcAdjustment(0x0, elf_.get()));
elf_->FakeSetLoadBias(0x100);
- ASSERT_EQ(0U, arm.GetPcAdjustment(0xff, elf_.get()));
- ASSERT_EQ(2U, arm.GetPcAdjustment(0x105, elf_.get()));
- ASSERT_EQ(0U, arm.GetPcAdjustment(0x104, elf_.get()));
- ASSERT_EQ(0U, arm.GetPcAdjustment(0x103, elf_.get()));
- ASSERT_EQ(0U, arm.GetPcAdjustment(0x102, elf_.get()));
- ASSERT_EQ(0U, arm.GetPcAdjustment(0x101, elf_.get()));
- ASSERT_EQ(0U, arm.GetPcAdjustment(0x100, elf_.get()));
+ EXPECT_EQ(0U, arm.GetPcAdjustment(0x1, elf_.get()));
+ EXPECT_EQ(2U, arm.GetPcAdjustment(0x2, elf_.get()));
+ EXPECT_EQ(2U, arm.GetPcAdjustment(0xff, elf_.get()));
+ EXPECT_EQ(2U, arm.GetPcAdjustment(0x105, elf_.get()));
+ EXPECT_EQ(2U, arm.GetPcAdjustment(0x104, elf_.get()));
+ EXPECT_EQ(2U, arm.GetPcAdjustment(0x103, elf_.get()));
+ EXPECT_EQ(2U, arm.GetPcAdjustment(0x102, elf_.get()));
+ EXPECT_EQ(0U, arm.GetPcAdjustment(0x101, elf_.get()));
+ EXPECT_EQ(0U, arm.GetPcAdjustment(0x100, elf_.get()));
// Check thumb instructions handling.
elf_->FakeSetLoadBias(0);
memory_->SetData32(0x2000, 0);
- ASSERT_EQ(2U, arm.GetPcAdjustment(0x2005, elf_.get()));
+ EXPECT_EQ(2U, arm.GetPcAdjustment(0x2005, elf_.get()));
memory_->SetData32(0x2000, 0xe000f000);
- ASSERT_EQ(4U, arm.GetPcAdjustment(0x2005, elf_.get()));
+ EXPECT_EQ(4U, arm.GetPcAdjustment(0x2005, elf_.get()));
elf_->FakeSetLoadBias(0x400);
memory_->SetData32(0x2100, 0);
- ASSERT_EQ(2U, arm.GetPcAdjustment(0x2505, elf_.get()));
+ EXPECT_EQ(2U, arm.GetPcAdjustment(0x2505, elf_.get()));
memory_->SetData32(0x2100, 0xf111f111);
- ASSERT_EQ(4U, arm.GetPcAdjustment(0x2505, elf_.get()));
+ EXPECT_EQ(4U, arm.GetPcAdjustment(0x2505, elf_.get()));
}
TEST_F(RegsTest, elf_invalid) {
@@ -181,32 +183,33 @@
RegsMips regs_mips;
RegsMips64 regs_mips64;
MapInfo map_info(0x1000, 0x2000);
- Elf* invalid_elf = new Elf(new MemoryFake);
+ Elf* invalid_elf = new Elf(nullptr);
map_info.elf.reset(invalid_elf);
regs_arm.set_pc(0x1500);
EXPECT_EQ(0x500U, invalid_elf->GetRelPc(regs_arm.pc(), &map_info));
- EXPECT_EQ(4U, regs_arm.GetPcAdjustment(0x500U, invalid_elf));
+ EXPECT_EQ(2U, regs_arm.GetPcAdjustment(0x500U, invalid_elf));
+ EXPECT_EQ(2U, regs_arm.GetPcAdjustment(0x511U, invalid_elf));
regs_arm64.set_pc(0x1600);
EXPECT_EQ(0x600U, invalid_elf->GetRelPc(regs_arm64.pc(), &map_info));
- EXPECT_EQ(0U, regs_arm64.GetPcAdjustment(0x600U, invalid_elf));
+ EXPECT_EQ(4U, regs_arm64.GetPcAdjustment(0x600U, invalid_elf));
regs_x86.set_pc(0x1700);
EXPECT_EQ(0x700U, invalid_elf->GetRelPc(regs_x86.pc(), &map_info));
- EXPECT_EQ(0U, regs_x86.GetPcAdjustment(0x700U, invalid_elf));
+ EXPECT_EQ(1U, regs_x86.GetPcAdjustment(0x700U, invalid_elf));
regs_x86_64.set_pc(0x1800);
EXPECT_EQ(0x800U, invalid_elf->GetRelPc(regs_x86_64.pc(), &map_info));
- EXPECT_EQ(0U, regs_x86_64.GetPcAdjustment(0x800U, invalid_elf));
+ EXPECT_EQ(1U, regs_x86_64.GetPcAdjustment(0x800U, invalid_elf));
regs_mips.set_pc(0x1900);
EXPECT_EQ(0x900U, invalid_elf->GetRelPc(regs_mips.pc(), &map_info));
- EXPECT_EQ(0U, regs_mips.GetPcAdjustment(0x900U, invalid_elf));
+ EXPECT_EQ(8U, regs_mips.GetPcAdjustment(0x900U, invalid_elf));
regs_mips64.set_pc(0x1a00);
EXPECT_EQ(0xa00U, invalid_elf->GetRelPc(regs_mips64.pc(), &map_info));
- EXPECT_EQ(0U, regs_mips64.GetPcAdjustment(0xa00U, invalid_elf));
+ EXPECT_EQ(8U, regs_mips64.GetPcAdjustment(0xa00U, invalid_elf));
}
TEST_F(RegsTest, arm_verify_sp_pc) {
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp
index 6c242a5..2b8f0c2 100644
--- a/libunwindstack/tests/UnwindOfflineTest.cpp
+++ b/libunwindstack/tests/UnwindOfflineTest.cpp
@@ -285,7 +285,7 @@
" #01 pc 00067f00 libarttestd.so (Java_Main_unwindInProcess+10032)\n"
" #02 pc 000021a8 (offset 0x2000) 137-cfi.odex (boolean Main.unwindInProcess(boolean, int, "
"boolean)+136)\n"
- " #03 pc 0000fe81 anonymous:ee74c000 (boolean Main.bar(boolean)+65)\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 "
"(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+885)\n"
@@ -300,7 +300,7 @@
"20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n"
" #09 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
" #10 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
- " #11 pc 0000fe04 anonymous:ee74c000 (int Main.compare(Main, Main)+52)\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 "
"(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+885)\n"
@@ -315,8 +315,8 @@
"20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n"
" #17 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
" #18 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
- " #19 pc 0000fd3c anonymous:ee74c000 (int Main.compare(java.lang.Object, "
- "java.lang.Object)+108)\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 "
"(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+885)\n"
@@ -331,9 +331,9 @@
"20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n"
" #25 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
" #26 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
- " #27 pc 0000fbdc anonymous:ee74c000 (int "
+ " #27 pc 0000fbdb anonymous:ee74c000 (int "
"java.util.Arrays.binarySearch0(java.lang.Object[], int, int, java.lang.Object, "
- "java.util.Comparator)+332)\n"
+ "java.util.Comparator)+331)\n"
" #28 pc 006ad6a2 libartd.so (art_quick_invoke_static_stub+418)\n"
" #29 pc 00146acb libartd.so "
"(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+907)\n"
@@ -348,7 +348,7 @@
"20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n"
" #33 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
" #34 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
- " #35 pc 0000f625 anonymous:ee74c000 (boolean Main.foo()+165)\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 "
"(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+885)\n"
@@ -363,7 +363,7 @@
"20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n"
" #41 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
" #42 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
- " #43 pc 0000eedc anonymous:ee74c000 (void Main.runPrimary()+60)\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 "
"(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+885)\n"
@@ -378,7 +378,7 @@
"20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n"
" #49 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
" #50 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
- " #51 pc 0000ac22 anonymous:ee74c000 (void Main.main(java.lang.String[])+98)\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 "
"(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+907)\n"
@@ -420,7 +420,7 @@
EXPECT_EQ(0xffeb52a0U, unwinder.frames()[1].sp);
EXPECT_EQ(0xec6061a8U, unwinder.frames()[2].pc);
EXPECT_EQ(0xffeb5ce0U, unwinder.frames()[2].sp);
- EXPECT_EQ(0xee75be81U, unwinder.frames()[3].pc);
+ 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);
@@ -436,7 +436,7 @@
EXPECT_EQ(0xffeb5fb0U, unwinder.frames()[9].sp);
EXPECT_EQ(0xf72945bdU, unwinder.frames()[10].pc);
EXPECT_EQ(0xffeb6110U, unwinder.frames()[10].sp);
- EXPECT_EQ(0xee75be04U, unwinder.frames()[11].pc);
+ 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);
@@ -452,7 +452,7 @@
EXPECT_EQ(0xffeb63e0U, unwinder.frames()[17].sp);
EXPECT_EQ(0xf72945bdU, unwinder.frames()[18].pc);
EXPECT_EQ(0xffeb6530U, unwinder.frames()[18].sp);
- EXPECT_EQ(0xee75bd3cU, unwinder.frames()[19].pc);
+ 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);
@@ -468,7 +468,7 @@
EXPECT_EQ(0xffeb6810U, unwinder.frames()[25].sp);
EXPECT_EQ(0xf72945bdU, unwinder.frames()[26].pc);
EXPECT_EQ(0xffeb6960U, unwinder.frames()[26].sp);
- EXPECT_EQ(0xee75bbdcU, unwinder.frames()[27].pc);
+ 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);
@@ -484,7 +484,7 @@
EXPECT_EQ(0xffeb6c50U, unwinder.frames()[33].sp);
EXPECT_EQ(0xf72945bdU, unwinder.frames()[34].pc);
EXPECT_EQ(0xffeb6dd0U, unwinder.frames()[34].sp);
- EXPECT_EQ(0xee75b625U, unwinder.frames()[35].pc);
+ 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);
@@ -500,7 +500,7 @@
EXPECT_EQ(0xffeb70a0U, unwinder.frames()[41].sp);
EXPECT_EQ(0xf72945bdU, unwinder.frames()[42].pc);
EXPECT_EQ(0xffeb71f0U, unwinder.frames()[42].sp);
- EXPECT_EQ(0xee75aedcU, unwinder.frames()[43].pc);
+ 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);
@@ -516,7 +516,7 @@
EXPECT_EQ(0xffeb74f0U, unwinder.frames()[49].sp);
EXPECT_EQ(0xf72945bdU, unwinder.frames()[50].pc);
EXPECT_EQ(0xffeb7680U, unwinder.frames()[50].sp);
- EXPECT_EQ(0xee756c22U, unwinder.frames()[51].pc);
+ 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);
diff --git a/mkbootimg/Android.bp b/mkbootimg/Android.bp
new file mode 100644
index 0000000..b494346
--- /dev/null
+++ b/mkbootimg/Android.bp
@@ -0,0 +1,32 @@
+// Copyright 2012 The Android Open Source Project
+
+cc_library_headers {
+ name: "libmkbootimg_abi_headers",
+ vendor_available: true,
+ export_include_dirs: ["include"],
+}
+
+cc_library_headers {
+ name: "bootimg_headers",
+ vendor_available: true,
+ export_include_dirs: ["include/bootimg"],
+ host_supported: true,
+ target: {
+ windows: {
+ enabled: true,
+ },
+ },
+}
+
+cc_library {
+ name: "libmkbootimg_abi_check",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "mkbootimg_dummy.cpp",
+ ],
+ header_libs: ["libmkbootimg_abi_headers"],
+ export_header_lib_headers: ["libmkbootimg_abi_headers"],
+}
diff --git a/mkbootimg/Android.mk b/mkbootimg/Android.mk
index 8661d7d..92e1e27 100644
--- a/mkbootimg/Android.mk
+++ b/mkbootimg/Android.mk
@@ -9,3 +9,12 @@
LOCAL_MODULE := mkbootimg
include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := unpack_bootimg
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_IS_HOST_MODULE := true
+
+LOCAL_MODULE := unpack_bootimg
+
+include $(BUILD_PREBUILT)
diff --git a/mkbootimg/OWNERS b/mkbootimg/OWNERS
new file mode 100644
index 0000000..39448cf
--- /dev/null
+++ b/mkbootimg/OWNERS
@@ -0,0 +1 @@
+tbao@google.com
diff --git a/mkbootimg/bootimg.h b/mkbootimg/bootimg.h
deleted file mode 100644
index 60834fe..0000000
--- a/mkbootimg/bootimg.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/* tools/mkbootimg/bootimg.h
-**
-** Copyright 2007, 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>
-
-#ifndef _BOOT_IMAGE_H_
-#define _BOOT_IMAGE_H_
-
-typedef struct boot_img_hdr boot_img_hdr;
-
-#define BOOT_MAGIC "ANDROID!"
-#define BOOT_MAGIC_SIZE 8
-#define BOOT_NAME_SIZE 16
-#define BOOT_ARGS_SIZE 512
-#define BOOT_EXTRA_ARGS_SIZE 1024
-
-struct boot_img_hdr
-{
- uint8_t magic[BOOT_MAGIC_SIZE];
-
- uint32_t kernel_size; /* size in bytes */
- uint32_t kernel_addr; /* physical load addr */
-
- uint32_t ramdisk_size; /* size in bytes */
- uint32_t ramdisk_addr; /* physical load addr */
-
- uint32_t second_size; /* size in bytes */
- uint32_t second_addr; /* physical load addr */
-
- uint32_t tags_addr; /* physical addr for kernel tags */
- uint32_t page_size; /* flash page size we assume */
- uint32_t unused; /* reserved for future expansion: MUST be 0 */
-
- /* operating system version and security patch level; for
- * version "A.B.C" and patch level "Y-M-D":
- * ver = A << 14 | B << 7 | C (7 bits for each of A, B, C)
- * lvl = ((Y - 2000) & 127) << 4 | M (7 bits for Y, 4 bits for M)
- * os_version = ver << 11 | lvl */
- uint32_t os_version;
-
- uint8_t name[BOOT_NAME_SIZE]; /* asciiz product name */
-
- uint8_t cmdline[BOOT_ARGS_SIZE];
-
- uint32_t id[8]; /* timestamp / checksum / sha1 / etc */
-
- /* Supplemental command line data; kept here to maintain
- * binary compatibility with older versions of mkbootimg */
- uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
-} __attribute__((packed));
-
-/*
-** +-----------------+
-** | boot header | 1 page
-** +-----------------+
-** | kernel | n pages
-** +-----------------+
-** | ramdisk | m pages
-** +-----------------+
-** | second stage | o pages
-** +-----------------+
-**
-** n = (kernel_size + page_size - 1) / page_size
-** m = (ramdisk_size + page_size - 1) / page_size
-** o = (second_size + page_size - 1) / page_size
-**
-** 0. all entities are page_size aligned in flash
-** 1. kernel and ramdisk are required (size != 0)
-** 2. second is optional (second_size == 0 -> no second)
-** 3. load each element (kernel, ramdisk, second) at
-** the specified physical address (kernel_addr, etc)
-** 4. prepare tags at tag_addr. kernel_args[] is
-** appended to the kernel commandline in the tags.
-** 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
-** 6. if second_size != 0: jump to second_addr
-** else: jump to kernel_addr
-*/
-
-#if 0
-typedef struct ptentry ptentry;
-
-struct ptentry {
- char name[16]; /* asciiz partition name */
- unsigned start; /* starting block number */
- unsigned length; /* length in blocks */
- unsigned flags; /* set to zero */
-};
-
-/* MSM Partition Table ATAG
-**
-** length: 2 + 7 * n
-** atag: 0x4d534d70
-** <ptentry> x n
-*/
-#endif
-
-#endif
diff --git a/mkbootimg/include/abi_check/mkbootimg_abi_check.h b/mkbootimg/include/abi_check/mkbootimg_abi_check.h
new file mode 100644
index 0000000..d478aba
--- /dev/null
+++ b/mkbootimg/include/abi_check/mkbootimg_abi_check.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <bootimg/bootimg.h>
+
+// This header has been created for the following reaons:
+// 1) In order for a change in a user defined type to be classified as API /
+// ABI breaking, it needs to be referenced by an 'exported interface'
+// (in this case the function mkbootimg_dummy).
+// 2) Since 'mkbootimg_dummy' needs to be exported, we need to have it
+// exposed through a public header.
+// 3) It is desirable not to pollute bootimg.h with interfaces which are not
+// 'used' in reality by on device binaries. Furthermore, bootimg.h might
+// be exported by a library in the future, so we must avoid polluting it.
+void mkbootimg_dummy(boot_img_hdr*);
diff --git a/mkbootimg/include/bootimg/bootimg.h b/mkbootimg/include/bootimg/bootimg.h
new file mode 100644
index 0000000..4311b46
--- /dev/null
+++ b/mkbootimg/include/bootimg/bootimg.h
@@ -0,0 +1,164 @@
+/* tools/mkbootimg/bootimg.h
+**
+** Copyright 2007, 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>
+
+#ifndef _BOOT_IMAGE_H_
+#define _BOOT_IMAGE_H_
+
+#define BOOT_MAGIC "ANDROID!"
+#define BOOT_MAGIC_SIZE 8
+#define BOOT_NAME_SIZE 16
+#define BOOT_ARGS_SIZE 512
+#define BOOT_EXTRA_ARGS_SIZE 1024
+
+#define BOOT_HEADER_VERSION_ZERO 0
+/*
+ * Bootloader expects the structure of boot_img_hdr with header version
+ * BOOT_HEADER_VERSION_ZERO to be as follows:
+ */
+struct boot_img_hdr_v0 {
+ uint8_t magic[BOOT_MAGIC_SIZE];
+
+ uint32_t kernel_size; /* size in bytes */
+ uint32_t kernel_addr; /* physical load addr */
+
+ uint32_t ramdisk_size; /* size in bytes */
+ uint32_t ramdisk_addr; /* physical load addr */
+
+ uint32_t second_size; /* size in bytes */
+ uint32_t second_addr; /* physical load addr */
+
+ uint32_t tags_addr; /* physical addr for kernel tags */
+ uint32_t page_size; /* flash page size we assume */
+ /*
+ * version for the boot image header.
+ */
+ uint32_t header_version;
+
+ /* operating system version and security patch level; for
+ * version "A.B.C" and patch level "Y-M-D":
+ * ver = A << 14 | B << 7 | C (7 bits for each of A, B, C)
+ * lvl = ((Y - 2000) & 127) << 4 | M (7 bits for Y, 4 bits for M)
+ * os_version = ver << 11 | lvl */
+ uint32_t os_version;
+
+ uint8_t name[BOOT_NAME_SIZE]; /* asciiz product name */
+
+ uint8_t cmdline[BOOT_ARGS_SIZE];
+
+ uint32_t id[8]; /* timestamp / checksum / sha1 / etc */
+
+ /* Supplemental command line data; kept here to maintain
+ * binary compatibility with older versions of mkbootimg */
+ uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
+} __attribute__((packed));
+
+/*
+ * It is expected that callers would explicitly specify which version of the
+ * boot image header they need to use.
+ */
+typedef struct boot_img_hdr_v0 boot_img_hdr;
+
+/* When a boot header is of version BOOT_HEADER_VERSION_ZERO, the structure of boot image is as
+ * follows:
+ *
+ * +-----------------+
+ * | boot header | 1 page
+ * +-----------------+
+ * | kernel | n pages
+ * +-----------------+
+ * | ramdisk | m pages
+ * +-----------------+
+ * | second stage | o pages
+ * +-----------------+
+ *
+ * n = (kernel_size + page_size - 1) / page_size
+ * m = (ramdisk_size + page_size - 1) / page_size
+ * o = (second_size + page_size - 1) / page_size
+ *
+ * 0. all entities are page_size aligned in flash
+ * 1. kernel and ramdisk are required (size != 0)
+ * 2. second is optional (second_size == 0 -> no second)
+ * 3. load each element (kernel, ramdisk, second) at
+ * the specified physical address (kernel_addr, etc)
+ * 4. prepare tags at tag_addr. kernel_args[] is
+ * appended to the kernel commandline in the tags.
+ * 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
+ * 6. if second_size != 0: jump to second_addr
+ * else: jump to kernel_addr
+ */
+
+#define BOOT_HEADER_VERSION_ONE 1
+
+struct boot_img_hdr_v1 : public boot_img_hdr_v0 {
+ uint32_t recovery_dtbo_size; /* size in bytes for recovery DTBO image */
+ uint64_t recovery_dtbo_offset; /* physical load addr */
+ uint32_t header_size;
+} __attribute__((packed));
+
+/* When the boot image header has a version of BOOT_HEADER_VERSION_ONE, the structure of the boot
+ * image is as follows:
+ *
+ * +-----------------+
+ * | boot header | 1 page
+ * +-----------------+
+ * | kernel | n pages
+ * +-----------------+
+ * | ramdisk | m pages
+ * +-----------------+
+ * | second stage | o pages
+ * +-----------------+
+ * | recovery dtbo | p pages
+ * +-----------------+
+ * n = (kernel_size + page_size - 1) / page_size
+ * m = (ramdisk_size + page_size - 1) / page_size
+ * o = (second_size + page_size - 1) / page_size
+ * p = (recovery_dtbo_size + page_size - 1) / page_size
+ *
+ * 0. all entities are page_size aligned in flash
+ * 1. kernel and ramdisk are required (size != 0)
+ * 2. recovery_dtbo is required for recovery.img in non-A/B devices(recovery_dtbo_size != 0)
+ * 3. second is optional (second_size == 0 -> no second)
+ * 4. load each element (kernel, ramdisk, second, recovery_dtbo) at
+ * the specified physical address (kernel_addr, etc)
+ * 5. prepare tags at tag_addr. kernel_args[] is
+ * appended to the kernel commandline in the tags.
+ * 6. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
+ * 7. if second_size != 0: jump to second_addr
+ * else: jump to kernel_addr
+ */
+
+#if 0
+typedef struct ptentry ptentry;
+
+struct ptentry {
+ char name[16]; /* asciiz partition name */
+ unsigned start; /* starting block number */
+ unsigned length; /* length in blocks */
+ unsigned flags; /* set to zero */
+};
+
+/* MSM Partition Table ATAG
+**
+** length: 2 + 7 * n
+** atag: 0x4d534d70
+** <ptentry> x n
+*/
+#endif
+
+#endif
diff --git a/mkbootimg/mkbootimg b/mkbootimg/mkbootimg
index 5a13da2..ac20d05 100755
--- a/mkbootimg/mkbootimg
+++ b/mkbootimg/mkbootimg
@@ -57,7 +57,7 @@
args.base + args.second_offset, # physical load addr
args.base + args.tags_offset, # physical addr for kernel tags
args.pagesize, # flash page size we assume
- 0, # future expansion: MUST be 0
+ args.header_version, # version of bootimage header
(args.os_version << 11) | args.os_patch_level)) # os version and patch level
args.output.write(pack('16s', args.board.encode())) # asciiz product name
args.output.write(pack('512s', args.cmdline[:512].encode()))
@@ -66,10 +66,20 @@
update_sha(sha, args.kernel)
update_sha(sha, args.ramdisk)
update_sha(sha, args.second)
+
+ if args.header_version > 0:
+ update_sha(sha, args.recovery_dtbo)
+
img_id = pack('32s', sha.digest())
args.output.write(img_id)
args.output.write(pack('1024s', args.cmdline[512:].encode()))
+
+ if args.header_version > 0:
+ args.output.write(pack('I', filesize(args.recovery_dtbo))) # size in bytes
+ args.output.write(pack('Q', args.base + args.recovery_dtbo_offset)) # physical load addr
+ args.output.write(pack('I', args.output.tell() + 4)) # size of boot header
+
pad_file(args.output, args.pagesize)
return img_id
@@ -132,6 +142,7 @@
required=True)
parser.add_argument('--ramdisk', help='path to the ramdisk', type=FileType('rb'))
parser.add_argument('--second', help='path to the 2nd bootloader', type=FileType('rb'))
+ parser.add_argument('--recovery_dtbo', help='path to the recovery DTBO', type=FileType('rb'))
parser.add_argument('--cmdline', help='extra arguments to be passed on the '
'kernel command line', default='', action=ValidateStrLenAction, maxlen=1536)
parser.add_argument('--base', help='base address', type=parse_int, default=0x10000000)
@@ -139,6 +150,8 @@
parser.add_argument('--ramdisk_offset', help='ramdisk offset', type=parse_int, default=0x01000000)
parser.add_argument('--second_offset', help='2nd bootloader offset', type=parse_int,
default=0x00f00000)
+ parser.add_argument('--recovery_dtbo_offset', help='recovery dtbo offset', type=parse_int,
+ default=0x0f000000)
parser.add_argument('--os_version', help='operating system version', type=parse_os_version,
default=0)
parser.add_argument('--os_patch_level', help='operating system patch level',
@@ -150,6 +163,7 @@
choices=[2**i for i in range(11,15)], default=2048)
parser.add_argument('--id', help='print the image ID on standard output',
action='store_true')
+ parser.add_argument('--header_version', help='boot image header version', type=parse_int, default=0)
parser.add_argument('-o', '--output', help='output file name', type=FileType('wb'),
required=True)
return parser.parse_args()
@@ -160,6 +174,8 @@
write_padded_file(args.output, args.ramdisk, args.pagesize)
write_padded_file(args.output, args.second, args.pagesize)
+ if args.header_version > 0:
+ write_padded_file(args.output, args.recovery_dtbo, args.pagesize)
def main():
args = parse_cmdline()
diff --git a/mkbootimg/mkbootimg_dummy.cpp b/mkbootimg/mkbootimg_dummy.cpp
new file mode 100644
index 0000000..410d379
--- /dev/null
+++ b/mkbootimg/mkbootimg_dummy.cpp
@@ -0,0 +1,24 @@
+/*
+ * 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 <abi_check/mkbootimg_abi_check.h>
+
+void mkbootimg_dummy(boot_img_hdr* hdr) {
+ // TODO: Hack to trigger abi checks, remove this.
+ if (hdr) {
+ hdr--;
+ }
+}
diff --git a/mkbootimg/unpack_bootimg b/mkbootimg/unpack_bootimg
new file mode 100755
index 0000000..8e42ec0
--- /dev/null
+++ b/mkbootimg/unpack_bootimg
@@ -0,0 +1,137 @@
+#!/usr/bin/env python
+# Copyright 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.
+
+"""unpacks the bootimage.
+
+Extracts the kernel, ramdisk, second bootloader and recovery dtbo images.
+"""
+
+from __future__ import print_function
+from argparse import ArgumentParser, FileType
+from struct import unpack
+import os
+
+
+def create_out_dir(dir_path):
+ """creates a directory 'dir_path' if it does not exist"""
+ if not os.path.exists(dir_path):
+ os.makedirs(dir_path)
+
+
+def extract_image(offset, size, bootimage, extracted_image_name):
+ """extracts an image from the bootimage"""
+ bootimage.seek(offset)
+ with open(extracted_image_name, 'wb') as file_out:
+ file_out.write(bootimage.read(size))
+
+
+def get_number_of_pages(image_size, page_size):
+ """calculates the number of pages required for the image"""
+ return (image_size + page_size - 1) / page_size
+
+
+def unpack_bootimage(args):
+ """extracts kernel, ramdisk, second bootloader and recovery dtbo"""
+ boot_magic = unpack('8s', args.boot_img.read(8))
+ print('boot_magic: %s' % boot_magic)
+ kernel_ramdisk_second_info = unpack('10I', args.boot_img.read(10 * 4))
+ print('kernel_size: %s' % kernel_ramdisk_second_info[0])
+ print('kernel load address: %s' % kernel_ramdisk_second_info[1])
+ print('ramdisk size: %s' % kernel_ramdisk_second_info[2])
+ print('ramdisk load address: %s' % kernel_ramdisk_second_info[3])
+ print('second bootloader size: %s' % kernel_ramdisk_second_info[4])
+ print('second bootloader load address: %s' % kernel_ramdisk_second_info[5])
+ print('kernel tags load address: %s' % kernel_ramdisk_second_info[6])
+ print('page size: %s' % kernel_ramdisk_second_info[7])
+ print('boot image header version: %s' % kernel_ramdisk_second_info[8])
+ print('os version and patch level: %s' % kernel_ramdisk_second_info[9])
+
+ product_name = unpack('16s', args.boot_img.read(16))
+ print('product name: %s' % product_name)
+ cmdline = unpack('512s', args.boot_img.read(512))
+ print('command line args: %s' % cmdline)
+
+ args.boot_img.read(32) # ignore SHA
+
+ extra_cmdline = unpack('1024s', args.boot_img.read(1024))
+ print('additional command line args: %s' % extra_cmdline)
+
+ kernel_size = kernel_ramdisk_second_info[0]
+ ramdisk_size = kernel_ramdisk_second_info[2]
+ second_size = kernel_ramdisk_second_info[4]
+ page_size = kernel_ramdisk_second_info[7]
+ version = kernel_ramdisk_second_info[8]
+ if version > 0:
+ recovery_dtbo_size = unpack('I', args.boot_img.read(1 * 4))[0]
+ print('recovery dtbo size: %s' % recovery_dtbo_size)
+ recovery_dtbo_address = unpack('Q', args.boot_img.read(8))[0]
+ print('recovery dtbo load address: %s' % recovery_dtbo_address)
+ boot_header_size = unpack('I', args.boot_img.read(4))[0]
+ print('boot header size: %s' % boot_header_size)
+ else:
+ recovery_dtbo_size = 0
+
+ # The first page contains the boot header
+ num_header_pages = 1
+
+ num_kernel_pages = get_number_of_pages(kernel_size, page_size)
+ kernel_offset = page_size * num_header_pages # header occupies a page
+ image_info_list = [(kernel_offset, kernel_size, 'kernel')]
+
+ num_ramdisk_pages = get_number_of_pages(ramdisk_size, page_size)
+ ramdisk_offset = page_size * (num_header_pages + num_kernel_pages
+ ) # header + kernel
+ image_info_list.append((ramdisk_offset, ramdisk_size, 'ramdisk'))
+
+ num_second_pages = get_number_of_pages(second_size, page_size)
+ second_offset = page_size * (
+ num_header_pages + num_kernel_pages + num_ramdisk_pages
+ ) # header + kernel + ramdisk
+ image_info_list.append((second_offset, second_size, 'second'))
+
+ if recovery_dtbo_size > 0:
+ dtbo_offset = page_size * (num_header_pages + num_kernel_pages +
+ num_ramdisk_pages + num_second_pages)
+ image_info_list.append((dtbo_offset, recovery_dtbo_size,
+ 'recovery_dtbo'))
+
+ for image_info in image_info_list:
+ extract_image(image_info[0], image_info[1], args.boot_img,
+ os.path.join(args.out, image_info[2]))
+
+
+def parse_cmdline():
+ """parse command line arguments"""
+ parser = ArgumentParser(
+ description='Unpacks boot.img/recovery.img, extracts the kernel,'
+ 'ramdisk, second bootloader and recovery dtbo')
+ parser.add_argument(
+ '--boot_img',
+ help='path to boot image',
+ type=FileType('rb'),
+ required=True)
+ parser.add_argument('--out', help='path to out binaries', default='out')
+ return parser.parse_args()
+
+
+def main():
+ """parse arguments and unpack boot image"""
+ args = parse_cmdline()
+ create_out_dir(args.out)
+ unpack_bootimage(args)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 94465f4..ba96cc8 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -218,13 +218,20 @@
namespace.vndk.asan.permitted.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%/hw
namespace.vndk.asan.permitted.paths += /system/${LIB}/vndk-sp%VNDK_VER%/hw
+# The "vndk" namespace links to "default" namespace for LLNDK libs and links to
+# "sphal" namespace for vendor libs. The ordering matters. The "default"
+# namespace has higher priority than the "sphal" namespace.
+namespace.vndk.links = default,sphal
+
# When these NDK libs are required inside this namespace, then it is redirected
# to the default namespace. This is possible since their ABI is stable across
# Android releases.
-namespace.vndk.links = default
namespace.vndk.link.default.shared_libs = %LLNDK_LIBRARIES%
namespace.vndk.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
+# Allow VNDK-SP extensions to use vendor libraries
+namespace.vndk.link.sphal.allow_all_shared_libs = true
+
###############################################################################
# Namespace config for vendor processes. In O, no restriction is enforced for
# them. However, in O-MR1, access to /system/${LIB} will not be allowed to