Closed dmik closed 9 years ago
There is at least one failed case due to this difference: http://trac.netlabs.org/odin32/ticket/109.
will try look at this today
odin built fine with my local build of gcc 4.7.3
Please see the comment in there. And also, can you confirm that your local build also produces __ehInit
in every object file?
What's the best way to check if local objects include that symbol?
Cheers,
Paul On Jun 9, 2014 7:32 PM, "Dmitriy Kuminov" notifications@github.com wrote:
Please see the comment in there. And also, can you confirm that your local build also produces __ehInit in every object file?
— Reply to this email directly or view it on GitHub https://github.com/psmedley/gcc/issues/8#issuecomment-45476556.
The simplest way is to search for __ehInit
within the .o file. One way to do this: cat -v file.o | grep -o __ehInit
. If the output is __ehInit
, there is such a reference.
[U:\DEV\odin32\trunk\out\os2.x86\release\obj\pe]cat -v pe.o | grep -o __ehInit
[U:\DEV\odin32\trunk\out\os2.x86\release\obj\pe]
On Mon, Jun 9, 2014 at 7:53 PM, Dmitriy Kuminov notifications@github.com wrote:
The simplest way is to search for ehInit within the .o file. One way to do this: cat -v file.o | grep -o ehInit. If the output is __ehInit, there is such a reference.
— Reply to this email directly or view it on GitHub.
FWIW, I also get no references to ehInit with 4.7.2. Poking about, it appears that this symbol and ___eh_frame are somehow related to DWARF2 debug data based on what I see in dwarf2out.c.
Well, this means that something's wrong with the RPM build... AFAIR __eh_frame
(and all other eh
stuff) is used to keep track of stack frames needed when handling C++ exceptions. And this mechanism is definitely used on OS/2 as well.
Paul, is there any update on this topic? WRT 4.9.0, for instance.
As I recall, I couldn't reproduce locally, hence nothing from me.
Cheers,
Paul On 20 Jan 2015 4:33 am, "Dmitriy Kuminov" notifications@github.com wrote:
Paul, is there any update on this topic? WRT 4.9.0, for instance.
— Reply to this email directly or view it on GitHub https://github.com/psmedley/gcc/issues/8#issuecomment-70535715.
using -fno-asynchronous-unwind-tables produces a object file without unwinding table (so without eh_frame and _ehInit).
So, in short, we need to find out why -fasynchronous-unwind-tables
is default for our RPM build and not for Paul's. My guess it that configure run in the RPM env thinks it should use this option. And since the Paul's env is different, it's not triggered on his side. Yuri, could you check if configure is responsible for this option?
I got the %sil error too. I fixed it with: --- \usrsvn\include\386\builtin.h 2014-10-26 18:40:22.000000000 +1030 +++ \usr\include\386\builtin.h 2014-04-23 18:32:36.000000000 +0930 @@ -15,7 +15,8 @@ static inline signed char cxchg (__volatile signed char *p, signed char v) {
@ydario reports that configuring gcc with --enable-frame-pointer
restores usage of the -fno-ansynchronous-unwind-tables
option by default on OS/2.
@psmedley can you confirm that your own builds of gcc use --enable-frame-pointer
? And also can you explain why you made --disabled-frame-pointer
to be set by default on OS/2 in 311439ca12c3a5847cede9a71a576812631899b3?
Why --disable-frame-pointer
triggers -fasynchronous-unwind-tables
is another story. But we should find it out to have this issue fully resolved.
Also, I found that our gcc/configure
doesn't match gcc/configure.ac
. Perhaps this is the case for other configure files as well as for some Makefiles. This is hackish and error prone. We should sort it out to have these files in sync. I created a separate issue #11 for that.
Above changeset is wrong because target_os == os2-emx
The difference is made by --enable-frame-pointer, which restores behavior of pre 4.6 compilers. It is still not clear to me why this interacts with unwind tables, they are related somehow...
Even without unwinding tables C++ exceptions are still working, Paul confirmed this with some KO c++ source tested.
BTW even setting the correct target os, the OS/2 build is still adding frame pointers to code. Only adding -fomit-frame-pointer effectively removes them.
And for the bad news stream, I have to say that the newly build stdcpp6.dll does not catch exceptions thrown by code built with gcc 4.7.3, current AOO binaries shows this issue. And it is not related to above flags, since happens with all kind of builds of 4.9.2 sources. Sounds like we need to change dll name again.
Stack trace shows that stdcpp6.dll it is unable to unwind the stack...
Function | Part | Source | Module
------------------------------------------------------------------------------+------------------+------------+-----------------------
0x1E5B6AC4 | libc066.dll:1 | | libc066.dll:1:748228
0x1E5B67C6 | libc066.dll:1 | | libc066.dll:1:747462
0x1E52E174 | libc066.dll:1 | | libc066.dll:1:188788
0x1E52E0CE | libc066.dll:1 | | libc066.dll:1:188622
0x1E52CFEE | libc066.dll:1 | | libc066.dll:1:184302
0x1E52F835 | libc066.dll:1 | | libc066.dll:1:194613
0x1E553F38 | libc066.dll:1 | | libc066.dll:1:343864
0x1E557FC3 | libc066.dll:1 | | libc066.dll:1:360387
0x1E54ABFA | libc066.dll:1 | | libc066.dll:1:306170
ZN9gnu_cxx27verbose_terminate_handlerEv | stdcpp6.dll:1 | | stdcpp6.dll:1:354898
ZN10cxxabiv111terminateEPFvvE | stdcpp6.dll:1 | | stdcpp6.dll:1:110168
ZSt9terminatev | stdcpp6.dll:1 | | stdcpp6.dll:1:110782
___cxa_throw | stdcpp6.dll:1 | | stdcpp6.dll:1:111788
ZN3com3sun4star10reflection24InvalidTypeNameExceptionaSERKS3_ | bootstra.dll:1 | | bootstra.dll:1:254525
_ZN3com3sun4star10connection18NoConnectExceptionaSERKS3 | cppuh3.dll:1 | | cppuh3.dll:1:180615
_ZN3com3sun4star10connection18NoConnectExceptionaSERKS3 | cppuh3.dll:1 | | cppuh3.dll:1:182236
@ydario okay about the wrong platform spec, but sorry I don't understand you so far as some of your statements contradict each other. My question: does only adding --enable-frame-pointer
to configure
influence your build WRT the __ehInit
behavior? If yes, how exactly does it do so?
What about the name for stdcpp
, we should follow the upstream rules. If there is an incompatible ABI change, they increase the number. If there is not, then it's definitely a bug of our port for which we should find an exact reason before making a decision. Why did you decide to use this number? From what I see in libstdc++-v3/acinclude.m4
, libtool version-info is 6:20:0
which according to libtool rules should give us 6
. But the previous releases of GCC would result in 6 as well as for e.g. 4.7.3 it is 6:17:0
.
interaction between these flags is handled in gcc/config/i386/i386.c #3771, see x_flag_asynchronous_unwind_tables. initially set to 2, it became !USE_IX86_FRAME_POINTER at #3775 (result 1). but maybe something else is triggered, I'm not sure everything is here.
for stdcpp6, we changed name for 4.7.3 because 473 build was not compatible with older 442 dll (stdcpp.dll). So I think we got again the same issue saw in the past.
You still didn't answer my question regarding --enable-frame-pointer
. From what I see in config files, this setting triggers the USE_IX86_FRAME_POINTER=1
define. However, in mail you told us that USE_IX86_FRAME_POINTER
is always set to 1 in gcc/config/i386/sol2-bi.h
which will indicate that --enable-frame-pointer
is meaningless in case if OS/2 uses gcc/config/i386/sol2-bi.h
. So what is the case? Who uses what and what is the value for USE_IX86_FRAME_POINTER
in your builds depending on the options?
Next, regarding x_flag_asynchronous_unwind_tables
. 2 most likely means 'default', i.e., when the value isn't explicitly specified on the command line. Which in such case makes it an inversion of USE_IX86_FRAME_POINTER
(i.e. when the frame pointer is used, the asynchronous tables are disabled and vice versa). So the question now is why this flag is obeyed on OS/2? Does OS/2 support DWARF2 in any way?
Regarding the version. I couldn't quickly find where they set the version suffix in 4.4.x, but in 4.7.x they switched to libtool's version-info and according to that the major suffix is not changed between 4.7 and 4.9. Which means that officially the DLL must be binary compatible. What exactly makes it incompatible in our case?
ok, I got the stdcpp issue: my new stdcpp6.dll was linked against gcc492.dll; since my bot was still holding the static lib, I used dllar to produce stdcpp6.dll with current runtime, e.g. linked with gcc473.dll: AOO starts correctly now! I got the idea after looking cxxabiv1::cxa_throw() code in src\libstdc++-v3\libsupc++\eh_throw.cc; the call to __cxa_begin_catch (&header->exc.unwindHeader); goes to the gcc runtime dll. Probably the gcc runtime takes care of unwinding.
I remember during OOo development that exception handling must be driven by a single dll, otherwise exceptions were not able to cross DLLs. At that time I wrote the first stdc432.dll code to get exceptions working.
Yes, it's known that gcc.dlll takes care of unwinding. Regarding ABI, this proves that what I wrote above is correct (JFYI): https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html.
Now we have a problem: how to get the unwinding code in the same dll... a program built with two different runtimes cannot correctly handle exceptions... I think it does not handle exceptions at all...
According to the GCC ABI reference mentioned above, libgcc is meant to be binary compatible among all gcc 3.x and gcc 4.x releases. This suggests us that we should name it gcc1.dll (to follow the common ABI and naming rules) and not change this name until compatibility officially breaks upstream. Once we have gcc1.dll
and stdcpp6.dll
(for the current ABI), both will be updated at once when updating GCC so old code will continue to work.
However, to make work old code that we already built with gcc473 (which uses stdcpp6.dll
and gcc473.dll
) we have to replace gcc473.dll
with a wrapper that forwards everything to gcc1.dll
— to make sure these apps use the new version of both stdcpp
AND gcc
. As for even older builds of gcc, (4.4.x), they use stdcpp.dll
instead of stdcpp6.dll
and therefore won't be affected by our new work at all.
In order to create the wrapper we should take the approach which Knut uses for libc. But I think this wrapper should be built at RPM level (i.e. patches + .spec) rather than placed within the GCC code base — it has nothing to do with gcc itself (it should always produce gcc1.dll, as on other platforms), it's about our house keeping. And since we create ZIPs for every RPM, this forwarding wrapper will be also available as ZIP for anyone not using RPM.
Yuri, about --enable-frame-pointer
again. You say that you had to use it in your build and at the same time you claim that the above target_os check is not correct. But that means that --enable-frame-pointer
is set on OS/2 by default. So it's not clear then how using it may change the situation. This still needs investigation.
As for x_flag_asynchronous_unwind_tables
, it seems the simplest solution is to change line 3775 of gcc/config/i386/i386.c
from
opts->x_flag_asynchronous_unwind_tables = !USE_IX86_FRAME_POINTER;
to
#ifdef __OS2__
/* Don't emit DWARF 2 unwind tables on OS/2 by default as it makes no use of it */
opts->x_flag_asynchronous_unwind_tables = 0;
#else
opts->x_flag_asynchronous_unwind_tables = !USE_IX86_FRAME_POINTER;
#endif
--enable-frame-pointer is not set by default, adding it changes completely gcc code generation.
Please look here https://github.com/psmedley/gcc/blob/gcc-4_9-branch-os2/gcc/configure#L11494:
# Check whether --enable-frame-pointer was given.
if test "${enable_frame_pointer+set}" = set; then :
enableval=$enable_frame_pointer;
else
case $target_os in
linux* | darwin[8912]* | i386-pc-os2-emx )
# Enable -fomit-frame-pointer by default for Linux, OS/2 and Darwin with
# DWARF2.
enable_frame_pointer=no
;;
*)
enable_frame_pointer=yes
;;
esac
fi
Given that target_os
is os2-emx
, the code above will set enable_frame_pointer
to yes
when no option is given on the command line. Which is completely equivalent to specifying --enable-frame-pointer
.
Hi guys,
On 22/01/15 21:30, Dmitriy Kuminov wrote:
@psmedley https://github.com/psmedley can you confirm that your own builds of gcc use |--enable-frame-pointer|? And also can you explain why you made |--disabled-frame-pointer| to be set by default on OS/2 in 311439c https://github.com/psmedley/gcc/commit/311439ca12c3a5847cede9a71a576812631899b3?
Unfortunately I can't recall. I can say though that this change was made around GCC 4.7 timeframe - ie it wasn't in 4.6.
Obviously I was trying to fix something, but right now I don't recall what it was :(
I'm sure all default gcc builds are not using enable-frame-pointer, the code generation always wrote unwind tables. I know the above snippet is wrong, but this did not enable the frame pointer, probably this option does something else. I built gcc 4.9.0 and 4.9.2 many times, all added unwind tables until I used --enable-frame-pointer in configure script.
We are now moving to gcc1 naming scheme, as per gcc specs. RPM is building forwarders to gcc1 for gcc446.dll and gcc473.dll; since ABI is compatible for all gcc 3.x and 4.x builds, I think we could gather all def files for existing runtimes and transform them as forwarders. This will allow us to get rid of different runtimes floating around and build them in a single place. Unfortunately, since gccXXX has been always built using ordinals exports only, we need the .def file to prepare the forwarder.
The def file can be created from libgcc_so_d.a too, converting it first to .lib, then .imp and finally .def
Yuri, the only thing --enable-frame-pointer
does is sets enable_frame_pointer
which then in turn sets USE_IX86_FRAME_POINTER
. That's all. So it can't be like you say. Or we miss something.
Re gcc1.dll
. It's really great that it worked as we planned. Now we have one headache less.
I did the unwind fix in 4712cb74ba517ad855791481a1c143629a36c49a. This is to make sure we don't use unwind tables even if --disable-frame-pointer
is given to configure.
Finally, I found out why --enable-frame-pointer
is so inconsistent. The reason is that gcc/config.gcc
where this option is turned into USE_IX86_FRAME_POINTER=1
is included before handling this option in the main gcc/configure
file where it is assigned a default value if not explicitly set. When --enable-frame-pointer
is explicitly given, it's already set by the time config.gcc
is included and hence all works as designed. This looks like an upstream bug in gcc/configure.ac
to me. I'm not well aware of all GCC configure nuances and also #11 is not yet resolved, so I better won't touch it for now.
The thing is that if you forget to use --enable-frame-pointer
in configure, you will get a GCC build that, when asked for optimization with -O1
, -O2
and O3
, creates binaries which can't be properly debugged (in particular, you will never get a full call stack trace with these binaries during a trap since functions will not use EBP to point to the current stack frame). This is definitely not what we want. And because of problems with configure I have to force this with an ifdef directly in i386.c
(like I did for the unwind thingy). See 8ae923657e8d45965eeb26a77a7bef530cdbe174.
With this, I consider this issue as resolved.
For some reason, GCC 4.7.3 adds a reference to
__ehInit
(defined ingcc/config/i386/emx-eh.c
) to each and every generated C and C++ source file. There is no need to refer to it in regular object files. This is part of CRT startup code (whose job is to initialize exception handling and such).The previous GCC versions (e.g. 4.4.6) don't put this symbol into object files.
This looks like a 4.7.3 regression then.