]>
Commit | Line | Data |
---|---|---|
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 | ||
42 | use strict; | |
43 | use DirHandle; | |
44 | use File::Basename (); | |
45 | use File::Copy (); | |
46 | use File::Spec; | |
47 | use IO::File; | |
48 | ||
49 | my $MyName = File::Basename::basename($0); | |
50 | ||
51 | my $OutDir; | |
52 | my %Stub; | |
53 | my %StubArgs; | |
54 | my $StubFile = 'libsyscall.list'; | |
55 | my %Suffix = ( | |
56 | debug => ['do', '_debug'],, | |
57 | dynamic => ['So', ''],, | |
58 | profile => ['po', '_profile'],, | |
59 | ); | |
60 | my $SyscallBase = 'libc.syscall'; | |
61 | ||
62 | ########################################################################## | |
63 | # Scan the archive for existing wrappers, and remove them from the stub | |
64 | # list. | |
65 | ########################################################################## | |
66 | sub 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 | ########################################################################## | |
83 | sub 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 | ########################################################################## | |
110 | sub 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 | ||
128 | sub usage { | |
129 | die "Usage: $MyName usr-local-lib-system out-directory\n"; | |
130 | } | |
131 | ||
132 | usage() unless scalar(@ARGV) == 2; | |
133 | my($usr_local_lib_system); | |
134 | ($usr_local_lib_system, $OutDir) = @ARGV; | |
135 | die "$MyName: $usr_local_lib_system: No such directory\n" unless -d $usr_local_lib_system; | |
136 | die "$MyName: $OutDir: No such directory\n" unless -d $OutDir; | |
137 | my @pieces = File::Spec->splitdir($OutDir); | |
138 | my $form = pop(@pieces); | |
139 | my $arch = pop(@pieces); | |
140 | my $suf = $Suffix{$form}; | |
141 | die "$MyName: $form: Unknown form\n" unless defined($suf); | |
142 | my($suffix, $sufname) = @$suf; | |
143 | readStub($usr_local_lib_system); | |
144 | readLibcSyscalls($arch, $usr_local_lib_system); | |
145 | processLibc($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 | ########################################################################## | |
151 | my %Inv; | |
152 | while(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 | ########################################################################## | |
161 | my $path = File::Spec->join($OutDir, 'Makefile'); | |
162 | my $f = IO::File->new($path, 'w'); | |
163 | die "$MyName: $path: $!\n" unless defined($f); | |
164 | ||
165 | ########################################################################## | |
166 | # List all the object files | |
167 | ########################################################################## | |
168 | my $dir = DirHandle->new($OutDir); | |
169 | die "$MyName: can't open $dir\n" unless defined($dir); | |
170 | print $f "OBJS = libsystem.o \\\n"; | |
171 | my @objs; | |
172 | while(defined($_ = $dir->read())) { | |
173 | next unless s/\.$suffix$/.o/; | |
174 | push(@objs, $_); | |
175 | } | |
176 | undef $dir; | |
177 | printf $f "\t%s\n", join(" \\\n\t", @objs); | |
178 | ||
179 | ########################################################################## | |
180 | # Add the build logic | |
181 | ########################################################################## | |
182 | print $f <<XXX; | |
183 | ||
184 | LIB = libc$sufname.a | |
185 | ||
186 | all: \$(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 | ||
196 | XXX | |
197 | ||
198 | ########################################################################## | |
199 | # Special case each binary that needs aliasing | |
200 | ########################################################################## | |
201 | foreach 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 | } |