ELF-Writer

 view release on metacpan or  search on metacpan

lib/ELF/Writer.pm  view on Meta::CPAN



our (%data_to_sym, %data_from_sym);
_init_enum(\%data_to_sym, \%data_from_sym,
	'2LSB' => 1,
	'2MSB' => 2,
);

has data => ( is => 'rw', coerce => sub {
	my $x= $data_from_sym{$_[0]};
	defined $x? $x
		: (int($_[0]) == $_[0])? $_[0]
		: croak "$_[0] is not a valid 'data'"
});

sub data_sym {
	my $self= shift;
	$self->data($_[0]) if @_;
	my $v= $self->data;
	$data_to_sym{$v} || $v
}


has header_version  => ( is => 'rw', default => sub { 1 } );


our (%osabi_to_sym, %osabi_from_sym);
_init_enum(\%osabi_to_sym, \%osabi_from_sym,
	'SystemV'  => 0,
	'HP-UX'    => 1,
	'NetBSD'   => 2,
	'Linux'    => 3,
	'Solaris'  => 6,
	'AIX'      => 7,
	'IRIX'     => 8,
	'FreeBSD'  => 9,
	'OpenBSD'  => 0x0C,
	'OpenVMS'  => 0x0D,
);

has osabi => ( is => 'rw', coerce => sub {
	my $x= $osabi_from_sym{$_[0]};
	defined $x? $x
		: (int($_[0]) == $_[0])? $_[0]
		: croak "$_[0] is not a valid 'osabi'"
});

sub osabi_sym {
	my $self= shift;
	$self->osabi($_[0]) if @_;
	my $v= $self->osabi;
	$osabi_to_sym{$v} || $v
}


has osabi_version   => ( is => 'rw', default => sub { 0 } );

our (%type_to_sym, %type_from_sym);
_init_enum(\%type_to_sym, \%type_from_sym,
	'none'        => 0,
	'relocatable' => 1,
	'executable'  => 2,
	'shared'      => 3,
	'core'        => 4,
);

has type => ( is => 'rw', coerce => sub {
	my $x= $type_from_sym{$_[0]};
	defined $x? $x
		: (int($_[0]) == $_[0])? $_[0]
		: croak "$_[0] is not a valid 'type'"
});

sub type_sym {
	my $self= shift;
	$self->type($_[0]) if @_;
	my $v= $self->type;
	$type_to_sym{$v} || $v
}


our (%machine_to_sym, %machine_from_sym);
_init_enum(\%machine_to_sym, \%machine_from_sym,
	'SPARC'       => 0x02,
	'i386'        => 0x03,
	'Motorola68K' => 0x04,
	'Motorola88K' => 0x05,
	'i860'        => 0x07,
	'MIPS-RS3000' => 0x08,
	'MIPS-RS4000' => 0xA0,
	'PowerPC'     => 0x14,
	'ARM'         => 0x28,
	'SuperH'      => 0x2A,
	'IA-64'       => 0x32,
	'x86-64'      => 0x3E,
	'AArch64'     => 0xB7,
);

has machine => ( is => 'rw', coerce => sub {
	my $x= $machine_from_sym{$_[0]};
	defined $x? $x
		: (int($_[0]) == $_[0])? $_[0]
		: croak "$_[0] is not a valid 'machine'"
});

sub machine_sym {
	my $self= shift;
	$self->machine($_[0]) if @_;
	my $v= $self->machine;
	$machine_to_sym{$v} || $v
}


has version         => ( is => 'rw', default => sub { 1 } );

has flags           => ( is => 'rw', default => sub { 0 } );

has entry_point     => ( is => 'rw' );


our $Magic= "\x7fELF";

lib/ELF/Writer.pm  view on Meta::CPAN

  # 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 );

=head1 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.

=head1 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.

=head1 ATTRIBUTES

B<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".

=head2 class, class_sym

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

=head2 data, data_sym

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

Must be set before writing.

=head2 header_version

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

=head2 osabi, osabi_sym

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

=head2 osabi_version

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

=head2 type, type_sym

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

=head2 machine, machine_sym

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

=head2 version

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

=head2 entry_point

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

=head2 flags

32 bit flags, defined per-machine.

=head2 elf_header_len

Read-only, determined from L</class>.  (52 or 64 bytes)

=head2 segment_header_elem_len

Read-only, determined from L</class>.  (32 or 56 bytes)

=head2 section_header_elem_len

Read-only, determined from L</class>.  (40 or 64 bytes)

=head2 segments

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

=head2 segment_count

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

=head2 segment_list

Handy alias for C<< @{ $elf->segments } >>

=head2 sections

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

=head2 section_count

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

=head2 section_list

Handy alias for C<< @{ $elf->sections } >>

=head2 section_name_string_table_idx



( run in 2.251 seconds using v1.01-cache-2.11-cpan-71847e10f99 )