| 41 | } |
| 42 | |
| 43 | void ElfCoreStream::plan() { |
| 44 | // Filter to readable, non-empty VMAs. No size cap any more — streaming |
| 45 | // means a 5 GiB process produces a 5 GiB virtual file at zero RAM cost. |
| 46 | std::vector<const Vma*> use; |
| 47 | use.reserve(vmas_.size()); |
| 48 | for (auto& v : vmas_) { |
| 49 | if (!v.readable()) continue; |
| 50 | if (v.size() == 0) continue; |
| 51 | use.push_back(&v); |
| 52 | } |
| 53 | |
| 54 | // Layout: [Ehdr][N × Phdr][padding to kHdrAlign][segment 0 data][seg 1]… |
| 55 | const std::size_t hdr_struct_size = |
| 56 | sizeof(Elf64_Ehdr) + use.size() * sizeof(Elf64_Phdr); |
| 57 | const std::size_t hdr_padded = |
| 58 | (hdr_struct_size + (kHdrAlign - 1)) & ~(kHdrAlign - 1); |
| 59 | |
| 60 | header_blob_.assign(hdr_padded, 0); |
| 61 | |
| 62 | Elf64_Ehdr eh{}; |
| 63 | std::memcpy(eh.e_ident, "\x7f""ELF", 4); |
| 64 | eh.e_ident[4] = 2; // ELFCLASS64 |
| 65 | eh.e_ident[5] = 1; // ELFDATA2LSB |
| 66 | eh.e_ident[6] = 1; // EV_CURRENT |
| 67 | eh.e_type = ET_CORE; |
| 68 | eh.e_machine = EM_X86_64; |
| 69 | eh.e_version = 1; |
| 70 | eh.e_phoff = sizeof(Elf64_Ehdr); |
| 71 | eh.e_ehsize = sizeof(Elf64_Ehdr); |
| 72 | eh.e_phentsize = sizeof(Elf64_Phdr); |
| 73 | eh.e_phnum = static_cast<u16>(use.size()); |
| 74 | std::memcpy(header_blob_.data(), &eh, sizeof(eh)); |
| 75 | |
| 76 | Elf64_Phdr* phdrs = reinterpret_cast<Elf64_Phdr*>( |
| 77 | header_blob_.data() + sizeof(Elf64_Ehdr)); |
| 78 | |
| 79 | u64 file_off = hdr_padded; |
| 80 | segs_.reserve(use.size()); |
| 81 | for (std::size_t i = 0; i < use.size(); ++i) { |
| 82 | const Vma& v = *use[i]; |
| 83 | const u64 sz = v.size(); |
| 84 | |
| 85 | Elf64_Phdr& ph = phdrs[i]; |
| 86 | std::memset(&ph, 0, sizeof(ph)); |
| 87 | ph.p_type = PT_LOAD; |
| 88 | ph.p_flags = (v.executable() ? PF_X : 0) | |
| 89 | (v.writable() ? PF_W : 0) | |
| 90 | (v.readable() ? PF_R : 0); |
| 91 | ph.p_offset = file_off; |
| 92 | ph.p_vaddr = v.vm_start; |
| 93 | ph.p_paddr = 0; |
| 94 | ph.p_filesz = sz; |
| 95 | ph.p_memsz = sz; |
| 96 | ph.p_align = 0x1000; |
| 97 | |
| 98 | segs_.push_back({ file_off, sz, v.vm_start }); |
| 99 | file_off += sz; |
| 100 | } |
nothing calls this directly
no test coverage detected