4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-03-01 04:25:27 +08:00
newlib-cygwin/winsup/cygwin/gentls_offsets
Corinna Vinschen 8f66bc28ae Cygwin: fix new sigfe.o generation in optimized case
Commit 0597c84b9bdb ("Cygwin: revamp TLS offsets computation")
introduced a really weird problem when building Cygwin with
optimization.

First of all, the tlsoffsets file is broken with -O2.  This
can easily be fixed by running the compiler with -O0 when called
from the gentls_offsets script.

But it gets worse:

When creating sigfe.o with optimization, the generated machine code
uses incorrect offsets: For some reason the assembler codes using
_cygtls.stackptr as offset value are assembled into machine code
using _cygtls.pstackptr as offsets.

And as if that isn't already absurd enough, renaming _cygtls.pstackptr
to, say, _cygtls.blurb, fixes the assembled machine code expressions;
they use the value of _cygtls.stackptr again.

So I changed gentls_offsets and gendef to use _cygtls.foo_p rather
than _cygtls.pfoo and that fixes the assembled code in the optimized
case.

No, I can't explain that.  There's no system in that behaviour.
It looks absolutely crazy.

Fixes: 0597c84b9bdb ("Cygwin: revamp TLS offsets computation")
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2022-05-13 21:22:44 +02:00

84 lines
2.5 KiB
Bash
Executable File

#!/usr/bin/env bash
#set -x
input_file=$1
output_file=$2
# Preprocess cygtls.h and filter out only the member lines from
# class _cygtls to generate an input file for the cross compiler
# to generate the member offsets for tlsoffsets-$(target_cpu).h.
${CXXCOMPILE} -E -P "${input_file}" 2> /dev/null | \
gawk '
BEGIN {
# marker is used to split out the member lines from class _cygtls
marker=0;
# Prepare the input file for the subsequent compiler run.
# Prepend value of __CYGTLS_PADSIZE__ so we can compute the offsets
# up and down at the same time
print "#include \"winsup.h\"";
print "#include \"cygtls.h\"";
print "extern \"C\" const uint32_t __CYGTLS__start_offset = __CYGTLS_PADSIZE__;";
}
/^class _cygtls$/ {
# Ok, bump marker, next we are expecting a "public:" line
marker=1;
}
/^public:/ {
# We are only interested in the lines between the first (marker == 2)
# and the second (marker == 3) "public:" line in class _cygtls. These
# are where the members are defined.
if (marker > 0) ++marker;
if (marker > 2) exit;
}
{
if (marker == 2 && $1 != "public:") {
# Filter out function names
$0 = gensub (/\(\*(\w+)\)\s*\([^\)]*\)/, "\\1", "g");
# Filter out leading asterisk
$NF = gensub (/^\**(\w+)/, "\\1", "g", $NF);
# Filter out trailing array expression
$NF = gensub (/(\w+)\s*\[[^\]]*\]/, "\\1", "g", $NF);
$NF = gensub (/(\w+);/, "\\1", "g", $NF);
print "extern \"C\" const uint32_t __CYGTLS__" $NF " = offsetof (class _cygtls, " $NF ");";
}
}
' | \
# Now run the compiler to generate an assembler file.
${CXXCOMPILE} -x c++ -g0 -O0 -S - -o - | \
# The assembler file consists of lines like these:
#
# __CYGTLS__foo
# .long 42
# .globl __CYGTLS__foo
# .align 4
#
# From this info, generate the tlsoffsets file.
gawk '\
BEGIN {
varname=""
start_offset = 0
}
/^__CYGTLS__/ {
varname = gensub (/__CYGTLS__(\w+):/, "\\1", "g");
}
/\s*\.space\s*4/ {
if (length (varname) > 0) {
printf (".equ _cygtls.%s, %d\n", varname, -start_offset);
printf (".equ _cygtls.%s_p, 0\n", varname);
varname = "";
}
}
/\s*\.long\s+/ {
if (length (varname) > 0) {
if (varname == "start_offset") {
start_offset = $2;
printf (".equ _cygtls.%s, -%u\n", varname, start_offset);
} else {
value = $2;
printf (".equ _cygtls.%s, %d\n", varname, value - start_offset);
printf (".equ _cygtls.%s_p, %d\n", varname, value);
}
varname = "";
}
}
' > "${output_file}"