: in(path, 0)
{
    
    elf_size = in.buffer().size();
    if (elf_size < sizeof(ElfEhdr))
        throw Exception("The size of supposedly ELF file is too small", ErrorCodes::CANNOT_PARSE_ELF);
    mapped = in.buffer().begin();
    header = reinterpret_cast<const ElfEhdr *>(mapped);
    if (memcmp(header->e_ident, "\x7F""ELF", 4) != 0)
        throw Exception("The file is not ELF according to magic", ErrorCodes::CANNOT_PARSE_ELF);
    
    ElfOff section_header_offset = header->e_shoff;
    uint16_t section_header_num_entries = header->e_shnum;
    if (!section_header_offset
        || !section_header_num_entries
        || section_header_offset + section_header_num_entries * sizeof(ElfShdr) > elf_size)
        throw Exception("The ELF is truncated (section header points after end of file)", ErrorCodes::CANNOT_PARSE_ELF);
    section_headers = reinterpret_cast<const ElfShdr *>(mapped + section_header_offset);
    
    auto section_names_strtab = findSection([&](const Section & section, size_t idx)
    {
        return section.header.sh_type == SHT_STRTAB && header->e_shstrndx == idx;
    });
    if (!section_names_strtab)
        throw Exception("The ELF doesn't have string table with section names", ErrorCodes::CANNOT_PARSE_ELF);
    ElfOff section_names_offset = section_names_strtab->header.sh_offset;