Chris’ CodeGear Debugger Blog

RAD Studio 2010: Delay Load import exceptions

One of the things I do after a product release (or an update release, for that matter) is keep an eye on the Incident Reports that are submitted to QualityCentral via the Send Report wizard that is built into the IDE.  A few years ago, I wrote a tool that makes it really easy to see which reports are coming in at a high frequency.  The data gleaned from this tool is really helpful when looking for "big bang for the buck" type bug fixes to go after for an update (or future product release).  One issue that I’ve seen reported at a moderate level (about a dozen reports, so far) for the 2010 release is related to the new "delay-loaded import" feature.  You can learn more about this feature by reading the following posts by Allen Bauer and Christian Wimmer:

http://blogs.embarcadero.com/abauer/2009/08/25/38894

http://blogs.embarcadero.com/abauer/2009/08/29/38896

http://blog.delphi-jedi.net/2009/08/29/version-checking-for-delphi/

In Christian’s post and in Allen’s second post, there is discussion of the exception that is raised when a delay-loaded method can not be found at runtime.  It is this exception that is prompting D2010 users to submit QC reports.  In fact, every single one of these reports I’ve seen so far are coming from developers who are using the JVCL at design time in the IDE — in particular it appears that these developers are using a TJvCustomSpeedButton descendant.  Based on the exception, it would appear that each report was generated on a pre-Vista OS.

The error message associated with this exception is either "External Exception $C0FB007E" or "External Exception $C0FB007F."  Here is the top of the stack trace for one of these reports (this is what you’ll see if you click the "Details" button on the error message in the IDE):


[7C812A6B]{kernel32.dll} RaiseException + $52
[50011BDB]{rtl140.bpl  } System.@_delayLoadHelper (Line 302, "C:\Builds\TP\rtl\sys\delayhlp.c" + 158) + $D
[500B0681]{rtl140.bpl  } UxTheme.uxtheme.dll (Line 5112, "UxTheme.pas" + 0) + $5
[500B0712]{rtl140.bpl  } UxTheme.DrawThemeTextEx (Line 5138, "UxTheme.pas" + 1) + $20
[490EE508]{JvCoreD14R.bpl} JvThemes.DrawGlassableText + $C4
[490EE54C]{JvCoreD14R.bpl} JvThemes.DrawGlassableText + $108
[49ACF1B4]{JvStdCtrlsD14R.bpl} JvSpeedButton.TJvxButtonGlyph.DrawButtonText + $C4
[49ACF2A6]{JvStdCtrlsD14R.bpl} JvSpeedButton.TJvxButtonGlyph.DrawEx + $E2
[49ACDA81]{JvStdCtrlsD14R.bpl} JvSpeedButton.TJvImageSpeedButton.PaintImage + $C5
[49AE416C]{JvStdCtrlsD14R.bpl} JvToolEdit.TJvEditButton.PaintImage + $78
[49ACCC96]{JvStdCtrlsD14R.bpl} JvSpeedButton.TJvCustomSpeedButton.Paint + $336
[49AE4078]{JvStdCtrlsD14R.bpl} JvToolEdit.TJvEditButton.Paint + $98
[501CE436]{vcl140.bpl  } Graphics.TCanvas.SetPenPos (Line 4050, "Graphics.pas" + 1) + $9
[5029F685]{vcl140.bpl  } Controls.TGraphicControl.WMPaint (Line 13141, "Controls.pas" + 7) + $5
[49ACD58E]{JvStdCtrlsD14R.bpl} JvSpeedButton.TJvCustomSpeedButton.WMPaint + $B6
[50295DFC]{vcl140.bpl  } Controls.TControl.WndProc (Line 7062, "Controls.pas" + 91) + $6

 

The exception is raised because in Delphi 2010, the DrawThemeTextEx declaration in UxTheme.pas was changed from using the LoadLibrary/GetProcAddress mechanism mentioned by Allen to use the new delay-loaded mechanism. 

Below if the pre-D2010 version of the implementation of DrawThemeTextEx:
 


