//===-- AuxVector.cpp -------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// C Includes
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

// C++ Includes
// Other libraries and framework includes
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Log.h"
#include "lldb/Target/Process.h"

#include "AuxVector.h"

using namespace lldb;
using namespace lldb_private;

static bool
GetMaxU64(DataExtractor &data,
          uint32_t *offset, uint64_t *value, unsigned int byte_size)
{
    uint32_t saved_offset = *offset;
    *value = data.GetMaxU64(offset, byte_size);
    return *offset != saved_offset;
}

static bool
ParseAuxvEntry(DataExtractor &data, AuxVector::Entry &entry, 
               uint32_t *offset, unsigned int byte_size)
{
    if (!GetMaxU64(data, offset, &entry.type, byte_size))
        return false;

    if (!GetMaxU64(data, offset, &entry.value, byte_size))
        return false;

    return true;
}

DataBufferSP
AuxVector::GetAuxvData()
{
    static const size_t path_size = 128;
    static char path[path_size];
    DataBufferSP buf_sp;
    int fd;

    // Ideally, we would simply create a FileSpec and call ReadFileContents.
    // However, files in procfs have zero size (since they are, in general,
    // dynamically generated by the kernel) which is incompatible with the
    // current ReadFileContents implementation.  Therefore we simply stream the
    // data into a DataBuffer ourselves.
    if (snprintf(path, path_size, "/proc/%d/auxv", m_process->GetID()) < 0)
        return buf_sp;

    if ((fd = open(path, O_RDONLY, 0)) < 0)
        return buf_sp;

    size_t bytes_read = 0;
    std::auto_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
    for (;;) 
    {
        size_t avail = buf_ap->GetByteSize() - bytes_read;
        ssize_t status = read(fd, buf_ap->GetBytes() + bytes_read, avail);

        if (status < 0) 
            break;

        bytes_read += status;

        if (status == 0) 
        {
            buf_ap->SetByteSize(bytes_read);
            buf_sp.reset(buf_ap.release());
            break;
        }

        if (avail - status == 0)
            buf_ap->SetByteSize(2 * buf_ap->GetByteSize());
    }

    return buf_sp;
}

void
AuxVector::ParseAuxv(DataExtractor &data)
{
    const unsigned int byte_size  = m_process->GetAddressByteSize();
    uint32_t offset = 0;

    for (;;) 
    {
        Entry entry;

        if (!ParseAuxvEntry(data, entry, &offset, byte_size))
            break;

        if (entry.type == AT_NULL)
            break;

        if (entry.type == AT_IGNORE)
            continue;

        m_auxv.push_back(entry);
    }
}

AuxVector::AuxVector(Process *process)
    : m_process(process)
{
    DataExtractor data;
    LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));

    data.SetData(GetAuxvData());
    data.SetByteOrder(m_process->GetByteOrder());
    data.SetAddressByteSize(m_process->GetAddressByteSize());
    
    ParseAuxv(data);

    if (log)
        DumpToLog(log);
}

AuxVector::iterator 
AuxVector::FindEntry(EntryType type) const
{
    for (iterator I = begin(); I != end(); ++I)
    {
        if (I->type == static_cast<uint64_t>(type))
            return I;
    }

    return end();
}

void
AuxVector::DumpToLog(LogSP log) const
{
    if (!log)
        return;

    log->PutCString("AuxVector: ");
    for (iterator I = begin(); I != end(); ++I)
    {
        log->Printf("   %s [%d]: %lx", GetEntryName(*I), I->type, I->value);
    }
}

const char *
AuxVector::GetEntryName(EntryType type)
{
    const char *name;

#define ENTRY_NAME(_type) _type: name = #_type
    switch (type) 
    {
    default:
        name = "unkown";
        break;

    case ENTRY_NAME(AT_NULL);   break;
    case ENTRY_NAME(AT_IGNORE); break;
    case ENTRY_NAME(AT_EXECFD); break;
    case ENTRY_NAME(AT_PHDR);   break;
    case ENTRY_NAME(AT_PHENT);  break;
    case ENTRY_NAME(AT_PHNUM);  break;
    case ENTRY_NAME(AT_PAGESZ); break;
    case ENTRY_NAME(AT_BASE);   break;
    case ENTRY_NAME(AT_FLAGS);  break;
    case ENTRY_NAME(AT_ENTRY);  break;
    case ENTRY_NAME(AT_NOTELF); break;
    case ENTRY_NAME(AT_UID);    break;
    case ENTRY_NAME(AT_EUID);   break;
    case ENTRY_NAME(AT_GID);    break;
    case ENTRY_NAME(AT_EGID);   break;
    case ENTRY_NAME(AT_CLKTCK); break;
    }
#undef ENTRY_NAME

    return name;
}

