/*
 * Copyright (c) 2018 Virtuozzo International GmbH
 *
 * Based on source of Wine project
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "qemu/osdep.h"
#include "pdb.h"
#include "err.h"

static uint32_t pdb_get_file_size(const struct pdb_reader *r, unsigned idx)
{
    return r->ds.toc->file_size[idx];
}

static pdb_seg *get_seg_by_num(struct pdb_reader *r, size_t n)
{
    size_t i = 0;
    char *ptr;

    for (ptr = r->segs; (ptr < r->segs + r->segs_size); ) {
        i++;
        ptr += 8;
        if (i == n) {
            break;
        }
        ptr += sizeof(pdb_seg);
    }

    return (pdb_seg *)ptr;
}

uint64_t pdb_find_public_v3_symbol(struct pdb_reader *r, const char *name)
{
    size_t size = pdb_get_file_size(r, r->symbols->gsym_file);
    int length;
    const union codeview_symbol *sym;
    const uint8_t *root = r->modimage;
    size_t i;

    for (i = 0; i < size; i += length) {
        sym = (const void *)(root + i);
        length = sym->generic.len + 2;

        if (!sym->generic.id || length < 4) {
            break;
        }

        if (sym->generic.id == S_PUB_V3 &&
                !strcmp(name, sym->public_v3.name)) {
            pdb_seg *segment = get_seg_by_num(r, sym->public_v3.segment);
            uint32_t sect_rva = segment->dword[1];
            uint64_t rva = sect_rva + sym->public_v3.offset;

            printf("%s: 0x%016x(%d:\'%.8s\') + 0x%08x = 0x%09lx\n", name,
                    sect_rva, sym->public_v3.segment,
                    ((char *)segment - 8), sym->public_v3.offset, rva);
            return rva;
        }
    }

    return 0;
}

uint64_t pdb_resolve(uint64_t img_base, struct pdb_reader *r, const char *name)
{
    uint64_t rva = pdb_find_public_v3_symbol(r, name);

    if (!rva) {
        return 0;
    }

    return img_base + rva;
}

static void pdb_reader_ds_exit(struct pdb_reader *r)
{
    free(r->ds.toc);
}

static void pdb_exit_symbols(struct pdb_reader *r)
{
    free(r->modimage);
    free(r->symbols);
}

static void pdb_exit_segments(struct pdb_reader *r)
{
    free(r->segs);
}

static void *pdb_ds_read(const PDB_DS_HEADER *header,
        const uint32_t *block_list, int size)
{
    int i, nBlocks;
    uint8_t *buffer;

    if (!size) {
        return NULL;
    }

    nBlocks = (size + header->block_size - 1) / header->block_size;

    buffer = malloc(nBlocks * header->block_size);
    if (!buffer) {
        return NULL;
    }

    for (i = 0; i < nBlocks; i++) {
        memcpy(buffer + i * header->block_size, (const char *)header +
                block_list[i] * header->block_size, header->block_size);
    }

    return buffer;
}

static void *pdb_ds_read_file(struct pdb_reader* r, uint32_t file_number)
{
    const uint32_t *block_list;
    uint32_t block_size;
    const uint32_t *file_size;
    size_t i;

    if (!r->ds.toc || file_number >= r->ds.toc->num_files) {
        return NULL;
    }

    file_size = r->ds.toc->file_size;
    r->file_used[file_number / 32] |= 1 << (file_number % 32);

    if (file_size[file_number] == 0 || file_size[file_number] == 0xFFFFFFFF) {
        return NULL;
    }

    block_list = file_size + r->ds.toc->num_files;
    block_size = r->ds.header->block_size;

    for (i = 0; i < file_number; i++) {
        block_list += (file_size[i] + block_size - 1) / block_size;
    }

    return pdb_ds_read(r->ds.header, block_list, file_size[file_number]);
}

static int pdb_init_segments(struct pdb_reader *r)
{
    char *segs;
    unsigned stream_idx = r->sidx.segments;

    segs = pdb_ds_read_file(r, stream_idx);
    if (!segs) {
        return 1;
    }

    r->segs = segs;
    r->segs_size = pdb_get_file_size(r, stream_idx);

    return 0;
}

static int pdb_init_symbols(struct pdb_reader *r)
{
    int err = 0;
    PDB_SYMBOLS *symbols;
    PDB_STREAM_INDEXES *sidx = &r->sidx;

    memset(sidx, -1, sizeof(*sidx));

    symbols = pdb_ds_read_file(r, 3);
    if (!symbols) {
        return 1;
    }

    r->symbols = symbols;

    if (symbols->stream_index_size != sizeof(PDB_STREAM_INDEXES)) {
        err = 1;
        goto out_symbols;
    }

    memcpy(sidx, (const char *)symbols + sizeof(PDB_SYMBOLS) +
            symbols->module_size + symbols->offset_size +
            symbols->hash_size + symbols->srcmodule_size +
            symbols->pdbimport_size + symbols->unknown2_size, sizeof(*sidx));

    /* Read global symbol table */
    r->modimage = pdb_ds_read_file(r, symbols->gsym_file);
    if (!r->modimage) {
        err = 1;
        goto out_symbols;
    }

    return 0;

