Mercurial > illumos > illumos-gate
changeset 5152:fa5ab16f3606
5035454 mixing -Kpic and -KPIC may cause SIGSEGV with -xarch=v9
line wrap: on
line diff
--- a/usr/src/cmd/sgs/include/conv.h Mon Oct 01 09:45:31 2007 -0700 +++ b/usr/src/cmd/sgs/include/conv.h Mon Oct 01 10:33:16 2007 -0700 @@ -190,7 +190,7 @@ /* conv_config_feat() */ -#define CONV_CONFIG_FEAT_BUFSIZE 195 +#define CONV_CONFIG_FEAT_BUFSIZE 194 typedef union { Conv32_inv_buf_t inv_buf; @@ -232,7 +232,7 @@ /* conv_dl_flag() */ -#define CONV_DL_FLAG_BUFSIZE 195 +#define CONV_DL_FLAG_BUFSIZE 175 typedef union { Conv32_inv_buf_t inv_buf;
--- a/usr/src/cmd/sgs/include/sparc/machdep.h Mon Oct 01 09:45:31 2007 -0700 +++ b/usr/src/cmd/sgs/include/sparc/machdep.h Mon Oct 01 10:33:16 2007 -0700 @@ -157,6 +157,7 @@ /* transition flags for got sizing */ #define M_GOT_LARGE (Sword)(-M_GOT_MAXSMALL - 1) #define M_GOT_SMALL (Sword)(-M_GOT_MAXSMALL - 2) +#define M_GOT_MIXED (Sword)(-M_GOT_MAXSMALL - 3) /*
--- a/usr/src/cmd/sgs/libconv/Makefile.targ Mon Oct 01 09:45:31 2007 -0700 +++ b/usr/src/cmd/sgs/libconv/Makefile.targ Mon Oct 01 10:33:16 2007 -0700 @@ -20,7 +20,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -46,9 +46,21 @@ $(COMPILE.c) -DCAP_UPPERCASE -o $@ $(ELFCAP)/elfcap.c $(POST_PROCESS_O) +# This rule generates the report_bufsize.h include file used by libconv +# code to ensure that their private buffer size calculations agree with +# the public values exposed in sgs/include/conv.h. The limit value +# supplied must be larger than the largest buffer used in libconv. There +# is little penalty for making it very large, because the header file is +# only included in error situations where the compilation will fail. +# +# We make this depend on Makefile.targ, because a change to Makefile.targ +# can change the limit, in which case we want to force everything to rebuild. +report_bufsize.h: ../Makefile.targ + perl ../../tools/libconv_mk_report_bufsize.pl 2000 + ../common/%.c: %_msg.h -%_msg.h: $(SGSMSG) ../common/%.msg +%_msg.h: $(SGSMSG) ../common/%.msg report_bufsize.h $(SGSMSG) $(SGSMSGFLAGS) -l -h $@ -d $@ $< $(SGSMSG): FRC
--- a/usr/src/cmd/sgs/libconv/common/config.c Mon Oct 01 09:45:31 2007 -0700 +++ b/usr/src/cmd/sgs/libconv/common/config.c Mon Oct 01 10:33:16 2007 -0700 @@ -53,8 +53,10 @@ * information that is not available in the environment of other programs * that include the conv.h header file. */ -#if (CONV_CONFIG_FEAT_BUFSIZE < FEATSZ) && !defined(__lint) -#error "CONV_CONFIG_FEAT_BUFSIZE is not large enough" +#if (CONV_CONFIG_FEAT_BUFSIZE != FEATSZ) && !defined(__lint) +#define REPORT_BUFSIZE FEATSZ +#include "report_bufsize.h" +#error "CONV_CONFIG_FEAT_BUFSIZE does not match FEATSZ" #endif /* @@ -111,8 +113,10 @@ * information that is not available in the environment of other programs * that include the conv.h header file. */ -#if (CONV_CONFIG_OBJ_BUFSIZE < FLAGSZ) && !defined(__lint) -#error "CONV_CONFIG_OBJ_BUFSIZE is not large enough" +#if (CONV_CONFIG_OBJ_BUFSIZE != FLAGSZ) && !defined(__lint) +#define REPORT_BUFSIZE FLAGSZ +#include "report_bufsize.h" +#error "CONV_CONFIG_OBJ_BUFSIZE does not match FLAGSZ" #endif /*
--- a/usr/src/cmd/sgs/libconv/common/dl.c Mon Oct 01 09:45:31 2007 -0700 +++ b/usr/src/cmd/sgs/libconv/common/dl.c Mon Oct 01 10:33:16 2007 -0700 @@ -51,8 +51,10 @@ * information that is not available in the environment of other programs * that include the conv.h header file. */ -#if (CONV_DL_MODE_BUFSIZE < MODESZ) && !defined(__lint) -#error "CONV_DL_MODE_BUFSIZE is not large enough" +#if (CONV_DL_MODE_BUFSIZE != MODESZ) && !defined(__lint) +#define REPORT_BUFSIZE MODESZ +#include "report_bufsize.h" +#error "CONV_DL_MODE_BUFSIZE does not match MODESZ" #endif /* @@ -129,8 +131,10 @@ * information that is not available in the environment of other programs * that include the conv.h header file. */ -#if (CONV_DL_FLAG_BUFSIZE < FLAGSZ) && !defined(__lint) -#error "CONV_DL_FLAG_BUFSIZE is not large enough" +#if (CONV_DL_FLAG_BUFSIZE != FLAGSZ) && !defined(__lint) +#define REPORT_BUFSIZE FLAGSZ +#include "report_bufsize.h" +#error "CONV_DL_FLAG_BUFSIZE does not match FLAGSZ" #endif /*
--- a/usr/src/cmd/sgs/libconv/common/dwarf_ehe.c Mon Oct 01 09:45:31 2007 -0700 +++ b/usr/src/cmd/sgs/libconv/common/dwarf_ehe.c Mon Oct 01 10:33:16 2007 -0700 @@ -44,8 +44,10 @@ * information that is not available in the environment of other programs * that include the conv.h header file. */ -#if (CONV_DWARF_EHE_BUFSIZE < FLAGSZ) && !defined(__lint) -#error "CONV_DWARF_EHE_BUFSIZE is not large enough" +#if (CONV_DWARF_EHE_BUFSIZE != FLAGSZ) && !defined(__lint) +#define REPORT_BUFSIZE FLAGSZ +#include "report_bufsize.h" +#error "CONV_DWARF_EHE_BUFSIZE does not match FLAGSZ" #endif const char *
--- a/usr/src/cmd/sgs/libconv/common/dynamic.c Mon Oct 01 09:45:31 2007 -0700 +++ b/usr/src/cmd/sgs/libconv/common/dynamic.c Mon Oct 01 10:33:16 2007 -0700 @@ -56,8 +56,10 @@ * information that is not available in the environment of other programs * that include the conv.h header file. */ -#if CONV_DYN_POSFLAG1_BUFSIZE < POSSZ -#error "CONV_DYN_POSFLAG1_BUFSIZE is not large enough" +#if (CONV_DYN_POSFLAG1_BUFSIZE != POSSZ) && !defined(__lint) +#define REPORT_BUFSIZE POSSZ +#include "report_bufsize.h" +#error "CONV_DYN_POSFLAG1_BUFSIZE does not match POSSZ" #endif const char * @@ -111,10 +113,11 @@ * information that is not available in the environment of other programs * that include the conv.h header file. */ -#if CONV_DYN_FLAG_BUFSIZE < FLAGSZ -#error "CONV_DYN_FLAG_BUFSIZE is not large enough" +#if (CONV_DYN_FLAG_BUFSIZE != FLAGSZ) && !defined(__lint) +#define REPORT_BUFSIZE FLAGSZ +#include "report_bufsize.h" +#error "CONV_DYN_FLAG_BUFSIZE does not match FLAGSZ" #endif - const char * conv_dyn_flag(Xword flags, Conv_fmt_flags_t fmt_flags, Conv_dyn_flag_buf_t *dyn_flag_buf) @@ -181,8 +184,10 @@ * information that is not available in the environment of other programs * that include the conv.h header file. */ -#if CONV_DYN_FLAG1_BUFSIZE < FLAG1SZ -#error "CONV_DYN_FLAG1_BUFSIZE is not large enough" +#if (CONV_DYN_FLAG1_BUFSIZE != FLAG1SZ) && !defined(__lint) +#define REPORT_BUFSIZE FLAG1SZ +#include "report_bufsize.h" +#error "CONV_DYN_FLAG1_BUFSIZE does not match FLAG1SZ" #endif const char * @@ -244,8 +249,10 @@ * information that is not available in the environment of other programs * that include the conv.h header file. */ -#if CONV_DYN_FEATURE1_BUFSIZE < FEATSZ -#error "CONV_DYN_FEATURE1_BUFSIZE is not large enough" +#if (CONV_DYN_FEATURE1_BUFSIZE != FEATSZ) && !defined(__lint) +#define REPORT_BUFSIZE FEATSZ +#include "report_bufsize.h" +#error "CONV_DYN_FEATURE1_BUFSIZE does not match FEATSZ" #endif const char * @@ -455,8 +462,10 @@ * information that is not available in the environment of other programs * that include the conv.h header file. */ -#if CONV_BND_TYPE_BUFSIZE < BINDTSZ -#error "CONV_BND_TYPE_BUFSIZE is not large enough" +#if (CONV_BND_TYPE_BUFSIZE != BINDTSZ) && !defined(__lint) +#define REPORT_BUFSIZE BINDTSZ +#include "report_bufsize.h" +#error "CONV_BND_TYPE_BUFSIZE does not match BINDTSZ" #endif const char * @@ -501,8 +510,10 @@ * information that is not available in the environment of other programs * that include the conv.h header file. */ -#if CONV_BND_OBJ_BUFSIZE < BINDOSZ -#error "CONV_BND_OBJ_BUFSIZE is not large enough" +#if (CONV_BND_OBJ_BUFSIZE != BINDOSZ) && !defined(__lint) +#define REPORT_BUFSIZE BINDOSZ +#include "report_bufsize.h" +#error "CONV_BND_OBJ_BUFSIZE does not match BINDOSZ" #endif const char *
--- a/usr/src/cmd/sgs/libconv/common/elf.c Mon Oct 01 09:45:31 2007 -0700 +++ b/usr/src/cmd/sgs/libconv/common/elf.c Mon Oct 01 10:33:16 2007 -0700 @@ -260,8 +260,10 @@ * information that is not available in the environment of other programs * that include the conv.h header file. */ -#if CONV_EHDR_FLAGS_BUFSIZE < EFLAGSZ -#error "CONV_EHDR_FLAGS_BUFSIZE is not large enough" +#if (CONV_EHDR_FLAGS_BUFSIZE != EFLAGSZ) && !defined(__lint) +#define REPORT_BUFSIZE EFLAGSZ +#include "report_bufsize.h" +#error "CONV_EHDR_FLAGS_BUFSIZE does not match EFLAGSZ" #endif /*
--- a/usr/src/cmd/sgs/libconv/common/group.c Mon Oct 01 09:45:31 2007 -0700 +++ b/usr/src/cmd/sgs/libconv/common/group.c Mon Oct 01 10:33:16 2007 -0700 @@ -48,8 +48,10 @@ * information that is not available in the environment of other programs * that include the conv.h header file. */ -#if (CONV_GRPHDL_FLAGS_BUFSIZE < HDLSZ) && !defined(__lint) -#error "CONV_GRPHDL_FLAGS_BUFSIZE is not large enough" +#if (CONV_GRPHDL_FLAGS_BUFSIZE != HDLSZ) && !defined(__lint) +#define REPORT_BUFSIZE HDLSZ +#include "report_bufsize.h" +#error "CONV_GRPHDL_FLAGS_BUFSIZE does not match HDLSZ" #endif /* @@ -99,8 +101,10 @@ * information that is not available in the environment of other programs * that include the conv.h header file. */ -#if (CONV_GRPDESC_FLAGS_BUFSIZE < DESCSZ) && !defined(__lint) -#error "CONV_GRPDESC_FLAGS_BUFSIZE is not large enough" +#if (CONV_GRPDESC_FLAGS_BUFSIZE != DESCSZ) && !defined(__lint) +#define REPORT_BUFSIZE DESCSZ +#include "report_bufsize.h" +#error "CONV_GRPDESC_FLAGS_BUFSIZE does not match DESCSZ" #endif /*
--- a/usr/src/cmd/sgs/libconv/common/phdr.c Mon Oct 01 09:45:31 2007 -0700 +++ b/usr/src/cmd/sgs/libconv/common/phdr.c Mon Oct 01 10:33:16 2007 -0700 @@ -115,8 +115,10 @@ * information that is not available in the environment of other programs * that include the conv.h header file. */ -#if CONV_PHDR_FLAGS_BUFSIZE < PHDRSZ -#error "CONV_PHDR_FLAGS_BUFSIZE is not large enough" +#if (CONV_PHDR_FLAGS_BUFSIZE != PHDRSZ) && !defined(__lint) +#define REPORT_BUFSIZE PHDRSZ +#include "report_bufsize.h" +#error "CONV_PHDR_FLAGS_BUFSIZE does not match PHDRSZ" #endif const char *
--- a/usr/src/cmd/sgs/libconv/common/sections.c Mon Oct 01 09:45:31 2007 -0700 +++ b/usr/src/cmd/sgs/libconv/common/sections.c Mon Oct 01 10:33:16 2007 -0700 @@ -165,8 +165,10 @@ * information that is not available in the environment of other programs * that include the conv.h header file. */ -#if CONV_SEC_FLAGS_BUFSIZE < FLAGSZ -#error "CONV_SEC_FLAGS_BUFSIZE is not large enough" +#if (CONV_SEC_FLAGS_BUFSIZE != FLAGSZ) && !defined(__lint) +#define REPORT_BUFSIZE FLAGSZ +#include "report_bufsize.h" +#error "CONV_SEC_FLAGS_BUFSIZE does not match FLAGSZ" #endif const char *
--- a/usr/src/cmd/sgs/libconv/common/segments.c Mon Oct 01 09:45:31 2007 -0700 +++ b/usr/src/cmd/sgs/libconv/common/segments.c Mon Oct 01 10:33:16 2007 -0700 @@ -58,8 +58,10 @@ * information that is not available in the environment of other programs * that include the conv.h header file. */ -#if (CONV_SEG_FLAGS_BUFSIZE < SEGSZ) && !defined(__lint) -#error "CONV_SEG_FLAGS_BUFSIZE is not large enough" +#if (CONV_SEG_FLAGS_BUFSIZE != SEGSZ) && !defined(__lint) +#define REPORT_BUFSIZE SEGSZ +#include "report_bufsize.h" +#error "CONV_SEG_FLAGS_BUFSIZE does not match SEGSZ" #endif const char *
--- a/usr/src/cmd/sgs/libconv/common/syminfo.c Mon Oct 01 09:45:31 2007 -0700 +++ b/usr/src/cmd/sgs/libconv/common/syminfo.c Mon Oct 01 10:33:16 2007 -0700 @@ -52,8 +52,10 @@ * is not available in the environment of other programs that include * the conv.h header file. */ -#if CONV_SYMINFO_FLAGS_BUFSIZE < FLAGSZ -#error "CONV_SYMINFO_FLAGS_BUFSIZE is not large enough" +#if (CONV_SYMINFO_FLAGS_BUFSIZE != FLAGSZ) && !defined(__lint) +#define REPORT_BUFSIZE FLAGSZ +#include "report_bufsize.h" +#error "CONV_SYMINFO_FLAGS_BUFSIZE does not match FLAGSZ" #endif const char *
--- a/usr/src/cmd/sgs/libld/common/libld.sparc.msg Mon Oct 01 09:45:31 2007 -0700 +++ b/usr/src/cmd/sgs/libld/common/libld.sparc.msg Mon Oct 01 10:33:16 2007 -0700 @@ -20,7 +20,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -49,6 +49,10 @@ @ MSG_REL_SMALLGOT "too many symbols require `small' PIC references:\n\ \thave %d, maximum %d -- recompile some \ modules -K PIC." +@ MSG_REL_MIXEDGOT "too many symbols require mixed mode \ + (both `small' and `large') PIC references:\n\ + \thave %d, maximum %d -- recompile some \ + modules -K PIC." @ MSG_SYM_INCOMPREG1 "register %s symbol used incompatibly:\n\ \t(file %s symbol `%s', file %s symbol `%s');"
--- a/usr/src/cmd/sgs/libld/common/machrel.sparc.c Mon Oct 01 09:45:31 2007 -0700 +++ b/usr/src/cmd/sgs/libld/common/machrel.sparc.c Mon Oct 01 10:33:16 2007 -0700 @@ -41,6 +41,7 @@ */ static Sword neggotoffset = 0; /* off. of GOT table from GOT symbol */ static Sword smlgotcnt = M_GOT_XNumber; /* no. of small GOT symbols */ +static Sword mixgotcnt = 0; /* # syms with both large/small GOT */ Word ld_init_rel(Rel_desc *reld, void *reloc) @@ -1788,6 +1789,7 @@ * into the GOT, whereas large uses an unsigned 32-bit offset. */ static Sword small_index; /* starting index for small GOT entries */ +static Sword mixed_index; /* starting index for mixed GOT entries */ static Sword large_index; /* starting index for large GOT entries */ uintptr_t @@ -1812,6 +1814,10 @@ if (small_index == 0) small_index = M_GOT_XNumber; break; + case M_GOT_MIXED: + gnp->gn_gotndx = mixed_index; + mixed_index += gotents; + break; case M_GOT_LARGE: gnp->gn_gotndx = large_index; large_index += gotents; @@ -1886,26 +1892,56 @@ Listnode * lnp, * plnp; uint_t gotents; - raddend = rsp->rel_raddend; - if (pgnp && (pgnp->gn_addend == raddend) && (pgnp->gn_gotref == gref)) { - /* - * If an entry for this addend already exists, determine if it - * should be changed to a SMALL got. - */ - if ((pgnp->gn_gotndx != M_GOT_SMALL) && - (rsp->rel_rtype == R_SPARC_GOT13)) { - smlgotcnt++; - pgnp->gn_gotndx = M_GOT_SMALL; - sdp->sd_flags |= FLG_SY_SMGOT; - } - return (1); - } - + /* Some TLS requires two relocations with two GOT entries */ if ((gref == GOT_REF_TLSGD) || (gref == GOT_REF_TLSLD)) gotents = 2; else gotents = 1; + raddend = rsp->rel_raddend; + if (pgnp && (pgnp->gn_addend == raddend) && (pgnp->gn_gotref == gref)) { + + /* + * If an entry for this addend already exists, determine if it + * has mixed mode GOT access (both PIC and pic). + * + * In order to be accessible by both large and small pic, + * a mixed mode GOT must be located in the positive index + * range above _GLOBAL_OFFSET_TABLE_, and in the range + * reachable small pic. This is necessary because the large + * PIC mode cannot use a negative offset. This implies that + * there can be no more than (M_GOT_MAXSMALL/2 - M_GOT_XNumber) + * such entries. + */ + switch (pgnp->gn_gotndx) { + case M_GOT_SMALL: + /* + * This one was previously identified as a small + * GOT. If this access is large, then convert + * it to mixed. + */ + if (rsp->rel_rtype != R_SPARC_GOT13) { + pgnp->gn_gotndx = M_GOT_MIXED; + mixgotcnt += gotents; + } + break; + + case M_GOT_LARGE: + /* + * This one was previously identified as a large + * GOT. If this access is small, convert it to mixed. + */ + if (rsp->rel_rtype == R_SPARC_GOT13) { + smlgotcnt += gotents; + mixgotcnt += gotents; + pgnp->gn_gotndx = M_GOT_MIXED; + sdp->sd_flags |= FLG_SY_SMGOT; + } + break; + } + return (1); + } + plnp = 0; for (LIST_TRAVERSE(lst, lnp, _gnp)) { if (_gnp->gn_addend > raddend) @@ -1924,10 +1960,11 @@ if (rsp->rel_rtype == R_SPARC_GOT13) { gnp->gn_gotndx = M_GOT_SMALL; - smlgotcnt++; + smlgotcnt += gotents; sdp->sd_flags |= FLG_SY_SMGOT; - } else + } else { gnp->gn_gotndx = M_GOT_LARGE; + } if (gref == GOT_REF_TLSLD) { ofl->ofl_tlsldgotndx = gnp; @@ -1966,30 +2003,57 @@ uintptr_t ld_allocate_got(Ofl_desc * ofl) { + const Sword first_large_ndx = M_GOT_MAXSMALL / 2; Sym_desc * sdp; Addr addr; /* - * Sanity check -- is this going to fit at all? + * Sanity check -- is this going to fit at all? There are two + * limits to be concerned about: + * 1) There is a limit on the number of small pic GOT indices, + * given by M_GOT_MAXSMALL. + * 2) If there are more than (M_GOT_MAXSMALL/2 - M_GOT_XNumber) + * small GOT indices, there will be items at negative + * offsets from _GLOBAL_OFFSET_TABLE_. Items that are + * accessed via large (PIC) code cannot reach these + * negative slots, so mixed mode items must be in the + * non-negative range. This implies a limit of + * (M_GOT_MAXSMALL/2 - M_GOT_XNumber) mixed mode indices. */ - if (smlgotcnt >= M_GOT_MAXSMALL) { + if (smlgotcnt > M_GOT_MAXSMALL) { eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_REL_SMALLGOT), EC_WORD(smlgotcnt), M_GOT_MAXSMALL); return (S_ERROR); } + if (mixgotcnt > (first_large_ndx - M_GOT_XNumber)) { + eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_REL_MIXEDGOT), + EC_WORD(mixgotcnt), first_large_ndx - M_GOT_XNumber); + return (S_ERROR); + } /* * Set starting offset to be either 0, or a negative index into * the GOT based on the number of small symbols we've got. */ - neggotoffset = ((smlgotcnt > (M_GOT_MAXSMALL / 2)) ? - -((smlgotcnt - (M_GOT_MAXSMALL / 2))) : 0); + neggotoffset = ((smlgotcnt >= first_large_ndx) ? + (first_large_ndx - smlgotcnt) : 0); /* - * Initialize the large and small got offsets (used in assign_got()). + * Initialize the got offsets used by assign_got() to + * locate GOT items: + * small - Starting index of items referenced only + * by small offsets (-Kpic). + * mixed - Starting index of items referenced + * by both large (-KPIC) and small (-Kpic). + * large - Indexes referenced only by large (-KPIC) + * + * Small items can have negative indexes (i.e. lie below + * _GLOBAL_OFFSET_TABLE_). Mixed and large items must have + * non-negative offsets. */ - small_index = neggotoffset == 0 ? M_GOT_XNumber : neggotoffset; + small_index = (neggotoffset == 0) ? M_GOT_XNumber : neggotoffset; large_index = neggotoffset + smlgotcnt; + mixed_index = large_index - mixgotcnt; /* * Assign bias to GOT symbols.
--- a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg Mon Oct 01 09:45:31 2007 -0700 +++ b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg Mon Oct 01 10:33:16 2007 -0700 @@ -1205,7 +1205,7 @@ # Global offset table entries. -@ MSG_GOT_INDEX " [%ld]" +@ MSG_GOT_INDEX " [%d]" @ MSG_GOT_SMALL_PIC "pic" @ MSG_GOT_BIG_PIC "PIC"
--- a/usr/src/cmd/sgs/packages/common/SUNWonld-README Mon Oct 01 09:45:31 2007 -0700 +++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README Mon Oct 01 10:33:16 2007 -0700 @@ -1261,3 +1261,4 @@ 6603313 dlclose() can fail to unload objects after fix for 6573641 6234471 need a way to edit ELF objects PSARC/2007/509 elfedit +5035454 mixing -Kpic and -KPIC may cause SIGSEGV with -xarch=v9
--- a/usr/src/cmd/sgs/packages/inc.flg Mon Oct 01 09:45:31 2007 -0700 +++ b/usr/src/cmd/sgs/packages/inc.flg Mon Oct 01 10:33:16 2007 -0700 @@ -51,6 +51,7 @@ usr/src/cmd/sgs/messages \ usr/src/cmd/sgs/moe \ usr/src/cmd/sgs/elfdump \ + usr/src/cmd/sgs/elfedit \ usr/src/cmd/sgs/pvs \ usr/src/cmd/sgs/rtld \ usr/src/cmd/sgs/rtld.4.x \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/sgs/tools/libconv_mk_report_bufsize.pl Mon Oct 01 10:33:16 2007 -0700 @@ -0,0 +1,114 @@ +#!/usr/bin/perl + +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +#ident "%Z%%M% %I% %E% SMI" + +use warnings; +use strict; + +use vars qw($script $limit $i); + +$script = "libconv_mk_report_bufsize"; + + +# This perl script is used by the sgs/libconv makefile to generate an +# include file named report_bufsize.h. That include file is used to +# generate an error message that tells the programmer the required +# size for a libconv buffer type. +# +# For details of how that generated file is supposed to be used, please +# read the comment that is placed at the top of that file, the text of +# which is found further down in this script. + + +# Highest value to test for +((scalar(@ARGV) == 1) && (($limit = int($ARGV[0])) > 0)) || + die "usage: $script toplimit\n"; + +open(OFILE, ">report_bufsize.h") || + die "$script: Unable to create report_bufsize.h"; + + +print OFILE <<TEXT; +/* + * This file was generated by $script, + * from the libconv Makefile. + * + * Many of the buffer types defined in sgs/include/conv.h are defined + * as a fixed integer rather than using the actual size calculation that + * would take the lengths of all the possible strings into consideration. + * The code that implements the conversion function does the proper + * calculation. It is important that these two values be the same. + * + * It is done this way because: + * + * (1) The size calculation uses message length values only available + * within the file that implements the conversion function. + * (2) Separating the size calculation from the code that uses it + * would increase the odds of not updating both, and is + * therefore more error prone. + * + * If the public size in conv.h and the real size computed by the + * implementing module are not the same, memory corruption or wasted + * space will result. Therefore, the code is supposed to contain a + * preprocessor check that refuses to compile if they don't. This + * is easy to do, but when the sizes do not match, it can be tedious + * to determine the right size to set the conv.h value to. This file + * is used to help with that. + * + * Example: Suppose the external size declared in conv.h is + * CONV_DYN_FLAG_BUFSIZE, and the internal computed value based + * on the actual strings is FLAGSZ. The module would use the following + * to ensure they match: + * + * #if CONV_DYN_FLAG_BUFSIZE != FLAGSZ + * #define REPORT_BUFSIZE FLAGSZ + * #include "report_bufsize.h" + * #error "CONV_DYN_FLAG_BUFSIZE does not match FLAGSZ" + * #endif + * + * In the error case, report_bufsize.h is included. It will use a #warning + * preprocessor directive to show the current value of the REPORT_BUFSIZE + * macro. The programmer will therefore see a message giving the correct + * size of the value that should be defined in conv.h, followed by a + * #error line telling them which constant is at fault. + */ + +#ifndef REPORT_BUFSIZE +#error "REPORT_BUFSIZE must be defined before including report_bufsize.h" +TEXT + +for ($i = 1; $i <= $limit; $i++) { + print OFILE "#elif REPORT_BUFSIZE == $i\n"; + print OFILE "#warning \"The correct buffer size is $i\"\n"; +} + +print OFILE <<TEXT; +#else +#warning "report_bufsize.h encountered value larger than $limit. Please raise the limit and rerun" +#endif +TEXT + +close OFILE;