function DrawThemeTextEx(hTheme: HTHEME; hdc: HDC; iPartId: Integer;
  iStateId: Integer; pszText: LPCWSTR; cchText: Integer; dwTextFlags: DWORD;
  pRect: PRect; var pOptions: TDTTOpts): HResult;
begin
  if Assigned(_DrawThemeTextEx) then
    Result := _DrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText, cchText,
      dwTextFlags, pRect, pOptions)
  else
  begin
    Result := E_NOTIMPL;
    if ThemeLibrary > 0 then
    begin
      _DrawThemeTextEx := GetProcAddress(ThemeLibrary, 'DrawThemeTextEx'); // Do not localize
      if Assigned(_DrawThemeTextEx) then
        Result := _DrawThemeTextEx(hTheme, hdc, iPartId, iStateId, pszText,
          cchText, dwTextFlags, pRect, pOptions);
    end;
  end;
end;

And here is the D2010 version:


function DrawThemeTextEx(hTheme: HTHEME; hdc: HDC; iPartId: Integer;
iStateId: Integer; pszText: LPCWSTR; cchText: Integer; dwTextFlags: DWORD;
pRect: PRect; var pOptions: TDTTOpts): HResult; stdcall; external themelib name 'DrawThemeTextEx' delayed;

Because of the change, existing code that calls this API on a pre-Vista system would now generate the aforementioned delay-load exception.  With the old mechanism, calling this method would have resulted in a "E_NOTIMPL" return value.   The JVCL code that calls this API, had error-handling code in place to properly handle the E_NOTIMPL return value, but this did not help with the new exception-raising mechanism.   I just checked, and it looks like the JVCL team has addressed this issue.  The sources contained in the current JVCL tip revision properly handle the situation by doing a Windows version check before calling the API (see revision 12491 of JVThemes.pas, committed on September 4th, 2009).  That said, if you are using the JVCL and have not yet updated to the most recent sources, you may still run into this exception in D2010 when running on Windows XP (or any pre-Vista version of Windows).  To avoid this, I would suggest updating your JVCL sources.  If that’s not practical, I would at least apply the changes made in the aforementioned revision.
 

On a related note, it would probably be a good idea for the IDE to give a better error message in this particular case.  I think that if the IDE used a solution similar to one presented by Allen in his second post, that would definitely make things much more user-friendly should an error like this occur again in the future.   Telling the user that a particular entry point is missing from a particular module is much nicer than giving an external exception with an obscure error code.   I’ll be investigating such a solution for a future release.

 UPDATE: I just noticed that Andreas Hausladen blogged on this exact issue a few months ago:  http://andy.jgknet.de/blog/?p=660

Posted by Chris Hesik on November 2nd, 2009 under C++Builder, Delphi, IDE, RAD Studio | 7 Comments »


Debugger Tip: Ignoring non-user breakpoints

I just realized that a feature that was added for the 2007 releases is not mentioned on my page that outlines debugger additions that have been made since Delphi7/BCB6.  I’ve gone ahead and updated that page, but I think this feature is worth mentioning in a separate post.

The feature I’m talking about is the addition of the debugger option called "Ignore non-user breakpoints".  In the 2010 release, this option can be found on the "Embarcadero Debuggers" page on the Tools | Options dialog (or you can use IDE Insight to find it).  In previous releases the page would have been called either "CodeGear Debuggers" or "Borland Debuggers", depending on the company name at the time of the release.

This function of this option should be self-explanatory — the only thing that might not be clear is what exactly constitutes a "non-user breakpoint".  A non-user breakpoint is any breakpoint that you have not explicitly set in the IDE.  There are a couple of different things that cause a non-user breakpoint to be triggered.  Some common causes:

  1. A hardcoded breakpoint using inline assembly.  The assembly instruction for a breakpoint is "int 3".  If you have any inline assembly that includes this instruction, a breakpoint will be triggered if you are running under the debugger when that instruction is executed.
  2. A call to the WINAPI procedure "DebugBreak".  If you have code that calls this procedure, a breakpoint will be triggered if you are running under the debugger when that procedure is called.
  3. Pressing F12 in an application that is running under the debugger.  This hotkey is controlled by the OS (on by default for XP, can be disabled; off by default in newer Windows versions, can be enabled).  It basically causes an app that is running under the debugger to break back into the debugger via a breakpoint.
  4. Sometimes passing bad parameters or data to some WINAPI functions causes those functions to trigger breakpoints if you are running under the debugger.

