]> git.saurik.com Git - apple/libsystem.git/blame - libsys/build-libc.pl
Libsystem-111.1.1.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 {
67 my($arch, $dir) = @_;
68 local $_;
69 my $file = File::Spec->join($dir, 'libc-partial.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");
88 push(@files, $archfile) if -r $archfile;
89 foreach my $file (@files) {
90 my $f = IO::File->new($file, 'r');
91 die "$MyName: $file: $!\n" unless defined($f);
92 while(<$f>) {
93 next if /^#/;
94 chomp;
95 my($k, $v) = split;
96 if(defined($v)) {
97 $Stub{$k} = $v;
98 } else {
99 delete($Stub{$k});
100 }
101 }
102 }
103}
104
105##########################################################################
106# Read the libsyscall.list file for the system call names and number
107# of arguments and store in %StubArgs. Also, make an entry for a syscall
108# stub.
109##########################################################################
110sub readStub {
111 my $dir = shift;
112 local $_;
113 my $file = File::Spec->join($dir, $StubFile);
114 my $f = IO::File->new($file, 'r');
115 die "$MyName: $file: $!\n" unless defined($f);
116 while(<$f>) {
117 chomp;
118 my($k, $v) = split;
119 if(!($k =~ s/^#//)) {
120 $_ = $k;
121 s/^__//;
122 $Stub{$_} = $k;
123 }
124 $StubArgs{$k} = $v;
125 }
126}
127
128sub usage {
129 die "Usage: $MyName usr-local-lib-system out-directory\n";
130}
131
132usage() unless scalar(@ARGV) == 2;
133my($usr_local_lib_system);
134($usr_local_lib_system, $OutDir) = @ARGV;
135die "$MyName: $usr_local_lib_system: No such directory\n" unless -d $usr_local_lib_system;
136die "$MyName: $OutDir: No such directory\n" unless -d $OutDir;
137my @pieces = File::Spec->splitdir($OutDir);
138my $form = pop(@pieces);
139my $arch = pop(@pieces);
140my $suf = $Suffix{$form};
141die "$MyName: $form: Unknown form\n" unless defined($suf);
142my($suffix, $sufname) = @$suf;
143readStub($usr_local_lib_system);
144readLibcSyscalls($arch, $usr_local_lib_system);
145processLibc($arch, $usr_local_lib_system);
146
147##########################################################################
148# Invert the Stub hash, so the key will correspond to the file to process.
149# The value will be an array ref containing all aliases.
150##########################################################################
151my %Inv;
152while(my($k, $v) = each(%Stub)) {
153 my $a = $Inv{$v};
154 $a = $Inv{$v} = [] if !defined($a);
155 push(@$a, $k);
156}
157
158##########################################################################
159# Create the Makefile file
160##########################################################################
161my $path = File::Spec->join($OutDir, 'Makefile');
162my $f = IO::File->new($path, 'w');
163die "$MyName: $path: $!\n" unless defined($f);
164
165##########################################################################
166# List all the object files
167##########################################################################
168my $dir = DirHandle->new($OutDir);
169die "$MyName: can't open $dir\n" unless defined($dir);
170print $f "OBJS = libsystem.o \\\n";
171my @objs;
172while(defined($_ = $dir->read())) {
173 next unless s/\.$suffix$/.o/;
174 push(@objs, $_);
175}
176undef $dir;
177printf $f "\t%s\n", join(" \\\n\t", @objs);
178
179##########################################################################
180# Add the build logic
181##########################################################################
182print $f <<XXX;
183
184LIB = libc$sufname.a
185
186all: \$(LIB)
187
188\$(LIB): \$(OBJS)
189 ar cq \$(.TARGET) `lorder \$(OBJS) | tsort -q`
190
191.SUFFIXES: .$suffix
192
193.$suffix.o:
194 mv \$(.IMPSRC) \$(.TARGET)
195
196XXX
197
198##########################################################################
199# Special case each binary that needs aliasing
200##########################################################################
201foreach my $k (sort(keys(%Inv))) {
202 my $n = $k;
203 $n =~ s/^_//;
204 print $f "$n.o: $n.$suffix\n";
205 print $f "\tld -arch $arch -r -keep_private_externs";
206 foreach my $i (@{$Inv{$k}}) {
207 $_ = $i;
208 s/\$/\$\$/g;
209 printf $f " -alias '$k' '$_'";
210 }
211 printf $f " -o \$(.TARGET) \$(.IMPSRC)\n";
212}