| #!/usr/bin/perl |
| # |
| # This file is part of Cygwin. |
| # |
| # This software is a copyrighted work licensed under the terms of the |
| # Cygwin license. Please consult the file "CYGWIN_LICENSE" for |
| # details. |
| # |
| use integer; |
| use strict; |
| sub xit($@); |
| my $strip = $ARGV[0] eq '-s'; |
| shift if $strip; |
| my $objdump = shift; |
| my @objcopy = ((shift)); |
| my $dll = shift; |
| my $dbg = shift; |
| xit 0, @objcopy, '-R', '.gnu_debuglink_overlay', '--add-gnu-debuglink=/dev/null', '--only-keep-debug', $dll, $dbg; |
| xit 0, @objcopy, '-g', '--add-gnu-debuglink=' . $dbg, $dll; |
| open(OBJDUMP, '-|', "$objdump --headers $dll"); |
| my %section; |
| while (<OBJDUMP>) { |
| my ($idx, $name, $size, $vma, $lma, $fileoff, $algn) = /^\s*(\d+)\s+(\.\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s*$/; |
| if ($name eq '.gnu_debuglink') { |
| push(@objcopy, '--set-section-flag', '.gnu_debuglink=contents,readonly,debug,noload'); |
| $idx = $section{'.gnu_debuglink'}{-idx} if defined($section{'.gnu_debuglink'}{-idx}); |
| } elsif ($name eq '.gnu_debuglink_overlay') { |
| push (@objcopy, '-R', '.gnu_debuglink_overlay'); |
| $section{'.gnu_debuglink'}{-idx} = $idx; |
| next; |
| } |
| defined($idx) and |
| $section{$name} = {-idx=>int($idx), -size=>hex($size), -vma=>hex($vma), -lma=>hex($lma), -fileoff=>hex($fileoff), |
| -algn=>0x00001000}; |
| } |
| close OBJDUMP; |
| my $vma; |
| for my $k (sort {$section{$a}{-idx} <=> $section{$b}{-idx}} keys %section) { |
| if ($strip && $k =~ /\.(?:stab|debug)/o) { |
| push(@objcopy, '-R', $k); |
| next; |
| } |
| if (!defined($vma)) { |
| $vma = $section{$k}{-vma}; |
| } |
| if ($vma != $section{$k}{-vma}) { |
| my $newvma = align($vma, $section{$k}{-algn}); |
| if ($newvma != $vma) { |
| printf STDERR "$0: ERROR $k VMA 0x%08x != 0x%08x\n", $vma, $newvma; |
| exit 1; |
| } |
| push(@objcopy, '--change-section-address', sprintf "$k=0x%08x", $vma); |
| } |
| $vma = align($vma + $section{$k}{-size}, $section{$k}{-algn}); |
| } |
| |
| warn "$0: ERROR final VMA (" . sprintf("0x%08x", $vma) . ") not on 64K boundary\n" if $vma != align($vma, 64 * 1024); |
| push(@objcopy, $dll, @ARGV); |
| xit 1, @objcopy; |
| sub align { |
| my $n = $_[0]; |
| my $align = $_[1] - 1; |
| return ($n + $align) & ~$align; |
| } |
| |
| sub xit($@) { |
| my $execit = shift; |
| print "+ @_\n"; |
| if ($execit) { |
| exec @_ or die "$0: couldn't exec $_[0] - $!\n"; |
| } else { |
| system @_ and die "$0: couldn't exec $_[0] - $!\n"; |
| } |
| } |