Merge "Add support for displaying soname in an apk."
This commit is contained in:
commit
4886a5bd59
18 changed files with 169 additions and 80 deletions
|
@ -93,9 +93,12 @@ void Elf::Invalidate() {
|
|||
valid_ = false;
|
||||
}
|
||||
|
||||
bool Elf::GetSoname(std::string* name) {
|
||||
std::string Elf::GetSoname() {
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
return valid_ && interface_->GetSoname(name);
|
||||
if (!valid_) {
|
||||
return "";
|
||||
}
|
||||
return interface_->GetSoname();
|
||||
}
|
||||
|
||||
uint64_t Elf::GetRelPc(uint64_t pc, const MapInfo* map_info) {
|
||||
|
|
|
@ -374,13 +374,12 @@ void ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) {
|
|||
}
|
||||
|
||||
template <typename DynType>
|
||||
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 <typename SymType>
|
||||
|
@ -653,8 +651,8 @@ template void ElfInterface::ReadSectionHeaders<Elf64_Ehdr, Elf64_Shdr>(const Elf
|
|||
template std::string ElfInterface::ReadBuildID<Elf32_Nhdr>();
|
||||
template std::string ElfInterface::ReadBuildID<Elf64_Nhdr>();
|
||||
|
||||
template bool ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(std::string*);
|
||||
template bool ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(std::string*);
|
||||
template std::string ElfInterface::GetSonameWithTemplate<Elf32_Dyn>();
|
||||
template std::string ElfInterface::GetSonameWithTemplate<Elf64_Dyn>();
|
||||
|
||||
template bool ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(uint64_t, std::string*,
|
||||
uint64_t*);
|
||||
|
|
|
@ -188,44 +188,57 @@ Memory* MapInfo::CreateMemory(const std::shared_ptr<Memory>& process_memory) {
|
|||
}
|
||||
|
||||
Elf* MapInfo::GetElf(const std::shared_ptr<Memory>& process_memory, ArchEnum expected_arch) {
|
||||
// Make sure no other thread is trying to add the elf to this map.
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
{
|
||||
// Make sure no other thread is trying to add the elf to this map.
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
|
||||
if (elf.get() != nullptr) {
|
||||
return elf.get();
|
||||
}
|
||||
|
||||
bool locked = false;
|
||||
if (Elf::CachingEnabled() && !name.empty()) {
|
||||
Elf::CacheLock();
|
||||
locked = true;
|
||||
if (Elf::CacheGet(this)) {
|
||||
Elf::CacheUnlock();
|
||||
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<std::mutex> 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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 <typename DynType>
|
||||
bool GetSonameWithTemplate(std::string* soname);
|
||||
std::string GetSonameWithTemplate();
|
||||
|
||||
template <typename SymType>
|
||||
bool GetFunctionNameWithTemplate(uint64_t addr, std::string* name, uint64_t* func_offset);
|
||||
|
@ -183,9 +183,7 @@ class ElfInterface32 : public ElfInterface {
|
|||
ElfInterface::InitHeadersWithTemplate<uint32_t>(load_bias);
|
||||
}
|
||||
|
||||
bool GetSoname(std::string* soname) override {
|
||||
return ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(soname);
|
||||
}
|
||||
std::string GetSoname() override { return ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(); }
|
||||
|
||||
bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) override {
|
||||
return ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(addr, name, func_offset);
|
||||
|
@ -215,9 +213,7 @@ class ElfInterface64 : public ElfInterface {
|
|||
ElfInterface::InitHeadersWithTemplate<uint64_t>(load_bias);
|
||||
}
|
||||
|
||||
bool GetSoname(std::string* soname) override {
|
||||
return ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(soname);
|
||||
}
|
||||
std::string GetSoname() override { return ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(); }
|
||||
|
||||
bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) override {
|
||||
return ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(addr, name, func_offset);
|
||||
|
|
|
@ -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_;
|
||||
};
|
||||
|
||||
|
|
|
@ -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<std::string, uint64_t> globals_;
|
||||
std::string fake_build_id_;
|
||||
std::string fake_soname_;
|
||||
|
||||
static std::deque<FunctionData> functions_;
|
||||
static std::deque<StepData> steps_;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 ""; }
|
||||
|
||||
|
|
|
@ -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<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
|
||||
memory_->SetMemory(0x2000, &ehdr, sizeof(ehdr));
|
||||
Elf* elf = info2.GetElf(process_memory_, ARCH_ARM);
|
||||
ASSERT_TRUE(elf != nullptr);
|
||||
ASSERT_TRUE(elf->valid());
|
||||
|
||||
ASSERT_NE(elf, info1.GetElf(process_memory_, ARCH_ARM));
|
||||
}
|
||||
|
||||
// Verify that a read-only map followed by a read-execute map will result
|
||||
// in the same elf object in both maps.
|
||||
TEST_F(MapInfoGetElfTest, read_only_followed_by_read_exec_share_elf) {
|
||||
MapInfo r_info(nullptr, 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<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
|
||||
memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr));
|
||||
Elf* elf = rw_info.GetElf(process_memory_, ARCH_ARM);
|
||||
ASSERT_TRUE(elf != nullptr);
|
||||
ASSERT_TRUE(elf->valid());
|
||||
|
||||
ASSERT_EQ(elf, r_info.GetElf(process_memory_, ARCH_ARM));
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue