ELF-Writer
view release on metacpan or search on metacpan
lib/ELF/Writer.pm view on Meta::CPAN
$data .= $_->data;
}
return $data;
}
sub _serialize_segment_header {
my ($self, $seg)= @_;
# Faster than checking bit lengths on every field ourself
use warnings FATAL => 'pack';
# Make sure all required attributes are defined
defined $seg->$_ or croak "Attribute $_ is not defined"
for qw( type offset virt_addr align );
my $filesize= $seg->filesize;
$filesize= length($seg->data) + $seg->data_offset
unless defined $filesize;
my $align= $seg->align;
my $memsize= $seg->memsize;
$memsize= int(($filesize + $align - 1) / $align) * $align
unless defined $memsize;
# 'flags' moves depending on 32 vs 64 bit, so changing the pack string isn't enough
return $self->_encoding < 2?
pack($self->_segment_header_packstr,
$seg->type, $seg->offset, $seg->virt_addr, $seg->phys_addr || 0,
$filesize, $memsize, $seg->flags, $seg->align
)
: pack($self->_segment_header_packstr,
$seg->type, $seg->flags, $seg->offset, $seg->virt_addr,
$seg->phys_addr || 0, $filesize, $memsize, $seg->align
);
}
sub _serialize_section_header {
my ($self, $sec)= @_;
# Make sure all required attributes are defined
defined $sec->$_ or croak "Attribute $_ is not defined"
for qw( type name flags addr offset size link info addralign entsize );
# Faster than checking bit lengths on every field ourself
use warnings FATAL => 'pack';
return pack($self->_section_header_packstr,
$sec->name, $sec->type, $sec->flags, $sec->addr, $sec->offset,
$sec->size, $sec->link, $sec->info, $sec->align, $sec->entry_size
);
}
sub write_file {
my ($self, $filename, $mode)= @_;
$mode= 0755 unless defined $mode;
require File::Temp;
my ($fh, $tmpname)= File::Temp::tempfile( $filename.'-XXXXXX' );
print $fh $self->serialize or croak "write: $!";
close $fh or croak "close: $!";
chmod($mode, $tmpname) or croak "chmod: $!";
rename($tmpname, $filename) or croak "rename: $!";
}
# coerce arrayref of hashrefs into arrayref of objects
sub _coerce_segments {
my $spec= shift;
return [ map { (__PACKAGE__.'::Segment')->coerce($_) } @$spec ];
}
# coerce arrayref of hashrefs into arrayref of objects
sub _coerce_sections {
my $spec= shift;
return [ map { (__PACKAGE__.'::Section')->coerce($_) } @$spec ];
}
# Overridden by subclasses for machine-specific defaults
sub _apply_section_defaults {
my ($self, $sec)= @_;
# Undef type is "null" type 0
my $type= $sec->type;
defined $type
or $sec->type($type= 0);
my $offset= $sec->offset;
my $size= $sec->size;
if ($type == 0) { # 'null'
# Ensure length and offset are zero
$size= $sec->size(0) unless defined $size;
$offset= $sec->offset(0) unless defined $offset;
croak "null section should have offset=0 and size=0"
if $offset || $size;
}
elsif ($type == 8) { # 'nobits'
# Offset can be set but ensure size is zero
$size= $sec->size(0) unless defined $size;
croak "nobits section should have size=0"
if $size;
}
else {
# 'size' is required, but can be computed from 'data' and 'data_offset'.
if (!defined $size) {
defined $sec->data or croak "Section must define 'size' or 'data'";
$sec->size($sec->data_start + length($sec->data));
}
}
}
# Overridden by subclasses for machine-specific defaults
sub _apply_segment_defaults {
my ($self, $seg)= @_;
# Undef type is "null" type 0
my $type= $seg->type;
defined $type
or $seg->type($type= 0);
my $offset= $seg->offset;
my $filesize= $seg->filesize;
if ($type == 0) { # 'null'
# Ensure length and offset are zero
( run in 0.485 second using v1.01-cache-2.11-cpan-39bf76dae61 )