# frozen_string_literal: true module Sass # The {ELF} class. # # It parses ELF header to extract interpreter. # @see https://github.com/torvalds/linux/blob/HEAD/include/uapi/linux/elf.h # @see https://github.com/torvalds/linux/blob/HEAD/kernel/kexec_elf.c class ELF # The {PackInfo} class. class PackInfo def initialize(format:, sizeof:, struct:) @format_le = format.freeze @format_be = format.tr('<', '>').freeze @sizeof = sizeof.freeze @struct = struct.freeze end attr_reader :sizeof def pack(io, data, little_endian) raise ArgumentError if io.write(data.values_at(*@struct).pack(format(little_endian))) != @sizeof end def unpack(io, little_endian) @struct.zip(io.read(@sizeof).unpack(format(little_endian))).to_h end private def format(little_endian) little_endian ? @format_le : @format_be end end private_constant :PackInfo # These constants are for the segment types stored in the image headers PT_NULL = 0 PT_LOAD = 1 PT_DYNAMIC = 2 PT_INTERP = 3 PT_NOTE = 4 PT_SHLIB = 5 PT_PHDR = 6 PT_TLS = 7 PT_LOOS = 0x60000000 PT_HIOS = 0x6fffffff PT_LOPROC = 0x70000000 PT_HIPROC = 0x7fffffff PN_XNUM = 0xffff # These constants define the different elf file types ET_NONE = 0 ET_REL = 1 ET_EXEC = 2 ET_DYN = 3 ET_CORE = 4 ET_LOPROC = 0xff00 ET_HIPROC = 0xffff EI_NIDENT = 16 Elf32_Ehdr = PackInfo.new( format: "a#{EI_NIDENT}S<2L<5S<6", sizeof: 52, struct: %i[ e_ident e_type e_machine e_version e_entry e_phoff e_shoff e_flags e_ehsize e_phentsize e_phnum e_shentsize e_shnum e_shstrndx ] ).freeze Elf64_Ehdr = PackInfo.new( format: "a#{EI_NIDENT}S<2L