The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

ELF::Writer - Encode elf files with pure-perl

VERSION

version 0.011

SYNOPSIS

  my $elf= ELF::Writer::Linux_x86_64->new(
    type => 'executable',
    segments => [{
      virt_addr   => 0x10000,
      data        => $my_machine_code,
    }],
    entry_point => 0x10000,
  );
  $elf->write_file($binary_name);
  
  # Example above wastes almost 4K to align the first segment.
  # We can overlap the first segment with the elf header, so that the entire
  # file gets paged into RAM, but then the entry point needs adjusted by the
  # size of the ELF headers.
  
  my $prog_offset= $elf->elf_header_len + $elf->segment_header_elem_len;
  $elf->segments->[0]->offset(0);
  $elf->segments->[0]->data_start( $prog_offset );
  $elf->entry_point( $elf->segments->[0]->virt_addr + $prog_offset );

MODULE STATUS

I wrote this module while learning the ELF format, so this is not the work of an expert. But, since there wasn't anything on CPAN yet, I decided to implement as complete an API as I could and release it. Bug reports are very welcome.

DESCRPTION

This module lets you define the attributes, segments, and sections of the ELF specification, and then serialize it to a file. All data must reside in memory before writing, so this module is really just a very elaborate call to 'pack'. This module also assumes you know how an ELF file is structured, and the purpose of Segments and Sections. Patches welcome for adding user-friendly features and sanity checks.

ATTRIBUTES

Note on enumerated values: The ELF format has enumerations for many of its fields which are left open-ended to be extended in the future. Also, the symbolic names seem to differ between various sources, so it was difficult to determine what the official names should be. My solution was to store the attribute as the numeric value, but auto-convert symbolic names, and allow access to the symbolic name by a second attribute accessor with suffix "_sym".

class, class_sym

8-bit integer, or one of: "32bit" or "64bit". Must be set before writing.

data, data_sym

8-bit integer, or one of: "2LSB" or "2MSB". (2's complement least/most significant byte first) i.e. little-endian or big-endian

Must be set before writing.

header_version

8-bit integer; defaults to '1' for original version of ELF.

osabi, osabi_sym

8-bit integer, or one of: "SystemV", "HP-UX", "NetBSD", "Linux", "Solaris", "AIX", "IRIX", "FreeBSD", "OpenBSD", "OpenVMS". Must be set before writing.

osabi_version

Depends on osabi. Not used for Linux. Defaults to 0.

type, type_sym

16-bit integer, or one of: "relocatable", "executable", "shared", "core". Must be set before writing.

machine, machine_sym

16-bit integer, or one of: "Sparc", "x86", "MIPS", "PowerPC", "ARM", "SuperH", "IA-64", "x86-64", "AArch64".

version

32-bit integer; defaults to 1 for original version of ELF.

entry_point

32-bit or 64-bit pointer to address where process starts executing. Defaults to 0 unless type is "executable", then you must specify it before writing.

flags

32 bit flags, defined per-machine.

elf_header_len

Read-only, determined from "class". (52 or 64 bytes)

segment_header_elem_len

Read-only, determined from "class". (32 or 56 bytes)

section_header_elem_len

Read-only, determined from "class". (40 or 64 bytes)

segments

Arrayref of ELF::Writer::Segment objects. You can also pass hashrefs to the constructor which will be coerced automatically.

segment_count

Handy alias for $#{ $elf->segments }

segment_list

Handy alias for @{ $elf->segments }

sections

Arrayref of ELF::Writer::Section objects. You can also pass hashrefs to the constructor which will be coerced automatically.

section_count

Handy alias for $#{ $elf->sections }

section_list

Handy alias for @{ $elf->sections }

section_name_string_table_idx

Index into the section array of a string-table section where the names of the sections are stored.

METHODS

serialize

Return a string of the composed ELF file. Throws exceptions if required attributes are missing.

write_file

  $elf->write_file( $filename [, $mode]);

Convenience method for writing to a file. Writes with mode 0755 by default.

SEE ALSO

Brian Raiter has a nice write-up of how to hack around on ELF files, which I found very educational:

http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html

AUTHOR

Michael Conrad <mike@nrdvana.net>

COPYRIGHT AND LICENSE

This software is copyright (c) 2017 by Michael Conrad.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.