package Section;

require Exporter;

@ISA = qw(Exporter);
@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:
# [ 0]                   NULL            00000000 000000 000000 00      0   0  0
# [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;
  $_ = substr($line,  7, 18); s/\s+$//; $self->{NAME} = $_;
  $_ = substr($line, 25, 16); s/\s+$//; $self->{TYPE} = $_;
  $_ = substr($line, 41,  8); $self->{ADDR} = $_;
  $_ = substr($line, 50,  6); $self->{OFFSET} = $_;
  $_ = substr($line, 57,  6); $self->{SIZE} = $_;
  $_ = substr($line, 64,  2); $self->{ES} = $_;
  $_ = substr($line, 67,  3); s/^\s+//; $self->{FLG} = $_;
  $_ = substr($line, 71,  2); s/^\s+//; $self->{LK} = $_;
  $_ = substr($line, 74,  3); s/^\s+//; $self->{INF} = $_;
  $_ = substr($line, 78,  2); s/^\s+//; $self->{ALIGN} = $_;

  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 = Misc::split_hex($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));
  }
}
