sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1 | #! @PERL@ |
| 2 | |
| 3 | # Generic information about a purpose of this script can be found in |
| 4 | # link_tool_exe_linux.in. |
| 5 | # |
| 6 | # Solaris specific notes: |
| 7 | # |
| 8 | # - load address has to be specified in the mapfile, there is no command line |
| 9 | # option to achieve that |
| 10 | # |
| 11 | # - mapfile version 2 is used |
| 12 | # |
| 13 | # - information about Solaris linker can be found in its man page |
| 14 | # (http://download.oracle.com/docs/cd/E19253-01/816-5165/ld-1/index.html) |
| 15 | # and in Oracle's Linker and Libraries Guide |
| 16 | # (http://download.oracle.com/docs/cd/E19963-01/html/819-0690/index.html) |
| 17 | # |
| 18 | |
| 19 | use warnings; |
| 20 | use strict; |
| 21 | use File::Temp qw/tempfile unlink0/; |
| 22 | use Fcntl qw/F_SETFD/; |
| 23 | |
| 24 | # expect at least: alt-load-address gcc -o foo bar.o |
| 25 | die "Not enough arguments" |
| 26 | if (($#ARGV + 1) < 5); |
| 27 | |
| 28 | my $ala = $ARGV[0]; |
| 29 | |
| 30 | # check for plausible-ish alt load address |
| 31 | die "Bogus alt-load address" |
| 32 | if (length($ala) < 3 || index($ala, "0x") != 0); |
| 33 | |
Elliott Hughes | ed39800 | 2017-06-21 14:41:24 -0700 | [diff] [blame] | 34 | # the cc invocation to do the final link |
sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 35 | my $cc = $ARGV[1]; |
| 36 | |
| 37 | # and the 'restargs' are argv[2 ..] |
| 38 | |
| 39 | # create a temporary mapfile |
| 40 | (my $fh, my $path) = tempfile(); |
| 41 | |
| 42 | # reset FD_CLOEXEC flag |
| 43 | fcntl($fh, F_SETFD, 0) |
| 44 | or die "Can't clear close-on-exec flag on temp fh: $!"; |
| 45 | |
| 46 | # safely unlink the file |
| 47 | unlink0($fh, $path) |
| 48 | or die "Error unlinking file $path safely"; |
| 49 | undef $path; |
| 50 | |
| 51 | # fill it with data |
| 52 | # |
| 53 | # this is a bit tricky, the problem is that the following condition has to be |
| 54 | # true for both PT_LOAD segments: |
| 55 | # (phdr->p_vaddr & PAGEOFFSET) == (phdr->p_offset & PAGEOFFSET) |
| 56 | # if it doesn't hold then the kernel maps a segment as an anon mapping instead |
| 57 | # of a file mapping (which, for example, breaks reading debug information) |
| 58 | print $fh <<"END"; |
| 59 | \$mapfile_version 2 |
| 60 | LOAD_SEGMENT text { VADDR = $ala; ROUND = 0x1000 }; |
| 61 | LOAD_SEGMENT data { ROUND = 0x1000 }; |
| 62 | END |
| 63 | |
| 64 | # build up the complete command here: |
| 65 | # 'cc' -Wl,-Mtmpfile 'restargs' |
| 66 | |
| 67 | my $cmd="$cc -Wl,-M/proc/$$/fd/" . fileno($fh); |
| 68 | |
| 69 | # add the rest of the parameters |
| 70 | foreach my $n (2 .. $#ARGV) { |
| 71 | $cmd = "$cmd $ARGV[$n]"; |
| 72 | } |
| 73 | |
| 74 | #print "link_tool_exe_solaris: $cmd\n"; |
| 75 | |
| 76 | |
| 77 | # execute the command: |
| 78 | my $r = system("$cmd"); |
| 79 | |
| 80 | if ($r == 0) { |
| 81 | exit 0; |
| 82 | } else { |
| 83 | exit 1; |
| 84 | } |