There may be other situations that cause a non-user breakpoint to get hit.  You’ll know you’ve hit one by looking in the CPU view after your application unexpectedly breaks back into the debugger.  If you see an "int 3" instruction in the CPU view at the address immediately preceding the instruction at the address indicated by the current EIP, you can be pretty sure you’ve hit a non-user breakpoint.  All of the common causes mentioned above boil down to an "int 3" instruction getting executed by the app being debugged.

Using the "Ignore non-user breakpoint" debugger option, you can tell the debugger that you don’t want your process to stop when it encounters one of these.  When that happens, the debugger will respond to the breakpoint triggering by just setting the process running again — there will be no indication that a non-user breakpoint is hit.

This can be especially useful for case #3 above — if your app uses F12 as a hotkey, and you need to debug its handling of the F12 key on XP, but don’t want to disable it globally on your system.

Posted by Chris Hesik on October 28th, 2009 under C++Builder, CodeGear Debugger, Debugger, Delphi | 7 Comments »


RAD Studio 2010: TThread support for naming a thread

In my post on Thread-Specific Breakpoints, I mentioned that the Delphi RTL’s TThread class has improved support for naming threads.

Before looking at that, let’s quickly review how naming threads for the debugger works.  The concept of naming threads in Delphi and C++Builder is not new (if I remember correctly the debugger support was added in the 6.0 versions), and it was modeled after other tools that supported that same mechanism.  Basically the debugger listens for a specific exception type (one with an exception code of $406D1388) within the application being debugged.  When this exception type is raised by the application, the debugger recognizes the exception type and cracks open the structure passed to the RaiseException call to extract the thread name.  It will then apply this name to the appropriate thread (which is also determined by looking at the structure that contains the name).  The most common case is to name the thread that raises the exception, but this mechanism also supports naming any thread running within the process from any thread running within the process.  For reference, this MSDN article shows how to do this from an application.

This mechanism is also supported by other Windows debugging tools (including Visual Studio and AQTime).

In previous Delphi and C++Builder versions, you would have to provide all the code yourself to name a thread.  If you created a thread using the "Thread Object" item that appeared under either the "Delphi Files" or "C++Builder Files" section of the File | New | Other dialog box, you were given the option to name the thread you were about to create.  If, however, after the fact, you wanted to go back and name your thread, or if you had a thread that you manually created,  you were on your own to copy/paste the appropriate code into your thread object.

Now, however, the Delphi RTL has built-in support for doing this.  You can now easily name any thread using a single function call.  The TThread class now has a new method:

    class procedure NameThreadForDebugging(AThreadName: AnsiString; AThreadID: LongWord = $FFFFFFFF); static;

The simple case is to call it passing in just a string representing the name for the thread.  In that case, the debugger will name whichever thread makes the call.  If you want to name a different thread, you can do that by also passing in the OS thread ID that corresponds to the thread you want to name.  Because this is a class method and because the second parameter can be the thread id of any thread in your application, you do not even need to be within a TThread object to call it, and in fact, you can call it to name a thread even if that thread is not a TThread descendant.  Two other things to note:  first, this new method does nothing if the application is not running under a debugger (IsDebuggerPresent returns false); and second, the code that raises the exception for the debugger is wrapped with an emtpy try/except block to ensure the exception doesn’t bubble out of the NameThreadForDebugging procedure.

Even though thread naming has been around for a while, it wasn’t until this small addition was made to the RTL, that we (the IDE team) made a concerted effort to name the threads created by the IDE.  As soon as it became dead-simple to name a thread, it was a simple matter of hunting down the threads created by the IDE and adding a single call to each thread.  For TThread descendants, we just added a single call as the first line of each thread’s overridden "Execute" method.

