gdb: Incorrect stack unwinding if compressed debug info is used

Vladimir Simonov sv@sw.ru
Thu Feb 3 16:51:00 GMT 2011


On 02/02/2011 10:55 PM, Paul Pluzhnikov wrote:
> On Mon, Jan 31, 2011 at 7:42 AM, Vladimir Simonov<sv@sw.ru>  wrote:
>
>> If I create -Od -g3 executable with -Wl,compressed-debug-sections=zlib
>
> What is '-Od' ?
>
> And you mean '-Wl,--compress-debug-sections=zlib', not
> '-Wl,compressed-debug-sections=zlib'
Sorry, to the end of day cl/gcc options are messed in my head.
"-g -O0" are used as gcc options, "objcopy --compress-debug-sections --only-keep-debug"
is used to compress debug info.

You can see build procedure in attached b.sh file.

>
>> using gold linker or compress debug-info via objcopy I have problems with
>> local variables and bacttraces in gdb.
>
> Can you construct a small example showing the problem? I haven't been able
> to reproduce it.
>
>> Something like this:
>> gdb: bt
>> ....
>> #11 0xb2356a74 in Core::WorkerImpl::WorkerThread (this=Could not find
>> the frame base for "Core::WorkerImpl::WorkerThread()".
>> )
>> ....
>>
>> I've spend some time and, looks like, found the problem. It is in
>> dwarf2_symbol_mark_computed function (dwarf2read.c). Check
>> "DW_UNSND (attr)<  dwarf2_per_objfile->loc.size"
>> is incorrect if compressed section is used. In this case
>> loc.size contains compressed section size, not decompressed one.
>> It happens if the section has not been read via dwarf2_read_section yet.
>> But dwarf2_locate_sections has been done.
>
> I am curious how your GDB avoids dwarf2_read_section(). As far as I can
> tell, it should always be called (indirectly) by dwarf2_initialize_objfile().
Please see gdb_old_log - session of debug original gdb using real
program. "b dwarf2read.c:14367" means breakpoint in the head of
dwarf2_symbol_mark_computed.
When break is reached
(gdb) p dwarf2_per_objfile->loc
$1 = {asection = 0x91effc0, buffer = 0x0, size = 56165, was_mmapped = 0,
   readin = 0}
(gdb) p (attr)->u.unsnd
$2 = 83336
You can see:
1. dwarf2_per_objfile->loc is not read (readin = 0)
2. (attr)->u.unsnd > dwarf2_per_objfile->loc.size
As result the code goes into lowest part of dwarf2_symbol_mark_computed,
complaint and set baton->size = 0, baton->data = 0.

gdb_debug_log - session of debug patched gdb using dbg_info_test.
In it we see that _real_ section read will be done
if check "DW_UNSND (attr)<  dwarf2_per_objfile->loc.size" is _passed_.

#0  dwarf2_read_section (objfile=0x849a2c8, info=0x849eed0)
#1  0x081ac376 in fill_in_loclist_baton (cu=0x8491130, baton=0x84a7354,
#2  0x081ac5a7 in dwarf2_symbol_mark_computed (attr=0x84a3328, sym=0x84a7328, cu=0x8491130)
...
This answers your curiosity -  GDB avoids dwarf2_read_section
because of incorrect (for compressed sections)
"DW_UNSND (attr)<  dwarf2_per_objfile->loc.size" check.

Unfortunately I was not able to force  (attr)->u.unsnd
to be greater than compressed size in simple example.
But hope above analysis unveils the problem.

In real life it leads to situation when if you are unlucky
and set breakpoint on function which attr outside of loc.size
you'll never see its local variables in current debug session.

>
>> As result symbols not passed above verification are left with
>> size==0 and data==NULL after dwarf2_symbol_mark_computed function.
>>
>> The patch idea is to introduce uncompressed_size field in
>> struct dwarf2_section_info. And fill it in dwarf2_locate_sections.
>> Check in dwarf2_symbol_mark_computed function takes into
>> account uncompressed_size. The patch is quite large cause I
>> try to avoid code duplication with zlib_decompress section.
>
>
> Assuming the patch makes sense (which I am not yet convinced) ...
>
> +static void
> +fill_dwarf2_section_info (struct dwarf2_section_info* info,
> +			  bfd *abfd, asection *sectp)
> +{
> +  bfd_size_type size;
> +
> +  info->asection = sectp;
> +  info->size = bfd_get_section_size (sectp);
> +  info->uncompressed_size = 0;
> +  if (!is_compressed_section_name (sectp->name))
> +    return;
> +  read_uncompressed_size (abfd, sectp,&info->uncompressed_size);
> +}
>
> Would it make sense to just set uncompressed_size to size if the section
> is not compressed? I think that would simplify the patch a bit.
>
> +      fill_dwarf2_section_info(&dwarf2_per_objfile->info, abfd, sectp);
>
> Missing space before '('.
>
> Your patch is also missing ChangeLog entry.
Thank you for comments.
Attaching new version of the patch.

Regards
Vladimir Simonov
-------------- next part --------------
A non-text attachment was scrubbed...
Name: b.sh
Type: application/x-sh
Size: 468 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/gdb-patches/attachments/20110203/0bae1668/attachment.sh>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: dbg_info_test.c
URL: <http://sourceware.org/pipermail/gdb-patches/attachments/20110203/0bae1668/attachment.c>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: gdb_old_log
URL: <http://sourceware.org/pipermail/gdb-patches/attachments/20110203/0bae1668/attachment.ksh>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: gdb_debug_log
URL: <http://sourceware.org/pipermail/gdb-patches/attachments/20110203/0bae1668/attachment-0001.ksh>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: gdb-7.2-compressed-section-4.patch
URL: <http://sourceware.org/pipermail/gdb-patches/attachments/20110203/0bae1668/attachment-0002.ksh>


More information about the Gdb-patches mailing list