// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/debug/elf_reader.h"

#include <arpa/inet.h>
#include <elf.h>
#include <string.h>

#include <optional>
#include <string_view>

#include "base/bits.h"
#include "base/compiler_specific.h"
#include "base/containers/span.h"
#include "base/hash/sha1.h"
#include "base/strings/safe_sprintf.h"
#include "build/build_config.h"

// NOTE: This code may be used in crash handling code, so the implementation
// must avoid dynamic memory allocation or using data structures which rely on
// dynamic allocation.

namespace base::debug {
namespace {

// See https://refspecs.linuxbase.org/elf/elf.pdf for the ELF specification.

#if __SIZEOF_POINTER__ == 4
using Ehdr = Elf32_Ehdr;
using Dyn = Elf32_Dyn;
using Half = Elf32_Half;
using Nhdr = Elf32_Nhdr;
using Word = Elf32_Word;
using Xword = Elf32_Word;
#else
using Ehdr = Elf64_Ehdr;
using Dyn = Elf64_Dyn;
using Half = Elf64_Half;
using Nhdr = Elf64_Nhdr;
using Word = Elf64_Word;
using Xword = Elf64_Xword;
#endif

constexpr char kGnuNoteName[] = "GNU";

// Returns a pointer to the header of the ELF binary mapped into memory, or a
// null pointer if the header is invalid. Here and below |elf_mapped_base| is a
// pointer to the start of the ELF image.
const Ehdr* GetElfHeader(const void* elf_mapped_base) {
  if (UNSAFE_TODO(strncmp(reinterpret_cast<const char*>(elf_mapped_base),
                          ELFMAG, SELFMAG)) != 0) {
    return nullptr;
  }

  return reinterpret_cast<const Ehdr*>(elf_mapped_base);
}

}  // namespace

size_t ReadElfBuildId(const void* elf_mapped_base,
                      bool uppercase,
                      ElfBuildIdBuffer build_id) {
  // NOTE: Function should use async signal safe calls only.

  const Ehdr* elf_header = GetElfHeader(elf_mapped_base);
  if (!elf_header) {
    return 0;
  }

  const size_t relocation_offset = GetRelocationOffset(elf_mapped_base);
  for (const Phdr& header : GetElfProgramHeaders(elf_mapped_base)) {
    if (header.p_type != PT_NOTE) {
      continue;
    }

    // Look for a NT_GNU_BUILD_ID note with name == "GNU".
    const char* current_section =
        reinterpret_cast<const char*>(header.p_vaddr + relocation_offset);
    const char* section_end = UNSAFE_TODO(current_section + header.p_memsz);
    const Nhdr* current_note = nullptr;
    bool found = false;
    while (current_section < section_end) {
      current_note = reinterpret_cast<const Nhdr*>(current_section);
      if (current_note->n_type == NT_GNU_BUILD_ID) {
        std::string_view note_name(UNSAFE_TODO(current_section + sizeof(Nhdr)),
                                   current_note->n_namesz);
        // Explicit constructor is used to include the '\0' character.
        if (note_name == std::string_view(kGnuNoteName, sizeof(kGnuNoteName))) {
          found = true;
          break;
        }
      }

      size_t section_size =
          bits::AlignUp(current_note->n_namesz, static_cast<Word>(4)) +
          bits::AlignUp(current_note->n_descsz, static_cast<Word>(4)) +
          sizeof(Nhdr);
      if (section_size > static_cast<size_t>(section_end - current_section)) {
        return 0;
      }
      UNSAFE_TODO(current_section += section_size);
    }

    if (!found) {
      continue;
    }

    // Validate that the serialized build ID will fit inside |build_id|.
    size_t note_size = current_note->n_descsz;
    if ((note_size * 2) > kMaxBuildIdStringLength) {
      continue;
    }

    // Write out the build ID as a null-terminated hex string.
    const uint8_t* build_id_raw = UNSAFE_TODO(
        reinterpret_cast<const uint8_t*>(current_note) + sizeof(Nhdr) +
        bits::AlignUp(current_note->n_namesz, static_cast<Word>(4)));
    size_t i = 0;
    for (i = 0; i < current_note->n_descsz; ++i) {
      strings::SafeSNPrintf(&UNSAFE_TODO(build_id[i * 2]), 3,
                            (uppercase ? "%02X" : "%02x"),
                            UNSAFE_TODO(build_id_raw[i]));
    }
    UNSAFE_TODO(build_id[i * 2]) = '\0';

    // Return the length of the string.
    return i * 2;
  }

  return 0;
}

std::optional<std::string_view> ReadElfLibraryName(
    const void* elf_mapped_base) {
  // NOTE: Function should use async signal safe calls only.

  const Ehdr* elf_header = GetElfHeader(elf_mapped_base);
  if (!elf_header) {
    return {};
  }

  const size_t relocation_offset = GetRelocationOffset(elf_mapped_base);
  for (const Phdr& header : GetElfProgramHeaders(elf_mapped_base)) {
    if (header.p_type != PT_DYNAMIC) {
      continue;
    }

    // Read through the ELF dynamic sections to find the string table and
    // SONAME offsets, which are used to compute the offset of the library
    // name string.
    const Dyn* dynamic_start =
        reinterpret_cast<const Dyn*>(header.p_vaddr + relocation_offset);
    const Dyn* dynamic_end = reinterpret_cast<const Dyn*>(
        header.p_vaddr + relocation_offset + header.p_memsz);
    Xword soname_strtab_offset = 0;
    const char* strtab_addr = nullptr;
    for (const Dyn* dynamic_iter = dynamic_start; dynamic_iter < dynamic_end;
         UNSAFE_TODO(++dynamic_iter)) {
      if (dynamic_iter->d_tag == DT_STRTAB) {
#if BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_ANDROID) || \
    (defined(ARCH_CPU_RISCV_FAMILY) && BUILDFLAG(IS_LINUX))
        // Fuchsia and Android do not relocate the strtab pointer on ELF load.
        // When the dynamic section is readonly, the strtab pointer is also not
        // relocated. This is the default ABI behavior on RISC-V GNU Linux (See
        // sysdeps/riscv/dl-relocate-ld.h).
        strtab_addr =
            UNSAFE_TODO(static_cast<size_t>(dynamic_iter->d_un.d_ptr) +
                        reinterpret_cast<const char*>(relocation_offset));
#else
        strtab_addr = reinterpret_cast<const char*>(dynamic_iter->d_un.d_ptr);
#endif
      } else if (dynamic_iter->d_tag == DT_SONAME) {
        // The Android NDK wrongly defines `d_val` as an Elf32_Sword for 32 bits
        // and thus needs this cast.
        soname_strtab_offset = static_cast<Xword>(dynamic_iter->d_un.d_val);
      }
    }
    if (soname_strtab_offset && strtab_addr) {
      return std::string_view(UNSAFE_TODO(strtab_addr + soname_strtab_offset));
    }
  }

  return std::nullopt;
}

span<const Phdr> GetElfProgramHeaders(const void* elf_mapped_base) {
  // NOTE: Function should use async signal safe calls only.

  const Ehdr* elf_header = GetElfHeader(elf_mapped_base);
  if (!elf_header) {
    return {};
  }

  const char* phdr_start = UNSAFE_TODO(
      reinterpret_cast<const char*>(elf_header) + elf_header->e_phoff);
  return UNSAFE_TODO(span<const Phdr>(reinterpret_cast<const Phdr*>(phdr_start),
                                      elf_header->e_phnum));
}

// Returns the offset to add to virtual addresses in the image to compute the
// mapped virtual address.
size_t GetRelocationOffset(const void* elf_mapped_base) {
  span<const Phdr> headers = GetElfProgramHeaders(elf_mapped_base);
  for (const Phdr& header : headers) {
    if (header.p_type == PT_LOAD) {
      // |elf_mapped_base| + |header.p_offset| is the mapped address of this
      // segment. |header.p_vaddr| is the specified virtual address within the
      // ELF image.
      const char* const mapped_address = UNSAFE_TODO(
          reinterpret_cast<const char*>(elf_mapped_base) + header.p_offset);
      return reinterpret_cast<uintptr_t>(mapped_address) - header.p_vaddr;
    }
  }

  // Assume the virtual addresses in the image start at 0, so the offset is
  // from 0 to the actual mapped base address.
  return static_cast<size_t>(reinterpret_cast<uintptr_t>(elf_mapped_base) -
                             reinterpret_cast<uintptr_t>(nullptr));
}

}  // namespace base::debug