This alone has made debugging the multi-threaded parts of the IDE much simpler.  When debugging a crash or a thread-contention issue, you used to have to double-click the various threads in the Thread Status view and then look at the Call Stack view in order to find a particular thread.  Now, with most of the critical IDE threads named, it is a simple matter of locating the thread, by name, in the Thread Status view.  And naming all our threads, has made it possible for use to effectively use Thread-Specific Breakpoints, and the new Thread Freeze/Thaw mechanism that was also introduced in Delphi 2010 and C++Builder 2010.

Posted by Chris Hesik on October 22nd, 2009 under C++Builder, CodeGear Debugger, Debugger, Delphi, IDE, RAD Studio | 5 Comments »


Debugger Tip: Another case for selective symbol table loading

A few weeks ago, I talked about a debugger feature, "Selective Symbol Table Loading", that can be used to increase performance of the debugger.  In addition to its performance benefit, this feature is also useful in other situations.  One situation, in particular, where it comes in handy, is when a single source file is shared by more than one PE Module loaded by the process you’re debugging.  It is especially useful when that shared source file contains IFDEFs so that the source is compiled differently for each PE Module.  Let’s take a look at a test case (which, I’ll admit, is a bit contrived) and see how this feature can help out in this case.

First a couple of IDE screenshots:

Figure 1

Figure 1

Figure 2

Figure 2

What we have here is a basic C++ project group that contains two DLL projects and one EXE project.  The two DLLs, both include the SharedUnit.cpp.  As you can see in Figure 1, that source file contains a single function, whose implementation is IFDEFd so that its return value depends on whether or not the conditional symbol "TEN" is defined.  The "RegDll.dll" project builds this unit without that define, while the "TenDll.dll" project builds it with "TEN" defined.  In Figure 2, you see the source for the EXE project.  All it does is dynamically load the two DLLs using the LoadLibrary Windows API call.

So, let’s say you build all three projects, and then use the debugger to step over the two LoadLibrary calls in the EXE.  If you then go and look at SharedUnit.cpp in the code editor, where would you expect the blue dots to appear?  Figure 3 shows where they appear.

Figure 3

Figure 3

As you can see, a blue dot only appears on the first return statement, even though both return statements are actually valid locations for breakpoints (they are both valid because both DLLs are loaded).   Due to some limitations in the way the debugger deals with source files that appear in more than one symbol table, when painting the blue dots in the code editor, the debugger will only see the symbols for the first DLL loaded which reports symbols for that source file.   Since TenDLL is loaded first, its symbol table wins and the blue dots for SharedUnit.cpp reflect the source for that DLL.  If RegDLL had been loaded first, then its symbol table would have won, and the blue dots would have reflected the source for that DLL.

So, what are you to do if you are running into this situation and it’s not practical to alter the PE module load order?  Let’s take a look at how Selective Symbol Table Loading can help.  Assuming that, for the moment, you only care about debugging into RegDll.dll, you can tell the debugger to temporarily ignore the symbols for TenDll.dll.  As explained in the previous post on this topic, you do this using the Symbol Tables page of the Project | Options dialog.  On that page, you can add the DLL you want ignored to the list of Modules, while leaving the "Symbol Table Path" blank (as shown in Figure 4).

Figure 4

Figure 4

Then, when you debug the EXE again, and step over the two Load Library calls, this time the blue dots shown in the SharedUnit.cpp source file reflect the symbols loaded for RegDll.dll (Figure 5).

Figure 5

Figure 5

While I’ve admitted that test case I’ve used to illustrate this feature is a bit contrived, this exact situation exists within the Delphi codebase itself.  The Delphi compiler sources (written mostly in C), can be used (with the help of many IFDEFs) to build different flavors of the compiler dll.  Back when the IDE hosted both the Delphi win32 and Delphi.net compilers, it would be possible to run into this situation when trying to debug one flavor of the compiler instead of the other (dcc100.dll vs. dcc100il.dll).  Selective Symbol Table Loading was quite handy in easing the debugging of the shared, ifdef’d source files, as you typically only cared about one compiler flavor at a time.  And although I haven’t needed this yet, I expect it to be just as handy when needing to debug the IDE-hosted versions of the MacOSX and Linux compilers that are being worked on for ProjectX.

