Commit fbc0b24a authored by Mirek Klimos's avatar Mirek Klimos Committed by Facebook Github Bot

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
parent 520148aa
......@@ -21,6 +21,18 @@
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);
......
......@@ -263,24 +263,18 @@ bool ElfFile::init(const char** msg) {
}
}
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;
}
......
......@@ -122,6 +122,14 @@ class ElfFile {
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
......
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment