#! @PERL@ # Generic information about a purpose of this script can be found in # link_tool_exe_linux.in. # # Solaris specific notes: # # - load address has to be specified in the mapfile, there is no command line # option to achieve that # # - mapfile version 2 is used # # - information about Solaris linker can be found in its man page # (http://download.oracle.com/docs/cd/E19253-01/816-5165/ld-1/index.html) # and in Oracle's Linker and Libraries Guide # (http://download.oracle.com/docs/cd/E19963-01/html/819-0690/index.html) # use warnings; use strict; use File::Temp qw/tempfile unlink0/; use Fcntl qw/F_SETFD/; # expect at least: alt-load-address gcc -o foo bar.o die "Not enough arguments" if (($#ARGV + 1) < 5); my $ala = $ARGV[0]; # check for plausible-ish alt load address die "Bogus alt-load address" if (length($ala) < 3 || index($ala, "0x") != 0); # the cc invocation to do the final link my $cc = $ARGV[1]; # and the 'restargs' are argv[2 ..] # create a temporary mapfile (my $fh, my $path) = tempfile(); # reset FD_CLOEXEC flag fcntl($fh, F_SETFD, 0) or die "Can't clear close-on-exec flag on temp fh: $!"; # safely unlink the file unlink0($fh, $path) or die "Error unlinking file $path safely"; undef $path; # fill it with data # # this is a bit tricky, the problem is that the following condition has to be # true for both PT_LOAD segments: # (phdr->p_vaddr & PAGEOFFSET) == (phdr->p_offset & PAGEOFFSET) # if it doesn't hold then the kernel maps a segment as an anon mapping instead # of a file mapping (which, for example, breaks reading debug information) print $fh <<"END"; \$mapfile_version 2 LOAD_SEGMENT text { VADDR = $ala; ROUND = 0x1000 }; LOAD_SEGMENT data { ROUND = 0x1000 }; END # build up the complete command here: # 'cc' -Wl,-Mtmpfile 'restargs' my $cmd="$cc -Wl,-M/proc/$$/fd/" . fileno($fh); # add the rest of the parameters foreach my $n (2 .. $#ARGV) { $cmd = "$cmd $ARGV[$n]"; } #print "link_tool_exe_solaris: $cmd\n"; # execute the command: my $r = system("$cmd"); if ($r == 0) { exit 0; } else { exit 1; }