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