jcs's openbsd hax
openbsd
1# $OpenBSD: Library.pm,v 1.14 2023/07/08 08:15:32 espie Exp $
2
3# Copyright (c) 2007-2010 Steven Mestdagh <steven@openbsd.org>
4# Copyright (c) 2012 Marc Espie <espie@openbsd.org>
5#
6# Permission to use, copy, modify, and distribute this software for any
7# purpose with or without fee is hereby granted, provided that the above
8# copyright notice and this permission notice appear in all copies.
9#
10# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
18use v5.36;
19
20package LT::Library::Stash;
21
22sub new($class)
23{
24 bless {}, $class;
25}
26
27sub create($self, $key)
28{
29 if (!exists $self->{$key}) {
30 $self->{$key} = LT::Library->new($key);
31 }
32 return $self->{$key};
33}
34
35package LT::Library;
36
37use LT::Util;
38use LT::Trace;
39
40# find actual library filename
41# XXX pick the right one if multiple are found!
42sub resolve_library($self, $dirs, $shared, $staticflag, $linkmode, $gp = undef)
43{
44
45 my $libtofind = $self->{key};
46 my $libfile = 0;
47 my @globbedlib;
48
49 my $pic = ''; # used when finding static libraries
50 if ($linkmode eq 'LT::LaFile') {
51 $pic = '_pic';
52 }
53
54 if (defined $self->{lafile}) {
55 require LT::LaFile;
56 # if there is a .la file, use the info from there
57 tsay {"found .la file $self->{lafile} for library key: ",
58 $self->{key}};
59 my $lainfo = LT::LaFile->parse($self->{lafile});
60 my $dlname = $lainfo->{dlname};
61 my $oldlib = $lainfo->{old_library};
62 my $libdir = $lainfo->{libdir};
63 my $installed = $lainfo->{installed};
64 my $d = abs_dir($self->{lafile});
65 # get the name we need (this may include a -release)
66 if (!$dlname && !$oldlib) {
67 die "Link error: neither static nor shared library found in $self->{lafile}\n";
68 }
69 if ($d !~ m/\Q$ltdir\E$/ && $installed eq 'no') {
70 $d .= "/$ltdir";
71 }
72 if ($shared) {
73 if ($dlname) {
74 $libfile = "$d/$dlname";
75 } else {
76 # fall back to static
77 $libfile = "$d/$oldlib";
78 }
79 # if -static has been passed, don't link dynamically
80 # against not-installed libraries
81 if ($staticflag && $installed eq 'no') {
82 $libfile = "$d/$oldlib";
83 }
84 } else {
85 $libfile = "$d/$oldlib";
86 }
87 if (! -f $libfile) {
88 tsay {".la file ", $self->{lafile},
89 "points to nonexistent file ", $libfile, " !"};
90 }
91 } else {
92 # search in .libs when priority is high
93 push @$dirs, $gp->libsearchdirs if defined $gp;
94 tsay {"searching for $libtofind"};
95 tsay {"search path= ", join(':', @$dirs)};
96 tsay {"search type= ", $shared ? 'shared' : 'static'};
97 foreach my $sd (@$dirs) {
98 if ($shared) {
99 # select correct library by sorting by version number only
100 my $bestlib = $self->findbest($sd, $libtofind);
101 if ($bestlib) {
102 tsay {"found $libtofind in $sd"};
103 $libfile = $bestlib;
104 last;
105 } else {
106 # XXX find static library instead?
107 my $spath = "$sd/lib$libtofind$pic.a";
108 if (-f $spath) {
109 tsay {"found static $libtofind in $sd"};
110 $libfile = $spath;
111 last;
112 }
113 }
114 } else {
115 # look for a static library
116 my $spath = "$sd/lib$libtofind.a";
117 if (-f $spath) {
118 tsay {"found static $libtofind in $sd"};
119 $libfile = $spath;
120 last;
121 }
122 }
123 }
124 }
125 if (!$libfile) {
126 delete $self->{fullpath};
127 if ($linkmode eq 'LT::LaFile') {
128 say "warning: dependency on $libtofind dropped";
129 $self->{dropped} = 1;
130 } elsif ($linkmode eq 'LT::Program') {
131 die "Link error: $libtofind not found!\n";
132 }
133 } else {
134 $self->{fullpath} = $libfile;
135 tsay {"\$libs->{$self->{key}}->{fullpath} = ",
136 $self->{fullpath}};
137 }
138}
139
140sub findbest($self, $sd, $name)
141{
142 my $best = undef;
143 if (opendir(my $dir, $sd)) {
144 my ($major, $minor) = (-1, -1);
145 while (my $e = readdir($dir)) {
146 next unless $e =~ m/^lib\Q$name\E\.so\.(\d+)\.(\d+)$/;
147 if ($1 > $major || ($1 == $major && $2 > $minor)) {
148 ($major, $minor) = ($1, $2);
149 $best = "$sd/$e";
150 }
151 }
152 closedir($dir);
153 }
154 if (!defined $best) {
155 my $cand = "$sd/lib$name.so";
156 if (-e $cand) {
157 $best = $cand;
158 }
159 }
160 return $best;
161}
162
163# give a list of library dependencies found in the actual shared library
164sub inspect($self)
165{
166 my $filename = $self->{fullpath};
167 my @deps;
168
169 if (!defined($filename)){
170 say "warning: library was specified that could not be found: $self->{key}";
171 return;
172 }
173 tsay {"inspecting $filename for library dependencies..."};
174 open(my $fh, '-|', "objdump", "-p", "--", $filename);
175 while (<$fh>) {
176 if (m/\s+NEEDED\s+(\S+)\s*$/) {
177 push @deps, $1;
178 }
179 }
180 tsay {"found ", (@deps == 0) ? 'no ' : '',
181 "deps for $filename\n@deps"};
182 return @deps;
183}
184
185# give the list of RPATH/RUNPATH directories
186sub findrpaths($self)
187{
188 my $filename = $self->{fullpath};
189 my @dirs;
190
191 if (!defined($filename)){
192 say "warning: library was specified that could not be found: $self->{key}";
193 return;
194 }
195 tsay {"inspecting $filename for non standard RPATH/RUNPATH..."};
196 open(my $fh, '-|', "objdump", "-p", "--", $filename);
197 while (<$fh>) {
198 if (m/R(?:UN)?PATH\s+(.*)$/) {
199 @dirs = split(":", $1);
200 last;
201 }
202 }
203 tsay {"found ", (@dirs == 0) ? 'none ' : '',
204 "RPATH/RUNPATH for $filename\n@dirs"};
205 return @dirs;
206}
207
208sub new($class, $key)
209{
210 bless { key => $key }, $class;
211}
212
2131;