]> git.saurik.com Git - apple/libsystem.git/blame - libsys/build-libc.pl
Libsystem-111.1.3.tar.gz
[apple/libsystem.git] / libsys / build-libc.pl
CommitLineData
7a301563
A
1#!/usr/bin/perl
2#
3# Copyright (c) 2006-2007 Apple Inc. All rights reserved.
4#
5# @APPLE_LICENSE_HEADER_START@
6#
7# This file contains Original Code and/or Modifications of Original Code
8# as defined in and that are subject to the Apple Public Source License
9# Version 2.0 (the 'License'). You may not use this file except in
10# compliance with the License. Please obtain a copy of the License at
11# http://www.opensource.apple.com/apsl/ and read it before using this
12# file.
13#
14# The Original Code and all software distributed under the License are
15# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19# Please see the License for the specific language governing rights and
20# limitations under the License.
21#
22# @APPLE_LICENSE_HEADER_END@
23#
24##########################################################################
25#
26# % build-libc.pl usr-local-lib-system out-directory
27#
28# This script takes the directory full of the contents libc-partial*.a and
29# libsyscall*.a, and makes the necessary symbol aliases for those syscalls
30# that aren't being wrapped in Libc. The usr-local-lib-system is the
31# /usr/local/lib/system or equivalent directory where the necessary symbol
32# files from Libc and Libsyscall reside.
33#
34# A Makefile is created that will build libc*.a from the contents of the
35# out-directory after symbol aliasing has been added.
36#
37# The out-directory path must be of the form ".../arch/form", where arch is
38# the architecture being built and form is one of debug, dynamic and profile.
39#
40##########################################################################
41
42use strict;
43use DirHandle;
44use File::Basename ();
45use File::Copy ();
46use File::Spec;
47use IO::File;
48
49my $MyName = File::Basename::basename($0);
50
51my $OutDir;
52my %Stub;
53my %StubArgs;
54my $StubFile = 'libsyscall.list';
55my %Suffix = (
56 debug => ['do', '_debug'],,
57 dynamic => ['So', ''],,
58 profile => ['po', '_profile'],,
59);
60my $SyscallBase = 'libc.syscall';
61
62##########################################################################
63# Scan the archive for existing wrappers, and remove them from the stub
64# list.
65##########################################################################
66sub processLibc {
c9e8bbd6 67 my($arch, $dir, $sufname) = @_;
7a301563 68 local $_;
c9e8bbd6 69 my $file = File::Spec->join($dir, "libc-partial$sufname.a");
7a301563
A
70 my $f = IO::File->new("nm -g -arch $arch $file |");
71 die "$MyName: nm -g -arch $arch $file: $!\n" unless defined($f);
72 while(<$f>) {
73 next unless s/^.* T //;
74 chomp;
75 delete($Stub{$_});
76 }
77}
78
79##########################################################################
80# Read the libc.syscall and any libc.syscall.arch file for additional aliases
81# for the double underbar syscalls.
82##########################################################################
83sub readLibcSyscalls {
84 my($arch, $dir) = @_;
85 local $_;
86 my @files = (File::Spec->join($dir, $SyscallBase));
87 my $archfile = File::Spec->join($dir, "$SyscallBase.$arch");
c9e8bbd6
A
88 if(-r $archfile) {
89 push(@files, $archfile);
90 } elsif($arch =~ s/^armv.*/arm/) {
91 $archfile = File::Spec->join($dir, "$SyscallBase.$arch");
92 push(@files, $archfile) if -r $archfile;
93 }
7a301563
A
94 foreach my $file (@files) {
95 my $f = IO::File->new($file, 'r');
96 die "$MyName: $file: $!\n" unless defined($f);
97 while(<$f>) {
98 next if /^#/;
99 chomp;
100 my($k, $v) = split;
101 if(defined($v)) {
102 $Stub{$k} = $v;
103 } else {
104 delete($Stub{$k});
105 }
106 }
107 }
108}
109
110##########################################################################
111# Read the libsyscall.list file for the system call names and number
112# of arguments and store in %StubArgs. Also, make an entry for a syscall
113# stub.
114##########################################################################
115sub readStub {
116 my $dir = shift;
117 local $_;
118 my $file = File::Spec->join($dir, $StubFile);
119 my $f = IO::File->new($file, 'r');
120 die "$MyName: $file: $!\n" unless defined($f);
121 while(<$f>) {
122 chomp;
123 my($k, $v) = split;
124 if(!($k =~ s/^#//)) {
125 $_ = $k;
126 s/^__//;
127 $Stub{$_} = $k;
128 }
129 $StubArgs{$k} = $v;
130 }
131}
132
133sub usage {
134 die "Usage: $MyName usr-local-lib-system out-directory\n";
135}
136
137usage() unless scalar(@ARGV) == 2;
138my($usr_local_lib_system);
139($usr_local_lib_system, $OutDir) = @ARGV;
140die "$MyName: $usr_local_lib_system: No such directory\n" unless -d $usr_local_lib_system;
141die "$MyName: $OutDir: No such directory\n" unless -d $OutDir;
142my @pieces = File::Spec->splitdir($OutDir);
143my $form = pop(@pieces);
144my $arch = pop(@pieces);
145my $suf = $Suffix{$form};
146die "$MyName: $form: Unknown form\n" unless defined($suf);
147my($suffix, $sufname) = @$suf;
148readStub($usr_local_lib_system);
149readLibcSyscalls($arch, $usr_local_lib_system);
c9e8bbd6 150processLibc($arch, $usr_local_lib_system, $sufname);
7a301563
A
151
152##########################################################################
153# Invert the Stub hash, so the key will correspond to the file to process.
154# The value will be an array ref containing all aliases.
155##########################################################################
156my %Inv;
157while(my($k, $v) = each(%Stub)) {
158 my $a = $Inv{$v};
159 $a = $Inv{$v} = [] if !defined($a);
160 push(@$a, $k);
161}
162
163##########################################################################
164# Create the Makefile file
165##########################################################################
166my $path = File::Spec->join($OutDir, 'Makefile');
167my $f = IO::File->new($path, 'w');
168die "$MyName: $path: $!\n" unless defined($f);
169
170##########################################################################
171# List all the object files
172##########################################################################
173my $dir = DirHandle->new($OutDir);
174die "$MyName: can't open $dir\n" unless defined($dir);
175print $f "OBJS = libsystem.o \\\n";
176my @objs;
177while(defined($_ = $dir->read())) {
178 next unless s/\.$suffix$/.o/;
179 push(@objs, $_);
180}
181undef $dir;
182printf $f "\t%s\n", join(" \\\n\t", @objs);
183
184##########################################################################
185# Add the build logic
186##########################################################################
187print $f <<XXX;
188
189LIB = libc$sufname.a
190
191all: \$(LIB)
192
193\$(LIB): \$(OBJS)
194 ar cq \$(.TARGET) `lorder \$(OBJS) | tsort -q`
195
196.SUFFIXES: .$suffix
197
198.$suffix.o:
199 mv \$(.IMPSRC) \$(.TARGET)
200
201XXX
202
203##########################################################################
204# Special case each binary that needs aliasing
205##########################################################################
206foreach my $k (sort(keys(%Inv))) {
207 my $n = $k;
208 $n =~ s/^_//;
209 print $f "$n.o: $n.$suffix\n";
210 print $f "\tld -arch $arch -r -keep_private_externs";
211 foreach my $i (@{$Inv{$k}}) {
212 $_ = $i;
213 s/\$/\$\$/g;
214 printf $f " -alias '$k' '$_'";
215 }
216 printf $f " -o \$(.TARGET) \$(.IMPSRC)\n";
217}