Commit c8c0682f authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Mark most ElfFile members as noexcept

Summary:
[Folly] Mark most `ElfFile` members as `noexcept`.

Since they may be used in signal handlers, they are required not to throw exceptions. Mark it so.

Reviewed By: luciang

Differential Revision: D18743292

fbshipit-source-id: 95fb2a20511ca4cc7c0e832c1b20b8324ca7d0af
parent f9b187fe
......@@ -22,7 +22,8 @@ namespace folly {
namespace symbolizer {
template <class Fn>
const ElfPhdr* ElfFile::iterateProgramHeaders(Fn fn) const {
const ElfPhdr* ElfFile::iterateProgramHeaders(Fn fn) const
noexcept(is_nothrow_invocable_v<Fn, ElfPhdr const&>) {
// there exist ELF binaries which execute correctly, but have invalid internal
// offset(s) to program/section headers; most probably due to invalid
// stripping of symbols
......@@ -40,7 +41,8 @@ const ElfPhdr* ElfFile::iterateProgramHeaders(Fn fn) const {
}
template <class Fn>
const ElfShdr* ElfFile::iterateSections(Fn fn) const {
const ElfShdr* ElfFile::iterateSections(Fn fn) const
noexcept(is_nothrow_invocable_v<Fn, ElfShdr const&>) {
// there exist ELF binaries which execute correctly, but have invalid internal
// offset(s) to program/section headers; most probably due to invalid
// stripping of symbols
......@@ -58,7 +60,8 @@ const ElfShdr* ElfFile::iterateSections(Fn fn) const {
}
template <class Fn>
const ElfShdr* ElfFile::iterateSectionsWithType(uint32_t type, Fn fn) const {
const ElfShdr* ElfFile::iterateSectionsWithType(uint32_t type, Fn fn) const
noexcept(is_nothrow_invocable_v<Fn, ElfShdr const&>) {
return iterateSections(
[&](const ElfShdr& sh) { return sh.sh_type == type && fn(sh); });
}
......@@ -66,7 +69,7 @@ const ElfShdr* ElfFile::iterateSectionsWithType(uint32_t type, Fn fn) const {
template <class Fn>
const ElfShdr* ElfFile::iterateSectionsWithTypes(
std::initializer_list<uint32_t> types,
Fn fn) const {
Fn fn) const noexcept(is_nothrow_invocable_v<Fn, ElfShdr const&>) {
return iterateSections([&](const ElfShdr& sh) {
auto const it = std::find(types.begin(), types.end(), sh.sh_type);
return it != types.end() && fn(sh);
......@@ -74,7 +77,8 @@ const ElfShdr* ElfFile::iterateSectionsWithTypes(
}
template <class Fn>
const char* ElfFile::iterateStrings(const ElfShdr& stringTable, Fn fn) const {
const char* ElfFile::iterateStrings(const ElfShdr& stringTable, Fn fn) const
noexcept(is_nothrow_invocable_v<Fn, const char*>) {
validateStringTable(stringTable);
const char* start = file_ + stringTable.sh_offset;
......@@ -89,7 +93,8 @@ const char* ElfFile::iterateStrings(const ElfShdr& stringTable, Fn fn) const {
}
template <class Fn>
const ElfSym* ElfFile::iterateSymbols(const ElfShdr& section, Fn fn) const {
const ElfSym* ElfFile::iterateSymbols(const ElfShdr& section, Fn fn) const
noexcept(is_nothrow_invocable_v<Fn, ElfSym const&>) {
FOLLY_SAFE_CHECK(
section.sh_entsize == sizeof(ElfSym),
"invalid entry size in symbol table");
......@@ -112,7 +117,7 @@ template <class Fn>
const ElfSym* ElfFile::iterateSymbolsWithType(
const ElfShdr& section,
uint32_t type,
Fn fn) const {
Fn fn) const noexcept(is_nothrow_invocable_v<Fn, ElfSym const&>) {
// N.B. st_info has the same representation on 32- and 64-bit platforms
return iterateSymbols(section, [&](const ElfSym& sym) -> bool {
return ELF32_ST_TYPE(sym.st_info) == type && fn(sym);
......@@ -123,7 +128,7 @@ template <class Fn>
const ElfSym* ElfFile::iterateSymbolsWithTypes(
const ElfShdr& section,
std::initializer_list<uint32_t> types,
Fn fn) const {
Fn fn) const noexcept(is_nothrow_invocable_v<Fn, ElfSym const&>) {
// N.B. st_info has the same representation on 32- and 64-bit platforms
return iterateSymbols(section, [&](const ElfSym& sym) -> bool {
auto const elfType = ELF32_ST_TYPE(sym.st_info);
......
......@@ -159,7 +159,7 @@ ElfFile::ElfFile(ElfFile&& other) noexcept
other.baseAddress_ = 0;
}
ElfFile& ElfFile::operator=(ElfFile&& other) {
ElfFile& ElfFile::operator=(ElfFile&& other) noexcept {
assert(this != &other);
reset();
......@@ -179,7 +179,7 @@ ElfFile& ElfFile::operator=(ElfFile&& other) {
return *this;
}
void ElfFile::reset() {
void ElfFile::reset() noexcept {
filepath_[0] = 0;
if (file_ != MAP_FAILED) {
......@@ -193,7 +193,7 @@ void ElfFile::reset() {
}
}
ElfFile::OpenResult ElfFile::init() {
ElfFile::OpenResult ElfFile::init() noexcept {
if (length_ < 4) {
return {kInvalidElfFile, "not an ELF file (too short)"};
}
......@@ -266,16 +266,17 @@ ElfFile::OpenResult ElfFile::init() {
return {kSuccess, nullptr};
}
const ElfShdr* ElfFile::getSectionByIndex(size_t idx) const {
const ElfShdr* ElfFile::getSectionByIndex(size_t idx) const noexcept {
FOLLY_SAFE_CHECK(idx < elfHeader().e_shnum, "invalid section index");
return &at<ElfShdr>(elfHeader().e_shoff + idx * sizeof(ElfShdr));
}
folly::StringPiece ElfFile::getSectionBody(const ElfShdr& section) const {
folly::StringPiece ElfFile::getSectionBody(const ElfShdr& section) const
noexcept {
return folly::StringPiece(file_ + section.sh_offset, section.sh_size);
}
void ElfFile::validateStringTable(const ElfShdr& stringTable) const {
void ElfFile::validateStringTable(const ElfShdr& stringTable) const noexcept {
FOLLY_SAFE_CHECK(
stringTable.sh_type == SHT_STRTAB, "invalid type for string table");
......@@ -287,8 +288,8 @@ void ElfFile::validateStringTable(const ElfShdr& stringTable) const {
"invalid string table");
}
const char* ElfFile::getString(const ElfShdr& stringTable, size_t offset)
const {
const char* ElfFile::getString(const ElfShdr& stringTable, size_t offset) const
noexcept {
validateStringTable(stringTable);
FOLLY_SAFE_CHECK(
offset < stringTable.sh_size, "invalid offset in string table");
......@@ -296,7 +297,7 @@ const char* ElfFile::getString(const ElfShdr& stringTable, size_t offset)
return file_ + stringTable.sh_offset + offset;
}
const char* ElfFile::getSectionName(const ElfShdr& section) const {
const char* ElfFile::getSectionName(const ElfShdr& section) const noexcept {
if (elfHeader().e_shstrndx == SHN_UNDEF) {
return nullptr; // no section name string table
}
......@@ -305,7 +306,7 @@ const char* ElfFile::getSectionName(const ElfShdr& section) const {
return getString(sectionNames, section.sh_name);
}
const ElfShdr* ElfFile::getSectionByName(const char* name) const {
const ElfShdr* ElfFile::getSectionByName(const char* name) const noexcept {
if (elfHeader().e_shstrndx == SHN_UNDEF) {
return nullptr; // no section name string table
}
......@@ -323,7 +324,8 @@ const ElfShdr* ElfFile::getSectionByName(const char* name) const {
return foundSection;
}
ElfFile::Symbol ElfFile::getDefinitionByAddress(uintptr_t address) const {
ElfFile::Symbol ElfFile::getDefinitionByAddress(uintptr_t address) const
noexcept {
Symbol foundSymbol{nullptr, nullptr};
auto findSection = [&](const ElfShdr& section) {
......@@ -351,7 +353,7 @@ ElfFile::Symbol ElfFile::getDefinitionByAddress(uintptr_t address) const {
return foundSymbol;
}
ElfFile::Symbol ElfFile::getSymbolByName(const char* name) const {
ElfFile::Symbol ElfFile::getSymbolByName(const char* name) const noexcept {
Symbol foundSymbol{nullptr, nullptr};
auto findSection = [&](const ElfShdr& section) -> bool {
......@@ -390,13 +392,14 @@ ElfFile::Symbol ElfFile::getSymbolByName(const char* name) const {
return foundSymbol;
}
const ElfShdr* ElfFile::getSectionContainingAddress(ElfAddr addr) const {
const ElfShdr* ElfFile::getSectionContainingAddress(ElfAddr addr) const
noexcept {
return iterateSections([&](const ElfShdr& sh) -> bool {
return (addr >= sh.sh_addr) && (addr < (sh.sh_addr + sh.sh_size));
});
}
const char* ElfFile::getSymbolName(Symbol symbol) const {
const char* ElfFile::getSymbolName(Symbol symbol) const noexcept {
if (!symbol.first || !symbol.second) {
return nullptr;
}
......
......@@ -86,10 +86,10 @@ class ElfFile {
~ElfFile();
ElfFile(ElfFile&& other) noexcept;
ElfFile& operator=(ElfFile&& other);
ElfFile& operator=(ElfFile&& other) noexcept;
/** Retrieve the ELF header */
const ElfEhdr& elfHeader() const {
const ElfEhdr& elfHeader() const noexcept {
return at<ElfEhdr>(0);
}
......@@ -97,24 +97,25 @@ class ElfFile {
* Get the base address, the address where the file should be loaded if
* no relocations happened.
*/
uintptr_t getBaseAddress() const {
uintptr_t getBaseAddress() const noexcept {
return baseAddress_;
}
/** Find a section given its name */
const ElfShdr* getSectionByName(const char* name) const;
const ElfShdr* getSectionByName(const char* name) const noexcept;
/** Find a section given its index in the section header table */
const ElfShdr* getSectionByIndex(size_t idx) const;
const ElfShdr* getSectionByIndex(size_t idx) const noexcept;
/** Retrieve the name of a section */
const char* getSectionName(const ElfShdr& section) const;
const char* getSectionName(const ElfShdr& section) const noexcept;
/** Get the actual section body */
folly::StringPiece getSectionBody(const ElfShdr& section) const;
folly::StringPiece getSectionBody(const ElfShdr& section) const noexcept;
/** Retrieve a string from a string table section */
const char* getString(const ElfShdr& stringTable, size_t offset) const;
const char* getString(const ElfShdr& stringTable, size_t offset) const
noexcept;
/**
* Iterate over all strings in a string table section for as long as
......@@ -123,7 +124,8 @@ class ElfFile {
* if fn returned false for all strings in the table.
*/
template <class Fn>
const char* iterateStrings(const ElfShdr& stringTable, Fn fn) const;
const char* iterateStrings(const ElfShdr& stringTable, Fn fn) const
noexcept(is_nothrow_invocable_v<Fn, const char*>);
/**
* Iterate over program headers as long as fn(section) returns false.
......@@ -131,7 +133,8 @@ class ElfFile {
* true, or nullptr if fn returned false for all sections.
*/
template <class Fn>
const ElfPhdr* iterateProgramHeaders(Fn fn) const;
const ElfPhdr* iterateProgramHeaders(Fn fn) const
noexcept(is_nothrow_invocable_v<Fn, ElfPhdr const&>);
/**
* Iterate over all sections for as long as fn(section) returns false.
......@@ -139,14 +142,16 @@ class ElfFile {
* true, or nullptr if fn returned false for all sections.
*/
template <class Fn>
const ElfShdr* iterateSections(Fn fn) const;
const ElfShdr* iterateSections(Fn fn) const
noexcept(is_nothrow_invocable_v<Fn, ElfShdr 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 ElfShdr* iterateSectionsWithType(uint32_t type, Fn fn) const;
const ElfShdr* iterateSectionsWithType(uint32_t type, Fn fn) const
noexcept(is_nothrow_invocable_v<Fn, ElfShdr const&>);
/**
* Iterate over all sections with a given types. Similar to
......@@ -155,7 +160,7 @@ class ElfFile {
template <class Fn>
const ElfShdr* iterateSectionsWithTypes(
std::initializer_list<uint32_t> types,
Fn fn) const;
Fn fn) const noexcept(is_nothrow_invocable_v<Fn, ElfShdr const&>);
/**
* Iterate over all symbols witin a given section.
......@@ -164,15 +169,17 @@ class ElfFile {
* or nullptr if fn returned false for all symbols.
*/
template <class Fn>
const ElfSym* iterateSymbols(const ElfShdr& section, Fn fn) const;
const ElfSym* iterateSymbols(const ElfShdr& section, Fn fn) const
noexcept(is_nothrow_invocable_v<Fn, ElfSym const&>);
template <class Fn>
const ElfSym*
iterateSymbolsWithType(const ElfShdr& section, uint32_t type, Fn fn) const;
iterateSymbolsWithType(const ElfShdr& section, uint32_t type, Fn fn) const
noexcept(is_nothrow_invocable_v<Fn, ElfSym const&>);
template <class Fn>
const ElfSym* iterateSymbolsWithTypes(
const ElfShdr& section,
std::initializer_list<uint32_t> types,
Fn fn) const;
Fn fn) const noexcept(is_nothrow_invocable_v<Fn, ElfSym const&>);
/**
* Find symbol definition by address.
......@@ -182,7 +189,7 @@ class ElfFile {
* Returns {nullptr, nullptr} if not found.
*/
typedef std::pair<const ElfShdr*, const ElfSym*> Symbol;
Symbol getDefinitionByAddress(uintptr_t address) const;
Symbol getDefinitionByAddress(uintptr_t address) const noexcept;
/**
* Find symbol definition by name.
......@@ -192,13 +199,13 @@ class ElfFile {
*
* Returns {nullptr, nullptr} if not found.
*/
Symbol getSymbolByName(const char* name) const;
Symbol getSymbolByName(const char* name) const noexcept;
/**
* Get the value of a symbol.
*/
template <class T>
const T& getSymbolValue(const ElfSym* symbol) const {
const T& getSymbolValue(const ElfSym* symbol) const noexcept {
const ElfShdr* section = getSectionByIndex(symbol->st_shndx);
FOLLY_SAFE_CHECK(section, "Symbol's section index is invalid");
......@@ -217,7 +224,7 @@ class ElfFile {
* const char* str = &getSymbolValue<const char>(addr);
*/
template <class T>
const T& getAddressValue(const ElfAddr addr) const {
const T& getAddressValue(const ElfAddr addr) const noexcept {
const ElfShdr* section = getSectionContainingAddress(addr);
FOLLY_SAFE_CHECK(section, "Address does not refer to existing section");
......@@ -227,22 +234,22 @@ class ElfFile {
/**
* Retrieve symbol name.
*/
const char* getSymbolName(Symbol symbol) const;
const char* getSymbolName(Symbol symbol) const noexcept;
/** Find the section containing the given address */
const ElfShdr* getSectionContainingAddress(ElfAddr addr) const;
const ElfShdr* getSectionContainingAddress(ElfAddr addr) const noexcept;
private:
OpenResult init();
void reset();
OpenResult init() noexcept;
void reset() noexcept;
ElfFile(const ElfFile&) = delete;
ElfFile& operator=(const ElfFile&) = delete;
void validateStringTable(const ElfShdr& stringTable) const;
void validateStringTable(const ElfShdr& stringTable) const noexcept;
template <class T>
const typename std::enable_if<std::is_pod<T>::value, T>::type& at(
ElfOff offset) const {
ElfOff offset) const noexcept {
if (offset + sizeof(T) > length_) {
char msg[kFilepathMaxLen + 128];
snprintf(
......@@ -261,7 +268,7 @@ class ElfFile {
}
template <class T>
const T& valueAt(const ElfShdr& section, const ElfAddr addr) const {
const T& valueAt(const ElfShdr& section, const ElfAddr addr) const noexcept {
// 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
......
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