namespace folly {
namespace symbolizer {
+using ElfAddr = ElfW(Addr);
+using ElfEhdr = ElfW(Ehdr);
+using ElfOff = ElfW(Off);
+using ElfPhdr = ElfW(Phdr);
+using ElfShdr = ElfW(Shdr);
+using ElfSym = ElfW(Sym);
+
/**
* ELF file parser.
*
ElfFile() noexcept;
// Note: may throw, call openNoThrow() explicitly if you don't want to throw
- explicit ElfFile(const char* name, bool readOnly=true);
+ explicit ElfFile(const char* name, bool readOnly = true);
// Open the ELF file.
// Returns 0 on success, kSystemError (guaranteed to be -1) (and sets errno)
kInvalidElfFile = -2,
};
// Open the ELF file. Does not throw on error.
- int openNoThrow(const char* name, bool readOnly=true,
- const char** msg=nullptr) noexcept;
+ int openNoThrow(
+ const char* name,
+ bool readOnly = true,
+ const char** msg = nullptr) noexcept;
// Like openNoThrow, but follow .gnu_debuglink if present
- int openAndFollow(const char* name, bool readOnly=true,
- const char** msg=nullptr) noexcept;
+ int openAndFollow(
+ const char* name,
+ bool readOnly = true,
+ const char** msg = nullptr) noexcept;
// Open the ELF file. Throws on error.
- void open(const char* name, bool readOnly=true);
+ void open(const char* name, bool readOnly = true);
~ElfFile();
ElfFile& operator=(ElfFile&& other);
/** Retrieve the ELF header */
- const ElfW(Ehdr)& elfHeader() const {
- return at<ElfW(Ehdr)>(0);
+ const ElfEhdr& elfHeader() const {
+ return at<ElfEhdr>(0);
}
/**
}
/** Find a section given its name */
- const ElfW(Shdr)* getSectionByName(const char* name) const;
+ const ElfShdr* getSectionByName(const char* name) const;
/** Find a section given its index in the section header table */
- const ElfW(Shdr)* getSectionByIndex(size_t idx) const;
+ const ElfShdr* getSectionByIndex(size_t idx) const;
/** Retrieve the name of a section */
- const char* getSectionName(const ElfW(Shdr)& section) const;
+ const char* getSectionName(const ElfShdr& section) const;
/** Get the actual section body */
- folly::StringPiece getSectionBody(const ElfW(Shdr)& section) const;
+ folly::StringPiece getSectionBody(const ElfShdr& section) const;
/** Retrieve a string from a string table section */
- const char* getString(const ElfW(Shdr)& stringTable, size_t offset) const;
+ const char* getString(const ElfShdr& stringTable, size_t offset) const;
/**
* Iterate over all strings in a string table section for as long as
* if fn returned false for all strings in the table.
*/
template <class Fn>
- const char* iterateStrings(const ElfW(Shdr)& stringTable, Fn fn) const;
+ const char* iterateStrings(const ElfShdr& stringTable, Fn fn) const;
/**
* Iterate over all sections for as long as fn(section) returns false.
* true, or nullptr if fn returned false for all sections.
*/
template <class Fn>
- const ElfW(Shdr)* iterateSections(Fn fn) const;
+ const ElfShdr* iterateSections(Fn fn) const;
/**
* Iterate over all sections with a given type. Similar to
* iterateSections(), but filtered only for sections with the given type.
*/
template <class Fn>
- const ElfW(Shdr)* iterateSectionsWithType(uint32_t type, Fn fn) const;
+ const ElfShdr* iterateSectionsWithType(uint32_t type, Fn fn) const;
/**
* Iterate over all symbols witin a given section.
* or nullptr if fn returned false for all symbols.
*/
template <class Fn>
- const ElfW(Sym)* iterateSymbols(const ElfW(Shdr)& section, Fn fn) const;
+ const ElfSym* iterateSymbols(const ElfShdr& section, Fn fn) const;
template <class Fn>
- const ElfW(Sym)* iterateSymbolsWithType(const ElfW(Shdr)& section,
- uint32_t type, Fn fn) const;
+ const ElfSym*
+ iterateSymbolsWithType(const ElfShdr& section, uint32_t type, Fn fn) const;
/**
* Find symbol definition by address.
*
* Returns {nullptr, nullptr} if not found.
*/
- typedef std::pair<const ElfW(Shdr)*, const ElfW(Sym)*> Symbol;
+ typedef std::pair<const ElfShdr*, const ElfSym*> Symbol;
Symbol getDefinitionByAddress(uintptr_t address) const;
/**
* Get the value of a symbol.
*/
template <class T>
- const T& getSymbolValue(const ElfW(Sym)* symbol) const {
- const ElfW(Shdr)* section = getSectionByIndex(symbol->st_shndx);
+ const T& getSymbolValue(const ElfSym* symbol) const {
+ const ElfShdr* section = getSectionByIndex(symbol->st_shndx);
FOLLY_SAFE_CHECK(section, "Symbol's section index is invalid");
return valueAt<T>(*section, symbol->st_value);
* a char* symbol, you'd do something like this:
*
* auto sym = getSymbolByName("someGlobalValue");
- * auto addr = getSymbolValue<ElfW(Addr)>(sym.second);
+ * auto addr = getSymbolValue<ElfAddr>(sym.second);
* const char* str = &getSymbolValue<const char>(addr);
*/
template <class T>
- const T& getAddressValue(const ElfW(Addr) addr) const {
- const ElfW(Shdr)* section = getSectionContainingAddress(addr);
+ const T& getAddressValue(const ElfAddr addr) const {
+ const ElfShdr* section = getSectionContainingAddress(addr);
FOLLY_SAFE_CHECK(section, "Address does not refer to existing section");
return valueAt<T>(*section, addr);
const char* getSymbolName(Symbol symbol) const;
/** Find the section containing the given address */
- const ElfW(Shdr)* getSectionContainingAddress(ElfW(Addr) addr) const;
+ const ElfShdr* getSectionContainingAddress(ElfAddr addr) const;
private:
bool init(const char** msg);
ElfFile(const ElfFile&) = delete;
ElfFile& operator=(const ElfFile&) = delete;
- void validateStringTable(const ElfW(Shdr)& stringTable) const;
+ void validateStringTable(const ElfShdr& stringTable) const;
template <class T>
- const typename std::enable_if<std::is_pod<T>::value, T>::type&
- at(ElfW(Off) offset) const {
- FOLLY_SAFE_CHECK(offset + sizeof(T) <= length_,
- "Offset is not contained within our mmapped file");
+ const typename std::enable_if<std::is_pod<T>::value, T>::type& at(
+ ElfOff offset) const {
+ FOLLY_SAFE_CHECK(
+ offset + sizeof(T) <= length_,
+ "Offset is not contained within our mmapped file");
return *reinterpret_cast<T*>(file_ + offset);
}
template <class T>
- const T& valueAt(const ElfW(Shdr)& section, const ElfW(Addr) addr) const {
+ const T& valueAt(const ElfShdr& section, const ElfAddr addr) const {
// For exectuables and shared objects, st_value holds a virtual address
// that refers to the memory owned by sections. Since we didn't map the
// sections into the addresses that they're expecting (sh_addr), but
"Only exectuables and shared objects are supported");
FOLLY_SAFE_CHECK(
addr >= section.sh_addr &&
- (addr + sizeof(T)) <= (section.sh_addr + section.sh_size),
+ (addr + sizeof(T)) <= (section.sh_addr + section.sh_size),
"Address is not contained within the provided segment");
return at<T>(section.sh_offset + (addr - section.sh_addr));
}
int fd_;
- char* file_; // mmap() location
- size_t length_; // mmap() length
+ char* file_; // mmap() location
+ size_t length_; // mmap() length
uintptr_t baseAddress_;
};
-} // namespace symbolizer
-} // namespace folly
+} // namespace symbolizer
+} // namespace folly
#include <folly/experimental/symbolizer/Elf-inl.h>