Posted by Chris Hesik on October 19th, 2009 under C++Builder, CodeGear Debugger, Debugger, Delphi, ednfront | 3 Comments »


RAD Studio 2010: Keeping Watches (and Locals) expanded

Ever since Expandable Evaluation was added in the 2006 release, there has been a common complaint amongst Delphi and C++Builder users:  every time you step or hit a breakpoint after having expanded a Watch item or an item in the Locals view, the treeview collapses again.  The QC entry for this issue can be seen here:  http://qc.embarcadero.com/wc/qcmain.aspx?d=67560.  There have been other QC entries that have tracked this issue longer than is indicated by the date on that report, but those reports were either "private" reports, or had been marked as duplicates of 67560.

While I’m not thrilled that it took this long to fix this long-standing customer complaint, I’m happy to report that it has finally been fixed in the 2010 release.  Now, the IDE will try to preserve the expanded state of both the Watches treeview and the Locals treeview.  When a step operation completes, or you hit a breakpoint, exception, or some other stop condition in the debugger, the IDE will attempt to restore the state of those trees to the previous state.  In other words, it will try to re-expand each item that was previously expanded.  Of course it only does this for Watches or Local items that are still valid (still in scope) after the process stops.   Not only will the views restore the expanded state, they will also try to restore the scroll position;  so if you’ve scrolled either view down to see some additional data, after you step, the same data will remain scrolled into view.

In writing this blog post I noticed that the aforementioned QC entry had not been marked Fixed yet.  I’ve heard that there have been some problems with the synchronization of data between our internal bug tracking system and QualityCentral, but rather than waiting for that to get straightened out, in this case, I’ve used my powers as a QC sysop to go ahead and mark that particular issue as Fixed.

Also, if you want to see this fix in action, I demonstrated it in my CodeRage 4 session.  You can download the replay from CodeCentral at http://cc.embarcadero.com/download.aspx?id=27263.  I show this particular item around the 22:00 mark in the video.

Posted by Chris Hesik on October 6th, 2009 under C++Builder, CodeGear Debugger, Debugger, Delphi | 4 Comments »


Debugger Enhancements since Delphi 7/C++Builder 6

 Back in April of 2007, I wrote a post listing all the debugger features that have been added to Delphi and C++Builder since the Delphi 7 release.  While it was up to date at the time (the 2007 release), it has not been kept up to date with features added since then.  Rather than updating an old blog post with each new release or to write a new post for each release, I thought it would make sense to have a page here on my blog that I can update with each new release.

To that end, you can now see the complete list of features and enhancements added to the debugger since the Delphi 7 and C++Builder 6 releases.

Posted by Chris Hesik on October 5th, 2009 under C++Builder, CodeGear Debugger, Debugger, Delphi, ednfront | 2 Comments »


Debugger Tip: Increase debugger startup performance using Selective Symbol Table Loading

On occasion I get questions asking what someone can do to increase application startup time when running under the debugger.  In general, applications start up slower under the debugger since the debugger needs to monitor certain events (like modules getting loaded/unloaded, threads getting created/destroyed, exceptions that occur, etc.) and load and read symbol tables that contain the debug information for an application.

Loading symbol tables can be time consuming when the symbols tables are very large or when a lot of individual symbol tables need to be loaded.  By default, the debugger will try to load a symbol table for each module (.exe, dll, .bpl, etc.) that gets loaded into the application.

One thing you can do to speed things up when debugging is tell the debugger only load symbols for certain modules.  This feature, which we call "Selective Symbol Table Loading", was originally added for BDS2006 because loading symbol tables was especially slow for .NET assemblies.  Fortunately, this feature is quite useful for debugging native processes as well (especially for large applications that have a lot of modules).  It gives you full control over which symbol tables are loaded by the debugger when you are debugging an application.  For the purposes of this feature a “symbol table” is defined as “the set of symbols which corresponds to the code in a PE module”.  It’s important to note that each module can have a corresponding symbol table.

