current commit
260929.11 · deps: update lief to 1.0.0
/* 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/MachO/hash.hpp"
#include "LIEF/MachO/Binary.hpp"
#include "LIEF/MachO/BinaryParser.hpp"
#include "LIEF/MachO/BindingInfo.hpp"
#include "LIEF/MachO/BindingInfoIterator.hpp"
#include "LIEF/MachO/BuildToolVersion.hpp"
#include "LIEF/MachO/BuildVersion.hpp"
#include "LIEF/MachO/Builder.hpp"
#include "LIEF/MachO/ChainedBindingInfo.hpp"
#include "LIEF/MachO/CodeSignature.hpp"
#include "LIEF/MachO/CodeSignatureDir.hpp"
#include "LIEF/MachO/DataCodeEntry.hpp"
#include "LIEF/MachO/DataInCode.hpp"
#include "LIEF/MachO/DyldBindingInfo.hpp"
#include "LIEF/MachO/DyldChainedFixups.hpp"
#include "LIEF/MachO/DyldChainedFixupsCreator.hpp"
#include "LIEF/MachO/DyldEnvironment.hpp"
#include "LIEF/MachO/DyldExportsTrie.hpp"
#include "LIEF/MachO/DyldInfo.hpp"
#include "LIEF/MachO/DylibCommand.hpp"
#include "LIEF/MachO/DylinkerCommand.hpp"
#include "LIEF/MachO/DynamicSymbolCommand.hpp"
#include "LIEF/MachO/EncryptionInfo.hpp"
#include "LIEF/MachO/ExportInfo.hpp"
#include "LIEF/MachO/FatBinary.hpp"
#include "LIEF/MachO/FilesetCommand.hpp"
#include "LIEF/MachO/FunctionStarts.hpp"
#include "LIEF/MachO/Header.hpp"
#include "LIEF/MachO/LinkEdit.hpp"
#include "LIEF/MachO/LinkerOptHint.hpp"
#include "LIEF/MachO/LoadCommand.hpp"
#include "LIEF/MachO/MainCommand.hpp"
#include "LIEF/MachO/NoteCommand.hpp"
#include "LIEF/MachO/Parser.hpp"
#include "LIEF/MachO/RPathCommand.hpp"
#include "LIEF/MachO/Relocation.hpp"
#include "LIEF/MachO/RelocationDyld.hpp"
#include "LIEF/MachO/RelocationFixup.hpp"
#include "LIEF/MachO/RelocationObject.hpp"
#include "LIEF/MachO/Routine.hpp"
#include "LIEF/MachO/Section.hpp"
#include "LIEF/MachO/SegmentCommand.hpp"
#include "LIEF/MachO/SegmentSplitInfo.hpp"
#include "LIEF/MachO/SourceVersion.hpp"
#include "LIEF/MachO/Stub.hpp"
#include "LIEF/MachO/SubFramework.hpp"
#include "LIEF/MachO/Symbol.hpp"
#include "LIEF/MachO/SymbolCommand.hpp"
#include "LIEF/MachO/ThreadCommand.hpp"
#include "LIEF/MachO/TwoLevelHints.hpp"
#include "LIEF/MachO/UUIDCommand.hpp"
#include "LIEF/MachO/UnknownCommand.hpp"
#include "LIEF/MachO/VersionMin.hpp"
#include "LIEF/MachO/hash.hpp"
#include "LIEF/MachO/json.hpp"
#include "LIEF/MachO/utils.hpp"

#include "Object.tcc"

namespace LIEF::MachO {

Hash::~Hash() = default;

size_t Hash::hash(const Object& obj) {
  return LIEF::Hash::hash<LIEF::MachO::Hash>(obj);
}

void Hash::visit(const Binary& binary) {
  process(binary.header());
  process(binary.commands().begin(), binary.commands().end());
  process(binary.symbols().begin(), binary.symbols().end());
}


void Hash::visit(const Header& header) {
  process(header.magic());
  process(header.cpu_type());
  process(header.cpu_subtype());
  process(header.file_type());
  process(header.nb_cmds());
  process(header.sizeof_cmds());
  process(header.flags());
  process(header.reserved());
}

void Hash::visit(const LoadCommand& cmd) {
  process(cmd.command());
  process(cmd.size());
  process(cmd.data());
  process(cmd.command_offset());
}

void Hash::visit(const UUIDCommand& uuid) {
  visit(*uuid.as<LoadCommand>());
  process(uuid.uuid());
}

void Hash::visit(const SymbolCommand& symbol) {

  visit(*symbol.as<LoadCommand>());
  process(symbol.symbol_offset());
  process(symbol.numberof_symbols());
  process(symbol.strings_offset());
  process(symbol.strings_size());
}

void Hash::visit(const SegmentCommand& segment) {

  visit(*segment.as<LoadCommand>());
  process(segment.name());
  process(segment.virtual_address());
  process(segment.virtual_size());
  process(segment.file_size());
  process(segment.file_offset());
  process(segment.max_protection());
  process(segment.init_protection());
  process(segment.numberof_sections());
  process(segment.flags());
  process(segment.content());
  process(segment.sections().begin(), segment.sections().end());
}

void Hash::visit(const Section& section) {
  process(section.content());
  process(section.segment_name());
  process(section.address());
  process(section.alignment());
  process(section.relocation_offset());
  process(section.numberof_relocations());
  process(section.flags());
  process(section.type());
  process(section.reserved1());
  process(section.reserved2());
  process(section.reserved3());
  process(section.raw_flags());
  process(section.relocations().begin(), section.relocations().end());
}

void Hash::visit(const MainCommand& maincmd) {

  visit(*maincmd.as<LoadCommand>());

  process(maincmd.entrypoint());
  process(maincmd.stack_size());
}

void Hash::visit(const NoteCommand& note) {
  visit(*note.as<LoadCommand>());
}

void Hash::visit(const DynamicSymbolCommand& dynamic_symbol) {
  visit(*dynamic_symbol.as<LoadCommand>());
  process(dynamic_symbol.idx_local_symbol());
  process(dynamic_symbol.nb_local_symbols());

  process(dynamic_symbol.idx_external_define_symbol());
  process(dynamic_symbol.nb_external_define_symbols());

  process(dynamic_symbol.idx_undefined_symbol());
  process(dynamic_symbol.nb_undefined_symbols());

  process(dynamic_symbol.toc_offset());
  process(dynamic_symbol.nb_toc());

  process(dynamic_symbol.module_table_offset());
  process(dynamic_symbol.nb_module_table());

  process(dynamic_symbol.external_reference_symbol_offset());
  process(dynamic_symbol.nb_external_reference_symbols());

  process(dynamic_symbol.indirect_symbol_offset());
  process(dynamic_symbol.nb_indirect_symbols());

  process(dynamic_symbol.external_relocation_offset());
  process(dynamic_symbol.nb_external_relocations());

  process(dynamic_symbol.local_relocation_offset());
  process(dynamic_symbol.nb_local_relocations());
}

void Hash::visit(const DylinkerCommand& dylinker) {
  visit(*dylinker.as<LoadCommand>());
  process(dylinker.name());
}

void Hash::visit(const DylibCommand& dylib) {
  visit(*dylib.as<LoadCommand>());

  process(dylib.name());
  process(dylib.timestamp());
  process(dylib.current_version());
  process(dylib.compatibility_version());
}

void Hash::visit(const ThreadCommand& threadcmd) {
  visit(*threadcmd.as<LoadCommand>());
  process(threadcmd.flavor());
  process(threadcmd.count());
  process(threadcmd.state());
}

void Hash::visit(const RPathCommand& rpath) {
  visit(*rpath.as<LoadCommand>());
  process(rpath.path());
}

void Hash::visit(const Routine& routine) {
  visit(*routine.as<LoadCommand>());
}

void Hash::visit(const Symbol& symbol) {
  process(symbol.name());
  process(symbol.value());
  process(symbol.size());

  process(symbol.type());
  process(symbol.numberof_sections());
  process(symbol.description());

  // if (symbol.has_binding_info()) {
  //   process(symbol.binding_info());
  // }

  // if (symbol.has_export_info()) {
  //   process(symbol.export_info());
  // }
}

void Hash::visit(const Relocation& relocation) {

  process(relocation.size());
  process(relocation.address());
  process(static_cast<size_t>(relocation.is_pc_relative()));
  process(relocation.type());
  process(relocation.origin());

  if (relocation.has_symbol()) {
    process(relocation.symbol()->name());
  }
}

void Hash::visit(const RelocationObject& robject) {

  visit(*robject.as<Relocation>());
  process(static_cast<size_t>(robject.is_scattered()));
  if (robject.is_scattered()) {
    process(robject.value());
  }
}

void Hash::visit(const RelocationDyld& rdyld) {
  visit(*rdyld.as<Relocation>());
}

void Hash::visit(const RelocationFixup& fixup) {
  visit(*fixup.as<Relocation>());
  process(fixup.target());
}

void Hash::visit(const BindingInfo& binding) {

  process(binding.library_ordinal());
  process(binding.addend());
  process(static_cast<size_t>(binding.is_weak_import()));
  process(binding.address());

  if (binding.has_symbol()) {
    process(binding.symbol()->name());
  }

  if (binding.has_library()) {
    process(*binding.library());
  }
}

void Hash::visit(const DyldBindingInfo& binding) {
  visit(*binding.as<BindingInfo>());
  process(binding.binding_class());
  process(binding.binding_type());
}

void Hash::visit(const ChainedBindingInfo& binding) {
  visit(*binding.as<BindingInfo>());
  process(binding.format());
}

void Hash::visit(const DyldExportsTrie& trie) {
  visit(*trie.as<LoadCommand>());
  process(trie.data_offset());
  process(trie.data_size());
  process(trie.content());
}

void Hash::visit(const ExportInfo& einfo) {
  process(einfo.node_offset());
  process(einfo.flags());
  process(einfo.address());

  if (einfo.has_symbol()) {
    process(einfo.symbol()->name());
  }
}

void Hash::visit(const FunctionStarts& fs) {
  visit(*fs.as<LoadCommand>());
  process(fs.data_offset());
  process(fs.data_size());
  process(fs.functions());
}

void Hash::visit(const CodeSignature& cs) {
  visit(*cs.as<LoadCommand>());
  process(cs.data_offset());
  process(cs.data_size());
}

void Hash::visit(const DataInCode& dic) {
  visit(*dic.as<LoadCommand>());
  process(dic.data_offset());
  process(dic.data_size());
  process(dic.entries().begin(), dic.entries().end());
}

void Hash::visit(const DataCodeEntry& dce) {
  process(dce.offset());
  process(dce.length());
  process(dce.type());
}

void Hash::visit(const VersionMin& vmin) {
  visit(*vmin.as<LoadCommand>());
  process(vmin.version());
  process(vmin.sdk());
}

void Hash::visit(const UnknownCommand& ukn) {
  visit(*ukn.as<LoadCommand>());
  process(ukn.original_command());
}

void Hash::visit(const SourceVersion& sv) {
  visit(*sv.as<LoadCommand>());
  process(sv.version());
}

void Hash::visit(const SegmentSplitInfo& ssi) {
  visit(*ssi.as<LoadCommand>());
  process(ssi.data_offset());
  process(ssi.data_size());
}

void Hash::visit(const SubFramework& sf) {
  visit(*sf.as<LoadCommand>());
  process(sf.umbrella());
}

void Hash::visit(const DyldEnvironment& de) {
  visit(*de.as<LoadCommand>());
  process(de.value());
}

void Hash::visit(const EncryptionInfo& e) {
  visit(*e.as<LoadCommand>());
  process(e.crypt_offset());
  process(e.crypt_size());
  process(e.crypt_id());
}

void Hash::visit(const BuildVersion& e) {
  BuildVersion::tools_list_t tools = e.tools();

  visit(*e.as<LoadCommand>());
  process(e.platform());
  process(e.minos());
  process(e.sdk());
  process(tools.begin(), tools.end());
}

void Hash::visit(const BuildToolVersion& e) {
  process(e.tool());
  process(e.version());
}

void Hash::visit(const FilesetCommand& e) {
  process(e.name());
  process(e.virtual_address());
  process(e.file_offset());
}

void Hash::visit(const CodeSignatureDir& e) {
  process(e.data_offset());
  process(e.data_size());
  process(e.content());
}

void Hash::visit(const TwoLevelHints& e) {
  process(e.content());
}

void Hash::visit(const LinkerOptHint& e) {
  process(e.data_offset());
  process(e.data_size());
  process(e.content());
}


} // namespace LIEF::MachO