/*
 * 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 = (ehdr.e_ident[EI_CLASS] == ELFCLASS64) ? Riscv64 : Riscv32;
    } 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.base = data.base = bss.base = 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.base = phdr.p_paddr + phdr.p_filesz;
            bss.size = phdr.p_memsz - phdr.p_filesz;
            bss.data = nullptr;
        }

        // 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.base = phdr.p_paddr;
            text.size = phdr.p_filesz;
            text.data = fileData + phdr.p_offset;
        } else if (phdr.p_vaddr <= data_sec_start &&
                   phdr.p_vaddr + phdr.p_filesz > data_sec_start) {
            data.base = phdr.p_paddr;
            data.size = phdr.p_filesz;
            data.data = fileData + phdr.p_offset;
        } else {
            // If it's none of the above but is loadable,
            // load the filesize worth of data
            Segment extra;
            extra.base = phdr.p_paddr;
            extra.size = phdr.p_filesz;
            extra.data = 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: %#x %d\ndata: %#x %d\nbss: %#x %d\n",
             text.base, text.size, data.base, data.size,
             bss.base, 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::loadSegments(const PortProxy& mem_proxy, Addr addr_mask,
                        Addr offset)
{
    if (!ObjectFile::loadSegments(mem_proxy, addr_mask, offset))
        return false;

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

    if (interpreter)
        interpreter->loadSegments(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.base += bias_addr;
    data.base += bias_addr;
    bss.base  += bias_addr;
    for (auto &segment : extraSegments)
        segment.base += bias_addr;
}
