/*
 * Copyright (c) 2011-2013, 2019 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Steve Reinhardt
 *          Ali Saidi
 */

#include "base/loader/elf_object.hh"

#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <cassert>
#include <string>

#include "base/bitfield.hh"
#include "base/loader/symtab.hh"
#include "base/logging.hh"
#include "base/trace.hh"
#include "debug/Loader.hh"
#include "gelf.h"
#include "sim/byteswap.hh"

ObjectFile *
ElfObjectFormat::load(ImageFileDataPtr ifd)
{
    // check that header matches library version
    if (elf_version(EV_CURRENT) == EV_NONE)
        panic("wrong elf version number!");

    ObjectFile *object = nullptr;

    // get a pointer to elf structure
    // Check that we actually have a elf file
    Elf *elf =
        elf_memory((char *)const_cast<uint8_t *>(ifd->data()), ifd->len());
    assert(elf);

    GElf_Ehdr ehdr;
    if (gelf_getehdr(elf, &ehdr) == 0)
        DPRINTFR(Loader, "Not ELF\n");
    else
        object = new ElfObject(ifd);

    elf_end(elf);

    return object;
}

namespace
{

ElfObjectFormat elfObjectFormat;
std::string interpDir;

} // anonymous namespace

void
setInterpDir(const std::string &dirname)
{
    fatal_if(!interpDir.empty(),
        "Error: setInterpDir has already been called once\n");
    interpDir = dirname;
}

ElfObject::ElfObject(ImageFileDataPtr ifd) : ObjectFile(ifd)
{
    // get a pointer to elf structure
    elf = elf_memory((char *)const_cast<uint8_t *>(imageData->data()),
                     imageData->len());
    assert(elf);
    gelf_getehdr(elf, &ehdr);

    determineArch();
    determineOpSys();

    entry = ehdr.e_entry;
    _programHeaderCount = ehdr.e_phnum;
    _programHeaderSize = ehdr.e_phentsize;

    // Go through all the segments in the program and record them.
    for (int i = 0; i < ehdr.e_phnum; ++i) {
        GElf_Phdr phdr;
        if (gelf_getphdr(elf, i, &phdr) == 0) {
            panic("gelf_getphdr failed for segment %d.", i);
        }

        if (phdr.p_type == PT_LOAD)
            handleLoadableSegment(phdr, i);
        if (phdr.p_type == PT_INTERP) {
            // Make sure the interpreter is an valid ELF file.
            auto interp_path = getInterpPath(phdr);
            ObjectFile *obj = createObjectFile(interp_path);
            interpreter = dynamic_cast<ElfObject *>(obj);
            assert(interpreter != nullptr);
        }
    }

    // should have found at least one loadable segment
    warn_if(image.segments().empty(),
            "No loadable segments in '%s'. ELF file corrupted?\n",
            imageData->filename());

    for (auto M5_VAR_USED &seg: image.segments())
        DPRINTFR(Loader, "%s\n", seg);

    // We will actually read the sections when we need to load them
}

std::string
ElfObject::getInterpPath(const GElf_Phdr &phdr) const
{
    // This is the interpreter path as specified in the elf file
    const std::string elf_path = (char *)imageData->data() + phdr.p_offset;
    if (!interpDir.empty())
        return interpDir + elf_path;
    else
        return elf_path;
}

void
ElfObject::determineArch()
{
    auto &emach = ehdr.e_machine;
    auto &eclass = ehdr.e_ident[EI_CLASS];
    auto &edata = ehdr.e_ident[EI_DATA];

    // Detect the architecture
    if (emach == EM_SPARC64 || (emach == EM_SPARC && eclass == ELFCLASS64) ||
        emach == EM_SPARCV9) {
        arch = SPARC64;
    } else if (emach == EM_SPARC32PLUS ||
               (emach == EM_SPARC && eclass == ELFCLASS32)) {
        arch = SPARC32;
    } else if (emach == EM_MIPS && eclass == ELFCLASS32) {
        arch = Mips;
        if (edata != ELFDATA2LSB) {
            fatal("The binary you're trying to load is compiled for big "
                  "endian MIPS. gem5\nonly supports little endian MIPS. "
                  "Please recompile your binary.\n");
        }
    } else if (emach == EM_X86_64 && eclass == ELFCLASS64) {
        arch = X86_64;
    } else if (emach == EM_386 && eclass == ELFCLASS32) {
        arch = I386;
    } else if (emach == EM_ARM && eclass == ELFCLASS32) {
        arch = bits(ehdr.e_entry, 0) ? Thumb : Arm;
    } else if (emach == EM_AARCH64 && eclass == ELFCLASS64) {
        arch = Arm64;
    } else if (emach == EM_RISCV) {
        arch = (eclass == ELFCLASS64) ? Riscv64 : Riscv32;
    } else if (emach == EM_PPC && eclass == ELFCLASS32) {
        arch = Power;
        if (edata != ELFDATA2MSB) {
            fatal("The binary you're trying to load is compiled for "
                  "little endian Power.\ngem5 only supports big "
                  "endian Power. Please recompile your binary.\n");
        }
    } else if (emach == EM_PPC64) {
        fatal("The binary you're trying to load is compiled for 64-bit "
              "Power. M5\n only supports 32-bit Power. Please "
              "recompile your binary.\n");
    } else if (eclass == ELFCLASS64) {
        // Since we don't know how to check for alpha right now, we'll
        // just assume if it wasn't something else and it's 64 bit, that's
        // what it must be.
        arch = Alpha;
    } else {
        warn("Unknown architecture: %d\n", emach);
    }
}

