package SectionSet;

require Exporter;

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

use strict;
use Section();

sub new($$)
{
  my $proto = shift;
  my $from_readelf = shift;

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

  $self->{START_LINE} = 'Sections:';
  $self->{LINE_PATTERN} = '\s*[0-9]+';
  $self->{FUNC} = \&Section::from_objdump;
  $self->{FUNC_NAME} = 'Section::from_objdump';

  if ($from_readelf)
  {
    $self->{START_LINE} = 'Section Headers:';
    $self->{LINE_PATTERN} = '^\s*\[\s*[0-9]+\]';
    $self->{FUNC} = \&Section::from_readelf;
    $self->{FUNC_NAME} = 'Section::from_readelf';
  }

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

sub read($$;$)
{
  my $self = shift;
  my $ref_line = shift;

  my $start_line = $self->{START_LINE};
  for(my $i = 0; $i < $#$ref_line; $i++)
  {
    my $line = $$ref_line[$i];
    if ($line =~
      m/^There are (\d+) section headers, starting at offset 0x([0-9a-fA-f]+)/)
    { # occurs only with 'readelf -S'
      $self->{e_shnum} = $1;
      $self->{e_shoff} = $2;
      next;
    }
    if ($line eq $start_line)
    {
      return $self->read_sections($ref_line, $i + 1);
    }
  }
  return 'No section headers.';
}

sub read_sections($$$)
{
  my $self = shift;
  my $ref_line = shift;
  my $start = shift;

  my $pattern = $self->{LINE_PATTERN};
  my $func = $self->{FUNC};
  my @section;
  my %count_type;
  for(my $i = $start; $i <= $#$ref_line; $i++)
  {
    my $line = $$ref_line[$i];

    if ($line =~ m/^$pattern\s+([\w\.]+)\s+/)
    {
      my $section = Section->new;
      my $msg = $section->$func($line, $$ref_line[$i + 1]);
      return $self->{FUNC_NAME} . ' ' . $msg if (defined($msg));

      if ($1 eq '.text')
      {
        return 'More than one section ".text".'
	if (defined($self->{'.text'}));
	$self->{$1} = $section;
      }
      push @section, $section;
      $count_type{$1}++;
      next;
    }
    last if (0 == length($line));
  }
  $self->{SECTION} = \@section;
  $self->{COUNT_TYPE} = \%count_type;
  return undef;
}
