std::shared_ptr<TSocketWriteThread> THttpConnection::CreateWriteThread(std::shared_ptr<SoySocket> Socket,SoyRef ConnectionRef)
{
	std::shared_ptr<TSocketWriteThread> WriteThread( new THttpWriteThread(Socket,ConnectionRef) );
	WriteThread->mOnStreamError.AddListener( mOnError );
	WriteThread->Start();
	return WriteThread;
}
Exemple #2
0
// Write the core dump file:
//   ELF header
//   Single section header (Shdr) for 64 bit program header count
//   Phdr for the PT_NOTE
//   PT_LOAD
//   PT_NOTEs
//      process info (prpsinfo_t)
//      NT_FILE entries
//      threads
//      alignment
//   memory blocks
bool
DumpWriter::WriteDump()
{
    // Write the ELF header
    Ehdr ehdr;
    memset(&ehdr, 0, sizeof(Ehdr));
    ehdr.e_ident[0] = ELFMAG0;
    ehdr.e_ident[1] = ELFMAG1;
    ehdr.e_ident[2] = ELFMAG2;
    ehdr.e_ident[3] = ELFMAG3;
    ehdr.e_ident[4] = ELF_CLASS;

    // Note: The sex is the current system running minidump-2-core
    //       Big or Little endian.  This means you have to create
    //       the core (minidump-2-core) on the system that matches
    //       your intent to debug properly.
    ehdr.e_ident[5] = sex() ? ELFDATA2MSB : ELFDATA2LSB;
    ehdr.e_ident[6] = EV_CURRENT;
    ehdr.e_ident[EI_OSABI] = ELFOSABI_LINUX;

    ehdr.e_type = ET_CORE;
    ehdr.e_machine = ELF_ARCH;
    ehdr.e_version = EV_CURRENT;
    ehdr.e_shoff = sizeof(Ehdr);
    ehdr.e_phoff = sizeof(Ehdr) + sizeof(Shdr);

    ehdr.e_ehsize = sizeof(Ehdr);
    ehdr.e_phentsize = sizeof(Phdr);
    ehdr.e_shentsize = sizeof(Shdr);

    // The ELF header only allows UINT16 for the number of program
    // headers. In a core dump this equates to PT_NODE and PT_LOAD.
    //
    // When more program headers than 65534 the first section entry
    // is used to store the actual program header count.

    // PT_NOTE + number of memory regions
    uint64_t phnum = 1 + m_crashInfo.MemoryRegions().size();

    if (phnum < PH_HDR_CANARY) {
        ehdr.e_phnum = phnum;
    }
    else {
        ehdr.e_phnum = PH_HDR_CANARY;
    }

    if (!WriteData(&ehdr, sizeof(Ehdr))) {
        return false;
    }

    size_t offset = sizeof(Ehdr) + sizeof(Shdr) + (phnum * sizeof(Phdr));
    size_t filesz = GetProcessInfoSize() + GetAuxvInfoSize() + GetThreadInfoSize() + GetNTFileInfoSize();

    // Add single section containing the actual count
    // of the program headers to be written.
    Shdr shdr;
    memset(&shdr, 0, sizeof(shdr));
    shdr.sh_info = phnum;
    // When section header offset is present but ehdr section num = 0
    // then is is expected that the sh_size indicates the size of the
    // section array or 1 in our case.
    shdr.sh_size = 1;
    if (!WriteData(&shdr, sizeof(shdr))) {
        return false;
    }

    // PT_NOTE header
    Phdr phdr;
    memset(&phdr, 0, sizeof(Phdr));
    phdr.p_type = PT_NOTE;
    phdr.p_offset = offset;
    phdr.p_filesz = filesz;

    if (!WriteData(&phdr, sizeof(phdr))) {
        return false;
    }

    // PT_NOTE sections must end on 4 byte boundary
    // We output the NT_FILE, AUX and Thread entries
    // AUX is aligned, NT_FILE is aligned and then we
    // check to pad end of the thread list
    phdr.p_type = PT_LOAD;
    phdr.p_align = 4096;

    size_t finalNoteAlignment = phdr.p_align - ((offset + filesz) % phdr.p_align);
    if (finalNoteAlignment == phdr.p_align) {
        finalNoteAlignment = 0;
    }
    offset += finalNoteAlignment;

    TRACE("Writing memory region headers to core file\n");

    // Write memory region note headers
    for (const MemoryRegion& memoryRegion : m_crashInfo.MemoryRegions())
    {
        phdr.p_flags = memoryRegion.Permissions();
        phdr.p_vaddr = memoryRegion.StartAddress();
        phdr.p_memsz = memoryRegion.Size();

        offset += filesz;
        phdr.p_filesz = filesz = memoryRegion.Size();
        phdr.p_offset = offset;

        if (!WriteData(&phdr, sizeof(phdr))) {
            return false;
        }
    }

    // Write process info data to core file
    if (!WriteProcessInfo()) {
        return false;
    }

    // Write auxv data to core file
    if (!WriteAuxv()) {
        return false;
    }

    // Write NT_FILE entries to the core file
    if (!WriteNTFileInfo()) {
        return false;
    }

    TRACE("Writing %ld thread entries to core file\n", m_crashInfo.Threads().size());

    // Write all the thread's state and registers
    for (const ThreadInfo* thread : m_crashInfo.Threads()) 
    {
        if (!WriteThread(*thread, SIGABRT)) {
            return false;
        }
    }

    // Zero out the end of the PT_NOTE section to the boundary
    // and then laydown the memory blocks
    if (finalNoteAlignment > 0) {
        assert(finalNoteAlignment < sizeof(m_tempBuffer));
        memset(m_tempBuffer, 0, finalNoteAlignment);
        if (!WriteData(m_tempBuffer, finalNoteAlignment)) {
            return false;
        }
    }

    TRACE("Writing %ld memory regions to core file\n", m_crashInfo.MemoryRegions().size());

    // Read from target process and write memory regions to core
    uint64_t total = 0;
    for (const MemoryRegion& memoryRegion : m_crashInfo.MemoryRegions())
    {
        uint32_t size = memoryRegion.Size();
        uint64_t address = memoryRegion.StartAddress();
        total += size;

        while (size > 0)
        {
            uint32_t bytesToRead = std::min(size, (uint32_t)sizeof(m_tempBuffer));
            uint32_t read = 0;

            if (FAILED(m_crashInfo.DataTarget()->ReadVirtual(address, m_tempBuffer, bytesToRead, &read))) {
                fprintf(stderr, "ReadVirtual(%016lx, %08x) FAILED\n", address, bytesToRead);
                return false;
            }

            if (!WriteData(m_tempBuffer, read)) {
                return false;
            }

            address += read;
            size -= read;
        }
    }

    printf("Written %ld bytes (%ld pages) to core file\n", total, total >> PAGE_SHIFT);

    return true;
}