1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
|
#! @PERL@
# This script handles linking the tool executables on Linux,
# statically and at an alternative load address.
#
# Linking statically sidesteps all sorts of complications to do with
# having two copies of the dynamic linker (valgrind's and the
# client's) coexisting in the same process. The alternative load
# address is needed because Valgrind itself will load the client at
# whatever address it specifies, which is almost invariably the
# default load address. Hence we can't allow Valgrind itself (viz,
# the tool executable) to be loaded at that address.
#
# Unfortunately there's no standard way to do 'static link at
# alternative address', so these link_tool_exe_*.in scripts handle
# the per-platform hoop-jumping.
#
# What we get passed here is:
# first arg
# the alternative load address
# all the rest of the args
# the gcc invocation to do the final link, that
# the build system would have done, left to itself
#
# We just let the script 'die' if something is wrong, rather than do
# proper error reporting. We don't expect the users to run this
# directly. It is only run as part of the build process, with
# carefully constrained inputs.
#
#
# So: what we actually do is:
#
# Look at the specified gcc invocation. Ignore all parts of it except
# the *.a, *.o and -o outfile parts. Wrap them up in a new command
# which looks (eg) as follows:
#
# (64-bit):
#
# /usr/bin/ld -static -arch x86_64 -macosx_version_min 10.6 \
# -o memcheck-amd64-darwin -u __start -e __start \
# -image_base 0x158000000 -stack_addr 0x13c000000 \
# -stack_size 0x800000 \
# memcheck_amd*.o \
# ../coregrind/libcoregrind-amd64-darwin.a \
# ../VEX/libvex-amd64-darwin.a
#
# (32-bit)
#
# /usr/bin/ld -static -arch i386 -macosx_version_min 10.6 \
# -o memcheck-x86-darwin -u __start -e __start \
# -image_base 0x58000000 -stack_addr 0x3c000000 \
# -stack_size 0x800000 \
# memcheck_x86*.o \
# ../coregrind/libcoregrind-x86-darwin.a \
# ../VEX/libvex-x86-darwin.a
#
# The addresses shown above will actually work, although "for real" we
# of course need to take it from argv[1]. In these examples the stack
# is placed 64M after the executable start. It is probably safer to
# place it 64M before the executable's start point, so the executable
# + data + bss can grow arbitrarily in future without colliding with
# the stack.
#
# There's one more twist: we need to know the word size of the
# executable for which we are linking. We need to know this because
# we must tell the linker that, by handing it either "-arch x86_64" or
# "-arch i386". Fortunately we can figure this out by scanning the
# gcc invocation, which itself must contain either "-arch x86_64" or
# "-arch i386".
use warnings;
use strict;
# we need to be able to do 64-bit arithmetic:
use Math::BigInt;
# User configurable constants: how far before the exe should we
# place the stack?
my $TX_STACK_OFFSET_BEFORE_TEXT = 64 * 1024 * 1024;
# and how big should the stack be?
my $TX_STACK_SIZE = 8 * 1024 * 1024;
# string -> bool
sub is_dota_or_doto($)
{
my ($str) = @_;
if ($str =~ /.\.a$/ || $str =~ /.\.o$/) {
return 1;
} else {
return 0;
}
}
# expect at least: alt-load-address gcc -o foo bar.o
die "Not enough arguments"
if (($#ARGV + 1) < 5);
my $ala = $ARGV[0]; # the load address to use
my $cc = $ARGV[1]; # the C compiler in use
# check for plausible-ish alt load address
die "Bogus alt-load address (1)"
if (length($ala) < 3 || index($ala, "0x") != 0);
die "Bogus alt-load address (2)"
if ($ala !~ /^0x[0-9a-fA-F]+$/);
# get hold of the outfile name (following "-o")
my $outname = "";
foreach my $n (2 .. $#ARGV - 1) {
my $str = $ARGV[$n];
if ($str eq "-o" && $outname eq "") {
$outname = $ARGV[$n + 1];
}
}
die "Can't find '-o outfilename' in command line"
if ($outname eq "");
# get hold of the string following "-arch"
my $archstr = "";
foreach my $n (2 .. $#ARGV - 1) {
my $str = $ARGV[$n];
if ($str eq "-arch" && $archstr eq "") {
$archstr = $ARGV[$n + 1];
}
}
die "Can't find '-arch archstr' in command line"
if ($archstr eq "");
# build the command line
my $cmd = "/usr/bin/ld";
$cmd = "$cmd -static";
# If we're building with clang (viz, the C compiler as specified
# by the 2nd arg ends in "clang"), we also need -new_linker. See
# https://bugs.kde.org/show_bug.cgi?id=295427
if ("$cc" =~ /clang$/) {
$cmd = "$cmd -new_linker";
}
$cmd = "$cmd -arch $archstr";
$cmd = "$cmd -macosx_version_min 10.6";
$cmd = "$cmd -o $outname";
$cmd = "$cmd -u __start -e __start";
my $stack_addr = Math::BigInt->new( $ala ) - $TX_STACK_OFFSET_BEFORE_TEXT;
my $stack_addr_str = $stack_addr->as_hex();
my $stack_size_str = Math::BigInt::as_hex($TX_STACK_SIZE);
$cmd = "$cmd -image_base $ala";
$cmd = "$cmd -stack_addr $stack_addr_str";
$cmd = "$cmd -stack_size $stack_size_str";
foreach my $n (2 .. $#ARGV) {
my $str = $ARGV[$n];
if (is_dota_or_doto($str)) {
$cmd = "$cmd $str";
}
}
print "link_tool_exe_darwin: $cmd\n";
# Execute the command:
my $r = system("$cmd");
if ($r != 0) {
exit 1;
}
# and now kludge the tool exe
# see bug 267997
$cmd = "../coregrind/fixup_macho_loadcmds";
$cmd = "$cmd $stack_addr_str $stack_size_str $outname";
print "link_tool_exe_darwin: $cmd\n";
$r = system("$cmd");
if ($r != 0) {
exit 1;
}
exit 0;
|