void
ElfObject::determineOpSys()
{
    // Detect the operating system
    switch (ehdr.e_ident[EI_OSABI]) {
      case ELFOSABI_LINUX:
        opSys = Linux;
        return;
      case ELFOSABI_SOLARIS:
        opSys = Solaris;
        return;
      case ELFOSABI_TRU64:
        opSys = Tru64;
        return;
      case ELFOSABI_ARM:
        opSys = LinuxArmOABI;
        return;
      case ELFOSABI_FREEBSD:
        opSys = FreeBSD;
        return;
      default:
        opSys = UnknownOpSys;
    }

    Elf_Scn *section = elf_getscn(elf, 1);
    for (int sec_idx = 1; section; section = elf_getscn(elf, ++sec_idx)) {
        GElf_Shdr shdr;
        gelf_getshdr(section, &shdr);

        char *e_str = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name);
        if (shdr.sh_type == SHT_NOTE && !strcmp(".note.ABI-tag", e_str)) {
            // we have found a ABI note section
            // Check the 5th 32bit word for OS  0 == linux, 1 == hurd,
            // 2 == solaris, 3 == freebsd
            Elf_Data *raw_data = elf_rawdata(section, nullptr);
            assert(raw_data && raw_data->d_buf);

            uint32_t raw_abi = ((uint32_t *)raw_data->d_buf)[4];
            bool is_le = ehdr.e_ident[EI_DATA] == ELFDATA2LSB;
            uint32_t os_abi = is_le ? htole(raw_abi) : htobe(raw_abi);

            switch (os_abi) {
              case 0:
                opSys = Linux;
                return;
              case 1:
                fatal("gem5 does not support the HURD ABI.\n");
              case 2:
                opSys = Solaris;
                return;
              case 3:
                opSys = FreeBSD;
                return;
            }
        }

        if (!strcmp(".SUNW_version", e_str) || !strcmp(".stab.index", e_str)) {
            opSys = Solaris;
            return;
        }
    }
}

void
ElfObject::handleLoadableSegment(GElf_Phdr phdr, int seg_num)
{
    auto name = std::to_string(seg_num);

    image.addSegment({ name, phdr.p_paddr, imageData,
                       phdr.p_offset, phdr.p_filesz });
    Addr uninitialized = phdr.p_memsz - phdr.p_filesz;
    if (uninitialized) {
        // There may be parts of a segment which aren't included in the
        // file. In those cases, we need to create a new segment with no
        // data to take up the extra space. This should be zeroed when
        // loaded into memory.
        image.addSegment({ name + "(uninitialized)",
                           phdr.p_paddr + phdr.p_filesz, uninitialized });
    }

    const Addr file_start = phdr.p_offset;
    const Addr file_end = file_start + phdr.p_filesz;

    // If there is a program header table, figure out the virtual
    // address of the header table in the final memory image. We use
    // the program headers themselves to translate from a file offset
    // to the address in the image.
    if (file_start <= ehdr.e_phoff && file_end > ehdr.e_phoff)
        _programHeaderTable = phdr.p_vaddr + (ehdr.e_phoff - file_start);
}

ElfObject::~ElfObject()
{
    elf_end(elf);
}

