From: Mirek Klimos Date: Wed, 16 Aug 2017 04:04:27 +0000 (-0700) Subject: folly::ElfFile - add support to iterate over program headers X-Git-Tag: v2017.08.21.00~12 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=fbc0b24a622addf974413b5288479f2884e6bf9c;p=folly.git folly::ElfFile - add support to iterate over program headers Summary: Adding iterateProgramHeaders, similar to iterateSections, just iterates over program headers instead of section headers. I want this to get the size of the first PT_LOAD header. Differential Revision: D5602575 fbshipit-source-id: f73989cade20214f884571c1099761ecaa4841f7 --- diff --git a/folly/experimental/symbolizer/Elf-inl.h b/folly/experimental/symbolizer/Elf-inl.h index 1679f5c7..bd9b0a40 100644 --- a/folly/experimental/symbolizer/Elf-inl.h +++ b/folly/experimental/symbolizer/Elf-inl.h @@ -21,6 +21,18 @@ namespace folly { namespace symbolizer { +template +const ElfPhdr* ElfFile::iterateProgramHeaders(Fn fn) const { + const ElfPhdr* ptr = &at(elfHeader().e_phoff); + for (size_t i = 0; i < elfHeader().e_phnum; i++, ptr++) { + if (fn(*ptr)) { + return ptr; + } + } + + return nullptr; +} + template const ElfShdr* ElfFile::iterateSections(Fn fn) const { const ElfShdr* ptr = &at(elfHeader().e_shoff); diff --git a/folly/experimental/symbolizer/Elf.cpp b/folly/experimental/symbolizer/Elf.cpp index 038bea7a..a0dfe9ce 100644 --- a/folly/experimental/symbolizer/Elf.cpp +++ b/folly/experimental/symbolizer/Elf.cpp @@ -263,24 +263,18 @@ bool ElfFile::init(const char** msg) { } } - const ElfPhdr* programHeader = &at(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; } diff --git a/folly/experimental/symbolizer/Elf.h b/folly/experimental/symbolizer/Elf.h index 48b5f8fb..2bf37a9d 100644 --- a/folly/experimental/symbolizer/Elf.h +++ b/folly/experimental/symbolizer/Elf.h @@ -122,6 +122,14 @@ class ElfFile { template 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 + 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 diff --git a/folly/experimental/symbolizer/test/ElfTests.cpp b/folly/experimental/symbolizer/test/ElfTests.cpp index f27fef41..51d8531d 100644 --- a/folly/experimental/symbolizer/test/ElfTests.cpp +++ b/folly/experimental/symbolizer/test/ElfTests.cpp @@ -52,6 +52,13 @@ TEST_F(ElfTest, PointerValue) { 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);