What is incomplete for /lib/libgcc_s.so-based C++ exception handling (where WITH_LLVM_LIBUNWIND= and /usr/local/lib/gcc*/libgcc_s.so are not used)

2018-10-17 Thread Mark Millard via freebsd-toolchain
[This summarizes other results without the code
and debugger evidence and such from my recent
explorations. It should be much easier to
follow than my exploration reports.]

Documents like DWARF5.pdf document the "row" vs. Location
information for Call Frame Information as (also used
for .eh_frame like materials for C++ exception handling):
(CFA: Cannonical Frame Address)

QUOTE ("Structure of Call Frame Information")
LOC CFA R0 R1...RN

L0

L1

...

LN
END QUOTE

Note that the CFA is conceptually one of the
registers in each row, even though it is not a
machine register but a way to calculate the
conceptual register's value from machine
registers.

The information for the machine registers are
typically based on the earlier CFA value (from
the same row!). Absent a correct CFA cell in
a row, most potential use of that row is likely
messed up.

One way CFA is found is by adding an offset to
the value of a machine register for the range
in question, Ln up to L(n+1) [or based on the
end of the overall range for the last Ln]. I
will use that for illustration because there
are examples of this in my testing.

/lib/libgcc_s.so.1 does not implement this
fully for some DW_CFA_* operations:

QUOTE (note the "every register" reference, so including CFA)
DW_CFA_remember_state

The DW_CFA_remember_state instruction takes no operands. The required action is 
to push the set of rules for every register onto an implicit stack.

DW_CFA_restore_state

The DW_CFA_restore_state instruction takes no operands. The required action is 
to pop the set of rules off the implicit stack and place them in the current 
row.
END QUOTE

In other words: push and pop a complete row,
not just machine registers information from
the row.

For example, the the "cfa_offset" for computing the CFA
value from from a register is not saved and restored.
Nor is which register the offset is based on. (This
can vary, though not in my examples.) In general the
CFA cell is not saved and restored, what ever its
contents.

So any compiler that produces code depending on
DW_CFA_remember_state and DW_CFA_restore_state
for .eh_frame like material ends up with C++
exception handling messed up when the
DW_CFA_restore_state should change the CFA to a 
non-default one (from the prior
DW_CFA_remember_state).

This prevents reliable use of throwing C++ exceptions
when building via the likes of devel/powerpc64-gcc
or lang/gcc8 ( when not using
-Wl,-rpath=-Wl,-rpath=/usr/local/lib/gcc8 so that
/lib/libgcc_s.so.1 ends up being used). One result
can be _Unwind_RaiseException looping looking at
the same frame over and over instead of progressing
to the next frame. For example, this happens via
cfa_offset 0 being used. devel/powerpc64-gcc -O2
code tends to get that.


Notes:

For powerpc64, clang++ tends to use another register
(%r31) with the old value (of %r1, the stack pointer)
instead of involving the
DW_CFA_remember_state/DW_CFA_restore_state pair
based on just %r1. (clang has other problems
relative to sue for buildworld buildkernel.)

Code generation styles matter for if the incomplete
coverage by /lib/libgcc_s.so will be visible or not.

At this stage, WITH_LLVM_LIBUNWIND= builds
targeting powerpc64 do not even compile/assemble
the relevant code, apparently both because of
darwin specific assembler code and FreeBSD's build
not using the C-preprocessor on the .S file as
required. (There could be more to getting it
working.)

I do not know about other architecture/compiler
(or toolchain) combinations that may not yet be
able to use WITH_LLVM_LIBUNWIND= . But I'd
expect a potentially similar status from some.

A range of modern /usr/local/lib/gcc*/libgcc_s.so
do implement DW_CFA_remember_state/DW_CFA_restore_state
operations and they are put to use. So using the likes
of -Wl,-rpath=/usr/local/lib/gcc8 works for g++8 C++
exception handling (but is problematical for buildworld
buildkernel).

I made a similar exploration of the issue in around
early 2016 and got basically the same results, not that
I remembered much. But I now have a small source code
example that shows the cfa_offset issue for the likes
of devel/powerpc64-gcc output.

The standard source for throw_exception in
/lib/libgcc_s.so produces the cfa_offset problem
when devel/powerpc64-gcc is used to buildworld.
This turns all thrown C++ exceptions in to
unbounded looping in _Unwind_RaiseException for
that kind of context.

===
Mark Millard
marklmi at yahoo.com
( dsl-only.net went
away in early 2018-Mar)

___
freebsd-toolchain@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-toolchain
To unsubscribe, send any mail to "freebsd-toolchain-unsubscr...@freebsd.org"


/lib/libgcc_s.so.1 mishandles eh_frame information that /usr/local/lib/gcc8/libgcc_s.so.1 handles (powerpc64 test context): a simple example program

2018-10-17 Thread Mark Millard via freebsd-toolchain
(I happen to be using head -r339076 and ports -r480180
vintage materials, not that I expect such narrow vintage
ties.)

I finally have a simple example of the
issue on powerpc64 . . .

The following simple C++ program shows
a significant difference for powerpc64
depending on which libgcc_s.so is used
(system's vs. gcc8's):

# more exception_test1.cpp 
#include 

// -O2 context used.

volatile unsigned int v = 1;

extern int f()
{
volatile unsigned char c = 'a';
v++; // Despite "volatile" the access to v in g
 // was otherwise optimized out and the
 // std::exception was not followed by
 // code for f(). So force g's use.
return c;
}

extern void g()
{
if (v) throw std::exception();
f(); // ends up inlined but the problem is demonstrated.
}

