summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Srbecky <dsrbecky@google.com>2021-05-13 23:46:18 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2021-05-13 23:46:18 +0000
commit67889d84f68c35575d083b85c4f894bf16ec5ec8 (patch)
treeccc0290608ce6e174caa46343e2ac214c628f85a
parent3fb6f21d3404125d8a32ba1110a340af14eee1ac (diff)
parent0f9a7e4f40c9e61423572a35e3938f47b09a6fbb (diff)
downloadunwinding-67889d84f68c35575d083b85c4f894bf16ec5ec8.tar.gz
Fix symbol look for ART's function end-marker. am: 2edcc18349 am: 2867719610 am: 0f9a7e4f40
Original change: https://android-review.googlesource.com/c/platform/system/unwinding/+/1706751 Change-Id: Ice43baf64ad9420aa6bed8122f307ee9196f2e37
-rw-r--r--libunwindstack/Symbols.cpp12
-rw-r--r--libunwindstack/tests/SymbolsTest.cpp32
2 files changed, 39 insertions, 5 deletions
diff --git a/libunwindstack/Symbols.cpp b/libunwindstack/Symbols.cpp
index 26f893e..499cc31 100644
--- a/libunwindstack/Symbols.cpp
+++ b/libunwindstack/Symbols.cpp
@@ -70,13 +70,15 @@ Symbols::Info* Symbols::BinarySearch(uint64_t addr, Memory* elf_memory, uint64_t
if (!elf_memory->ReadFully(offset_ + symbol_index * entry_size_, &sym, sizeof(sym))) {
return nullptr;
}
- Info info{.size = static_cast<uint32_t>(sym.st_size), .index = current};
- it = symbols_.emplace(sym.st_value + sym.st_size, info).first;
+ // There shouldn't be multiple symbols with same end address, but in case there are,
+ // overwrite the cache with the last entry, so that 'sym' and 'info' are consistent.
+ Info& info = symbols_[sym.st_value + sym.st_size];
+ info = {.size = static_cast<uint32_t>(sym.st_size), .index = current};
if (addr < sym.st_value) {
last = current;
} else if (addr < sym.st_value + sym.st_size) {
*func_offset = addr - sym.st_value;
- return &it->second;
+ return &info;
} else {
first = current + 1;
}
@@ -104,7 +106,9 @@ void Symbols::BuildRemapTable(Memory* elf_memory) {
SymType sym;
memcpy(&sym, &buffer[offset], sizeof(SymType)); // Copy to ensure alignment.
addrs.push_back(sym.st_value); // Always insert so it is indexable by symbol index.
- if (IsFunc(&sym)) {
+ // NB: It is important to filter our zero-sized symbols since otherwise we can get
+ // duplicate end addresses in the table (e.g. if there is custom "end" symbol marker).
+ if (IsFunc(&sym) && sym.st_size != 0) {
remap_->push_back(symbol_idx); // Indices of function symbols only.
}
}
diff --git a/libunwindstack/tests/SymbolsTest.cpp b/libunwindstack/tests/SymbolsTest.cpp
index bae4e28..89147a2 100644
--- a/libunwindstack/tests/SymbolsTest.cpp
+++ b/libunwindstack/tests/SymbolsTest.cpp
@@ -307,6 +307,36 @@ TYPED_TEST_P(SymbolsTest, symtab_read_cached) {
ASSERT_EQ(3U, func_offset);
}
+TYPED_TEST_P(SymbolsTest, symtab_end_marker) {
+ Symbols symbols(0x1000, 3 * sizeof(TypeParam), sizeof(TypeParam), 0xa000, 0x1000);
+
+ TypeParam sym;
+ uint64_t offset = 0x1000;
+
+ // Add normal symbol function: Let's say this could be symbol from hand written assembly.
+ this->InitSym(&sym, 0x1000, 0x500, 0x100);
+ this->memory_.SetMemory(offset, &sym, sizeof(sym));
+ offset += sizeof(sym);
+
+ // And zero-sized symbol: A programmer might do that to label the end of assembly method.
+ // This might be a challenge for booking since both symbols end at the same address.
+ this->InitSym(&sym, 0x1500, 0x000, 0x200);
+ this->memory_.SetMemory(offset, &sym, sizeof(sym));
+ offset += sizeof(sym);
+
+ std::string fake_name;
+ fake_name = "entry";
+ this->memory_.SetMemory(0xa100, fake_name.c_str(), fake_name.size() + 1);
+ fake_name = "entry_end";
+ this->memory_.SetMemory(0xa200, fake_name.c_str(), fake_name.size() + 1);
+
+ SharedString name;
+ uint64_t func_offset;
+ ASSERT_TRUE(symbols.GetName<TypeParam>(0x1250, &this->memory_, &name, &func_offset));
+ ASSERT_EQ("entry", name);
+ ASSERT_EQ(0x250U, func_offset);
+}
+
TYPED_TEST_P(SymbolsTest, get_global) {
uint64_t start_offset = 0x1000;
uint64_t str_offset = 0xa000;
@@ -377,7 +407,7 @@ TYPED_TEST_P(SymbolsTest, get_global) {
REGISTER_TYPED_TEST_SUITE_P(SymbolsTest, function_bounds_check, no_symbol, multiple_entries,
multiple_entries_nonstandard_size, symtab_value_out_of_bounds,
- symtab_read_cached, get_global);
+ symtab_read_cached, get_global, symtab_end_marker);
typedef ::testing::Types<Elf32_Sym, Elf64_Sym> SymbolsTestTypes;
INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, SymbolsTest, SymbolsTestTypes);