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; }
// 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; }