diff --git a/libunwindstack/Elf.cpp b/libunwindstack/Elf.cpp index 2f5eed9f8..4b93abb43 100644 --- a/libunwindstack/Elf.cpp +++ b/libunwindstack/Elf.cpp @@ -93,9 +93,12 @@ void Elf::Invalidate() { valid_ = false; } -bool Elf::GetSoname(std::string* name) { +std::string Elf::GetSoname() { std::lock_guard guard(lock_); - return valid_ && interface_->GetSoname(name); + if (!valid_) { + return ""; + } + return interface_->GetSoname(); } uint64_t Elf::GetRelPc(uint64_t pc, const MapInfo* map_info) { diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp index c1b98d999..12efb9487 100644 --- a/libunwindstack/ElfInterface.cpp +++ b/libunwindstack/ElfInterface.cpp @@ -374,13 +374,12 @@ void ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) { } template -bool ElfInterface::GetSonameWithTemplate(std::string* soname) { +std::string ElfInterface::GetSonameWithTemplate() { if (soname_type_ == SONAME_INVALID) { - return false; + return ""; } if (soname_type_ == SONAME_VALID) { - *soname = soname_; - return true; + return soname_; } soname_type_ = SONAME_INVALID; @@ -397,7 +396,7 @@ bool ElfInterface::GetSonameWithTemplate(std::string* soname) { if (!memory_->ReadFully(offset, &dyn, sizeof(dyn))) { last_error_.code = ERROR_MEMORY_INVALID; last_error_.address = offset; - return false; + return ""; } if (dyn.d_tag == DT_STRTAB) { @@ -416,17 +415,16 @@ bool ElfInterface::GetSonameWithTemplate(std::string* soname) { if (entry.first == strtab_addr) { soname_offset = entry.second + soname_offset; if (soname_offset >= entry.second + strtab_size) { - return false; + return ""; } if (!memory_->ReadString(soname_offset, &soname_)) { - return false; + return ""; } soname_type_ = SONAME_VALID; - *soname = soname_; - return true; + return soname_; } } - return false; + return ""; } template @@ -653,8 +651,8 @@ template void ElfInterface::ReadSectionHeaders(const Elf template std::string ElfInterface::ReadBuildID(); template std::string ElfInterface::ReadBuildID(); -template bool ElfInterface::GetSonameWithTemplate(std::string*); -template bool ElfInterface::GetSonameWithTemplate(std::string*); +template std::string ElfInterface::GetSonameWithTemplate(); +template std::string ElfInterface::GetSonameWithTemplate(); template bool ElfInterface::GetFunctionNameWithTemplate(uint64_t, std::string*, uint64_t*); diff --git a/libunwindstack/MapInfo.cpp b/libunwindstack/MapInfo.cpp index a38236c60..28373b27f 100644 --- a/libunwindstack/MapInfo.cpp +++ b/libunwindstack/MapInfo.cpp @@ -188,44 +188,57 @@ Memory* MapInfo::CreateMemory(const std::shared_ptr& process_memory) { } Elf* MapInfo::GetElf(const std::shared_ptr& process_memory, ArchEnum expected_arch) { - // Make sure no other thread is trying to add the elf to this map. - std::lock_guard guard(mutex_); + { + // Make sure no other thread is trying to add the elf to this map. + std::lock_guard guard(mutex_); - if (elf.get() != nullptr) { - return elf.get(); - } - - bool locked = false; - if (Elf::CachingEnabled() && !name.empty()) { - Elf::CacheLock(); - locked = true; - if (Elf::CacheGet(this)) { - Elf::CacheUnlock(); + if (elf.get() != nullptr) { return elf.get(); } + + bool locked = false; + if (Elf::CachingEnabled() && !name.empty()) { + Elf::CacheLock(); + locked = true; + if (Elf::CacheGet(this)) { + Elf::CacheUnlock(); + return elf.get(); + } + } + + Memory* memory = CreateMemory(process_memory); + if (locked) { + if (Elf::CacheAfterCreateMemory(this)) { + delete memory; + Elf::CacheUnlock(); + return elf.get(); + } + } + elf.reset(new Elf(memory)); + // If the init fails, keep the elf around as an invalid object so we + // don't try to reinit the object. + elf->Init(); + if (elf->valid() && expected_arch != elf->arch()) { + // Make the elf invalid, mismatch between arch and expected arch. + elf->Invalidate(); + } + + if (locked) { + Elf::CacheAdd(this); + Elf::CacheUnlock(); + } } - Memory* memory = CreateMemory(process_memory); - if (locked) { - if (Elf::CacheAfterCreateMemory(this)) { - delete memory; - Elf::CacheUnlock(); - return elf.get(); + // If there is a read-only map then a read-execute map that represents the + // same elf object, make sure the previous map is using the same elf + // object if it hasn't already been set. + if (prev_map != nullptr && elf_start_offset != offset && prev_map->offset == elf_start_offset && + prev_map->name == name) { + std::lock_guard guard(prev_map->mutex_); + if (prev_map->elf.get() == nullptr) { + prev_map->elf = elf; } } - elf.reset(new Elf(memory)); - // If the init fails, keep the elf around as an invalid object so we - // don't try to reinit the object. - elf->Init(); - if (elf->valid() && expected_arch != elf->arch()) { - // Make the elf invalid, mismatch between arch and expected arch. - elf->Invalidate(); - } - - if (locked) { - Elf::CacheAdd(this); - Elf::CacheUnlock(); - } return elf.get(); } diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp index 2734cf8d3..a1c58ddb3 100644 --- a/libunwindstack/Unwinder.cpp +++ b/libunwindstack/Unwinder.cpp @@ -105,6 +105,12 @@ void Unwinder::FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, uint64_ if (resolve_names_) { frame->map_name = map_info->name; + if (embedded_soname_ && map_info->elf_start_offset != 0 && !frame->map_name.empty()) { + std::string soname = elf->GetSoname(); + if (!soname.empty()) { + frame->map_name += '!' + soname; + } + } } frame->map_elf_start_offset = map_info->elf_start_offset; frame->map_exact_offset = map_info->offset; diff --git a/libunwindstack/include/unwindstack/Elf.h b/libunwindstack/include/unwindstack/Elf.h index 00a249ff6..ac94f101c 100644 --- a/libunwindstack/include/unwindstack/Elf.h +++ b/libunwindstack/include/unwindstack/Elf.h @@ -59,7 +59,7 @@ class Elf { void Invalidate(); - bool GetSoname(std::string* name); + std::string GetSoname(); bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset); diff --git a/libunwindstack/include/unwindstack/ElfInterface.h b/libunwindstack/include/unwindstack/ElfInterface.h index d41bb13e3..dbd917d67 100644 --- a/libunwindstack/include/unwindstack/ElfInterface.h +++ b/libunwindstack/include/unwindstack/ElfInterface.h @@ -56,7 +56,7 @@ class ElfInterface { virtual void InitHeaders(uint64_t load_bias) = 0; - virtual bool GetSoname(std::string* name) = 0; + virtual std::string GetSoname() = 0; virtual bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* offset) = 0; @@ -117,7 +117,7 @@ class ElfInterface { void ReadSectionHeaders(const EhdrType& ehdr); template - bool GetSonameWithTemplate(std::string* soname); + std::string GetSonameWithTemplate(); template bool GetFunctionNameWithTemplate(uint64_t addr, std::string* name, uint64_t* func_offset); @@ -183,9 +183,7 @@ class ElfInterface32 : public ElfInterface { ElfInterface::InitHeadersWithTemplate(load_bias); } - bool GetSoname(std::string* soname) override { - return ElfInterface::GetSonameWithTemplate(soname); - } + std::string GetSoname() override { return ElfInterface::GetSonameWithTemplate(); } bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) override { return ElfInterface::GetFunctionNameWithTemplate(addr, name, func_offset); @@ -215,9 +213,7 @@ class ElfInterface64 : public ElfInterface { ElfInterface::InitHeadersWithTemplate(load_bias); } - bool GetSoname(std::string* soname) override { - return ElfInterface::GetSonameWithTemplate(soname); - } + std::string GetSoname() override { return ElfInterface::GetSonameWithTemplate(); } bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) override { return ElfInterface::GetFunctionNameWithTemplate(addr, name, func_offset); diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h index ddda7fd9f..a0554e2f1 100644 --- a/libunwindstack/include/unwindstack/Unwinder.h +++ b/libunwindstack/include/unwindstack/Unwinder.h @@ -100,6 +100,11 @@ class Unwinder { // set to an empty string and the function offset being set to zero. void SetResolveNames(bool resolve) { resolve_names_ = resolve; } + // Enable/disable soname printing the soname for a map name if the elf is + // embedded in a file. This is enabled by default. + // NOTE: This does nothing unless resolving names is enabled. + void SetEmbeddedSoname(bool embedded_soname) { embedded_soname_ = embedded_soname; } + #if !defined(NO_LIBDEXFILE_SUPPORT) void SetDexFiles(DexFiles* dex_files, ArchEnum arch); #endif @@ -124,6 +129,7 @@ class Unwinder { DexFiles* dex_files_ = nullptr; #endif bool resolve_names_ = true; + bool embedded_soname_ = true; ErrorData last_error_; }; diff --git a/libunwindstack/tests/ElfFake.h b/libunwindstack/tests/ElfFake.h index 946bc3c21..bd3083ce4 100644 --- a/libunwindstack/tests/ElfFake.h +++ b/libunwindstack/tests/ElfFake.h @@ -68,7 +68,7 @@ class ElfInterfaceFake : public ElfInterface { bool Init(uint64_t*) override { return false; } void InitHeaders(uint64_t) override {} - bool GetSoname(std::string*) override { return false; } + std::string GetSoname() override { return fake_soname_; } bool GetFunctionName(uint64_t, std::string*, uint64_t*) override; bool GetGlobalVariable(const std::string&, uint64_t*) override; @@ -83,6 +83,8 @@ class ElfInterfaceFake : public ElfInterface { void FakeSetBuildID(std::string& build_id) { fake_build_id_ = build_id; } void FakeSetBuildID(const char* build_id) { fake_build_id_ = build_id; } + void FakeSetSoname(const char* soname) { fake_soname_ = soname; } + static void FakePushFunctionData(const FunctionData data) { functions_.push_back(data); } static void FakePushStepData(const StepData data) { steps_.push_back(data); } @@ -98,6 +100,7 @@ class ElfInterfaceFake : public ElfInterface { private: std::unordered_map globals_; std::string fake_build_id_; + std::string fake_soname_; static std::deque functions_; static std::deque steps_; diff --git a/libunwindstack/tests/ElfInterfaceTest.cpp b/libunwindstack/tests/ElfInterfaceTest.cpp index 7239749c6..d895863bb 100644 --- a/libunwindstack/tests/ElfInterfaceTest.cpp +++ b/libunwindstack/tests/ElfInterfaceTest.cpp @@ -555,9 +555,7 @@ void ElfInterfaceTest::Soname() { ASSERT_TRUE(elf->Init(&load_bias)); EXPECT_EQ(0U, load_bias); - std::string name; - ASSERT_TRUE(elf->GetSoname(&name)); - ASSERT_STREQ("fake_soname.so", name.c_str()); + ASSERT_EQ("fake_soname.so", elf->GetSoname()); } TEST_F(ElfInterfaceTest, elf32_soname) { @@ -578,8 +576,7 @@ void ElfInterfaceTest::SonameAfterDtNull() { ASSERT_TRUE(elf->Init(&load_bias)); EXPECT_EQ(0U, load_bias); - std::string name; - ASSERT_FALSE(elf->GetSoname(&name)); + ASSERT_EQ("", elf->GetSoname()); } TEST_F(ElfInterfaceTest, elf32_soname_after_dt_null) { @@ -600,8 +597,7 @@ void ElfInterfaceTest::SonameSize() { ASSERT_TRUE(elf->Init(&load_bias)); EXPECT_EQ(0U, load_bias); - std::string name; - ASSERT_FALSE(elf->GetSoname(&name)); + ASSERT_EQ("", elf->GetSoname()); } TEST_F(ElfInterfaceTest, elf32_soname_size) { @@ -624,8 +620,7 @@ void ElfInterfaceTest::SonameMissingMap() { ASSERT_TRUE(elf->Init(&load_bias)); EXPECT_EQ(0U, load_bias); - std::string name; - ASSERT_FALSE(elf->GetSoname(&name)); + ASSERT_EQ("", elf->GetSoname()); } TEST_F(ElfInterfaceTest, elf32_soname_missing_map) { diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp index 1ff23064f..23c9cf860 100644 --- a/libunwindstack/tests/ElfTest.cpp +++ b/libunwindstack/tests/ElfTest.cpp @@ -126,9 +126,9 @@ TEST_F(ElfTest, elf_invalid) { ASSERT_FALSE(elf.valid()); ASSERT_TRUE(elf.interface() == nullptr); - std::string name; - ASSERT_FALSE(elf.GetSoname(&name)); + ASSERT_EQ("", elf.GetSoname()); + std::string name; uint64_t func_offset; ASSERT_FALSE(elf.GetFunctionName(0, &name, &func_offset)); @@ -309,7 +309,7 @@ class ElfInterfaceMock : public ElfInterface { bool Init(uint64_t*) override { return false; } void InitHeaders(uint64_t) override {} - bool GetSoname(std::string*) override { return false; } + std::string GetSoname() override { return ""; } bool GetFunctionName(uint64_t, std::string*, uint64_t*) override { return false; } std::string GetBuildID() override { return ""; } diff --git a/libunwindstack/tests/MapInfoGetElfTest.cpp b/libunwindstack/tests/MapInfoGetElfTest.cpp index d7b848544..d60b8b1af 100644 --- a/libunwindstack/tests/MapInfoGetElfTest.cpp +++ b/libunwindstack/tests/MapInfoGetElfTest.cpp @@ -371,4 +371,35 @@ TEST_F(MapInfoGetElfTest, multiple_thread_get_elf) { } } +// Verify that previous maps don't automatically get the same elf object. +TEST_F(MapInfoGetElfTest, prev_map_elf_not_set) { + MapInfo info1(nullptr, 0x1000, 0x2000, 0, PROT_READ, "/not/present"); + MapInfo info2(&info1, 0x2000, 0x3000, 0, PROT_READ, elf_.path); + + Elf32_Ehdr ehdr; + TestInitEhdr(&ehdr, ELFCLASS32, EM_ARM); + memory_->SetMemory(0x2000, &ehdr, sizeof(ehdr)); + Elf* elf = info2.GetElf(process_memory_, ARCH_ARM); + ASSERT_TRUE(elf != nullptr); + ASSERT_TRUE(elf->valid()); + + ASSERT_NE(elf, info1.GetElf(process_memory_, ARCH_ARM)); +} + +// Verify that a read-only map followed by a read-execute map will result +// in the same elf object in both maps. +TEST_F(MapInfoGetElfTest, read_only_followed_by_read_exec_share_elf) { + MapInfo r_info(nullptr, 0x1000, 0x2000, 0, PROT_READ, elf_.path); + MapInfo rw_info(&r_info, 0x2000, 0x3000, 0x1000, PROT_READ | PROT_EXEC, elf_.path); + + Elf32_Ehdr ehdr; + TestInitEhdr(&ehdr, ELFCLASS32, EM_ARM); + memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr)); + Elf* elf = rw_info.GetElf(process_memory_, ARCH_ARM); + ASSERT_TRUE(elf != nullptr); + ASSERT_TRUE(elf->valid()); + + ASSERT_EQ(elf, r_info.GetElf(process_memory_, ARCH_ARM)); +} + } // namespace unwindstack diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp index 86bc4654c..655579e84 100644 --- a/libunwindstack/tests/UnwindOfflineTest.cpp +++ b/libunwindstack/tests/UnwindOfflineTest.cpp @@ -300,7 +300,7 @@ TEST_F(UnwindOfflineTest, jit_debug_x86) { EXPECT_EQ( " #00 pc 00068fb8 libarttestd.so (art::CauseSegfault()+72)\n" " #01 pc 00067f00 libarttestd.so (Java_Main_unwindInProcess+10032)\n" - " #02 pc 000021a8 137-cfi.odex (offset 0x2000) (boolean Main.unwindInProcess(boolean, int, " + " #02 pc 000021a8 137-cfi.odex (boolean Main.unwindInProcess(boolean, int, " "boolean)+136)\n" " #03 pc 0000fe80 anonymous:ee74c000 (boolean Main.bar(boolean)+64)\n" " #04 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n" @@ -601,7 +601,7 @@ TEST_F(UnwindOfflineTest, jit_debug_arm) { ASSERT_EQ(76U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; EXPECT_EQ( " #00 pc 00018a5e libarttestd.so (Java_Main_unwindInProcess+866)\n" - " #01 pc 0000212d 137-cfi.odex (offset 0x2000) (boolean Main.unwindInProcess(boolean, int, " + " #01 pc 0000212d 137-cfi.odex (boolean Main.unwindInProcess(boolean, int, " "boolean)+92)\n" " #02 pc 00011cb1 anonymous:e2796000 (boolean Main.bar(boolean)+72)\n" " #03 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n" @@ -1312,7 +1312,8 @@ TEST_F(UnwindOfflineTest, shared_lib_in_apk_arm64) { " #02 pc 00000000000008bc vdso.so\n" " #03 pc 00000000000846f4 libc.so (abort+172)\n" " #04 pc 0000000000084ad4 libc.so (__assert2+36)\n" - " #05 pc 000000000003d5b4 ANGLEPrebuilt.apk (offset 0x4000) (ANGLEGetUtilityAPI+56)\n" + " #05 pc 000000000003d5b4 ANGLEPrebuilt.apk!libfeature_support_angle.so (offset 0x4000) " + "(ANGLEGetUtilityAPI+56)\n" " #06 pc 000000000007fe68 libc.so (__libc_init)\n", frame_info); diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp index 2dc511848..504b57a4e 100644 --- a/libunwindstack/tests/UnwinderTest.cpp +++ b/libunwindstack/tests/UnwinderTest.cpp @@ -79,8 +79,13 @@ class UnwinderTest : public ::testing::Test { AddMapInfo(0x33000, 0x34000, 0, PROT_READ | PROT_WRITE, "/fake/compressed.so", elf); elf = new ElfFake(new MemoryFake); - elf->FakeSetInterface(new ElfInterfaceFake(nullptr)); + ElfInterfaceFake* interface = new ElfInterfaceFake(nullptr); + interface->FakeSetSoname("lib_fake.so"); + elf->FakeSetInterface(interface); AddMapInfo(0x43000, 0x44000, 0x1d000, PROT_READ | PROT_WRITE, "/fake/fake.apk", elf); + MapInfo* map_info = maps_->Find(0x43000); + ASSERT_TRUE(map_info != nullptr); + map_info->elf_start_offset = 0x1d000; AddMapInfo(0x53000, 0x54000, 0, PROT_READ | PROT_WRITE, "/fake/fake.oat"); @@ -317,6 +322,36 @@ TEST_F(UnwinderTest, non_zero_map_offset) { ASSERT_EQ(1U, unwinder.NumFrames()); + auto* frame = &unwinder.frames()[0]; + EXPECT_EQ(0U, frame->num); + EXPECT_EQ(0U, frame->rel_pc); + EXPECT_EQ(0x43000U, frame->pc); + EXPECT_EQ(0x10000U, frame->sp); + EXPECT_EQ("Frame0", frame->function_name); + EXPECT_EQ(0U, frame->function_offset); + EXPECT_EQ("/fake/fake.apk!lib_fake.so", frame->map_name); + EXPECT_EQ(0x1d000U, frame->map_elf_start_offset); + EXPECT_EQ(0x1d000U, frame->map_exact_offset); + EXPECT_EQ(0x43000U, frame->map_start); + EXPECT_EQ(0x44000U, frame->map_end); + EXPECT_EQ(0U, frame->map_load_bias); + EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); +} + +TEST_F(UnwinderTest, disable_embedded_soname) { + ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); + + regs_.set_pc(0x43000); + regs_.set_sp(0x10000); + ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); + + Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); + unwinder.SetEmbeddedSoname(false); + unwinder.Unwind(); + EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + + ASSERT_EQ(1U, unwinder.NumFrames()); + auto* frame = &unwinder.frames()[0]; EXPECT_EQ(0U, frame->num); EXPECT_EQ(0U, frame->rel_pc); @@ -325,7 +360,7 @@ TEST_F(UnwinderTest, non_zero_map_offset) { EXPECT_EQ("Frame0", frame->function_name); EXPECT_EQ(0U, frame->function_offset); EXPECT_EQ("/fake/fake.apk", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); + EXPECT_EQ(0x1d000U, frame->map_elf_start_offset); EXPECT_EQ(0x1d000U, frame->map_exact_offset); EXPECT_EQ(0x43000U, frame->map_start); EXPECT_EQ(0x44000U, frame->map_end); @@ -813,8 +848,8 @@ TEST_F(UnwinderTest, map_ignore_suffixes) { EXPECT_EQ(0x10010U, frame->sp); EXPECT_EQ("Frame1", frame->function_name); EXPECT_EQ(1U, frame->function_offset); - EXPECT_EQ("/fake/fake.apk", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); + EXPECT_EQ("/fake/fake.apk!lib_fake.so", frame->map_name); + EXPECT_EQ(0x1d000U, frame->map_elf_start_offset); EXPECT_EQ(0x1d000U, frame->map_exact_offset); EXPECT_EQ(0x43000U, frame->map_start); EXPECT_EQ(0x44000U, frame->map_end); diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt b/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt index 3cd9d408f..4043122de 100644 --- a/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt +++ b/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt @@ -1,5 +1,6 @@ ab0d3000-ab0d8000 r-xp 0 00:00 0 dalvikvm32 dfe4e000-dfe7b000 r-xp 0 00:00 0 libarttestd.so +e0445000-e0447000 r--p 0 00:00 0 137-cfi.odex e0447000-e0448000 r-xp 2000 00:00 0 137-cfi.odex e2796000-e4796000 r-xp 0 00:00 0 anonymous:e2796000 e648e000-e690f000 r-xp 0 00:00 0 libart.so diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/maps.txt b/libunwindstack/tests/files/offline/jit_debug_x86/maps.txt index a8d215c2a..f255a44e0 100644 --- a/libunwindstack/tests/files/offline/jit_debug_x86/maps.txt +++ b/libunwindstack/tests/files/offline/jit_debug_x86/maps.txt @@ -1,5 +1,6 @@ 56573000-56577000 r-xp 0 00:00 0 dalvikvm32 eb833000-eb8cc000 r-xp 0 00:00 0 libarttestd.so +ec604000-ec606000 r--p 0 00:00 0 137-cfi.odex ec606000-ec607000 r-xp 2000 00:00 0 137-cfi.odex ee74c000-f074c000 r-xp 0 00:00 0 anonymous:ee74c000 f6be1000-f732b000 r-xp 0 00:00 0 libartd.so diff --git a/libunwindstack/tools/unwind_info.cpp b/libunwindstack/tools/unwind_info.cpp index 19982d8f6..92e5c0af3 100644 --- a/libunwindstack/tools/unwind_info.cpp +++ b/libunwindstack/tools/unwind_info.cpp @@ -118,8 +118,8 @@ int GetElfInfo(const char* file, uint64_t offset) { return 1; } - std::string soname; - if (elf.GetSoname(&soname)) { + std::string soname(elf.GetSoname()); + if (!soname.empty()) { printf("Soname: %s\n", soname.c_str()); } diff --git a/libunwindstack/tools/unwind_reg_info.cpp b/libunwindstack/tools/unwind_reg_info.cpp index 4b6f49ac3..b77a86bbf 100644 --- a/libunwindstack/tools/unwind_reg_info.cpp +++ b/libunwindstack/tools/unwind_reg_info.cpp @@ -185,8 +185,8 @@ int GetInfo(const char* file, uint64_t pc) { return 1; } - std::string soname; - if (elf.GetSoname(&soname)) { + std::string soname(elf.GetSoname()); + if (!soname.empty()) { printf("Soname: %s\n\n", soname.c_str()); } diff --git a/libunwindstack/tools/unwind_symbols.cpp b/libunwindstack/tools/unwind_symbols.cpp index 91284307e..b0a4dd07a 100644 --- a/libunwindstack/tools/unwind_symbols.cpp +++ b/libunwindstack/tools/unwind_symbols.cpp @@ -71,8 +71,8 @@ int main(int argc, char** argv) { return 1; } - std::string soname; - if (elf.GetSoname(&soname)) { + std::string soname(elf.GetSoname()); + if (!soname.empty()) { printf("Soname: %s\n\n", soname.c_str()); }