/*
 * 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%09"PRIx64"\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)
{
    GError *gerr = NULL;
    int err = 0;
    void *map;

    reader->gmf = g_mapped_file_new(name, TRUE, &gerr);
    if (gerr) {
        eprintf("Failed to map PDB file \'%s\'\n", name);
        return 1;
    }

    reader->file_size = g_mapped_file_get_length(reader->gmf);
    map = g_mapped_file_get_contents(reader->gmf);
    if (pdb_reader_init(reader, map)) {
        err = 1;
        goto out_unmap;
    }

    return 0;

out_unmap:
    g_mapped_file_unref(reader->gmf);

    return err;
}

void pdb_exit(struct pdb_reader *reader)
{
    g_mapped_file_unref(reader->gmf);
    pdb_reader_exit(reader);
}
