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 <utility>
#include <set>

#include "LIEF/MachO/FatBinary.hpp"
#include "LIEF/MachO/Builder.hpp"
#include "LIEF/MachO/Binary.hpp"

#include "logging.hpp"


namespace LIEF::MachO {

FatBinary::~FatBinary() = default;
FatBinary::FatBinary() = default;

FatBinary::FatBinary(binaries_t binaries) :
  binaries_{std::move(binaries)} {}

std::unique_ptr<FatBinary> FatBinary::create(binaries_t binaries) {
  std::set<uint64_t> seen;
  for (const std::unique_ptr<Binary>& bin : binaries) {
    if (bin == nullptr) {
      continue;
    }
    const Header& hdr = bin->header();
    uint64_t arch = (uint64_t(hdr.cpu_type()) << 32) | uint64_t(hdr.cpu_subtype());
    if (!seen.insert(arch).second) {
      LIEF_ERR("Duplicate architecture: {} (subtype: {:#x})",
               to_string(hdr.cpu_type()), hdr.cpu_subtype());
      return nullptr;
    }
  }
  return std::unique_ptr<FatBinary>(new FatBinary(std::move(binaries)));
}

std::unique_ptr<Binary> FatBinary::pop_back() {
  if (binaries_.empty()) {
    return nullptr;
  }
  std::unique_ptr<Binary> last = std::move(binaries_.back());
  binaries_.pop_back();
  return last;
}

std::unique_ptr<Binary> FatBinary::take(Header::CPU_TYPE cpu) {
  auto it = std::find_if(binaries_.begin(), binaries_.end(),
                         [cpu](const std::unique_ptr<Binary>& bin) {
                           return bin->header().cpu_type() == cpu;
                         });

  if (it == binaries_.end()) {
    return nullptr;
  }

  std::unique_ptr<Binary> ret = std::move(*it);
  binaries_.erase(it);
  return ret;
}


const Binary* FatBinary::get(Header::CPU_TYPE cpu) const {
  auto it = std::find_if(binaries_.begin(), binaries_.end(),
                         [cpu](const std::unique_ptr<Binary>& bin) {
                           return bin->header().cpu_type() == cpu;
                         });
  if (it == binaries_.end()) {
    return nullptr;
  }
  return it->get();
}

std::unique_ptr<Binary> FatBinary::take(size_t index) {
  if (index >= binaries_.size()) {
    return nullptr;
  }
  auto it = binaries_.begin();
  std::advance(it, index);
  std::unique_ptr<Binary> ret = std::move(*it);
  binaries_.erase(it);
  return ret;
}

void FatBinary::write(const std::string& filename) {
  Builder::write(*this, filename);
}

std::vector<uint8_t> FatBinary::raw() {
  std::vector<uint8_t> buffer;
  Builder::write(*this, buffer);
  return buffer;
}

std::ostream& operator<<(std::ostream& os, const FatBinary& fatbinary) {
  for (const Binary& binary : fatbinary) {
    os << binary << "\n\n";
  }

  return os;
}

}