diff --git a/embed.fnc b/embed.fnc index 762f47f06c63..6087f3fa1ac6 100644 --- a/embed.fnc +++ b/embed.fnc @@ -663,6 +663,10 @@ Adp |SV * |amagic_deref_call \ p |bool |amagic_is_enabled \ |int method +CTdp |void |api_version_assert \ + |size_t interp_size \ + |NULLOK void *v_my_perl \ + |NN const char *api_version ETXip |void |append_utf8_from_native_byte \ |const U8 byte \ |NN U8 **dest diff --git a/embed.h b/embed.h index 6cb789ce5e02..bb93d157939a 100644 --- a/embed.h +++ b/embed.h @@ -128,6 +128,7 @@ # define _to_utf8_upper_flags(a,b,c,d,e) Perl__to_utf8_upper_flags(aTHX_ a,b,c,d,e) # define amagic_call(a,b,c,d) Perl_amagic_call(aTHX_ a,b,c,d) # define amagic_deref_call(a,b) Perl_amagic_deref_call(aTHX_ a,b) +# define api_version_assert Perl_api_version_assert # define apply_attrs_string(a,b,c,d) Perl_apply_attrs_string(aTHX_ a,b,c,d) # define apply_builtin_cv_attributes(a,b) Perl_apply_builtin_cv_attributes(aTHX_ a,b) # define atfork_lock Perl_atfork_lock diff --git a/lib/ExtUtils/t/Embed.t b/lib/ExtUtils/t/Embed.t index 1057f8179096..49eb0a90052f 100644 --- a/lib/ExtUtils/t/Embed.t +++ b/lib/ExtUtils/t/Embed.t @@ -103,13 +103,26 @@ if ($^O eq 'VMS') { elsif ($^O eq 'os390' && $Config{usedl}) { push(@cmd,"-L$lib", ldopts()); } else { # Not MSWin32 or OS/390 (z/OS) dynamic. - push(@cmd,"-L$lib",'-lperl'); + my $ldopts = ldopts(); + if ($^O eq 'openbsd' && $Config{useshrplib} eq "false") { + # see github #22125 + # with OpenBSD, the packaged gcc (tries to) link + # against the system libperl, this will be fine once + # this perl gets installed, but that's not so good when + # testing against the uninstalled perl. + # This also matches how Makefile.SH links the perl executable + push @cmd, "$lib/libperl.a"; + $ldopts =~ s/ -lperl\b//; + } + else { + push(@cmd,"-L$lib",'-lperl'); + } local $SIG{__WARN__} = sub { warn $_[0] unless $_[0] =~ /No library found for .*perl/ }; push(@cmd, '-Zlinker', '/PM:VIO') # Otherwise puts a warning to STDOUT! if $^O eq 'os2' and $Config{ldflags} =~ /(? we +link against matches the perl we are building. [GH #22125] =back @@ -338,9 +339,10 @@ L section. =over 4 -=item XXX-some-platform +=item OpenBSD -XXX +When testing embedding, ensure we link against the correct static +libperl. [GH #22125] =back diff --git a/pod/perldiag.pod b/pod/perldiag.pod index 69e332ded180..842b3c0906a6 100644 --- a/pod/perldiag.pod +++ b/pod/perldiag.pod @@ -4020,6 +4020,11 @@ See L. by a missing delimiter on a string or pattern, because it eventually ended earlier on the current line. +=item Mismatch between expected and libperl %s + +(F) For an embedded perl, the perl headers and configuration you built +your binary against don't match the library you've linked with. + =item Mismatched brackets in template (F) A pack template could not be parsed because pairs of C<[...]> or diff --git a/proto.h b/proto.h index d648766b4898..f11f4ca79a8b 100644 --- a/proto.h +++ b/proto.h @@ -193,6 +193,11 @@ Perl_amagic_is_enabled(pTHX_ int method) __attribute__visibility__("hidden"); #define PERL_ARGS_ASSERT_AMAGIC_IS_ENABLED +PERL_CALLCONV void +Perl_api_version_assert(size_t interp_size, void *v_my_perl, const char *api_version); +#define PERL_ARGS_ASSERT_API_VERSION_ASSERT \ + assert(api_version) + PERL_CALLCONV SSize_t Perl_apply(pTHX_ I32 type, SV **mark, SV **sp) __attribute__visibility__("hidden"); diff --git a/util.c b/util.c index 069ec59c1747..30e5596d29c4 100644 --- a/util.c +++ b/util.c @@ -5737,6 +5737,52 @@ S_xs_version_bootcheck(pTHX_ SSize_t items, SSize_t ax, const char *xs_p, } } +/* +=for apidoc api_version_assert + +Used by the PERL_API_VERSION_CHECK macro to compare the perl the +object was built with and the perl that C was built with. + +This can be used to ensure that these match and produces a more +diagnosable than random crashes and mis-behaviour. + +=cut +*/ + +void +Perl_api_version_assert(size_t interp_size, void *v_my_perl, + const char *api_version) { + dTHX; + + PERL_ARGS_ASSERT_API_VERSION_ASSERT; + + if (interp_size != sizeof(PerlInterpreter)) { + /* detects various types of configuration mismatches */ + /* diag_listed_as: Mismatch between expected and libperl %s */ + Perl_croak(aTHX_ + "Mismatch between expected and libperl interpreter structure size %zd vs %zd", + interp_size, sizeof(PerlInterpreter)); + } + if ( +#ifdef MULTIPLICITY + v_my_perl != my_perl +#else + v_my_perl != NULL +#endif + ) { + /* detect threads vs non-threads mismatch */ + /* diag_listed_as: Mismatch between expected and libperl %s */ + Perl_croak(aTHX_ + "Mismatch between expected and libperl interpreter pointer"); + } + if (strNE(api_version, PERL_API_VERSION_STRING)) { + /* diag_listed_as: Mismatch between expected and libperl %s */ + Perl_croak(aTHX_ + "Mismatch between expected and libperl API versions %s vs %s", + api_version, PERL_API_VERSION_STRING); + } +} + PERL_STATIC_INLINE bool S_gv_has_usable_name(pTHX_ GV *gv) {