The Basics

The Selective Symbol Table Loading feature basically allows you to control the following things:

  • Whether or not symbols are loaded for a particular module
  • The location of the file from which to load symbols for a given module

Before describing the user interface in detail, I’d like to briefly describe the correlation between modules and their symbol table files.  This correlation is different for the two personalities supported in the IDE.  In both cases, the symbol file (if it exists) will have the same base file name as the module to which it corresponds — it is just the file extension that differs between the two personalities.

  • For Delphi executables and dlls, in the common case, there is no external symbol table file.  As described in this post, the debug symbols are actually just held in memory by the delphi compiler.  The Delphi Win32 compiler does support generating an external symbol table file for remote debugging.  In this case, the symbol table file will have a “.rsm“ extension.  In the case of packages, the symbol table will come from the .dcp file for the package (assuming the package is built with debug information).
  • For C++, the debug symbols are found in a file with a “.tds“ extension.

The User Interface

The UI for this feature is available in the Project | Options dialog under the tree node titled “Symbol Tables”.  It is also available in the Run | Parameters dialog.  It is a little complex, but with that complexity comes a whole lot of flexibility.  Following is a screen shot showing the dialog configured for debugging bds.exe:

There are two parts to the UI — the “Debug symbols search path” setting and the “Module name to Symbol table path mapping” settings.

The “Debug symbols search path” setting allows you to specify a project-specific path that the debugger should use to locate symbol table files.  Note that there is also a global path that you can set if you want to use a common symbol search path for all of your projects.  The global path appears on the "Embarcadero Debuggers" page of the Tools | Options dialog.  If all you want to do is to tell the debugger the directories it should use when searching for a symbol table file, then you should just use one of these settings.  As with all path settings in the IDE, you can specify a semi-colon-delimited list of directories for these settings.   This setting is only used if either the "Load all Symbols" checkbox or the "Load symbols for unspecified modules" checkbox is checked (see below).

The second part of the UI, the “Module name to Symbol table path mapping” settings, is where the extra flexibility comes in.  Using this list, you can tell the debugger whether or not to load a symbol table for a particular module and from where to load a particular symbol table.  There are a several rules governing this list:

  1. If "Load all symbols" is checked, then the list is ignored, and the debugger will try to load a symbol table for each module that is loaded. Alternatively, if "Load all symbols" is not checked, then the debugger will use the list of modules/paths to determine if a symbol table should be loaded.
  2. If a module appears in the list, but has an empty path associated with it, the debugger will not try to load a symbol table for that module
  3. If "Load symbols for unspecified modules" is checked, then the debugger will try to load a symbol table for each module that is not listed.
  4. The list of modules supports wildcards — if a loaded module’s name matches the pattern of an item in the list, the debugger will use that item’s "Symbol Table Path" for the loaded module.
  5. The order of the list of modules is important.  When a module is loaded by the debugged process, the list of modules is searched in order (top to bottom) for an item that matches the module name (either an exact match or a wildcard match).  As soon as it encounters a match, it uses that item’s "Symbol Table Path".

In Action

Let’s look at how the settings shown in the screenshot come into play when I debug the IDE in itself.

The first case we’ll look at are how two modules bordbk140.dll and bordbk140n.dll are handled.  When bordbk140.dll gets loaded, the debugger searches the list and finds the first matching entry.  In this case, it finds "bordbk???.dll".  Since that item does not have a path specified, then the debugger will not attempt to load a symbol table for that module.  When bordbk140N.dll gets loaded, the debugger again searches the list to find the first matching entry.  In this case, it finds "bordbk*.dll".  Since that entry does have a path, it will attempt to load the symbol table from the specified path.  Note, however, that if the order of the two aforementioned entries were reveresed, then symbol tables for both modules would have been loaded (since "bordbk*.dll" matches both modules).

