Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2024-11

Separate debug info for release builds

8 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Henry Vermaak

When I add -Xg, the compiler writes the debug info into a separate .dbg file and adds a .gnu_debuglink section so the debugger can find the info. So far so good (and simpler than having the use objcopy).

The size of the binary is much larger than building without debug info, though. E.g. with -O2 it goes from 35K to 188K.

When I do exactly the same with gcc (via objcopy and strip), there's almost no difference between the stripped binary and a binary built without debugging info (even diffing objdump output).

Can anyone explain why this is?

Henry

Reply by email

Martin Frb
to Henry Vermaak
Henry Vermaak wrote 13 lines
When I add -Xg, the compiler writes the debug info into a separate .dbg file and adds a .gnu_debuglink section so the debugger can find the info. So far so good (and simpler than having the use objcopy). The size of the binary is much larger than building without debug info, though. E.g. with -O2 it goes from 35K to 188K. When I do exactly the same with gcc (via objcopy and strip), there's almost no difference between the stripped binary and a binary built without debugging info (even diffing objdump output). Can anyone explain why this is?

I may not have all the factors, but O- O1 and O2 are not debug info, but optimization.
So they generate different code, and that leads to different exe sizes.

I am not sure it explains the full size diff you get. Depending on the code, you may have a difference due to smart linking.

To check if any other symbols (e.g. those needed for the linker) differ between the various builds, you can try to use strip, and that shows you how much actually remains for the app-code/data.

-----------
Then of course there are a few problems that make the whole thing more complex.

gcc can (afaik) generate working debug info for optimized code.

fpc does not. If data is in registers then fpc does not represent that (at least not always correctly) in the debug info. So data will be show incorrect in the debugger.
fpc does not generate line info for inlined code. And I don't know how well/exact line info is for different level of optimization in different fpc versions.
And some versions of fpc (or maybe some linkers?) caused broken debug info when smart linking was enabled.

So basically, if you want to debug, then you can't really optimize. Or at least you must check exactly what is supported by the version of fpc you use.

Reply by email

Martin Frb
to Martin Frb
Martin Frb wrote 8 lines
On 01/11/2024 15:59, Henry Vermaak via fpc-pascal wrote: > When I add -Xg, the compiler writes the debug info into a separate > .dbg file and adds a .gnu_debuglink section so the debugger can find > the info. So far so good (and simpler than having the use objcopy). > > The size of the binary is much larger than building without debug > info, though. E.g. with -O2 it goes from 35K to 188K. >

Ok, I misread that.

Thinking you change it to O2 for one of the builds only...

------------
Another factor could be that debug info affects smartlinking. Or leaves symbols for the linker in sections that are shared with non-debug info.

But I don't know either of that.

Afaik external debug info is created at the end by using objcopy or similar to split the one big exe.

In theory therefore, debug info could have created symbols in sections used by the linker, and left behind.
Also debug info may in the worst case have referred code and prevented smart linking.

Again, neither of those are know by me.

Reply by email

Henry Vermaak
to Martin Frb: I may not have all the factors, but O- O1 and O2 are not debug info, but optimization. So…
Martin Frb wrote
On 01/11/2024 15:59, Henry Vermaak via fpc-pascal wrote: I may not have all the factors, but O- O1 and O2 are not debug info, but optimization. So they generate different code, and that leads to different exe sizes.

I understand that. I was comparing a build with (-O2) to a build with (-O2 -g -Xg). The -Xg isn't particularly relevant here, building with (-O2 -g) then stripping leaves you with a binary that's much larger than without -g. This works fine with gcc and the binaries are the same size after stripping.

I am not sure it explains the full size diff you get. Depending on the code, you may have a difference due to smart linking. To check if any other symbols (e.g. those needed for the linker) differ between the various builds, you can try to use strip, and that shows you how much actually remains for the app-code/data.

All binaries are fully stripped.

Show quoted text 10 lines
Then of course there are a few problems that make the whole thing more complex. gcc can (afaik) generate working debug info for optimized code. fpc does not. If data is in registers then fpc does not represent that (at least not always correctly) in the debug info. So data will be show incorrect in the debugger. fpc does not generate line info for inlined code. And I don't know how well/exact line info is for different level of optimization in different fpc versions. And some versions of fpc (or maybe some linkers?) caused broken debug info when smart linking was enabled. So basically, if you want to debug, then you can't really optimize. Or at least you must check exactly what is supported by the version of fpc you use.

Sure, I understand that optimising messes up debugging, I just want a stack trace that points me in the general direction of what's going wrong (and that works OK in simple tests). Except if fpc ignores -O2 somehow when I pair it with -g?

Henry

Reply by email

Henry Vermaak
to Henry Vermaak
Henry Vermaak wrote 7 lines
On Fri, 1 Nov 2024 at 15:49, Martin Frb via fpc-pascal wrote: > Another factor could be that debug info affects smartlinking. Or leaves symbols for the linker in sections that are shared with non-debug info. This seems to be the problem. I think adding -g turns off smartlinking, which then blows up the binary size, I've just tested with and without (-CX -XX).

Looks like I can "fix" this by passing --gc-sections to ld.

Are there any fpc devs that can comment on why smart linking gets switched off when -g is passed?

Henry

Reply by email

Nikolay Nikolov
to Henry Vermaak
Henry Vermaak wrote 11 lines
On Fri, 1 Nov 2024 at 16:12, Henry Vermaak wrote: > On Fri, 1 Nov 2024 at 15:49, Martin Frb via fpc-pascal > wrote: >> Another factor could be that debug info affects smartlinking. Or leaves symbols for the linker in sections that are shared with non-debug info. > This seems to be the problem. I think adding -g turns off > smartlinking, which then blows up the binary size, I've just tested > with and without (-CX -XX). Looks like I can "fix" this by passing --gc-sections to ld. Are there any fpc devs that can comment on why smart linking gets switched off when -g is passed?

Because Free Pascal doesn't support smartlinking+debug info on most platforms. The only exception is macOS, where it is actually supported. Adding --gc-sections to the linker on other platforms will probably result in broken debug info and is not guaranteed to work. Of course, you are encouraged to try it and test it, and see if it works, but it probably doesn't.

Best regards,

Nikolay

Reply by email

Henry Vermaak
to Nikolay Nikolov
Nikolay Nikolov wrote
Because Free Pascal doesn't support smartlinking+debug info on most platforms. The only exception is macOS, where it is actually supported.

Do you know why it's not supported? What are the barriers to supporting it?

It's quite common to ship an optimised build with separate debug info so either the user can add them later to get a useful backtrace, or the developer can convert addresses to lines in gdb (info line *0x1234). Debian's debug packages work like this.

Adding --gc-sections to the linker on other platforms will probably result in broken debug info and is not guaranteed to work. Of course, you are encouraged to try it and test it, and see if it works, but it probably doesn't.

It works fine in a simple example, I'll test for larger builds. I'd be hesitant to ship something that isn't supported, though. That means I'll have to roll separate debug installers, which is a pain.

Henry

Reply by email