Exceptions not caught

delphi package - automated exception handling
Post Reply
rsassen
Posts: 24
Joined: Fri Jun 20, 2014 2:41 pm

Exceptions not caught

Post by rsassen »

Hi,

I've enabled madExcept for one of our projects, and I'm trying to figure out why madExcept does not catch the exceptions in the application. I unfortunately can't reproduce this in a small test project, it seems to be specific for this somewhat larger project.

From an old post I remember that madExcept can log its actions during its initialization, so I figured I'd add madExcept.pas to my project and enable that. Maybe it could show me if all hooks are being registered as expected. However, adding the .pas file to my project resulted in the problem being gone: exceptions were being caught by madExcept. I've also tried including the madExcept.obj to my project instead of the madExcept.pas. Same result: exceptions are caught by madExcept. When adding madExcept_.lib instead of the .pas or .obj file the exceptions are not caught by madExcept.

I've checked my main project cpp file. All #pragma link statements added by madExcept are present.

I should also mention that even in scenarios where madExcept is not catching the exceptions, memory leaks are being reported by madExcept. So it seems madExcept was able to patch the executable?

Do you perhaps have suggestions for finding the cause of this problem? Might there be a problem during initialization?

As a workaround, would adding madExcept.pas to my project be a advisable for a stable release? Or would it risk other issues?

Anyway, I would like to find out if there is a problem with my project. So any suggestions to debug it are welcome.

During these test I'm always compiling and running the project from within the RAD Studio IDE.
C++ Builder Sydney 10.4 update 1
madCollection 2.8.11.0
Windows VCL project, 32 bit, classic compiler

Thanks,

Rutger Sassen
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: Exceptions not caught

Post by madshi »

To be honest, I've no idea what's going on. One thing you could do is create an empty file "madExceptWizard.txt" on your desktop, and then start BCB and compile the project. If you do this both ways (with obj file vs pas file) and then compare the log files, maybe you can spot a meaningful difference?

In any case, just adding the pas file should work just fine.
rsassen
Posts: 24
Joined: Fri Jun 20, 2014 2:41 pm

Re: Exceptions not caught

Post by rsassen »

The madExceptWizard.txt for the not-working version, and the working version where i've added the madExcept.obj to my project show some interesting differences. In the not-working situation the madExcept patch utility can't seem to find it's own hook functions in the executable. E.g.:

Not working:
madExcept.BcbInitExceptBlockLDTC not found
Working:
madExcept.BcbInitExceptBlockLDTC: $000338cc
Also, the output of the working situation has a line
Info: Binary patched.
whereas the non-working situation does not have this line.

I've no clue why it's not working in the normal situation, i.e. without explicitly adding madexcept.obj to the project.

Do you have any suggestions for further debugging the issue?

Also, it would be helpful if the madExcept wizard could notify when the patching fails?
Attachments
madExceptWizard_working.zip
Working, added madExcept.obj to the project
(1.14 KiB) Not downloaded yet
madExceptWizard_not_working.zip
Not working
(1.07 KiB) Not downloaded yet
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: Exceptions not caught

Post by madshi »

In the non-working case, it seems that the wizard doesn't find anything related to madExcept.obj at all. Are you sure that the madExcept.obj is even linked in at all?
rsassen
Posts: 24
Joined: Fri Jun 20, 2014 2:41 pm

Re: Exceptions not caught

Post by rsassen »

To test, I added a TApplicationEvents component to the main form of the application, and in its onException event I call Madexcept::HandleException(). This compiles and links fine, and when an exception is thrown this event is invoked and the madExcept dialog appears. So madExcept.obj seems to be linked in. The output of madExceptWizard is still the same as the previous non-working situation: it cannot find the madExcept hook routines.
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: Exceptions not caught

Post by madshi »

I've no explanation for that right now. The easy solution is to just copy madExcept.pas into your project folder, I guess. Though, it should work the other way, too.
rsassen
Posts: 24
Joined: Fri Jun 20, 2014 2:41 pm

Re: Exceptions not caught

