diff options
author | rie <none@none> | 2005-09-15 10:30:34 -0700 |
---|---|---|
committer | rie <none@none> | 2005-09-15 10:30:34 -0700 |
commit | dd94ecef63e3f299c1915ec8109e20b0c2bc0457 (patch) | |
tree | ce472cc8651f4dc1207bff829e30f029630d8183 | |
parent | 3cac8019b3348d73726cdcdce300b35ef15e156a (diff) | |
download | illumos-gate-dd94ecef63e3f299c1915ec8109e20b0c2bc0457.tar.gz |
6318401 mis-aligned TLS variable
6324019 ld.so.1: malloc alignment is insufficient for new compilers
-rw-r--r-- | usr/src/cmd/sgs/include/libld.h | 7 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libld/common/outfile.c | 48 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libld/common/place.c | 27 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libld/common/syms.c | 4 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libld/common/update.c | 63 | ||||
-rw-r--r-- | usr/src/cmd/sgs/packages/common/SUNWonld-README | 9 | ||||
-rw-r--r-- | usr/src/cmd/sgs/rtld/common/malloc.c | 2 |
7 files changed, 84 insertions, 76 deletions
diff --git a/usr/src/cmd/sgs/include/libld.h b/usr/src/cmd/sgs/include/libld.h index c47864ea25..d3a9595514 100644 --- a/usr/src/cmd/sgs/include/libld.h +++ b/usr/src/cmd/sgs/include/libld.h @@ -266,7 +266,7 @@ struct ofl_desc { #define FLG_OF_SEGSORT 0x00020000 /* segment sorting is required */ #define FLG_OF_TEXTREL 0x00040000 /* text relocations have been found */ #define FLG_OF_MULDEFS 0x00080000 /* multiple symbols are allowed */ -#define FLG_OF_OUTMMAP 0x00100000 /* output image is mmaped to file */ +#define FLG_OF_TLSPHDR 0x00100000 /* a TLS program header is required */ #define FLG_OF_BLDGOT 0x00200000 /* build GOT table */ #define FLG_OF_VERDEF 0x00400000 /* record version definitions */ #define FLG_OF_VERNEED 0x00800000 /* record version dependencies */ @@ -317,7 +317,7 @@ struct ofl_desc { #define FLG_OF1_TLSOREL 0x00100000 /* output relocation against .tlsbss */ /* section */ #define FLG_OF1_DEMANGL 0x00200000 /* demangle C++ sym name diagnostics */ -#define FLG_OF1_GRPSECT 0x00400000 /* GROUP sections are present */ + #define FLG_OF1_NOHDR 0x00800000 /* no elf header/phdr alignment */ /* needed */ #define FLG_OF1_VADDR 0x01000000 /* vaddr was explicitly set */ @@ -526,8 +526,7 @@ struct os_desc { /* Output section descriptor */ #define FLG_OS_ORDER_KEY 0x01 /* include a sort key section */ #define FLG_OS_OUTREL 0x02 /* output rel against this section */ -#define FLG_OS_TLSNONEMPTY 0x04 /* non empty TLS sections */ -#define FLG_OS_SECTREF 0x08 /* isps are not affected by -zignore */ +#define FLG_OS_SECTREF 0x04 /* isps are not affected by -zignore */ /* * For sorting sections. diff --git a/usr/src/cmd/sgs/libld/common/outfile.c b/usr/src/cmd/sgs/libld/common/outfile.c index e76b5c93e2..5d6723c0b3 100644 --- a/usr/src/cmd/sgs/libld/common/outfile.c +++ b/usr/src/cmd/sgs/libld/common/outfile.c @@ -24,7 +24,7 @@ * All Rights Reserved * * - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -242,13 +242,13 @@ create_outfile(Ofl_desc * ofl) Os_desc * osp; Is_desc * isp; Elf_Scn * scn; + Elf_Data * tlsdata = 0; Shdr * shdr; - Word ptype, flags = ofl->ofl_flags; + Word flags = ofl->ofl_flags; size_t ndx = 0, fndx = 0; Elf_Cmd cmd; Boolean fixalign = FALSE; - int fd, nseg = 0, shidx = 0, dataidx = 0, ptloadidx = 0, - tlsidx = 0; + int fd, nseg = 0, shidx = 0, dataidx = 0, ptloadidx = 0; /* * If FLG_OF1_NOHDR was set in map_parse() or FLG_OF1_VADDR was set, @@ -291,15 +291,14 @@ create_outfile(Ofl_desc * ofl) DBG_CALL(Dbg_util_nl()); for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp)) { + int frst = 0; + Phdr *phdr = &(sgp->sg_phdr); + Word ptype = phdr->p_type; + /* * Count the number of segments that will go in the program * header table. If a segment is empty, ignore it. */ - int frst = 0; - Phdr * phdr = &(sgp->sg_phdr); - - ptype = phdr->p_type; - if (!(flags & FLG_OF_RELOBJ)) { if (ptype == PT_PHDR) { /* @@ -324,7 +323,7 @@ create_outfile(Ofl_desc * ofl) if (flags & FLG_OF_DYNAMIC) nseg++; } else if (ptype == PT_TLS) { - if (ofl->ofl_ostlsseg.head) + if (flags & FLG_OF_TLSPHDR) nseg++; #if (defined(__i386) || defined(__amd64)) && defined(_ELF64) } else if (ptype == PT_SUNW_UNWIND) { @@ -406,6 +405,19 @@ create_outfile(Ofl_desc * ofl) if ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) osp->os_shdr->sh_flags &= ~SHF_GROUP; + /* + * If this is a TLS section, save it so that the PT_TLS + * program header information can be established after + * the output image has been initialy created. At this + * point, all TLS input sections are ordered as they + * will appear in the output image. + */ + if ((ofl->ofl_flags & FLG_OF_TLSPHDR) && + (osp->os_shdr->sh_flags & SHF_TLS)) { + if (list_appendc(&ofl->ofl_ostlsseg, osp) == 0) + return (S_ERROR); + } + dataidx = 0; for (LIST_TRAVERSE(&(osp->os_isdescs), lnp3, isp)) { Elf_Data * data; @@ -476,15 +488,17 @@ create_outfile(Ofl_desc * ofl) isp->is_indata = data; /* - * Make sure that the first tls section is - * aligned on pointer size alignment. + * Save the first TLS data buffer, as this is + * the start of the TLS segment. Realign this + * buffer based on the alignment requirements + * of all the TLS input sections. */ - if ((tlsidx == 0) && - ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) && + if ((ofl->ofl_flags & FLG_OF_TLSPHDR) && (isp->is_shdr->sh_flags & SHF_TLS)) { - data->d_align = lcm(M_WORD_ALIGN, - isp->is_shdr->sh_addralign); - tlsidx = 1; + if (tlsdata == 0) + tlsdata = data; + tlsdata->d_align = lcm(tlsdata->d_align, + isp->is_shdr->sh_addralign); } #if defined(_ELF64) && defined(_ILP32) diff --git a/usr/src/cmd/sgs/libld/common/place.c b/usr/src/cmd/sgs/libld/common/place.c index 39f6a76951..5bfdebd23a 100644 --- a/usr/src/cmd/sgs/libld/common/place.c +++ b/usr/src/cmd/sgs/libld/common/place.c @@ -117,7 +117,6 @@ place_section(Ofl_desc * ofl, Is_desc * isp, int ident, Word link) isp->is_flags |= FLG_IS_DISCARD; return ((Os_desc *)0); } - ofl->ofl_flags1 |= FLG_OF1_GRPSECT; } } @@ -335,16 +334,12 @@ place_section(Ofl_desc * ofl, Is_desc * isp, int ident, Word link) set_addralign(ofl, osp, isp); /* - * If this section is a non-empty TLS section and - * if the osp is not yet recorded in ofl_osttlsseg, - * record it. + * If this section is a non-empty TLS section indicate + * that a PT_TLS program header is required. */ - if ((shflags & SHF_TLS) && (shdr->sh_size != 0) && - ((osp->os_flags & FLG_OS_TLSNONEMPTY) == 0)) { - osp->os_flags |= FLG_OS_TLSNONEMPTY; - if (list_appendc(&ofl->ofl_ostlsseg, osp) == 0) - return ((Os_desc *)S_ERROR); - } + if ((shflags & SHF_TLS) && shdr->sh_size && + ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0)) + ofl->ofl_flags |= FLG_OF_TLSPHDR; /* * If is_txtndx is 0 then this section was not @@ -515,14 +510,12 @@ place_section(Ofl_desc * ofl, Is_desc * isp, int ident, Word link) } /* - * If this section is a TLS section - keep track of it - * for the latter building of the PT_TLS segment. + * If this section is a non-empty TLS section indicate that a PT_TLS + * program header is required. */ - if ((shflags & SHF_TLS) && (shdr->sh_size != 0)) { - osp->os_flags |= FLG_OS_TLSNONEMPTY; - if (list_appendc(&ofl->ofl_ostlsseg, osp) == 0) - return ((Os_desc *)S_ERROR); - } + if ((shflags & SHF_TLS) && shdr->sh_size && + ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0)) + ofl->ofl_flags |= FLG_OF_TLSPHDR; /* * If a non-allocatable section is going to be put into a loadable diff --git a/usr/src/cmd/sgs/libld/common/syms.c b/usr/src/cmd/sgs/libld/common/syms.c index 1f73bbc855..d0e991a341 100644 --- a/usr/src/cmd/sgs/libld/common/syms.c +++ b/usr/src/cmd/sgs/libld/common/syms.c @@ -492,7 +492,7 @@ sym_enter(const char *name, Sym *osym, Word hash, Ifl_desc *ifl, Ofl_desc *ofl, * and without underscores. This routine is called, after all other symbol * resolution has completed, to generate a reserved absolute symbol (the * underscore version). Special symbols are updated with the appropriate - * values in sym_update(). If the user has already defined this symbol + * values in update_osym(). If the user has already defined this symbol * issue a warning and leave the symbol as is. If the non-underscore symbol * is referenced then turn it into a weak alias of the underscored symbol. * @@ -1201,7 +1201,7 @@ sym_validate(Ofl_desc *ofl) align = &tlsalign; } *size = (Xword)S_ROUND(*size, sym->st_value) + - sym->st_size; + sym->st_size; if (sym->st_value > *align) *align = sym->st_value; } diff --git a/usr/src/cmd/sgs/libld/common/update.c b/usr/src/cmd/sgs/libld/common/update.c index baef7f4889..81e1631e90 100644 --- a/usr/src/cmd/sgs/libld/common/update.c +++ b/usr/src/cmd/sgs/libld/common/update.c @@ -24,7 +24,7 @@ * All Rights Reserved * * - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -780,8 +780,7 @@ update_osym(Ofl_desc *ofl) sdp->sd_isc = ofl->ofl_istlsbss; sdp->sd_flags |= FLG_SY_COMMEXP; /* - * TLS symbols are relative to - * the TLS segment. + * TLS symbols are relative to the TLS segment. */ symptr->st_value -= ofl->ofl_tlsphdr->p_vaddr; } @@ -2759,46 +2758,40 @@ update_outfile(Ofl_desc *ofl) continue; } #endif - if (phdr->p_type == PT_TLS) { - Os_desc *_osp; - Shdr *firstshdr; - Shdr *fshdr; - Shdr *bssshdr; + Os_desc *tlsosp; + Shdr *firstshdr = 0, *lastfilshdr, *lastmemshdr; - if ((ofl->ofl_ostlsseg.head == NULL) || - (flags & FLG_OF_RELOBJ)) + if (ofl->ofl_ostlsseg.head == NULL) continue; - _osp = (Os_desc *) - (ofl->ofl_ostlsseg.head->data); - firstshdr = fshdr = bssshdr = _osp->os_shdr; - phdr->p_flags = PF_R | PF_W; - phdr->p_memsz = 0; - phdr->p_filesz = 0; - for (LIST_TRAVERSE(&ofl->ofl_ostlsseg, - lnp2, _osp)) { - Shdr *_shdr; - _shdr = _osp->os_shdr; - if (_shdr->sh_addr < firstshdr->sh_addr) - firstshdr = _shdr; - if ((_shdr->sh_addr + _shdr->sh_size) > - (bssshdr->sh_addr + bssshdr->sh_size)) - bssshdr = _shdr; - if (_shdr->sh_type != SHT_NOBITS) { - if ((_shdr->sh_addr + _shdr->sh_size) > - (fshdr->sh_addr + - fshdr->sh_size)) - fshdr = _shdr; + + for (LIST_TRAVERSE(&ofl->ofl_ostlsseg, lnp2, tlsosp)) { + Shdr *tlsshdr = tlsosp->os_shdr; + + if (firstshdr == 0) { + firstshdr = lastfilshdr = lastmemshdr = + tlsosp->os_shdr; + continue; } + + if (tlsshdr->sh_type == SHT_NOBITS) + lastmemshdr = tlsshdr; + else + lastfilshdr = tlsshdr; } + + phdr->p_flags = PF_R | PF_W; phdr->p_vaddr = firstshdr->sh_addr; phdr->p_offset = firstshdr->sh_offset; - phdr->p_filesz = fshdr->sh_offset + - fshdr->sh_size - phdr->p_offset; - phdr->p_memsz = bssshdr->sh_offset + - bssshdr->sh_size - phdr->p_offset; + phdr->p_align = firstshdr->sh_addralign; + phdr->p_filesz = lastfilshdr->sh_offset + + lastfilshdr->sh_size - phdr->p_offset; + phdr->p_memsz = lastmemshdr->sh_offset + + lastmemshdr->sh_size - phdr->p_offset; + DBG_CALL(Dbg_seg_entry(ofl->ofl_e_machine, - segndx, sgp)); + segndx, sgp)); + ofl->ofl_tlsphdr = phdr; ofl->ofl_phdr[phdrndx++] = *phdr; continue; diff --git a/usr/src/cmd/sgs/packages/common/SUNWonld-README b/usr/src/cmd/sgs/packages/common/SUNWonld-README index 9b73e54e2e..9fc3ec07d5 100644 --- a/usr/src/cmd/sgs/packages/common/SUNWonld-README +++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README @@ -1509,4 +1509,13 @@ All the above change is incorporated in the following patches: -------------------------------------------------------------------------------- 6314115 Checkpoint refuses to start, crashes on start, after application of linker patch 112963-22 +-------------------------------------------------------------------------------- +All the above change is incorporated in the following patches: + Solaris/SunOS 5.9_sparc patch T112963-24 + Solaris/SunOS 5.9_x86 patch T113986-20 + Solaris/SunOS 5.8_sparc patch T109147-39 + Solaris/SunOS 5.8_x86 patch T109148-39 +-------------------------------------------------------------------------------- 6318306 a dlsym() from a filter should be redirected to an associated filtee +6318401 mis-aligned TLS variable +6324019 ld.so.1: malloc alignment is insufficient for new compilers diff --git a/usr/src/cmd/sgs/rtld/common/malloc.c b/usr/src/cmd/sgs/rtld/common/malloc.c index cd2a770a4a..5189291e29 100644 --- a/usr/src/cmd/sgs/rtld/common/malloc.c +++ b/usr/src/cmd/sgs/rtld/common/malloc.c @@ -68,7 +68,7 @@ struct page { #define HDR_BLOCK (sizeof (struct block) - sizeof (void *)) #define HDR_PAGE (sizeof (struct page) - sizeof (void *)) -#define MINSZ sizeof (void *) +#define MINSZ 8 static struct page *memstart; |