From 96e966eb3d5cfd83015e1c6519825a59d2b93d72 Mon Sep 17 00:00:00 2001 From: Florian Mayer Date: Thu, 13 Aug 2020 09:41:29 +0100 Subject: [PATCH] Set warning for dex pc not in map. This way, the profilers will know they have to reparse maps. Bug: 163130539 Test: Verified updated unit tests pass. Change-Id: I88a801ffdda12811eab5e4833dcf472f2d75c09a --- libunwindstack/Unwinder.cpp | 3 +- libunwindstack/include/unwindstack/Error.h | 7 +++++ libunwindstack/include/unwindstack/Unwinder.h | 2 ++ libunwindstack/tests/UnwinderTest.cpp | 28 +++++++++++++++++++ 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp index 2d867cd5e..b904632ef 100644 --- a/libunwindstack/Unwinder.cpp +++ b/libunwindstack/Unwinder.cpp @@ -75,7 +75,7 @@ void Unwinder::FillInDexFrame() { frame->rel_pc = dex_pc - info->start; } else { frame->rel_pc = dex_pc; - return; + warnings_ |= WARNING_DEX_PC_NOT_IN_MAP; } if (!resolve_names_) { @@ -142,6 +142,7 @@ static bool ShouldStop(const std::vector* map_suffixes_to_ignore, void Unwinder::Unwind(const std::vector* initial_map_names_to_skip, const std::vector* map_suffixes_to_ignore) { frames_.clear(); + warnings_ = WARNING_NONE; last_error_.code = ERROR_NONE; last_error_.address = 0; elf_from_memory_not_file_ = false; diff --git a/libunwindstack/include/unwindstack/Error.h b/libunwindstack/include/unwindstack/Error.h index 72ec4547f..66fefe76d 100644 --- a/libunwindstack/include/unwindstack/Error.h +++ b/libunwindstack/include/unwindstack/Error.h @@ -21,6 +21,13 @@ namespace unwindstack { +// A bit map of warnings, multiple warnings can be set at the same time. +enum WarningCode : uint64_t { + WARNING_NONE = 0, + WARNING_DEX_PC_NOT_IN_MAP = 0x1, // A dex pc was found, but it doesn't exist + // in any valid map. +}; + enum ErrorCode : uint8_t { ERROR_NONE, // No error. ERROR_MEMORY_INVALID, // Memory read failed. diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h index 4d49f236a..a974b6349 100644 --- a/libunwindstack/include/unwindstack/Unwinder.h +++ b/libunwindstack/include/unwindstack/Unwinder.h @@ -113,6 +113,7 @@ class Unwinder { ErrorCode LastErrorCode() { return last_error_.code; } uint64_t LastErrorAddress() { return last_error_.address; } + uint64_t warnings() { return warnings_; } // Builds a frame for symbolization using the maps from this unwinder. The // constructed frame contains just enough information to be used to symbolize @@ -141,6 +142,7 @@ class Unwinder { // file. This is only true if there is an actual file backing up the elf. bool elf_from_memory_not_file_ = false; ErrorData last_error_; + uint64_t warnings_; }; class UnwinderFromPid : public Unwinder { diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp index dd33aa9d7..d10af2f0b 100644 --- a/libunwindstack/tests/UnwinderTest.cpp +++ b/libunwindstack/tests/UnwinderTest.cpp @@ -168,6 +168,7 @@ TEST_F(UnwinderTest, multiple_frames) { Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(3U, unwinder.NumFrames()); @@ -233,6 +234,7 @@ TEST_F(UnwinderTest, multiple_frames_dont_resolve_names) { unwinder.SetResolveNames(false); unwinder.Unwind(); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(3U, unwinder.NumFrames()); @@ -293,6 +295,7 @@ TEST_F(UnwinderTest, non_zero_load_bias) { Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(1U, unwinder.NumFrames()); @@ -323,6 +326,7 @@ TEST_F(UnwinderTest, non_zero_elf_offset) { Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(1U, unwinder.NumFrames()); @@ -353,6 +357,7 @@ TEST_F(UnwinderTest, non_zero_map_offset) { Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(1U, unwinder.NumFrames()); @@ -384,6 +389,7 @@ TEST_F(UnwinderTest, disable_embedded_soname) { unwinder.SetEmbeddedSoname(false); unwinder.Unwind(); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(1U, unwinder.NumFrames()); @@ -421,6 +427,7 @@ TEST_F(UnwinderTest, no_frames_after_finished) { Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(1U, unwinder.NumFrames()); @@ -454,6 +461,7 @@ TEST_F(UnwinderTest, max_frames) { Unwinder unwinder(20, maps_.get(), ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_MAX_FRAMES_EXCEEDED, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(20U, unwinder.NumFrames()); @@ -497,6 +505,7 @@ TEST_F(UnwinderTest, verify_frames_skipped) { std::vector skip_libs{"libunwind.so", "libanother.so"}; unwinder.Unwind(&skip_libs); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(3U, unwinder.NumFrames()); @@ -559,6 +568,7 @@ TEST_F(UnwinderTest, sp_not_in_map) { Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(2U, unwinder.NumFrames()); @@ -607,6 +617,7 @@ TEST_F(UnwinderTest, pc_in_device_stops_unwind) { Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(1U, unwinder.NumFrames()); @@ -627,6 +638,7 @@ TEST_F(UnwinderTest, sp_in_device_stops_unwind) { Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(1U, unwinder.NumFrames()); @@ -642,6 +654,7 @@ TEST_F(UnwinderTest, pc_without_map) { Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_INVALID_MAP, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(1U, unwinder.NumFrames()); @@ -679,6 +692,7 @@ TEST_F(UnwinderTest, speculative_frame) { Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(3U, unwinder.NumFrames()); @@ -745,6 +759,7 @@ TEST_F(UnwinderTest, speculative_frame_removed) { Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_INVALID_MAP, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(2U, unwinder.NumFrames()); @@ -795,6 +810,7 @@ TEST_F(UnwinderTest, speculative_frame_not_removed_pc_bad) { Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(2U, unwinder.NumFrames()); @@ -843,6 +859,7 @@ TEST_F(UnwinderTest, speculative_frame_check_with_no_frames) { std::vector skip_names{"libanother.so"}; unwinder.Unwind(&skip_names); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(0U, unwinder.NumFrames()); @@ -866,6 +883,7 @@ TEST_F(UnwinderTest, map_ignore_suffixes) { std::vector suffixes{"oat"}; unwinder.Unwind(nullptr, &suffixes); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(2U, unwinder.NumFrames()); @@ -925,6 +943,7 @@ TEST_F(UnwinderTest, sp_pc_do_not_change) { Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_REPEATED_FRAME, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(3U, unwinder.NumFrames()); @@ -984,6 +1003,7 @@ TEST_F(UnwinderTest, dex_pc_in_map) { Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(2U, unwinder.NumFrames()); @@ -1028,6 +1048,7 @@ TEST_F(UnwinderTest, dex_pc_in_map_non_zero_offset) { Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(2U, unwinder.NumFrames()); @@ -1072,6 +1093,7 @@ TEST_F(UnwinderTest, dex_pc_not_in_map) { Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_DEX_PC_NOT_IN_MAP, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(2U, unwinder.NumFrames()); @@ -1119,6 +1141,7 @@ TEST_F(UnwinderTest, dex_pc_multiple_frames) { Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(3U, unwinder.NumFrames()); @@ -1178,6 +1201,7 @@ TEST_F(UnwinderTest, dex_pc_max_frames) { Unwinder unwinder(1, maps_.get(), ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_MAX_FRAMES_EXCEEDED, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(1U, unwinder.NumFrames()); @@ -1208,6 +1232,7 @@ TEST_F(UnwinderTest, elf_from_memory_not_file) { Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_TRUE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(1U, unwinder.NumFrames()); @@ -1238,6 +1263,7 @@ TEST_F(UnwinderTest, elf_from_memory_but_no_valid_file_with_bracket) { Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(1U, unwinder.NumFrames()); @@ -1268,6 +1294,7 @@ TEST_F(UnwinderTest, elf_from_memory_but_empty_filename) { Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(1U, unwinder.NumFrames()); @@ -1298,6 +1325,7 @@ TEST_F(UnwinderTest, elf_from_memory_but_from_memfd) { Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + EXPECT_EQ(WARNING_NONE, unwinder.warnings()); EXPECT_FALSE(unwinder.elf_from_memory_not_file()); ASSERT_EQ(1U, unwinder.NumFrames());