The second case we’ll look at is how the module "startpageide140.bpl" will be handled.  Since none of the items in the list match that item and since the "Load symbols for unspecified modules" checkbox is not checked, no symbols will be loaded for that module.  If I decide later that I want to be able to debug that package, then I can do one of three things:  I can check the "Load all symbols" checkbox, and then the debugger will attempt to load all symbols; I can add "startpageide140.bpl" to the list with a valid path to its symbol table; or I can check the "Load symbols for unspecified modules" checkbox.  After doing any of these, the next time I debug, the debugger will attempt to load the symbol table for that module.

At the start of this article, I mentioned that this feature can be used to decrease the amount of time it takes to start an application under the debugger.  As a quick illustration, I just did some quick stopwatch timing on one of my machines, measuring how long it takes for the IDE to start up under the debugger.  With the configuration I was testing, my IDE loaded 244 modules.  Without any custom symbol table settings, the debugger loaded symbol tables for 120 of those modules (so, nearly half).  It took about 18 seconds for the debugged IDE to startup.  Using the settings shown in the screenshot above, the debugger loaded 35 symbol tables, and the time was cut to about 13 seconds (eyeballing the list of symbol tables loaded, it looks like the largest symbol tables are still loaded with that list).  Changing the settings so that no symbol tables are loaded, the debugged IDE starts up in about 10 seconds.  For reference, using "Run Without Debugging" so that the debugger is not involved at all reduced the startup time to about 7 seconds.

While the overall time saved may not seem significant, if you think about how many times a day (or week, month, or year…) you start your app under the debugger, the time saved can start to add up.  Of course the actual performance increase you see will depend heavily on how many modules with symbol tables are loaded by your application, and for how many of those it makes sense to skip loading debug symbols on a regular basis.

Posted by Chris Hesik on September 22nd, 2009 under C++Builder, Debugger, Delphi, Uncategorized | 5 Comments »


Deciphering the various "Debug information" settings in a Delphi project

Those of you who have used Delphi for a while may have noticed three similar sounding settings in the Project | Options dialog, all of which seem related to Debug Information.

In Delphi 2009 and 2010, on the "Compiling" page of the Project Options dialog there is a setting "Debug information".  On the "Linking" page, there are two related settings: "Debug information" and "Include remote debug symbols".

In older versions (I checked both Delphi 7 and Delphi 2006 while writing this), there is a "Debug information" setting on the "Compiler" page, and the "Linker" page has "Include TD32 debug info" and "Include remote debug symbols".

Let’s take a look at these three settings and discuss what each does.  For the purposes of this discussion, we’ll focus on the UI and using these settings in the Delphi 2010 IDE.

Project | Options | Compiling | Debug information

This setting is on by Default in the Debug configuration.  Of the three aforementioned settings, this is the only setting you need if you want to build and debug your application in the IDE.  This setting will increase the size of .dcu files (and .dcp files when building packages), but doesn’t actually affect .exe (or .bpl, .dll, etc.) size — the symbol table used by the debugger will be kept in memory after compiling and linking your application in the IDE, thus obviating the need to keep the symbol table elsewhere.  After building your project with this setting, you can simply run the application in the debugger and the in-memory symbol table will be used by the debugger.

Compiler command line switch:  -$D+.   Compiler Directive: {$DEBUGINFO ON}

Project | Options | Linking | Debug information

This setting is off by Default in the Debug configuation.  This setting tells the Delphi linker that you want C++-style symbols to be included in the final image produced (i.e. the .exe, .dll, .bpl, etc.).  This used to be called "TD32 debug info", because the now-obsolete TD32 standalone debugger required C++-style symbols.  There are other third-party tools that require this type of debug information (AQTime for instance).  In general, unless you are using a third-party tool that needs this, you’ll want to leave the setting unchecked.  This setting will slow down the linking phase a bit and make your .exe much bigger.

As a side note (and I don’t recommend this), if you want to debug your Delphi applications using the C++ expression evaluator in the integrated debugger, you can use this setting.  Then, if you close your Delphi project and use the Run | Load Process menu item to load your .exe into the debugger, it will use the C++ expression evaluator rather than the Delphi evaluator (since the only symbols the debugger will see are the C++-style symbols).

