summaryrefslogtreecommitdiff
path: root/usr
diff options
context:
space:
mode:
authorrie <none@none>2007-11-29 08:50:31 -0800
committerrie <none@none>2007-11-29 08:50:31 -0800
commita194faf8907a6722dcf10ad16c6ca72c9b7bd0ba (patch)
treed24cfdf302395bb6cbc356d2192c9e42ba7951ea /usr
parent7a6460b615cb8a60e3de57d76ba619a0a253ff74 (diff)
downloadillumos-joyent-a194faf8907a6722dcf10ad16c6ca72c9b7bd0ba.tar.gz
6629404 ld with -z ignore doesn't scale
Diffstat (limited to 'usr')
-rw-r--r--usr/src/cmd/sgs/elfdump/common/elfdump.c2
-rw-r--r--usr/src/cmd/sgs/elfdump/common/fake_shdr.c1
-rw-r--r--usr/src/cmd/sgs/include/_string_table.h126
-rw-r--r--usr/src/cmd/sgs/include/debug.h2
-rw-r--r--usr/src/cmd/sgs/include/string_table.h101
-rw-r--r--usr/src/cmd/sgs/libld/common/sections.c191
-rw-r--r--usr/src/cmd/sgs/libld/common/syms.c10
-rw-r--r--usr/src/cmd/sgs/libld/common/update.c6
-rw-r--r--usr/src/cmd/sgs/liblddbg/common/cap.c1
-rw-r--r--usr/src/cmd/sgs/liblddbg/common/got.c2
-rw-r--r--usr/src/cmd/sgs/liblddbg/common/liblddbg.msg15
-rw-r--r--usr/src/cmd/sgs/liblddbg/common/llib-llddbg4
-rw-r--r--usr/src/cmd/sgs/liblddbg/common/sections.c63
-rw-r--r--usr/src/cmd/sgs/liblddbg/common/syminfo.c1
-rw-r--r--usr/src/cmd/sgs/liblddbg/common/syms.c22
-rw-r--r--usr/src/cmd/sgs/liblddbg/common/version.c2
-rw-r--r--usr/src/cmd/sgs/packages/common/SUNWonld-README1
-rw-r--r--usr/src/cmd/sgs/rtld/common/dlfcns.c1
-rw-r--r--usr/src/cmd/sgs/tools/common/sgsmsg.c78
-rw-r--r--usr/src/cmd/sgs/tools/common/string_table.c572
20 files changed, 653 insertions, 548 deletions
diff --git a/usr/src/cmd/sgs/elfdump/common/elfdump.c b/usr/src/cmd/sgs/elfdump/common/elfdump.c
index 0bb56ca130..e19f5f7a8c 100644
--- a/usr/src/cmd/sgs/elfdump/common/elfdump.c
+++ b/usr/src/cmd/sgs/elfdump/common/elfdump.c
@@ -33,6 +33,7 @@
#include <sys/elf_amd64.h>
#include <sys/elf_SPARC.h>
#include <dwarf.h>
+#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <strings.h>
@@ -42,7 +43,6 @@
#include <_elfdump.h>
-
/*
* VERSYM_STATE is used to maintain information about the VERSYM section
* in the object being analyzed. It is filled in by versions(), and used
diff --git a/usr/src/cmd/sgs/elfdump/common/fake_shdr.c b/usr/src/cmd/sgs/elfdump/common/fake_shdr.c
index 6484f48bce..f6f6d6eb25 100644
--- a/usr/src/cmd/sgs/elfdump/common/fake_shdr.c
+++ b/usr/src/cmd/sgs/elfdump/common/fake_shdr.c
@@ -63,6 +63,7 @@
#include <machdep.h>
#include <sys/elf_amd64.h>
+#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
diff --git a/usr/src/cmd/sgs/include/_string_table.h b/usr/src/cmd/sgs/include/_string_table.h
new file mode 100644
index 0000000000..de0955ec58
--- /dev/null
+++ b/usr/src/cmd/sgs/include/_string_table.h
@@ -0,0 +1,126 @@
+/*
+ * 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
+ */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef __STRING_TABLE_DOT_H
+#define __STRING_TABLE_DOT_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include <sys/avl.h>
+#include <string_table.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * A string is represented in a string table using two values: length, and
+ * value. Grouping all the strings of a given length together allows for
+ * efficient matching of tail strings, as each input string value is hashed.
+ * Each string table uses a 2-level AVL tree of AVL trees to represent this
+ * organization.
+ *
+ * The outer (main) AVL tree contains LenNode structures. The search key for
+ * nodes on this main tree is the string length. Each such node represents
+ * all strings of a given length, and all strings of that length are found
+ * within.
+ *
+ * The strings within each LenNode are maintained using a secondary AVL tree
+ * of StrNode structures. The search key for this inner tree is the string
+ * itself. The strings are maintained in lexical order.
+ */
+typedef struct {
+ avl_node_t sn_avlnode; /* AVL book-keeping */
+ const char *sn_str; /* string */
+ uint_t sn_refcnt; /* reference count */
+} StrNode;
+
+typedef struct {
+ avl_node_t ln_avlnode; /* AVL book-keeping */
+ avl_tree_t *ln_strtree; /* AVL tree of associated strings */
+ uint_t ln_strlen; /* length of associated strings */
+} LenNode;
+
+/*
+ * Define a master string data item. Other strings may be suffixes of this
+ * string. The final string table will consist of the master string values,
+ * laid end to end, with the other strings referencing their tails.
+ */
+typedef struct str_master Str_master;
+
+struct str_master {
+ const char *sm_str; /* pointer to master string */
+ Str_master *sm_next; /* used for tracking master strings */
+ uint_t sm_strlen; /* length of master string */
+ uint_t sm_hashval; /* hashval of master string */
+ uint_t sm_stroff; /* offset into destination strtab */
+};
+
+/*
+ * Define a hash data item. This item represents an individual string that has
+ * been input into the String hash table. The string may either be a suffix of
+ * another string, or a master string.
+ */
+typedef struct str_hash Str_hash;
+
+struct str_hash {
+ uint_t hi_strlen; /* string length */
+ uint_t hi_refcnt; /* number of references to str */
+ uint_t hi_hashval; /* hash for string */
+ Str_master *hi_mstr; /* pointer to master string */
+ Str_hash *hi_next; /* next entry in hash bucket */
+};
+
+/*
+ * Controlling data structure for a String Table.
+ */
+struct str_tbl {
+ avl_tree_t *st_lentree; /* AVL tree of string lengths */
+ char *st_strbuf; /* string buffer */
+ Str_hash **st_hashbcks; /* hash buckets */
+ Str_master *st_mstrlist; /* list of all master strings */
+ uint_t st_fullstrsize; /* uncompressed table size */
+ uint_t st_nextoff; /* next available string */
+ uint_t st_strsize; /* compressed size */
+ uint_t st_strcnt; /* number of strings */
+ uint_t st_hbckcnt; /* number of buckets in */
+ /* hashlist */
+ uint_t st_flags;
+};
+
+#define FLG_STTAB_COMPRESS 0x01 /* compressed string table */
+#define FLG_STTAB_COOKED 0x02 /* offset has been assigned */
+
+/*
+ * Starting value for use with string hashing functions inside of string_table.c
+ */
+#define HASHSEED 5381
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STRING_TABLE_DOT_H */
diff --git a/usr/src/cmd/sgs/include/debug.h b/usr/src/cmd/sgs/include/debug.h
index b777961190..bb77b596d4 100644
--- a/usr/src/cmd/sgs/include/debug.h
+++ b/usr/src/cmd/sgs/include/debug.h
@@ -786,7 +786,7 @@ extern void Dbg_syms_ar_resolve(Lm_list *, Xword, Elf_Arsym *,
const char *, int);
extern void Dbg_syms_ar_title(Lm_list *, const char *, int);
extern void Dbg_syms_created(Lm_list *, const char *);
-extern void Dbg_syms_discarded(Lm_list *, Sym_desc *, Is_desc *);
+extern void Dbg_syms_discarded(Lm_list *, Sym_desc *);
extern void Dbg_syms_dlsym(Rt_map *, const char *, const char *, int);
extern void Dbg_syms_dup_sort_addr(Lm_list *, const char *, const char *,
const char *, Addr);
diff --git a/usr/src/cmd/sgs/include/string_table.h b/usr/src/cmd/sgs/include/string_table.h
index 433ca394e2..1bd2d383e2 100644
--- a/usr/src/cmd/sgs/include/string_table.h
+++ b/usr/src/cmd/sgs/include/string_table.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * 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.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -29,109 +28,33 @@
#pragma ident "%Z%%M% %I% %E% SMI"
-#include <stdio.h>
#include <sys/types.h>
-#include <sys/avl.h>
-#include <sgs.h>
#ifdef __cplusplus
extern "C" {
#endif
-typedef struct str_hash Str_hash;
-typedef struct str_tbl Str_tbl;
-typedef struct str_master Str_master;
-
-
-/*
- * The Stringlist is the list of 'input strings'
- * associatied with the AVL nodes Stringelem.
- */
-typedef struct stringlist {
- const char *sl_string;
- struct stringlist *sl_next;
-} Stringlist;
-
-/*
- * Nodes for the initial AVL tree which contains all of
- * the input strings. The AVL tree is indexed off of
- * the length of the strings. This permits later traversal
- * of all of the strings based off of their string length.
- */
-typedef struct {
- avl_node_t se_avlnode;
- Stringlist *se_strlist;
- uint_t se_stlen;
-} Stringelem;
-
-
-/*
- * Pointer to the Master string, other strings may be suffixes
- * of this string.
- */
-struct str_master {
- const char *sm_str; /* pointer to master string */
- Str_master *sm_next; /* used for tracking master strings */
- uint_t sm_stlen; /* length of master string */
- uint_t sm_hashval; /* hashval of master string */
- uint_t sm_stoff; /* offset into destination strtab */
-};
-
-
-/*
- * Represents a individual string that was input into
- * the String hash table. The string may either be a
- * suffix of another string or a master string.
- */
-struct str_hash {
- uint_t hi_stlen; /* string length */
- uint_t hi_refcnt; /* # of references to str */
- uint_t hi_hashval; /* hash for string */
- Str_master *hi_mstr; /* pointer to master string */
- Str_hash *hi_next; /* next entry in hash bckt */
-};
-
-/*
- * Controlling data structure for a String Table
- */
-struct str_tbl {
- avl_tree_t *st_strtree; /* avl tree of initial strs */
- char *st_strbuf; /* string buffer */
- Str_hash **st_hashbcks; /* hash buckets */
- Str_master *st_mstrlist; /* list of all master strings */
- uint_t st_fullstringsize; /* uncompressed table size */
- uint_t st_nextoff; /* next available string */
- uint_t st_stringsize; /* compressed size */
- uint_t st_stringcnt; /* # of strings */
- uint_t st_hbckcnt; /* # of buckets in hashlist */
- uint_t st_flags;
-};
-
-#define FLG_STTAB_COOKED 0x00000001 /* offset has been assigned */
-#define FLG_STTAB_COMPRESS 0x00000002 /* build compressed str tab */
-
-/*
- * starting value for use with string hashing functions
- * inside of string_table.c
- */
-#define HASHSEED 5381
-
/*
- * Flags for st_new
+ * Exported, opaque string table handle.
*/
-#define FLG_STNEW_COMPRESS 0x00000001 /* build compressed str tab */
+typedef struct str_tbl Str_tbl;
/*
- * exported string_table.c functions
+ * Exported string table functions.
*/
extern int st_delstring(Str_tbl *, const char *);
extern void st_destroy(Str_tbl *);
extern uint_t st_getstrtab_sz(Str_tbl *);
extern const char *st_getstrbuf(Str_tbl *);
extern int st_insert(Str_tbl *, const char *);
+extern Str_tbl *st_new(uint_t);
extern int st_setstrbuf(Str_tbl *, char *, uint_t);
extern int st_setstring(Str_tbl *, const char *, uint_t *);
-extern Str_tbl *st_new(uint_t);
+
+/*
+ * Exported flags values for st_new().
+ */
+#define FLG_STNEW_COMPRESS 0x01 /* compressed string table */
#ifdef __cplusplus
}
diff --git a/usr/src/cmd/sgs/libld/common/sections.c b/usr/src/cmd/sgs/libld/common/sections.c
index ff0226c683..9d90bad446 100644
--- a/usr/src/cmd/sgs/libld/common/sections.c
+++ b/usr/src/cmd/sgs/libld/common/sections.c
@@ -39,7 +39,7 @@
#include "msg.h"
#include "_libld.h"
-static void
+inline static void
remove_local(Ofl_desc *ofl, Sym_desc *sdp, int allow_ldynsym)
{
Sym *sym = sdp->sd_sym;
@@ -49,11 +49,13 @@ remove_local(Ofl_desc *ofl, Sym_desc *sdp, int allow_ldynsym)
if ((ofl->ofl_flags1 & FLG_OF1_REDLSYM) == 0) {
ofl->ofl_locscnt--;
+
err = st_delstring(ofl->ofl_strtab, sdp->sd_name);
assert(err != -1);
if (allow_ldynsym && ldynsym_symtype[type]) {
ofl->ofl_dynlocscnt--;
+
err = st_delstring(ofl->ofl_dynstrtab, sdp->sd_name);
assert(err != -1);
/* Remove from sort section? */
@@ -63,7 +65,7 @@ remove_local(Ofl_desc *ofl, Sym_desc *sdp, int allow_ldynsym)
sdp->sd_flags |= FLG_SY_ISDISC;
}
-static void
+inline static void
remove_scoped(Ofl_desc *ofl, Sym_desc *sdp, int allow_ldynsym)
{
Sym *sym = sdp->sd_sym;
@@ -79,6 +81,7 @@ remove_scoped(Ofl_desc *ofl, Sym_desc *sdp, int allow_ldynsym)
if (allow_ldynsym && ldynsym_symtype[type]) {
ofl->ofl_dynscopecnt--;
+
err = st_delstring(ofl->ofl_dynstrtab, sdp->sd_name);
assert(err != -1);
/* Remove from sort section? */
@@ -87,11 +90,80 @@ remove_scoped(Ofl_desc *ofl, Sym_desc *sdp, int allow_ldynsym)
sdp->sd_flags1 |= FLG_SY1_ELIM;
}
-#pragma inline(remove_local)
-#pragma inline(remove_scoped)
+inline static void
+ignore_sym(Ofl_desc *ofl, Ifl_desc *ifl, Sym_desc *sdp, int allow_ldynsym)
+{
+ Os_desc *osp;
+ Is_desc *isp = sdp->sd_isc;
+ uchar_t bind = ELF_ST_BIND(sdp->sd_sym->st_info);
+
+ if (bind == STB_LOCAL) {
+ uchar_t type = ELF_ST_TYPE(sdp->sd_sym->st_info);
+
+ /*
+ * Skip section symbols, these were never collected in the
+ * first place.
+ */
+ if (type == STT_SECTION)
+ return;
+
+ /*
+ * Determine if the whole file is being removed. Remove any
+ * file symbol, and any symbol that is not associated with a
+ * section, provided the symbol has not been identified as
+ * (update) required.
+ */
+ if (((ifl->ifl_flags & FLG_IF_FILEREF) == 0) &&
+ ((type == STT_FILE) || ((isp == NULL) &&
+ ((sdp->sd_flags & FLG_SY_UPREQD) == 0)))) {
+ DBG_CALL(Dbg_syms_discarded(ofl->ofl_lml, sdp));
+ if (ifl->ifl_flags & FLG_IF_IGNORE)
+ remove_local(ofl, sdp, allow_ldynsym);
+ return;
+ }
+
+ } else {
+ /*
+ * Global symbols can only be eliminated when the interfaces of
+ * an object have been defined via versioning/scoping.
+ */
+ if ((sdp->sd_flags1 & FLG_SY1_HIDDEN) == 0)
+ return;
+
+ /*
+ * Remove any unreferenced symbols that are not associated with
+ * a section.
+ */
+ if ((isp == NULL) && ((sdp->sd_flags & FLG_SY_UPREQD) == 0)) {
+ DBG_CALL(Dbg_syms_discarded(ofl->ofl_lml, sdp));
+ if (ifl->ifl_flags & FLG_IF_IGNORE)
+ remove_scoped(ofl, sdp, allow_ldynsym);
+ return;
+ }
+ }
+
+ /*
+ * Do not discard any symbols that are associated with non-allocable
+ * segments.
+ */
+ if (isp && ((isp->is_flags & FLG_IS_SECTREF) == 0) &&
+ ((osp = isp->is_osdesc) != 0) &&
+ (osp->os_sgdesc->sg_phdr.p_type == PT_LOAD)) {
+ DBG_CALL(Dbg_syms_discarded(ofl->ofl_lml, sdp));
+ if (ifl->ifl_flags & FLG_IF_IGNORE) {
+ if (bind == STB_LOCAL)
+ remove_local(ofl, sdp, allow_ldynsym);
+ else
+ remove_scoped(ofl, sdp, allow_ldynsym);
+ }
+ }
+}
/*
- * If -zignore is in effect, scan all input sections to see if there are any
+ * If -zignore has been in effect, scan all input files to determine if the
+ * file, or sections from the file, have been referenced. If not, the file or
+ * some of the files sections can be discarded.
+ *
* which haven't been referenced (and hence can be discarded). If sections are
* to be discarded, rescan the output relocations and the symbol table and
* remove the relocations and symbol entries that are no longer required.
@@ -112,9 +184,7 @@ ignore_section_processing(Ofl_desc *ofl)
Listnode *lnp;
Ifl_desc *ifl;
Rel_cache *rcp;
- int allow_ldynsym;
-
- allow_ldynsym = OFL_ALLOW_LDYNSYM(ofl);
+ int allow_ldynsym = OFL_ALLOW_LDYNSYM(ofl);
for (LIST_TRAVERSE(&ofl->ofl_objs, lnp, ifl)) {
uint_t num, discard;
@@ -165,82 +235,28 @@ ignore_section_processing(Ofl_desc *ofl)
*/
for (num = 1; num < ifl->ifl_symscnt; num++) {
Sym_desc *sdp;
- Sym *symp;
- Os_desc *osp;
- /* LINTED - only used for assert() */
- int err;
- uchar_t type;
-
- sdp = ifl->ifl_oldndx[num];
- symp = sdp->sd_sym;
- type = ELF_ST_TYPE(symp->st_info);
/*
- * If the whole file is being eliminated, remove the
- * local file symbol, and any COMMON symbols (which
- * aren't associated with a section) provided they
- * haven't been referenced by a relocation.
+ * If the symbol definition has been resolved to another
+ * file, or the symbol has already been discarded or
+ * eliminated, skip it.
*/
- if ((ofl->ofl_flags1 & FLG_OF1_IGNORE) &&
- ((ifl->ifl_flags & FLG_IF_FILEREF) == 0) &&
- ((type == STT_FILE) ||
- ((symp->st_shndx == SHN_COMMON) &&
- ((sdp->sd_flags & FLG_SY_UPREQD) == 0)))) {
- remove_local(ofl, sdp, allow_ldynsym);
- continue;
- }
-
- /*
- * Skip any undefined, reserved section symbols, already
- * discarded or eliminated symbols. Also skip any
- * symbols that don't originate from a section, or
- * aren't defined from the file being examined.
- */
- if ((symp->st_shndx == SHN_UNDEF) ||
- (symp->st_shndx >= SHN_LORESERVE) ||
- (type == STT_SECTION) ||
+ sdp = ifl->ifl_oldndx[num];
+ if ((sdp->sd_file != ifl) ||
(sdp->sd_flags & FLG_SY_ISDISC) ||
- (sdp->sd_flags1 & FLG_SY1_ELIM) ||
- (sdp->sd_isc == 0) || (sdp->sd_file != ifl))
+ (sdp->sd_flags1 & FLG_SY1_ELIM))
continue;
/*
- * If any references were made against the section
- * the symbol is being defined in - skip it.
+ * Complete the investigation of the symbol.
*/
- if ((sdp->sd_isc->is_flags & FLG_IS_SECTREF) ||
- ((ifl->ifl_flags & FLG_IF_FILEREF) &&
- ((osp = sdp->sd_isc->is_osdesc) != 0) &&
- (osp->os_sgdesc->sg_phdr.p_type != PT_LOAD)))
- continue;
-
- /*
- * Finish processing any local symbols.
- */
- if (ELF_ST_BIND(symp->st_info) == STB_LOCAL) {
- if (ofl->ofl_flags1 & FLG_OF1_IGNORE)
- remove_local(ofl, sdp, allow_ldynsym);
-
- DBG_CALL(Dbg_syms_discarded(ofl->ofl_lml,
- sdp, sdp->sd_isc));
- continue;
- }
-
- /*
- * Global symbols can only be eliminated when an objects
- * interfaces (versioning/scoping) is defined.
- */
- if (sdp->sd_flags1 & FLG_SY1_HIDDEN) {
- if (ofl->ofl_flags1 & FLG_OF1_IGNORE)
- remove_scoped(ofl, sdp, allow_ldynsym);
-
- DBG_CALL(Dbg_syms_discarded(ofl->ofl_lml,
- sdp, sdp->sd_isc));
- continue;
- }
+ ignore_sym(ofl, ifl, sdp, allow_ldynsym);
}
}
+ /*
+ * If we were only here to solicit debugging diagnostics, we're done.
+ */
if ((ofl->ofl_flags1 & FLG_OF1_IGNPRC) == 0)
return (1);
@@ -249,45 +265,44 @@ ignore_section_processing(Ofl_desc *ofl)
* ignored sections. If one is found, decrement the total outrel count.
*/
for (LIST_TRAVERSE(&ofl->ofl_outrels, lnp, rcp)) {
- Rel_desc *orsp;
- Os_desc *relosp;
+ Rel_desc *rsp;
+ Os_desc *osp;
/* LINTED */
- for (orsp = (Rel_desc *)(rcp + 1);
- orsp < rcp->rc_free; orsp++) {
- Is_desc *_isdesc = orsp->rel_isdesc;
+ for (rsp = (Rel_desc *)(rcp + 1); rsp < rcp->rc_free; rsp++) {
+ Is_desc *isc = rsp->rel_isdesc;
uint_t flags, entsize;
Shdr *shdr;
Ifl_desc *ifl;
- if ((_isdesc == 0) ||
- ((_isdesc->is_flags & (FLG_IS_SECTREF))) ||
- ((ifl = _isdesc->is_file) == 0) ||
+ if ((isc == 0) ||
+ ((isc->is_flags & (FLG_IS_SECTREF))) ||
+ ((ifl = isc->is_file) == 0) ||
((ifl->ifl_flags & FLG_IF_IGNORE) == 0) ||
- ((shdr = _isdesc->is_shdr) == 0) ||
+ ((shdr = isc->is_shdr) == 0) ||
((shdr->sh_flags & SHF_ALLOC) == 0))
continue;
- flags = orsp->rel_flags;
+ flags = rsp->rel_flags;
if (flags & (FLG_REL_GOT | FLG_REL_BSS |
FLG_REL_NOINFO | FLG_REL_PLT))
continue;
- relosp = orsp->rel_osdesc;
+ osp = rsp->rel_osdesc;
- if (orsp->rel_flags & FLG_REL_RELA)
+ if (rsp->rel_flags & FLG_REL_RELA)
entsize = sizeof (Rela);
else
entsize = sizeof (Rel);
- assert(relosp->os_szoutrels > 0);
- relosp->os_szoutrels -= entsize;
+ assert(osp->os_szoutrels > 0);
+ osp->os_szoutrels -= entsize;
if (!(flags & FLG_REL_PLT))
ofl->ofl_reloccntsub++;
- if (orsp->rel_rtype == M_R_RELATIVE)
+ if (rsp->rel_rtype == M_R_RELATIVE)
ofl->ofl_relocrelcnt--;
}
}
diff --git a/usr/src/cmd/sgs/libld/common/syms.c b/usr/src/cmd/sgs/libld/common/syms.c
index 5052d81511..8ff5489872 100644
--- a/usr/src/cmd/sgs/libld/common/syms.c
+++ b/usr/src/cmd/sgs/libld/common/syms.c
@@ -73,7 +73,7 @@ ld_sym_avl_comp(const void *elem1, const void *elem2)
/*
* Focal point for verifying symbol names.
*/
-static const char *
+inline static const char *
string(Ofl_desc *ofl, Ifl_desc *ifl, Sym *sym, const char *strs, size_t strsize,
int symndx, Word shndx, const char *symsecname, const char *strsecname,
Word *flags)
@@ -231,7 +231,7 @@ ld_sym_find(const char *name, Word hash, avl_index_t *where, Ofl_desc *ofl)
/*
* Perform search for symbol in AVL tree. Note that the 'where' field
* is passed in from the caller. If a 'where' is present, it can be
- * used in subsequent 'sym_enter()' calls if required.
+ * used in subsequent 'ld_sym_enter()' calls if required.
*/
sav = avl_find(&ofl->ofl_symavl, &qsav, where);
@@ -1957,8 +1957,7 @@ ld_sym_process(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl)
if (sdp->sd_isc &&
(sdp->sd_isc->is_flags & FLG_IS_DISCARD)) {
sdp->sd_flags |= FLG_SY_ISDISC;
- DBG_CALL(Dbg_syms_discarded(ofl->ofl_lml,
- sdp, sdp->sd_isc));
+ DBG_CALL(Dbg_syms_discarded(ofl->ofl_lml, sdp));
continue;
}
@@ -2183,8 +2182,7 @@ ld_sym_process(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl)
sdp->sd_flags = FLG_SY_ISDISC;
ifl->ifl_oldndx[ndx] = sdp;
- DBG_CALL(Dbg_syms_discarded(ofl->ofl_lml, sdp,
- sdp->sd_isc));
+ DBG_CALL(Dbg_syms_discarded(ofl->ofl_lml, sdp));
continue;
}
}
diff --git a/usr/src/cmd/sgs/libld/common/update.c b/usr/src/cmd/sgs/libld/common/update.c
index 858f5c9289..503415692e 100644
--- a/usr/src/cmd/sgs/libld/common/update.c
+++ b/usr/src/cmd/sgs/libld/common/update.c
@@ -1927,7 +1927,8 @@ update_osym(Ofl_desc *ofl)
dynsort_compare_syms = ldynsym;
qsort(dynsymsort, dynsymsort_ndx,
sizeof (*dynsymsort), dynsort_compare);
- dynsort_dupwarn(ofl, ldynsym, dynstr->st_strbuf,
+ dynsort_dupwarn(ofl, ldynsym,
+ st_getstrbuf(dynstr),
dynsymsort, dynsymsort_ndx,
MSG_ORIG(MSG_SCN_DYNSYMSORT));
}
@@ -1941,7 +1942,8 @@ update_osym(Ofl_desc *ofl)
dynsort_compare_syms = ldynsym;
qsort(dyntlssort, dyntlssort_ndx,
sizeof (*dyntlssort), dynsort_compare);
- dynsort_dupwarn(ofl, ldynsym, dynstr->st_strbuf,
+ dynsort_dupwarn(ofl, ldynsym,
+ st_getstrbuf(dynstr),
dyntlssort, dyntlssort_ndx,
MSG_ORIG(MSG_SCN_DYNTLSSORT));
}
diff --git a/usr/src/cmd/sgs/liblddbg/common/cap.c b/usr/src/cmd/sgs/liblddbg/common/cap.c
index 6659c302cc..43f15883d5 100644
--- a/usr/src/cmd/sgs/liblddbg/common/cap.c
+++ b/usr/src/cmd/sgs/liblddbg/common/cap.c
@@ -25,6 +25,7 @@
*/
#pragma ident "%Z%%M% %I% %E% SMI"
+#include <stdio.h>
#include <debug.h>
#include <libld.h>
#include <conv.h>
diff --git a/usr/src/cmd/sgs/liblddbg/common/got.c b/usr/src/cmd/sgs/liblddbg/common/got.c
index 7494a7a19c..17fe407110 100644
--- a/usr/src/cmd/sgs/liblddbg/common/got.c
+++ b/usr/src/cmd/sgs/liblddbg/common/got.c
@@ -25,7 +25,7 @@
*/
#pragma ident "%Z%%M% %I% %E% SMI"
-#include <stdlib.h>
+#include <stdio.h>
#include "_debug.h"
#include "msg.h"
#include "libld.h"
diff --git a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg
index 1f19a9e207..b5b412568c 100644
--- a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg
+++ b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg
@@ -566,12 +566,11 @@
discarded: member of existing group: %s:%s"
@ MSG_SEC_STRTAB_STND "strtab=%s; full size: %d; uncompressed"
-@ MSG_SEC_STRTAB_COMP "strtab=%s; full size: %d -> compressed down to: %d"
-@ MSG_SEC_STRTAB_HD "Compressed String Table: %s \
- [%d buckets]:"
-@ MSG_SEC_STRTAB_BCKT " Bucket[%3d]:"
-@ MSG_SEC_STRTAB_MSTR " ref[%2d] %s <master>"
-@ MSG_SEC_STRTAB_SUFSTR " ref[%2d] %s <suffix of> %s"
+@ MSG_SEC_STRTAB_COMP "strtab=%s; full size: %d; compressed down to: %d"
+@ MSG_SEC_STRTAB_HD "strtab=%s; compression information [%d buckets]:"
+@ MSG_SEC_STRTAB_BCKT " bucket[%d]:"
+@ MSG_SEC_STRTAB_MSTR " [%d] %s <master>"
+@ MSG_SEC_STRTAB_SUFSTR " [%d] %s <suffix of: %s>"
# Unused messages
@@ -638,8 +637,10 @@
@ MSG_SYM_ELIMINATING "symbol=%s; eliminating"
@ MSG_SYM_NOTELIMINATE "symbol=%s; not eliminated: referenced by \
section=%s, entry[%d]"
-@ MSG_SYM_DISCARDED "symbol=%s; discarded because it is part of \
+@ MSG_SYM_DISCARD_SEC "symbol=%s; discarded: originates from unused or \
discarded section=%s from file=%s"
+@ MSG_SYM_DISCARD_FILE "symbol=%s; discarded: originates from unused or \
+ discarded file=%s"
@ MSG_SYM_AOUT "symbol=%s; (original AOUT name)"
@ MSG_SYM_LOOKUP "symbol=%s; lookup in file=%s [ %s ]"
diff --git a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg
index 73122cd337..fbabd9b205 100644
--- a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg
+++ b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg
@@ -342,8 +342,8 @@ void Dbg32_syms_ar_title(Lm_list *, const char *, int);
void Dbg64_syms_ar_title(Lm_list *, const char *, int);
void Dbg32_syms_created(Lm_list *, const char *);
void Dbg64_syms_created(Lm_list *, const char *);
-void Dbg32_syms_discarded(Lm_list *, Sym_desc *, Is_desc *);
-void Dbg64_syms_discarded(Lm_list *, Sym_desc *, Is_desc *);
+void Dbg32_syms_discarded(Lm_list *, Sym_desc *);
+void Dbg64_syms_discarded(Lm_list *, Sym_desc *);
void Dbg32_syms_dlsym(Rt_map *, const char *, const char *, int);
void Dbg64_syms_dlsym(Rt_map *, const char *, const char *, int);
void Dbg32_syms_entered(Ofl_desc *, Sym *, Sym_desc *);
diff --git a/usr/src/cmd/sgs/liblddbg/common/sections.c b/usr/src/cmd/sgs/liblddbg/common/sections.c
index a88653f084..bd1b76e2de 100644
--- a/usr/src/cmd/sgs/liblddbg/common/sections.c
+++ b/usr/src/cmd/sgs/liblddbg/common/sections.c
@@ -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.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -28,23 +28,12 @@
#include "msg.h"
#include "_debug.h"
#include "libld.h"
-
-/*
- * Error message string table.
- */
-static const Msg order_errors[] = {
- MSG_ORD_ERR_INFORANGE, /* MSG_INTL(MSG_ORD_ERR_INFORANGE) */
- MSG_ORD_ERR_ORDER, /* MSG_INTL(MSG_ORD_ERR_ORDER) */
- MSG_ORD_ERR_LINKRANGE, /* MSG_INTL(MSG_ORD_ERR_LINKRANGE) */
- MSG_ORD_ERR_FLAGS, /* MSG_INTL(MSG_ORD_ERR_FLAGS) */
- MSG_ORD_ERR_CYCLIC, /* MSG_INTL(MSG_ORD_ERR_CYCLIC) */
- MSG_ORD_ERR_LINKINV /* MSG_INTL(MSG_ORD_ERR_LINKINV) */
-};
+#include "_string_table.h"
void
Dbg_sec_strtab(Lm_list *lml, Os_desc *osp, Str_tbl *stp)
{
- uint_t i;
+ uint_t cnt;
if (DBG_NOTCLASS(DBG_C_STRTAB))
return;
@@ -55,10 +44,10 @@ Dbg_sec_strtab(Lm_list *lml, Os_desc *osp, Str_tbl *stp)
Dbg_util_nl(lml, DBG_NL_STD);
if (stp->st_flags & FLG_STTAB_COMPRESS)
dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_COMP), osp->os_name,
- stp->st_fullstringsize, stp->st_stringsize);
+ stp->st_fullstrsize, stp->st_strsize);
else
dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_STND), osp->os_name,
- stp->st_fullstringsize);
+ stp->st_fullstrsize);
if ((DBG_NOTDETAIL()) ||
((stp->st_flags & FLG_STTAB_COMPRESS) == 0))
@@ -68,27 +57,31 @@ Dbg_sec_strtab(Lm_list *lml, Os_desc *osp, Str_tbl *stp)
dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_HD), osp->os_name,
stp->st_hbckcnt);
- for (i = 0; i < stp->st_hbckcnt; i++) {
- Str_hash *sthash;
+ for (cnt = 0; cnt < stp->st_hbckcnt; cnt++) {
+ Str_hash *strhash = stp->st_hashbcks[cnt];
+
+ if (strhash == 0)
+ continue;
- dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_BCKT), i);
+ dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_BCKT), cnt);
- for (sthash = stp->st_hashbcks[i]; sthash;
- sthash = sthash->hi_next) {
- uint_t stroff = sthash->hi_mstr->sm_stlen -
- sthash->hi_stlen;
+ while (strhash) {
+ uint_t stroff = strhash->hi_mstr->sm_strlen -
+ strhash->hi_strlen;
if (stroff == 0) {
dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_MSTR),
- sthash->hi_refcnt, sthash->hi_mstr->sm_str);
+ strhash->hi_refcnt,
+ strhash->hi_mstr->sm_str);
} else {
dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_SUFSTR),
- sthash->hi_refcnt,
- &sthash->hi_mstr->sm_str[stroff],
- sthash->hi_mstr->sm_str);
+ strhash->hi_refcnt,
+ &strhash->hi_mstr->sm_str[stroff],
+ strhash->hi_mstr->sm_str);
}
- }
+ strhash = strhash->hi_next;
+ }
}
}
@@ -143,7 +136,7 @@ Dbg_sec_created(Lm_list *lml, Os_desc *osp, Sg_desc *sgp)
void
Dbg_sec_discarded(Lm_list *lml, Is_desc *isp, Is_desc *disp)
{
- if (DBG_NOTCLASS(DBG_C_SECTIONS))
+ if (DBG_NOTCLASS(DBG_C_SECTIONS | DBG_C_UNUSED))
return;
dbg_print(lml, MSG_INTL(MSG_SEC_DISCARDED), isp->is_basename,
@@ -244,6 +237,18 @@ Dbg_sec_order_list(Ofl_desc *ofl, int flag)
Dbg_util_nl(lml, DBG_NL_STD);
}
+/*
+ * Error message string table.
+ */
+static const Msg order_errors[] = {
+ MSG_ORD_ERR_INFORANGE, /* MSG_INTL(MSG_ORD_ERR_INFORANGE) */
+ MSG_ORD_ERR_ORDER, /* MSG_INTL(MSG_ORD_ERR_ORDER) */
+ MSG_ORD_ERR_LINKRANGE, /* MSG_INTL(MSG_ORD_ERR_LINKRANGE) */
+ MSG_ORD_ERR_FLAGS, /* MSG_INTL(MSG_ORD_ERR_FLAGS) */
+ MSG_ORD_ERR_CYCLIC, /* MSG_INTL(MSG_ORD_ERR_CYCLIC) */
+ MSG_ORD_ERR_LINKINV /* MSG_INTL(MSG_ORD_ERR_LINKINV) */
+};
+
void
Dbg_sec_order_error(Lm_list *lml, Ifl_desc *ifl, Word ndx, int error)
{
diff --git a/usr/src/cmd/sgs/liblddbg/common/syminfo.c b/usr/src/cmd/sgs/liblddbg/common/syminfo.c
index f33b78066d..36aeecfe66 100644
--- a/usr/src/cmd/sgs/liblddbg/common/syminfo.c
+++ b/usr/src/cmd/sgs/liblddbg/common/syminfo.c
@@ -26,6 +26,7 @@
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sgs.h>
+#include <stdio.h>
#include <debug.h>
#include <msg.h>
diff --git a/usr/src/cmd/sgs/liblddbg/common/syms.c b/usr/src/cmd/sgs/liblddbg/common/syms.c
index fd81e514a2..03f302040a 100644
--- a/usr/src/cmd/sgs/liblddbg/common/syms.c
+++ b/usr/src/cmd/sgs/liblddbg/common/syms.c
@@ -178,20 +178,28 @@ Dbg_syms_spec_title(Lm_list *lml)
}
void
-Dbg_syms_discarded(Lm_list *lml, Sym_desc *sdp, Is_desc *disp)
+Dbg_syms_discarded(Lm_list *lml, Sym_desc *sdp)
{
- const char *sectname;
+ const char *file;
- if (DBG_NOTCLASS(DBG_C_SYMBOLS))
+ if (DBG_NOTCLASS(DBG_C_SYMBOLS | DBG_C_UNUSED))
return;
if (DBG_NOTDETAIL())
return;
- if ((sectname = disp->is_basename) == 0)
- sectname = disp->is_name;
+ if ((sdp->sd_file == NULL) || ((file = sdp->sd_file->ifl_name) == NULL))
+ file = MSG_INTL(MSG_STR_UNKNOWN);
+
+ if (sdp->sd_isc) {
+ const char *sec;
- dbg_print(lml, MSG_INTL(MSG_SYM_DISCARDED),
- Dbg_demangle_name(sdp->sd_name), sectname, disp->is_file->ifl_name);
+ if ((sec = sdp->sd_isc->is_basename) == 0)
+ sec = sdp->sd_isc->is_name;
+ dbg_print(lml, MSG_INTL(MSG_SYM_DISCARD_SEC),
+ Dbg_demangle_name(sdp->sd_name), sec, file);
+ } else
+ dbg_print(lml, MSG_INTL(MSG_SYM_DISCARD_FILE),
+ Dbg_demangle_name(sdp->sd_name), file);
}
void
diff --git a/usr/src/cmd/sgs/liblddbg/common/version.c b/usr/src/cmd/sgs/liblddbg/common/version.c
index 12fa399e76..914d5d11ec 100644
--- a/usr/src/cmd/sgs/liblddbg/common/version.c
+++ b/usr/src/cmd/sgs/liblddbg/common/version.c
@@ -25,7 +25,7 @@
*/
#pragma ident "%Z%%M% %I% %E% SMI"
-#include <link.h>
+#include <stdio.h>
#include <debug.h>
#include "msg.h"
#include "_debug.h"
diff --git a/usr/src/cmd/sgs/packages/common/SUNWonld-README b/usr/src/cmd/sgs/packages/common/SUNWonld-README
index a1c186c220..0438300045 100644
--- a/usr/src/cmd/sgs/packages/common/SUNWonld-README
+++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README
@@ -1300,3 +1300,4 @@ Bugid Risk Synopsis
PSARC/2007/620 elfdump -T, and simplified matching
6627765 soffice failure after integration of 6603313 - dangling GROUP pointer.
6319025 SUNWbtool packaging issues in Nevada and S10u1.
+6629404 ld with -z ignore doesn't scale
diff --git a/usr/src/cmd/sgs/rtld/common/dlfcns.c b/usr/src/cmd/sgs/rtld/common/dlfcns.c
index d4e54beca3..61038dbfed 100644
--- a/usr/src/cmd/sgs/rtld/common/dlfcns.c
+++ b/usr/src/cmd/sgs/rtld/common/dlfcns.c
@@ -35,6 +35,7 @@
#include "_synonyms.h"
#include <sys/debug.h>
+#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
#include <synch.h>
diff --git a/usr/src/cmd/sgs/tools/common/sgsmsg.c b/usr/src/cmd/sgs/tools/common/sgsmsg.c
index f2757508b4..3b06e5ff6a 100644
--- a/usr/src/cmd/sgs/tools/common/sgsmsg.c
+++ b/usr/src/cmd/sgs/tools/common/sgsmsg.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * 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.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*
* sgsmsg generates several message files from an input template file. Messages
* are constructed for use with gettext(3i) - the default - or catgets(3c). The
@@ -80,7 +79,7 @@
#include <sys/param.h>
#include <sgs.h>
-#include <string_table.h>
+#include <_string_table.h>
/*
* Define any error message strings.
@@ -150,14 +149,13 @@ message_append(const char *defn, const char *message)
(void) fprintf(stderr, Errmsg_nmem, strerror(errno));
exit(1);
}
- if (stp == 0) {
- /*
- * Initialize string table
- */
- if ((stp = st_new(FLG_STNEW_COMPRESS)) == 0) {
- (void) fprintf(stderr, Errmsg_stnw, strerror(errno));
- exit(1);
- }
+
+ /*
+ * Initialize the string table.
+ */
+ if ((stp == 0) && ((stp = st_new(FLG_STNEW_COMPRESS)) == NULL)) {
+ (void) fprintf(stderr, Errmsg_stnw, strerror(errno));
+ exit(1);
}
@@ -313,45 +311,51 @@ getmesgid(char *id)
return (0);
}
-
/*
* Dump contents of String Table to standard out
*/
static void
dump_stringtab(Str_tbl *stp)
{
- uint_t i;
+ uint_t cnt;
if ((stp->st_flags & FLG_STTAB_COMPRESS) == 0) {
- (void) printf("uncompressed strings: %d\n",
- stp->st_fullstringsize);
+ (void) printf("string table full size: %d: uncompressed\n",
+ stp->st_fullstrsize);
return;
}
+ (void) printf("string table full size: %d compressed down to: %d\n\n",
+ stp->st_fullstrsize, stp->st_strsize);
+ (void) printf("string table compression information [%d buckets]:\n",
+ stp->st_hbckcnt);
+
+ for (cnt = 0; cnt < stp->st_hbckcnt; cnt++) {
+ Str_hash *sthash = stp->st_hashbcks[cnt];
+
+ if (sthash == 0)
+ continue;
+
+ (void) printf(" bucket: [%d]\n", cnt);
+
+ while (sthash) {
+ uint_t stroff = sthash->hi_mstr->sm_strlen -
+ sthash->hi_strlen;
- for (i = 0; i < stp->st_hbckcnt; i++) {
- Str_hash *sthash;
- (void) printf("Bucket: [%3d]\n", i);
- for (sthash = stp->st_hashbcks[i]; sthash;
- sthash = sthash->hi_next) {
- uint_t stroff;
- stroff = sthash->hi_mstr->sm_stlen - sthash->hi_stlen;
if (stroff == 0) {
- (void) printf(" %2d %s <master>\n",
- sthash->hi_refcnt,
- sthash->hi_mstr->sm_str);
+ (void) printf(" [%d]: '%s' <master>\n",
+ sthash->hi_refcnt, sthash->hi_mstr->sm_str);
} else {
- const char *str;
- str = &sthash->hi_mstr->sm_str[stroff];
- (void) printf(" %2d %s <suffix of> -> %s\n",
- sthash->hi_refcnt,
- str, sthash->hi_mstr->sm_str);
+ (void) printf(" [%d]: '%s' <suffix of: "
+ "'%s'>\n", sthash->hi_refcnt,
+ &sthash->hi_mstr->sm_str[stroff],
+ sthash->hi_mstr->sm_str);
}
+ sthash = sthash->hi_next;
}
}
- (void) printf("fullstringsize: %d compressed: %d\n",
- stp->st_fullstringsize, stp->st_stringsize);
}
+
/*
* Initialize the message definition header file stream.
*/
@@ -519,7 +523,6 @@ fini_defs(void)
return (0);
}
-
/*
* The entire messaging file has been scanned - and all strings have been
* inserted into the string_table. We can now walk the message queue
@@ -899,6 +902,7 @@ message:
* unless an escape character is found
* terminate the data string with a 0.
*/
+ /* BEGIN CSTYLED */
if (*token == '"') {
if (fdlint && (fprintf(fdlint,
"%c", *token) < 0)) {
@@ -924,6 +928,7 @@ message:
_token = '\0';
} else
_token = *token;
+ /* END CSTYLED */
}
if (fdmsgs && (prtmsgs == 1) &&
@@ -1186,7 +1191,6 @@ main(int argc, char ** argv)
if (vflag)
dump_stringtab(stp);
-
/*
* Close up everything and go home.
*/
diff --git a/usr/src/cmd/sgs/tools/common/string_table.c b/usr/src/cmd/sgs/tools/common/string_table.c
index c8d0aacc63..b3b669a8c3 100644
--- a/usr/src/cmd/sgs/tools/common/string_table.c
+++ b/usr/src/cmd/sgs/tools/common/string_table.c
@@ -20,46 +20,42 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
-#include <string_table.h>
+#include <_string_table.h>
#include <strings.h>
#include <sgs.h>
#include <stdio.h>
-
-
/*
- * This file provides the interfaces to build a Str_tbl suitable
- * for use by either the sgsmsg system or a standard ELF
- * SHT_STRTAB.
+ * This file provides the interfaces to build a Str_tbl suitable for use by
+ * either the sgsmsg message system, or a standard ELF string table (SHT_STRTAB)
+ * as created by ld(1).
*
- * There are two modes which can be used when constructing a
- * string table:
+ * There are two modes which can be used when constructing a string table:
*
* st_new(0)
* standard string table - no compression. This is the
- * traditional method and fast
+ * traditional, fast method.
*
- * st_new(FLG_STNEW_COMPRESS)
- * build a compressed string table which both
- * eliminates duplicate strings and permits
- * strings with common suffixes (atexit vs. exit) to
- * overlap in the table. This provides space
- * savings for many string tables.
+ * st_new(FLG_STTAB_COMPRESS)
+ * builds a compressed string table which both eliminates
+ * duplicate strings, and permits strings with common suffixes
+ * (atexit vs. exit) to overlap in the table. This provides space
+ * savings for many string tables. Although more work than the
+ * traditional method, the algorithms used are designed to scale
+ * and keep any overhead at a minimum.
*
- * These string tables are now built with a common interface in a
- * two-pass manner, the first pass it to find all of the strings
- * required for the string-table and to calculate the size that
- * will be required for the final string table.
+ * These string tables are built with a common interface in a two-pass manner.
+ * The first pass finds all of the strings required for the string-table and
+ * calculates the size required for the final string table.
*
- * The second pass allocates the string table and populates the
- * strings into the table and returns the offsets the strings
- * have been assigned.
+ * The second pass allocates the string table, populates the strings into the
+ * table and returns the offsets the strings have been assigned.
*
* The calling sequence to build and populate a string table is:
*
@@ -71,7 +67,6 @@
*
* st_delstring(st?); // remove string previously
* // inserted
- *
* st_insert(stN);
*
* st_getstrtab_sz(); // freezes strtab and computes
@@ -113,219 +108,234 @@
* The above method will find all suffixes of a given string given
* that the strings are inserted from shortest to longest. That is
* why this is a two phase method, we first collect all of the
- * strings and store them based off of their length in a nice AVL tree.
+ * strings and store them based off of their length in an AVL tree.
* Once all of the strings have been submitted we then start the
* hash table build by traversing the AVL tree in order and
* inserting the strings from shortest to longest as described
* above.
- *
*/
/* LINTLIBRARY */
-
-int
-strlen_compare(const void *elem1, const void *elem2)
+static int
+avl_len_compare(const void *n1, const void *n2)
{
- uint_t l1, l2;
- l1 = ((Stringelem *)elem1)->se_stlen;
- l2 = ((Stringelem *)elem2)->se_stlen;
+ uint_t len1, len2;
+
+ len1 = ((LenNode *)n1)->ln_strlen;
+ len2 = ((LenNode *)n2)->ln_strlen;
- if (l1 == l2)
+ if (len1 == len2)
return (0);
- if (l2 < l1)
+ if (len2 < len1)
return (1);
-
return (-1);
}
+static int
+avl_str_compare(const void *n1, const void *n2)
+{
+ const char *str1, *str2;
+ int rc;
+
+ str1 = ((StrNode *)n1)->sn_str;
+ str2 = ((StrNode *)n2)->sn_str;
+
+ rc = strcmp(str1, str2);
+ if (rc > 0)
+ return (1);
+ if (rc < 0)
+ return (-1);
+ return (0);
+}
+
/*
- * Return a initialized Str_tbl - returns NULL on failure.
- *
- * stflags:
- *
- * FLG_STNEW_COMPRESS - build a compressed string table
+ * Return an initialized Str_tbl - returns NULL on failure.
*
+ * flags:
+ * FLG_STTAB_COMPRESS - build a compressed string table
*/
Str_tbl *
-st_new(uint_t stflags)
+st_new(uint_t flags)
{
Str_tbl *stp;
- if ((stp = calloc(sizeof (Str_tbl), 1)) == 0)
- return (0);
+ if ((stp = calloc(sizeof (Str_tbl), 1)) == NULL)
+ return (NULL);
/*
* Start with a leading '\0' - it's tradition.
*/
- stp->st_stringsize = stp->st_fullstringsize = stp->st_nextoff = 1;
+ stp->st_strsize = stp->st_fullstrsize = stp->st_nextoff = 1;
/*
- * Do we compress this string table
+ * Do we compress this string table?
*/
- if ((stflags & FLG_STNEW_COMPRESS) == 0)
+ stp->st_flags = flags;
+ if ((stp->st_flags & FLG_STTAB_COMPRESS) == 0)
return (stp);
- stp->st_flags |= FLG_STTAB_COMPRESS;
- if ((stp->st_strtree = calloc(sizeof (avl_tree_t), 1)) == 0) {
- return (0);
- }
+ if ((stp->st_lentree = calloc(sizeof (avl_tree_t), 1)) == NULL)
+ return (NULL);
- avl_create(stp->st_strtree, &strlen_compare, sizeof (Stringelem),
- SGSOFFSETOF(Stringelem, se_avlnode));
+ avl_create(stp->st_lentree, &avl_len_compare, sizeof (LenNode),
+ SGSOFFSETOF(LenNode, ln_avlnode));
return (stp);
}
/*
- * Tear down a String_Table structure.
- */
-void
-st_destroy(Str_tbl *stp)
-{
- Str_hash *sthash, *psthash;
- Str_master *mstr, *pmstr;
- uint_t i;
-
- /*
- * cleanup the master strings
- */
- for (mstr = stp->st_mstrlist, pmstr = 0; mstr;
- mstr = mstr->sm_next) {
- if (pmstr)
- free(pmstr);
- pmstr = mstr;
- }
- if (pmstr)
- free(pmstr);
-
- if (stp->st_hashbcks) {
- for (i = 0; i < stp->st_hbckcnt; i++) {
- for (sthash = stp->st_hashbcks[i], psthash = 0;
- sthash; sthash = sthash->hi_next) {
- if (psthash)
- free(psthash);
- psthash = sthash;
- }
- if (psthash)
- free(psthash);
- }
- free(stp->st_hashbcks);
- }
- free(stp);
-}
-
-
-
-
-/*
- * Remove a previously inserted string from the Str_tbl
+ * Insert a new string into the Str_tbl. There are two AVL trees used.
+ *
+ * . The first LenNode AVL tree maintains a tree of nodes based on string
+ * sizes.
+ * . Each LenNode maintains a StrNode AVL tree for each string. Large
+ * applications have been known to contribute thousands of strings of
+ * the same size. Should strings need to be removed (-z ignore), then
+ * the string AVL tree makes this removal efficient and scalable.
*/
int
-st_delstring(Str_tbl *stp, const char *str)
+st_insert(Str_tbl *stp, const char *str)
{
- uint_t stlen;
- Stringelem qstelem;
- Stringelem *stelem;
- Stringlist *stlist, *pstlist;
+ uint_t len;
+ StrNode *snp, sn = { 0 };
+ LenNode *lnp, ln = { 0 };
+ avl_index_t where;
/*
* String table can't have been cooked
*/
assert((stp->st_flags & FLG_STTAB_COOKED) == 0);
- stlen = (uint_t)strlen(str);
- stp->st_fullstringsize -= stlen + 1;
+ /*
+ * Null strings always point to the head of the string
+ * table - no reason to keep searching.
+ */
+ if ((len = (uint_t)strlen(str)) == 0)
+ return (0);
+
+ stp->st_fullstrsize += len + 1;
+ stp->st_strcnt++;
if ((stp->st_flags & FLG_STTAB_COMPRESS) == 0)
return (0);
- qstelem.se_stlen = stlen;
- if ((stelem = avl_find(stp->st_strtree, &qstelem, 0)) == NULL) {
- /*
- * no strings of this length recorded, let alone
- * this specific string - someone goofed.
- */
- return (-1);
- }
+ /*
+ * From the controlling string table, determine which LenNode AVL node
+ * provides for this string length. If the node doesn't exist, insert
+ * a new node to represent this string length.
+ */
+ ln.ln_strlen = len;
+ if ((lnp = avl_find(stp->st_lentree, &ln, &where)) == NULL) {
+ if ((lnp = calloc(sizeof (LenNode), 1)) == NULL)
+ return (-1);
+ lnp->ln_strlen = len;
+ avl_insert(stp->st_lentree, lnp, where);
- pstlist = 0;
- for (stlist = stelem->se_strlist; stlist; stlist = stlist->sl_next) {
- if (strcmp(str, stlist->sl_string) == 0)
- break;
- pstlist = stlist;
- }
+ if ((lnp->ln_strtree = calloc(sizeof (avl_tree_t), 1)) == NULL)
+ return (0);
- if (stlist == 0) {
- /*
- * string was not found
- */
- return (-1);
+ avl_create(lnp->ln_strtree, &avl_str_compare, sizeof (StrNode),
+ SGSOFFSETOF(StrNode, sn_avlnode));
}
- if (pstlist == 0) {
- /*
- * String is first on list.
- */
- stelem->se_strlist = stlist->sl_next;
- } else {
- /*
- * remove string from list.
- */
- pstlist->sl_next = stlist->sl_next;
+ /*
+ * From the string length AVL node determine whether a StrNode AVL node
+ * provides this string. If the node doesn't exist, insert a new node
+ * to represent this string.
+ */
+ sn.sn_str = str;
+ if ((snp = avl_find(lnp->ln_strtree, &sn, &where)) == NULL) {
+ if ((snp = calloc(sizeof (StrNode), 1)) == NULL)
+ return (-1);
+ snp->sn_str = str;
+ avl_insert(lnp->ln_strtree, snp, where);
}
+ snp->sn_refcnt++;
- free(stlist);
return (0);
}
-
/*
- * Insert a new string into the Str_tbl
+ * Remove a previously inserted string from the Str_tbl.
*/
int
-st_insert(Str_tbl *stp, const char *str)
+st_delstring(Str_tbl *stp, const char *str)
{
- uint_t stlen;
- Stringelem qstelem;
- Stringelem *stelem;
- Stringlist *strlist;
- avl_index_t where;
+ uint_t len;
+ LenNode *lnp, ln = { 0 };
+ StrNode *snp, sn = { 0 };
/*
* String table can't have been cooked
*/
assert((stp->st_flags & FLG_STTAB_COOKED) == 0);
- stlen = (uint_t)strlen(str);
- /*
- * Null strings always point to the head of the string
- * table - no reason to keep searching.
- */
- if (stlen == 0)
- return (0);
- stp->st_fullstringsize += stlen + 1;
- stp->st_stringcnt++;
+ len = (uint_t)strlen(str);
+ stp->st_fullstrsize -= len + 1;
if ((stp->st_flags & FLG_STTAB_COMPRESS) == 0)
return (0);
- qstelem.se_stlen = strlen(str);
- if ((stelem = avl_find(stp->st_strtree, &qstelem,
- &where)) == NULL) {
- if ((stelem = calloc(sizeof (Stringelem), 1)) == 0)
- return (-1);
- stelem->se_stlen = qstelem.se_stlen;
- avl_insert(stp->st_strtree, stelem, where);
+ /*
+ * Determine which LenNode AVL node provides for this string length.
+ */
+ ln.ln_strlen = len;
+ if ((lnp = avl_find(stp->st_lentree, &ln, 0)) != NULL) {
+ sn.sn_str = str;
+ if ((snp = avl_find(lnp->ln_strtree, &sn, 0)) != NULL) {
+ /*
+ * Reduce the reference count, and if zero remove the
+ * node.
+ */
+ if (--snp->sn_refcnt == 0)
+ avl_remove(lnp->ln_strtree, snp);
+ return (0);
+ }
}
- if ((strlist = malloc(sizeof (Stringlist))) == 0)
- return (-1);
- strlist->sl_string = str;
- strlist->sl_next = stelem->se_strlist;
- stelem->se_strlist = strlist;
+ /*
+ * No strings of this length, or no string itself - someone goofed.
+ */
+ return (-1);
+}
- return (0);
+/*
+ * Tear down a String_Table structure.
+ */
+void
+st_destroy(Str_tbl *stp)
+{
+ Str_hash *sthash, *psthash;
+ Str_master *mstr, *pmstr;
+ uint_t i;
+
+ /*
+ * cleanup the master strings
+ */
+ for (mstr = stp->st_mstrlist, pmstr = 0; mstr;
+ mstr = mstr->sm_next) {
+ if (pmstr)
+ free(pmstr);
+ pmstr = mstr;
+ }
+ if (pmstr)
+ free(pmstr);
+
+ if (stp->st_hashbcks) {
+ for (i = 0; i < stp->st_hbckcnt; i++) {
+ for (sthash = stp->st_hashbcks[i], psthash = 0;
+ sthash; sthash = sthash->hi_next) {
+ if (psthash)
+ free(psthash);
+ psthash = sthash;
+ }
+ if (psthash)
+ free(psthash);
+ }
+ free(stp->st_hashbcks);
+ }
+ free(stp);
}
@@ -368,7 +378,7 @@ st_setstring(Str_tbl *stp, const char *str, uint_t *stoff)
/*
* Have we overflowed our assigned buffer?
*/
- if ((_stoff + stlen) > stp->st_fullstringsize)
+ if ((_stoff + stlen) > stp->st_fullstrsize)
return (-1);
memcpy(stp->st_strbuf + _stoff, str, stlen);
*stoff = _stoff;
@@ -377,26 +387,25 @@ st_setstring(Str_tbl *stp, const char *str, uint_t *stoff)
}
/*
- * Calculate reverse hash for string
+ * Calculate reverse hash for string.
*/
hashval = HASHSEED;
for (i = stlen; i >= 0; i--) {
hashval = ((hashval << 5) + hashval) +
- str[i]; /* h = ((h * 33) + c) */
+ str[i]; /* h = ((h * 33) + c) */
}
for (sthash = stp->st_hashbcks[hashval % stp->st_hbckcnt]; sthash;
sthash = sthash->hi_next) {
- if (sthash->hi_hashval == hashval) {
- const char *hstr;
+ const char *hstr;
- hstr = &sthash->hi_mstr->sm_str[
- sthash->hi_mstr->sm_stlen -
- sthash->hi_stlen];
- if (strcmp(str, hstr) == 0) {
- break;
- }
- }
+ if (sthash->hi_hashval != hashval)
+ continue;
+
+ hstr = &sthash->hi_mstr->sm_str[sthash->hi_mstr->sm_strlen -
+ sthash->hi_strlen];
+ if (strcmp(str, hstr) == 0)
+ break;
}
/*
@@ -409,29 +418,33 @@ st_setstring(Str_tbl *stp, const char *str, uint_t *stoff)
* Has this string been copied into the string table?
*/
mstr = sthash->hi_mstr;
- if (mstr->sm_stoff == 0) {
- uint_t mstlen = mstr->sm_stlen + 1;
- mstr->sm_stoff = stp->st_nextoff;
+ if (mstr->sm_stroff == 0) {
+ uint_t mstrlen = mstr->sm_strlen + 1;
+
+ mstr->sm_stroff = stp->st_nextoff;
+
/*
* Have we overflowed our assigned buffer?
*/
- if ((mstr->sm_stoff + mstlen) > stp->st_fullstringsize)
+ if ((mstr->sm_stroff + mstrlen) > stp->st_fullstrsize)
return (-1);
- memcpy(stp->st_strbuf + mstr->sm_stoff, mstr->sm_str,
- mstlen);
- stp->st_nextoff += mstlen;
+
+ (void) memcpy(stp->st_strbuf + mstr->sm_stroff,
+ mstr->sm_str, mstrlen);
+ stp->st_nextoff += mstrlen;
}
+
/*
- * Calculate offset of (sub)string
+ * Calculate offset of (sub)string.
*/
- *stoff = mstr->sm_stoff + mstr->sm_stlen - sthash->hi_stlen;
+ *stoff = mstr->sm_stroff + mstr->sm_strlen - sthash->hi_strlen;
return (0);
}
static int
-st_hash_insert(Str_tbl *stp, const char *str, uint_t stlen)
+st_hash_insert(Str_tbl *stp, const char *str, uint_t len)
{
int i;
uint_t hashval = HASHSEED;
@@ -450,51 +463,48 @@ st_hash_insert(Str_tbl *stp, const char *str, uint_t stlen)
* any suffixes already exist in the tree as we generate
* the hash.
*/
- for (i = stlen; i >= 0; i--) {
-
+ for (i = len; i >= 0; i--) {
hashval = ((hashval << 5) + hashval) +
- str[i]; /* h = ((h * 33) + c) */
+ str[i]; /* h = ((h * 33) + c) */
+
for (sthash = hashbcks[hashval % bckcnt];
sthash; sthash = sthash->hi_next) {
-
- if (sthash->hi_hashval == hashval) {
- const char *hstr;
- Str_master *_mstr;
-
- _mstr = sthash->hi_mstr;
- hstr = &_mstr->sm_str[_mstr->sm_stlen -
- sthash->hi_stlen];
- if (strcmp(&str[i], hstr) == 0) {
- if (i == 0) {
- /*
- * Entry already in table,
- * increment refcnt and get
- * out.
- */
- sthash->hi_refcnt++;
- return (0);
- } else {
- /*
- * If this 'suffix' is
- * presently a 'master' string,
- * then take over it's record.
- */
- if (sthash->hi_stlen ==
- _mstr->sm_stlen) {
- /*
- * we should only do
- * this once.
- */
- assert(mstr == 0);
- mstr = _mstr;
- }
- }
+ const char *hstr;
+ Str_master *_mstr;
+
+ if (sthash->hi_hashval != hashval)
+ continue;
+
+ _mstr = sthash->hi_mstr;
+ hstr = &_mstr->sm_str[_mstr->sm_strlen -
+ sthash->hi_strlen];
+
+ if (strcmp(&str[i], hstr))
+ continue;
+
+ if (i == 0) {
+ /*
+ * Entry already in table, increment refcnt and
+ * get out.
+ */
+ sthash->hi_refcnt++;
+ return (0);
+ } else {
+ /*
+ * If this 'suffix' is presently a 'master
+ * string, then take over it's record.
+ */
+ if (sthash->hi_strlen == _mstr->sm_strlen) {
+ /*
+ * we should only do this once.
+ */
+ assert(mstr == 0);
+ mstr = _mstr;
}
}
}
}
-
/*
* Do we need a new master string, or can we take over
* one we already found in the table?
@@ -507,23 +517,22 @@ st_hash_insert(Str_tbl *stp, const char *str, uint_t stlen)
return (-1);
mstr->sm_next = stp->st_mstrlist;
stp->st_mstrlist = mstr;
- stp->st_stringsize += stlen + 1;
+ stp->st_strsize += len + 1;
} else {
/*
- * We are taking over a existing master string,
- * the stringsize only increments by the
- * difference between the currnet string and the
- * previous master.
+ * We are taking over a existing master string, the string size
+ * only increments by the difference between the current string
+ * and the previous master.
*/
- assert(stlen > mstr->sm_stlen);
- stp->st_stringsize += stlen - mstr->sm_stlen;
+ assert(len > mstr->sm_strlen);
+ stp->st_strsize += len - mstr->sm_strlen;
}
if ((sthash = calloc(sizeof (Str_hash), 1)) == 0)
return (-1);
mstr->sm_hashval = sthash->hi_hashval = hashval;
- mstr->sm_stlen = sthash->hi_stlen = stlen;
+ mstr->sm_strlen = sthash->hi_strlen = len;
mstr->sm_str = str;
sthash->hi_refcnt = 1;
sthash->hi_mstr = mstr;
@@ -543,16 +552,15 @@ st_hash_insert(Str_tbl *stp, const char *str, uint_t stlen)
uint_t
st_getstrtab_sz(Str_tbl *stp)
{
- assert(stp->st_fullstringsize > 0);
+ assert(stp->st_fullstrsize > 0);
if ((stp->st_flags & FLG_STTAB_COMPRESS) == 0) {
stp->st_flags |= FLG_STTAB_COOKED;
- return (stp->st_fullstringsize);
+ return (stp->st_fullstrsize);
}
-
if ((stp->st_flags & FLG_STTAB_COOKED) == 0) {
- Stringelem *stelem;
+ LenNode *lnp;
void *cookie;
stp->st_flags |= FLG_STTAB_COOKED;
@@ -560,77 +568,87 @@ st_getstrtab_sz(Str_tbl *stp)
* allocate a hash table about the size of # of
* strings input.
*/
- stp->st_hbckcnt = findprime(stp->st_stringcnt);
+ stp->st_hbckcnt = findprime(stp->st_strcnt);
if ((stp->st_hashbcks =
calloc(sizeof (Str_hash), stp->st_hbckcnt)) == NULL)
return (0);
/*
- * We now walk all of the strings in the list,
- * from shortest to longest, and insert them into
- * the hashtable.
+ * We now walk all of the strings in the list, from shortest to
+ * longest, and insert them into the hashtable.
*/
- if ((stelem = avl_first(stp->st_strtree)) == NULL) {
+ if ((lnp = avl_first(stp->st_lentree)) == NULL) {
/*
- * Is it possible we have a empty string table,
- * if so - the table still conains '\0'
- * so still return the size.
+ * Is it possible we have an empty string table, if so,
+ * the table still contains '\0', so return the size.
*/
- if (avl_numnodes(stp->st_strtree) == 0) {
- assert(stp->st_stringsize == 1);
- return (stp->st_stringsize);
+ if (avl_numnodes(stp->st_lentree) == 0) {
+ assert(stp->st_strsize == 1);
+ return (stp->st_strsize);
}
return (0);
}
- while (stelem) {
- Stringlist *strlist, *pstrlist;
+
+ while (lnp) {
+ StrNode *snp;
/*
- * Walk the string lists and insert them
- * into the hash list. Once a string is
- * inserted we no longer need it's entry,
- * so free it
+ * Walk the string lists and insert them into the hash
+ * list. Once a string is inserted we no longer need
+ * it's entry, so the string can be freed.
*/
- for (strlist = stelem->se_strlist, pstrlist = 0;
- strlist; strlist = strlist->sl_next) {
- if (st_hash_insert(stp, strlist->sl_string,
- stelem->se_stlen) == -1)
+ for (snp = avl_first(lnp->ln_strtree); snp;
+ snp = AVL_NEXT(lnp->ln_strtree, snp)) {
+ if (st_hash_insert(stp, snp->sn_str,
+ lnp->ln_strlen) == -1)
return (0);
- if (pstrlist)
- free(pstrlist);
}
- free(pstrlist);
- stelem->se_strlist = 0;
- stelem = AVL_NEXT(stp->st_strtree, stelem);
+
+ /*
+ * Now that the strings have been copied, walk the
+ * StrNode tree and free all the AVL nodes. Note,
+ * avl_destroy_nodes() beats avl_remove() as the
+ * latter balances the nodes as they are removed.
+ * We just want to tear the whole thing down fast.
+ */
+ cookie = NULL;
+ while ((snp = avl_destroy_nodes(lnp->ln_strtree,
+ &cookie)) != NULL)
+ free(snp);
+ avl_destroy(lnp->ln_strtree);
+ free(lnp->ln_strtree);
+ lnp->ln_strtree = NULL;
+
+ /*
+ * Move on to the next LenNode.
+ */
+ lnp = AVL_NEXT(stp->st_lentree, lnp);
}
/*
- * Now that all of the strings have been freed,
- * go ahead and quickly re-walk the AVL tree and
- * free all of the AVL nodes.
- *
- * avl_destroy_nodes() beats avl_remove() because
- * avl_remove will 'ballance' the tree as nodes
- * are deleted - we just want to tear the whole
- * thing down now.
+ * Now that all of the strings have been freed, walk the
+ * LenNode tree and free all of the AVL nodes. Note,
+ * avl_destroy_nodes() beats avl_remove() as the latter
+ * balances the nodes as they are removed. We just want to
+ * tear the whole thing down fast.
*/
cookie = NULL;
- while ((stelem = avl_destroy_nodes(stp->st_strtree,
+ while ((lnp = avl_destroy_nodes(stp->st_lentree,
&cookie)) != NULL)
- free(stelem);
- avl_destroy(stp->st_strtree);
- free(stp->st_strtree);
- stp->st_strtree = 0;
+ free(lnp);
+ avl_destroy(stp->st_lentree);
+ free(stp->st_lentree);
+ stp->st_lentree = 0;
}
- assert(stp->st_stringsize > 0);
- assert(stp->st_fullstringsize >= stp->st_stringsize);
+ assert(stp->st_strsize > 0);
+ assert(stp->st_fullstrsize >= stp->st_strsize);
- return (stp->st_stringsize);
+ return (stp->st_strsize);
}
/*
- * Associate a buffer with the string table.
+ * Associate a buffer with a string table.
*/
const char *
st_getstrbuf(Str_tbl *stp)
@@ -644,10 +662,10 @@ st_setstrbuf(Str_tbl *stp, char *stbuf, uint_t bufsize)
assert(stp->st_flags & FLG_STTAB_COOKED);
if ((stp->st_flags & FLG_STTAB_COMPRESS) == 0) {
- if (bufsize < stp->st_fullstringsize)
+ if (bufsize < stp->st_fullstrsize)
return (-1);
} else {
- if (bufsize < stp->st_stringsize)
+ if (bufsize < stp->st_strsize)
return (-1);
}