remove unused sgsmsg utility (originally imported from opensolaris)
MFC after: 25 days
This commit is contained in:
parent
65b71c48d2
commit
9875367b9a
@ -1497,7 +1497,7 @@ _btxld= usr.sbin/btxld
|
||||
# Rebuild ctfconvert and ctfmerge to avoid difficult-to-diagnose failures
|
||||
# resulting from missing bug fixes or ELF Toolchain updates.
|
||||
.if ${MK_CDDL} != "no"
|
||||
_dtrace_tools= cddl/usr.bin/sgsmsg cddl/lib/libctf cddl/usr.bin/ctfconvert \
|
||||
_dtrace_tools= cddl/lib/libctf cddl/usr.bin/ctfconvert \
|
||||
cddl/usr.bin/ctfmerge
|
||||
.endif
|
||||
|
||||
|
@ -38,6 +38,8 @@
|
||||
# xargs -n1 | sort | uniq -d;
|
||||
# done
|
||||
|
||||
# 20150928: unused sgsmsg utility is removed
|
||||
OLD_FILES+=usr/bin/sgsmsg
|
||||
# 20150926: remove links to removed/unimplemented mbuf(9) macros
|
||||
OLD_FILES+=usr/share/man/man9/MEXT_ADD_REF.9.gz
|
||||
OLD_FILES+=usr/share/man/man9/MEXTFREE.9.gz
|
||||
|
@ -1,126 +0,0 @@
|
||||
/*
|
||||
* 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 2008 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 */
|
||||
size_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 */
|
||||
size_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 */
|
||||
size_t sm_strlen; /* length of master string */
|
||||
uint_t sm_hashval; /* hashval of master string */
|
||||
size_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 {
|
||||
size_t hi_strlen; /* string length */
|
||||
size_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 */
|
||||
size_t st_fullstrsize; /* uncompressed table size */
|
||||
size_t st_nextoff; /* next available string */
|
||||
size_t st_strsize; /* compressed size */
|
||||
size_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 */
|
@ -1,280 +0,0 @@
|
||||
/*
|
||||
* 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 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* Define an Alist, a list maintained as a reallocable array, and a for() loop
|
||||
* macro to generalize its traversal. Note that the array can be reallocated
|
||||
* as it is being traversed, thus the offset of each element is recomputed from
|
||||
* the start of the structure.
|
||||
*/
|
||||
|
||||
#ifndef _ALIST_H
|
||||
#define _ALIST_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef illumos
|
||||
#include <sys/machelf.h>
|
||||
#else
|
||||
#include <sys/elf.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* An Alist implements array lists. The functionality is similar to
|
||||
* that of a linked list. However, an Alist is represented by a single
|
||||
* contigious allocation of memory. The head of the memory is a header
|
||||
* that contains control information for the list. Following the header
|
||||
* is an array used to hold the user data. In the type definitions that
|
||||
* follow, we define these as an array with a single element, but when
|
||||
* we allocate the memory, we actually allocate the amount of memory needed.
|
||||
*
|
||||
* There are two "flavors" of array list:
|
||||
*
|
||||
* Alist - Contain arbitrary data, usually structs.
|
||||
* APlist - Contain pointers to data allocated elsewhere.
|
||||
*
|
||||
* This differentiation is useful, because pointer lists are heavily
|
||||
* used, and support a slightly different set of operations that are
|
||||
* unique to their purpose.
|
||||
*
|
||||
* Array lists are initially represented by a NULL pointer. The memory
|
||||
* for the list is only allocated if an item is inserted. This is very
|
||||
* efficient for data structures that may or may not be needed for a
|
||||
* given linker operation --- you only pay for what you use. In addition:
|
||||
*
|
||||
* - Array lists grow as needed (memory is reallocated as necessary)
|
||||
* - Data is kept contiguously (no unused holes in between elements)
|
||||
* at the beginning of the data area. This locality has
|
||||
* good cache behavior, as access to adjacent items are
|
||||
* highly likely to be in the same page of memory.
|
||||
* - Insert/Delete operations at the end of the list are very
|
||||
* efficient. However, insert/delete operations elsewhere
|
||||
* will cause a relatively expensive overlapped memory
|
||||
* copy of the data following the insert/delete location.
|
||||
* - As with any generic memory alloctor (i.e. malloc()/free()),
|
||||
* array lists are not type safe for the data they contain.
|
||||
* Data is managed as (void *) pointers to data of a given
|
||||
* length, so the Alist module cannot prevent the caller from
|
||||
* inserting/extracting the wrong type of data. The caller
|
||||
* must guard against this.
|
||||
* - To free an array list, simply call the standard free() function
|
||||
* on the list pointer.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Aliste is used to represent list indexes, offsets, and sizes.
|
||||
*/
|
||||
typedef size_t Aliste;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Alist is used to hold non-pointer items --- usually structs:
|
||||
* - There must be an even number of Aliste fields before the
|
||||
* al_data field. This ensures that al_data will have
|
||||
* an alignment of 8, no matter whether sizeof(Aliste)
|
||||
* is 4 or 8. That means that al_data will have sufficient
|
||||
* alignment for any use, just like memory allocated via
|
||||
* malloc().
|
||||
* - al_nitems and al_next are redundant, in that they are
|
||||
* directly related:
|
||||
* al_next = al_nitems * al_size
|
||||
* We do this to make ALIST_TRAVERSE_BYOFFSET maximally
|
||||
* efficient. This doesn't waste space, because of the
|
||||
* requirement to have an even # of Alist fields (above).
|
||||
*
|
||||
* Note that Alists allow the data to be referenced by 0 based array
|
||||
* index, or by their byte offset from the start of the Alist memory
|
||||
* allocation. The index form is preferred for most use, as it is simpler.
|
||||
* However, by-offset access is used by rtld link maps, and this ability
|
||||
* is convenient in that case.
|
||||
*/
|
||||
typedef struct {
|
||||
Aliste al_arritems; /* # of items in al_data allocation */
|
||||
Aliste al_nitems; /* # items (index of next avail item) */
|
||||
Aliste al_next; /* offset of next available al_data[] */
|
||||
Aliste al_size; /* size of each al_data[] item */
|
||||
void *al_data[1]; /* data (can grow) */
|
||||
} Alist;
|
||||
|
||||
/*
|
||||
* APlist is a variant of Alist that contains pointers. There are several
|
||||
* benefits to this special type:
|
||||
* - API is simpler
|
||||
* - Pointers are used directly, instead of requiring a
|
||||
* pointer-to-pointer double indirection.
|
||||
* - The implementation is slightly more efficient.
|
||||
* - Operations that make particular sense for pointers
|
||||
* can be supported without confusing the API for the
|
||||
* regular Alists.
|
||||
*/
|
||||
typedef struct {
|
||||
Aliste apl_arritems; /* # of items in apl_data allocation */
|
||||
Aliste apl_nitems; /* # items (index of next avail item) */
|
||||
void *apl_data[1]; /* data area: (arrcnt * size) bytes */
|
||||
} APlist;
|
||||
|
||||
|
||||
/*
|
||||
* The ALIST_OFF_DATA and APLIST_OFF_DATA macros give the byte offset
|
||||
* from the start of an array list to the first byte of the data area
|
||||
* used to hold user data. The same trick used by the standard offsetof()
|
||||
* macro is used.
|
||||
*/
|
||||
#define ALIST_OFF_DATA ((size_t)(((Alist *)0)->al_data))
|
||||
#define APLIST_OFF_DATA ((size_t)(((APlist *)0)->apl_data))
|
||||
|
||||
|
||||
/*
|
||||
* The TRAVERSE macros are intended to be used within a for(), and
|
||||
* cause the resulting loop to iterate over each item in the loop,
|
||||
* in order.
|
||||
* ALIST_TRAVERSE: Traverse over the items in an Alist,
|
||||
* using the zero based item array index to refer to
|
||||
* each item.
|
||||
* ALIST_TRAVERSE_BY_OFFSET: Traverse over the items in an
|
||||
* Alist using the byte offset from the head of the
|
||||
* Alist pointer to refer to each item. It should be noted
|
||||
* that the first such offset is given by ALIST_OFF_DATA,
|
||||
* and as such, there will never be a 0 offset. Some code
|
||||
* uses this fact to treat 0 as a reserved value with
|
||||
* special meaning.
|
||||
*
|
||||
* By-offset access is convenient for some parts of
|
||||
* rtld, where a value of 0 is used to indicate an
|
||||
* uninitialized link map control.
|
||||
*
|
||||
* APLIST_TRAVERSE: Traverse over the pointers in an APlist, using
|
||||
* the zero based item array index to refer to each pointer.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Within the loop:
|
||||
*
|
||||
* LIST - Pointer to Alist structure for list
|
||||
* IDX - The current item index
|
||||
* OFF - The current item offset
|
||||
* DATA - Pointer to item
|
||||
*/
|
||||
#define ALIST_TRAVERSE(LIST, IDX, DATA) \
|
||||
(IDX) = 0, \
|
||||
((LIST) != NULL) && ((DATA) = (void *)(LIST)->al_data); \
|
||||
\
|
||||
((LIST) != NULL) && ((IDX) < (LIST)->al_nitems); \
|
||||
\
|
||||
(IDX)++, \
|
||||
(DATA) = (void *) (((LIST)->al_size * (IDX)) + (char *)(LIST)->al_data)
|
||||
|
||||
#define ALIST_TRAVERSE_BY_OFFSET(LIST, OFF, DATA) \
|
||||
(((LIST) != NULL) && ((OFF) = ALIST_OFF_DATA) && \
|
||||
(((DATA) = (void *)((char *)(LIST) + (OFF))))); \
|
||||
\
|
||||
(((LIST) != NULL) && ((OFF) < (LIST)->al_next)); \
|
||||
\
|
||||
(((OFF) += ((LIST)->al_size)), \
|
||||
((DATA) = (void *)((char *)(LIST) + (OFF))))
|
||||
|
||||
/*
|
||||
* Within the loop:
|
||||
*
|
||||
* LIST - Pointer to APlist structure for list
|
||||
* IDX - The current item index
|
||||
* PTR - item value
|
||||
*
|
||||
* Note that this macro is designed to ensure that PTR retains the
|
||||
* value of the final pointer in the list after exiting the for loop,
|
||||
* and to avoid dereferencing an out of range address. This is done by
|
||||
* doing the dereference in the middle expression, using the comma
|
||||
* operator to ensure that a NULL pointer won't stop the loop.
|
||||
*/
|
||||
#define APLIST_TRAVERSE(LIST, IDX, PTR) \
|
||||
(IDX) = 0; \
|
||||
\
|
||||
((LIST) != NULL) && ((IDX) < (LIST)->apl_nitems) && \
|
||||
(((PTR) = ((LIST)->apl_data)[IDX]), 1); \
|
||||
\
|
||||
(IDX)++
|
||||
|
||||
|
||||
/*
|
||||
* Possible values returned by aplist_test()
|
||||
*/
|
||||
typedef enum {
|
||||
ALE_ALLOCFAIL = 0, /* Memory allocation error */
|
||||
ALE_EXISTS = 1, /* alist entry already exists */
|
||||
ALE_NOTFND = 2, /* item not found and insert not required */
|
||||
ALE_CREATE = 3 /* alist entry created */
|
||||
} aplist_test_t;
|
||||
|
||||
|
||||
/*
|
||||
* Access to an Alist item by index or offset. This is needed because the
|
||||
* size of an item in an Alist is not known by the C compiler, and we
|
||||
* have to do the indexing arithmetic explicitly.
|
||||
*
|
||||
* For an APlist, index the apl_data field directly --- No macro is needed.
|
||||
*/
|
||||
#define alist_item(_lp, _idx) \
|
||||
((void *)(ALIST_OFF_DATA + ((_idx) * (_lp)->al_size) + (char *)(_lp)))
|
||||
#define alist_item_by_offset(_lp, _off) \
|
||||
((void *)((_off) + (char *)(_lp)))
|
||||
|
||||
/*
|
||||
* # of items currently found in a list. These macros handle the case
|
||||
* where the list has not been allocated yet.
|
||||
*/
|
||||
#define alist_nitems(_lp) (((_lp) == NULL) ? 0 : (_lp)->al_nitems)
|
||||
#define aplist_nitems(_lp) (((_lp) == NULL) ? 0 : (_lp)->apl_nitems)
|
||||
|
||||
|
||||
extern void *alist_append(Alist **, const void *, size_t, Aliste);
|
||||
extern void alist_delete(Alist *, Aliste *);
|
||||
extern void alist_delete_by_offset(Alist *, Aliste *);
|
||||
extern void *alist_insert(Alist **, const void *, size_t,
|
||||
Aliste, Aliste);
|
||||
extern void *alist_insert_by_offset(Alist **, const void *, size_t,
|
||||
Aliste, Aliste);
|
||||
extern void alist_reset(Alist *);
|
||||
|
||||
|
||||
extern void *aplist_append(APlist **, const void *, Aliste);
|
||||
extern void aplist_delete(APlist *, Aliste *);
|
||||
extern int aplist_delete_value(APlist *, const void *);
|
||||
extern void *aplist_insert(APlist **, const void *,
|
||||
Aliste, Aliste idx);
|
||||
extern void aplist_reset(APlist *);
|
||||
extern aplist_test_t aplist_test(APlist **, const void *, Aliste);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ALIST_H */
|
File diff suppressed because it is too large
Load Diff
@ -1,296 +0,0 @@
|
||||
/*
|
||||
* 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 (c) 1988 AT&T
|
||||
* All Rights Reserved
|
||||
*
|
||||
*
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* Global include file for all sgs.
|
||||
*/
|
||||
|
||||
#ifndef _SGS_H
|
||||
#define _SGS_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* <assert.h> keys off of NDEBUG */
|
||||
#ifdef DEBUG
|
||||
#undef NDEBUG
|
||||
#else
|
||||
#define NDEBUG
|
||||
#endif
|
||||
|
||||
#ifndef _ASM
|
||||
#include <sys/types.h>
|
||||
#ifdef illumos
|
||||
#include <sys/machelf.h>
|
||||
#else
|
||||
#include <elf.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <libelf.h>
|
||||
#include <assert.h>
|
||||
#include <alist.h>
|
||||
#endif /* _ASM */
|
||||
|
||||
/*
|
||||
* Software identification.
|
||||
*/
|
||||
#define SGS ""
|
||||
#define SGU_PKG "Software Generation Utilities"
|
||||
#define SGU_REL "(SGU) Solaris-ELF (4.0)"
|
||||
|
||||
|
||||
#ifndef _ASM
|
||||
|
||||
/*
|
||||
* link_ver_string[] contains a version string for use by the link-editor
|
||||
* and all other linker components. It is found in libconv, and is
|
||||
* generated by sgs/libconv/common/bld_vernote.ksh. That script produces
|
||||
* libconv/{plat}/vernote.s, which is in turn assembled/linked into
|
||||
* libconv.
|
||||
*/
|
||||
extern const char link_ver_string[];
|
||||
/*
|
||||
* Macro to round to next double word boundary.
|
||||
*/
|
||||
#define S_DROUND(x) (((x) + sizeof (double) - 1) & ~(sizeof (double) - 1))
|
||||
|
||||
/*
|
||||
* General align and round macros.
|
||||
*/
|
||||
#define S_ALIGN(x, a) ((x) & ~(((a) ? (a) : 1) - 1))
|
||||
#define S_ROUND(x, a) ((x) + (((a) ? (a) : 1) - 1) & ~(((a) ? (a) : 1) - 1))
|
||||
|
||||
/*
|
||||
* Bit manipulation macros; generic bit mask and is `v' in the range
|
||||
* supportable in `n' bits?
|
||||
*/
|
||||
#define S_MASK(n) ((1 << (n)) -1)
|
||||
#define S_INRANGE(v, n) (((-(1 << (n)) - 1) < (v)) && ((v) < (1 << (n))))
|
||||
|
||||
|
||||
/*
|
||||
* Yet another definition of the OFFSETOF macro, used with the AVL routines.
|
||||
*/
|
||||
#define SGSOFFSETOF(s, m) ((size_t)(&(((s *)0)->m)))
|
||||
|
||||
/*
|
||||
* When casting between integer and pointer types, gcc will complain
|
||||
* if the integer type used is not large enough to hold the pointer
|
||||
* value without loss. Although a dubious practice in general, this
|
||||
* is sometimes done by design. In those cases, the general solution
|
||||
* is to introduce an intermediate cast to widen the integer value. The
|
||||
* CAST_PTRINT macro does this, and its use documents the fact that
|
||||
* the programmer is doing that sort of cast.
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
#define CAST_PTRINT(cast, value) ((cast)(uintptr_t)value)
|
||||
#else
|
||||
#define CAST_PTRINT(cast, value) ((cast)value)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* General typedefs.
|
||||
*/
|
||||
typedef enum {
|
||||
FALSE = 0,
|
||||
TRUE = 1
|
||||
} Boolean;
|
||||
|
||||
/*
|
||||
* Types of errors (used by eprintf()), together with a generic error return
|
||||
* value.
|
||||
*/
|
||||
typedef enum {
|
||||
ERR_NONE,
|
||||
ERR_WARNING,
|
||||
ERR_FATAL,
|
||||
ERR_ELF,
|
||||
ERR_NUM /* Must be last */
|
||||
} Error;
|
||||
|
||||
#if defined(_LP64) && !defined(_ELF64)
|
||||
#define S_ERROR (~(uint_t)0)
|
||||
#else
|
||||
#define S_ERROR (~(uintptr_t)0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* LIST_TRAVERSE() is used as the only "argument" of a "for" loop to
|
||||
* traverse a linked list. The node pointer `node' is set to each node in
|
||||
* turn and the corresponding data pointer is copied to `data'. The macro
|
||||
* is used as in
|
||||
* for (LIST_TRAVERSE(List *list, Listnode *node, void *data)) {
|
||||
* process(data);
|
||||
* }
|
||||
*/
|
||||
#define LIST_TRAVERSE(L, N, D) \
|
||||
(void) (((N) = (L)->head) != NULL && ((D) = (N)->data) != NULL); \
|
||||
(N) != NULL; \
|
||||
(void) (((N) = (N)->next) != NULL && ((D) = (N)->data) != NULL)
|
||||
|
||||
typedef struct listnode Listnode;
|
||||
typedef struct list List;
|
||||
|
||||
struct listnode { /* a node on a linked list */
|
||||
void *data; /* the data item */
|
||||
Listnode *next; /* the next element */
|
||||
};
|
||||
|
||||
struct list { /* a linked list */
|
||||
Listnode *head; /* the first element */
|
||||
Listnode *tail; /* the last element */
|
||||
};
|
||||
|
||||
|
||||
#ifdef _SYSCALL32
|
||||
typedef struct listnode32 Listnode32;
|
||||
typedef struct list32 List32;
|
||||
|
||||
struct listnode32 { /* a node on a linked list */
|
||||
Elf32_Addr data; /* the data item */
|
||||
Elf32_Addr next; /* the next element */
|
||||
};
|
||||
|
||||
struct list32 { /* a linked list */
|
||||
Elf32_Addr head; /* the first element */
|
||||
Elf32_Addr tail; /* the last element */
|
||||
};
|
||||
#endif /* _SYSCALL32 */
|
||||
|
||||
|
||||
/*
|
||||
* Structure to maintain rejected files elf information. Files that are not
|
||||
* applicable to the present link-edit are rejected and a search for an
|
||||
* appropriate file may be resumed. The first rejected files information is
|
||||
* retained so that a better error diagnostic can be given should an appropriate
|
||||
* file not be located.
|
||||
*/
|
||||
typedef struct {
|
||||
ushort_t rej_type; /* SGS_REJ_ value */
|
||||
ushort_t rej_flag; /* additional information */
|
||||
uint_t rej_info; /* numeric and string information */
|
||||
const char *rej_str; /* associated with error */
|
||||
const char *rej_name; /* object name - expanded library */
|
||||
/* name and archive members */
|
||||
} Rej_desc;
|
||||
|
||||
#define SGS_REJ_NONE 0
|
||||
#define SGS_REJ_MACH 1 /* wrong ELF machine type */
|
||||
#define SGS_REJ_CLASS 2 /* wrong ELF class (32-bit/64-bit) */
|
||||
#define SGS_REJ_DATA 3 /* wrong ELF data format (MSG/LSB) */
|
||||
#define SGS_REJ_TYPE 4 /* bad ELF type */
|
||||
#define SGS_REJ_BADFLAG 5 /* bad ELF flags value */
|
||||
#define SGS_REJ_MISFLAG 6 /* mismatched ELF flags value */
|
||||
#define SGS_REJ_VERSION 7 /* mismatched ELF/lib version */
|
||||
#define SGS_REJ_HAL 8 /* HAL R1 extensions required */
|
||||
#define SGS_REJ_US3 9 /* Sun UltraSPARC III extensions */
|
||||
/* required */
|
||||
#define SGS_REJ_STR 10 /* generic error - info is a string */
|
||||
#define SGS_REJ_UNKFILE 11 /* unknown file type */
|
||||
#define SGS_REJ_HWCAP_1 12 /* hardware capabilities mismatch */
|
||||
|
||||
/*
|
||||
* For those source files used both inside and outside of the
|
||||
* libld source base (tools/common/string_table.c) we can
|
||||
* automatically switch between the allocation models
|
||||
* based off of the 'cc -DUSE_LIBLD_MALLOC' flag.
|
||||
*/
|
||||
#ifdef USE_LIBLD_MALLOC
|
||||
#define calloc(x, a) libld_malloc(((size_t)x) * ((size_t)a))
|
||||
#define free libld_free
|
||||
#define malloc libld_malloc
|
||||
#define realloc libld_realloc
|
||||
|
||||
#define libld_calloc(x, a) libld_malloc(((size_t)x) * ((size_t)a))
|
||||
extern void libld_free(void *);
|
||||
extern void *libld_malloc(size_t);
|
||||
extern void *libld_realloc(void *, size_t);
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Data structures (defined in libld.h).
|
||||
*/
|
||||
typedef struct ent_desc Ent_desc;
|
||||
typedef struct group_desc Group_desc;
|
||||
typedef struct ifl_desc Ifl_desc;
|
||||
typedef struct is_desc Is_desc;
|
||||
typedef struct isa_desc Isa_desc;
|
||||
typedef struct isa_opt Isa_opt;
|
||||
typedef struct mv_desc Mv_desc;
|
||||
typedef struct ofl_desc Ofl_desc;
|
||||
typedef struct os_desc Os_desc;
|
||||
typedef struct rel_cache Rel_cache;
|
||||
typedef struct sdf_desc Sdf_desc;
|
||||
typedef struct sdv_desc Sdv_desc;
|
||||
typedef struct sg_desc Sg_desc;
|
||||
typedef struct sort_desc Sort_desc;
|
||||
typedef struct sec_order Sec_order;
|
||||
typedef struct sym_desc Sym_desc;
|
||||
typedef struct sym_aux Sym_aux;
|
||||
typedef struct sym_avlnode Sym_avlnode;
|
||||
typedef struct uts_desc Uts_desc;
|
||||
typedef struct ver_desc Ver_desc;
|
||||
typedef struct ver_index Ver_index;
|
||||
typedef struct audit_desc Audit_desc;
|
||||
typedef struct audit_info Audit_info;
|
||||
typedef struct audit_list Audit_list;
|
||||
|
||||
/*
|
||||
* Data structures defined in machrel.h.
|
||||
*/
|
||||
typedef struct rel_desc Rel_desc;
|
||||
|
||||
/*
|
||||
* Data structures defined in rtld.h.
|
||||
*/
|
||||
typedef struct lm_list Lm_list;
|
||||
#ifdef _SYSCALL32
|
||||
typedef struct lm_list32 Lm_list32;
|
||||
#endif /* _SYSCALL32 */
|
||||
|
||||
/*
|
||||
* For the various utilities that include sgs.h
|
||||
*/
|
||||
extern int assfail(const char *, const char *, int);
|
||||
extern void eprintf(Lm_list *, Error, const char *, ...);
|
||||
extern char *sgs_demangle(char *);
|
||||
extern uint_t sgs_str_hash(const char *);
|
||||
extern uint_t findprime(uint_t);
|
||||
|
||||
#endif /* _ASM */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _SGS_H */
|
@ -1,63 +0,0 @@
|
||||
/*
|
||||
* 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 2008 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>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Exported, opaque string table handle.
|
||||
*/
|
||||
typedef struct str_tbl Str_tbl;
|
||||
|
||||
/*
|
||||
* Exported string table functions.
|
||||
*/
|
||||
extern int st_delstring(Str_tbl *, const char *);
|
||||
extern void st_destroy(Str_tbl *);
|
||||
extern size_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 *, size_t);
|
||||
extern int st_setstring(Str_tbl *, const char *, size_t *);
|
||||
|
||||
/*
|
||||
* Exported flags values for st_new().
|
||||
*/
|
||||
#define FLG_STNEW_COMPRESS 0x01 /* compressed string table */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _STRING_TABLE_DOT_H */
|
@ -1,62 +0,0 @@
|
||||
#
|
||||
# Copyright 2008 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"
|
||||
#
|
||||
#
|
||||
# Global message identifiers for the sgs utilities. This information is read
|
||||
# by sgsmsg(1l) using the -i option.
|
||||
# Each utilities message file references one of the `MSGID' identifiers. Its
|
||||
# associated numeric setid is used when creating catgets(3c) messages, the
|
||||
# string domain is used when creating gettext(3i) messages.
|
||||
#
|
||||
|
||||
mesgid setid domain
|
||||
|
||||
MSG_ID_RTLD 1 SUNW_OST_SGS /* sgs/rtld */
|
||||
MSG_ID_LIBRTLD 2 SUNW_OST_SGS /* sgs/librtld */
|
||||
MSG_ID_LIBLD 3 SUNW_OST_SGS /* sgs/libld */
|
||||
MSG_ID_LIBLDDBG 4 SUNW_OST_SGS /* sgs/liblddbg */
|
||||
MSG_ID_LIBLDSTAB 5 SUNW_OST_SGS /* sgs/libldstab */
|
||||
MSG_ID_LIBRTLD_DB 6 SUNW_OST_SGS /* sgs/librtld_db */
|
||||
MSG_ID_LIBPROF 7 SUNW_OST_SGS /* sgs/libprof */
|
||||
MSG_ID_LIBCRLE 8 SUNW_OST_SGS /* sgs/libcrle */
|
||||
|
||||
MSG_ID_LIBELF 10 SUNW_OST_SGS /* sgs/libelf */
|
||||
|
||||
MSG_ID_LD 20 SUNW_OST_SGS /* sgs/ld */
|
||||
MSG_ID_LDD 21 SUNW_OST_SGS /* sgs/ldd */
|
||||
MSG_ID_PVS 22 SUNW_OST_SGS /* sgs/pvs */
|
||||
MSG_ID_CRLE 23 SUNW_OST_SGS /* sgs/crle */
|
||||
MSG_ID_ELFDUMP 24 SUNW_OST_SGS /* sgs/elfdump */
|
||||
MSG_ID_MOE 25 SUNW_OST_SGS /* sgs/moe */
|
||||
MSG_ID_ELFEDIT 26 SUNW_OST_SGS /* sgs/elfedit */
|
||||
MSG_ID_ELFEDIT_CAP 27 SUNW_OST_SGS /* cap: */
|
||||
MSG_ID_ELFEDIT_DYN 27 SUNW_OST_SGS /* dyn: */
|
||||
MSG_ID_ELFEDIT_EHDR 27 SUNW_OST_SGS /* ehdr: */
|
||||
MSG_ID_ELFEDIT_PHDR 27 SUNW_OST_SGS /* phdr: */
|
||||
MSG_ID_ELFEDIT_SHDR 27 SUNW_OST_SGS /* shdr: */
|
||||
MSG_ID_ELFEDIT_STR 27 SUNW_OST_SGS /* str: */
|
||||
MSG_ID_ELFEDIT_SYM 27 SUNW_OST_SGS /* sym: */
|
||||
MSG_ID_ELFEDIT_SYMINFO 27 SUNW_OST_SGS /* syminfo: */
|
||||
MSG_ID_ELFWRAP 28 SUNW_OST_SGS /* sgs/elfwrap */
|
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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 2003 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sgs.h>
|
||||
|
||||
/*
|
||||
* function that will find a prime'ish number. Usefull for
|
||||
* hashbuckets and related things.
|
||||
*/
|
||||
uint_t
|
||||
findprime(uint_t count)
|
||||
{
|
||||
uint_t h, f;
|
||||
|
||||
if (count <= 3)
|
||||
return (3);
|
||||
|
||||
|
||||
/*
|
||||
* Check to see if divisible by two, if so
|
||||
* increment.
|
||||
*/
|
||||
if ((count & 0x1) == 0)
|
||||
count++;
|
||||
|
||||
for (h = count, f = 2; f * f <= h; f++)
|
||||
if ((h % f) == 0)
|
||||
h += f = 1;
|
||||
return (h);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,685 +0,0 @@
|
||||
/*
|
||||
* 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 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#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 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:
|
||||
*
|
||||
* st_new(0)
|
||||
* standard string table - no compression. This is the
|
||||
* traditional, fast method.
|
||||
*
|
||||
* 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 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, 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:
|
||||
*
|
||||
* st_new(); // initialize strtab
|
||||
*
|
||||
* st_insert(st1); // first pass of strings ...
|
||||
* // calculates size required for
|
||||
* // string table
|
||||
*
|
||||
* st_delstring(st?); // remove string previously
|
||||
* // inserted
|
||||
* st_insert(stN);
|
||||
*
|
||||
* st_getstrtab_sz(); // freezes strtab and computes
|
||||
* // size of table.
|
||||
*
|
||||
* st_setstrbuf(); // associates a final destination
|
||||
* // for the string table
|
||||
*
|
||||
* st_setstring(st1); // populate the string table
|
||||
* ... // offsets are based off of second
|
||||
* // pass through the string table
|
||||
* st_setstring(stN);
|
||||
*
|
||||
* st_destroy(); // tear down string table
|
||||
* // structures.
|
||||
*
|
||||
* String Suffix Compression Algorithm:
|
||||
*
|
||||
* Here's a quick high level overview of the Suffix String
|
||||
* compression algorithm used. First - the heart of the algorithm
|
||||
* is a Hash table list which represents a dictionary of all unique
|
||||
* strings inserted into the string table. The hash function for
|
||||
* this table is a standard string hash except that the hash starts
|
||||
* at the last character in the string (&str[n - 1]) and works towards
|
||||
* the first character in the function (&str[0]). As we compute the
|
||||
* HASH value for a given string, we also compute the hash values
|
||||
* for all of the possible suffix strings for that string.
|
||||
*
|
||||
* As we compute the hash - at each character see if the current
|
||||
* suffix string for that hash is already present in the table. If
|
||||
* it is, and the string is a master string. Then change that
|
||||
* string to a suffix string of the new string being inserted.
|
||||
*
|
||||
* When the final hash value is found (hash for str[0...n]), check
|
||||
* to see if it is in the hash table - if so increment the reference
|
||||
* count for the string. If it is not yet in the table, insert a
|
||||
* new hash table entry for a master string.
|
||||
*
|
||||
* 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 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 */
|
||||
|
||||
static int
|
||||
avl_len_compare(const void *n1, const void *n2)
|
||||
{
|
||||
size_t len1, len2;
|
||||
|
||||
len1 = ((LenNode *)n1)->ln_strlen;
|
||||
len2 = ((LenNode *)n2)->ln_strlen;
|
||||
|
||||
if (len1 == len2)
|
||||
return (0);
|
||||
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 an initialized Str_tbl - returns NULL on failure.
|
||||
*
|
||||
* flags:
|
||||
* FLG_STTAB_COMPRESS - build a compressed string table
|
||||
*/
|
||||
Str_tbl *
|
||||
st_new(uint_t flags)
|
||||
{
|
||||
Str_tbl *stp;
|
||||
|
||||
if ((stp = calloc(sizeof (Str_tbl), 1)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
/*
|
||||
* Start with a leading '\0' - it's tradition.
|
||||
*/
|
||||
stp->st_strsize = stp->st_fullstrsize = stp->st_nextoff = 1;
|
||||
|
||||
/*
|
||||
* Do we compress this string table?
|
||||
*/
|
||||
stp->st_flags = flags;
|
||||
if ((stp->st_flags & FLG_STTAB_COMPRESS) == 0)
|
||||
return (stp);
|
||||
|
||||
if ((stp->st_lentree = calloc(sizeof (avl_tree_t), 1)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
avl_create(stp->st_lentree, &avl_len_compare, sizeof (LenNode),
|
||||
SGSOFFSETOF(LenNode, ln_avlnode));
|
||||
|
||||
return (stp);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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_insert(Str_tbl *stp, const char *str)
|
||||
{
|
||||
size_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);
|
||||
|
||||
/*
|
||||
* Null strings always point to the head of the string
|
||||
* table - no reason to keep searching.
|
||||
*/
|
||||
if ((len = strlen(str)) == 0)
|
||||
return (0);
|
||||
|
||||
stp->st_fullstrsize += len + 1;
|
||||
stp->st_strcnt++;
|
||||
|
||||
if ((stp->st_flags & FLG_STTAB_COMPRESS) == 0)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
if ((lnp->ln_strtree = calloc(sizeof (avl_tree_t), 1)) == NULL)
|
||||
return (0);
|
||||
|
||||
avl_create(lnp->ln_strtree, &avl_str_compare, sizeof (StrNode),
|
||||
SGSOFFSETOF(StrNode, sn_avlnode));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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++;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove a previously inserted string from the Str_tbl.
|
||||
*/
|
||||
int
|
||||
st_delstring(Str_tbl *stp, const char *str)
|
||||
{
|
||||
size_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);
|
||||
|
||||
len = strlen(str);
|
||||
stp->st_fullstrsize -= len + 1;
|
||||
|
||||
if ((stp->st_flags & FLG_STTAB_COMPRESS) == 0)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* No strings of this length, or no string itself - someone goofed.
|
||||
*/
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* For a given string - copy it into the buffer associated with
|
||||
* the string table - and return the offset it has been assigned.
|
||||
*
|
||||
* If a value of '-1' is returned - the string was not found in
|
||||
* the Str_tbl.
|
||||
*/
|
||||
int
|
||||
st_setstring(Str_tbl *stp, const char *str, size_t *stoff)
|
||||
{
|
||||
size_t stlen;
|
||||
uint_t hashval;
|
||||
Str_hash *sthash;
|
||||
Str_master *mstr;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* String table *must* have been previously cooked
|
||||
*/
|
||||
assert(stp->st_strbuf);
|
||||
|
||||
assert(stp->st_flags & FLG_STTAB_COOKED);
|
||||
stlen = strlen(str);
|
||||
/*
|
||||
* Null string always points to head of string table
|
||||
*/
|
||||
if (stlen == 0) {
|
||||
*stoff = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
if ((stp->st_flags & FLG_STTAB_COMPRESS) == 0) {
|
||||
size_t _stoff;
|
||||
|
||||
stlen++; /* count for trailing '\0' */
|
||||
_stoff = stp->st_nextoff;
|
||||
/*
|
||||
* Have we overflowed our assigned buffer?
|
||||
*/
|
||||
if ((_stoff + stlen) > stp->st_fullstrsize)
|
||||
return (-1);
|
||||
memcpy(stp->st_strbuf + _stoff, str, stlen);
|
||||
*stoff = _stoff;
|
||||
stp->st_nextoff += stlen;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate reverse hash for string.
|
||||
*/
|
||||
hashval = HASHSEED;
|
||||
for (i = stlen; i >= 0; i--) {
|
||||
hashval = ((hashval << 5) + hashval) +
|
||||
str[i]; /* h = ((h * 33) + c) */
|
||||
}
|
||||
|
||||
for (sthash = stp->st_hashbcks[hashval % stp->st_hbckcnt]; sthash;
|
||||
sthash = sthash->hi_next) {
|
||||
const char *hstr;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Did we find the string?
|
||||
*/
|
||||
if (sthash == 0)
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* Has this string been copied into the string table?
|
||||
*/
|
||||
mstr = sthash->hi_mstr;
|
||||
if (mstr->sm_stroff == 0) {
|
||||
size_t mstrlen = mstr->sm_strlen + 1;
|
||||
|
||||
mstr->sm_stroff = stp->st_nextoff;
|
||||
|
||||
/*
|
||||
* Have we overflowed our assigned buffer?
|
||||
*/
|
||||
if ((mstr->sm_stroff + mstrlen) > stp->st_fullstrsize)
|
||||
return (-1);
|
||||
|
||||
(void) memcpy(stp->st_strbuf + mstr->sm_stroff,
|
||||
mstr->sm_str, mstrlen);
|
||||
stp->st_nextoff += mstrlen;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate offset of (sub)string.
|
||||
*/
|
||||
*stoff = mstr->sm_stroff + mstr->sm_strlen - sthash->hi_strlen;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
st_hash_insert(Str_tbl *stp, const char *str, size_t len)
|
||||
{
|
||||
int i;
|
||||
uint_t hashval = HASHSEED;
|
||||
uint_t bckcnt = stp->st_hbckcnt;
|
||||
Str_hash **hashbcks = stp->st_hashbcks;
|
||||
Str_hash *sthash;
|
||||
Str_master *mstr = 0;
|
||||
|
||||
/*
|
||||
* We use a classic 'Bernstein k=33' hash function. But
|
||||
* instead of hashing from the start of the string to the
|
||||
* end, we do it in reverse.
|
||||
*
|
||||
* This way - we are essentially building all of the
|
||||
* suffix hashvalues as we go. We can check to see if
|
||||
* any suffixes already exist in the tree as we generate
|
||||
* the hash.
|
||||
*/
|
||||
for (i = len; i >= 0; i--) {
|
||||
hashval = ((hashval << 5) + hashval) +
|
||||
str[i]; /* h = ((h * 33) + c) */
|
||||
|
||||
for (sthash = hashbcks[hashval % bckcnt];
|
||||
sthash; sthash = sthash->hi_next) {
|
||||
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?
|
||||
*/
|
||||
if (mstr == 0) {
|
||||
/*
|
||||
* allocate a new master string
|
||||
*/
|
||||
if ((mstr = calloc(sizeof (Str_hash), 1)) == 0)
|
||||
return (-1);
|
||||
mstr->sm_next = stp->st_mstrlist;
|
||||
stp->st_mstrlist = mstr;
|
||||
stp->st_strsize += len + 1;
|
||||
} else {
|
||||
/*
|
||||
* 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(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_strlen = sthash->hi_strlen = len;
|
||||
mstr->sm_str = str;
|
||||
sthash->hi_refcnt = 1;
|
||||
sthash->hi_mstr = mstr;
|
||||
|
||||
/*
|
||||
* Insert string element into head of hash list
|
||||
*/
|
||||
hashval = hashval % bckcnt;
|
||||
sthash->hi_next = hashbcks[hashval];
|
||||
hashbcks[hashval] = sthash;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return amount of space required for the string table.
|
||||
*/
|
||||
size_t
|
||||
st_getstrtab_sz(Str_tbl *stp)
|
||||
{
|
||||
assert(stp->st_fullstrsize > 0);
|
||||
|
||||
if ((stp->st_flags & FLG_STTAB_COMPRESS) == 0) {
|
||||
stp->st_flags |= FLG_STTAB_COOKED;
|
||||
return (stp->st_fullstrsize);
|
||||
}
|
||||
|
||||
if ((stp->st_flags & FLG_STTAB_COOKED) == 0) {
|
||||
LenNode *lnp;
|
||||
void *cookie;
|
||||
|
||||
stp->st_flags |= FLG_STTAB_COOKED;
|
||||
/*
|
||||
* allocate a hash table about the size of # of
|
||||
* strings input.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
if ((lnp = avl_first(stp->st_lentree)) == NULL) {
|
||||
/*
|
||||
* 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_lentree) == 0) {
|
||||
assert(stp->st_strsize == 1);
|
||||
return (stp->st_strsize);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
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 the string can be freed.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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, 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 ((lnp = avl_destroy_nodes(stp->st_lentree,
|
||||
&cookie)) != NULL)
|
||||
free(lnp);
|
||||
avl_destroy(stp->st_lentree);
|
||||
free(stp->st_lentree);
|
||||
stp->st_lentree = 0;
|
||||
}
|
||||
|
||||
assert(stp->st_strsize > 0);
|
||||
assert(stp->st_fullstrsize >= stp->st_strsize);
|
||||
|
||||
return (stp->st_strsize);
|
||||
}
|
||||
|
||||
/*
|
||||
* Associate a buffer with a string table.
|
||||
*/
|
||||
const char *
|
||||
st_getstrbuf(Str_tbl *stp)
|
||||
{
|
||||
return (stp->st_strbuf);
|
||||
}
|
||||
|
||||
int
|
||||
st_setstrbuf(Str_tbl *stp, char *stbuf, size_t bufsize)
|
||||
{
|
||||
assert(stp->st_flags & FLG_STTAB_COOKED);
|
||||
|
||||
if ((stp->st_flags & FLG_STTAB_COMPRESS) == 0) {
|
||||
if (bufsize < stp->st_fullstrsize)
|
||||
return (-1);
|
||||
} else {
|
||||
if (bufsize < stp->st_strsize)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
stp->st_strbuf = stbuf;
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* for debug builds - start with a stringtable filled in
|
||||
* with '0xff'. This makes it very easy to find wholes
|
||||
* which we failed to fill in - in the strtab.
|
||||
*/
|
||||
memset(stbuf, 0xff, bufsize);
|
||||
stbuf[0] = '\0';
|
||||
#else
|
||||
memset(stbuf, 0x0, bufsize);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
@ -6,7 +6,6 @@ SUBDIR= \
|
||||
ctfconvert \
|
||||
ctfdump \
|
||||
ctfmerge \
|
||||
sgsmsg \
|
||||
${_tests} \
|
||||
${_zinject} \
|
||||
${_zlook} \
|
||||
|
@ -1,17 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/cmd/sgs/tools/common
|
||||
.PATH: ${.CURDIR}/../../../sys/cddl/contrib/opensolaris/common/avl
|
||||
|
||||
# This program is required as a bootstrap tool for 'make buildworld'
|
||||
PROG= sgsmsg
|
||||
MAN=
|
||||
SRCS= avl.c sgsmsg.c string_table.c findprime.c
|
||||
|
||||
WARNS?= 0
|
||||
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/compat/opensolaris \
|
||||
-I${.CURDIR}/../../../cddl/compat/opensolaris/include \
|
||||
-I${OPENSOLARIS_USR_DISTDIR}/cmd/sgs/include \
|
||||
-I${OPENSOLARIS_SYS_DISTDIR}/uts/common
|
||||
|
||||
.include <bsd.prog.mk>
|
@ -1,19 +0,0 @@
|
||||
# $FreeBSD$
|
||||
# Autogenerated - do NOT edit!
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
lib/libc \
|
||||
lib/libcompiler_rt \
|
||||
lib/libelf \
|
||||
|
||||
|
||||
.include <dirdeps.mk>
|
||||
|
||||
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
|
||||
# local dependencies - needed for -jN in clean tree
|
||||
.endif
|
@ -12,7 +12,6 @@ DIRDEPS = \
|
||||
cddl/lib/libnvpair \
|
||||
cddl/lib/libumem \
|
||||
cddl/lib/libuutil \
|
||||
cddl/usr.bin/sgsmsg \
|
||||
|
||||
|
||||
DIRDEPS.CTF = \
|
||||
|
@ -910,7 +910,6 @@ OLD_LIBS+=lib/libuutil.so.2
|
||||
OLD_FILES+=usr/bin/ctfconvert
|
||||
OLD_FILES+=usr/bin/ctfdump
|
||||
OLD_FILES+=usr/bin/ctfmerge
|
||||
OLD_FILES+=usr/bin/sgsmsg
|
||||
OLD_FILES+=usr/lib/dtrace/drti.o
|
||||
OLD_FILES+=usr/lib/dtrace/errno.d
|
||||
OLD_FILES+=usr/lib/dtrace/io.d
|
||||
|
Loading…
Reference in New Issue
Block a user