Recent

Author Topic: How to get line numbers in stack trace?  (Read 2826 times)

olly

  • New Member
  • *
  • Posts: 42
How to get line numbers in stack trace?
« on: July 13, 2020, 06:39:03 pm »
DumpCallStack (see attachment) works on any other platform, but on macOS x64_86 I just get addresses.

"Generate info for the debugger" and "Display line numbers (-gl)" are both enabled.
However regardless if "Generate info for debugger" is enabled or disabled the binary size remains the same.

However, when cocoa (the widgetset) encounters a exception it produces function names as seen here: https://forum.lazarus.freepascal.org/index.php/topic,50455.msg368291.html#msg368291.

Is this a bug, or is there something I'm doing wrong?

Cyrax

  • Hero Member
  • *****
  • Posts: 836
Re: How to get line numbers in stack trace?
« Reply #1 on: July 13, 2020, 06:49:48 pm »
Which FPC version you are using?

olly

  • New Member
  • *
  • Posts: 42
Re: How to get line numbers in stack trace?
« Reply #2 on: July 13, 2020, 06:58:27 pm »
Which FPC version you are using?

Sorry, 3.2.0 and this also happened in 3.0.4.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9754
  • Debugger - SynEdit - and more
    • wiki
Re: How to get line numbers in stack trace?
« Reply #3 on: July 13, 2020, 07:23:33 pm »
I don't know if this is still accurate (or was so in first).
But afaik  FPC only has a unit to support STABS (-gs) to generate linenumber in stack trace dumped by the executable.
I don't know if it is still possible to compile with STABS on Mac.

However: IF you use dwarf, you may be able to use the "leak and traces" view. (May require Lazarus 2.1 / trunk).
Package: LeakView.
Paste the trace into the leak-view, and press the button "resolve". It will prompt for the exe. If that exe was build with dwarf, then it should find the line-numbers for the addresses.
(I only tested that on Windows)


olly

  • New Member
  • *
  • Posts: 42
Re: How to get line numbers in stack trace?
« Reply #4 on: July 13, 2020, 07:54:48 pm »
...

Resolving in leaks and traces seems to work (gives no errors) but still only gives addresses.
I tried all the Dwarf options (Dwarf with sets, Dwarf 2, Dwarf 3).

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9754
  • Debugger - SynEdit - and more
    • wiki
Re: How to get line numbers in stack trace?
« Reply #5 on: July 13, 2020, 08:30:25 pm »
Resolving in leaks and traces seems to work (gives no errors) but still only gives addresses.
I tried all the Dwarf options (Dwarf with sets, Dwarf 2, Dwarf 3).

Did you try with Lazarus trunk?

IIRC Lazarus 2.0.x (including 2.0.10) uses the dwarf reader from the fpc unit. But if I am right that does not exist on Mac.

In Lazarus trunk the leak view uses the dwarf reader from fpdebug. And that works at least when using the lldb+fpdebug on Mac. It *should* also work in leak view. (unless leak view gets the file wrong) not sure if you must resolve against the bundle, or the exe inside the bundle)


Dwarf 2/3 or with-sets only affects watches in the debugger. It has no impact on addresses in leakview.

olly

  • New Member
  • *
  • Posts: 42
Re: How to get line numbers in stack trace?
« Reply #6 on: July 13, 2020, 11:23:29 pm »
...

Trunk worked, thanks!

Finally, I have no plans of tackling this but can fpDebug be used to fix the orginal issue?

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9754
  • Debugger - SynEdit - and more
    • wiki
Re: How to get line numbers in stack trace?
« Reply #7 on: July 13, 2020, 11:56:50 pm »
Finally, I have no plans of tackling this but can fpDebug be used to fix the orginal issue?
You mean, original issue = "fpc does not print the line numbers"?

No fpdebug will not help there.

Well, I am not part of the compiler team, but this is my understanding.

Fpc has for each platform (well most....) a unit with a minimal debug info (dwarf and/or stabs) reader.
This reader is
1) kept as small as possible (otherwise the end user app get a lot of extra code)
2) written to work with minimal resource requirement. I.e. ideally a very small statically allocated bit of memory.

The 2nd part is important. Stack dumps may happen after an app crashed. The memory management may be corrupted. If you try to get memory, then that would crash the stack dumper.... not helpful.

FpDebug is made for a full blown debugger. It uses memory as it sees fit. And of course it can do more that just read line info, and separating this out would be quite some work.


Of course it depends on the use case....

If you want the stack dump only for your debug builds, then you would not mind if some more code is added.

And for release builds, you should actually (if anything at all) only dump addresses. Your clients do not need the unit names. And you can use leak view to resolve the addresses.
(you need to build your release with debug info, keep a copy, and use strip on the version you ship)