One final note on this setting:  if you build your project with this setting and decide later that you want to remove the embedded debug information, you can use the "tdstrp32.exe" command line utility to strip out the debug info (and optionally save it into a .tds file).  I’ve just noticed is that the tdstrp32.exe utility does not like files without a .exe or .dll extension (for instance packages which have a .bpl extension).  If you want to use it on a package, it appears to be sufficient to temporarily rename the package to a .dll, run tdstrp32.exe on the renamed .dll and then rename the file back to a .bpl.

Compiler command line switch:  -V

Project | Options | Linking | Include remote debug symbols

This setting is off by Default in the Debug configuration.  This setting tells the Delphi linker to create a separate file that contains the Delphi-style debug information.  The file generated will have the same base name as the .exe (or .dll, .bpl, etc.), and a ".rsm" extension.  This setting will also slow down the linking phase a bit.

This symbol table file is meant to be used with the remote debugger, since when you use the remote debugger, the copy of the compiler used for debugging on the remote machine will not have the in-memory symbol table mentioned earlier.  The .rsm file can also be used to load symbols if you use the Run | Load Process menu item to load an .exe file into the debugger.  Doing this will allow you to debug using the Delphi evaluator rather than the C++ evaluator.   Also, when the debugger is used to attach to an already-running process, ".rsm" files will be used (if available) to load debug information for the process.

Compiler command line switch:  -VR

[Updated to include the equivalent compiler command line switches]

Posted by Chris Hesik on September 15th, 2009 under Debugger, Delphi, ednfront | 8 Comments »


RAD Studio 2010 ToolsAPI: Plugging into the code editor space in the IDE

In an earlier post, I listed the major changes made to the ToolsAPI for the RAD Studio 2010 release.  In the second bullet item in that post, I mentioned that I would provide a simple example that showed how to use the new interfaces to add UI into the code editor space in the IDE.  I’ve just uploaded the simple example to CodeCentral.  It can be found at the following URL: http://cc.embarcadero.com/Item/27315.

For reference, here is the Description of the CodeCentral submission: 

This is a simple package that uses new ToolsAPI interfaces introduced in the 2010 release to add both top-level and bottom-level tabs into the code editor view in the IDE.

The pertinent interfaces are:

INTACustomEditorView
INTACustomEditorViewState
INTACustomEditorViewStatusPanel
INTACustomEditorSubView
IOTAEditorViewServices
INTAEditorServices

Open the project in the Delphi 2010 IDE, and install the package (right click the project in the Project Manager and select the "Install" menu item).

After installing the package you will see the following:

Under the main IDE View menu, there will be a menu item called "Something Cool", that when selected, does something that really isn’t all that cool <g>. It opens a top-level editor tab with a colorful bouncing ball…..

Also, when you open a file that is saved on disk, there will be an additional tab at the bottom of the editor (along side the Code, Design, and History tabs). It is called "OS File Information" and when you select it, you see a frame that displays the Creation time, Modified time, and the File Size. There is also a combo box to select between different files contained in the module (.pas, .dfm, etc). This tab does not use the virtual file system, so it will not show correct info for things not saved to disk.

Posted by Chris Hesik on September 11th, 2009 under C++Builder, Delphi, IDE, RAD Studio, ToolsAPI, ednfront | 4 Comments »


What’s new in the Delphi and C++Builder Debugger?

Want to find out?  Be sure to sign up for CodeRage and check out my session.  I just put the final touches on my presentation today.  It’s nearly 35 minutes of non-stop demos showing many of the new debugger features in Delphi 2010 and C++Builder 2010.  Several of the features have been blogged about already (by myself and others), but there are many things shown in the session that I haven’t seen mentioned yet, plus it’s always useful to see some features in action rather than just reading about them.

My session will debut on Tuesday and then be repeated on Friday.

Looks like there are plenty of great sessions throughout the week.

Posted by Chris Hesik on September 1st, 2009 under C++Builder, Debugger, Delphi, RAD Studio | 4 Comments »




Server Response from: blog1.codegear.com