perl: SIGSEGV on start if LC_ALL is unset
Maintainer: Esaaprilia Salsabila Environment: ARMv7 Processor rev 4 (v7l), custom OpenWRT fw
Description:
perlalways crashes on startup after upgrade
GDB output:
Reading symbols from ./build_dir/target-arm_cortex-a15+neon-vfpv4_musl_eabi/perl/perl-5.40.0/perl...
0xb6fe69c8 in _dlstart () from /home/egorenar/Repositories/openwrt-rel/scripts/../staging_dir/target-arm_cortex-a15+neon-vfpv4_musl_eabi/root-alpine/lib/ld-musl-armhf.so.1
=> 0xb6fe69c8 <_dlstart+0>: e3a0b000 mov r11, #0
(gdb) r
Starting program: /home/egorenar/Repositories/openwrt-rel/build_dir/target-arm_cortex-a15+neon-vfpv4_musl_eabi/perl/perl-5.40.0/perl
Program received signal SIGSEGV, Segmentation fault.
0xb6fd8d18 in strlen (s=<optimized out>) at src/string/strlen.c:17
17 for (w = (const void *)s; !HASZERO(*w); w++);
0xb6fd8d0c <strlen+52>: e308e080 movw lr, #32896 @ 0x8080
0xb6fd8d10 <strlen+56>: e34f4efe movt r4, #65278 @ 0xfefe
0xb6fd8d14 <strlen+60>: e348e080 movt lr, #32896 @ 0x8080
=> 0xb6fd8d18 <strlen+64>: e593c000 ldr r12, [r3]
0xb6fd8d1c <strlen+68>: e1a02003 mov r2, r3
0xb6fd8d20 <strlen+72>: e2833004 add r3, r3, #4
0xb6fd8d24 <strlen+76>: e08c1004 add r1, r12, r4
0xb6fd8d28 <strlen+80>: e1c1100c bic r1, r1, r12
0xb6fd8d2c <strlen+84>: e111000e tst r1, lr
0xb6fd8d30 <strlen+88>: 0afffff8 beq 0xb6fd8d18 <strlen+64>
0xb6fd8d34 <strlen+92>: e1a03002 mov r3, r2
(gdb) bt
#0 0xb6fd8d18 in strlen (s=<optimized out>) at src/string/strlen.c:17
#1 0xb6e3265c in Perl_sv_vcatpvfn_flags ()
from /home/egorenar/Repositories/openwrt-rel/scripts/../staging_dir/target-arm_cortex-a15+neon-vfpv4_musl_eabi/root-alpine/usr/lib/perl5/5.40/CORE/libperl.so
#2 0xb6e3265c in Perl_sv_vcatpvfn_flags ()
from /home/egorenar/Repositories/openwrt-rel/scripts/../staging_dir/target-arm_cortex-a15+neon-vfpv4_musl_eabi/root-alpine/usr/lib/perl5/5.40/CORE/libperl.so
#3 0xb6e3265c in Perl_sv_vcatpvfn_flags ()
from /home/egorenar/Repositories/openwrt-rel/scripts/../staging_dir/target-arm_cortex-a15+neon-vfpv4_musl_eabi/root-alpine/usr/lib/perl5/5.40/CORE/libperl.so
#4 0xb6e3265c in Perl_sv_vcatpvfn_flags ()
from /home/egorenar/Repositories/openwrt-rel/scripts/../staging_dir/target-arm_cortex-a15+neon-vfpv4_musl_eabi/root-alpine/usr/lib/perl5/5.40/CORE/libperl.so
#5 0xb6e3265c in Perl_sv_vcatpvfn_flags ()
from /home/egorenar/Repositories/openwrt-rel/scripts/../staging_dir/target-arm_cortex-a15+neon-vfpv4_musl_eabi/root-alpine/usr/lib/perl5/5.40/CORE/libperl.so
#6 0xb6e3265c in Perl_sv_vcatpvfn_flags ()
from /home/egorenar/Repositories/openwrt-rel/scripts/../staging_dir/target-arm_cortex-a15+neon-vfpv4_musl_eabi/root-alpine/usr/lib/perl5/5.40/CORE/libperl.so
#7 0xb6e3265c in Perl_sv_vcatpvfn_flags ()
from /home/egorenar/Repositories/openwrt-rel/scripts/../staging_dir/target-arm_cortex-a15+neon-vfpv4_musl_eabi/root-alpine/usr/lib/perl5/5.40/CORE/libperl.so
#8 0xb6e3265c in Perl_sv_vcatpvfn_flags ()
from /home/egorenar/Repositories/openwrt-rel/scripts/../staging_dir/target-arm_cortex-a15+neon-vfpv4_musl_eabi/root-alpine/usr/lib/perl5/5.40/CORE/libperl.so
#9 0xb6e3265c in Perl_sv_vcatpvfn_flags ()
from /home/egorenar/Repositories/openwrt-rel/scripts/../staging_dir/target-arm_cortex-a15+neon-vfpv4_musl_eabi/root-alpine/usr/lib/perl5/5.40/CORE/libperl.so
#10 0xb6e3265c in Perl_sv_vcatpvfn_flags ()
gdb> info reg # r3 is from....
gdb> info proc mappings # same offsets look like excess recursion -> stack depletion -> ??? overflow to trap page ???
also set breakpoint at Perl_sv_vcatfpn_flags () and run it again. might need -g -O0 build if too much sense is optimized away.
info proc mappings
thanks for the hints!
Program received signal SIGSEGV, Segmentation fault.
0xb6fd8d18 in strlen (s=<optimized out>) at src/string/strlen.c:17
17 for (w = (const void *)s; !HASZERO(*w); w++);
0xb6fd8d0c <strlen+52>: e308e080 movw lr, #32896 @ 0x8080
0xb6fd8d10 <strlen+56>: e34f4efe movt r4, #65278 @ 0xfefe
0xb6fd8d14 <strlen+60>: e348e080 movt lr, #32896 @ 0x8080
=> 0xb6fd8d18 <strlen+64>: e593c000 ldr r12, [r3]
0xb6fd8d1c <strlen+68>: e1a02003 mov r2, r3
0xb6fd8d20 <strlen+72>: e2833004 add r3, r3, #4
0xb6fd8d24 <strlen+76>: e08c1004 add r1, r12, r4
0xb6fd8d28 <strlen+80>: e1c1100c bic r1, r1, r12
0xb6fd8d2c <strlen+84>: e111000e tst r1, lr
0xb6fd8d30 <strlen+88>: 0afffff8 beq 0xb6fd8d18 <strlen+64>
0xb6fd8d34 <strlen+92>: e1a03002 mov r3, r2
(gdb) info reg
r0 0x5c8 0x5c8
r1 0xbefffbe0 0xbefffbe0
r2 0x5c8 0x5c8
r3 0x5c8 0x5c8
r4 0xfefefeff 0xfefefeff
r5 0x0 0x0
r6 0xb6e87e56 0xb6e87e56
r7 0xb6e87e5d 0xb6e87e5d
r8 0xffffffff 0xffffffff
r9 0x73 0x73
r10 0x0 0x0
r11 0x6666666 0x6666666
r12 0xb6f71c98 0xb6f71c98
sp 0xbefffa28 0xbefffa28
lr 0x80808080 0x80808080
pc 0xb6fd8d18 0xb6fd8d18 <strlen+64>
cpsr 0x60000010 0x60000010
fpscr 0x10 0x10
tpidruro <unavailable>
(gdb) info proc mappings
process 17207
Mapped address spaces:
Start Addr End Addr Size Offset Perms objfile
0x10000 0x11000 0x1000 0x0 r-xp /usr/bin/perl5.40.0
0x11000 0x12000 0x1000 0x0 r--p /usr/bin/perl5.40.0
0x12000 0x13000 0x1000 0x0 rw-p [heap]
0x13000 0x14000 0x1000 0x0 ---p [heap]
0x14000 0x15000 0x1000 0x0 rw-p [heap]
0xb6c87000 0xb6ca3000 0x1c000 0x0 rw-p
0xb6ca3000 0xb6cae000 0xb000 0x0 r-xp /lib/libgcc_s.so.1
0xb6cae000 0xb6caf000 0x1000 0xa000 r--p /lib/libgcc_s.so.1
0xb6caf000 0xb6cb0000 0x1000 0xb000 rw-p /lib/libgcc_s.so.1
0xb6cb0000 0xb6f69000 0x2b9000 0x0 r-xp /usr/lib/perl5/5.40/CORE/libperl.so
0xb6f69000 0xb6f72000 0x9000 0x2b9000 r--p /usr/lib/perl5/5.40/CORE/libperl.so
0xb6f72000 0xb6f73000 0x1000 0x2c2000 rw-p /usr/lib/perl5/5.40/CORE/libperl.so
0xb6f73000 0xb6f7a000 0x7000 0x0 rw-p
0xb6f7a000 0xb6f7b000 0x1000 0x0 r-xp [sigpage]
0xb6f7b000 0xb6f7c000 0x1000 0x0 r--p [vvar]
0xb6f7c000 0xb6f7d000 0x1000 0x0 r-xp [vdso]
0xb6f7d000 0xb6ffc000 0x7f000 0x0 r-xp /lib/libc.so
0xb6ffc000 0xb6ffe000 0x2000 0x7f000 rw-p /lib/libc.so
0xb6ffe000 0xb7000000 0x2000 0x0 rw-p
0xbefdf000 0xbf000000 0x21000 0x0 rw-p [stack]
0xffff0000 0xffff1000 0x1000 0x0 r-xp [vectors]
(gdb)
I will try to obtain more information like suggested.
The r3 does not look like a pointer totally....
0xb6ffc000 0xb6ffe000 0x2000 0x7f000 rw-p /lib/libc.so
Is in libc.
More excersises:
Confirm that perl function in backtrace is in libperl mapping
Set breakpoint gdb> b Perl_sv_vcatpvfn_flags then once it is hit continue and check registers -> what is in R3, but should be only SP changing until runs out of stack.
More useful backtrace with -g -O0:
Program received signal SIGSEGV, Segmentation fault.
0xb6fd8d18 in strlen (s=<optimized out>, s@entry=0x5c8 <error: Cannot access memory at address 0x5c8>) at src/string/strlen.c:17
17 for (w = (const void *)s; !HASZERO(*w); w++);
0xb6fd8d0c <strlen+52>: e308e080 movw lr, #32896 @ 0x8080
0xb6fd8d10 <strlen+56>: e34f4efe movt r4, #65278 @ 0xfefe
0xb6fd8d14 <strlen+60>: e348e080 movt lr, #32896 @ 0x8080
=> 0xb6fd8d18 <strlen+64>: e593c000 ldr r12, [r3]
0xb6fd8d1c <strlen+68>: e1a02003 mov r2, r3
0xb6fd8d20 <strlen+72>: e2833004 add r3, r3, #4
0xb6fd8d24 <strlen+76>: e08c1004 add r1, r12, r4
0xb6fd8d28 <strlen+80>: e1c1100c bic r1, r1, r12
0xb6fd8d2c <strlen+84>: e111000e tst r1, lr
0xb6fd8d30 <strlen+88>: 0afffff8 beq 0xb6fd8d18 <strlen+64>
0xb6fd8d34 <strlen+92>: e1a03002 mov r3, r2
(gdb) bt
#0 0xb6fd8d18 in strlen (s=<optimized out>, s@entry=0x5c8 <error: Cannot access memory at address 0x5c8>) at src/string/strlen.c:17
#1 0xb6e3265c in Perl_sv_vcatpvfn_flags (my_perl=my_perl@entry=0xb6ca1020, sv=sv@entry=0xb6c9ea40, pat=pat@entry=0xb6e87e48 "%s: %: panic: %s%s%s\n", patlen=patlen@entry=0x15, args=<optimized out>,
args@entry=0xbefffbe0, svargs=<optimized out>, svargs@entry=0xb6e76764 <Perl_vmess+84>, sv_count=<optimized out>, sv_count@entry=0xbefffbe0, maybe_tainted=<optimized out>,
maybe_tainted@entry=0x0, flags=<optimized out>, flags@entry=0x0) at sv.c:12669
#2 0xb6e4984c in Perl_sv_vsetpvfn (my_perl=my_perl@entry=0xb6ca1020, sv=sv@entry=0xb6c9ea40, pat=pat@entry=0xb6e87e48 "%s: %: panic: %s%s%s\n", patlen=0x15, args=args@entry=0xbefffbe0,
svargs=svargs@entry=0x0, sv_count=sv_count@entry=0x0, maybe_tainted=maybe_tainted@entry=0x0) at sv.c:11295
#3 0xb6e76764 in Perl_vmess (my_perl=my_perl@entry=0xb6ca1020, pat=0xb6e87e48 "%s: %: panic: %s%s%s\n", pat@entry=0xb6ca1020 "`\300\377\266", args=0xbefffbe0, args@entry=0xbefffbc0) at util.c:1684
#4 0xb6e75ee0 in Perl_vcroak (my_perl=my_perl@entry=0xb6ca1020, pat=pat@entry=0xb6ca1020 "`\300\377\266", args=args@entry=0xbefffbc0) at util.c:1899
#5 0xb6e76af8 in Perl_croak (my_perl=my_perl@entry=0xb6ca1020, pat=0xb6e87e48 "%s: %: panic: %s%s%s\n") at util.c:1952
#6 0xb6d3e38c in Perl_locale_panic (msg=0xb6ffffb0 "'C.UTF-8;C;C;C;C;C' needs an '=' to split name=value\n", immediate_caller_line=immediate_caller_line@entry=0x5c8,
higher_caller_file=<optimized out>, higher_caller_line=0x1001, higher_caller_line@entry=0xb6d40b98) at locale.c:1113
#7 0xb6d40a34 in S_parse_LC_ALL_string (my_perl=0xb6e880c8, my_perl@entry=0xb6ca1020, string=string@entry=0xb6fffcf0 "C.UTF-8;C;C;C;C;C", output=0xb6ffff98, output@entry=0xbefffc84,
always_use_full_array=0x20, always_use_full_array@entry=0x1, panic_on_error=0x1, caller_line=0x1001, override=override_if_ignored) at locale.c:1480
#8 0xb6d40b98 in S_new_LC_ALL (my_perl=my_perl@entry=0xb6ca1020, lc_all=lc_all@entry=0xb6fffcf0 "C.UTF-8;C;C;C;C;C", force=force@entry=0x1) at locale.c:4090
#9 0xb6d439b8 in S_give_perl_locale_control (caller_line=0x23fd, lc_all_string=0xb6fffcf0 "C.UTF-8;C;C;C;C;C", my_perl=0xb6ca1020) at locale.c:8575
#10 Perl_init_i18nl10n (my_perl=0xb6ca1020, printwarn=printwarn@entry=0x1) at locale.c:9213
#11 0xb6cfc95c in perl_construct (my_perl=<optimized out>) at perl.c:464
#12 0x0001091c in main (argc=<optimized out>, argv=<optimized out>, env=<optimized out>) at perlmain.c:102
(gdb)
Try to set LC_ALL=C and see if backtrace is same or it goes through. I am no expert in perl internals, that comes just from superfluus look at the text messages.
LC_ALL
Yes, i noticed that too, Perl seems to crash while parsing LC_ALL :rofl:
The problem disappears with export LC_ALL=C or export LC_ALL=en_US.UTF-8.
I think something goes wrong in locale.c (generated file ???) of Perl
/* diag_listed_as: panic: %s */
Perl_croak(aTHX_ "%s: %" LINE_Tf ": panic: %s%s%s\n",
__FILE__, immediate_caller_line,
msg, errno_text, called_by);
and from handy.h
#define LINE_Tf U32uf
It's a typical format string error. immediate_caller_line (0x5c8 in backtrace) is interpreted as %s.
I've never seen a C format string %U32uf :scream:
Look what i found while re-compiling Perl:
locale.c: In function 'Perl_locale_panic':
locale.c:1089:37: warning: unknown conversion type character '\x0a' in format [-Wformat=]
1089 | called_by = Perl_form(aTHX_ "\nCalled by %s: %" LINE_Tf "\n",
| ^~~~~~~~~~~~~~~~~~~
locale.c:1089:66: note: format string is defined here
1089 | called_by = Perl_form(aTHX_ "\nCalled by %s: %" LINE_Tf "\n",
| ^~
locale.c:1089:37: warning: too many arguments for format [-Wformat-extra-args]
1089 | called_by = Perl_form(aTHX_ "\nCalled by %s: %" LINE_Tf "\n",
| ^~~~~~~~~~~~~~~~~~~
locale.c:1113:22: warning: unknown conversion type character ':' in format [-Wformat=]
1113 | Perl_croak(aTHX_ "%s: %" LINE_Tf ": panic: %s%s%s\n",
| ^~~~~~~
locale.c:1113:39: note: format string is defined here
1113 | Perl_croak(aTHX_ "%s: %" LINE_Tf ": panic: %s%s%s\n",
| ^
locale.c:1113:22: warning: format '%s' expects argument of type 'char *', but argument 4 has type 'line_t' {aka 'long unsigned int'} [-Wformat=]
1113 | Perl_croak(aTHX_ "%s: %" LINE_Tf ": panic: %s%s%s\n",
| ^~~~~~~
1114 | __FILE__, immediate_caller_line,
| ~~~~~~~~~~~~~~~~~~~~~
| |
| line_t {aka long unsigned int}
locale.c:1113:49: note: format string is defined here
1113 | Perl_croak(aTHX_ "%s: %" LINE_Tf ": panic: %s%s%s\n",
| ~^
| |
| char *
| %ld
locale.c:1113:22: warning: too many arguments for format [-Wformat-extra-args]
1113 | Perl_croak(aTHX_ "%s: %" LINE_Tf ": panic: %s%s%s\n",
| ^~~~~~~
In file included from locale.c:383:
locale.c: In function 'S_bool_setlocale_2008_i':
locale.c:2571:39: warning: unknown conversion type character ')' in format [-Wformat=]
2571 | locale_panic_(Perl_form(aTHX_ "(called from %" LINE_Tf "):"
| ^~~~~~~~~~~~~~~~
perl.h:7525:56: note: in definition of macro 'locale_panic_via_'
7525 | #define locale_panic_via_(m, f, l) Perl_locale_panic((m), __LINE__, f, l)
| ^
locale.c:2571:9: note: in expansion of macro 'locale_panic_'
2571 | locale_panic_(Perl_form(aTHX_ "(called from %" LINE_Tf "):"
| ^~~~~~~~~~~~~
locale.c:2571:54: note: format string is defined here
2571 | locale_panic_(Perl_form(aTHX_ "(called from %" LINE_Tf "):"
| ^
locale.c:2571:39: warning: too many arguments for format [-Wformat-extra-args]
2571 | locale_panic_(Perl_form(aTHX_ "(called from %" LINE_Tf "):"
| ^~~~~~~~~~~~~~~~
perl.h:7525:56: note: in definition of macro 'locale_panic_via_'
7525 | #define locale_panic_via_(m, f, l) Perl_locale_panic((m), __LINE__, f, l)
| ^
locale.c:2571:9: note: in expansion of macro 'locale_panic_'
2571 | locale_panic_(Perl_form(aTHX_ "(called from %" LINE_Tf "):"
| ^~~~~~~~~~~~~
locale.c: In function 'S_setlocale_failure_panic_via_i':
locale.c:3379:56: warning: spurious trailing '%' in format [-Wformat=]
3379 | proxy_text = Perl_form(aTHX_ "\nCalled via %s: %" LINE_Tf,
| ^
locale.c:3379:38: warning: too many arguments for format [-Wformat-extra-args]
3379 | proxy_text = Perl_form(aTHX_ "\nCalled via %s: %" LINE_Tf,
| ^~~~~~~~~~~~~~~~~~~~
locale.c:3386:58: warning: spurious trailing '%' in format [-Wformat=]
3386 | proxy_text = Perl_form(aTHX_ "%s\nCalled via %s: %" LINE_Tf,
| ^
locale.c:3386:38: warning: too many arguments for format [-Wformat-extra-args]
3386 | proxy_text = Perl_form(aTHX_ "%s\nCalled via %s: %" LINE_Tf,
| ^~~~~~~~~~~~~~~~~~~~~~
This is also interesting: https://github.com/Perl/perl5/pull/21956
Okay, U32uf seems to be a Perl-specific format string specifier: https://perldoc.perl.org/5.37.3/perl5372delta#Internal-Changes.
The above warnings can be ignored then.
To me it seems that Perl_sv_vcatpvfn_flags doesn't support the format string specifier U32uf, and therefore, just skips it and goes straight for the next specifier which is %s, and attempts to interpret a line number as a string pointer :stuck_out_tongue_winking_eye:
According to Perl's devs, OpenWrt's Perl package configuration is broken :disappointed:
config.sh generation is outdated in OpenWrt and needs to be fixed for 5.40.
The missing format string symbols have been a problem since perl 5.38, but apparently nobody noticed then.
Helps to tag maintainer @pprindeville and recent commiter @esaaprillia
@esaaprillia
the perl package should be updated. I see many are outdated. but at that time I was too lazy to update everything. let the perl package maintainer update it
It might be useful to check how buildroot builds Perl: https://github.com/buildroot/buildroot/blob/3ebc7c69d56430c34eba4c869d1d4fe4d1e8de55/package/perl/perl.mk buildroot doesn't use custom config files. i wonder why OpenWrt needs all these custom configs. This will be a constant pain to keep in sync with upstream.
Okay, i dropped outdated symbols from base.config and added new formats to architecture.config
and got this error:
$ perl
locale.c: 1480: panic: 'C.UTF-8;C;C;C;C;C' needs an '=' to split name=value
; errno=0
Called by locale.c: 4097
The panic is thrown by perl's S_parse_LC_ALL_string().
{ /* Get the category part when each component is the
* 'category=locale' form */
category_end = strchr(s, '=');
/* The '=' terminates the category name. If no '=', is improper
* form */
if (! category_end) {
error = no_equals;
goto failure;
}
...
switch (error) {
case incomplete:
msg = "doesn't list every locale category";
display_start = string;
break;
case no_equals:
msg = "needs an '=' to split name=value";
break;
Any idea where C.UTF-8;C;C;C;C;C comes from ?
Okay, found out that d_perl_lc_all_uses_name_value_pairs='define' is responsible for the above panic which was added in commit https://github.com/openwrt/packages/commit/c5b97d4d967fde1e090b90b547500abaa40cc925.
Okay, found out that
d_perl_lc_all_uses_name_value_pairs='define'is responsible for the above panic which was added in commit c5b97d4.
do you succeed in building perl if you change define to undef?
Okay, found out that
d_perl_lc_all_uses_name_value_pairs='define'is responsible for the above panic which was added in commit c5b97d4.do you succeed in building perl if you change define to undef?
Sadly, not yet :( Tried different combinations. Need to look deeper into it.
This might give the hint why:
d_perl_lc_all_category_positions_init (disparate_lc_all.U):
This symbol, if defined, indicates that $lc_all_category_positions_init
is valid
d_perl_lc_all_separator (disparate_lc_all.U):
This symbol, if defined, indicates that $perl_lc_all_separator is valid
d_perl_lc_all_uses_name_value_pairs (disparate_lc_all.U):
This symbol, if defined, indicates that the string returned by
setlocale(LC_ALL, NULL) uses 'name=value;' pairs to indicate what each
category's locale is when they aren't all set to the same locale.
When not defined, the platform uses positional notation.
Okay, this seems to help:
modified lang/perl/files/base.config
@@ -365,9 +365,9 @@ d_open3='define'
d_openat='define'
d_pathconf='define'
d_pause='define'
-d_perl_lc_all_category_positions_init='undef'
-d_perl_lc_all_separator='undef'
-d_perl_lc_all_uses_name_value_pairs='define'
+d_perl_lc_all_category_positions_init='define'
+d_perl_lc_all_separator='define'
+d_perl_lc_all_uses_name_value_pairs='undef'
d_perl_otherlibdirs='undef'
d_phostname='undef'
d_pipe='define'
@@ -842,6 +842,8 @@ passcat='cat /etc/passwd'
path_sep=':'
perl=''
perl5=''
+perl_lc_all_category_positions_init='{ 0, 1, 5, 2, 3, 4 }'
+perl_lc_all_separator='";"'
perl_patchlevel=''
perl_static_inline='static __inline__'
perlpath='/usr/bin/perl'
I made a branch for my Perl fixes: https://github.com/egorenar/openwrt-packages/tree/perl
@egorenar
if the problem is solved please update perl. thanks
@egorenar Does your branch is already compile-able?, getting the following when compiling with gcc 14 targeting x86_64 glibc :
In file included from /home/user/works/openwrt/staging_dir/toolchain-x86_64_gcc-14.1.0_glibc/include/features.h:503,
from /home/user/works/openwrt/staging_dir/toolchain-x86_64_gcc-14.1.0_glibc/include/sys/types.h:25,
from perl.h:1117,
from locale.c:383:
locale.c: In function 'Perl_init_i18nl10n':
perl.h:4280:36: error: negative width in bit-field '__error_if_negative'
4280 | # define STATIC_ASSERT_DECL(COND) static_assert(COND, #COND)
| ^~~~~~~~~~~~~
perl.h:4296:52: note: in expansion of macro 'STATIC_ASSERT_DECL'
4296 | #define STATIC_ASSERT_STMT(COND) STMT_START { STATIC_ASSERT_DECL(COND); } STMT_END
| ^~~~~~~~~~~~~~~~~~
locale.c:8813:9: note: in expansion of macro 'STATIC_ASSERT_STMT'
8813 | STATIC_ASSERT_STMT( C_ARRAY_LENGTH(lc_all_category_positions)
| ^~~~~~~~~~~~~~~~~~
make[3]: *** [Makefile:266: locale.o] Error 1
@egorenar Does your branch is already compile-able?, getting the following when compiling with gcc 14 targeting x86_64 glibc :
In file included from /home/user/works/openwrt/staging_dir/toolchain-x86_64_gcc-14.1.0_glibc/include/features.h:503, from /home/user/works/openwrt/staging_dir/toolchain-x86_64_gcc-14.1.0_glibc/include/sys/types.h:25, from perl.h:1117, from locale.c:383: locale.c: In function 'Perl_init_i18nl10n': perl.h:4280:36: error: negative width in bit-field '__error_if_negative' 4280 | # define STATIC_ASSERT_DECL(COND) static_assert(COND, #COND) | ^~~~~~~~~~~~~ perl.h:4296:52: note: in expansion of macro 'STATIC_ASSERT_DECL' 4296 | #define STATIC_ASSERT_STMT(COND) STMT_START { STATIC_ASSERT_DECL(COND); } STMT_END | ^~~~~~~~~~~~~~~~~~ locale.c:8813:9: note: in expansion of macro 'STATIC_ASSERT_STMT' 8813 | STATIC_ASSERT_STMT( C_ARRAY_LENGTH(lc_all_category_positions) | ^~~~~~~~~~~~~~~~~~ make[3]: *** [Makefile:266: locale.o] Error 1
Yes, but i tested only with musl.
I think perl_lc_all_category_positions_init='{ 0, 1, 5, 2, 3, 4 }' should be different for glibc.
@vortexilation Try this for perl_lc_all_category_positions_init
https://github.com/Perl/perl5/blob/b786e5e6e5e961082d2f48dac2a1f3ab69339b14/perl.h#L1239
@egorenar Thanks, it compile-able now, but haven't tested functionalities wise.
Then you will also use perl_lc_all_category_positions_init for glibc as for musl?, if not how you overcome glibc and musl differences for base.config ?.
Then you will also use perl_lc_all_category_positions_init for glibc as for musl?, if not how you overcome glibc and musl differences for base.config ?.
We have to put them into libc.config i think. There are conditionals for musl and glibc.
musl
LC_ALL categories:
#define LC_CTYPE 0
#define LC_NUMERIC 1
#define LC_TIME 2
#define LC_COLLATE 3
#define LC_MONETARY 4
#define LC_MESSAGES 5
Perl's LC_ positions (locale_table.h):
#define LC_CTYPE 0
#define LC_NUMERIC 1
#define LC_COLLATE 2
#define LC_TIME 3
#define LC_MESSAGES 4
#define LC_MONETARY 5
perl_lc_all_category_positions_init maps musl category positions to Perl's category positions.
perl_lc_all_category_positions_init='{ 0, 1, 3, 2, 5, 4 }'
glibc
LC_ALL categories:
#define LC_CTYPE 0
#define LC_NUMERIC 1
#define LC_TIME 2
#define LC_COLLATE 3
#define LC_MONETARY 4
#define LC_MESSAGES 5
#define LC_PAPER 7
#define LC_NAME 8
#define LC_ADDRESS 9
#define LC_TELEPHONE 10
#define LC_MEASUREMENT 11
#define LC_IDENTIFICATION 12
Perl's LC_ positions (locale_table.h):
#define LC_CTYPE 0
#define LC_NUMERIC 1
#define LC_COLLATE 2
#define LC_TIME 3
#define LC_MESSAGES 4
#define LC_MONETARY 5
#define LC_ADDRESS 6
#define LC_IDENTIFICATION 7
#define LC_MEASUREMENT 8
#define LC_PAPER 9
#define LC_TELEPHONE 10
#define LC_NAME 11
perl_lc_all_category_positions_init maps glibc category positions to Perl's category positions.
perl_lc_all_category_positions_init='{ 0, 1, 3, 2, 5, 4, -1, 9, 11, 6, 10, 8, 7 }'
Still unsure about mapping, need to double check everything and then test it.
A simple program to obtain all LC_* values:
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
int main()
{
#ifdef LC_CTYPE
fprintf(stdout, "LC_CTYPE: %d\n", LC_CTYPE);
#endif
#ifdef LC_NUMERIC
fprintf(stdout, "LC_NUMERIC: %d\n", LC_NUMERIC);
#endif
#ifdef LC_TIME
fprintf(stdout, "LC_TIME: %d\n", LC_TIME);
#endif
#ifdef LC_COLLATE
fprintf(stdout, "LC_COLLATE: %d\n", LC_COLLATE);
#endif
#ifdef LC_MONETARY
fprintf(stdout, "LC_MONETARY: %d\n", LC_MONETARY);
#endif
#ifdef LC_MESSAGES
fprintf(stdout, "LC_MESSAGES: %d\n", LC_MESSAGES);
#endif
#ifdef LC_PAPER
fprintf(stdout, "LC_PAPER: %d\n", LC_PAPER);
#endif
#ifdef LC_NAME
fprintf(stdout, "LC_NAME: %d\n", LC_NAME);
#endif
#ifdef LC_ADDRESS
fprintf(stdout, "LC_ADDRESS: %d\n", LC_ADDRESS);
#endif
#ifdef LC_TELEPHONE
fprintf(stdout, "LC_TELEPHONE: %d\n", LC_TELEPHONE);
#endif
#ifdef LC_MEASUREMENT
fprintf(stdout, "LC_MEASUREMENT: %d\n", LC_MEASUREMENT);
#endif
#ifdef LC_IDENTIFICATION
fprintf(stdout, "LC_IDENTIFICATION: %d\n", LC_IDENTIFICATION);
#endif
#ifdef LC_SYNTAX
fprintf(stdout, "LC_SYNTAX: %d\n", LC_SYNTAX);
#endif
#ifdef LC_TOD
fprintf(stdout, "LC_TOD: %d\n", LC_TOD);
#endif
return 0;
}
I verified the above LC_* values on musl and glibc.