Project

General

Profile

Bug #1736

ld segfaults on sparc during python26 build

Added by Yuri Pankov almost 8 years ago. Updated almost 8 years ago.

Status:
In Progress
Priority:
Normal
Assignee:
Category:
cmd - userland programs
Start date:
2011-11-06
Due date:
% Done:

20%

Estimated time:
Difficulty:
Medium
Tags:

Description

building 'cStringIO' extension
/opt/SUNWspro/sunstudio12.1/bin/cc -m32 -xO4 -xtarget=ultra2 -xarch=sparcvis -xchip=ultra2 -xregs=no%appl,float -W2,-xwrap_int -xmemalign=8s -mt -G build/temp.solaris-2.11-sun4u-2.6/home/yuri/oi-build/components/python/python26/Python-2.6.4/Modules/cStringIO.o -L. -lpython2.6 -o build/lib.solaris-2.11-sun4u-2.6/cStringIO.so
cc: Fatal error in /usr/ccs/bin/ld
cc: Status 139

To reproduce:

/usr/bin/env LD_OPTIONS="-M /usr/lib/ld/map.noexstk -M /usr/lib/ld/map.noexbss -M /usr/lib/ld/map.pagealign -Bdirect -z ignore"  DFLAGS="-32" /opt/SUNWspro/sunstudio12.1/bin/cc -m32 -xO4 -xtarget=ultra2 -xarch=sparcvis -xchip=ultra2 -xregs=no%appl,float -W2,-xwrap_int -xmemalign=8s -mt -G cStringIO.o -L. -lpython2.6 -o cStringIO.so


Files

cStringIO.o (20.6 KB) cStringIO.o Yuri Pankov, 2011-11-06 01:30 AM
libpython2.6.so.1.0.bz2 (802 KB) libpython2.6.so.1.0.bz2 Yuri Pankov, 2011-11-06 01:30 AM
core.bz2 (3.04 MB) core.bz2 Yuri Pankov, 2011-11-06 01:30 AM

History

#1

Updated by Rich Lowe almost 8 years ago

  • Assignee set to Rich Lowe
  • Tags deleted (needs-triage)

Yuri discovered that this problem is triggered by the use of the noexbss mapfile, more specifically it's another bug triggered by the presence of a separate BSS segment (the stock bssalign mapfile will also cause this problem).

A workaround is to avoid the use of mapfiles which don't cause the creation of a separate segment for BSS.

#2

Updated by Rich Lowe almost 8 years ago

  • Status changed from New to In Progress
  • % Done changed from 0 to 70

This is, likely, not an actually SPARC specific problem in general, but SPARC specific in that the SPARC compiler is what created these specific input objects.

The problem is that we are using a mapfile, map.noexbss which requests the creation of a BSS segment, to which input bss, tbss, etc will be assigned. However, our input object contains no uninitialized globals, nor uninitialized COMMON symbols, and so has no BSS. Since we were asked to create the segment, we did, and we're left with a segment of 0 size, containing no sections.

Now, if this BSS segment is the last loadable segment we use it to locate the _end symbol, attempting to do so relative to its final section. This makes no attempt to validate the number of sections in the segment, and underflows apl_nitems (the number of elements in the section list), walking considerably past the end of the output section list. In Yuri's case, this appeared to hit a '0', such that we crashed when dereferencing the NULL output section descriptor

            /*
             * If we're dealing with a memory reservation there are
             * no sections to establish an index for _end, so assign
             * it as an absolute.
             */
            if (sgp->sg_osdescs != NULL) {
                /*
                 * Determine the last section for this segment.
                 */
                Os_desc    *osp = sgp->sg_osdescs->apl_data
                    [sgp->sg_osdescs->apl_nitems - 1];

                /* LINTED */
                end_ndx = elf_ndxscn(osp->os_scn);
            } else {
                end_ndx = SHN_ABS;
                end_abs = 1;
            }
> $C
ffffffff7fffe471 libld.so.4`update_osym+0xbdc(7fefe4008a8, d, 20000, 20000, 
20000, 7fefe405938)
ffffffff7fffe881 libld.so.4`ld32_update_outfile+0xe40(7fefe400020, 7fefda06efc, 
7fefe400f40, 1, 40, d)
ffffffff7fffe9f1 libld.so.4`ld32_main+0x764(7fefe400020, ffffffff, 10000000, 
7fefe400020, 7feff4ae110, 80008000)
ffffffff7fffeab1 main+0x140(100000, ffffffff7ffff438, 1b, 100002000, 100002, 
100000)
ffffffff7fffeb81 _start+0x17c(0, 0, 0, 0, 0, 0)

> update_osym+0xbdc::dis
libld.so.4`update_osym+0xbcc:   sllx      %g1, 0x3, %o4
libld.so.4`update_osym+0xbd0:   add       %i5, %o4, %o3
libld.so.4`update_osym+0xbd4:   ldx       [%o3 + 0x10], %l7
libld.so.4`update_osym+0xbd8:   
call      +0x157d64     <PLT=libelf.so.1`elf_ndxscn>
libld.so.4`update_osym+0xbdc:   ldx       [%l7 + 0x8], %o0
libld.so.4`update_osym+0xbe0:   st        %o0, [%fp + 0x73b]
libld.so.4`update_osym+0xbe4:   
ba        +0x54         <libld.so.4`update_osym+0xc38>
> <l7=K                               
                0               
> ::offsetof Os_desc os_scn
offsetof (Os_desc, os_scn) = 8, sizeof (...->os_scn) = 8

%l7 is the (NULL) Os_desc, we're trying to dereference the ->os_scn in the delay slot of the elf_ndxscn call, to pass as the argument.

It is debatable what we should do about the empty segment. In general, we would prefer to not have needless loadable segments, since we have to think about them while mapping objects. However, the user has explicitly, via the mapfile, requested that a BSS segment of certain properties exist, pruning it would be directly contrary to that (if likely not problematic).

The fix, thus, is to check not only that the last loadable segment is not NULL (that is, that loadable segments exist), but also that this segment contains at least one section.

#3

Updated by Rich Lowe almost 8 years ago

  • % Done changed from 70 to 20

The logic that since a segment was asked for, it should remain, is incorrect.
Partially following on from that, it turns out that this is more complicated than it seems, and that while the simple change works it does so accidentally.

I'll update the bug with more information once I'm more sure of it

Also available in: Atom PDF