out_symbols:
    free(symbols);

    return err;
}

static int pdb_reader_ds_init(struct pdb_reader *r, PDB_DS_HEADER *hdr)
{
    memset(r->file_used, 0, sizeof(r->file_used));
    r->ds.header = hdr;
    r->ds.toc = pdb_ds_read(hdr, (uint32_t *)((uint8_t *)hdr +
                hdr->toc_page * hdr->block_size), hdr->toc_size);

    if (!r->ds.toc) {
        return 1;
    }

    return 0;
}

static int pdb_reader_init(struct pdb_reader *r, void *data)
{
    int err = 0;
    const char pdb7[] = "Microsoft C/C++ MSF 7.00";

    if (memcmp(data, pdb7, sizeof(pdb7) - 1)) {
        return 1;
    }

    if (pdb_reader_ds_init(r, data)) {
        return 1;
    }

    r->ds.root = pdb_ds_read_file(r, 1);
    if (!r->ds.root) {
        err = 1;
        goto out_ds;
    }

    if (pdb_init_symbols(r)) {
        err = 1;
        goto out_root;
    }

    if (pdb_init_segments(r)) {
        err = 1;
        goto out_sym;
    }

    return 0;

out_sym:
    pdb_exit_symbols(r);
out_root:
    free(r->ds.root);
out_ds:
    pdb_reader_ds_exit(r);

    return err;
}

static void pdb_reader_exit(struct pdb_reader *r)
{
    pdb_exit_segments(r);
    pdb_exit_symbols(r);
    free(r->ds.root);
    pdb_reader_ds_exit(r);
}

int pdb_init_from_file(const char *name, struct pdb_reader *reader)
{
    int err = 0;
    int fd;
    void *map;
    struct stat st;

    fd = open(name, O_RDONLY, 0);
    if (fd == -1) {
        eprintf("Failed to open PDB file \'%s\'\n", name);
        return 1;
    }
    reader->fd = fd;

    fstat(fd, &st);
    reader->file_size = st.st_size;

    map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    if (map == MAP_FAILED) {
        eprintf("Failed to map PDB file\n");
        err = 1;
        goto out_fd;
    }

    if (pdb_reader_init(reader, map)) {
        err = 1;
        goto out_unmap;
    }

    return 0;

out_unmap:
    munmap(map, st.st_size);
out_fd:
    close(fd);

    return err;
}

void pdb_exit(struct pdb_reader *reader)
{
    munmap(reader->ds.header, reader->file_size);
    close(reader->fd);
    pdb_reader_exit(reader);
}
