From 9c8a436caa2a80830433bf1afa2ce75efe6d62de Mon Sep 17 00:00:00 2001 From: waker Date: Wed, 3 Nov 2010 20:57:04 +0100 Subject: merged apbuild into deadbeef tree --- tools/apbuild/Apbuild/GCC.pm | 539 +++++++++++++++++ tools/apbuild/Apbuild/Utils.pm | 195 ++++++ tools/apbuild/BINARY-PORTABILITY-NOTES | 36 ++ tools/apbuild/ChangeLog | 375 ++++++++++++ tools/apbuild/README | 1 + tools/apbuild/apg++ | 10 + tools/apbuild/apgcc | 1023 ++++++++++++++++++++++++++++++++ tools/apbuild/apsymbols.h | 275 +++++++++ tools/apbuild/buildlist | 48 ++ tools/apbuild/ctype.h | 268 +++++++++ tools/apbuild/make-icons | 58 ++ tools/apbuild/relaytool | 584 ++++++++++++++++++ tools/apbuild/relaytool.m4 | 28 + tools/apbuild/scandeps | 137 +++++ tools/apbuild/test-app/randomapp1.c | 16 + 15 files changed, 3593 insertions(+) create mode 100644 tools/apbuild/Apbuild/GCC.pm create mode 100644 tools/apbuild/Apbuild/Utils.pm create mode 100644 tools/apbuild/BINARY-PORTABILITY-NOTES create mode 100644 tools/apbuild/ChangeLog create mode 100644 tools/apbuild/README create mode 100755 tools/apbuild/apg++ create mode 100755 tools/apbuild/apgcc create mode 100644 tools/apbuild/apsymbols.h create mode 100755 tools/apbuild/buildlist create mode 100644 tools/apbuild/ctype.h create mode 100755 tools/apbuild/make-icons create mode 100755 tools/apbuild/relaytool create mode 100644 tools/apbuild/relaytool.m4 create mode 100755 tools/apbuild/scandeps create mode 100644 tools/apbuild/test-app/randomapp1.c (limited to 'tools') diff --git a/tools/apbuild/Apbuild/GCC.pm b/tools/apbuild/Apbuild/GCC.pm new file mode 100644 index 00000000..b4246148 --- /dev/null +++ b/tools/apbuild/Apbuild/GCC.pm @@ -0,0 +1,539 @@ +# Various gcc-related functions +package Apbuild::GCC; + +use strict; +use Apbuild::Utils; +use IPC::Open3; + + +######## Special constants; used for parsing GCC parameters ######## + +# Parameters that require an extra parameter +our $extraTypes = 'o|u|Xlinker|b|V|MF|MT|MQ|I|L|R|Wl,-rpath|isystem|D|x'; +# Linker parameters +our $linkerTypes = 'L|Wl|o$|l|s|n|R'; +# Files with these extensions are objects +our $staticLibTypes = 'a|al'; +our $objectTypes = "o|os|so(\\.\\d+)*|la|lo|$staticLibTypes"; +our $headerTypes = 'h|hpp'; +# Source file types +our $cTypes = 'c|C'; +our $cxxTypes = 'cpp|cxx|cc|c\+\+'; +our $srcTypes = "$cTypes|$cxxTypes"; + + +######## Methods ######## + +## +# Apbuild::GCC->new(gcc_command) +# gcc_command: The command for invoking GCC. +# +# Create a new Apbuild:GCC object. +sub new { + my ($class, $gcc) = @_; + my %self; + + $self{gcc} = $gcc; + $self{gcc_file} = checkCommand($gcc); + if (!defined $self{gcc_file}) { + error "$gcc: command not found\n"; + exit 127; + } + + # FIXME: should use gcc -print-search-paths. + $self{searchPaths} = ["/usr/lib", "/usr/local/lib"]; + foreach (reverse(split(/:/, $ENV{LIBRARY_PATH}))) { + push @{$self{searchPaths}}, $_; + } + + bless \%self, $class; + return \%self; +} + +## +# $gcc->capabilities() +# Returns: a hash with capabilities for this compiler. +# +# Check GCC's capabilities. This function will return +# a hash with the following keys: +# libgcc : Is 1 if gcc supports the parameter -{shared,static}-libgcc. +# as_needed: Is 1 if gcc's linker supports --as-needed. +# abi2 : Is 1 if gcc supports -fabi-version=2. +# +# This function takes care of caching results. +sub capabilities { + my ($self) = @_; + my (%capabilities, %cache); + + my $gcc = $self->{gcc}; + my $gcc_file = $self->{gcc_file}; + + # First, check the cache + my @stat = stat $gcc_file; + my $gcc_mtime = $stat[9]; + my $home = homeDir(); + if (-f "$home/.apbuild") { + parseDataFile("$home/.apbuild", \%cache); + if ($cache{version} != 2) { + # Cache file version incompatible; delete cache + %cache = (); + + } else { + if ($cache{"mtime_$gcc_file"} != $gcc_mtime) { + # Cache out of date for this compiler; update cache + delete $cache{"libgcc_$gcc_file"}; + delete $cache{"abi2_$gcc_file"}; + delete $cache{"as_needed_$gcc_file"}; + delete $cache{"hash_style_$gcc_file"}; + delete $cache{"stack_protector_$gcc_file"}; + delete $cache{"fortify_source_$gcc_file"}; + } + } + } + + my $lc_all = $ENV{LC_ALL}; + $ENV{LC_ALL} = 'C'; + + if (exists $cache{"libgcc_$gcc_file"} && exists $cache{"abi2_$gcc_file"}) { + $capabilities{libgcc} = $cache{"libgcc_$gcc_file"}; + $capabilities{abi2} = $cache{"abi2_$gcc_file"}; + + } else { + # Get output from 'gcc -v' + my ($r, $w, $e); + + my $pid = open3($w, $r, $e, $gcc_file, '-v'); + close $w if ($w); + close $e if ($e); + my @output = <$r>; + waitpid $pid, 0; + + # Check whether gcc >= 3.0 + my ($major, $minor) = $output[@output - 1] =~ /version ([0-9]+)\.([0-9]+)/; + if ($major >= 3) { + $capabilities{libgcc} = 1; + $cache{"libgcc_$gcc_file"} = 1; + } else { + $capabilities{libgcc} = 0; + $cache{"libgcc_$gcc_file"} = 0; + } + + if ($major > 3 || ($major >= 3 && $minor >= 4)) { + $capabilities{abi2} = 1; + $cache{"abi2_$gcc_file"} = 1; + } else { + $capabilities{abi2} = 0; + $cache{"abi2_$gcc_file"} = 0; + } + + $cache{"mtime_$gcc_file"} = $gcc_mtime; + } + + if (exists $cache{"as_needed_$gcc_file"}) { + $capabilities{as_needed} = $cache{"as_needed_$gcc_file"}; + + } else { + my ($r, $w, $e); + + my $pid = open3($w, $r, $e, $gcc_file, '-Wl,--help'); + close $w if ($w); + close $e if ($e); + local($/); + my $output = <$r>; + waitpid $pid, 0; + + if ($output =~ /--as-needed/) { + $capabilities{as_needed} = 1; + $cache{"as_needed_$gcc_file"} = 1; + } else { + $capabilities{as_needed} = 0; + $cache{"as_needed_$gcc_file"} = 0; + } + } + + if (exists $cache{"hash_style_$gcc_file"}) { + $capabilities{hash_style} = $cache{"hash_style_$gcc_file"}; + } else { + my ($r, $w, $e); + + my $pid = open3($w, $r, $e, $gcc_file, '-Wl,--help'); + close $w if ($w); + close $e if ($e); + local($/); + my $output = <$r>; + waitpid $pid, 0; + + if ($output =~ /--hash-style/) { + $capabilities{hash_style} = 1; + $cache{"hash_style_$gcc_file"} = 1; + } else { + $capabilities{hash_style} = 0; + $cache{"hash_style_$gcc_file"} = 0; + } + } + + if (exists $cache{"stack_protector_$gcc_file"}) { + $capabilities{stack_protector} = $cache{"stack_protector_$gcc_file"}; + } else { + # Get output from 'gcc -v' + my ($r, $w, $e); + + my $pid = open3($w, $r, $e, $gcc_file, '-v'); + close $w if ($w); + close $e if ($e); + my @output = <$r>; + waitpid $pid, 0; + + # Check whether gcc >= 3.0 + my ($major, $minor) = $output[@output - 1] =~ /version ([0-9]+)\.([0-9]+)/; + if ($major >= 4 && $minor >= 1) { + $capabilities{stack_protector} = 1; + $cache{"stack_protector_$gcc_file"} = 1; + } else { + $capabilities{stack_protector} = 0; + $cache{"stack_protector_$gcc_file"} = 0; + } + } + + if (exists $cache{"fortify_source_$gcc_file"}) { + $capabilities{fortify_source} = $cache{"fortify_source_$gcc_file"}; + } else { + # Get output from 'gcc -v' + my ($r, $w, $e); + + my $pid = open3($w, $r, $e, $gcc_file, '-v'); + close $w if ($w); + close $e if ($e); + my @output = <$r>; + waitpid $pid, 0; + + # Check whether gcc >= 4.1 + my ($major, $minor) = $output[@output - 1] =~ /version ([0-9]+)\.([0-9]+)/; + if ($major >= 4 && $minor >= 1) { + $capabilities{fortify_source} = 1; + $cache{"fortify_source_$gcc_file"} = 1; + } else { + $capabilities{fortify_source} = 0; + $cache{"fortify_source_$gcc_file"} = 0; + } + } + + if (defined $lc_all) { + $ENV{LC_ALL} = $lc_all; + } else { + delete $ENV{LC_ALL}; + } + + $cache{version} = 2; + writeDataFile("$home/.apbuild", \%cache); + return %capabilities; +} + + +## +# $gcc->command() +# +# Returns the GCC command associated with this Apbuild::GCC object. +sub command { + my ($self) = @_; + return $self->{gcc}; +} + + +## +# $gcc->foreach(args, callback) +# args: a reference to an array which contains GCC parameters. +# callback: the callback function which will be called in every iteration of the loop. +# +# Iterate through each GCC parameter. $callback will be called as follows: +# $callback->(type, args...); +# $type is the current parameter's type, either "param" or "file" (source file). +# args is an array of parameters. If this parameter is a parameter which excepts +# another parameter (such as -o, it expects a filename), then the expected +# parameter will also be passed to the callback function. +sub foreach { + my ($self, $args, $callback) = @_; + for (my $i = 0; $i < @{$args}; $i++) { + $_ = $args->[$i]; + if (/^-/ || /\.($objectTypes|$headerTypes)$/ || /.*\.so\.?$/) { + # Parameter + if (/^-($extraTypes)$/) { + # This parameter expects another parameter + $callback->("param", $_, $args->[$i + 1]); + $i++; + } else { + $callback->("param", $_); + } + + } else { + # File + $callback->("file", $_); + } + } +} + +## +# $gcc->splitParams(args, files, params) +# args: a reference to an array which contains GCC parameters. +# files: a reference to an array, or undef. +# params: a reference to an array, or undef. +# +# Parse GCC's parameters. Seperate files and arguments. +# A list of files will be stored in the array referenced to by $file, +# a list of non-file parameters will be stored in the array referenced to by $params. +sub splitParams { + my ($self, $args, $files, $params) = @_; + + my $callback = sub { + my $type = shift; + if ($type eq "param") { + push @{$params}, @_ if ($params); + } elsif ($type eq "file") { + push @{$files}, $_[0] if ($files); + } + }; + $self->foreach($args, $callback); +} + + +sub stripLinkerParams { + my ($self, $r_params, $linking) = @_; + my @params; + my $i = 0; + + my $callback = sub { + my $type = shift; + if ($type eq 'param' && $_[0] =~ /^-($linkerTypes)/) { + push @{$linking}, @_; + } else { + push @params, @_; + } + }; + $self->foreach($r_params, $callback); + @{$r_params} = @params; +} + + +sub addSearchPaths { + my ($self, $dir) = @_; + push @{$self->{searchPaths}}, $dir; +} + +# Parse $args and extract library search paths from it. +# Those paths, along with paths added by addSearchPaths(), +# will be appended to $paths. +sub getSearchPaths { + my ($self, $args, $paths) = @_; + + my $callback = sub { + my $type = shift; + return if ($type ne "param"); + + if ($_[0] eq "-L") { + push @{$paths}, $_[1]; + + } elsif ($_[0] =~ /^-L(.+)/ || $_[0] =~ /^--library-path=(.+)/) { + push @{$paths}, $1; + } + }; + $self->foreach($args, $callback); + + push @{$paths}, @{$self->{searchPaths}}; +} + + +## +# $gcc->isLibrary(arg, libname) +# +# Check whether $arg is a (dynamic) library argument. +# The base library name will be stored in $$libname. +sub isLibrary { + my ($self, $arg, $libname) = @_; + if ($arg =~ /^-l(.+)/ || $arg =~ /^--library=(.+)/ || $arg =~ /^(?:.*\/)?lib([^\/]+)\.so/) { + $$libname = $1 if ($libname); + return 1; + } else { + return 0; + } +} + +## +# $gcc->isObject(arg) +# +# Check whether $arg is an object. This includes static libraries. +sub isObject { + my ($self, $arg) = @_; + return $arg !~ /^-/ && $arg =~ /\.($objectTypes)$/; +} + +sub isStaticLib { + my ($self, $arg) = @_; + return $arg !~ /^-/ && $arg =~ /\.($staticLibTypes)$/; +} + +## +# $gcc->isSource(file) +# +# Checks whether $file is a source file. +sub isSource { + my ($self, $file) = @_; + return $file =~ /\.($srcTypes)$/; +} + +## +# $gcc->isCxxSource(file) +# +# Checks whether $file is a C++ source file. +sub isCxxSource { + my ($self, $file) = @_; + return $file =~ /\.($cxxTypes)$/; +} + + +# I wish I know how to explain what these functions do, but I can't. :( +# If you know a better way to name these, please do tell me. +sub sourceOrderIsImportant { + my ($self, $arg) = @_; + return $arg =~ /^-(x)$/; +} + +sub linkOrderIsImportant { + my ($self, $arg) = @_; + return $arg =~ /^-(Wl,--whole-archive|Wl,--no-whole-archive)$/; +} + +## +# $gcc->getOutputFile(args) +# args: a reference to an array which contains GCC parameters. +# Returns: a filename. +# +# Parse the GCC arguments and detect the output filename. +sub getOutputFile { + my ($gcc, $args) = @_; + my ($output, $compilingToObject, $source); + + my $callback = sub { + my $type = shift; + if ($type eq 'param' && $_[0] eq '-o') { + $output = $_[1]; + + } elsif ($type eq 'param' && $_[0] eq '-c') { + $compilingToObject = 1; + + } elsif ($type eq 'file' && $gcc->isSource($_[0])) { + $source = $_[0]; + } + }; + $gcc->foreach($args, $callback); + + if (defined $output) { + return $output; + } elsif ($compilingToObject) { + $source =~ s/\.[^.]*?$/.o/; + return $source; + } else { + return "a.out"; + } +} + +## +# $gcc->setOutputFile(args, new_output_file) +# args: a reference to an array which contains GCC parameters. +# new_output_file: the new output filename. +# +# Parse the GCC arguments and change the output filename. +# The array referenced by $args will be modified. +sub setOutputFile { + my ($gcc, $args, $new_output_file) = @_; + my (@newArgs, $changed); + + my $callback = sub { + my $type = shift; + + if ($type eq 'param' && $_[0] eq '-o') { + push @newArgs, "-o", $new_output_file; + $changed = 1; + + } else { + push @newArgs, @_; + } + }; + $gcc->foreach($args, $callback); + + if (!$changed) { + push @newArgs, "-o", $new_output_file if (!$changed); + } + @{$args} = @newArgs; +} + + +## +# $gcc->situation(args) +# args: a reference to an array which contains GCC arguments. +# Returns: 'compile', 'depcheck', 'compile and link', 'linking' or 'other'. +# +# Detect the situation in which the compiler is used. +# Basically, there are 5 situations in which the compiler is used: +# 1) Compilation (to an object file). +# 2) Linking. +# 3) Compilation and linking. +# 4) Dependancy checking with -M* or -E. +# 5) None of the above. Compiler is invoked with --help or something. +# Note that source files may also contain non-C/C++ files. +sub situation { + my ($self, $args) = @_; + + my $files = 0; + for (@{$args}) { + $files++ if (!(/^-/)); + } + + for (@{$args}) { + if (/^-c$/) { + # Situation 1 + return 'compile'; + } elsif (/^-M(|M|G)$/ || /^-E$/) { + # Situation 4 + return 'depcheck'; + } + } + + if ($files == 1) + { + my $i = 0; + for (@{$args}) + { + if (!(/^-/) && (/\.($headerTypes)$/)) + { + print($args->[$i], "\n"); + return 'precompiled header'; + } + $i++; + } + } + + my $i = 0; + for (@{$args}) { + if (!(/^-/) && !(/\.($objectTypes)$/)) { + if ($i > 0 && $args->[$i - 1] =~ /^-($extraTypes)$/) { + $i++; + next; + } else { + # Situation 3 + return 'compile and link'; + } + } + $i++; + } + + if ($files == 0) { + # Situation 5 + return 'other'; + } else { + # Situation 2 + return 'linking'; + } +} + + +1; diff --git a/tools/apbuild/Apbuild/Utils.pm b/tools/apbuild/Apbuild/Utils.pm new file mode 100644 index 00000000..a5089299 --- /dev/null +++ b/tools/apbuild/Apbuild/Utils.pm @@ -0,0 +1,195 @@ +package Apbuild::Utils; + +use strict; +use warnings; +use Exporter; +use base qw(Exporter); +use IO::Handle; +use IPC::Open2; +use POSIX; +use Cwd qw(abs_path); + + +our @EXPORT = qw(debug error checkCommand empty homeDir searchLib searchStaticLib soname run parseDataFile writeDataFile); +our $debugOpened = 0; + + +## +# debug(message) +# +# If the environment variable $APBUILD_DEBUG is set to 1, +# then print a debugging message to /dev/tty (not stdout or stderr). +sub debug { + return if (empty($ENV{APBUILD_DEBUG}) || !$ENV{APBUILD_DEBUG}); + + if (!$debugOpened) { + if (open DEBUG, '>/dev/tty') { + $debugOpened = 1; + } else { + return; + } + } + + my @args = split /\n/, "@_"; + foreach (@args) { + $_ = '# ' . $_; + $_ .= "\n"; + } + + print DEBUG "\033[1;33m"; + print DEBUG join '', @args; + print DEBUG "\033[0m"; + DEBUG->flush; +} + + +## +# error(message) +# +# Print an error message to stderr. It will be displayed in red. +sub error { + print STDERR "\033[1;31m"; + print STDERR $_[0]; + print STDERR "\033[0m"; + STDERR->flush; +} + + +## +# checkCommand(file) +# file: an command's filename. +# Returns: the full path to $file, or undef if $file is not a valid command. +# +# Checks whether $file is an executable which is in $PATH or the working directory. +# +# Example: +# checkCommand('gcc'); # Returns "/usr/bin/gcc" +sub checkCommand { + my ($file, $file2) = split / /, $_[0]; + $file = $file2 if ($file =~ /ccache/); + + return abs_path($file) if (-x $file); + foreach my $dir (split /:+/, $ENV{PATH}) { + if (-x "$dir/$file") { + return "$dir/$file"; + } + } + return undef; +} + +## +# empty(str) +# +# Checks whether $str is undefined or empty. +sub empty { + return !defined($_[0]) || $_[0] eq ''; +} + +## +# homeDir() +# +# Returns the user's home folder. +sub homeDir { + if (!$ENV{HOME}) { + my $user = getpwuid(POSIX::getuid()); + $ENV{HOME} = (getpwnam($user))[7]; + } + return $ENV{HOME}; +} + +## +# searchLib(basename, [extra_paths]) +# basename: the base name of the library. +# extra_paths: a reference to an array, which contains extra folders in which to look for the library. +# Returns: the absolute path to the library, or undef if not found. +# +# Get the absolute path of a (static or shared) library. +# +# Example: +# searchLib("libfoo.so.1"); # Returns "/usr/lib/libfoo.so.1" +sub searchLib { + my ($basename, $extra_paths) = @_; + + if ($extra_paths) { + foreach my $path (reverse(@{$extra_paths})) { + return "$path/$basename" if (-f "$path/$basename"); + } + } + foreach my $path ('/usr/local/lib', '/lib', '/usr/lib') { + return "$path/$basename" if (-f "$path/$basename"); + } + return undef; +} + +## +# soname(lib) +# lib: a filename to a shared library. +# Returns: the soname. +# +# Get the soname of the specified shared library by reading +# the SONAME section of the shared library file. +sub soname { + my ($lib) = @_; + my ($r, $w); + + if (open2($r, $w, 'objdump', '-p', $lib)) { + close $w; + my @lines = <$r>; + close $r; + + my ($soname) = grep {/SONAME/} @lines; + $soname =~ s/.*?SONAME[ \t]+//; + $soname =~ s/\n//gs; + return $soname; + + } else { + my ($soname) = $lib =~ /.*\/lib(.+)\.so/; + return $soname; + } +} + +## +# run(args...) +# Returns: the command's exit code. +# +# Run a command with system(). +sub run { + # split the first item in @_ into "words". The `printf ...` + # takes care of respecting ' and " quotes so we don't split a + # quoted string that contains whitespace. If $cmd itself + # contains \n, this will still go wrong. + my $cmd = shift @_; + my @words = `printf '%s\n' $cmd`; + chomp @words; + my $status = system(@words, @_); + return 127 if ($status == -1); + return $status / 256 if ($status != 0); + return 0; +} + +sub parseDataFile { + my ($file, $r_hash) = @_; + + %{$r_hash} = (); + return if (!open FILE, "< $file"); + foreach () { + next if (/^#/); + s/[\r\n]//g; + next if (length($_) == 0); + + my ($key, $value) = split / /, $_, 2; + $r_hash->{$key} = $value; + } + close FILE; +} + +sub writeDataFile { + my ($file, $r_hash) = @_; + return if (!open FILE, "> $file"); + foreach my $key (sort(keys %{$r_hash})) { + print FILE "$key $r_hash->{$key}\n"; + } + close FILE; +} + +1; diff --git a/tools/apbuild/BINARY-PORTABILITY-NOTES b/tools/apbuild/BINARY-PORTABILITY-NOTES new file mode 100644 index 00000000..9a34566a --- /dev/null +++ b/tools/apbuild/BINARY-PORTABILITY-NOTES @@ -0,0 +1,36 @@ +1) C++ ABI +The C++ ABI generated by GCC version 2.95, 2.96, 3.0, and 3.1.1 are +incompatible with each other. This means that, for examples, apps compiled +with GCC 2.95 cannot link to libraries compiled with GCC 3.2. + +GCC 3.4 is the latest ABI at the moment (April 2005). But the most widely +used ABI at the moment is the GCC 3.2 ABI. + +2) Symbol collisions, be aware of what libraries are implicitly linked in. +Imagine the following situation: +- foo contains the symbol foobar (a function). +- libbar contains a symbol with the same name, but is a totally different + function. +- foo is linked to libbar. +When foo tries to call foobar(), it's undefined whether it will call the +foobar() from it's own binary, or the one from libbar. Depending on what +those functions do, foo may crash or do something it isn't supposed to do. + +Solution: rtld features, -Bgroup. However, at this moment these are not +supported by glibc. Until they are, keep these in mind: +- You should mark all functions that you do not want to export (or show up + in the symbol table) as static. +- If you're a library, you should namespace all functions. +- Internal functions that are used within a library, but across multiple + .c files, should be prefixed by a _ or __. + +3) Linking against shared versions of X11 extension libs +Some X libraries, such as libXrender, are originally not shared libraries. +Distributions just created shared library versions to save memory. So +some distributions don't ship the shared versions at all. Apbuild +automatically statically links some of those X libraries (you can turn +this behavior off of course). + +4) Usage of sys_errlist + +5) Don't use TLS (the __thread keyword). diff --git a/tools/apbuild/ChangeLog b/tools/apbuild/ChangeLog new file mode 100644 index 00000000..fe1587ce --- /dev/null +++ b/tools/apbuild/ChangeLog @@ -0,0 +1,375 @@ +2009-03-13 Jan Niklas Hasse + + * apgcc: Use warn instead of print to display warnings. Thanks to Scott + Pakin for the patch. + +-------------------- 2.0.8 was released -------------------- + +2009-03-11 Jan Niklas Hasse + + * Apbuild/GCC.pm: Applied patch by Mike Lundy which fixes compiling of + libpng where apgcc detected a symbol list as precompiled header rather than + a depcheck. Fixes #118. + * apsymbols.h: New symbol list created on a GLIBC_2.9 machine by Mike + Lundy. Thanks! Fixes #117. + +2009-03-11 Jan Niklas Hasse + + * apgcc: Applied patch by Scott Pakin which shows a warning message when + a library in APBUILD_STATIC isn't found. + * Apbuild/GCC.pm: getSearchPaths: Correctly add the content of the list not + a reference. Also a patch by Scott Pakin, thanks! + +2009-03-10 Jan Niklas Hasse + + * apgcc: Applied patch by Scott Pakin which fixes statically compiling + of libuuid. + +-------------------- 2.0.7 was released -------------------- + +2008-11-10 Jan Niklas Hasse + + * Apbuild/GCC.pm: Check if FORTIFY_SOURCE is available. I'm not sure if + this really was introduced in gcc 4.1, but it should fix the the linker + errors in Ubuntu 8.10 and other new distros using this feature. + * apgcc: Add -U_FORTIFY_SOURCE to deactivate FORTIFY_SOURCE=2. + +2008-09-11 Jan Niklas Hasse + + * buildlist: Bump minimum GLibc version to 2.3 (from 2.2) + * apsymbols.h: update list to work with the new 2.3 glibc min version + (Patch from Taj, me and Isak, should fix #20) + * apgcc: Check if APBUILD_STATIC_X is definied to prevent warnings. + +2008-08-03 Jan Niklas Hasse + + * relaytool: Check if /dev/tty exists. Fixes #63 + +2008-08-03 Jan Niklas Hasse + + * apgcc: Don't statically link X11 libs by default. Fixes #61 + +-------------------- 2.0.6 was released -------------------- + +Sun Dec 30 19:17:03 UTC 2007 Taj Morton + * relaytool: Apply patch from res in ticket #52. Now, if a lib cannot be relaytooled + for some reason, a stub that ensures libwhatever_is_present is defined will be + generated. + +Sun Sep 30 00:29:13 UTC 2007 Taj Morton + * relaytool: When multi-linking, use the first SONAME passed to --multilink + as the name to use for the _is_present variable and _symbol_is_present function. + Fixes #37. + +Sat Sep 22 02:39:11 UTC 2007 Taj Morton + * relaytool: Add --out-dir feature by user 'res' in ticket #50. + +2007-09-22 Isak Savo + + * relaytool (arch_ptr_size): Use 'uname -m' instead of 'arch' to get + machine name. Patch from user 'res' in ticket #51 (ticket fixed by + this commit) + +Tue Aug 14 17:04:32 UTC 2007 Taj Morton + * apgcc: Apply patch from Unfleshed One for precompiled header support. Fixes #32. + * Apbuild/GCC.pm: Apply patch from Unfleshed One from precompiled header and + SCons/Qt4 integration. Fixes #32. + +Tue Aug 14 16:51:30 UTC 2007 Taj Morton + * relaytool: When running on unsupported arch, give correct + defines for lib_is_present and symbol_is_present. + +Mon Jul 9 23:22:21 UTC 2007 Curtis L. Knight + * apgcc: Update for 2.0.6 release. + * Makefile: Update for 2.0.6 release. + +-------------------- 2.0.5 was released -------------------- + +Mon Jun 4 02:03:06 UTC 2007 Taj Morton + * apgcc: Append statically linked file's deps before adjusting + link line so that you can statically link the deps of the + libs you're statically linking (if that made any sense). + +Sat May 26 15:28:14 UTC 2007 Taj Morton + * make-icons: Put icons into a directory called icons relative to + where make-icons was run from. Ask user for type so that icons get + put in correct subdirectory. + +Fri May 25 03:02:28 UTC 2007 Curtis L. Knight + * apgcc: Update for 2.0.5 release. + * Makefile: Update for 2.0.5 release. + +Wed May 23 00:45:48 UTC 2007 Taj Morton + * apgcc: When statically linking, find the lib's DT_NEEDED entries + and link against them so we don't get linking errors. + +Thu May 17 20:38:11 UTC 2007 Taj Morton + * relaytool: Use /bin/bash instead of /bin/sh so we can work on + Ubuntu (where sh -> dash). Thanks ACSpike. Add multilink support + to relaytool (TODO: document it better). + +-------------------- 2.0.4 was released -------------------- + +Sun Apr 8 11:22:23 UTC 2007 Curtis L. Knight + * apgcc: Update for 2.0.4 release. + * Makefile: Update for 2.0.4 release. + +Sat Mar 31 21:09:45 UTC 2007 Taj Morton + * Apbuild/GCC.pm: Check if gcc supports -fstack-protector, + so it can be disabled. + * apgcc: If gcc supports -fstack-protector, disable it (it adds a + silent dependency on GLIBC 2.4). + * apsymbols.h: Rebuilt with GLIBC 2.4. Thanks to Chris Guirl for + rebuilding. + +Thu Mar 29 05:08:40 UTC 2007 Taj Morton + * apgcc: Respect the $APBUILD_NO_STATIC_X variable (as + documented on website). This doesn't mean it's a good idea + to use this features. + +-------------------- 2.0.3 was released -------------------- + +Sun Dec 17 01:05:08 UTC 2006 Curtis L. Knight + * apgcc: Update for 2.0.3 release. + * Makefile: Update for 2.0.3 release. + +Sat Nov 25 23:20:07 UTC 2006 Taj Morton + * Apbuild/GCC.pm: Detect if ld supports --hash-style so that we + can force both .gnu.hash and .hash to be generated on FC6. + * apgcc: If linker supports --hash-style, generate both .gnu.hash + and .hash sections so that binary works with linkers with support for + either type. By default, FC6 only generates .gnu.hash which makes its + binaries only work on systems with .gnu.hash. See: + http://fcp.surfsite.org/modules/newbb/viewtopic.php?topic_id=29929&forum=10&post_id=128939 + +-------------------- 2.0.2 was released -------------------- + +Thu Nov 2 22:53:33 UTC 2006 Taj Morton + * apgcc: Allow people to replace -I flags passed to apgcc with ones from + $APBUILD_INCLUDE. For example /opt/kde/include=/home/taj/kde-includes/3.3 + replaces -I/opt/kde/include with -I/home/taj/kde-includes/3.3. This is only + useful for apps where include path order is important (amarok 1.4.3, see + comments for details). + +-------------------- 2.0.1 was released -------------------- + +Fri Oct 13 14:54:54 UTC 2006 Taj Morton + * apgcc: Revert commit that "Just use[d] the multiple-file code for link and compile + in 1 command." This broke compiling main/libexec. Post 1.2 this code will get + better, I promise. :) + +Thu Oct 12 04:36:56 UTC 2006 Taj Morton + * apgcc: [translateLibNames()]: Always find libstdc++ if compiling C++, force + use of the compilers libstdc++, instead of what libtool provides (which + is probably wrong when using your non-system g++). + +Mon Oct 9 00:57:48 UTC 2006 Taj Morton + * apgcc: Remove special case with compiling and linking in 1 command with + 1 file. This code never called linkObjects() and so X libs were never + statically linked in. Just use the multiple-file code for link and compile in 1 + command. + [forceStatic()]: Link Xfixes if Xcursor is linked because sometimes Xcursor + depends on Xfixes (on Slack 11, xorg 6.9.0, at least). + +Sun Sep 24 22:38:50 UTC 2006 Taj Morton + * apgcc: [rearrangeForAsNeeded()]: Put -lXRender at the end of the + link command. See + http://lists.sunsite.dk/cgi-bin/ezmlm-cgi?21:mss:5187:200609:lkfnloheeaingojmnemi + for details. + +2006-09-13 Isak Savo + + * Makefile (PREFIX): Replaced bash specific '[[' testing with 'test' to work better with Ubuntu Edgy's 'dash' shell + +Thu Sep 7 19:10:53 UTC 2006 Taj Morton + * apgcc: When compiling and linking in 1 command make sure + bogus deps are stripped. Note: I did not update the + double-compilation part of the code to have the fix because + it's dead code. + +Tue May 30 01:04:05 2006 Mike Hearn + + * relaytool: Add x64 support based on patch by Psyche. + Fix a couple of minor bugs and make the code flow better. + +Thu Apr 13 23:56:32 2006 Mike Hearn + + * apgcc (translateLibNames): Only drop libstdc++.so from the + arguments list when double compiling. This fixes the case + when libtool passes -nostdlib and then gives us a libstdc++ + directly. However it's kind of a hack and will need to be + changed to work properly with double compiling. + +2006-03-04 Hongli Lai + + * apgcc: Apply patch by Francesco Montorsi. + This adds a new option APBUILD_RESOLVE_LIBPATH, which is a + space-seperated list of regular expressions which specify the + libraries whose path must be resolved into absolute paths. + This works around certain linking problems with static libraries, + when the order of the linking arguments is changed. + +2006-02-04 Peter Lund + + * APBuild/GCC.pm: Fix double linking of .moc.o files + +2006-02-01 Peter Lund + + * apgcc: Add support gcc-2.9x. + Minor comment/--help fixes. See + http://comments.gmane.org/gmane.comp.autopackage.devel/4408 + for more details + * APBuild/GCC.pm, APBuild/Utils.pm: Make apgcc work with ccache. + +2006-01-23 Peter Lund + + * Makefile: Use eager notation (`:=') instead of `=' for var assignment. Add $(PROGS)-variable to hold all binary names. + + +2005-12-02 Hongli Lai + * apgcc (rearrangeForAsNeeded): + Special case -lbfd and -liberty as they can cause link failures in + some cases. + +2005-11-30 Hongli Lai + * apgcc: + Do not link to incorrect libstdc++ version: remove + /usr/lib/libstdc++.so.x from the arguments. + +2005-11-08 Hongli Lai + * apgcc, Apbuild/GCC.pm, Apbuild/Utils.pm: + - Code cleanups. + - Fix C++ double compiling bugs: correctly set output filename + when -o is not given, surpress gcc output when double compiling. + +2005-11-07 Hongli Lai + * apgcc (linkObjects): remove duplicate system() call which + does nothing good but breaks some libtool versions. + +2005-10-30 Jan Nieuwenhuizen + + * Apbuild/GCC.pm (new): New member variable: searchPaths. Bugfix: + add LIBRARY_PATH to initialization. + (addSearchPaths): New function. + (getSearchPaths): Use searchPaths. + + * Apbuild/Utils.pm (searchLib): Bugfix: correct order of search + dirs. + + * apgcc (removeLibraries): Maintain searchPath for full .so name. + +October 16 2005 + * apgcc: Correctly double compile C++ binaries during linking. + +September 28 2005 Hongli Lai + * Support $APBUILD_NO_RPATH: don't add rpath entries. + Feature request by Andreas. + +September 3 2005 Hongli Lai + * relaytool: support W, V and G symbols (experimental C++ support) + +August 5 2005 Hongli Lai + * apgcc and GCC.pm: fixed an argument reordering bug. + * Makefile: add make-icons to distrbution. + +2005-08-02 Mike Hearn + * relaytool: Remove -include flags, if any. This makes relaytool + precompiled-header safe. + +2005-07-31 Mike Hearn + * relaytool.m4, relaytool: Optimization: use -ffunction-sections + and --gc-sections to eliminate unused jump slots + * relaytool: Don't break when CFLAGS is set + * relaytool: Optimization: only generate jump slots for exported + symbols from the library. + +July 30 2005 Hongli Lai + * Apbuild/GCC.pm: Commit Joseph's patch: fix $gcc->isLibrary() + +2005-07-20 Mike Hearn + * Makefile (dist): Ship relaytool.m4, make extra scripts +x + * relaytool.m4: Big improvements to the way you integrate with + C/C++ build systems. + +July 9 2005 Hongli Lai + * apgcc, Apbuild/GCC.pm (rearrangeForAsNeeded): + Fix rearrangement of objects: don't recognize parameters + (-Wl,foo.so) as objects. + +Thu Jun 16 22:43:55 2005 Mike Hearn + * make-icons: Add a script to generate icon theme dropins from an SVG + file, a convenient utility for developers + +May 31 2005 Hongli Lai + * apgcc: Automatically compile C++ source files with two different + ABIs. By default, C++ files are compiled with ABI 1. Another + file with ABI 2 is stored as output.o.GCCABI2 + +May 16th 2005 Vincent Béron + * relaytool: Keep only one copy of a given symbol per lib. + * relaytool: libdl won't ever be supported by relaytool, so skip it. + * relaytool: Add a --version option, reorganize a bit the rest of --help. + * relaytool: Allow generating a stub file for every library passed in args. + * relaytool: Skip generating a stub for libraries for which no functions + are called or no variables used. + * relaytool: Use proper quoting. + * relaytool: Support old nm versions + +May 15th 2005 Vincent Béron + * relaytool: Allow relaytool to understand more than one --relay + parameter. + * relaytool: Enable (via --minimal-list) relaytool to only + generate the minimum list of symbols by looking which ones are + undefined in .o objects. + * relaytool: Use CFLAGS (if available) while compiling the stub file. + * relaytool: Use a shell function to do the same thing as + readlink -f as the latter isn't always understood by readlink. + * relaytool: Fix a typo in PPC C code. + +May 14th 2005 Vincent Béron + * relaytool: Don't accidentally exclude all symbols with _init + or _fini in their names. + +April 16 2005 Hongli Lai + * Add new tool 'scandeps' which makes it easier for you to find + your software's library dependancies. + * Improve documentation. + +April 15 2005 Hongli Lai + * apgcc: add support for $APBUILD_INCLUDE, which allows you + to prepend any folder to the header search path. + * Improve documentation. + +Fri Apr 15 22:47:06 2005 Mike Hearn + * apsymbols.h: Update to glibc 2.3.5 + * buildlist: Don't spew so many errors + +April 10 2005 Hongli Lai + * What? We have a ChangeLog? I didn't know that! + In the last 2 weeks I worked on these: + - Support for GCC 3.4+'s --as-needed, for smarter automatic bogus + dependancy stripping. + - Improved our own dependancy stripper. + - Big code cleanups. + +Tue Apr 5 02:14:49 2005 Mike Hearn + * relaytool.m4: Add an autoconf check for relaytool + +Mon Feb 14 00:37:46 2005 Mike Hearn + * relaytool: Add --no-replace option, fix misc bugs revealed by + actually using relaytool in a real app + +Fri Feb 11 23:49:24 2005 Mike Hearn + * relaytool: don't request PROT_EXEC permissions, they aren't + needed + +2004-06-06 Mike Hearn + * relaytool: make relaytool jump thunks NX safe by using mmap + rather than malloc. + + * relaytool: Fix ELF scoping of dummy symbols for variable + imports, so the definitions in the imported lib don't get + resolved to the dummies (not all libs are compiled -Bsymbolic) + + * relaytool: support partial maps + diff --git a/tools/apbuild/README b/tools/apbuild/README new file mode 100644 index 00000000..9bc79658 --- /dev/null +++ b/tools/apbuild/README @@ -0,0 +1 @@ +Please read http://autopackage.org/aptools.html for documentation. diff --git a/tools/apbuild/apg++ b/tools/apbuild/apg++ new file mode 100755 index 00000000..30357b53 --- /dev/null +++ b/tools/apbuild/apg++ @@ -0,0 +1,10 @@ +#!/usr/bin/env perl +# Simple C++ wrapper for apgcc. + +use strict; +use FindBin; + +my $apgcc = "$FindBin::Bin/apgcc"; +$ENV{APBUILD_CXX_MODE} = 1; +my $a = do $apgcc; +die $@ if ($@); diff --git a/tools/apbuild/apgcc b/tools/apbuild/apgcc new file mode 100755 index 00000000..2aba0071 --- /dev/null +++ b/tools/apbuild/apgcc @@ -0,0 +1,1023 @@ +#!/usr/bin/env perl +# apbuild - a GCC wrapper for creating portable binaries +# Copyright (c) 2003,2004,2005 Hongli Lai +# Distributed under the GNU General Public License + +use warnings; +use strict; +use FindBin qw($RealBin); +use File::Spec; +use lib $RealBin; +use lib "$RealBin/../share/apbuild"; +use IPC::Open2; +use POSIX; +use Cwd; + +use Apbuild::GCC; +use Apbuild::Utils; + +# Don't forget to bump the version in Makefile too. +our $APBUILD_VERSION = "2.0.9"; + + +######## Initialization ######## + +# In C mode: +# $gcc is the default compiler. +# $gxx2 is not set. +# +# In C++ mode: +# $gcc is g++ 3.2. +# $gxx2 is g++ 3.4, and it might not be set. +# Double compiling is only enabled if both are set. +# +# Note that $APBUILD_CXX_MODE is an internal environment variable +# which should not be set by the user. +our ($gcc, $gxx2); + +if ($ENV{APBUILD_CXX_MODE}) { + # C++ support; user can: + # - Not set APBUILD_CXX1/2 at all -> use g++ as default, and don't double compile C++ sources. + # - Set APBUILD_CXX1 and APBUILD_CXX2 -> enable double compiling. + # - Set only APBUILD_CXX1 -> don't double compile. + # - Set only APBUILD_CXX2 -> use 'g++' as default for APBUILD_CXX1, and enable double compiling. + + if (empty($ENV{APBUILD_CXX1}) && empty($ENV{APBUILD_CXX2})) { + $gcc = new Apbuild::GCC('g++'); + + } elsif (!empty($ENV{APBUILD_CXX1}) && !empty($ENV{APBUILD_CXX2})) { + $gcc = new Apbuild::GCC($ENV{APBUILD_CXX1}); + $gxx2 = new Apbuild::GCC($ENV{APBUILD_CXX2}); + + } elsif (!empty($ENV{APBUILD_CXX1})) { + $gcc = new Apbuild::GCC($ENV{APBUILD_CXX1}); + + } elsif (!empty($ENV{APBUILD_CXX2})) { + $gcc = new Apbuild::GCC('g++'); + $gxx2 = new Apbuild::GCC($ENV{APBUILD_CXX2}); + } + +} else { + my $gcc_command = 'gcc'; + $gcc_command = $ENV{APBUILD_CC} if (!empty($ENV{APBUILD_CC})); + $gcc = new Apbuild::GCC($gcc_command); +} + + +our $appath; +our $libgcc = $ENV{APBUILD_STATIC_LIBGCC} ? '-static-libgcc' : '-shared-libgcc'; + +# Find out where apgcc is located and determine the apbuild header +# path relative to the apgcc script location. +$appath = $ENV{APBUILD_PATH} if (!empty($ENV{APBUILD_PATH})); +if (!defined $appath) { + $appath = $FindBin::Bin; + $appath =~ s/\/*$//g; + $appath =~ s/^(.*)\/.*?$/$1/; + $appath .= '/include/apbuild'; + if (! -f "$appath/apsymbols.h" && -f "$FindBin::Bin/apsymbols.h") { + $appath = $FindBin::Bin; + } +} + +# Special constants +our @linking = ('-Wl,--enable-new-dtags,--rpath,${ORIGIN}/../lib,--rpath,${ORIGIN}/../lib/autopackage'); +our @include = ("-I$appath", '-include', "$appath/apsymbols.h", "-DAPBUILD_VERSION=\"$APBUILD_VERSION\""); +our $extraTypes = $Apbuild::GCC::extraTypes; +our $srcTypes = $Apbuild::GCC::srcTypes; + + +@linking = () if ($ENV{APBUILD_NO_RPATH}); +if (!empty($ENV{APBUILD_INCLUDE})) { + foreach my $dir (split /:+/, $ENV{APBUILD_INCLUDE}) { + if ($dir =~ /=/) { + # allow people to force changing a path with oldpath=newpath, e.g.,: + # $echo $APBUILD_INCLUDE + # /opt/kde/include=/home/taj/kde-headers/kde-3.3.2/kde/include + # would change -I/opt/kde/include to my KDE 3.3 headers. + # this works around problems where the order of the include + # directories is important. Added for amarok 1.4.3 which has a + # header named scriptmanager.h. KDE also has a header named + # scriptmanager. Order of -I flags forces amarok header to be + # included. + my @splitpaths = split(/=/, $dir); + if (-d $splitpaths[1]) { + foreach (@ARGV) { + s/-I$splitpaths[0]$/-I$splitpaths[1]/g; + } + } + } + else { + push @include, "-I$dir" if (-d $dir); + } + } +} + +# Include the apbuild include folder, and all folders inside that folder. +if (opendir D, $appath) { + foreach my $dir (readdir D) { + if ($dir !~ /^\./ && -d "$appath/$dir") { + push @include, "-I$appath/$dir"; + } + } + closedir D; +} + +if (!empty($ENV{APBUILD_PROJECTNAME})) { + push @linking, '-Wl,--rpath,${ORIGIN}/../lib/' . $ENV{APBUILD_PROJECTNAME}; +} + + +our %capabilities = $gcc->capabilities; +if ($capabilities{hash_style}) { + # By default FC6 only generates a .gnu.hash section, not + # .hash (which is the only thing that FC5 and most other + # distros understand). + # Force generation of both sections if the linker supports it + # so that the binary will run on other systems. + # See http://fcp.surfsite.org/modules/newbb/viewtopic.php?topic_id=29929&forum=10&post_id=128939 + # for more details + push @linking, '-Wl,--hash-style=both'; +} + +if ($capabilities{stack_protector}) { + # gcc-4.1 introduced stack protection to help check for + # buffer overflows. This introduces a silent dependency on + # glibc 2.4 (__stack_chk_fail@@GLIBC_2.4) + # Not many people have glibc 2.4 yet, so disable it. + push @include, "-fno-stack-protector"; +} + +if ($capabilities{fortify_source}) { + # Some distros (e.g. Ubuntu 8.10) activate a bufferoverflow protection + # which is only available since glibc 2.3.4. Apbuild removes all symbols + # newer then 2.3, so this can't be used. + push @include, "-U_FORTIFY_SOURCE"; +} + +our %capabilities_gxx2; +%capabilities_gxx2 = $gxx2->capabilities if ($gxx2); +push @linking, $libgcc if ($capabilities{libgcc}); + + +############# Detect compilation situation ############# + +our $situation = $gcc->situation(\@ARGV); +if ($ENV{APBUILD_CXX_MODE}) { + debug "apg++ @ARGV\n"; +} else { + debug "apgcc @ARGV\n"; +} +debug "Situation: $situation\n"; + + +# Handle each situation +# Only situations that involve compiling or linking need to be treated specially +if ($situation eq 'compile') { + # Extract the parameters and files + my (@files, @params); + $gcc->splitParams(\@ARGV, \@files, \@params); + + # Compile each source file to an object file. + # Force GCC to compile C/C++ source files with older glibc symbols. + debug "\@files: is @files\n"; + foreach my $file (@files) { + if ($gxx2 && $gxx2->isCxxSource($file)) { + # This is a C++ source file. Compile the file twice with different ABIs. + my $src = $file; + my $old_gcc; + my %old_cap; + + compileSource($src, \@ARGV); + + $old_gcc = $gcc; + %old_cap = %capabilities; + $gcc = $gxx2; + %capabilities = %capabilities_gxx2; + + beginDoubleCompiling(); + compileSource($src, \@ARGV, '.GCCABI2'); + endDoubleCompiling(); + + $gcc = $old_gcc; + %capabilities = %old_cap; + + } else { + compileSource($file, \@ARGV); + } + } + exit; + +} elsif ($situation eq 'linking') { + linkObjects(\@ARGV); + + if ($gxx2) { + # Check whether there are .GCCABI2 objects. Link them if there are. + my @options; + my $doubleCompile; + + my $callback = sub { + my $type = shift; + + if ($type eq 'param' && ($gxx2->isLibrary($_[0]) || $gxx2->isObject($_[0])) && !$gxx2->isStaticLib($_[0]) && -f "$_[0].GCCABI2") { + push @options, "$_[0].GCCABI2"; + $doubleCompile = 1; + } else { + push @options, @_; + } + }; + + $gcc = $gxx2; + %capabilities = %capabilities_gxx2; + + $gcc->foreach(\@ARGV, $callback); + + if ($doubleCompile) { + debug "Double compiling.\n"; + beginDoubleCompiling(); + linkObjects(\@options, ".GCCABI2"); + endDoubleCompiling(); + } + } + exit; +} elsif ($situation eq 'precompiled header') { + # Extract the parameters and files + my (@files, @params); + $gcc->splitParams(\@ARGV, \@files, \@params); + + # Compile each source file to an object file. + # Force GCC to compile C/C++ source files with older glibc symbols. + debug "\@files: is @files\n"; + foreach my $file (@files) + { + compileSource($file, \@ARGV); + } +} elsif ($situation eq 'compile and link') { + # Extract the parameters and files + my (@params, @files, @linking2); + my @command; + my $status; + + # Seperate files and linker options. + # @params are all options except linker options, and is used for compilation of each individual source file. + # @files are the source files. + $gcc->splitParams(\@ARGV, \@files, \@params); + $gcc->stripLinkerParams(\@params, \@linking2); + + # Compile & link only one source file + if (@files == 1) { + my @options = modifyLinkerOptions(@params); + push @options, @linking2; + + if ($gxx2 && $gxx2->isCxxSource($files[0])) { + # This is a C++ file. Compile twice with different ABIs. + compileSource($files[0], \@ARGV); + manipulateDeps(@options); + + $gcc = $gxx2; + %capabilities = %capabilities_gxx2; + + beginDoubleCompiling(); + compileSource($files[0], \@ARGV, '.GCCABI2'); + manipulateDeps(@options); + endDoubleCompiling(); + + } else { + compileSource($files[0], [@linking, @options], undef); + manipulateDeps($files[0], @options); + } + + exit; + } + + # Compile individual files into objects + my $cxx; + debug "Multiple source files: @files\n"; + foreach my $file (@files) { + my $out = $file; + $out =~ s/^(.*)\..*?$/$1.o/; + + if ($gxx2 && $gxx2->isCxxSource($file)) { + # This is a C++ file. Compile twice with different ABIs. + my $old_gcc; + my %old_cap; + + $cxx = 1; + compileSource($file, [@ARGV, '-c']); + + $old_gcc = $gcc; + %old_cap = %capabilities; + $gcc = $gxx2; + %capabilities = %capabilities_gxx2; + + beginDoubleCompiling(); + compileSource($file, [@ARGV, '-c'], '.GCCABI2'); + endDoubleCompiling(); + + $gcc = $old_gcc; + %capabilities = %old_cap; + + } else { + compileSource($file, [@params, '-c'], undef); + } + + $file = $out; + } + + # Finally, link all objects together. + my @options = (@params, @linking2); + linkObjects([@files, @options]); + + if ($cxx) { + $gcc = $gxx2; + %capabilities = %capabilities_gxx2; + + # Also link the objects with ABI 2 together + foreach (@files) { + $_ .= ".GCCABI2"; + } + beginDoubleCompiling(); + linkObjects([@files, @options], '.GCCABI2'); + endDoubleCompiling(); + } + exit; + +} else { + my $ret = run($gcc->command, @ARGV); + if (defined $ARGV[0] && $ARGV[0] eq '--help') { + print "\napbuild environment variables:\n"; + print " APBUILD_PATH=path Specifies the include path for apsymbols.h\n" . + " (like: /usr/local/include/apbuild)\n" . + " APBUILD_DEBUG=1 Enable debugging messages\n" . + " APBUILD_BOGUS_DEPS=deps Specify a list of whitespace-seperated bogus\n" . + " library dependancies (like: X11 ICE png). These\n" . + " libraries will not be linked.\n" . + " APBUILD_STATIC=deps Specify a list of whitespace-seperated libraries\n" . + " to statically link to (like: popt z). You can also\n" . + " explicitly specify a filename to the static library.\n" . + " Example: popt=/usr/lib/libpopt.a\n" . + " APBUILD_STATIC_X=1 Force static linking of some X extension libraries\n" . + " Don't use this unless you know what you're doing.\n" . + " APBUILD_DISABLE_BOGUS_DETECTOR=1 Disable the automatic bogus dependancy\n" . + " detector. This is useful when linking to libraries\n" . + " don't have correct DT_NEEDED entries, like GTK 1.2.\n" . + " APBUILD_NOT_BOGUS=deps If you want to use the automatic bogus dependancy\n" . + " dectector anyway, then you can specify a list of\n" . + " dependancies here that are not bogus.\n" . + " APBUILD_STATIC_LIBGCC=1 Link all binaries with -static-libgcc. See the gcc\n" . + " info page for more info about this option.\n" . + " APBUILD_PROJECTNAME If non-empty, apbuild will add\n" . + " \$ORIGIN/../lib/\$APBUILD_PROJECTNAME to the library\n" . + " search path.\n" . + " APBUILD_INCLUDE Prepend the specified directory to the compiler's\n" . + " header search path. The compiler will search this\n" . + " directory first, before searching any other\n" . + " directory. This is useful in combination with the\n" . + " older GTK headers package (see the autopackage\n" . + " website). You can specify multiple directories,\n" . + " seperated by a ':', just like the \$PATH environment\n" . + " variable.\n" . + " APBUILD_NO_RPATH Do not add rpath entries during linking.\n" . + " APBUILD_CC Use the specified C compiler. Default value: gcc\n" . + " APBUILD_CXX1,APBUILD_CXX2 Use the specified C++ compiler. Default value: g++\n" . + " Set both variables to enable double compiling. The\n" . + " first should be set to the g++ 3.2 compiler and the\n" . + " second should be set to the g++ 3.4 (or newer)\n" . + " compiler.\n" . + " APBUILD_RESOLVE_LIBPATH A whitespace-separated list of regular expressions which\n" . + " specify the libraries whose path must be resolved into\n" . + " an absolute path.\n"; + } + exit $ret; +} + + +######## Functions ######## + + +sub modifyLinkerOptions { + my @argv = @_; + + # Remove manually specified bogus library dependancies + my @bogusDeps; + @bogusDeps = split / +/, $ENV{APBUILD_BOGUS_DEPS} if (!empty($ENV{APBUILD_BOGUS_DEPS})); + + # We call removeLibraries() twice because it may detect + # some dependancies after we've resolved the library names + @argv = removeLibraries(\@bogusDeps, @argv); + @argv = translateLibNames(@argv); + @argv = removeLibraries(\@bogusDeps, @argv); + + @argv = removeStaticGlibc(@argv); + if ($capabilities{as_needed}) { + @argv = rearrangeForAsNeeded(@argv); + @argv = forceStatic(@argv); + } + + return @argv; +} + + +sub removeLibraries { + my $blacklist = shift; + return @_ if (@{$blacklist} == 0); + + my @args; + my $callback = sub { + my $type = shift; + if ($type ne "param") { + push @args, @_; + return; + } + + my $lib; + $_ = $_[0]; + if (/^-l(.+)/) { + $lib = $1 + } elsif (/(.*)\/lib(.+)\.so/) { + $gcc->addSearchPaths($1); + $lib = $2; + } else { + push @args, @_; + return; + } + + # We now have a library parameter; remove this parameter + # if the library's in the blacklist + foreach my $dep (@{$blacklist}) { + return if ($lib eq $dep); + } + push @args, @_; + }; + + $gcc->foreach(\@_, $callback); + return @args; +} + + +# This function translates library linker options to something saner. +# - On my system, -lpng links to libpng.so. However, libpng.so is a symlink to libpng12.so. +# This function translates -lpng to -lpng12 so that the automatic bogus dependancy stripper +# can detect this as a bogus dependancy. +# - Translate /usr/lib/libpng.so to /usr/lib/libpng12.so because the soname is different. +# - Translates -pthread to -lpthread. +# - When in C++ mode, removes libstdc++.so from the argument list. This causes trouble when +# double compiling, unless the -nostdlib option is specified and we're not double compiling. +# libtool can put us in this configuration. + +# TODO: correctly handle static libraries. +# apg++ ... -L/usr/lib -Wl,-Bstatic -lphysfs -Wl,-Bdynamic +# -> /usr/lib/gcc-lib/i686-pc-linux-gnu/3.3.5/../../../../i686-pc-linux-gnu/bin/ld: cannot find -lphysfs-1.0 +sub translateLibNames { + my (@args, @searchPaths); + + # Get a list of search paths + $gcc->getSearchPaths(\@_, \@searchPaths); + + my $staticMode = 0; + my $callback = sub { + my $type = shift; + my $dontAdd; + + if ($type ne 'param') { + push @args, @_; + return; + } + + $_ = $_[0]; + if (/^-Wl,(.+)/) { + # Detect whether the next library will be linked statically or dynamically + foreach my $arg (split /,/, $1) { + if ($arg eq '-Bdynamic') { + $staticMode = 0; + } elsif ($arg eq '-Bstatic') { + $staticMode = 1; + } + } + + } elsif ($staticMode) { + # Don't try to resolve library name if it's linked statically + + } elsif (/^-l(.+)/ || /--library=(.+)/) { + my $libname = $1; + + # Resolve libname if explicitely asked to, through APBUILD_RESOLVE_LIBPATH. + my @libtosolve = split / +/, $ENV{APBUILD_RESOLVE_LIBPATH} if (!empty($ENV{APBUILD_RESOLVE_LIBPATH})); + foreach (@libtosolve) { + my $regexp = $_; + if ($libname =~ /($regexp)/) { + my $file = searchLib("lib$libname.a", \@searchPaths); + if ($file && -f $file) { + debug "resolved", $_[0], "as", $file; + # Replace -lXXX with the absolute path for libXXX.a + $_[0] = $file; + last; + } + } + } + + # Library is a symlink; check whether the sonames match + my $lib = searchLib("lib$libname.so", \@searchPaths); + if ($lib && -l $lib) { + my ($soname1) = $lib =~ /.*\/lib(.+)\.so/; + my $lib2 = soname($lib); + my ($soname2) = $lib2 =~ /lib(.+)\.so/; + + if ($soname1 ne $soname2 && defined searchLib("lib$soname2.so", \@searchPaths)) { + $_[0] = "-l$soname2"; + } + } + + } elsif ($_ eq '-pthread') { + $_[0] = "-lpthread"; + + } elsif ($ENV{APBUILD_CXX_MODE} && /\/?libstdc\+\+\.so(.[56])?/) { + # drop this in double compile mode as it can cause issues + # in single-compile mode leave it alone, otherwise, libtool can break + # ^^^ That used to be true + # Now drop it and add the compilers stdc++ + # Works around libtool problems where the wrong libstdc++.so is + # picked up from .la files of dependencies + my @command = ($gcc->command, "--print-file-name=libstdc++.so"); + chomp($_[0] = `@command`); + + } elsif (/(.*)\/?(lib.+\.so.*)/) { + $gcc->addSearchPaths ($1); + push @searchPaths, $1; + my $lib = searchLib($2, \@searchPaths); + if (defined $lib) { + my $soname = soname($lib); + $lib = searchLib($soname, \@searchPaths); + $_[0] = $lib if (defined $lib); + } + } + push @args, @_ if (!$dontAdd); + }; + $gcc->foreach(\@_, $callback); + + return @args; +} + + +# Replace -static with something else. We can't statically link to glibc! +# So we statically link to everything but glibc. +sub removeStaticGlibc { + my $hasStatic = 0; + foreach (@_) { + if ($_ eq '-static') { + $hasStatic = 1; + last; + } + } + return @_ if (!$hasStatic); + + my @argv; + foreach (@_) { + if ((/^-l(.+)/ || /^--library=(.+)/) && defined $1 && $1 ne 'c') { + push @argv, '-Wl,-Bstatic'; + push @argv, $_; + push @argv, '-Wl,-Bdynamic'; + } elsif ($_ ne "-static") { + push @argv, $_; + } + } + return @argv; +} + + +# 'gcc -Wl,--as-needed foo.o -lpng' breaks the binary. +# 'gcc foo.o -Wl,--as-needed -lpng' doesn't. +# Move object files to before the first library flag. +# +# Furthermore, -lbfd and -liberty must be the last arguments, or +# an app won't link properly in some cases. XRender needs to be +# after XCursor for some reason, so push it to the end too. +sub rearrangeForAsNeeded { + my @args; + my @nonParams; + my @last; + + my $callback = sub { + my $type = shift; + + if ($type ne "param") { + push @nonParams, @_; + + } elsif ($_[0] eq "-lbfd" || $_[0] eq "-liberty" || $_[0] eq "-lXrender") { + push @last, @_; + + } elsif ($gcc->isLibrary($_[0])) { + push @args, @_; + + } elsif ($gcc->isObject($_[0]) || $gcc->linkOrderIsImportant($_[0])) { + push @nonParams, @_; + + } else { + push @args, @_; + } + }; + + $gcc->foreach(\@_, $callback); + unshift @args, "-Wl,--as-needed"; + unshift @args, @nonParams; + push @args, @last; + return @args; +} + + +################ Automatic bogus dependancy stripper ################ + + +# Automatically detecting bogus dependancies & force static linking to certain X libraries +sub manipulateDeps { + return if ($capabilities{as_needed}); + my @searchPaths; + my $output = 'a.out'; + my $i = 0; + my @deps; + my @argv; + + if ($ENV{APBUILD_DISABLE_BOGUS_DETECTOR}) { + @argv = @_; + goto FINAL; + } + + # Get a list of search paths and the output filename + for ($i = 0; $i < @_; $i++) { + if ($_[$i] eq "-L") { + push (@searchPaths, $_[$i + 1]) if (defined $_[$i + 1]); + $i++; + } elsif ($_[$i] =~ /^-L(.+)/ || $_[$i] =~ /^--library-path=(.+)/) { + push (@searchPaths, $1); + } elsif ($_[$i] eq "-o") { + $output = $_[$i + 1] if (defined $_[$i + 1]); + $i++; + } + } + + # Find out what libraries the executable needs + my ($r, $w); + my $pid = open2 ($r, $w, 'objdump', '-p', $output); + close ($w); + foreach (<$r>) { + next unless (/^ NEEDED/); + s/^ NEEDED[ \t]+//; + s/\n//; + my $lib = searchLib ($_, \@searchPaths); + push (@deps, $lib) if (defined $lib); + } + close ($r); + waitpid ($pid, 0); + + # Some -l options have no effect. For example, when linking apollon, + # -lXinerama is passed, yet the resulting executable doesn't have a + # DT_NEEDED entry for libXinerama.so. Remove those options so that + # they won't interfere with forceStatic(). + foreach (@_) { + if ((/^-l(.+)/ || /^--library=(.+)/) + && !searchLib("lib$1.a", \@searchPaths) + && !(/^-lpng$/) # Special case the libpng mess, bah + ) { + # "Xinerama" + my $arg = $1; + # Only add to @argv if $arg is in @deps + foreach my $dep (@deps) { + # "/usr/X11R6/lib/libXinerama.so.1" -> "Xinerama" + my ($soname) = $dep =~ /.*\/lib(.+)\.so/; + if ($arg eq $soname) { + push (@argv, "-l$arg"); + last; + } + } + } else { + push (@argv, $_); + } + } + + # Find out which symbols the executable needs, and which symbols are provided + # by the libraries it's linked to. + my %appsyms = extractSymbols ('UBV', $output); + my @bogusDeps; + + foreach my $lib (@deps) { + # Never remove libc, libgcc_s and libstdc++ + next if ($lib =~ /^\/lib\/lib(c|gcc_s|stdc\+\+)\.so/); + + my %libsyms = extractSymbols ('TBVRDSWG', $lib); + my $bogus = 1; + + foreach my $sym (keys %libsyms) { + if (defined $appsyms{$sym}) { + debug ("Real dependancy $lib: $sym (lib: $libsyms{$sym} - app: $appsyms{$sym})\n"); + $bogus = 0; + last; + } + } + + if ($bogus) { + my ($soname) = $lib =~ /.*\/lib(.+)\.so/; + push (@bogusDeps, $soname); + } + } + + FINAL: { + # Don't strip dependancies that are explicitly marked as not bogus + my %notBogus; + if (!empty($ENV{APBUILD_NOT_BOGUS})) { + foreach (split / +/, $ENV{APBUILD_NOT_BOGUS}) { + $notBogus{$_} = 1; + } + } + + my @tmp; + foreach (@bogusDeps) { + push @tmp, $_ if (!$notBogus{$_}); + } + @bogusDeps = @tmp; + + my @options = removeLibraries(\@bogusDeps, @argv); + @options = forceStatic(@options); + + if ("@options" ne "@argv") { + my @command = ($gcc->command, @include, @linking, @options); + debug("Bogus dependancies: @bogusDeps\n") if (@bogusDeps); + debug("Relinking: @command\n"); + my $status = run(@command); + exit($status) if ($status != 0); + } + } +} + +sub extractSymbols { + my $types = shift; + my %symbols = (); + my ($r, $w); + my $pid = open2 ($r, $w, 'nm', '-D', @_); + + close ($w); + foreach (<$r>) { + if (/^.{9}[$types]/) { + s/\n//; + s/^.{9}//; + my ($type, $name) = split (/ /, $_, 2); + $symbols{$name} = $type; + } + } + close ($r); + waitpid ($pid, 0); + return %symbols; +} + + +# Force static linking against libraries in $APBUILD_STATIC and certain X libraries. +sub forceStatic { + my (%xlibs, %staticList, $X11linked, $linkedToStaticX); + my (@args, @searchPaths); + + # Create a list of libraries that we want to statically link + $gcc->getSearchPaths(\@_, \@searchPaths); + if (defined $ENV{'APBUILD_NO_STATIC_X'}) { + warn "WARNING: APBUILD_NO_STATIC_X is no longer used because it became the default behaviour.\n"; + } + if (defined $ENV{'APBUILD_STATIC_X'} && $ENV{'APBUILD_STATIC_X'} eq "1") { + foreach (qw(Xrender Xcursor Xfixes Xi Xinerama Xrandr Xv Xxf86dga Xxf86misc Xxf86vm)) { + my $file = searchLib("lib$_.a", \@searchPaths); + $staticList{$_} = $file if (defined $file); + $xlibs{$_} = 1; + } + } + + my @static_deps; + if (!empty($ENV{APBUILD_STATIC})) { + foreach (split / +/, $ENV{APBUILD_STATIC}) { + my ($lib, $file) = split /=/, $_, 2; + $file = searchLib("lib$lib.a", \@searchPaths) if (!defined $file); + $staticList{$lib} = $file if (defined $file); + + if (defined $file) { + # find the DT_NEEDED entries that this library-to-be-made-static + # has so that final linking works (the deps need to be added after the static lib so the bogus stripper doesn't remove them) + my ($r, $w); + my $abslib = searchLib("lib$lib.so", \@searchPaths); + if (!defined $abslib) { + warn "WARNING: Failed to find lib$lib.so in " . join(":", @searchPaths) . ".\n"; + next; + } + my $pid = open2 ($r, $w, 'objdump', '-p', $abslib); + close ($w); + foreach (<$r>) { + next unless (/^ NEEDED\s+lib(.+?)\.so/); + s/^ NEEDED\s+lib(.+?)\.so(.*)/$1/; + s/\n//; + push(@static_deps, "-l$_"); + } + close ($r); + waitpid ($pid, 0); + } + } + } + + push (@_, @static_deps); + + # Modify linker options for static linking + my $callback = sub { + my $type = shift; + my $libname; + if ($type eq "param" && $gcc->isLibrary($_[0], \$libname)) { + $X11linked = 1 if (!$X11linked && $libname eq 'X11'); + if ($staticList{$libname}) { + # This parameter is a library and is in the list of libraries + # to statically link; replace parameter by a filename to the + # static library + push @args, $staticList{$libname}; + $linkedToStaticX = 1 if ($xlibs{$libname}); + + if ($libname eq "Xcursor") { + # With some versions of X11 (on Slack 11, + # xorg 6.9.0, anyway), Xcursor links against Xfixes. + # If we switch Xcursor to being linked statically, + # force linking of Xfixes too so we don't get + # undefined symbol errors from Xcursor. + push @args, $staticList{"Xfixes"}; + } + + } else { + push @args, @_; + } + + } else { + push @args, @_; + } + }; + $gcc->foreach(\@_, $callback); + + # The app must be linked to libX11 if it has statically linked any the static X libraries + push @args, "-lX11" if ($linkedToStaticX && !$X11linked); + return @args; +} + +## +# compileSource(source, argss, extension, extra...) +# source: the source filename. +# args: the full GCC arguments (may include other source files) used for compilation. +# extension: if not undef, $extension will be appended to the output object file's filename. +# extra: extra parameters to pass to the compiler. +sub compileSource { + my ($source, $args, $ext) = @_; + my (@command, @tmp, @params, @sourceParams, @otherParams); + + $gcc->splitParams($args, undef, \@tmp); + push @tmp, $source; + + if (defined $ext) { + # Change the output file's extension. + $gcc->setOutputFile(\@tmp, $gcc->getOutputFile(\@tmp) . $ext); + } + $gcc->splitParams(\@tmp, undef, \@params); + + my $callback = sub { + my $type = shift; + if ($type eq 'param' && $gcc->sourceOrderIsImportant($_[0])) { + push @sourceParams, @_; + } else { + push @otherParams, @_; + } + }; + $gcc->foreach(\@params, $callback); + + if ($source =~ /\.($srcTypes)$/) { + @command = ($gcc->command, @include, @sourceParams, $source, @otherParams); + } else { + @command = ($gcc->command, @sourceParams, $source, @otherParams); + } + + debug "@command\n"; + my $status = run(@command); + exit($status) if ($status != 0); +} + +# Checks whether there should be an ABI2 version of a certain static library. +sub checkStaticLibrary { + my ($lib, $ext) = @_; + my ($pid, $r, $w, @objects, $doubleCompile); + my (undef, $libdir, $libname) = File::Spec->splitpath($lib); + my $newlib = "$lib$ext"; + + # Return the ABI2 version if already exists. + return $newlib if (-f $newlib); + + # Check the content of the archive. Check whether + # there are ABI2 versions of the object files inside. + $pid = open2($r, $w, 'ar', 't', $lib); + close($w); + while ((my $file = <$r>)) { + $file =~ s/\n//g; + if (-f "$libdir/$file$ext") { + push @objects, "$file$ext"; + $doubleCompile = 1; + } else { + push @objects, $file; + } + } + close($r); + waitpid ($pid, 0); + + if ($doubleCompile) { + my $oldDir = getcwd(); + $newlib = "$libname$ext"; + debug "Creating static library $newlib\n"; + + chdir($libdir); + my @command = ("ar", "cru", $newlib, @objects); + debug(@command); + my $ret = run(@command); + exit($ret) if ($ret != 0); + + @command = ("ranlib", $newlib); + debug(@command); + $ret = run(@command); + exit($ret) if ($ret != 0); + + chdir($oldDir); + return $newlib; + } else { + return undef; + } +} + +sub linkObjects { + my ($args, $ext) = @_; + my @options = modifyLinkerOptions(@{$args}); + + if (defined $ext) { + $gcc->setOutputFile(\@options, $gcc->getOutputFile(\@options) . $ext); + + # Check whether this object links to any static libraries. + # If it does, check whether there should be an ABI2 version of that + # static library, and attempt to create it. + my @options2; + + my $callback = sub { + my $type = shift; + if ($type eq 'param' && $gcc->isStaticLib($_[0])) { + my $newlib = checkStaticLibrary($_[0], $ext); + if (defined $newlib) { + push @options2, $newlib; + } else { + push @options2, @_; + } + } else { + push @options2, @_; + } + }; + $gcc->foreach(\@options, $callback); + @options = @options2; + } + + my @command = ($gcc->command, @linking, @options); + debug "@command\n"; + + my $status = run(@command); + exit ($status) if ($status != 0); + + my (@files, @options2); + $gcc->splitParams(\@options, \@files, \@options2); + manipulateDeps(@files, @options2); +} + +## +# beginDoubleCompiling() +# +# Prepare the environment for double compiling. +sub beginDoubleCompiling { + # Since g++ will be executed another time, we don't want it to + # print output to stdout/stderr, because it can potentially + # screw up some build systems such as libtool. + # stderr will go to the console (/dev/tty), stdout will be + # lost (/dev/null). + + our $stdout_fd = fileno(STDOUT); + our $stderr_fd = fileno(STDERR); + our $stdout_saved = POSIX::dup($stdout_fd); + our $stderr_saved = POSIX::dup($stderr_fd); + + my $fd1 = POSIX::open("/dev/null", O_CREAT | O_WRONLY, 0644); + my $fd2 = POSIX::open("/dev/tty", O_CREAT | O_WRONLY, 0644); + POSIX::dup2($fd1, $stdout_fd); + POSIX::dup2($fd2, $stderr_fd); + POSIX::close($fd1); + POSIX::close($fd2); +} + +## +# endDoubleCompiling() +# +# Unprepare the environment for double compiling. +sub endDoubleCompiling { + our ($stdout_fd, $stderr_fd, $stdout_saved, $stderr_saved); + + POSIX::dup2($stdout_saved, $stdout_fd); + POSIX::dup2($stderr_saved, $stderr_fd); + POSIX::close($stdout_saved); + POSIX::close($stderr_saved); +} diff --git a/tools/apbuild/apsymbols.h b/tools/apbuild/apsymbols.h new file mode 100644 index 00000000..32c7b18c --- /dev/null +++ b/tools/apbuild/apsymbols.h @@ -0,0 +1,275 @@ +/* apbuild embedded metadata */ +#define APBUILD_NOTE_METADATA(s) __asm__(".section .metadata, \"MS\", @note, 1\n\t.string \"" s "\"\n\t.previous\n\t") + +#ifdef APBUILD_VERSION +APBUILD_NOTE_METADATA("apbuild.version=" APBUILD_VERSION); +#endif + +/* apbuild generated symbol exclusion list */ +__asm__(".symver _sys_errlist,_sys_errlist@GLIBC_2.0"); +__asm__(".symver _sys_nerr,_sys_nerr@GLIBC_2.0"); +__asm__(".symver _sys_siglist,_sys_siglist@GLIBC_2.0"); +__asm__(".symver clnt_pcreateerror,clnt_pcreateerror@GLIBC_2.0"); +__asm__(".symver clnt_spcreateerror,clnt_spcreateerror@GLIBC_2.0"); +__asm__(".symver feupdateenv,feupdateenv@GLIBC_2.1"); +__asm__(".symver lio_listio,lio_listio@GLIBC_2.1"); +__asm__(".symver lio_listio64,lio_listio64@GLIBC_2.1"); +__asm__(".symver nftw,nftw@GLIBC_2.1"); +__asm__(".symver nftw64,nftw64@GLIBC_2.1"); +__asm__(".symver posix_fadvise64,posix_fadvise64@GLIBC_2.2"); +__asm__(".symver posix_fallocate64,posix_fallocate64@GLIBC_2.2"); +__asm__(".symver pthread_cond_broadcast,pthread_cond_broadcast@GLIBC_2.0"); +__asm__(".symver pthread_cond_destroy,pthread_cond_destroy@GLIBC_2.0"); +__asm__(".symver pthread_cond_init,pthread_cond_init@GLIBC_2.0"); +__asm__(".symver pthread_cond_signal,pthread_cond_signal@GLIBC_2.0"); +__asm__(".symver pthread_cond_timedwait,pthread_cond_timedwait@GLIBC_2.0"); +__asm__(".symver pthread_cond_wait,pthread_cond_wait@GLIBC_2.0"); +__asm__(".symver regexec,regexec@GLIBC_2.0"); +__asm__(".symver rpc_createerr,rpc_createerr@GLIBC_2.0"); +__asm__(".symver sys_errlist,sys_errlist@GLIBC_2.0"); +__asm__(".symver sys_nerr,sys_nerr@GLIBC_2.0"); +__asm__(".symver sys_sigabbrev,sys_sigabbrev@GLIBC_2.0"); +__asm__(".symver sys_siglist,sys_siglist@GLIBC_2.0"); +__asm__(".symver vm86,vm86@GLIBC_2.0"); +__asm__(".symver __rpc_thread_createerr,__rpc_thread_createerr@GLIBC_2.2.3"); +__asm__(".symver __guard,__guard@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __gethostname_chk,__gethostname_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver epoll_create,epoll_create@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __getdomainname_chk,__getdomainname_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __vswprintf_chk,__vswprintf_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __stpcpy_chk,__stpcpy_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver timerfd_gettime,timerfd_gettime@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver inotify_init1,inotify_init1@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __wcstombs_chk,__wcstombs_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __printf_chk,__printf_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __fgetws_chk,__fgetws_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __register_atfork,__register_atfork@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver gnu_dev_major,gnu_dev_major@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __vfwprintf_chk,__vfwprintf_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __wcpcpy_chk,__wcpcpy_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver open_wmemstream,open_wmemstream@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver inet6_opt_append,inet6_opt_append@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver timerfd_create,timerfd_create@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __swprintf_chk,__swprintf_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver getipv4sourcefilter,getipv4sourcefilter@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __vwprintf_chk,__vwprintf_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver readlinkat,readlinkat@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __wctomb_chk,__wctomb_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __readlink_chk,__readlink_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver setipv4sourcefilter,setipv4sourcefilter@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __isoc99_sscanf,__isoc99_sscanf@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __getlogin_r_chk,__getlogin_r_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver sync_file_range,sync_file_range@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __open64_2,__open64_2@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver inet6_rth_init,inet6_rth_init@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver inet6_opt_next,inet6_opt_next@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __fxstatat64,__fxstatat64@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver unlinkat,unlinkat@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __fwprintf_chk,__fwprintf_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __mempcpy_chk,__mempcpy_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver epoll_wait,epoll_wait@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver mkfifoat,mkfifoat@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __isoc99_scanf,__isoc99_scanf@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __read_chk,__read_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __fgetws_unlocked_chk,__fgetws_unlocked_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __vsprintf_chk,__vsprintf_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __wcsncpy_chk,__wcsncpy_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __stack_chk_fail,__stack_chk_fail@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver inotify_rm_watch,inotify_rm_watch@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver xdr_quad_t,xdr_quad_t@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __sched_cpualloc,__sched_cpualloc@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __obstack_vprintf_chk,__obstack_vprintf_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __isoc99_swscanf,__isoc99_swscanf@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __isoc99_vfwscanf,__isoc99_vfwscanf@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __sched_cpufree,__sched_cpufree@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver inet6_opt_finish,inet6_opt_finish@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __confstr_chk,__confstr_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __wcsncat_chk,__wcsncat_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver setsourcefilter,setsourcefilter@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver xdr_u_quad_t,xdr_u_quad_t@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __fread_unlocked_chk,__fread_unlocked_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver eaccess,eaccess@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver inet6_option_alloc,inet6_option_alloc@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __openat64_2,__openat64_2@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver sched_setaffinity,sched_setaffinity@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver inet6_option_append,inet6_option_append@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver futimens,futimens@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver renameat,renameat@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __wmemset_chk,__wmemset_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver inet6_opt_get_val,inet6_opt_get_val@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver unshare,unshare@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __isoc99_vsscanf,__isoc99_vsscanf@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver signalfd,signalfd@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver inet6_option_next,inet6_option_next@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver inet6_rth_add,inet6_rth_add@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver semtimedop,semtimedop@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver utimensat,utimensat@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver inet6_rth_segments,inet6_rth_segments@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __pread_chk,__pread_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __syslog_chk,__syslog_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver eventfd,eventfd@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __fgets_unlocked_chk,__fgets_unlocked_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __getcwd_chk,__getcwd_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver fchmodat,fchmodat@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver dup3,dup3@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __vprintf_chk,__vprintf_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __fprintf_chk,__fprintf_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __wmemcpy_chk,__wmemcpy_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __isoc99_wscanf,__isoc99_wscanf@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __wcscpy_chk,__wcscpy_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __isoc99_fscanf,__isoc99_fscanf@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __mbstowcs_chk,__mbstowcs_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __dprintf_chk,__dprintf_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __wmempcpy_chk,__wmempcpy_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver symlinkat,symlinkat@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __memmove_chk,__memmove_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __getwd_chk,__getwd_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __vsnprintf_chk,__vsnprintf_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver mkostemp64,mkostemp64@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver eventfd_read,eventfd_read@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver remap_file_pages,remap_file_pages@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __isoc99_vswscanf,__isoc99_vswscanf@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver fdopendir,fdopendir@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __openat_2,__openat_2@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __fgets_chk,__fgets_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __strncpy_chk,__strncpy_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __sched_cpucount,__sched_cpucount@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __mbsrtowcs_chk,__mbsrtowcs_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __wcscat_chk,__wcscat_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver inet6_option_space,inet6_option_space@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver sched_getaffinity,sched_getaffinity@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __open_2,__open_2@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver fchownat,fchownat@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver timerfd_settime,timerfd_settime@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver sched_getcpu,sched_getcpu@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __getgroups_chk,__getgroups_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver inet6_opt_init,inet6_opt_init@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __snprintf_chk,__snprintf_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver mkdirat,mkdirat@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __memset_chk,__memset_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __strncat_chk,__strncat_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver inet6_rth_space,inet6_rth_space@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __recv_chk,__recv_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver inet6_rth_reverse,inet6_rth_reverse@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __stack_smash_handler,__stack_smash_handler@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __realpath_chk,__realpath_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver qsort_r,qsort_r@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __obstack_printf_chk,__obstack_printf_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver inet6_rth_getaddr,inet6_rth_getaddr@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver splice,splice@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver eventfd_write,eventfd_write@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver vmsplice,vmsplice@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver getsourcefilter,getsourcefilter@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __isoc99_vwscanf,__isoc99_vwscanf@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver epoll_ctl,epoll_ctl@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver gnu_dev_minor,gnu_dev_minor@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __memcpy_chk,__memcpy_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __isoc99_vfscanf,__isoc99_vfscanf@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __stpncpy_chk,__stpncpy_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver inet6_opt_find,inet6_opt_find@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __mbsnrtowcs_chk,__mbsnrtowcs_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver strerror_l,strerror_l@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __fread_chk,__fread_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __wcsnrtombs_chk,__wcsnrtombs_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __wprintf_chk,__wprintf_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver epoll_create1,epoll_create1@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __vfprintf_chk,__vfprintf_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __vsyslog_chk,__vsyslog_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver inotify_add_watch,inotify_add_watch@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __wcrtomb_chk,__wcrtomb_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver epoll_pwait,epoll_pwait@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __strcpy_chk,__strcpy_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __vdprintf_chk,__vdprintf_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __vasprintf_chk,__vasprintf_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __xpg_strerror_r,__xpg_strerror_r@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __wcpncpy_chk,__wcpncpy_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver inet6_option_init,inet6_option_init@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __wmemmove_chk,__wmemmove_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __sprintf_chk,__sprintf_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver futimesat,futimesat@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __pread64_chk,__pread64_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver strptime_l,strptime_l@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver lchmod,lchmod@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __chk_fail,__chk_fail@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __isoc99_vscanf,__isoc99_vscanf@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __wcsrtombs_chk,__wcsrtombs_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver pipe2,pipe2@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __strcat_chk,__strcat_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver faccessat,faccessat@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __asprintf_chk,__asprintf_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ppoll,ppoll@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __recvfrom_chk,__recvfrom_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver inet6_opt_set_val,inet6_opt_set_val@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __ptsname_r_chk,__ptsname_r_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __isoc99_fwscanf,__isoc99_fwscanf@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __gets_chk,__gets_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver gnu_dev_makedev,gnu_dev_makedev@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __xmknodat,__xmknodat@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver inet6_option_find,inet6_option_find@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __ttyname_r_chk,__ttyname_r_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __readlinkat_chk,__readlinkat_chk@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver dlmopen,dlmopen@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver dladdr1,dladdr1@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver dlinfo,dlinfo@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver pthread_mutexattr_getprotocol,pthread_mutexattr_getprotocol@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver pthread_mutex_setprioceiling,pthread_mutex_setprioceiling@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver pthread_mutexattr_setprioceiling,pthread_mutexattr_setprioceiling@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __pthread_unregister_cancel_restore,__pthread_unregister_cancel_restore@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver pthread_attr_setaffinity_np,pthread_attr_setaffinity_np@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __pthread_cleanup_routine,__pthread_cleanup_routine@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver pthread_condattr_getclock,pthread_condattr_getclock@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __pthread_register_cancel_defer,__pthread_register_cancel_defer@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __pthread_unwind_next,__pthread_unwind_next@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver pthread_timedjoin_np,pthread_timedjoin_np@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver pthread_setaffinity_np,pthread_setaffinity_np@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver pthread_mutex_getprioceiling,pthread_mutex_getprioceiling@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver pthread_mutexattr_getprioceiling,pthread_mutexattr_getprioceiling@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver pthread_attr_getaffinity_np,pthread_attr_getaffinity_np@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver pthread_barrierattr_getpshared,pthread_barrierattr_getpshared@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver pthread_condattr_setclock,pthread_condattr_setclock@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver pthread_tryjoin_np,pthread_tryjoin_np@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver pthread_setschedprio,pthread_setschedprio@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver pthread_getaffinity_np,pthread_getaffinity_np@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver pthread_mutexattr_setrobust_np,pthread_mutexattr_setrobust_np@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver pthread_mutexattr_getrobust_np,pthread_mutexattr_getrobust_np@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver pthread_mutexattr_setprotocol,pthread_mutexattr_setprotocol@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver pthread_mutex_consistent_np,pthread_mutex_consistent_np@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_put16,ns_put16@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_name_pton,ns_name_pton@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_name_skip,ns_name_skip@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_name_pack,ns_name_pack@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_name_ntol,ns_name_ntol@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_sprintrr,ns_sprintrr@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_format_ttl,ns_format_ttl@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_name_ntop,ns_name_ntop@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_name_compress,ns_name_compress@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_name_unpack,ns_name_unpack@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_put32,ns_put32@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_sprintrrf,ns_sprintrrf@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_datetosecs,ns_datetosecs@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_get16,ns_get16@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_msg_getflag,ns_msg_getflag@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_samedomain,ns_samedomain@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __p_rcode,__p_rcode@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_parse_ttl,ns_parse_ttl@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_get32,ns_get32@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_skiprr,ns_skiprr@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_parserr,ns_parserr@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_name_rollback,ns_name_rollback@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_samename,ns_samename@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_name_uncompress,ns_name_uncompress@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_subdomain,ns_subdomain@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_makecanon,ns_makecanon@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver ns_initparse,ns_initparse@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver mq_open,mq_open@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver __mq_open_2,__mq_open_2@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver mq_timedsend,mq_timedsend@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver mq_notify,mq_notify@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver mq_receive,mq_receive@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver mq_close,mq_close@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver mq_getattr,mq_getattr@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver mq_send,mq_send@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver mq_unlink,mq_unlink@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver mq_setattr,mq_setattr@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver mq_timedreceive,mq_timedreceive@GLIBC_DONT_USE_THIS_SYMBOL"); +__asm__(".symver td_thr_tlsbase,td_thr_tlsbase@GLIBC_DONT_USE_THIS_SYMBOL"); diff --git a/tools/apbuild/buildlist b/tools/apbuild/buildlist new file mode 100755 index 00000000..24e789fd --- /dev/null +++ b/tools/apbuild/buildlist @@ -0,0 +1,48 @@ +#!/bin/bash + +# get a list of all symbols - YOU MUST RUN THIS SCRIPT WITH THE LATEST VERSIONS OF GLIBC +# currently blacklists all newer than 2.3.0 + +if [ -e syms ]; then rm syms; fi +if [ -e allsym ]; then rm allsym; fi +for f in /lib/*; do + if [ ! -f $f ]; then continue; fi + readelf -s --wide $f >>syms + objdump -T $f | grep "GLIBC_" | sed 's/\(.*\)GLIBC_//; s/)//' | grep -v PRIVATE | column -t >>allsym +done + + +# get a list of all symbol versions only available in 2.3+ +grep @@GLIBC_ syms | awk ' { print $8 } ' | sed 's/@@/ /; /GLIBC_P/d; s/GLIBC_//' | awk ' { if ($2 > 2.3) print $1 " " $2 } ' | column -t >glibc2.4.syms + +# select the symbols that already existed, but were obsoleted by 2.2+ versions +cat glibc2.4.syms | awk '{print $1}' | while read; do grep $REPLY allsym; done | sed '/2\.4/d' >syms-to-header + +# select the latest symbols of that set +# build a header from them +cat syms-to-header | awk '{print $2 " " $1 }' | sort | uniq >output +cat glibc2.4.syms | sort | uniq >> output + +cat output | sort | uniq | awk '{print $2 " " $1}' | sort -k2,1 | awk '{ if ($1 <= 2.3) print $1 " " $2 }' | column -t | sort -k2 | uniq -f1 >output2 + +# output the symbols that are brand new to 2.3+, ie not the ones that had earlier versions +cat glibc2.4.syms | awk '{ print $1 }' | while read; do if ! grep "$REPLY" output2 >/dev/null; then echo "DONT_USE_THIS_SYMBOL $REPLY" >>output2; fi; done; + +cat output2 | column -t | awk '{ print "__asm__(\".symver " $2 "," $2 "@GLIBC_" $1 "\");" }' > output + +# now remove dl_iterate_phdr as it's weak anyway (we should probably do this for all weak syms) +cat output | sed 's/__asm__("\.symver dl_iterate_phdr.*//' >output2 + +cat <apsymbols.h +/* apbuild embedded metadata */ +#define APBUILD_NOTE_METADATA(s) \ + __asm__(".section .metadata, \"MS\", @note, 1\n\t.string \"" s "\"\n\t.previous\n\t") + +#ifdef APBUILD_VERSION +APBUILD_NOTE_METADATA("apbuild.version=" APBUILD_VERSION); +#endif + +/* apbuild generated symbol exclusion list */ +EOF +cat output2 >> apsymbols.h +rm output2 diff --git a/tools/apbuild/ctype.h b/tools/apbuild/ctype.h new file mode 100644 index 00000000..2db84cc1 --- /dev/null +++ b/tools/apbuild/ctype.h @@ -0,0 +1,268 @@ +/* Copyright (C) 1991,92,93,95,96,97,98,99,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard 7.4: Character handling + */ + +#ifndef _CTYPE_H +#define _CTYPE_H 1 + +#include +#include + +__BEGIN_DECLS + +#ifndef _ISbit +/* These are all the characteristics of characters. + If there get to be more than 16 distinct characteristics, + many things must be changed that use `unsigned short int's. + + The characteristics are stored always in network byte order (big + endian). We define the bit value interpretations here dependent on the + machine's byte order. */ + +# include +# if __BYTE_ORDER == __BIG_ENDIAN +# define _ISbit(bit) (1 << (bit)) +# else /* __BYTE_ORDER == __LITTLE_ENDIAN */ +# define _ISbit(bit) ((bit) < 8 ? ((1 << (bit)) << 8) : ((1 << (bit)) >> 8)) +# endif + +enum +{ + _ISupper = _ISbit (0), /* UPPERCASE. */ + _ISlower = _ISbit (1), /* lowercase. */ + _ISalpha = _ISbit (2), /* Alphabetic. */ + _ISdigit = _ISbit (3), /* Numeric. */ + _ISxdigit = _ISbit (4), /* Hexadecimal numeric. */ + _ISspace = _ISbit (5), /* Whitespace. */ + _ISprint = _ISbit (6), /* Printing. */ + _ISgraph = _ISbit (7), /* Graphical. */ + _ISblank = _ISbit (8), /* Blank (usually SPC and TAB). */ + _IScntrl = _ISbit (9), /* Control character. */ + _ISpunct = _ISbit (10), /* Punctuation. */ + _ISalnum = _ISbit (11) /* Alphanumeric. */ +}; +#endif /* ! _ISbit */ + +/* These are defined in ctype-info.c. + The declarations here must match those in localeinfo.h. + + These point into arrays of 384, so they can be indexed by any `unsigned + char' value [0,255]; by EOF (-1); or by any `signed char' value + [-128,-1). ISO C requires that the ctype functions work for `unsigned + char' values and for EOF; we also support negative `signed char' values + for broken old programs. The case conversion arrays are of `int's + rather than `unsigned char's because tolower (EOF) must be EOF, which + doesn't fit into an `unsigned char'. But today more important is that + the arrays are also used for multi-byte character sets. */ +extern __const unsigned short int *__ctype_b; /* Characteristics. */ +extern __const __int32_t *__ctype_tolower; /* Case conversions. */ +extern __const __int32_t *__ctype_toupper; /* Case conversions. */ + +__asm__(".symver __ctype_b,__ctype_b@GLIBC_2.0"); +__asm__(".symver __ctype_tolower,__ctype_tolower@GLIBC_2.0"); +__asm__(".symver __ctype_toupper,__ctype_toupper@GLIBC_2.0"); + +#define __isctype(c, type) \ + (__ctype_b[(int) (c)] & (unsigned short int) type) + +#define __isascii(c) (((c) & ~0x7f) == 0) /* If C is a 7 bit value. */ +#define __toascii(c) ((c) & 0x7f) /* Mask off high bits. */ + +#define __exctype(name) extern int name (int) __THROW + +/* The following names are all functions: + int isCHARACTERISTIC(int c); + which return nonzero iff C has CHARACTERISTIC. + For the meaning of the characteristic names, see the `enum' above. */ +__exctype (isalnum); +__exctype (isalpha); +__exctype (iscntrl); +__exctype (isdigit); +__exctype (islower); +__exctype (isgraph); +__exctype (isprint); +__exctype (ispunct); +__exctype (isspace); +__exctype (isupper); +__exctype (isxdigit); + +#ifdef __USE_ISOC99 +__exctype (isblank); +#endif + + +/* Return the lowercase version of C. */ +extern int tolower (int __c) __THROW; + +/* Return the uppercase version of C. */ +extern int toupper (int __c) __THROW; + + +#if defined __USE_SVID || defined __USE_MISC || defined __USE_XOPEN + +/* Return nonzero iff C is in the ASCII set + (i.e., is no more than 7 bits wide). */ +extern int isascii (int __c) __THROW; + +/* Return the part of C that is in the ASCII set + (i.e., the low-order 7 bits of C). */ +extern int toascii (int __c) __THROW; + +/* These are the same as `toupper' and `tolower' except that they do not + check the argument for being in the range of a `char'. */ +__exctype (_toupper); +__exctype (_tolower); +#endif /* Use SVID or use misc. */ + +/* This code is needed for the optimized mapping functions. */ +#define __tobody(c, f, a, args) \ + (__extension__ \ + ({ int __res; \ + if (sizeof (c) > 1) \ + { \ + if (__builtin_constant_p (c)) \ + { \ + int __c = (c); \ + __res = __c < -128 || __c > 255 ? __c : a[__c]; \ + } \ + else \ + __res = f args; \ + } \ + else \ + __res = a[(int) (c)]; \ + __res; })) + +#ifndef __NO_CTYPE +# define isalnum(c) __isctype((c), _ISalnum) +# define isalpha(c) __isctype((c), _ISalpha) +# define iscntrl(c) __isctype((c), _IScntrl) +# define isdigit(c) __isctype((c), _ISdigit) +# define islower(c) __isctype((c), _ISlower) +# define isgraph(c) __isctype((c), _ISgraph) +# define isprint(c) __isctype((c), _ISprint) +# define ispunct(c) __isctype((c), _ISpunct) +# define isspace(c) __isctype((c), _ISspace) +# define isupper(c) __isctype((c), _ISupper) +# define isxdigit(c) __isctype((c), _ISxdigit) + +# ifdef __USE_ISOC99 +# define isblank(c) __isctype((c), _ISblank) +# endif + +# if __GNUC__ >= 2 && defined __OPTIMIZE__ && !defined __cplusplus +# define tolower(c) __tobody (c, tolower, __ctype_tolower, (c)) +# define toupper(c) __tobody (c, toupper, __ctype_toupper, (c)) +# endif /* Optimizing gcc */ + +# if defined __USE_SVID || defined __USE_MISC || defined __USE_XOPEN +# define isascii(c) __isascii (c) +# define toascii(c) __toascii (c) + +# define _tolower(c) ((int) __ctype_tolower[(int) (c)]) +# define _toupper(c) ((int) __ctype_toupper[(int) (c)]) +# endif + +#endif /* Not __NO_CTYPE. */ + + +#ifdef __USE_GNU +/* The concept of one static locale per category is not very well + thought out. Many applications will need to process its data using + information from several different locales. Another application is + the implementation of the internationalization handling in the + upcoming ISO C++ standard library. To support this another set of + the functions using locale data exist which have an additional + argument. + + Attention: all these functions are *not* standardized in any form. + This is a proof-of-concept implementation. */ + +/* Structure for reentrant locale using functions. This is an + (almost) opaque type for the user level programs. */ +# include + +/* These definitions are similar to the ones above but all functions + take as an argument a handle for the locale which shall be used. */ +# define __isctype_l(c, type, locale) \ + ((locale)->__ctype_b[(int) (c)] & (unsigned short int) type) + +# define __exctype_l(name) extern int name (int, __locale_t) __THROW + +/* The following names are all functions: + int isCHARACTERISTIC(int c, locale_t *locale); + which return nonzero iff C has CHARACTERISTIC. + For the meaning of the characteristic names, see the `enum' above. */ +__exctype_l (__isalnum_l); +__exctype_l (__isalpha_l); +__exctype_l (__iscntrl_l); +__exctype_l (__isdigit_l); +__exctype_l (__islower_l); +__exctype_l (__isgraph_l); +__exctype_l (__isprint_l); +__exctype_l (__ispunct_l); +__exctype_l (__isspace_l); +__exctype_l (__isupper_l); +__exctype_l (__isxdigit_l); + +__exctype_l (__isblank_l); + + +/* Return the lowercase version of C in locale L. */ +extern int __tolower_l (int __c, __locale_t __l) __THROW; + +/* Return the uppercase version of C. */ +extern int __toupper_l (int __c, __locale_t __l) __THROW; + +# if __GNUC__ >= 2 && defined __OPTIMIZE__ && !defined __cplusplus +# define __tolower_l(c, locale) \ + __tobody (c, __tolower_l, (locale)->__ctype_tolower, (c, locale)) +# define __toupper_l(c, locale) \ + __tobody (c, __toupper_l, (locale)->__ctype_toupper, (c, locale)) +# endif /* Optimizing gcc */ + + +# ifndef __NO_CTYPE +# define __isalnum_l(c,l) __isctype_l((c), _ISalnum, (l)) +# define __isalpha_l(c,l) __isctype_l((c), _ISalpha, (l)) +# define __iscntrl_l(c,l) __isctype_l((c), _IScntrl, (l)) +# define __isdigit_l(c,l) __isctype_l((c), _ISdigit, (l)) +# define __islower_l(c,l) __isctype_l((c), _ISlower, (l)) +# define __isgraph_l(c,l) __isctype_l((c), _ISgraph, (l)) +# define __isprint_l(c,l) __isctype_l((c), _ISprint, (l)) +# define __ispunct_l(c,l) __isctype_l((c), _ISpunct, (l)) +# define __isspace_l(c,l) __isctype_l((c), _ISspace, (l)) +# define __isupper_l(c,l) __isctype_l((c), _ISupper, (l)) +# define __isxdigit_l(c,l) __isctype_l((c), _ISxdigit, (l)) + +# define __isblank_l(c,l) __isctype_l((c), _ISblank, (l)) + +# if defined __USE_SVID || defined __USE_MISC || defined __USE_XOPEN +# define __isascii_l(c,l) __isascii(c) +# define __toascii_l(c,l) __toascii(c) +# endif + +# endif /* Not __NO_CTYPE. */ + +#endif /* Use GNU. */ + +__END_DECLS + +#endif /* ctype.h */ diff --git a/tools/apbuild/make-icons b/tools/apbuild/make-icons new file mode 100755 index 00000000..32c0c600 --- /dev/null +++ b/tools/apbuild/make-icons @@ -0,0 +1,58 @@ +#!/bin/sh + +# +# This script generates a directory and an automake fragment from an SVG +# file. It's useful when you have an SVG and want to pre-render icons of +# various sizes from it, then install them into the users icon theme. +# +# For autopackage users, put the following line in your specfile: +# +# installIcon share/icons/hicolor +# +# It uses rsvg to render the icons + +if [[ "$1" == "" ]] || [[ "$2" == "" ]] || [[ "$1" == "--help" ]] || [[ "$1" == "-h" ]]; then + echo "Usage: make-icons myprogram.svg type" + echo + echo "Generates a subdirectory called icons with an icon theme tree" + echo "in it. Also outputs some automake code you can copy/paste". + echo "" + echo "type is the type of icon and should be one of the following:" + echo "apps, mimetypes, actions, devices, filesystems" + echo "See FDO spec for details--you most likely want apps or mimetypes" + exit 0 +fi + +if ! which rsvg >/dev/null; then + # a part of librsvg + echo "make-icons: this script needs the rsvg program installed" + exit 1 +fi + +if [ ! -e $1 ]; then + echo "make-icons: the given file does not exist" + exit 1 +fi + +if [[ "$2" != "apps" && "$2" != "mimetypes" && "$2" != "actions" && "$2" != "devices" && "$2" != "filesystems" ]]; then + echo "make-icons: $2 is not a valid icon type. type should be one of these:" + echo "apps, mimetypes, actions, devices, filesystems" + echo "See FDO spec for details--you most likely want apps or mimetypes" + exit 1 +fi +mkdir -p icons/scalable/$2 +cp $1 icons/scalable/$2 + +newname="`basename $1`" +echo "iconSVGdir = \$(datadir)/icons/hicolor/scalable/$2" +echo "iconSVG_DATA = icons/scalable/$2/$newname" + +newname="${newname/.svg/}.png" + + +for size in 128 64 48 24 16; do + mkdir -p icons/${size}x${size}/$2 + rsvg --width=$size --height=$size $1 icons/${size}x${size}/$2/$newname + echo "icon${size}dir = \$(datadir)/icons/hicolor/${size}x${size}/$2" + echo "icon${size}_DATA = icons/${size}x${size}/$2/$newname" +done diff --git a/tools/apbuild/relaytool b/tools/apbuild/relaytool new file mode 100755 index 00000000..40b6de03 --- /dev/null +++ b/tools/apbuild/relaytool @@ -0,0 +1,584 @@ +#!/bin/bash + +# relaytool 1.2 +# Copyright 2004-2005 Mike Hearn +# Copyright 2005 Vincent Béron +# Copyright 2006 Psyche +# Copyright 2007 Taj Morton +# +############################################################################# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +############################################################################# +# +# TODO: +# - Figure out how to grab the GOT addr on PowerPC +# - Port to more archs +# - Figure out a way to check if we're on an ELF platform or not, +# maybe check for _GLOBAL_OFFSET_TABLE_ ? + +using_partial_map=false +using_minimal_list=false +using_multilink=false +outdir="." + +if [[ "$1" == "--version" ]]; then + echo "Relaytool 1.11" + echo "Copyright 2004 Mike Hearn" + echo "Copyright 2005 Vincent Béron" + echo + echo "See $0 for license details." + exit 1 +fi + +if [[ "$@" == "" ]] || [[ "$1" == "--help" ]] || [[ "$1" == "-h" ]]; then + echo "Relaytool will generate a file that can be used instead of linking" + echo "directly against a library, which will dlopen the DSO at init time" + echo + echo "Usage: relaytool [OPTION]... [LINKER COMMAND]..." + echo + echo "Options:" + echo " --relay LIB If a matching -lLIB is found, generate a file" + echo " that can be used instead of linking directly to" + echo " LIB. The name of the file is echoed on stdout." + echo " Multiple --relay can be used together, a file will" + echo " be generated for each matching ones." + echo " --replace-all-libs Generate a file for every -lLIB parameter." + echo " --minimal-list OBJ_LIST Will look in OBJ_LIST for undefined symbols, and" + echo " generate a file creating only the needed symbols" + echo " for each LIB." + echo " --partial-map MAP_FILE Generate a file creating only the symbols contained" + echo " in MAP_FILE. Will apply to all further -lLIB" + echo " parameters, so in general is not suitable to" + echo " multiple libs in the same invocation of relaytool." + echo " --no-replace Echo -lLIB on stdout even if a --relay LIB is" + echo " found, so it'll be linked in normally." + echo " --multilink [SONAMES...] If a library has different SONAMES on different" + echo " Linux distributions you can specify the various" + echo " SONAMES that it's known by here. Relaytool will" + echo " attempt to load them (in the order provided) until" + echo " one if found. This cannot be used with multiple" + echo " --relay options. The first SONAME in the list will" + echo " be used as the name in the _is_present variable and" + echo " _symbol_is_present function." + echo " --out-dir DIRECTORY Write stub file to DIRECTORY instead of CWD." + echo "Linker commands:" + echo " -LPATH Add PATH to the list of paths to search for LIBs." + echo " -lLIB If a matching --relay LIB is found (or if" + echo " --replace-all-libs is specified), generate a file" + echo " that can be used instead of linking directly to" + echo " LIB. If there's no --relay LIB, echo -lLIB to" + echo " stdout." + echo " All other linker commands are passed as is to stdout." + echo "Other commands:" + echo " --help|-h Print this help." + echo " --version Print version information." + exit 1 +fi + +function error() { + echo $@ >/dev/stderr + exit 1 +} + +function readfinallink() { + link_name="$1" + while [ -L "$link_name" ]; do + new_name=$( readlink "$link_name" ) + if [ "${new_name:0:1}" == "/" ]; then + link_name="$new_name" + else + link_name="`dirname "$link_name"`/$new_name" + fi + done + if [ -f "$link_name" ]; then + echo -n "$link_name" + exit 0 + else + exit 1 + fi +} + +function relay() { + lib="$1" + if $using_multilink; then + libname=$( echo $( basename ${multilinklist[0]} ) | sed 's/\.so.*//' | tr '-' '_' | tr '.' '_' ) + else + libname=$( echo $( basename "$lib" ) | sed 's/\.so.*//' | tr '-' '_' | tr '.' '_' ) + fi + soname=$( objdump -x "$lib" |grep SONAME | awk '{print $2}' ) + outfile="$outdir/`basename "$soname"`.stub.c" + + echo -n "$outfile" + + if $using_partial_map; then + functions=$( grep "^F " "$partial_map" | cut -d' ' -f2 ) + variables=$( grep "^V " "$partial_map" | cut -d' ' -f2 ) + else + functions=$( nm --extern-only -D "$lib" | awk '{ if (($2 == "T") || ($2 == "W")) print $3; }' | LC_ALL=C grep -v '\(\<_init\>\|\<_fini\>\)' | LC_ALL=C sort -u ) + variables=$( nm --extern-only -D "$lib" | awk '{ if (($2 == "D") || ($2 == "G") || ($2 == "B") || ($2 == "V")) print $3; }' | LC_ALL=C sort -u ) + fi + if $using_minimal_list; then + functions="$functions +$( nm `echo "$object_list"` | awk '{ if ($1 == "U") print $2; }' | LC_ALL=C sort -u )" + functions=$( echo "$functions" | LC_ALL=C sort | LC_ALL=C uniq -d ) + variables="$variables +$( nm `echo "$object_list"` | awk '{ if ($1 == "U") print $2; }' | LC_ALL=C sort -u )" + variables=$( echo "$variables" | LC_ALL=C sort | LC_ALL=C uniq -d ) + fi + + if [ "$functions" == "" ] && [ "$variables" == "" ]; then + # Nothing will be used, so do nothing for that lib + exit 1 + fi + + cat <"$outfile" +/* automatically generated: `date` by `id -un`@`uname -n`, do not edit + * + * Built by relaytool, a program for building delay-load jumptables + * relaytool is (C) 2004 Mike Hearn + * See http://autopackage.org/ for details. + */ +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + +static void **ptrs; +static char *functions[] = { +EOF + + for s in $functions; do + echo " \"$s\"," >>"$outfile" + done + echo " 0" >>"$outfile" + + cat <>"$outfile" +}; + +static char *variables[] = { +EOF + + for s in $variables; do + echo " \"$s\"," >>"$outfile" + done + echo " 0" >>"$outfile" + + cat <>"$outfile" +}; + +/* 1 if present, 0 if not */ +int ${libname}_is_present = 0; + +static void *handle = 0; + +/* 1 if present, 0 if not, 0 with warning to stderr if lib not present or symbol not found */ +int ${libname}_symbol_is_present(char *s) +{ + int i; + + if( !${libname}_is_present ) { + fprintf(stderr, "%s: relaytool: `basename "$lib"` not present so cannot check for symbol %s.\n", getenv("_"), s); + fprintf(stderr, "%s: relaytool: This probably indicates a bug in the application, please report.\n", getenv("_")); + return 0; + } + + i = 0; + while (functions[i++]) if (!strcmp( functions[i - 1], s )) return ptrs[i - 1] > 0 ? 1 : 0; + i = 0; + while (variables[i++]) if (!strcmp( variables[i - 1], s )) return dlsym( handle, s ) > 0 ? 1 : 0; + + fprintf( stderr, "%s: relaytool: %s is an unknown symbol in `basename "$lib"`.\n", getenv("_"), s ); + fprintf( stderr, "%s: relaytool: If you are the developer of this program, please correct the symbol name or rerun relaytool.\n", getenv("_") ); + return 0; +} + +__attribute__((noreturn)) void _relaytool_stubcall_${libname}(int offset) +{ + fprintf( stderr, "%s: relaytool: stub call to `basename "${lib}"`:%s, aborting.\n", getenv("_"), + functions[offset / sizeof(void*)] ); + exit( 1 ); +} + +#if defined( __i386__ ) + #define FIXUP_GOT_RELOC(sym, addr) \\ + asm("\tmovl %0, %%eax\n" \\ + "\tmovl %%eax, " sym "@GOT(%%ebx)\n" : : "r" (addr)); +#elif defined( __powerpc__ ) + + /* The PowerPC ELF ABI is a twisted nightmare. Until I figure it out, + for now we don't support GOT fixup on this architecture */ + + #error Variables are not currently supported on PowerPC + +#elif defined( __x86_64__ ) + #define FIXUP_GOT_RELOC(sym, addr) \\ + asm("\tmovq %0, %%rax\n" \\ + "\tmovq %%rax, " sym "@GOT(%%rbx)\n" : : "r" (addr)); +#else + #error Please define FIXUP_GOT_RELOC for your architecture +#endif + +void __attribute__((constructor)) _relaytool_init_${libname}() +{ + int i = 0; + + ptrs = malloc( sizeof(functions) ); + memset( ptrs, 0, sizeof(functions) ); +EOF + if $using_multilink; then + echo -n "char *multilink_libs[${#multilinklist[@]}] = {" | cat >> "$outfile" + for l in ${multilinklist[@]}; do + echo -n "\"$l\"" | cat >> "$outfile"; + if [[ "$l" != "${multilinklist[${#multilinklist[@]}-1]}" ]]; then + echo -n ", " | cat >> "$outfile"; + else + echo "};" | cat >> "$outfile" + fi + done + echo 'int multilink_count=0;' | cat >> "$outfile" + + echo 'while (!handle) { + handle = dlopen(multilink_libs[multilink_count++], RTLD_LAZY );' | cat >> "$outfile" + echo "if (multilink_count==${#multilinklist[@]}) break;}"| cat >> "$outfile" + else + echo "handle = dlopen( \"$soname\", RTLD_LAZY );" | cat >> "$outfile" + fi +cat <>"$outfile" + if (!handle) return; + + ${libname}_is_present = 1; + + /* build function jumptable */ + while (functions[i++]) ptrs[i - 1] = dlsym( handle, functions[i - 1] ); + +EOF + + if [ "$variables" != "" ]; then echo " /* now fixup the global offset table for variable imports */" >>"$outfile"; fi + for s in $variables; do + echo " FIXUP_GOT_RELOC( \"$s\", dlsym(handle, \"$s\") );" >>"$outfile" + done + + cat <>"$outfile" +} + +#if defined( __i386__ ) + +#define JUMP_SLOT(name, index) \\ + asm(".section .text." name ", \"ax\", @progbits\n" \\ + ".globl " name "\n" \\ + ".hidden " name "\n" \\ + " .type " name ", @function\n" \\ + name ":\n" \\ + " movl ptrs, %eax\n" \\ + " movl " #index "(%eax), %eax\n" \\ + " test %eax, %eax\n" \\ + " jnz JS" #index "\n" \\ + " push \$" #index "\n" \\ + " call _relaytool_stubcall_${libname}\n" \\ + "JS" #index ": jmp *%eax\n"); + + +#elif defined( __x86_64__ ) + +#define JUMP_SLOT(name, index) \\ + asm(".section .text." name ", \"ax\", @progbits\n" \\ + ".globl " name "\n" \\ + ".hidden " name "\n" \\ + " .type " name ", @function\n" \\ + name ":\n" \\ + " movq ptrs, %r11\n" \\ + " movq " #index "(%r11), %r11\n" \\ + " test %r11, %r11\n" \\ + " jnz JS" #index "\n" \\ + " push $" #index "\n" \\ + " call _relaytool_stubcall_${libname}\n" \\ + "JS" #index ": jmp *%r11\n"); +#elif defined( __powerpc__ ) + +#define JUMP_SLOT(name, index) \ \ + asm(".section .text." name ", \"ax\", @progbits\n" \\ + ".globl " name "\n" \\ + ".hidden " name "\n" \\ + " .type " name ", @function\n" \\ + name ":\n" \\ + " lis r11, ptrs@ha\n" \\ + " lwz r11, " #index "(r11)\n" \\ + " cmpi cr0,r11,0\n" \\ + " beq- 1f\n" \\ + " mtctr r11\n" \\ + " bctr\n" \\ + "1: li r3, " #index "\n" \\ + " b _relaytool_stubcall_${libname}\n" \\ + ); + +#else + #error Please define JUMP_SLOT for your architecture +#endif + +/* define placeholders for the variable imports: their type doesn't matter, + however we must restrict ELF symbol scope to prevent the definition in the imported + shared library being bound to this dummy symbol (not all libs are compiled -Bsymbolic) + */ +EOF + + for s in $variables; do + echo "int $s __attribute__(( visibility(\"hidden\") )) = -1;" >>"$outfile" + done + + cat <>"$outfile" + +/* define each jump slot in its own section. this increases generated code + size, but it means unused slots can be deleted by the linker when + --gc-sections is used. + */ +EOF + +# now generate the stubs + c=0 + for s in $functions; do + echo "JUMP_SLOT(\"$s\", $[c * $arch_ptr_size]);" >>"$outfile" + (( c++ )) + done + + echo >>"$outfile" + + cat <>"$outfile" + +#ifdef __cplusplus + } +#endif +EOF + +} + +function fakerelay() { + lib="$1" + libname=$( echo $( basename "$lib" ) | sed 's/\.so.*//' | tr '-' '_' | tr '.' '_' ) + soname=$( objdump -x "$lib" |grep SONAME | awk '{print $2}' ) + outfile="$outdir/`basename "$soname"`.stub.c" + + echo -n "$outfile" + + cat <"$outfile" +/* automatically generated: `date` by `id -un`@`uname -n`, do not edit + * + * Built by relaytool, a program for building delay-load jumptables + * relaytool is (C) 2004 Mike Hearn + * See http://autopackage.org/ for details. + */ + +#ifdef __cplusplus + extern "C" { +#endif + +/* 1 if present, 0 if not */ +int ${libname}_is_present = 1; + +/* 1 if present, 0 if not, 0 with warning to stderr if lib not present or symbol not found */ +int ${libname}_symbol_is_present(char * s) +{ + return 1; +} + +#ifdef __cplusplus + } +#endif +EOF + +} + +no_replace=false +replace_all=false +arch_ok=false +arch_ptr_size=0 +case `uname -m` in + i386 | i486 | i586 | i686 ) + arch_ok=true + arch_ptr_size=4 + ;; + x86_64) + arch_ok=true + arch_ptr_size=8 + ;; +esac + +searchpath=( "/usr/lib" "/usr/local/lib" "/lib" `pwd` ) +multilinklist=( ) +relaylist=( ) + +# process arguments +i=1 +while (( i <= $# )); do + a="${!i}" + + if [ "${a:0:2}" == "-L" ]; then + searchpath[${#searchpath}]="${a:2}" + echo -n "$a " # copy to stdout + + elif [ "$a" == "--replace-all-libs" ]; then + replace_all=true + + elif [ "$a" == "--partial-map" ]; then + using_partial_map=true + (( i++ )) + partial_map="${!i}" + + elif [ "$a" == "--minimal-list" ]; then + using_minimal_list=true + (( i++ )) + object_list="${!i}" + + elif [ "$a" == "--no-replace" ]; then + no_replace=true + + elif [ "$a" == "--multilink" ]; then + using_multilink=true + (( i++ )) + while [[ $i -lt $# && ${!i:0:2} != "--" ]]; do + multilinklist[${#multilinklist[@]}]="${!i}" + (( i++ )) + done + continue # $i has already been incremented, just continue with the loop + + elif [ "$a" == "--relay" ]; then + (( i++ )) + relaylist[${#relaylist[@]}]="${!i}" + + elif [ "$a" == "--out-dir" ]; then + (( i++ )) + outdir="${!i}" + + elif [ "$a" == "-ldl" ]; then + # libdl won't ever be supported by relaytool, so just pass it to stdout + echo -n "$a " + + elif [ "${a:0:2}" == "-l" ]; then + lib="${a:2}" + + # is this lib meant to be relayed? + if $replace_all; then + found=true + else + found=false + for b in ${relaylist[@]}; do + if [ "$b" == "$lib" ]; then + found=true + fi + done + fi + + if $found && $arch_ok; then + + # yes, so let's find its absolute filename by checking in each search path directory + spfound=false + for d in ${searchpath[@]}; do + if [ -e "$d/lib$lib.so" ]; then + + absname=$( readfinallink "$d/lib$lib.so" ) + if [ $? != 0 ] || [ ! -f "$absname" ]; then + error broken symlink "$absname" + fi + + stubfile=$( relay "$absname" ) + + # now we have to compile the stub + if [ $? == 0 ]; then + stubobj=$( echo "$stubfile" | sed 's/\.c$/\.o/' ) + # remove -include flags from CFLAGS, if any + CFLAGS=$( echo $CFLAGS | sed 's/-include .*\.h//g' ) + if [ -e /dev/tty ]; then + ${CC:-gcc} ${CFLAGS} -fPIC -c -o "$stubobj" "$stubfile" 2>/dev/tty + else + ${CC:-gcc} ${CFLAGS} -fPIC -c -o "$stubobj" "$stubfile" + fi + echo -n "$stubobj " + fi + + if $no_replace; then + echo -n "-l$lib " + fi + + spfound=true + break; + fi + done + + if ! $spfound; then + error could not find "$lib" in search path + fi + elif $found && ! $arch_ok; then + # yes, so let's find its absolute filename by checking in each search path directory + spfound=false + for d in ${searchpath[@]}; do + if [ -e "$d/lib$lib.so" ]; then + + absname=$( readfinallink "$d/lib$lib.so" ) + if [ $? != 0 ] || [ ! -f "$absname" ]; then + error broken symlink "$absname" + fi + + # Create a stub C source that just contains dummy + # libwhatever_... support functions + stubfile=$( fakerelay "$absname" ) + + # now we have to compile the stub + if [ $? == 0 ]; then + stubobj=$( echo "$stubfile" | sed 's/\.c$/\.o/' ) + # remove -include flags from CFLAGS, if any + CFLAGS=$( echo $CFLAGS | sed 's/-include .*\.h//g' ) + if [ -e /dev/tty ]; then + ${CC:-gcc} ${CFLAGS} -fPIC -c -o "$stubobj" "$stubfile" 2>/dev/tty + else + ${CC:-gcc} ${CFLAGS} -fPIC -c -o "$stubobj" "$stubfile" + fi + echo -n "$stubobj " + fi + + if $no_replace; then + echo -n "-l$lib " + fi + + spfound=true + break; + fi + done + + if ! $spfound; then + error could not find "$lib" in search path + fi + else + echo -n "$a " + fi + + else + # just copy whatever we don't recognise + echo -n "$a " + fi + + (( i++ )) +done +echo diff --git a/tools/apbuild/relaytool.m4 b/tools/apbuild/relaytool.m4 new file mode 100644 index 00000000..f8f20f98 --- /dev/null +++ b/tools/apbuild/relaytool.m4 @@ -0,0 +1,28 @@ +dnl Usage: RELAYTOOL(LIBRARY_NAME, LIBS, CFLAGS, ACTION-IF-WEAK-LINK-IS-POSSIBLE) + +dnl Example: +dnl RELAYTOOL("gtkspell", GTKSPELL_LIBS, GTKSPELL_CFLAGS, gtkspell_weak=yes) +dnl Will modify GTKSPELL_LIBS to include a call to relaytool if available +dnl or if not, will modify GTKSPELL_CFLAGS to include -D switches to define +dnl libgtkspell_is_present=1 and libgtkspell_symbol_is_present=1 + +AC_DEFUN([RELAYTOOL], [ + if test -z "$RELAYTOOL_PROG"; then + AC_PATH_PROG(RELAYTOOL_PROG, relaytool, no) + fi + + AC_MSG_CHECKING(whether we can weak link $1) + + _RELAYTOOL_PROCESSED_NAME=`echo "$1" | sed 's/-/_/g;s/\./_/g;'` + _RELAYTOOL_UPPER_NAME=`echo $_RELAYTOOL_PROCESSED_NAME | tr '[[:lower:]]' '[[:upper:]]'` + + if test "$RELAYTOOL_PROG" = "no"; then + AC_MSG_RESULT(no) + $3="-DRELAYTOOL_${_RELAYTOOL_UPPER_NAME}='static const int lib${_RELAYTOOL_PROCESSED_NAME}_is_present = 1; static int __attribute__((unused)) lib${_RELAYTOOL_PROCESSED_NAME}_symbol_is_present(char *m) { return 1; }' $$3" + else + AC_MSG_RESULT(yes) + $2="-Wl,--gc-sections \`relaytool --relay $1 $$2\`" + $3="-DRELAYTOOL_${_RELAYTOOL_UPPER_NAME}='extern int lib${_RELAYTOOL_PROCESSED_NAME}_is_present; extern int lib${_RELAYTOOL_PROCESSED_NAME}_symbol_is_present(char *s);' $$3" + $4 + fi +]) diff --git a/tools/apbuild/scandeps b/tools/apbuild/scandeps new file mode 100755 index 00000000..7d057129 --- /dev/null +++ b/tools/apbuild/scandeps @@ -0,0 +1,137 @@ +#!/usr/bin/env perl +use strict; +use IPC::Open2; + +if ($ARGV[0] eq '--version') { + print "scandeps version 1.0\n"; + print "Copright (c) 2005 Hongli Lai\n"; + print "Licensed under the GNU General Public License v2.\n"; + exit; +} elsif ($ARGV[0] eq '--help') { + print "Usage: scandeps [FILES...]\n"; + print "This script scans ELF binaries' library dependancies and prints a nice report\n" . + "of the dependancies.\n"; + exit; +} + + +# First, generate a list of binaries. Either scan user-specified files, +# or scan all files in the current directory (including subfolders). +my @files; + +if (@ARGV > 0) { + # Scan user-specified files + @files = @ARGV; +} else { + # Scan directory recursively + @files = scandir("."); +} + +# Now get the dependancies for all binaries +# %fileDeps: hash which contains a list of dependancies. The filename is the key. +# %depFiles: hash which contains a list of files. The dependancy is the key. +my (%fileDeps, %depFiles); +getdeps(\%fileDeps, \%depFiles, \@files); + +print "Common dependancies:\n"; +foreach my $dep (keys %depFiles) { + if (@{$depFiles{$dep}} == @files) { + print " $dep\n"; + } +} +print "\n"; + +print "All dependancies:\n"; +my @keys = keys %depFiles; +@keys = sort { @{$depFiles{$b}} - @{$depFiles{$a}} } @keys; +foreach my $dep (@keys) { + my $num = scalar(@{$depFiles{$dep}}); + my $word = ($num > 1) ? "files" : "file"; + printf " %-40s (used by %3d $word)\n", $dep, $num; +} + +print "\n"; +print "Dependancies and associated binaries:\n"; +foreach my $dep (@keys) { + print " $dep:\n"; + if (@{$depFiles{$dep}} == @files) { + print " All files depend on this library.\n"; + } else { + foreach my $file (@{$depFiles{$dep}}) { + print " $file\n"; + } + } + print "\n"; +} + + +################################## + +sub fatal { + print STDERR $_[0]; + exit 1; +} + +sub isELF { + my ($f, $data); + + if (!open($f, $_[0])) { + print STDERR "Warning: cannot open file '$_[0]' for reading.\n"; + return 0; + } + + binmode $f; + sysread $f, $data, 4; + close $f; + return $data eq "\177ELF"; +} + +sub scandir { + my $d; + + if (!opendir($d, $_[0])) { + print STDERR "Warning: cannot open directory '$_[0]' for reading.\n"; + return; + } + + my @files; + foreach my $file (readdir($d)) { + next if ($file eq "." || $file eq ".."); + + $file = "$_[0]/$file"; + if (-d $file) { + # Recurse into subdirectory + push @files, scandir("$file"); + + } elsif (-f $file && -x $file && isELF($file)) { + push @files, $file; + } + } + closedir($d); + return @files; +} + +sub getdeps { + my ($fileDeps, $depFiles, $files) = @_; + my ($r, $w); + if (!open2($r, $w, 'objdump', '-p', @{$files})) { + fatal("Cannot communicate with objdump.\n"); + } + close $w; + + my $currentFile; + foreach my $line (<$r>) { + if ($line =~ /^(.+):[ \t]+file format /) { + $currentFile = $1; + $currentFile =~ s/^.\///; + + } elsif ($line =~ /NEEDED[ \t]+(.+)$/) { + $fileDeps->{$currentFile} = [] if (!exists $fileDeps->{$currentFile}); + push @{$fileDeps->{$currentFile}}, $1; + + $depFiles->{$1} = [] if (!exists $depFiles->{$1}); + push @{$depFiles->{$1}}, $currentFile; + } + } + close $r; +} diff --git a/tools/apbuild/test-app/randomapp1.c b/tools/apbuild/test-app/randomapp1.c new file mode 100644 index 00000000..70252276 --- /dev/null +++ b/tools/apbuild/test-app/randomapp1.c @@ -0,0 +1,16 @@ +#include +#include +#include +#include +#include + +int main() { + char *respath = malloc(PATH_MAX); + unsigned char c = (unsigned char)"c"; + + printf("foo\n"); + printf("%d\n", isalpha(c)); + realpath("/some/path", respath); + fnmatch ("foo", "bar", 0); + return 0; +} -- cgit v1.2.3