namespace folly {
namespace symbolizer {
+template <class Fn>
+const ElfPhdr* ElfFile::iterateProgramHeaders(Fn fn) const {
+ const ElfPhdr* ptr = &at<ElfPhdr>(elfHeader().e_phoff);
+ for (size_t i = 0; i < elfHeader().e_phnum; i++, ptr++) {
+ if (fn(*ptr)) {
+ return ptr;
+ }
+ }
+
+ return nullptr;
+}
+
template <class Fn>
const ElfShdr* ElfFile::iterateSections(Fn fn) const {
const ElfShdr* ptr = &at<ElfShdr>(elfHeader().e_shoff);
}
}
- const ElfPhdr* programHeader = &at<ElfPhdr>(elfHeader.e_phoff);
- bool foundBase = false;
- for (size_t i = 0; i < elfHeader.e_phnum; programHeader++, i++) {
- // Program headers are sorted by load address, so the first PT_LOAD
- // header gives us the base address.
- if (programHeader->p_type == PT_LOAD) {
- baseAddress_ = programHeader->p_vaddr;
- foundBase = true;
- break;
- }
- }
+ // Program headers are sorted by load address, so the first PT_LOAD
+ // header gives us the base address.
+ const ElfPhdr* programHeader =
+ iterateProgramHeaders([](auto& h) { return h.p_type == PT_LOAD; });
- if (!foundBase) {
+ if (!programHeader) {
if (msg) {
*msg = "could not find base address";
}
return false;
}
+ baseAddress_ = programHeader->p_vaddr;
return true;
}
template <class Fn>
const char* iterateStrings(const ElfShdr& stringTable, Fn fn) const;
+ /**
+ * Iterate over program headers as long as fn(section) returns false.
+ * Returns a pointer to the current ("found") section when fn returned
+ * true, or nullptr if fn returned false for all sections.
+ */
+ template <class Fn>
+ const ElfPhdr* iterateProgramHeaders(Fn fn) const;
+
/**
* Iterate over all sections for as long as fn(section) returns false.
* Returns a pointer to the current ("found") section when fn returned
EXPECT_STREQ(kStringValue, str);
}
+TEST_F(ElfTest, iterateProgramHeaders) {
+ auto phdr = elfFile_.iterateProgramHeaders(
+ [](auto& h) { return h.p_type == PT_LOAD; });
+ EXPECT_NE(nullptr, phdr);
+ EXPECT_GE(phdr->p_filesz, 0);
+}
+
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
gflags::ParseCommandLineFlags(&argc, &argv, true);