This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: gdb: Incorrect stack unwinding if compressed debug info is used


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

Attachment: b.sh
Description: Bourne shell script

Attachment: dbg_info_test.c
Description: Text document

Attachment: gdb_old_log
Description: Text document

Attachment: gdb_debug_log
Description: Text document

Attachment: gdb-7.2-compressed-section-4.patch
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]