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 )