|
Bugzilla – Full Text Bug Listing |
| Summary: | glibc contains invalid DWARF frames | ||
|---|---|---|---|
| Product: | [openSUSE] SUSE LINUX 10.0 | Reporter: | Michael Matz <matz> |
| Component: | Basesystem | Assignee: | Andreas Schwab <schwab> |
| Status: | RESOLVED FIXED | QA Contact: | E-mail List <qa-bugs> |
| Severity: | Normal | ||
| Priority: | P5 - None | CC: | aj |
| Version: | Stable Snapshot 2 | ||
| Target Milestone: | --- | ||
| Hardware: | i686 | ||
| OS: | All | ||
| Whiteboard: | |||
| Found By: | Other | Services Priority: | |
| Business Priority: | Blocker: | --- | |
| Marketing QA Status: | --- | IT Deployment: | --- |
The right way to fix this is to use the CFI directives of the assembler as it is already done in HEAD. Probably just copying sysdep-cancel.h from HEAD will do. I cannot reproduce this with preview3, I get no output at all: aj@x40:~> readelf -wf /lib/tls/libpthread.so.0 > /dev/null aj@x40:~> readelf -wf /lib/tls/libc.so.6 > /dev/null Could you double check preview3, please? Are you sure? I just tried again in a buildsystem of STABLE (i386) and can reproduce just fine. I don't have preview3 immediately ready, but can't think of reasons why it should behave differently than STABLE in this regard. But will try tomorrow. Andreas S.: yes, it seems to work when I use the CVS sysdep-cancel.h, and look at fsync.S. I need this patch additionally: --- sysdeps/i386/sysdep.h 2005-08-01 07:30:55.633685071 +0000 +++ sysdeps/i386/sysdep.h.mm 2005-08-01 07:28:53.095269000 +0000 @@ -57,10 +57,12 @@ .align ALIGNARG(4); \ STABS_FUN(name) \ C_LABEL(name) \ + cfi_startproc; \ CALL_MCOUNT #undef END #define END(name) \ + cfi_endproc; \ ASM_SIZE_DIRECTIVE(name) \ STABS_FUN_END(name) I have not completely built glibc with these changes. Can someone please try this and submit it? From the ChangeLog I read that adding the cfi_startproc and cfi_endproc to i386/sysdep.h might need other changes in different files too, but I don't have time to look at this. Andreas, could you take it, please? Fixed. |
Do this: % readelf -wf /lib/tls/libpthread.so.0 > /dev/null readelf: Warning: unsupported or unknown DW_CFA_50 readelf: Warning: unsupported or unknown DW_CFA_50 This also happens on 9.3 already (I haven't tested back earlier). This currently confuses valgrind 3.0 's dwarf reader on SuSE Linux, making it work suboptimally. Same happens when looking at /lib/tls/libc.so.6 . The problem is in the fsync and close syscalls. I created a buildsystem for STABLE, and looked at the .os files: % readelf -wf cc-nptl/misc/fsync.os The section .eh_frame contains: 00000000 00000014 00000000 CIE Version: 1 Augmentation: "zR" Code alignment factor: 1 Data alignment factor: -4 Return address column: 8 Augmentation data: 1b DW_CFA_def_cfa: r4 ofs 4 DW_CFA_offset: r8 at cfa-4 DW_CFA_nop DW_CFA_nop 00000018 00000020 0000001c FDE cie=00000000 pc=00000000..00000065 DW_CFA_advance_loc: 12 to 0000000c DW_CFA_register: r3 in r2 DW_CFA_advance_loc: 13 to 00000019 DW_CFA_restore: r3 DW_CFA_advance_loc: 31 to 00000038 DW_CFA_def_cfa_offset: 8 readelf: Warning: unsupported or unknown DW_CFA_50 (same for cc-nptl/io/close.os). The problem is how NPTL syscalls with 1 argument are constructed, for which no arch specific one exists. E.g. the fsync syscall is constructed by feeding GCC with this on stdin: ------------------------------------------ #include <sysdep-cancel.h> PSEUDO (__libc_fsync, fsync, 1) ret PSEUDO_END(__libc_fsync) libc_hidden_def (__libc_fsync) weak_alias (__libc_fsync, fsync) libc_hidden_weak (fsync) ------------------------------------------ This expands directly to assembler, parts of it are: __libc_fsync: .L__libc_fsyncSTART: cmpl $0, %gs:12 jne .Lpseudo_cancel .type __fsync_nocancel,@function .globl __fsync_nocancel __fsync_nocancel: movl %ebx, %edx .LSAVEBX1: movl 4(%esp), %ebx movl $118, %eax int $0x80 movl %edx, %ebx .LRESTBX1: cmpl $-4095, %eax jae 0f ret .size __fsync_nocancel,.-__fsync_nocancel .Lpseudo_cancel: call __libc_enable_asynccancel movl %eax, %ecx movl %ebx, %edx .LSAVEBX2: movl 4(%esp), %ebx movl $118, %eax int $0x80 movl %edx, %ebx .LRESTBX2: pushl %eax .LPUSHSTATE: movl %ecx, %eax call __libc_disable_asynccancel popl %eax .LPOPSTATE: cmpl $-4095, %eax jae 0f .Lpseudo_end: .... .section .eh_frame,"a",@progbits .... .LSTARTFDE: .long .LSTARTFDE-.LSTARTFRAME .long .L__libc_fsyncSTART-. .long .L__libc_fsyncEND-.L__libc_fsyncSTART .uleb128 0 .byte 0x40+.LSAVEBX1-.L__libc_fsyncSTART .byte 9 .uleb128 3 .uleb128 2 .byte 0x40+.LRESTBX1-.LSAVEBX1 .byte 0xc3 .byte 0x40+.LPUSHSTATE-.LRESTBX1 .byte 14 .uleb128 8 .byte 0x40+.LSAVEBX2-.LPUSHSTATE <<<<<<<<<<<< here .byte 9 .uleb128 3 .uleb128 2 .byte 0x40+.LRESTBX2-.LSAVEBX2 .byte 0xc3 .byte 0x40+.LPOPSTATE-.LRESTBX2 .byte 14 .uleb128 4 .align 4 .LENDFDE: On the marked line the difference .LSAVEBX2-.LPUSHSTATE is used, but .LSAVEBX2 is in front of .LPUSHSTATE, hence it is negative, and in our case results in 0x32 overall, i.e. our 50 readelf complains about. I looked a bit at nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h . The body of the syscalls is this: L(pseudo_cancel): CENABLE SAVE_OLDTYPE_##args PUSHCARGS_##args DOCARGS_##args movl $SYS_ify (syscall_name), %eax; ENTER_KERNEL; POPCARGS_##args; POPSTATE_##args cmpl $-4095, %eax; jae SYSCALL_ERROR_LABEL; L(pseudo_end): Now look at some more macros: # define SAVE_OLDTYPE_0 movl %eax, %ecx; # define SAVE_OLDTYPE_1 SAVE_OLDTYPE_0 # define SAVE_OLDTYPE_2 pushl %eax; L(PUSHSTATE): # define POPSTATE_0 \ pushl %eax; L(PUSHSTATE): movl %ecx, %eax; CDISABLE; popl %eax; L(POPSTATE): # define POPSTATE_1 POPSTATE_0 # define POPSTATE_2 xchgl (%esp), %eax; CDISABLE; popl %eax; L(POPSTATE): Look at how with 2 or more args .LPUSHSTATE is set before the PUSHCARGS macro (which contains the .LSAVEBX2 label for instance, for all args). But with 0 and 1 argument this label is set by POPSTATE, hence after the use of the PUSHCARGS macro. For 0 arguments this doesn't matter it seems, as the macro setting up eh_frame for 0 args doesn't refer to .LSAVEBX2. But EH_FRAME_1 has this expression: .byte 0x40+L(SAVEBX2)-L(PUSHSTATE); /* DW_CFA_advance_loc+N */ hence it needs SAVEBX2 _after_ PUSHSTATE, but that's only the case for 2 or more args. So something must be changed, I'm just not sure what. If someone from the glibc maintainers could look at this, it would be nice.