On Fri, Mar 28, 2008 at 8:03 PM, Giel van Schijndel <me@mortis.eu> wrote:
Hi all,

I'm currently in the process of developing a more useful
exceptionhandler for our project (Warzone 2100 [1]). I'm basically
taking exchndl.c from Dr. MinGW's exception handling DLL (exchndl.dll)
and will extend that further where necessary.

I've started work on this by first trying to compile exchndl.c without
modifications and linking it statically into the project.

At first compiling failed due to what, according to some Googling, was a
misplaced parenthesis. This was fixed easily enough [2]. (Google was
faster than manually trying to find out all of the types of every struct
member involved).

I then got linker errors when linking with libbfd because of two missing
symbols: bfd_get_section_size_before_reloc and
bfd_get_section_size_after_reloc. In these same threads I found for the
above compiler error I also found a simple fix [3].

Now I could get exchndl.c to compile and link fine with the libbfd and
libiberty shipped with MinGW.

However, when I inserted some test code to trigger segfaults:
> int* i = 0; *i = 27;
I discovered that my self-compiled failed to extract symbols for the
generated stack dump. This unlike the precompiled exchndl.dll that is
shipped with mingw-utils 0.3 which does this successfully. Compiling
exchndl.c as a DLL had the same results as linking statically (i.e. no
symbols in the stack trace).

After yet some more Googling I found a thread on this mailing list which
seems to deal with the same issue (i.e. the symptoms are the same at
least) [4].

Like his case I traced the problem to the function
find_address_in_section in exchndl.c. Unlike his case, however, I
discovered that in my case bfd_find_nearest_line never even got called.
In my case the function already returned on this if-statement:
> if (info->pc >= vma + (size = bfd_get_section_size_before_reloc (section)))
>     return;
Apparently __all__ return addresses on the stack are larger than (vma +
size). Which lead me to look at vma's value, which apparently __always__
is zero (vma = 0) for me. Then after scanning the BFD documentation I
found out that the vma represents the virtual memory's base address.
This obviously shouldn't be zero on any modern OS, thus I assume
something went wrong in computing this vma.

The precompiled DLL, however, __does__ work, thus I would like to know
if and how this DLL is different from the source code provided. Aside
from that the only thing I can think of is that the versions of libbfd
that DLL has been linked against and the version I am using to link to
(version shipped with the MinGW-5.1.3 installer) might differ. This
would also explain the above mentioned linker errors.

I ran into similar issues when trying to make some tweaks to exchndl.c to add dll version information.

It has been a while since I did this and I don't remember exactly what I did, but my modified exchndl.c is available here: http://pidgin.im/~datallah/exchndl.c.  A diff against the file in mingw-utils-0.2 reveals that I switched it to use bfd_get_section_size() instead of bfd_get_section_size_before_reloc(), but I really don't recall the details.

IIRC, I was using headers and import libraries from the "binutils-2.17.50-20060824-1" package, if that helps.

-D