sub updateSize()

in maxas/MaxAs/Cubin.pm [558:635]


sub updateSize
{
    my ($cubin, $sec, $newSize, $updatePrgSize) = @_;

    my $elfHdr = $cubin->{elfHdr};
    my $class  = $elfHdr->{fileClass};

    # update section header
    my $delta = $newSize - $sec->{size};
    $sec->{size} = $newSize;

    # update symtab section
    if ($sec->{SymbolEnt})
    {
        $sec->{SymbolEnt}{size} = $newSize;
        my $symSection = $cubin->{'.symtab'};
        $symSection->{Data} = '';
        foreach my $symEnt (@{$symSection->{SymTab}})
        {
            $symSection->{Data} .= unpack "H*", pack $symHdrT[$class], @{$symEnt}{@{$symHdrC[$class]}};
        }
    }

    my $pos = $elfHdr->{ehSize};
    my %sizeMap;

    # update section header offsets
    foreach my $secHdr (@{$cubin->{secHdrs}})
    {
        # skip first header
        next if $secHdr->{align} == 0;

        # NOBITS data sections are size 0
        my $size = $secHdr->{type} == 8 ? 0 : $secHdr->{size};

        # Add any needed padding between sections
        my $pad = $pos % $secHdr->{align};
        if ($pad > 0)
        {
            $pos += $secHdr->{align} - $pad;
        }
        # map old offset to new
        $sizeMap{$secHdr->{offset}} = $pos;

        # update offset
        $secHdr->{offset} = $pos;

        # advance position by size
        $pos += $size;
    }

    # compute total section header size
    my $shSize = $elfHdr->{phOffset} - $elfHdr->{shOffset};

    # map old offset to new
    $sizeMap{$elfHdr->{shOffset}} = $pos;
    $sizeMap{$elfHdr->{phOffset}} = $pos + $shSize;

    $elfHdr->{shOffset} = $pos;
    $elfHdr->{phOffset} = $pos + $shSize;

    # update program header offsets and sizes
    foreach my $prgHdr (@{$cubin->{prgHdrs}})
    {
        # Not sure how best to adjust these so just assume they'll track other offsets.
        $prgHdr->{offset} = $sizeMap{$prgHdr->{offset}};

        # If the kernel sizes changes, also update the associated ProgramHeader.
        # Note that this size is the kernel size plus any constant section sizes.
        if ($updatePrgSize && $prgHdr->{type} == 1 &&
            $sec->{offset} >= $prgHdr->{offset} &&
            $sec->{offset} < $prgHdr->{offset} + $prgHdr->{fileSize} + $delta)
        {
            $prgHdr->{fileSize} += $delta;
            $prgHdr->{memSize}  += $delta;
        }
    }
}