Post by rsassen »

If I find the time I might try to dig somewhat deeper into the issue, but in the mean time I think I will just include the madExcept.obj into the project.

W.r.t. my earlier suggestion, for a future version it might be useful if the wizard could notify the developer when the patching fails?

Thanks for the support!
rsassen
Posts: 24
Joined: Fri Jun 20, 2014 2:41 pm

Re: Exceptions not caught

Post by rsassen »

I finally had some time to delve deeper into this issue.

I added some debug logging to madExceptPatcher in unit madMapFile.pas. From this I noticed that sometimes when the length of a segment is updated after adding a public symbol, the new length is incorrect. This seems to happen when the last added segment (FSLastAdded variable in madMapFile.pas) differs from the segment the newly added public is in. E.g. when the last added segment was in DATA (segment 2), but the new public is in BSS (segment 3).

FSLastAdded is an array with a boolean index indicating the CODE segment (segment 1) or not (segment >=2). Maybe the index should reflect the actual segment number?
rsassen
Posts: 24
Joined: Fri Jun 20, 2014 2:41 pm

Re: Exceptions not caught

Post by rsassen »

I forgot to mention that I also found that the public symbols (e.g. madExcept.BcbInitExceptBlockLDTC) are indeed detected by madExceptPatcher (function FindPublic), but that it thinks that the start address in not in the address range for unit madExcept. I believe this might be a result of the faulty segment calculations.
rsassen
Posts: 24
Joined: Fri Jun 20, 2014 2:41 pm

Re: Exceptions not caught

Post by rsassen »

Hi,
Can you confirm my findings on the issues I found in madExceptPatcher? If needed I can send you our executable, tds and map file and our mad settings file. Then you might be able to investigate further.
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: Exceptions not caught

Post by madshi »

Sorry for the late reply.

I assume this problem is specific to C++?

Maybe can you suggest a change to madExceptPatcher to fix the issue?
rsassen
Posts: 24
Joined: Fri Jun 20, 2014 2:41 pm

Re: Exceptions not caught

Post by rsassen »

I have no reason to assume it is specific to C++. I'm not very familiar with Delphi executables, but I think they also use both a DATA and a BSS segment?

Regarding a possible solution, in madExceptPatcher I have experimented somewhat with replacing the boolean index for FSLastAdded with an integer representing the segment number. That seems to help, but in order to do that, the segment number needs to be known (e.g. in ParsePublics). I found little documentation on how to get the segment number when parsing the executable and could not solve it for all cases.

Another approach would be to have the linker generate a detailed map file with all the info. That might be a lot easier to parse that trying to find the info in the executable. I'm not familiar enough with all possible use cases for RadStudio projects and madExceptPatcher to know if that approach would always work. Your thoughts?
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: Exceptions not caught

Post by madshi »

In BCB, the PE segments are much more complicated than in Delphi. So that's why I'm assuming this is probably specific to BCB. Maybe can you create a very simple test project which demonstrates the problem? The simpler, the better.
rsassen
Posts: 24
Joined: Fri Jun 20, 2014 2:41 pm

Re: Exceptions not caught

Post by rsassen »

I've tried, but am unable so far to create a simple test project to demonstrate the problem.

The problem occurs when e.g. a public symbols in segment 3 follows one in segment 2 and when as a result the length of a unit in segment 2 is recalculated. In the cases I've encountered the symbol Sysinit::ImageBase in segment 3 - which lives at a very high address - caused the recalculated length of the previous unit in segment 2 to be extremely long. This somehow also causes the address ranges of other units to get corrupted further along the process.

Furthermore it only poses a problem when the calculated address range of a unit in which madExceptPatcher is interested is wrong (e.g. the madExcept unit when it tries to find the public BcbInitExceptBlockDTC).

I don't know how to reproduce this a specific situation in a simple test project. But multiple of our larger C++ projects suffer from this issue. As stated before I could send you an executable and map file which demonstrates the issue. Are you interested? (I'd rather not post them on a public forum)
Post Reply