/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "LIEF/Visitor.hpp"
#include "LIEF/ELF/DynamicEntryFlags.hpp"
#include "frozen.hpp"
#include "fmt_formatter.hpp"
FMT_FORMATTER(LIEF::ELF::DynamicEntryFlags::FLAG, LIEF::ELF::to_string);
namespace LIEF::ELF {
static constexpr auto DF_FLAGS = {
DynamicEntryFlags::FLAG::ORIGIN, DynamicEntryFlags::FLAG::SYMBOLIC,
DynamicEntryFlags::FLAG::TEXTREL, DynamicEntryFlags::FLAG::BIND_NOW,
DynamicEntryFlags::FLAG::STATIC_TLS,
};
static constexpr auto DF_FLAGS_1 = {
DynamicEntryFlags::FLAG::NOW, DynamicEntryFlags::FLAG::GLOBAL,
DynamicEntryFlags::FLAG::GROUP, DynamicEntryFlags::FLAG::NODELETE,
DynamicEntryFlags::FLAG::LOADFLTR, DynamicEntryFlags::FLAG::INITFIRST,
DynamicEntryFlags::FLAG::NOOPEN, DynamicEntryFlags::FLAG::HANDLE_ORIGIN,
DynamicEntryFlags::FLAG::DIRECT, DynamicEntryFlags::FLAG::TRANS,
DynamicEntryFlags::FLAG::INTERPOSE, DynamicEntryFlags::FLAG::NODEFLIB,
DynamicEntryFlags::FLAG::NODUMP, DynamicEntryFlags::FLAG::CONFALT,
DynamicEntryFlags::FLAG::ENDFILTEE, DynamicEntryFlags::FLAG::DISPRELDNE,
DynamicEntryFlags::FLAG::DISPRELPND, DynamicEntryFlags::FLAG::NODIRECT,
DynamicEntryFlags::FLAG::IGNMULDEF, DynamicEntryFlags::FLAG::NOKSYMS,
DynamicEntryFlags::FLAG::NOHDR, DynamicEntryFlags::FLAG::EDITED,
DynamicEntryFlags::FLAG::NORELOC, DynamicEntryFlags::FLAG::SYMINTPOSE,
DynamicEntryFlags::FLAG::GLOBAUDIT, DynamicEntryFlags::FLAG::SINGLETON,
DynamicEntryFlags::FLAG::PIE, DynamicEntryFlags::FLAG::KMOD,
DynamicEntryFlags::FLAG::WEAKFILTER, DynamicEntryFlags::FLAG::NOCOMMON,
};
bool DynamicEntryFlags::has(DynamicEntryFlags::FLAG f) const {
if (tag() == DynamicEntry::TAG::FLAGS) {
auto raw = static_cast<uint64_t>(f);
if (BASE <= raw) {
return false;
}
return (value() & raw) > 0;
}
if (tag() == DynamicEntry::TAG::FLAGS_1) {
auto raw = static_cast<uint64_t>(f);
if (raw < BASE) {
return false;
}
raw -= BASE;
return (value() & raw) > 0;
}
return false;
}
DynamicEntryFlags::flags_list_t DynamicEntryFlags::flags() const {
flags_list_t flags;
if (tag() == DynamicEntry::TAG::FLAGS) {
for (DynamicEntryFlags::FLAG f : DF_FLAGS) {
if (has(f)) {
flags.push_back(f);
}
}
return flags;
}
if (tag() == DynamicEntry::TAG::FLAGS_1) {
for (DynamicEntryFlags::FLAG f : DF_FLAGS_1) {
if (has(f)) {
flags.push_back(f);
}
}
return flags;
}
return flags;
}
void DynamicEntryFlags::add(DynamicEntryFlags::FLAG f) {
if (tag() == DynamicEntry::TAG::FLAGS) {
auto raw = static_cast<uint64_t>(f);
if (BASE <= raw) {
return;
}
value(value() | raw);
return;
}
if (tag() == DynamicEntry::TAG::FLAGS_1) {
auto raw = static_cast<uint64_t>(f);
if (raw < BASE) {
return;
}
raw -= BASE;
value(value() | raw);
return;
}
return;
}
void DynamicEntryFlags::remove(DynamicEntryFlags::FLAG f) {
if (tag() == DynamicEntry::TAG::FLAGS) {
auto raw = static_cast<uint64_t>(f);
if (BASE <= raw) {
return;
}
value(value() & ~raw);
}
if (tag() == DynamicEntry::TAG::FLAGS_1) {
auto raw = static_cast<uint64_t>(f);
if (raw < BASE) {
return;
}
raw -= BASE;
value(value() & ~raw);
}
}
void DynamicEntryFlags::accept(Visitor& visitor) const {
visitor.visit(*this);
}
std::ostream& DynamicEntryFlags::print(std::ostream& os) const {
DynamicEntry::print(os);
os << fmt::to_string(flags());
return os;
}
const char* to_string(DynamicEntryFlags::FLAG flag) {
#define ENTRY(X) std::pair(DynamicEntryFlags::FLAG::X, #X)
STRING_MAP enums2str{
ENTRY(ORIGIN), ENTRY(SYMBOLIC), ENTRY(TEXTREL), ENTRY(BIND_NOW),
ENTRY(STATIC_TLS), ENTRY(NOW), ENTRY(GLOBAL), ENTRY(GROUP),
ENTRY(NODELETE), ENTRY(LOADFLTR), ENTRY(INITFIRST), ENTRY(NOOPEN),
ENTRY(HANDLE_ORIGIN), ENTRY(DIRECT), ENTRY(TRANS), ENTRY(INTERPOSE),
ENTRY(NODEFLIB), ENTRY(NODUMP), ENTRY(CONFALT), ENTRY(ENDFILTEE),
ENTRY(DISPRELDNE), ENTRY(DISPRELPND), ENTRY(NODIRECT), ENTRY(IGNMULDEF),
ENTRY(NOKSYMS), ENTRY(NOHDR), ENTRY(EDITED), ENTRY(NORELOC),
ENTRY(SYMINTPOSE), ENTRY(GLOBAUDIT), ENTRY(SINGLETON), ENTRY(PIE),
ENTRY(KMOD), ENTRY(WEAKFILTER), ENTRY(NOCOMMON),
};
#undef ENTRY
if (auto it = enums2str.find(flag); it != enums2str.end()) {
return it->second;
}
return "UNKNOWN";
}
}