diff --git a/lib/sass/elf.rb b/lib/sass/elf.rb index 775deb41..4fb1aa3b 100644 --- a/lib/sass/elf.rb +++ b/lib/sass/elf.rb @@ -7,73 +7,30 @@ module Sass # @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 - module PackInfo - PACK_MAP = { - Elf32_Ehdr: 'S<2L<5S<6', - Elf64_Ehdr: 'S<2L').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 @@ -92,6 +49,8 @@ module PackInfo PT_LOPROC = 0x70000000 PT_HIPROC = 0x7fffffff + PN_XNUM = 0xffff + # These constants define the different elf file types ET_NONE = 0 ET_REL = 1 @@ -103,6 +62,154 @@ module PackInfo 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') - [PackInfo::STRUCT_MAP[type], @buffer.read(size).unpack(format)].transpose.to_h - end - INTERPRETER = begin proc_self_exe = '/proc/self/exe' if File.exist?(proc_self_exe) diff --git a/spec/sass/elf_spec.rb b/spec/sass/elf_spec.rb index 024b2611..f6b20fa2 100644 --- a/spec/sass/elf_spec.rb +++ b/spec/sass/elf_spec.rb @@ -27,4 +27,12 @@ .to eq(File.basename(described_class::INTERPRETER)) end end + + it 'dumps elf headers' do + input = StringIO.new(File.binread('/proc/self/exe')) + output = StringIO.new.binmode + + described_class.new(input).dump(output) + expect(output.string).to eq(input.string.slice(0, output.length)) + end end