]>
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 { | |
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 | ########################################################################## | |
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"); | |
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 | ########################################################################## | |
115 | sub 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 | ||
133 | sub usage { | |
134 | die "Usage: $MyName usr-local-lib-system out-directory\n"; | |
135 | } | |
136 | ||
137 | usage() unless scalar(@ARGV) == 2; | |
138 | my($usr_local_lib_system); | |
139 | ($usr_local_lib_system, $OutDir) = @ARGV; | |
140 | die "$MyName: $usr_local_lib_system: No such directory\n" unless -d $usr_local_lib_system; | |
141 | die "$MyName: $OutDir: No such directory\n" unless -d $OutDir; | |
142 | my @pieces = File::Spec->splitdir($OutDir); | |
143 | my $form = pop(@pieces); | |
144 | my $arch = pop(@pieces); | |
145 | my $suf = $Suffix{$form}; | |
146 | die "$MyName: $form: Unknown form\n" unless defined($suf); | |
147 | my($suffix, $sufname) = @$suf; | |
148 | readStub($usr_local_lib_system); | |
149 | readLibcSyscalls($arch, $usr_local_lib_system); | |
c9e8bbd6 | 150 | processLibc($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 | ########################################################################## | |
156 | my %Inv; | |
157 | while(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 | ########################################################################## | |
166 | my $path = File::Spec->join($OutDir, 'Makefile'); | |
167 | my $f = IO::File->new($path, 'w'); | |
168 | die "$MyName: $path: $!\n" unless defined($f); | |
169 | ||
170 | ########################################################################## | |
171 | # List all the object files | |
172 | ########################################################################## | |
173 | my $dir = DirHandle->new($OutDir); | |
174 | die "$MyName: can't open $dir\n" unless defined($dir); | |
175 | print $f "OBJS = libsystem.o \\\n"; | |
176 | my @objs; | |
177 | while(defined($_ = $dir->read())) { | |
178 | next unless s/\.$suffix$/.o/; | |
179 | push(@objs, $_); | |
180 | } | |
181 | undef $dir; | |
182 | printf $f "\t%s\n", join(" \\\n\t", @objs); | |
183 | ||
184 | ########################################################################## | |
185 | # Add the build logic | |
186 | ########################################################################## | |
187 | print $f <<XXX; | |
188 | ||
189 | LIB = libc$sufname.a | |
190 | ||
191 | all: \$(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 | ||
201 | XXX | |
202 | ||
203 | ########################################################################## | |
204 | # Special case each binary that needs aliasing | |
205 | ########################################################################## | |
206 | foreach 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 | } |