psmedley / gcc

GNU General Public License v2.0
7 stars 1 forks source link

__ehInit is added to each and every object #8

Closed dmik closed 9 years ago

dmik commented 10 years ago

For some reason, GCC 4.7.3 adds a reference to __ehInit (defined in gcc/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.

dmik commented 10 years ago

There is at least one failed case due to this difference: http://trac.netlabs.org/odin32/ticket/109.

psmedley commented 10 years ago

will try look at this today

psmedley commented 10 years ago

odin built fine with my local build of gcc 4.7.3

dmik commented 10 years ago

Please see the comment in there. And also, can you confirm that your local build also produces __ehInit in every object file?

psmedley commented 10 years ago

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.

dmik commented 10 years ago

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.

psmedley commented 10 years ago

[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.

StevenLevine commented 10 years ago

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.

dmik commented 10 years ago

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.

dmik commented 9 years ago

Paul, is there any update on this topic? WRT 4.9.0, for instance.

psmedley commented 9 years ago

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.

ydario commented 9 years ago

using -fno-asynchronous-unwind-tables produces a object file without unwinding table (so without eh_frame and _ehInit).

dmik commented 9 years ago

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?

psmedley commented 9 years ago

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) {

dmik commented 9 years ago

@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.

ydario commented 9 years ago

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.

ydario commented 9 years ago

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.

ydario commented 9 years ago

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

dmik commented 9 years ago

@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?

dmik commented 9 years ago

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.

ydario commented 9 years ago

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.

ydario commented 9 years ago

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.

dmik commented 9 years ago

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?

ydario commented 9 years ago

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.

dmik commented 9 years ago

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.

ydario commented 9 years ago

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...

dmik commented 9 years ago

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.

dmik commented 9 years ago

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
ydario commented 9 years ago

--enable-frame-pointer is not set by default, adding it changes completely gcc code generation.

dmik commented 9 years ago

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.

psmedley commented 9 years ago

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 :(

ydario commented 9 years ago

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.

ydario commented 9 years ago

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

dmik commented 9 years ago

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.

dmik commented 9 years ago

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.

dmik commented 9 years ago

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.