#!/usr/bin/perl

if ($#ARGV != 1) {
    die "usage: elfextract <elf input file> <extractname>";
}

#
# ELF header field numbers
#
$e_entry = 4;
$e_phoff=5;
$e_shoff = 6;
$e_ehsize = 8;
$e_phentsize = 9;
$e_phnum = 10;
$e_shentsize = 11;
$e_shnum = 12;
$e_stblindx = 13;


# 
# Put the file in buffer $ibuf
#
print "input ELF file: $ARGV[0]\n";
$ifile = $ARGV[0];
if (-x $ifile){
    print $ifilesize=(-s $ifile),"\n";
}
open ifile or die "couldn't open input file: $ifile\n";
read (ifile,$ibuf,$ifilesize) == $ifilesize or die("couldnt allocate\n");
print "size of ibuf $#ibuf\n";


# 
# Parse elf header
#
@eh = unpack "a16nnNNNNNnnnnnn",$ibuf;
print "elfheader:\n";
print "$eh[0]\n";
print "$eh[1]\n";
print "$eh[2]\n";
$entry_point = $eh[$e_entry];
printf( "entry point 0x%x\n",$entry_point);
print "program header offset $eh[$e_phoff]\n";
printf("section header offset 0x%x\n",$eh[$e_shoff]);
print "program entry size $eh[$e_phentsize]\n";
print "number entries in program header table  $eh[$e_phnum]\n";
print "section header size $eh[$e_shentsize]\n";
print "number entries in section header table  $eh[$e_shnum]\n";
print "string table section  $eh[$e_stblindx]\n";

$program_offset = $eh[$e_phoff];


#
# Get info on each section and find bss section in particular
#
$off = $program_offset;
$load_low = 0xffffffff;
$load_high = 0;
print  length($ibuf), "long\n";
for($i=0;$i < $eh[$e_phnum];$i++) {
    $p = substr($ibuf,$off+8,4);
    ($addr) = unpack "N", $p;
    $p = substr($ibuf,$off+16,4);
    ($size) = unpack "N", $p;
    printf( "chunk addr,size  %x,%x  ", $addr,$size);    

    $p = substr($ibuf,$off,4);
    ($type) = unpack "N", $p;
    if ($type == 1) {
        printf( "loaded (type 0x%x)\n", $type);
        if ($addr < $load_low) {
            $load_low = $addr;
        }
        if ($addr + $size > $load_high) {
            $load_high = $addr + $size;
        }
    } else {
        printf( "not loaded (type 0x%x)\n", $type);
    }

    $off += $eh[$e_phentsize];
}

printf "lowest load address: %x\n",$load_low;
printf "highest load address: %x\n",$load_high;

#
# Open output file for info
#
open ofile, "> $ARGV[1].info" or die "no output file\n";

#
# Compute image size
#
$image_size = $load_high - $load_low;

#
# Write information we'll need to construct the PPC eval image
#
$header = "$load_low\n$image_size\n$entry_point\n";
    
syswrite ofile, $header, length($header) or die "couldn't write info file";
printf "Image size: 0x%x (%d), nBlks=%d\n",$image_size,$image_size,$image_size/512+1;

close ofile;

# MFK: It's not quite this simple.  Because of the way the kernel uses some
# ELF sections, the ELF binary file is not necessarily 1:1 with the raw
# binary, so rather than interpret and copy each section individually, use
# objcopy to do that later...
#
# Open output file for info
#
#open ofile, "> $ARGV[1].data" or die "no output file\n";
#
#
#
# Write image starting after elf and program header and 
# continuing to beginning of bss
#
#
#syswrite ofile, $ibuf, $bss_offset-$text_offset, $text_offset   or
#    die "couldnt write image to output file\n";
#
#close ofile;




