// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "lib/zxdump/elf-search.h"

#include "core.h"

namespace zxdump {

bool IsLikelyElfMapping(const zx_info_maps_t& maps) {
  const bool readonly =
      (maps.u.mapping.mmu_flags & (ZX_VM_PERM_READ | ZX_VM_PERM_WRITE)) == ZX_VM_PERM_READ;

  // It might be ELF if it...
  return maps.type == ZX_INFO_MAPS_TYPE_MAPPING &&
         maps.u.mapping.vmo_offset == 0 &&  // is the start of the file (VMO),
         readonly &&                        // maps it read-only,
         maps.size > sizeof(Elf::Ehdr);     // ... and has space for ELF,
}

// Try to detect an ELF image in this segment.  If one is found and its phdrs
// are accessible, return a view into them from process.read_memory.
fit::result<Error, zxdump::Buffer<Elf::Phdr>> DetectElf(Process& process,
                                                        const zx_info_maps_t& segment) {
  constexpr auto no_elf = []() { return fit::ok(zxdump::Buffer<Elf::Phdr>()); };

  if (segment.type != ZX_INFO_MAPS_TYPE_MAPPING) {
    return no_elf();
  }

  auto result = process.read_memory<Elf::Ehdr>(segment.base);
  if (result.is_error()) {
    return result.take_error();
  }

  const Elf::Ehdr& ehdr = result.value();
  if (ehdr.Valid() && ehdr.phentsize == sizeof(Elf::Phdr) && ehdr.phnum > 0 &&
      ehdr.phnum != Elf::Ehdr::kPnXnum && (ehdr.phoff % alignof(Elf::Phdr)) == 0 &&
      ehdr.phoff < segment.size && segment.size - ehdr.phoff >= ehdr.phnum * sizeof(Elf::Phdr)) {
    auto phdr_result = process.read_memory<Elf::Phdr>(segment.base + ehdr.phoff, ehdr.phnum);
    if (phdr_result.is_error()) {
      return phdr_result.take_error();
    }
    return fit::ok(*std::move(phdr_result));
  }

  return no_elf();
}

fit::result<Error, ElfIdentity> DetectElfIdentity(Process& process, const zx_info_maps_t& segment,
                                                  cpp20::span<const Elf::Phdr> phdrs) {
  // Find the first PT_LOAD segment.
  std::optional<uint64_t> first_load;
  for (const auto& phdr : phdrs) {
    if (phdr.type == elfldltl::ElfPhdrType::kLoad) {
      first_load = phdr.vaddr & -process.dump_page_size();
      break;
    }
  }
  if (!first_load) {
    // This is not really a valid ELF image, probably.
    return fit::ok(ElfIdentity{});
  }

  // Note the notes.
  std::vector<SegmentDisposition::Note> notes;
  std::optional<SegmentDisposition::Note> dynamic;
  for (const auto& phdr : phdrs) {
    if (phdr.type == elfldltl::ElfPhdrType::kNote && phdr.vaddr >= *first_load) {
      // It's an allocated note segment that might be within this segment.
      const size_t offset = phdr.vaddr - *first_load;
      if (offset < segment.size && segment.size - offset >= phdr.filesz) {
        // It actually fits inside the segment, so we can examine it.
        notes.push_back({phdr.vaddr, phdr.filesz});
      }
    } else if (phdr.type == elfldltl::ElfPhdrType::kDynamic && phdr.vaddr >= *first_load) {
      dynamic = {phdr.vaddr, phdr.filesz};
    }
  }
  // The phdrs view is no longer used now, so it's safe to use read_memory.

  ElfIdentity id;

  // Detect the build ID.
  constexpr std::string_view kBuildIdNoteName{
      "GNU", sizeof("GNU"),  // NUL terminator included!
  };

  for (auto note : notes) {
    note.vaddr += segment.base - *first_load;
    while (note.size >= sizeof(Elf::Nhdr)) {
      Elf::Nhdr nhdr;
      if (auto result = process.read_memory<Elf::Nhdr>(note.vaddr); result.is_error()) {
        return result.take_error();
      } else {
        nhdr = result.value();
      }

      const size_t this_note_size = sizeof(nhdr) + NoteAlign(nhdr.namesz) + NoteAlign(nhdr.descsz);
      if (this_note_size > note.size) {
        break;
      }

      if (nhdr.type == static_cast<uint32_t>(elfldltl::ElfNoteType::kGnuBuildId) &&
          nhdr.descsz > 0 && nhdr.namesz() == kBuildIdNoteName.size()) {
        auto result = process.read_memory<char, std::string_view>(note.vaddr + sizeof(Elf::Nhdr),
                                                                  kBuildIdNoteName.size());
        if (result.is_error()) {
          return result.take_error();
        }

        ZX_DEBUG_ASSERT(result.value()->size() == kBuildIdNoteName.size());
        if (**result == kBuildIdNoteName) {
          // We have a winner!
          note.size = this_note_size;
          id.build_id = note;
          break;
        }
      }

      note.vaddr += this_note_size;
      note.size -= this_note_size;
    }
  }

  // Detect the SONAME.  Ignore any memory errors since just returning
  // a build ID and no SONAME is better than returning no information at all.
  if (dynamic && dynamic->size > sizeof(Elf::Dyn)) {
    dynamic->vaddr += segment.base - *first_load;
    dynamic->size /= sizeof(Elf::Dyn);
    auto read = process.read_memory<Elf::Dyn>(dynamic->vaddr, dynamic->size);
    if (read.is_ok()) {
      std::optional<uint64_t> soname, strtab;
      for (const auto& dyn : **read) {
        switch (dyn.tag) {
          case elfldltl::ElfDynTag::kSoname:
            soname = dyn.val;
            break;
          case elfldltl::ElfDynTag::kStrTab:
            strtab = segment.base - *first_load + dyn.val;
            break;
          default:
            break;
        }
        if (soname && strtab) {
          uint64_t vaddr = *strtab + *soname;
          auto string = process.read_memory_string(vaddr);
          if (string.is_ok()) {
            id.soname = {vaddr, string.value().size()};
          }
          break;
        }
      }
    }
  }

  return fit::ok(id);
}

std::pair<MapsInfoSpanIterator, MapsInfoSpanIterator> ElfSearch(  //
    Process& process, MapsInfoSpanIterator first, MapsInfoSpanIterator last) {
  while (first < last) {
    const auto& segment = *first;
    if (IsLikelyElfMapping(segment)) {
      auto result = DetectElf(process, segment);
      if (result.is_error()) {
        return {first, first};
      }
      if (!result->empty()) {
        std::optional<uint64_t> vaddr_base, vaddr_limit;
        auto phdrs = *result.value();
        const uint64_t page_size = process.dump_page_size();
        for (const auto& phdr : phdrs) {
          if (phdr.type == elfldltl::ElfPhdrType::kLoad) {
            if (!vaddr_base) {
              vaddr_base = phdr.vaddr & -page_size;
            }
            if (phdr.vaddr < *vaddr_base) {
              // It's invalid to have non-ascending segments.
              // Consider this not to be a real ELF image at all.
              vaddr_limit.reset();
              break;
            }
            const uint64_t limit =
                (phdr.vaddr - *vaddr_base + segment.base + phdr.memsz + page_size - 1) & -page_size;
            if (limit < segment.base) {
              // Overflow is invalid.
              vaddr_limit.reset();
              break;
            }
            if (vaddr_limit && limit < *vaddr_limit) {
              // It's invalid to have overlapping segments.
              vaddr_limit.reset();
              break;
            }
            vaddr_limit = limit;
          }
        }
        if (vaddr_limit) {
          // We have an image.
          auto last_segment = first;
          do {
            ++last_segment;
          } while (last_segment != last && last_segment->base < *vaddr_limit);
          return {first, last_segment};
        }
      }
    }
    ++first;
  }
  return {last, last};
}

}  // namespace zxdump
