/*
 * Copyright (c) 2011-2013 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 *
ElfObject::tryFile(const std::string &fname, size_t len, uint8_t *data,
                   bool skip_interp_check)
{
    // check that header matches library version
    if (elf_version(EV_CURRENT) == EV_NONE)
        panic("wrong elf version number!");

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

    GElf_Ehdr ehdr;
    if (gelf_getehdr(elf, &ehdr) == 0) {
        DPRINTFR(Loader, "Not ELF\n");
        elf_end(elf);
        return NULL;
    }

    // Detect the architecture
    Arch arch = UnknownArch;
    if (ehdr.e_machine == EM_SPARC64 ||
        (ehdr.e_machine == EM_SPARC &&
         ehdr.e_ident[EI_CLASS] == ELFCLASS64) ||
        ehdr.e_machine == EM_SPARCV9) {
        arch = SPARC64;
    } else if (ehdr.e_machine == EM_SPARC32PLUS ||
               (ehdr.e_machine == EM_SPARC &&
                ehdr.e_ident[EI_CLASS] == ELFCLASS32)) {
        arch = SPARC32;
    } else if (ehdr.e_machine == EM_MIPS &&
               ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
        arch = Mips;
        if (ehdr.e_ident[EI_DATA] != 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 (ehdr.e_machine == EM_X86_64 &&
               ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
        arch = X86_64;
    } else if (ehdr.e_machine == EM_386 &&
               ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
        arch = I386;
    } else if (ehdr.e_machine == EM_ARM &&
               ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
        arch = bits(ehdr.e_entry, 0) ? Thumb : Arm;
    } else if (ehdr.e_machine == EM_AARCH64 &&
               ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
        arch = Arm64;
    } else if (ehdr.e_machine == EM_RISCV) {
        arch = Riscv;
    } else if (ehdr.e_machine == EM_PPC &&
               ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
        arch = Power;
        if (ehdr.e_ident[EI_DATA] != 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 (ehdr.e_machine == 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 (ehdr.e_ident[EI_CLASS] == 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", ehdr.e_machine);
        arch = UnknownArch;
    }

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

    // Take a look at the .note.ABI section.
    // It can let us know what's what.
    if (op_sys == UnknownOpSys) {
        int sec_idx = 1;

        // Get the first section
        Elf_Scn *section = elf_getscn(elf, sec_idx);

        // While there are no more sections
        while (section && op_sys == UnknownOpSys) {
            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, NULL);
                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:
                    op_sys = Linux;
                    break;
                  case 1:
                    fatal("gem5 does not support the HURD ABI.\n");
                  case 2:
                    op_sys = Solaris;
                    break;
                  case 3:
                    op_sys = FreeBSD;
                    break;
                }
            } // if section found

            if (!strcmp(".SUNW_version", e_str) ||
                !strcmp(".stab.index", e_str))
                op_sys = Solaris;

            section = elf_getscn(elf, ++sec_idx);
        } // while sections
    }

    ElfObject * result = new ElfObject(fname, len, data, arch, op_sys);

    // The number of headers in the file
    result->_programHeaderCount = ehdr.e_phnum;
    // Record the size of each entry
    result->_programHeaderSize = ehdr.e_phentsize;
    result->_programHeaderTable = 0;
    if (result->_programHeaderCount) { // 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.
        GElf_Phdr phdr;
        uint64_t e_phoff = ehdr.e_phoff;

        for (int i = 0; i < result->_programHeaderCount; i++) {
            gelf_getphdr(elf, i, &phdr);
            // Check if we've found the segment with the headers in it
            if (phdr.p_offset <= e_phoff &&
                phdr.p_offset + phdr.p_filesz > e_phoff) {
                result->_programHeaderTable =
                    phdr.p_paddr + (e_phoff - phdr.p_offset);
                break;
            }
        }
    }

    if (!skip_interp_check) {
        for (int i = 0; i < ehdr.e_phnum; i++) {
            GElf_Phdr phdr;
            M5_VAR_USED void *check_p = gelf_getphdr(elf, i, &phdr);
            assert(check_p != nullptr);

           if (phdr.p_type != PT_INTERP)
                continue;

            char *interp_path = (char*)data + phdr.p_offset;
            int fd = open(interp_path, O_RDONLY);
            if (fd == -1)
                fatal("Unable to open dynamic executable's interpreter.\n");

            struct stat sb;
            M5_VAR_USED int check_i = fstat(fd, &sb);
            assert(check_i == 0);

            void *mm = mmap(nullptr, sb.st_size, PROT_READ,
                            MAP_PRIVATE, fd, 0);
            assert(mm != MAP_FAILED);
            close(fd);

            uint8_t *interp_image = (uint8_t*)mm;
            ObjectFile *obj = tryFile(interp_path, sb.st_size,
                                      interp_image, true);
            assert(obj != nullptr);
            result->interpreter = dynamic_cast<ElfObject*>(obj);
            assert(result->interpreter != nullptr);
            break;
        }
    }

    elf_end(elf);
    return result;
}

ElfObject::ElfObject(const std::string &_filename, size_t _len,
                     uint8_t *_data, Arch _arch, OpSys _op_sys)
    : ObjectFile(_filename, _len, _data, _arch, _op_sys),
      _programHeaderTable(0), _programHeaderSize(0), _programHeaderCount(0),
      interpreter(nullptr), ldBias(0), relocate(true),
      ldMin(std::numeric_limits<Addr>::max()),
      ldMax(std::numeric_limits<Addr>::min())
{
    // 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*)fileData,len);
    assert(elf);

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

    entry = ehdr.e_entry;

    // initialize segment sizes to 0 in case they're not present
    text.size = data.size = bss.size = 0;
    text.baseAddr = data.baseAddr = bss.baseAddr = 0;

    int sec_idx = 1;

    // The first address of some important sections.
    Addr text_sec_start = 0;
    Addr data_sec_start = 0;
    Addr bss_sec_start = 0;

    // Get the first section
    Elf_Scn *section = elf_getscn(elf, sec_idx);

    // Find the beginning of the most interesting sections.
    while (section) {
        GElf_Shdr shdr;
        gelf_getshdr(section, &shdr);
        char *sec_name = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name);

        if (sec_name) {
            if (!strcmp(".text", sec_name)) {
                text_sec_start = shdr.sh_addr;
            } else if (!strcmp(".data", sec_name)) {
                data_sec_start = shdr.sh_addr;
            } else if (!strcmp(".bss", sec_name)) {
                bss_sec_start = shdr.sh_addr;
            }
        } else {
            Elf_Error errorNum = (Elf_Error)elf_errno();
            if (errorNum != ELF_E_NONE) {
                const char *errorMessage = elf_errmsg(errorNum);
                fatal("Error from libelf: %s.\n", errorMessage);
            }
        }

        section = elf_getscn(elf, ++sec_idx);
    }

    // Go through all the segments in the program, record them, and scrape
    // out information about the text, data, and bss areas needed by other
    // code.
    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);
        }

        // for now we don't care about non-loadable segments
        if (!(phdr.p_type & PT_LOAD))
            continue;

        ldMin = std::min(ldMin, phdr.p_vaddr);
        ldMax = std::max(ldMax, phdr.p_vaddr + phdr.p_memsz);

        // Check to see if this segment contains the bss section.
        if (phdr.p_paddr <= bss_sec_start &&
            phdr.p_paddr + phdr.p_memsz > bss_sec_start &&
            phdr.p_memsz - phdr.p_filesz > 0) {
            bss.baseAddr = phdr.p_paddr + phdr.p_filesz;
            bss.size = phdr.p_memsz - phdr.p_filesz;
            bss.fileImage = NULL;
        }

        // Check to see if this is the text or data segment
        if (phdr.p_vaddr <= text_sec_start &&
            phdr.p_vaddr + phdr.p_filesz > text_sec_start) {

            // If this value is nonzero, we need to flip the relocate flag.
            if (phdr.p_vaddr != 0)
                relocate = false;

            text.baseAddr = phdr.p_paddr;
            text.size = phdr.p_filesz;
            text.fileImage = fileData + phdr.p_offset;
        } else if (phdr.p_vaddr <= data_sec_start &&
                   phdr.p_vaddr + phdr.p_filesz > data_sec_start) {
            data.baseAddr = phdr.p_paddr;
            data.size = phdr.p_filesz;
            data.fileImage = fileData + phdr.p_offset;
        } else {
            // If it's none of the above but is loadable,
            // load the filesize worth of data
            Segment extra;
            extra.baseAddr = phdr.p_paddr;
            extra.size = phdr.p_filesz;
            extra.fileImage = fileData + phdr.p_offset;
            extraSegments.push_back(extra);
        }
    }

    // should have found at least one loadable segment
    warn_if(text.size == 0,
            "Empty .text segment in '%s'. ELF file corrupted?\n",
            filename);

    DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n",
             text.baseAddr, text.size, data.baseAddr, data.size,
             bss.baseAddr, bss.size);

    elf_end(elf);

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


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*)fileData,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);
}

bool
ElfObject::loadSections(PortProxy& mem_proxy, Addr addr_mask, Addr offset)
{
    if (!ObjectFile::loadSections(mem_proxy, addr_mask, offset))
        return false;

    for (auto seg : extraSegments) {
        if (!loadSection(&seg, mem_proxy, addr_mask, offset)) {
            return false;
        }
    }

    if (interpreter)
        interpreter->loadSections(mem_proxy, addr_mask, offset);

    return true;
}

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*)fileData,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.
    text.baseAddr += bias_addr;
    data.baseAddr += bias_addr;
    bss.baseAddr  += bias_addr;
    for (auto &segment : extraSegments)
        segment.baseAddr += bias_addr;
}