int main(void)
{
try {g();} // Used a separate function to avoid any potential
   // special handling of code in main. Call not
   // optimized out.
catch (std::exception& e) {}
return 0;
}


(gcc8 just happens to be the lang/gcc* that I have installed.
Similar points likely apply to gcc[?-8]. The same problem
can be demonstrated by devel/powerpc64-gcc use, which ends
up using /lib/libgcc_s.so.1 as well --but does not provide
the contrasting "it works" case.)

The only reason for the try/catch is to avoid the "it
works" case from doing:

# ./a.out
terminate called after throwing an instance of 'std::exception'
  what():  std::exception
Abort trap (core dumped)

Just calling g() is enough to have the problem with
/lib/libgcc_s.so.1 .

The program works fine for being built via:

# g++8 -Wl,-rpath=/usr/local/lib/gcc8 -g -O2 exception_test1.cpp
# ldd a.out
a.out:
libstdc++.so.6 => /usr/local/lib/gcc8/libstdc++.so.6 (0x81006e000)
libm.so.5 => /lib/libm.so.5 (0x8102c7000)
libgcc_s.so.1 => /usr/local/lib/gcc8/libgcc_s.so.1 (0x810307000)
libc.so.7 => /lib/libc.so.7 (0x81033)

But fails, stuck looping in _Unwind_RaiseException, for being built via:

# g++8 -g -O2 exception_test1.cpp
# ldd a.out
a.out:
libstdc++.so.6 => /usr/local/lib/gcc8/libstdc++.so.6 (0x81006e000)
libm.so.5 => /lib/libm.so.5 (0x8102c7000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x810307000)
libc.so.7 => /lib/libc.so.7 (0x81032d000)

The only difference (other than detailed addresses) is:

libgcc_s.so.1 => /usr/local/lib/gcc8/libgcc_s.so.1 (0x810307000)
vs.
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x810307000)

The dwarfdump -v -v -F reports match exactly for the two
builds of the program, as does the code for the function
g where the problem is observed.

What is different is that /lib/libgcc_s.so.1 misinterprets
the .eh_frame information (disagreeing with the dwarfdump
report and with /usr/local/lib/gcc8/libgcc_s.so.1 behavior).

# dwarfdump -v -v -F a.out | more

.eh_frame

fde:
<0><0x17a0:0x1840><>
   
0x17a0:  
 fde section offset 20 0x0014 cie offset for fde: 24 0x0018
 0 DW_CFA_nop
 1 DW_CFA_nop
 2 DW_CFA_nop
<1><0x1840:0x1894>
   
0x1840:  
0x184c:   
0x1854:   
0x1860:  
0x1864:   
 fde section offset 152 0x0098 cie offset for fde: 36 0x0024
 0 DW_CFA_advance_loc 12  (3 * 4)
 1 DW_CFA_def_cfa_offset 112
 3 DW_CFA_offset_extended_sf r65 16  (-2 * -8)
 6 DW_CFA_advance_loc 8  (2 * 4)
 7 DW_CFA_remember_state
 8 DW_CFA_def_cfa_offset 0
10 DW_CFA_advance_loc 12  (3 * 4)
11 DW_CFA_restore_extended r65
13 DW_CFA_advance_loc 4  (1 * 4)
14 DW_CFA_restore_state
<2><0x1db0:0x1ddc>
   
0x1db0:  
 fde section offset 64 0x0040 cie offset for fde: 68 0x0044
 0 DW_CFA_nop
 1 DW_CFA_nop
 2 DW_CFA_nop
<3><0x1de0:0x1e5c>
   
0x1de0:  
0x1de8:  
0x1e14:  
0x1e18:  
0x1e1c:   
0x1e24:   
 fde section offset 84 0x0054 cie offset for fde: 88 0x0058
 0 DW_CFA_advance_loc 8  (2 * 4)
 1 DW_CFA_def_cfa_offset 128
 4 DW_CFA_advance_loc 44  (11 * 4)
 5 DW_CFA_remember_state
 6 DW_CFA_def_cfa_offset 0
 8 DW_CFA_advance_loc 4  (1 * 4)
 9 DW_CFA_restore_state
10 DW_CFA_advance_loc 4  (1 * 4)
11 DW_CFA_register r65 = r0
14 DW_CFA_advance_loc 8  (2 * 4)
15 DW_CFA_offset_extended_sf r65 16  (-2 * -8)
18 DW_CFA_nop
<4><0x1ee0:0x1f34><>
   
0x1ee0:  
0x1ee4:   
0x1ef8:  
 fde section offset 40 0x0028 cie offset for fde: 44 0x002c
 0 DW_CFA_advance_loc 4  (1 * 4)
 1 DW_CFA_register r65 = r12
 4 DW_CFA_advance_loc 20  (5 * 4)
 5 DW_CFA_restore_extended r65

cie:
<0> version 1
cie section 

[Bug 230857] loading carp module panic i386 kernel (VIMAGE related)

2018-10-17 Thread bugzilla-noreply
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=230857

Bjoern A. Zeeb  changed:

   What|Removed |Added

 Depends on||232291, 232289

--- Comment #8 from Bjoern A. Zeeb  ---
Track the dependency problems;  need to solve at least the link_elf one before
we can do the BYTE(1) linker script and follow-up link_elf checks.


Referenced Bugs:

https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=232289
[Bug 232289] kern/link_elf.c fails for small sections sizes (https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=232291
[Bug 232291] ld.bfd (newer) and ld.lld (6 and imho 7) create empty sections
when they should not
-- 
You are receiving this mail because:
You are on the CC list for the bug.
___
freebsd-toolchain@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-toolchain
To unsubscribe, send any mail to "freebsd-toolchain-unsubscr...@freebsd.org"