PDA

View Full Version : My new, working lineinfo replacement (works ith dlls!)



Chebmaster
08-02-2008, 07:21 PM
The project page with the download link:
http://www.chebmaster.narod.ru/soft/libs_chelinfo_e.html

Test:

{$ifdef windows}
{$apptype gui}
{$endif}
program chelinfo_test;

{note: DON'T FORGET to compile your program with the -gw key
Lazarus: you must type it in
Project -> Compiler Options -> Other -> User parameters
}

uses
Classes, SysUtils, un_lineinfo;

begin
InitLineInfo(nil);
byte(nil^):= 0; // go BOOM!
end.

[cheb@localhost]$ ./chelinfo_test
An unhandled exception occurred at $080481E2 :
EAccessViolation : Access violation
$080481E2, line 16 of chelinfo_test.pp in ./chelinfo_test



Details:

unit un_lineinfo;

interface

uses
SysUtils, Classes;

procedure GetLineInfo
(addr: pointer; var exe, src: ansistring; var line, column: integer);
{
The format of returned information:
"exe" *always* receives the full name of the executable file
(the main exe or one of dlls it uses) the addr belongs to.
In Linux, it returns the real file name, with all symlinks
resolved.
"line" can be negative, which means no line info has been found
for this address. See LineInfoError (below) for details.
"src" returns the source file name. It either doesn't or does
contain a full path. If the source was in the same directory
as the program itself, there will be no path. If the source
was in the different directory, there will be a full path
(for the moment when the program was compiled, NOT for the
current location of that source).
"column" is positive ONLY when there is more than one address
stored for the same source line. FreePascal generates this
on VERY rare occasions, mostly for the arithmetic formulas
spanning several lines. So most of the time column will
receive -1.
}

function InitLineInfo(someaddr: pointer): longbool;
{
This function is called by GetLineInfo() anyway if it doesnt't
fid a loaded line info for the executable to which the
requested addres belongs.
Also installs the custom BackTraceStr handler.

Input:
someaddr is adress of any function that belongs to the executable
you want to pre-load the line info for. For example, a function
exported from a dll.
If you pass NIL, it will load loads the line info for the
executable it belongs to.

Output:
Returns false if it failed to load the line info for the particular
executable. In this case look LineInfoError for explanation
Returns true if the line info for the particular executable is loaded ok.
Returns true and does nothing if line info for that executable is
already loaded.
}

procedure GetModuleByAddr
(addr: pointer; var baseaddr: pointer; var filename: string);
{
This function allows you to know which executable (i.e. the main exe
or one of the dlls loaded by it) owns this part of the virtual
addres space.
baseaddr receives the exe/dll base address
(always NIL for the main exe in Linux).
The mechnaism is made with possibility of a DLL relocation
in mind, but that particular feature is untested.
This function is used by GetLineInfo() to determine which executable
to load line the info from.
}


var
LineInfoError: WideString = '';

implementation
....

arthurprs
08-02-2008, 08:08 PM
how can i have retrieve this kind of info with delphi?

JSoftware
08-02-2008, 10:20 PM
You probably can't. Utilizing hacks you can include function and class names but for everyday projects I wouldn't recommend it.

Chebmasters code probably utilises gdb or dwarf information which currently only fpc generates AFAIK(!!)

Chebmaster
09-02-2008, 06:42 AM
how can i have retrieve this kind of info with delphi?
...
You probably can't.
There *must* be something, as I clearly remember Delphi-generated programs returning such details in their error messages. And without any shamanistic dances like this one. I just don't know how. But it should be there. Try searching the delphi-specific forums.


Chebmasters code probably utilises gdb or dwarf information which currently only fpc generates AFAIK(!!)
That's true, it uses part of the dwarf information (the line info).

I just took two modules from FreePascal RTL - they were there, they just didn't work. I modified them some and added my own code for DLL support.

The lnfodwrf.pp had an almost working dwarf line info parser and ELF extractor, the lineinfo.pp had a working PE extractor (but tried to search for the old debugging info format that FPC doesn't generate anymore)

By the way, there are limitations. The line info is generated and stored per unit, so it would be available only for those units compiled with the -gw key.
The standard RTL units don't have such info.
So, if exception is raised in one of the standard classes (for example, you try to create a stream with invalid file name) - you'll get "no debug info is available for this address".

On the plus side, it does *always* find the executable name, be it your own exe or kernel32.dll - that's the power of VirtualQuery() (win32) and dladdr() (unix)

Thus, it can retrieve the line info even for a dll compiled in c - if it has that info.

Setharian
09-02-2008, 07:34 AM
With Delphi you can either use TD32 debug information or MAP files. TD32 is a modified version of CodeView debug information. Normally they are not generated, both options must be set in project settings. Be warned though, TD32 debug information increases the size of the executable/library substantially. JCL has classes/functions to work with TD32, MAP files and their own packed debug info format (JDBG). Problem with JCL like with many large libraries is that you have to include a lot of stuff in your project which normally wouldn't be necessary.

Chebmaster
09-02-2008, 10:48 AM
I updated it, now generates/uses a compressed external line info, thanks to the zstream module.

Chebmaster
09-02-2008, 12:14 PM
I updated it, now generates/uses a compressed external line info, thanks to the zstream module.

Chebmaster
10-02-2008, 01:00 AM
An important note: brutalstrip works incorrectly, it screws your exe files and they won't run.
But!
UPX'ing fixes them!

Chebmaster
12-04-2008, 01:18 PM
12 apr. 2008: update. Corrected a bug in brutalstrip, now doesn't cut out the .reloc section from the dlls.

A bit on the funny side: I performed some experimenting with the GetErrorMode() WinApi function (should be available from kernel32 in WinXP and higher). The WinXP just didn't load this function (GetProcAddress() returned nil). Wine, on the other hand gave me this:


EControlC at 602E317Ch

(no debug info is available for this address;

The line info section not found in the PE file.)

in c:\windows\system32\ntdll.dll

Control-C hit

Now I wonder what the Ctrl-C has to do with my attempt to call the GetErrorMode() function. :shock:

JernejL
12-04-2008, 06:52 PM
Now I wonder what the Ctrl-C has to do with my attempt to call the GetErrorMode() function. :shock:

CTRL-C sends console aps a terminate message.. in windows console apps when they aren't accepting input, and in unix-es.

JSoftware
12-04-2008, 07:20 PM
Actually MSDN says that it's only available on Vista and Windows Server 2008
http://msdn2.microsoft.com/en-us/library/ms679355(VS.85).aspx

marcov
15-04-2008, 09:21 AM
With Delphi you can either use TD32 debug information or MAP files. TD32 is a modified version of CodeView debug information. Normally they are not generated, both options must be set in project settings. Be warned though, TD32 debug information increases the size of the executable/library substantially. JCL has classes/functions to work with TD32, MAP files and their own packed debug info format (JDBG). Problem with JCL like with many large libraries is that you have to include a lot of stuff in your project which normally wouldn't be necessary.

Note that JCL largely compiles now (SVN JCL with SVN FPC). Remaining problems are mainly in the packages and TD32 area.

The only other exception is "implements" delegation

marcov
14-05-2008, 08:18 AM
Have a look at unit syncobjs.