package Section;

require Exporter;

@ISA = qw(Exporter);
@EXPORT = qw();
@EXPORT_OK = qw(
  new
);

use strict;
use Entity();

sub new
{
  my $proto = shift;
  my $class = ref($proto) || $proto;
  my $self  = {};

  $self->{NR} = undef;
  $self->{NAME} = undef;
  $self->{TYPE} = undef;
  $self->{ADDR} = undef;
  $self->{OFFSET} = undef;
  $self->{SIZE} = undef;
  $self->{ALIGN} = undef;

  bless ($self, $class);
  return $self;
}

# parse output of readelf -S
# $line1 = line with section description
# $line2 = ignored, for symmetry with objdump
#
# Input for 32-bit:
# [12] .text PROGBITS 08059440 011440 058680 00  AX  0   0 16
#
sub from_readelf($$;$)
{
  my $self = shift;
  my $line = shift;

  return "No section number"
  unless ($line =~ /^\s*\[\s*([0-9]+)\]\s+(.*)/);

  $self->{NR} = $1;
  my @word = Entity::split_number($2);
  return "Invalid number of fields ($#word)." if ($#word != 9);

  $self->{NAME} = $word[0];
  $self->{TYPE} = $word[1];
  $self->{ADDR} = $word[2];
  $self->{OFFSET} = $word[3];
  $self->{SIZE} = $word[4];
  $self->{ALIGN} = $word[9];

  return undef;
}

# parse output of objdump -h
# $line1 = first line of section description
# $line2 = second line of section description
#
# Input for 32-bit:
# 11 .text         00058680  08059440  08059440  00011440  2**4
#                  CONTENTS, ALLOC, LOAD, READONLY, CODE
#
sub from_objdump($$;$)
{
  my $self = shift;
  my $line1 = shift;
  my $line2 = shift;

  my @word = Entity::split_number($line1);
  return "Invalid number of fields ($#word)." if ($#word != 7);

  # objdump does not count array item 0, SHN_UNDEF, so add +1
  $self->{NR} = $word[1] + 1;
  $self->{NAME} = $word[2];
  $self->{SIZE} = $word[3];
  $self->{ADDR} = $word[4];
  $self->{OFFSET} = $word[6];

  my $align = $word[7];
  return "Invalid alignment ($align)"
  unless ($align =~ /^2\*\*([0-9]+)$/);
  $self->{ALIGN} = 1 << $1;

  return undef;
}

sub write_sh_variables($$$)
{
  my $self = shift;
  my $FILE = shift;
  my $prefix = shift;

  while(my ($key, $value) = each(%$self))
  {
    printf($FILE "%s%s=%s\n", $prefix, $key, $value) if (defined($value));
  }
}