bool
ElfObject::loadSomeSymbols(SymbolTable *symtab, int binding, Addr mask,
                           Addr base, Addr offset)
{
    if (!symtab)
        return false;

    // check that header matches library version
    if (elf_version(EV_CURRENT) == EV_NONE)
        panic("wrong elf version number!");

    // get a pointer to elf structure
    Elf *elf = elf_memory((char *)const_cast<uint8_t *>(
                imageData->data()), imageData->len());
    assert(elf != NULL);

    // Get the first section
    int sec_idx = 1; // there is a 0 but it is nothing, go figure
    Elf_Scn *section = elf_getscn(elf, sec_idx);

    // While there are no more sections
    bool found = false;
    while (section != NULL) {
        GElf_Shdr shdr;
        gelf_getshdr(section, &shdr);

        if (shdr.sh_type == SHT_SYMTAB) {
            found = true;
            Elf_Data *data = elf_getdata(section, NULL);
            int count = shdr.sh_size / shdr.sh_entsize;
            DPRINTF(Loader, "Found Symbol Table, %d symbols present\n", count);

            // loop through all the symbols, only loading global ones
            for (int i = 0; i < count; ++i) {
                GElf_Sym sym;
                gelf_getsym(data, i, &sym);
                if (GELF_ST_BIND(sym.st_info) == binding) {
                    char *sym_name =
                        elf_strptr(elf, shdr.sh_link, sym.st_name);
                    if (sym_name && sym_name[0] != '$') {
                        Addr value = sym.st_value - base + offset;
                        if (symtab->insert(value & mask, sym_name)) {
                            DPRINTF(Loader, "Symbol: %-40s value %#x\n",
                                    sym_name, value);
                        }
                    }
                }
            }
        }
        ++sec_idx;
        section = elf_getscn(elf, sec_idx);
    }

    elf_end(elf);

    return found;
}

bool
ElfObject::loadAllSymbols(SymbolTable *symtab, Addr base, Addr offset,
                          Addr addr_mask)
{
    return (loadGlobalSymbols(symtab, base, offset, addr_mask) &&
            loadLocalSymbols(symtab, base, offset, addr_mask) &&
            loadWeakSymbols(symtab, base, offset, addr_mask));
}

bool
ElfObject::loadGlobalSymbols(SymbolTable *symtab, Addr base, Addr offset,
                             Addr addr_mask)
{
    if (interpreter) {
        interpreter->loadSomeSymbols(symtab, STB_GLOBAL, addr_mask,
                                     base, offset);
    }
    return loadSomeSymbols(symtab, STB_GLOBAL, addr_mask, base, offset);
}

bool
ElfObject::loadLocalSymbols(SymbolTable *symtab, Addr base, Addr offset,
                            Addr addr_mask)
{
    if (interpreter) {
        interpreter->loadSomeSymbols(symtab, STB_LOCAL, addr_mask,
                                     base, offset);
    }
    return loadSomeSymbols(symtab, STB_LOCAL, addr_mask, base, offset);
}

bool
ElfObject::loadWeakSymbols(SymbolTable *symtab, Addr base, Addr offset,
                           Addr addr_mask)
{
    if (interpreter) {
        interpreter->loadSomeSymbols(symtab, STB_WEAK, addr_mask,
                                     base, offset);
    }
    return loadSomeSymbols(symtab, STB_WEAK, addr_mask, base, offset);
}

void
ElfObject::getSections()
{
    assert(!sectionNames.size());

    // check that header matches library version
    if (elf_version(EV_CURRENT) == EV_NONE)
        panic("wrong elf version number!");

    // get a pointer to elf structure
    Elf *elf =
        elf_memory((char *)const_cast<uint8_t *>(imageData->data()),
                imageData->len());
    assert(elf != NULL);

    // Check that we actually have a elf file
    GElf_Ehdr ehdr;
    if (gelf_getehdr(elf, &ehdr) ==0) {
        panic("Not ELF, shouldn't be here");
    }

    // Get the first section
    int sec_idx = 1; // there is a 0 but it is nothing, go figure
    Elf_Scn *section = elf_getscn(elf, sec_idx);

    // While there are no more sections
    while (section) {
        GElf_Shdr shdr;
        gelf_getshdr(section, &shdr);
        sectionNames.insert(elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name));
        section = elf_getscn(elf, ++sec_idx);
    } // while sections

    elf_end(elf);
}

bool
ElfObject::sectionExists(std::string sec)
{
    if (!sectionNames.size())
        getSections();

    return sectionNames.find(sec) != sectionNames.end();
}


void
ElfObject::updateBias(Addr bias_addr)
{
    // Record the bias.
    ldBias = bias_addr;

    // Patch the entry point with bias_addr.
    entry += bias_addr;

    // Patch segments with the bias_addr.
    image.offset(bias_addr);
}
