Stas Bekman wrote:
[...]
so that means that the linker decides that those symbols aren't used (and they indeed aren't) and it drops them. I think I've seen that behavior before. Just to prove that idea, try to use them somewhere (e.g some dummy function in mod_perl.c).
Exactly, when the target of a link operation is an actual binary, the linker will remove all unused functions. That is not the
case with a .so where the linker has no possible way of knowing what might be needed at a later time.
So, attached is a patch similar to httpd's ap_hack_* to work around this problem.
In a nutshell, create a modperl_exports.c that contains this :
const void *modperl_ugly_hack = NULL; const void *modperl_hack_$name = (const void *)modperl_$name; [...]
where $name is each and every single public modperl API function.
This doesn't even guarantee that the linker won't delete these entries from there, since it
will detect correctly that not a single external compilation uint needed any of the symbols
in modperl_exports.c. Thus, to create that dependency, in mod_perl.c :
const void *modperl_suck_in_ugly_hack(void);
const void *modperl_suck_in_ugly_hack(void)
{
extern const void *modperl_ugly_hack;
return modperl_ugly_hack;
}
And that does create an external link/dependency and the linker keeps all symbols around.
As a nice side effect, this might be of some help to people on more esoteric platforms.
Index: lib/ModPerl/Code.pm
===================================================================
RCS file: /home/cvs/modperl-2.0/lib/ModPerl/Code.pm,v
retrieving revision 1.125
diff -u -I$Id -r1.125 Code.pm
--- lib/ModPerl/Code.pm 2 Jul 2004 19:04:32 -0000 1.125
+++ lib/ModPerl/Code.pm 21 Sep 2004 06:17:50 -0000
@@ -637,6 +637,7 @@
generate_largefiles => {h => 'modperl_largefiles.h'},
generate_constants => {h => 'modperl_constants.h',
c => 'modperl_constants.c'},
+ generate_exports => {c => 'modperl_exports.c'},
);
my @c_src_names = qw(interp tipool log config cmd options callback handler
@@ -645,7 +646,7 @@
const constants apache_compat error debug
common_util common_log);
my @h_src_names = qw(perl_unembed);
-my @g_c_names = map { "modperl_$_" } qw(hooks directives flags xsinit);
+my @g_c_names = map { "modperl_$_" } qw(hooks directives flags xsinit exports);
my @c_names = ('mod_perl', (map "modperl_$_", @c_src_names));
sub c_files { [map { "$_.c" } @c_names, @g_c_names] }
sub o_files { [map { "$_.o" } @c_names, @g_c_names] }
@@ -1083,6 +1084,12 @@
unless $seen_const{$class}{$name}
}
}
+}
+
+sub generate_exports {
+ my($self, $c_fh) = @_;
+ require ModPerl::WrapXS;
+ ModPerl::WrapXS->generate_exports($c_fh);
}
# src/modules/perl/*.c files needed to build APR/APR::* outside
Index: lib/ModPerl/WrapXS.pm
===================================================================
RCS file: /home/cvs/modperl-2.0/lib/ModPerl/WrapXS.pm,v
retrieving revision 1.79
diff -u -I$Id -r1.79 WrapXS.pm
--- lib/ModPerl/WrapXS.pm 21 Sep 2004 05:54:56 -0000 1.79
+++ lib/ModPerl/WrapXS.pm 21 Sep 2004 06:17:51 -0000
@@ -1267,5 +1267,35 @@
return \%stats;
}
+sub generate_exports {
+ my($self, $fh) = @_;
+
+ if (!$build->should_build_apache) {
+ print $fh <<"EOF";
+/* This is intentionnaly left blank, only usefull for static build */
+const void *modperl_ugly_hack = NULL;
+EOF
+ return;
+ }
+
+ print $fh <<"EOF";
+/*
+ * This is indeed a ugly hack!
+ * See also src/modules/perl/mod_perl.c for modperl_ugly_hack
+ * If we don't build such a list of exported API functions, the over-zealous
+ * linker can and will remove the unused functions completely. In order to
+ * avoid this, we create this object and modperl_ugly_hack to create a
+ * dependency between all the exported API and mod_perl.c
+ */
+const void *modperl_ugly_hack = NULL;
+EOF
+
+ for my $entry (@$ModPerl::FunctionTable) {
+ next if $self->func_is_static($entry);
+ ( my $name ) = $entry->{name} =~ /^modperl_(.*)/;
+ print $fh "const void *modperl_hack_$name = (const void *)modperl_$name;\n";
+ }
+}
+
1;
__END__
Index: src/modules/perl/.cvsignore
===================================================================
RCS file: /home/cvs/modperl-2.0/src/modules/perl/.cvsignore,v
retrieving revision 1.12
diff -u -I$Id -r1.12 .cvsignore
--- src/modules/perl/.cvsignore 11 Sep 2004 00:07:33 -0000 1.12
+++ src/modules/perl/.cvsignore 21 Sep 2004 06:17:51 -0000
@@ -1,3 +1,4 @@
+modperl_exports.c
modperl_hooks.h
modperl_hooks.c
modperl_flags.h
Index: src/modules/perl/mod_perl.c
===================================================================
RCS file: /home/cvs/modperl-2.0/src/modules/perl/mod_perl.c,v
retrieving revision 1.221
diff -u -I$Id -r1.221 mod_perl.c
--- src/modules/perl/mod_perl.c 18 Sep 2004 04:33:34 -0000 1.221
+++ src/modules/perl/mod_perl.c 21 Sep 2004 06:17:51 -0000
@@ -1034,6 +1034,17 @@
return retval;
}
+/* This ugly hack pulls in any function listed in
+ * modperl_exports.c. Otherwise, the over-zealous
+ * linker would remove unused api functions
+ */
+const void *modperl_suck_in_ugly_hack(void);
+const void *modperl_suck_in_ugly_hack(void)
+{
+ extern const void *modperl_ugly_hack;
+ return modperl_ugly_hack;
+}
+
module AP_MODULE_DECLARE_DATA perl_module = {
STANDARD20_MODULE_STUFF,
modperl_config_dir_create, /* dir config creater */
signature.asc
Description: OpenPGP digital signature