Also note: Even on platform where fpc dumps the line numbers, it has safety nets build in (as again, the app may have crashed, making it unsafe for any code to do anything).
So if it comes to any line, that simple has no line number, it assumes there may be a problem, and it will stop printing line numbers, and do address only for the rest. (At least that is what it used to be).

The leak view, will continue looking, and pick up, if there is more info further down the stack.


Finally, for errors it is best to try and stop them in the debugger.
Of course mem leaks, you need the dump

If you want to collect a lot of traces, because you do not yet know what/where the error is, and you want the last trace before an error (crash/exception) happens... => the debugger can do that.
- Set a breakpoint.
- Go to the breakpoints properties (right click the breakpoint)
- uncheck "break"
- check take a snapshot
This will record the top 5 frames, if you need more, keep the stack window open.

The recorded snapshots can be accessed via menu: view > Debugger > history.
Double click a history entry to activate it, and the stack window will show the history.
https://wiki.lazarus.freepascal.org/IDE_Window:_Debug_History

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9754
  • Debugger - SynEdit - and more
    • wiki
Re: How to get line numbers in stack trace?
« Reply #8 on: July 14, 2020, 12:02:47 am »
One more node: I have not actually checked your code. (the dumpstack you use).

But I recall from previous posts that the issue exists in fpc code.

For testing, compile with -gh -gl
TObject.Create;
and do not free it, so a leak will be reported.

If the leak report should have unitnames/lines, then the issue is in your code. Otherwise its fpc.


The function names in the other thread where not listed by fpc code.
THey were produced by a debugger, or by the OS itself acting as debugger.

Fpc would have merely added the dwarf info. With that info any debugger can lookup the addresses.

And with that info leak view / fpdebug looks up the addresses...
And stack dump code in the app, would do that too, if correctly implemented and available for Mac.
The result of that build in lookup is "unitname linenumber". No function names.
« Last Edit: July 14, 2020, 12:08:53 am by Martin_fr »

olly

  • New Member
  • *
  • Posts: 42
Re: How to get line numbers in stack trace?
« Reply #9 on: July 14, 2020, 12:53:41 am »
Thanks for the replies.

DumpCallStack is from:
https://wiki.freepascal.org/Logging_exceptions#Dump_current_call_stack

My use case for this is that I distribute a optional debug binary (with lineinfo) which on exception the stack is written to disk.

This works perfectly on all platforms other from macOS x64_86 where just addresses are returned. I now know I can resolve using leaks and traces, however I was curious on how hard a fix would be.

Also leaking a TObject with -gh -gl does not return any lineinfo.

Code: [Select]
Call trace for block $0000000100DB0560 size 8
  $00000001001FB7E7
  $0000000100294559
  $0000000100294D1A
  $000000010029446A
  $0000000100011B0E
  $00000001001EDE69
  $00000001001DAA1A
  $00000001001DAB1E
  $00000001002ACC9D
  $00000001002B2DCF
  $00007FFF457D5A43
  $00007FFF4527B53F
  $00007FFF4527B467
  $00007FFF4527B36D
  $00007FFF452BC688
  $00007FFF45279BD6
« Last Edit: July 14, 2020, 01:01:18 am by olly »

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9754
  • Debugger - SynEdit - and more
    • wiki
Re: How to get line numbers in stack trace?
« Reply #10 on: July 14, 2020, 01:42:00 am »
Well "how hard a fix would be"

My best guess:
The dwarf decoding is the same on all platforms (I know this, its in FpDebug too)
IIRC unit infodwarf

So the code for decoding could be taken from any platform. (at least most of it).
The difference is reading it from the exe file or bundle.

On each platform you need the following  (assuming you do NOT select "external debug info" which is even one more step)
- find the file of the running exe on the disk.
  On Mac, that may be: find the entire bundle, as dwarf info is *split* over several files in the bundle.
- Open the file, and read it according to the fileformat
  I.e. on Windows its a PE file, on Linux ELF => they start with a header, which you can decode, and eventually find where the dwarf info is.
- Once you know the location of the dwarf info => read it => hand it to the decoder.
  Might be a bit extra on Mac, as (IIRC) the info is split accross several files.

The decoder may need to jump to other locations in the info.
Remember it works on low mem, so it constantly needs to load different bits.
So the decoder must at least be adapted to work with the loader.



If its for your own exe, you can of course embed the entire fpdebug. then all you need is the full path + filename of the bundle that is running.
leakview is only a handful of units. You should be able to find the few calls to fpdebug.

Of course that only works, if at the very least your apps memory manager is alive and healthy (not guaranteed, if you had an uncontrolled crash)
« Last Edit: July 14, 2020, 01:45:34 am by Martin_fr »

olly

  • New Member
  • *
  • Posts: 42
Re: How to get line numbers in stack trace?
« Reply #11 on: July 14, 2020, 02:45:27 am »
Looks like there is already a issue for this since 2017. https://bugs.freepascal.org/view.php?id=32775

 

TinyPortal © 2005-2018