Mercurial > illumos > illumos-gate
changeset 11827:d7ef53deac3f
6918143 symbol capabilities
6910387 .tdata and .tbss separation invalidates TLS program header information
line wrap: on
line diff
--- a/usr/src/cmd/sgs/Makefile Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/Makefile Mon Mar 01 10:20:48 2010 -0800 @@ -19,11 +19,9 @@ # CDDL HEADER END # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# include $(SRC)/cmd/Makefile.cmd @@ -192,6 +190,7 @@ # we want xref to list the source file. # XRDIRS= . \ + ../../common/elfcap \ ../../head \ ../../uts/common/krtld \ ../../uts/common/sys \
--- a/usr/src/cmd/sgs/Makefile.com Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/Makefile.com Mon Mar 01 10:20:48 2010 -0800 @@ -18,6 +18,7 @@ # # CDDL HEADER END # + # # Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. @@ -118,12 +119,14 @@ native := DYNFLAGS = -R$(SGSPROTO) -L$(SGSPROTO) $(ZNOVERSION) -USE_PROTO = -Yl,$(SGSPROTO) +# Comment out the following two lines to have the sgs built from the system +# link-editor, rather than the local proto link-editor. +CC_USE_PROTO = -Yl,$(SGSPROTO) +LD_USE_PROTO = $(SGSPROTO)/ # # lint-related stuff # - LIBNAME32 = $(LIBNAME:%=%32) LIBNAME64 = $(LIBNAME:%=%64) LIBNAMES = $(LIBNAME32) $(LIBNAME64) @@ -141,7 +144,20 @@ LINTFLAGS = -m -errtags=yes -erroff=E_SUPPRESSION_DIRECTIVE_UNUSED LINTFLAGS64 = -m -errtags=yes -erroff=E_SUPPRESSION_DIRECTIVE_UNUSED \ - $(VAR_LINTFLAGS64) \ + $(VAR_LINTFLAGS64) + +# +# When building a lint library, no other lint libraries are verified as +# dependencies, nor is the stardard C lint library processed. All dependency +# verification is carried out through linting the sources themselves. +# +$(LINTLIB) := LINTFLAGS += -n +$(LINTLIB) := LINTFLAGS64 += -n + +$(LINTLIB32) := LINTFLAGS += -n +$(LINTLIB32) := LINTFLAGS64 += -n +$(LINTLIB64) := LINTFLAGS += -n +$(LINTLIB64) := LINTFLAGS64 += -n # # These libraries have two resulting lint libraries. If a dependency is
--- a/usr/src/cmd/sgs/crle/Makefile.com Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/crle/Makefile.com Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -43,7 +43,7 @@ -D__EXTENSIONS__ LLDFLAGS = '-R$$ORIGIN/../lib' LLDFLAGS64 = '-R$$ORIGIN/../../lib/$(MACH64)' -LDFLAGS += $(VERSREF) $(USE_PROTO) $(MAPOPT) \ +LDFLAGS += $(VERSREF) $(CC_USE_PROTO) $(MAPOPT) \ $(LLDFLAGS) $(ZNOLAZYLOAD) LDLIBS += -lelf $(CONVLIBDIR) $(CONV_LIB) $(DLLIB) LINTFLAGS += -x
--- a/usr/src/cmd/sgs/dump/common/dump.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/dump/common/dump.c Mon Mar 01 10:20:48 2010 -0800 @@ -23,7 +23,7 @@ * Copyright (c) 1988 AT&T * All Rights Reserved * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1154,6 +1154,8 @@ case DT_PREINIT_ARRAYSZ: case DT_SUNW_RTLDINF: case DT_SUNW_CAP: + case DT_SUNW_CAPINFO: + case DT_SUNW_CAPCHAIN: case DT_SUNW_SYMTAB: case DT_SUNW_SYMSORT: case DT_SUNW_TLSSORT: @@ -1222,6 +1224,8 @@ case DT_SUNW_SYMSORTSZ: case DT_SUNW_TLSSORTSZ: case DT_SUNW_STRPAD: + case DT_SUNW_CAPCHAINENT: + case DT_SUNW_CAPCHAINSZ: (void) printf(pdyn_Fmtptr, EC_XWORD(p_dyn.d_un.d_val)); break;
--- a/usr/src/cmd/sgs/elfdump/Makefile.com Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/elfdump/Makefile.com Mon Mar 01 10:20:48 2010 -0800 @@ -52,7 +52,7 @@ $(CPPFLAGS.master) -I$(ELFCAP) LLDFLAGS = $(VAR_ELFDUMP_LLDFLAGS) LLDFLAGS64 = $(VAR_LD_LLDFLAGS64) -LDFLAGS += $(VERSREF) $(USE_PROTO) $(MAPOPT) $(LLDFLAGS) +LDFLAGS += $(VERSREF) $(CC_USE_PROTO) $(MAPOPT) $(LLDFLAGS) LDLIBS += $(ELFLIBDIR) -lelf $(LDDBGLIBDIR) $(LDDBG_LIB) \ $(CONVLIBDIR) $(CONV_LIB)
--- a/usr/src/cmd/sgs/elfdump/common/elfdump.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/elfdump/common/elfdump.c Mon Mar 01 10:20:48 2010 -0800 @@ -812,9 +812,8 @@ * We match these sections by name, rather than section type, * because they can come in as either SHT_AMD64_UNWIND, or as * SHT_PROGBITS, and because the type isn't enough to determine - * how they should be interprteted. + * how they should be interpreted. */ - /* Find the program header for .eh_frame_hdr if present */ if (phnum) uphdr = getphdr(phnum, phdr_types, @@ -822,7 +821,7 @@ /* * eh_state is used to retain data used by unwind_eh_frame() - * accross calls. + * across calls. */ bzero(&eh_state, sizeof (eh_state)); @@ -882,12 +881,739 @@ } /* - * Print the hardware/software capabilities. For executables and shared objects - * this should be accompanied with a program header. + * Initialize a symbol table state structure + * + * entry: + * state - State structure to be initialized + * cache - Cache of all section headers + * shnum - # of sections in cache + * secndx - Index of symbol table section + * ehdr - ELF header for file + * versym - Information about versym section + * file - Name of file + * flags - Command line option flags + */ +static int +init_symtbl_state(SYMTBL_STATE *state, Cache *cache, Word shnum, Word secndx, + Ehdr *ehdr, uchar_t osabi, VERSYM_STATE *versym, const char *file, + uint_t flags) +{ + Shdr *shdr; + + state->file = file; + state->ehdr = ehdr; + state->cache = cache; + state->osabi = osabi; + state->shnum = shnum; + state->seccache = &cache[secndx]; + state->secndx = secndx; + state->secname = state->seccache->c_name; + state->flags = flags; + state->shxndx.checked = 0; + state->shxndx.data = NULL; + state->shxndx.n = 0; + + shdr = state->seccache->c_shdr; + + /* + * Check the symbol data and per-item size. + */ + if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { + (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), + file, state->secname); + return (0); + } + if (state->seccache->c_data == NULL) + return (0); + + /* LINTED */ + state->symn = (Word)(shdr->sh_size / shdr->sh_entsize); + state->sym = (Sym *)state->seccache->c_data->d_buf; + + /* + * Check associated string table section. + */ + if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { + (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), + file, state->secname, EC_WORD(shdr->sh_link)); + return (0); + } + + /* + * Determine if there is a associated Versym section + * with this Symbol Table. + */ + if (versym && versym->cache && + (versym->cache->c_shdr->sh_link == state->secndx)) + state->versym = versym; + else + state->versym = NULL; + + + return (1); +} + +/* + * Determine the extended section index used for symbol tables entries. + */ +static void +symbols_getxindex(SYMTBL_STATE *state) +{ + uint_t symn; + Word symcnt; + + state->shxndx.checked = 1; /* Note that we've been called */ + for (symcnt = 1; symcnt < state->shnum; symcnt++) { + Cache *_cache = &state->cache[symcnt]; + Shdr *shdr = _cache->c_shdr; + + if ((shdr->sh_type != SHT_SYMTAB_SHNDX) || + (shdr->sh_link != state->secndx)) + continue; + + if ((shdr->sh_entsize) && + /* LINTED */ + ((symn = (uint_t)(shdr->sh_size / shdr->sh_entsize)) == 0)) + continue; + + if (_cache->c_data == NULL) + continue; + + state->shxndx.data = _cache->c_data->d_buf; + state->shxndx.n = symn; + return; + } +} + +/* + * Produce a line of output for the given symbol + * + * entry: + * state - Symbol table state + * symndx - Index of symbol within the table + * info - Value of st_info (indicates local/global range) + * symndx_disp - Index to display. This may not be the same + * as symndx if the display is relative to the logical + * combination of the SUNW_ldynsym/dynsym tables. + * sym - Symbol to display + */ +static void +output_symbol(SYMTBL_STATE *state, Word symndx, Word info, Word disp_symndx, + Sym *sym) +{ + /* + * Symbol types for which we check that the specified + * address/size land inside the target section. + */ + static const int addr_symtype[] = { + 0, /* STT_NOTYPE */ + 1, /* STT_OBJECT */ + 1, /* STT_FUNC */ + 0, /* STT_SECTION */ + 0, /* STT_FILE */ + 1, /* STT_COMMON */ + 0, /* STT_TLS */ + 0, /* 7 */ + 0, /* 8 */ + 0, /* 9 */ + 0, /* 10 */ + 0, /* 11 */ + 0, /* 12 */ + 0, /* STT_SPARC_REGISTER */ + 0, /* 14 */ + 0, /* 15 */ + }; +#if STT_NUM != (STT_TLS + 1) +#error "STT_NUM has grown. Update addr_symtype[]" +#endif + + char index[MAXNDXSIZE]; + const char *symname, *sec; + Versym verndx; + int gnuver; + uchar_t type; + Shdr *tshdr; + Word shndx; + Conv_inv_buf_t inv_buf; + + /* Ensure symbol index is in range */ + if (symndx >= state->symn) { + (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSYMNDX), + state->file, state->secname, EC_WORD(symndx)); + return; + } + + /* + * If we are using extended symbol indexes, find the + * corresponding SHN_SYMTAB_SHNDX table. + */ + if ((sym->st_shndx == SHN_XINDEX) && (state->shxndx.checked == 0)) + symbols_getxindex(state); + + /* LINTED */ + symname = string(state->seccache, symndx, + &state->cache[state->seccache->c_shdr->sh_link], state->file, + sym->st_name); + + tshdr = NULL; + sec = NULL; + + if (state->ehdr->e_type == ET_CORE) { + sec = (char *)MSG_INTL(MSG_STR_UNKNOWN); + } else if (state->flags & FLG_CTL_FAKESHDR) { + /* + * If we are using fake section headers derived from + * the program headers, then the section indexes + * in the symbols do not correspond to these headers. + * The section names are not available, so all we can + * do is to display them in numeric form. + */ + sec = conv_sym_shndx(state->osabi, state->ehdr->e_machine, + sym->st_shndx, CONV_FMT_DECIMAL, &inv_buf); + } else if ((sym->st_shndx < SHN_LORESERVE) && + (sym->st_shndx < state->shnum)) { + shndx = sym->st_shndx; + tshdr = state->cache[shndx].c_shdr; + sec = state->cache[shndx].c_name; + } else if (sym->st_shndx == SHN_XINDEX) { + if (state->shxndx.data) { + Word _shxndx; + + if (symndx > state->shxndx.n) { + (void) fprintf(stderr, + MSG_INTL(MSG_ERR_BADSYMXINDEX1), + state->file, state->secname, + EC_WORD(symndx)); + } else if ((_shxndx = + state->shxndx.data[symndx]) > state->shnum) { + (void) fprintf(stderr, + MSG_INTL(MSG_ERR_BADSYMXINDEX2), + state->file, state->secname, + EC_WORD(symndx), EC_WORD(_shxndx)); + } else { + shndx = _shxndx; + tshdr = state->cache[shndx].c_shdr; + sec = state->cache[shndx].c_name; + } + } else { + (void) fprintf(stderr, + MSG_INTL(MSG_ERR_BADSYMXINDEX3), + state->file, state->secname, EC_WORD(symndx)); + } + } else if ((sym->st_shndx < SHN_LORESERVE) && + (sym->st_shndx >= state->shnum)) { + (void) fprintf(stderr, + MSG_INTL(MSG_ERR_BADSYM5), state->file, + state->secname, EC_WORD(symndx), + demangle(symname, state->flags), sym->st_shndx); + } + + /* + * If versioning is available display the + * version index. If not, then use 0. + */ + if (state->versym) { + Versym test_verndx; + + verndx = test_verndx = state->versym->data[symndx]; + gnuver = state->versym->gnu_full; + + /* + * Check to see if this is a defined symbol with a + * version index that is outside the valid range for + * the file. The interpretation of this depends on + * the style of versioning used by the object. + * + * Versions >= VER_NDX_LORESERVE have special meanings, + * and are exempt from this checking. + * + * GNU style version indexes use the top bit of the + * 16-bit index value (0x8000) as the "hidden bit". + * We must mask off this bit in order to compare + * the version against the maximum value. + */ + if (gnuver) + test_verndx &= ~0x8000; + + if ((test_verndx > state->versym->max_verndx) && + (verndx < VER_NDX_LORESERVE)) + (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADVER), + state->file, state->secname, EC_WORD(symndx), + EC_HALF(test_verndx), state->versym->max_verndx); + } else { + verndx = 0; + gnuver = 0; + } + + /* + * Error checking for TLS. + */ + type = ELF_ST_TYPE(sym->st_info); + if (type == STT_TLS) { + if (tshdr && + (sym->st_shndx != SHN_UNDEF) && + ((tshdr->sh_flags & SHF_TLS) == 0)) { + (void) fprintf(stderr, + MSG_INTL(MSG_ERR_BADSYM3), state->file, + state->secname, EC_WORD(symndx), + demangle(symname, state->flags)); + } + } else if ((type != STT_SECTION) && sym->st_size && + tshdr && (tshdr->sh_flags & SHF_TLS)) { + (void) fprintf(stderr, + MSG_INTL(MSG_ERR_BADSYM4), state->file, + state->secname, EC_WORD(symndx), + demangle(symname, state->flags)); + } + + /* + * If a symbol with non-zero size has a type that + * specifies an address, then make sure the location + * it references is actually contained within the + * section. UNDEF symbols don't count in this case, + * so we ignore them. + * + * The meaning of the st_value field in a symbol + * depends on the type of object. For a relocatable + * object, it is the offset within the section. + * For sharable objects, it is the offset relative to + * the base of the object, and for other types, it is + * the virtual address. To get an offset within the + * section for non-ET_REL files, we subtract the + * base address of the section. + */ + if (addr_symtype[type] && (sym->st_size > 0) && + (sym->st_shndx != SHN_UNDEF) && ((sym->st_shndx < SHN_LORESERVE) || + (sym->st_shndx == SHN_XINDEX)) && (tshdr != NULL)) { + Word v = sym->st_value; + if (state->ehdr->e_type != ET_REL) + v -= tshdr->sh_addr; + if (((v + sym->st_size) > tshdr->sh_size)) { + (void) fprintf(stderr, + MSG_INTL(MSG_ERR_BADSYM6), state->file, + state->secname, EC_WORD(symndx), + demangle(symname, state->flags), + EC_WORD(shndx), EC_XWORD(tshdr->sh_size), + EC_XWORD(sym->st_value), EC_XWORD(sym->st_size)); + } + } + + /* + * A typical symbol table uses the sh_info field to indicate one greater + * than the symbol table index of the last local symbol, STB_LOCAL. + * Therefore, symbol indexes less than sh_info should have local + * binding. Symbol indexes greater than, or equal to sh_info, should + * have global binding. Note, we exclude UNDEF/NOTY symbols with zero + * value and size, as these symbols may be the result of an mcs(1) + * section deletion. + */ + if (info) { + uchar_t bind = ELF_ST_BIND(sym->st_info); + + if ((symndx < info) && (bind != STB_LOCAL)) { + (void) fprintf(stderr, + MSG_INTL(MSG_ERR_BADSYM7), state->file, + state->secname, EC_WORD(symndx), + demangle(symname, state->flags), EC_XWORD(info)); + + } else if ((symndx >= info) && (bind == STB_LOCAL) && + ((sym->st_shndx != SHN_UNDEF) || + (ELF_ST_TYPE(sym->st_info) != STT_NOTYPE) || + (sym->st_size != 0) || (sym->st_value != 0))) { + (void) fprintf(stderr, + MSG_INTL(MSG_ERR_BADSYM8), state->file, + state->secname, EC_WORD(symndx), + demangle(symname, state->flags), EC_XWORD(info)); + } + } + + (void) snprintf(index, MAXNDXSIZE, + MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(disp_symndx)); + Elf_syms_table_entry(0, ELF_DBG_ELFDUMP, index, state->osabi, + state->ehdr->e_machine, sym, verndx, gnuver, sec, symname); +} + +/* + * Process a SHT_SUNW_cap capabilities section. + */ +static int +cap_section(const char *file, Cache *cache, Word shnum, Cache *ccache, + uchar_t osabi, Ehdr *ehdr, uint_t flags) +{ + SYMTBL_STATE state; + Word cnum, capnum, nulls, symcaps; + int descapndx, objcap, title; + Cap *cap = (Cap *)ccache->c_data->d_buf; + Shdr *cishdr, *cshdr = ccache->c_shdr; + Cache *cicache, *strcache; + Capinfo *capinfo = NULL; + Word capinfonum; + const char *strs = NULL; + size_t strs_size; + + if ((cshdr->sh_entsize == 0) || (cshdr->sh_size == 0)) { + (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), + file, ccache->c_name); + return (0); + } + + /* + * If this capabilities section is associated with symbols, then the + * sh_link field points to the associated capabilities information + * section. The sh_link field of the capabilities information section + * points to the associated symbol table. + */ + if (cshdr->sh_link) { + Cache *scache; + Shdr *sshdr; + + /* + * Validate that the sh_link field points to a capabilities + * information section. + */ + if (cshdr->sh_link >= shnum) { + (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), + file, ccache->c_name, EC_WORD(cshdr->sh_link)); + return (0); + } + + cicache = &cache[cshdr->sh_link]; + cishdr = cicache->c_shdr; + + if (cishdr->sh_type != SHT_SUNW_capinfo) { + (void) fprintf(stderr, MSG_INTL(MSG_ERR_INVCAP), + file, ccache->c_name, EC_WORD(cshdr->sh_link)); + return (0); + } + + capinfo = cicache->c_data->d_buf; + capinfonum = (Word)(cishdr->sh_size / cishdr->sh_entsize); + + /* + * Validate that the sh_link field of the capabilities + * information section points to a valid symbol table. + */ + if ((cishdr->sh_link == 0) || (cishdr->sh_link >= shnum)) { + (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), + file, cicache->c_name, EC_WORD(cishdr->sh_link)); + return (0); + } + scache = &cache[cishdr->sh_link]; + sshdr = scache->c_shdr; + + if ((sshdr->sh_type != SHT_SYMTAB) && + (sshdr->sh_type != SHT_DYNSYM)) { + (void) fprintf(stderr, MSG_INTL(MSG_ERR_INVCAPINFO1), + file, cicache->c_name, EC_WORD(cishdr->sh_link)); + return (0); + } + + if (!init_symtbl_state(&state, cache, shnum, + cishdr->sh_link, ehdr, osabi, NULL, file, flags)) + return (0); + } + + /* + * If this capabilities section contains capability string entries, + * then determine the associated string table. Capabilities entries + * that define names require that the capability section indicate + * which string table to use via sh_info. + */ + if (cshdr->sh_info) { + Shdr *strshdr; + + /* + * Validate that the sh_info field points to a string table. + */ + if (cshdr->sh_info >= shnum) { + (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), + file, ccache->c_name, EC_WORD(cshdr->sh_info)); + return (0); + } + + strcache = &cache[cshdr->sh_info]; + strshdr = strcache->c_shdr; + + if (strshdr->sh_type != SHT_STRTAB) { + (void) fprintf(stderr, MSG_INTL(MSG_ERR_INVCAP), + file, ccache->c_name, EC_WORD(cshdr->sh_info)); + return (0); + } + strs = (const char *)strcache->c_data->d_buf; + strs_size = strcache->c_data->d_size; + } + + dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); + dbg_print(0, MSG_INTL(MSG_ELF_SCN_CAP), ccache->c_name); + + capnum = (Word)(cshdr->sh_size / cshdr->sh_entsize); + + nulls = symcaps = 0; + objcap = title = 1; + descapndx = -1; + + /* + * Traverse the capabilities section printing each capability group. + * The first capabilities group defines any object capabilities. Any + * following groups define symbol capabilities. In the case where no + * object capabilities exist, but symbol capabilities do, a single + * CA_SUNW_NULL terminator for the object capabilities exists. + */ + for (cnum = 0; cnum < capnum; cap++, cnum++) { + if (cap->c_tag == CA_SUNW_NULL) { + /* + * A CA_SUNW_NULL tag terminates a capabilities group. + * If the first capabilities tag is CA_SUNW_NULL, then + * no object capabilities exist. + */ + if ((nulls++ == 0) && (cnum == 0)) + objcap = 0; + title = 1; + } else { + if (title) { + if (nulls == 0) { + /* + * If this capabilities group represents + * the object capabilities (i.e., no + * CA_SUNW_NULL tag has been processed + * yet), then display an object + * capabilities title. + */ + dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); + dbg_print(0, + MSG_INTL(MSG_OBJ_CAP_TITLE)); + } else { + /* + * If this is a symbols capabilities + * group (i.e., a CA_SUNW_NULL tag has + * already be found that terminates + * the object capabilities group), then + * display a symbol capabilities title, + * and retain this capabilities index + * for later processing. + */ + dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); + dbg_print(0, + MSG_INTL(MSG_SYM_CAP_TITLE)); + descapndx = cnum; + } + Elf_cap_title(0); + title = 0; + } + + /* + * Print the capabilities data. + * + * Note that CA_SUNW_PLAT, CA_SUNW_MACH and CA_SUNW_ID + * entries require a string table, which should have + * already been established. + */ + if ((strs == NULL) && ((cap->c_tag == CA_SUNW_PLAT) || + (cap->c_tag == CA_SUNW_MACH) || + (cap->c_tag == CA_SUNW_ID))) { + (void) fprintf(stderr, + MSG_INTL(MSG_WARN_INVCAP4), file, + EC_WORD(elf_ndxscn(ccache->c_scn)), + ccache->c_name, EC_WORD(cshdr->sh_info)); + } + Elf_cap_entry(0, cap, cnum, strs, strs_size, + ehdr->e_machine); + } + + /* + * If this CA_SUNW_NULL tag terminates a symbol capabilities + * group, determine the associated symbols. + */ + if ((cap->c_tag == CA_SUNW_NULL) && (nulls > 1) && + (descapndx != -1)) { + Capinfo *cip; + Word inum; + + symcaps++; + + /* + * Make sure we've discovered a SHT_SUNW_capinfo table. + */ + if ((cip = capinfo) == NULL) { + (void) fprintf(stderr, + MSG_INTL(MSG_ERR_INVCAP), file, + ccache->c_name, EC_WORD(cshdr->sh_link)); + return (0); + } + + /* + * Determine what symbols reference this capabilities + * group. + */ + dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); + dbg_print(0, MSG_INTL(MSG_CAPINFO_ENTRIES)); + Elf_syms_table_title(0, ELF_DBG_ELFDUMP); + + for (inum = 1, cip++; inum < capinfonum; + inum++, cip++) { + Word gndx = (Word)ELF_C_GROUP(*cip); + + if (gndx && (gndx == descapndx)) { + output_symbol(&state, inum, 0, + inum, state.sym + inum); + } + } + descapndx = -1; + continue; + } + + /* + * An SF1_SUNW_ADDR32 software capability tag in a 32-bit + * object is suspicious as it has no effect. + */ + if ((cap->c_tag == CA_SUNW_SF_1) && + (ehdr->e_ident[EI_CLASS] == ELFCLASS32) && + (cap->c_un.c_val & SF1_SUNW_ADDR32)) { + (void) fprintf(stderr, MSG_INTL(MSG_WARN_INADDR32SF1), + file, ccache->c_name); + } + } + + /* + * If this is a dynamic object, with symbol capabilities, then a + * .SUNW_capchain section should exist. This section contains a chain + * of symbol indexes for each capabilities family. This is the list + * that is searched by ld.so.1 to determine the best capabilities + * candidate. + * + * Note, more than one capabilities lead symbol can point to the same + * family chain. For example, a weak/global pair of symbols can both + * represent the same family of capabilities symbols. Therefore, to + * display all possible families we traverse the capabilities + * information section looking for CAPINFO_SUNW_GLOB lead symbols. + * From these we determine the associated capabilities chain to inspect. + */ + if (symcaps && + ((ehdr->e_type == ET_EXEC) || (ehdr->e_type == ET_DYN))) { + Capinfo *cip; + Capchain *chain; + Cache *chcache; + Shdr *chshdr; + Word chainnum, inum; + + /* + * Validate that the sh_info field of the capabilities + * information section points to a capabilities chain section. + */ + if (cishdr->sh_info >= shnum) { + (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), + file, cicache->c_name, EC_WORD(cishdr->sh_info)); + return (0); + } + + chcache = &cache[cishdr->sh_info]; + chshdr = chcache->c_shdr; + + if (chshdr->sh_type != SHT_SUNW_capchain) { + (void) fprintf(stderr, MSG_INTL(MSG_ERR_INVCAPINFO2), + file, cicache->c_name, EC_WORD(cishdr->sh_info)); + return (0); + } + + chainnum = (Word)(chshdr->sh_size / chshdr->sh_entsize); + chain = (Capchain *)chcache->c_data->d_buf; + + dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); + dbg_print(0, MSG_INTL(MSG_ELF_SCN_CAPCHAIN), chcache->c_name); + + /* + * Traverse the capabilities information section looking for + * CAPINFO_SUNW_GLOB lead capabilities symbols. + */ + cip = capinfo; + for (inum = 1, cip++; inum < capinfonum; inum++, cip++) { + const char *name; + Sym *sym; + Word sndx, cndx; + Word gndx = (Word)ELF_C_GROUP(*cip); + + if ((gndx == 0) || (gndx != CAPINFO_SUNW_GLOB)) + continue; + + /* + * Determine the symbol that is associated with this + * capability information entry, and use this to + * identify this capability family. + */ + sym = (Sym *)(state.sym + inum); + name = string(cicache, inum, strcache, file, + sym->st_name); + + dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); + dbg_print(0, MSG_INTL(MSG_CAPCHAIN_TITLE), name); + dbg_print(0, MSG_INTL(MSG_CAPCHAIN_ENTRY)); + + cndx = (Word)ELF_C_SYM(*cip); + + /* + * Traverse this families chain and identify each + * family member. + */ + for (;;) { + char _chain[MAXNDXSIZE], _symndx[MAXNDXSIZE]; + + if (cndx >= chainnum) { + (void) fprintf(stderr, + MSG_INTL(MSG_ERR_INVCAPINFO3), file, + cicache->c_name, EC_WORD(inum), + EC_WORD(cndx)); + break; + } + if ((sndx = chain[cndx]) == 0) + break; + + /* + * Determine this entries symbol reference. + */ + if (sndx > state.symn) { + (void) fprintf(stderr, + MSG_INTL(MSG_ERR_CHBADSYMNDX), file, + EC_WORD(sndx), chcache->c_name, + EC_WORD(cndx)); + name = MSG_INTL(MSG_STR_UNKNOWN); + } else { + sym = (Sym *)(state.sym + sndx); + name = string(chcache, sndx, + strcache, file, sym->st_name); + } + + /* + * Display the family member. + */ + (void) snprintf(_chain, MAXNDXSIZE, + MSG_ORIG(MSG_FMT_INTEGER), cndx); + (void) snprintf(_symndx, MAXNDXSIZE, + MSG_ORIG(MSG_FMT_INDEX2), EC_WORD(sndx)); + dbg_print(0, MSG_ORIG(MSG_FMT_CHAIN_INFO), + _chain, _symndx, demangle(name, flags)); + + cndx++; + } + } + } + return (objcap); +} + +/* + * Print the capabilities. + * + * A .SUNW_cap section can contain one or more, CA_SUNW_NULL terminated, + * capabilities groups. The first group defines the object capabilities. + * This group defines the minimum capability requirements of the entire + * object file. If this is a dynamic object, this group should be associated + * with a PT_SUNWCAP program header. + * + * Additional capabilities groups define the association of individual symbols + * to specific capabilities. */ static void cap(const char *file, Cache *cache, Word shnum, Word phnum, Ehdr *ehdr, - Elf *elf) + uchar_t osabi, Elf *elf, uint_t flags) { Word cnt; Shdr *cshdr = NULL; @@ -896,7 +1622,7 @@ Xword cphdr_sz; /* - * Determine if a hardware/software capabilities header exists. + * Determine if a global capabilities header exists. */ if (phnum) { Phdr *phdr; @@ -916,84 +1642,52 @@ } /* - * Determine if a hardware/software capabilities section exists. + * Determine if a capabilities section exists. */ for (cnt = 1; cnt < shnum; cnt++) { Cache *_cache = &cache[cnt]; Shdr *shdr = _cache->c_shdr; - if (shdr->sh_type != SHT_SUNW_cap) - continue; - - if (cphdr_off && ((cphdr_off < shdr->sh_offset) || - (cphdr_off + cphdr_sz) > (shdr->sh_offset + shdr->sh_size))) + /* + * Process any capabilities information. + */ + if (shdr->sh_type == SHT_SUNW_cap) { + if (cap_section(file, cache, shnum, _cache, osabi, + ehdr, flags)) { + /* + * If this section defined an object capability + * group, retain the section information for + * program header validation. + */ + ccache = _cache; + cshdr = shdr; + } continue; - - if (_cache->c_data == NULL) - continue; - - ccache = _cache; - cshdr = shdr; - break; + } } if ((cshdr == NULL) && (cphdr_off == 0)) return; - /* - * Print the hardware/software capabilities section. - */ - if (cshdr) { - Word ndx, capn; - Cap *cap = (Cap *)ccache->c_data->d_buf; - - if ((cshdr->sh_entsize == 0) || (cshdr->sh_size == 0)) { - (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), - file, ccache->c_name); - return; - } - - dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); - dbg_print(0, MSG_INTL(MSG_ELF_SCN_CAP), ccache->c_name); - - Elf_cap_title(0); - - capn = (Word)(cshdr->sh_size / cshdr->sh_entsize); - - for (ndx = 0; ndx < capn; cap++, ndx++) { - if (cap->c_tag == CA_SUNW_NULL) - continue; - - Elf_cap_entry(0, cap, ndx, ehdr->e_machine); - - /* - * An SF1_SUNW_ADDR32 software capability in a 32-bit - * object is suspicious as it has no effect. - */ - if ((cap->c_tag == CA_SUNW_SF_1) && - (ehdr->e_ident[EI_CLASS] == ELFCLASS32) && - (cap->c_un.c_val & SF1_SUNW_ADDR32)) { - (void) fprintf(stderr, - MSG_INTL(MSG_WARN_INADDR32SF1), - file, ccache->c_name); - } - } - } else + if (cphdr_off && (cshdr == NULL)) (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP1), file); /* - * If this object is an executable or shared object, then the - * hardware/software capabilities section should have an accompanying - * program header. + * If this object is an executable or shared object, and it provided + * an object capabilities group, then the group should have an + * accompanying PT_SUNWCAP program header. */ if (cshdr && ((ehdr->e_type == ET_EXEC) || (ehdr->e_type == ET_DYN))) { - if (cphdr_off == 0) + if (cphdr_off == 0) { (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP2), - file, ccache->c_name); - else if ((cphdr_off != cshdr->sh_offset) || - (cphdr_sz != cshdr->sh_size)) + file, EC_WORD(elf_ndxscn(ccache->c_scn)), + ccache->c_name); + } else if ((cphdr_off != cshdr->sh_offset) || + (cphdr_sz != cshdr->sh_size)) { (void) fprintf(stderr, MSG_INTL(MSG_WARN_INVCAP3), - file, ccache->c_name); + file, EC_WORD(elf_ndxscn(ccache->c_scn)), + ccache->c_name); + } } } @@ -1532,359 +2226,6 @@ } /* - * Initialize a symbol table state structure - * - * entry: - * state - State structure to be initialized - * cache - Cache of all section headers - * shnum - # of sections in cache - * secndx - Index of symbol table section - * ehdr - ELF header for file - * versym - Information about versym section - * file - Name of file - * flags - Command line option flags - */ -static int -init_symtbl_state(SYMTBL_STATE *state, Cache *cache, Word shnum, Word secndx, - Ehdr *ehdr, uchar_t osabi, VERSYM_STATE *versym, const char *file, - uint_t flags) -{ - Shdr *shdr; - - state->file = file; - state->ehdr = ehdr; - state->cache = cache; - state->osabi = osabi; - state->shnum = shnum; - state->seccache = &cache[secndx]; - state->secndx = secndx; - state->secname = state->seccache->c_name; - state->flags = flags; - state->shxndx.checked = 0; - state->shxndx.data = NULL; - state->shxndx.n = 0; - - shdr = state->seccache->c_shdr; - - /* - * Check the symbol data and per-item size. - */ - if ((shdr->sh_entsize == 0) || (shdr->sh_size == 0)) { - (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSZ), - file, state->secname); - return (0); - } - if (state->seccache->c_data == NULL) - return (0); - - /* LINTED */ - state->symn = (Word)(shdr->sh_size / shdr->sh_entsize); - state->sym = (Sym *)state->seccache->c_data->d_buf; - - /* - * Check associated string table section. - */ - if ((shdr->sh_link == 0) || (shdr->sh_link >= shnum)) { - (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSHLINK), - file, state->secname, EC_WORD(shdr->sh_link)); - return (0); - } - - /* - * Determine if there is a associated Versym section - * with this Symbol Table. - */ - if (versym->cache && - (versym->cache->c_shdr->sh_link == state->secndx)) - state->versym = versym; - else - state->versym = NULL; - - - return (1); -} - -/* - * Determine the extended section index used for symbol tables entries. - */ -static void -symbols_getxindex(SYMTBL_STATE *state) -{ - uint_t symn; - Word symcnt; - - state->shxndx.checked = 1; /* Note that we've been called */ - for (symcnt = 1; symcnt < state->shnum; symcnt++) { - Cache *_cache = &state->cache[symcnt]; - Shdr *shdr = _cache->c_shdr; - - if ((shdr->sh_type != SHT_SYMTAB_SHNDX) || - (shdr->sh_link != state->secndx)) - continue; - - if ((shdr->sh_entsize) && - /* LINTED */ - ((symn = (uint_t)(shdr->sh_size / shdr->sh_entsize)) == 0)) - continue; - - if (_cache->c_data == NULL) - continue; - - state->shxndx.data = _cache->c_data->d_buf; - state->shxndx.n = symn; - return; - } -} - -/* - * Produce a line of output for the given symbol - * - * entry: - * state - Symbol table state - * symndx - Index of symbol within the table - * info - Value of st_info (indicates local/global range) - * symndx_disp - Index to display. This may not be the same - * as symndx if the display is relative to the logical - * combination of the SUNW_ldynsym/dynsym tables. - * sym - Symbol to display - */ -static void -output_symbol(SYMTBL_STATE *state, Word symndx, Word info, Word disp_symndx, - Sym *sym) -{ - /* - * Symbol types for which we check that the specified - * address/size land inside the target section. - */ - static const int addr_symtype[] = { - 0, /* STT_NOTYPE */ - 1, /* STT_OBJECT */ - 1, /* STT_FUNC */ - 0, /* STT_SECTION */ - 0, /* STT_FILE */ - 1, /* STT_COMMON */ - 0, /* STT_TLS */ - 0, /* 7 */ - 0, /* 8 */ - 0, /* 9 */ - 0, /* 10 */ - 0, /* 11 */ - 0, /* 12 */ - 0, /* STT_SPARC_REGISTER */ - 0, /* 14 */ - 0, /* 15 */ - }; -#if STT_NUM != (STT_TLS + 1) -#error "STT_NUM has grown. Update addr_symtype[]" -#endif - - char index[MAXNDXSIZE]; - const char *symname, *sec; - Versym verndx; - int gnuver; - uchar_t type; - Shdr *tshdr; - Word shndx; - Conv_inv_buf_t inv_buf; - - /* Ensure symbol index is in range */ - if (symndx >= state->symn) { - (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADSORTNDX), - state->file, state->secname, EC_WORD(symndx)); - return; - } - - /* - * If we are using extended symbol indexes, find the - * corresponding SHN_SYMTAB_SHNDX table. - */ - if ((sym->st_shndx == SHN_XINDEX) && (state->shxndx.checked == 0)) - symbols_getxindex(state); - - /* LINTED */ - symname = string(state->seccache, symndx, - &state->cache[state->seccache->c_shdr->sh_link], state->file, - sym->st_name); - - tshdr = NULL; - sec = NULL; - - if (state->ehdr->e_type == ET_CORE) { - sec = (char *)MSG_INTL(MSG_STR_UNKNOWN); - } else if (state->flags & FLG_CTL_FAKESHDR) { - /* - * If we are using fake section headers derived from - * the program headers, then the section indexes - * in the symbols do not correspond to these headers. - * The section names are not available, so all we can - * do is to display them in numeric form. - */ - sec = conv_sym_shndx(state->osabi, state->ehdr->e_machine, - sym->st_shndx, CONV_FMT_DECIMAL, &inv_buf); - } else if ((sym->st_shndx < SHN_LORESERVE) && - (sym->st_shndx < state->shnum)) { - shndx = sym->st_shndx; - tshdr = state->cache[shndx].c_shdr; - sec = state->cache[shndx].c_name; - } else if (sym->st_shndx == SHN_XINDEX) { - if (state->shxndx.data) { - Word _shxndx; - - if (symndx > state->shxndx.n) { - (void) fprintf(stderr, - MSG_INTL(MSG_ERR_BADSYMXINDEX1), - state->file, state->secname, - EC_WORD(symndx)); - } else if ((_shxndx = - state->shxndx.data[symndx]) > state->shnum) { - (void) fprintf(stderr, - MSG_INTL(MSG_ERR_BADSYMXINDEX2), - state->file, state->secname, - EC_WORD(symndx), EC_WORD(_shxndx)); - } else { - shndx = _shxndx; - tshdr = state->cache[shndx].c_shdr; - sec = state->cache[shndx].c_name; - } - } else { - (void) fprintf(stderr, - MSG_INTL(MSG_ERR_BADSYMXINDEX3), - state->file, state->secname, EC_WORD(symndx)); - } - } else if ((sym->st_shndx < SHN_LORESERVE) && - (sym->st_shndx >= state->shnum)) { - (void) fprintf(stderr, - MSG_INTL(MSG_ERR_BADSYM5), state->file, - state->secname, EC_WORD(symndx), - demangle(symname, state->flags), sym->st_shndx); - } - - /* - * If versioning is available display the - * version index. If not, then use 0. - */ - if (state->versym) { - Versym test_verndx; - - verndx = test_verndx = state->versym->data[symndx]; - gnuver = state->versym->gnu_full; - - /* - * Check to see if this is a defined symbol with a - * version index that is outside the valid range for - * the file. The interpretation of this depends on - * the style of versioning used by the object. - * - * Versions >= VER_NDX_LORESERVE have special meanings, - * and are exempt from this checking. - * - * GNU style version indexes use the top bit of the - * 16-bit index value (0x8000) as the "hidden bit". - * We must mask off this bit in order to compare - * the version against the maximum value. - */ - if (gnuver) - test_verndx &= ~0x8000; - - if ((test_verndx > state->versym->max_verndx) && - (verndx < VER_NDX_LORESERVE)) - (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADVER), - state->file, state->secname, EC_WORD(symndx), - EC_HALF(test_verndx), state->versym->max_verndx); - } else { - verndx = 0; - gnuver = 0; - } - - /* - * Error checking for TLS. - */ - type = ELF_ST_TYPE(sym->st_info); - if (type == STT_TLS) { - if (tshdr && - (sym->st_shndx != SHN_UNDEF) && - ((tshdr->sh_flags & SHF_TLS) == 0)) { - (void) fprintf(stderr, - MSG_INTL(MSG_ERR_BADSYM3), state->file, - state->secname, EC_WORD(symndx), - demangle(symname, state->flags)); - } - } else if ((type != STT_SECTION) && sym->st_size && - tshdr && (tshdr->sh_flags & SHF_TLS)) { - (void) fprintf(stderr, - MSG_INTL(MSG_ERR_BADSYM4), state->file, - state->secname, EC_WORD(symndx), - demangle(symname, state->flags)); - } - - /* - * If a symbol with non-zero size has a type that - * specifies an address, then make sure the location - * it references is actually contained within the - * section. UNDEF symbols don't count in this case, - * so we ignore them. - * - * The meaning of the st_value field in a symbol - * depends on the type of object. For a relocatable - * object, it is the offset within the section. - * For sharable objects, it is the offset relative to - * the base of the object, and for other types, it is - * the virtual address. To get an offset within the - * section for non-ET_REL files, we subtract the - * base address of the section. - */ - if (addr_symtype[type] && (sym->st_size > 0) && - (sym->st_shndx != SHN_UNDEF) && ((sym->st_shndx < SHN_LORESERVE) || - (sym->st_shndx == SHN_XINDEX)) && (tshdr != NULL)) { - Word v = sym->st_value; - if (state->ehdr->e_type != ET_REL) - v -= tshdr->sh_addr; - if (((v + sym->st_size) > tshdr->sh_size)) { - (void) fprintf(stderr, - MSG_INTL(MSG_ERR_BADSYM6), state->file, - state->secname, EC_WORD(symndx), - demangle(symname, state->flags), - EC_WORD(shndx), EC_XWORD(tshdr->sh_size), - EC_XWORD(sym->st_value), EC_XWORD(sym->st_size)); - } - } - - /* - * A typical symbol table uses the sh_info field to indicate one greater - * than the symbol table index of the last local symbol, STB_LOCAL. - * Therefore, symbol indexes less than sh_info should have local - * binding. Symbol indexes greater than, or equal to sh_info, should - * have global binding. Note, we exclude UNDEF/NOTY symbols with zero - * value and size, as these symbols may be the result of an mcs(1) - * section deletion. - */ - if (info) { - uchar_t bind = ELF_ST_BIND(sym->st_info); - - if ((symndx < info) && (bind != STB_LOCAL)) { - (void) fprintf(stderr, - MSG_INTL(MSG_ERR_BADSYM7), state->file, - state->secname, EC_WORD(symndx), - demangle(symname, state->flags), EC_XWORD(info)); - - } else if ((symndx >= info) && (bind == STB_LOCAL) && - ((sym->st_shndx != SHN_UNDEF) || - (ELF_ST_TYPE(sym->st_info) != STT_NOTYPE) || - (sym->st_size != 0) || (sym->st_value != 0))) { - (void) fprintf(stderr, - MSG_INTL(MSG_ERR_BADSYM8), state->file, - state->secname, EC_WORD(symndx), - demangle(symname, state->flags), EC_XWORD(info)); - } - } - - (void) snprintf(index, MAXNDXSIZE, - MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(disp_symndx)); - Elf_syms_table_entry(0, ELF_DBG_ELFDUMP, index, state->osabi, - state->ehdr->e_machine, sym, verndx, gnuver, sec, symname); -} - -/* * Search for and process any symbol tables. */ void @@ -2039,7 +2380,7 @@ } Elf_syms_table_title(0, ELF_DBG_ELFDUMP); - /* If not first one, insert a line of whitespace */ + /* If not first one, insert a line of white space */ if (output_cnt++ > 0) dbg_print(0, MSG_ORIG(MSG_STR_EMPTY)); @@ -2315,7 +2656,6 @@ } } - /* * There are some DT_ entries that have corresponding symbols * (e.g. DT_INIT and _init). It is expected that these items will @@ -2368,7 +2708,6 @@ } } - /* * Search for and process a .dynamic section. */ @@ -2388,6 +2727,8 @@ Cache *rel; Cache *rela; Cache *sunw_cap; + Cache *sunw_capinfo; + Cache *sunw_capchain; Cache *sunw_ldynsym; Cache *sunw_move; Cache *sunw_syminfo; @@ -2484,6 +2825,8 @@ GRAB(SHT_SUNW_move, sunw_move); GRAB(SHT_PREINIT_ARRAY, preinit_array); GRAB(SHT_SUNW_cap, sunw_cap); + GRAB(SHT_SUNW_capinfo, sunw_capinfo); + GRAB(SHT_SUNW_capchain, sunw_capchain); GRAB(SHT_SUNW_LDYNSYM, sunw_ldynsym); GRAB(SHT_SUNW_syminfo, sunw_syminfo); GRAB(SHT_SUNW_symsort, sunw_symsort); @@ -2674,7 +3017,7 @@ /* * Cases below this point are strictly sanity checking, * and do not generate a name string. The TEST_ macros - * are used to hide the boilerplate arguments neeeded + * are used to hide the boiler plate arguments neeeded * by dyn_test(). */ #define TEST_ADDR(_sh_type, _sec_field) \ @@ -2774,6 +3117,14 @@ TEST_ADDR(SHT_SUNW_cap, sunw_cap); break; + case DT_SUNW_CAPINFO: + TEST_ADDR(SHT_SUNW_capinfo, sunw_capinfo); + break; + + case DT_SUNW_CAPCHAIN: + TEST_ADDR(SHT_SUNW_capchain, sunw_capchain); + break; + case DT_SUNW_SYMTAB: TEST_ADDR(SHT_SUNW_LDYNSYM, sunw_ldynsym); break; @@ -4657,7 +5008,7 @@ checksum(elf); if ((flags & FLG_SHOW_CAP) && (osabi == ELFOSABI_SOLARIS)) - cap(file, cache, shnum, phnum, ehdr, elf); + cap(file, cache, shnum, phnum, ehdr, osabi, elf, flags); if ((flags & FLG_SHOW_UNWIND) && ((osabi == ELFOSABI_SOLARIS) || (osabi == ELFOSABI_LINUX)))
--- a/usr/src/cmd/sgs/elfdump/common/elfdump.msg Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/elfdump/common/elfdump.msg Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -42,8 +42,7 @@ @ MSG_USAGE_DETAIL5 "\t[-g]\t\tdump the contents of the .group sections\n" @ MSG_USAGE_DETAIL6 "\t[-G]\t\tdump the contents of the .got section\n" @ MSG_USAGE_DETAIL7 "\t[-h]\t\tdump the contents of the .hash section\n" -@ MSG_USAGE_DETAIL8 "\t[-H]\t\tdump the contents of the .SUNW_hwcap \ - section\n" +@ MSG_USAGE_DETAIL8 "\t[-H]\t\tdump the contents of the .SUNW_cap section\n" @ MSG_USAGE_DETAIL9 "\t[-i]\t\tdump the contents of the .interp section\n" @ MSG_USAGE_DETAIL10 "\t[-I index]\tqualify an option with an index\n" @ MSG_USAGE_DETAIL11 "\t[-l]\t\tdump with no truncated section names\n" @@ -75,7 +74,8 @@ # Errors @ MSG_ERR_BADFILE "%s: invalid file type\n" -@ MSG_ERR_BADREL1 "%s: bad relocation entry: %s: relocation requires symbol\n" +@ MSG_ERR_BADREL1 "%s: bad relocation entry: %s: relocation requires \ + symbol\n" @ MSG_ERR_NOSHDR "%s: section headers are not present: synthesizing \ from program headers (-P option)\n" @ MSG_ERR_PNEEDSPH "%s: file without program headers is incompatible \ @@ -92,21 +92,21 @@ @ MSG_ERR_BADSHINFO "%s: %s: invalid sh_info: %d\n" @ MSG_ERR_BADSHTYPE "%s: %s: invalid sh_type: %d\n" @ MSG_ERR_BADALIGN "%s: %s: bad sh_offset alignment\n" -@ MSG_ERR_BADSYM2 "%s: %s: index[%d]: bad symbol entry: %s: must be SHN_COMMON or \ - defined in SHT_NOBITS section\n" -@ MSG_ERR_BADSYM3 "%s: %s: index[%d]: bad symbol entry: %s: must be defined in \ - a SHF_TLS section\n" -@ MSG_ERR_BADSYM4 "%s: %s: index[%d]: bad symbol entry: %s: must be defined in \ - a non-SHF_TLS section\n" +@ MSG_ERR_BADSYM2 "%s: %s: index[%d]: bad symbol entry: %s: must be \ + SHN_COMMON or defined in SHT_NOBITS section\n" +@ MSG_ERR_BADSYM3 "%s: %s: index[%d]: bad symbol entry: %s: must be \ + defined in a SHF_TLS section\n" +@ MSG_ERR_BADSYM4 "%s: %s: index[%d]: bad symbol entry: %s: must be \ + defined in a non-SHF_TLS section\n" @ MSG_ERR_BADSYM5 "%s: %s: index[%d]: bad symbol entry: %s: \ invalid shndx: %d\n" @ MSG_ERR_BADSYM6 "%s: %s: index[%d]: bad symbol entry: %s: section[%d] \ size: %#llx: symbol (address %#llx, size %#llx) \ lies outside of containing section\n" -@ MSG_ERR_BADSYM7 "%s: %s: index[%d]: suspicious global symbol entry: %s: lies \ - within local symbol range (index < %lld)\n" -@ MSG_ERR_BADSYM8 "%s: %s: index[%d]: suspicious local symbol entry: %s: lies \ - within global symbol range (index >= %lld)\n" +@ MSG_ERR_BADSYM7 "%s: %s: index[%d]: suspicious global symbol entry: \ + %s: lies within local symbol range (index < %lld)\n" +@ MSG_ERR_BADSYM8 "%s: %s: index[%d]: suspicious local symbol entry: \ + %s: lies within global symbol range (index >= %lld)\n" @ MSG_ERR_RELBADSYMNDX "%s: bad symbol reference %d: from relocation \ entry: %d\n" @@ -127,7 +127,7 @@ @ MSG_ERR_NODYNSYM "%s: %s: associated SHT_DYNSYM section not found\n" @ MSG_ERR_BADNDXSEC "%s: %s: unexpected section type associated with \ index section: %s\n" -@ MSG_ERR_BADSORTNDX "%s: %s: sort section has bad symbol index: %d\n" +@ MSG_ERR_BADSYMNDX "%s: %s: bad symbol index: %d\n" @ MSG_ERR_BADVER "%s: %s: index[%d]: version %d is out of range: \ version definitions available: 0-%d\n" @ MSG_ERR_NOTSTRTAB "%s: section[%d] is not a string table as expected \ @@ -150,9 +150,10 @@ shdr[%d: %s].sh_entsize (%#llx)\n" @ MSG_ERR_DYNSYMVAL "%s: %s: symbol value does not match \ DT_%s entry: %s: value: %#llx\n" -@ MSG_ERR_MALSTR "%s: %s: malformed string table, initial or final byte\n" +@ MSG_ERR_MALSTR "%s: %s: malformed string table, initial or final \ + byte\n" @ MSG_ERR_MULTEHFRMHDR "%s: [%d: %s] multiple .eh_frame_hdr sections seen \ - (1 expected)\n" + (1 expected)\n" @ MSG_ERR_BADEHFRMPTR "%s: section[%d: %s] FramePtr (%#llx) does not match \ shdr[%d: %s].sh_addr (%#llx)\n" @ MSG_ERR_BADSORT "%s: %s: index[%d]: invalid sort order\n" @@ -162,10 +163,12 @@ @ MSG_WARN_INVINTERP2 "%s: interp section: %s: and PT_INTERP program \ header have conflicting size or offsets\n" @ MSG_WARN_INVCAP1 "%s: PT_SUNWCAP header has no associated section\n" -@ MSG_WARN_INVCAP2 "%s: capabilities section: %s: requires PT_CAP program \ - header\n" -@ MSG_WARN_INVCAP3 "%s: capabilities section: %s: and PT_CAP program \ +@ MSG_WARN_INVCAP2 "%s: capabilities section[%d]: %s: requires PT_CAP \ + program header\n" +@ MSG_WARN_INVCAP3 "%s: capabilities section[%d]: %s: and PT_CAP program \ header have conflicting size or offsets\n" +@ MSG_WARN_INVCAP4 "%s: capabilities section[%d]: %s: requires string \ + table: invalid sh_info: %d\n"; @ MSG_WARN_INADDR32SF1 "%s: capabilities section %s: software capability \ ADDR32: is ineffective within a 32-bit object\n" @ MSG_WARN_MULTEHFRM "%s: section[%d: %s]: %s object has multiple \ @@ -193,7 +196,8 @@ @ MSG_ELF_SHDR "Section Header[%d]: sh_name: %s" @ MSG_ELF_PHDR "Program Header[%d]:" -@ MSG_ELF_SCN_CAP "Hardware/Software Capabilities Section: %s" +@ MSG_ELF_SCN_CAP "Capabilities Section: %s" +@ MSG_ELF_SCN_CAPCHAIN "Capabilities Chain Section: %s" @ MSG_ELF_SCN_INTERP "Interpreter Section: %s" @ MSG_ELF_SCN_VERDEF "Version Definition Section: %s" @ MSG_ELF_SCN_VERNEED "Version Needed Section: %s" @@ -210,6 +214,23 @@ @ MSG_ELF_SCN_SYMSORT1 "Symbol Sort Section: %s (%s)" @ MSG_ELF_SCN_SYMSORT2 "Symbol Sort Section: %s (%s / %s)" +@ MSG_OBJ_CAP_TITLE " Object Capabilities:" +@ MSG_SYM_CAP_TITLE " Symbol Capabilities:" +@ MSG_CAPINFO_ENTRIES " Symbols:" +@ MSG_CAPCHAIN_TITLE " Capabilities family: %s" +@ MSG_CAPCHAIN_ENTRY " chainndx symndx name" +@ MSG_ERR_INVCAP "%s: capabilities section: %s: contains symbol \ + capabilities groups, but no capabilities information \ + section is defined: invalid sh_link: %d\n" +@ MSG_ERR_INVCAPINFO1 "%s: capabilities information section: %s: no symbol \ + table is defined: invalid sh_link: %d\n" +@ MSG_ERR_INVCAPINFO2 "%s: capabilities information section: %s: no \ + capabilities chain is defined: invalid sh_info: %d\n" +@ MSG_ERR_INVCAPINFO3 "%s: capabilities information section: %s: index %d: \ + bad capabilities chain index defined: %d\n" +@ MSG_ERR_CHBADSYMNDX "%s: bad symbol reference %d: from capability chain: \ + %s entry: %d\n" + @ MSG_ELF_HASH_BKTS1 "%10.10s buckets contain %8d symbols" @ MSG_ELF_HASH_BKTS2 "%10.10s buckets %8d symbols (globals)" @ MSG_ELF_HASH_INFO " bucket symndx name" @@ -274,7 +295,7 @@ offset: 0x%x datasize: 0x%x\n" @ MSG_NOTE_BADCOREARCH "%s: elfdump core file note support not available for \ architecture: %s\n" -@ MSG_NOTE_BADCOREDATA "%s: elfdump core file note data trunctated or \ +@ MSG_NOTE_BADCOREDATA "%s: elfdump core file note data truncated or \ otherwise malformed\n" @ _END_ @@ -331,6 +352,7 @@ @ MSG_FMT_INDEXRNG "[%d-%d]" @ MSG_FMT_INTEGER " %d" @ MSG_FMT_HASH_INFO "%10.10s %-10s %s" +@ MSG_FMT_CHAIN_INFO "%10.10s %-10s %s" @ MSG_FMT_ARSYM1 "%10.10s 0x%8.8x (%s):%s" @ MSG_FMT_ARSYM2 "%10.10s 0x%8.8x" @ MSG_FMT_ARNAME "%s(%s)" @@ -384,7 +406,7 @@ @ MSG_UNW_FDECFI " CallFrameInstructions:" # Unwind section Call Frame Instructions. These all start with a leading -# "%*s%s", used to insert leading whitespace and the opcode name. +# "%*s%s", used to insert leading white space and the opcode name. @ MSG_CFA_ADV_LOC "%*s%s: %s + %llu => %#llx" @ MSG_CFA_CFAOFF "%*s%s: %s, cfa%+lld" @@ -590,6 +612,8 @@ # Names of fake sections generated from program header data @ MSG_PHDRNAM_CAP ".SUNW_cap(phdr)" +@ MSG_PHDRNAM_CAPINFO ".SUNW_capinfo(phdr)" +@ MSG_PHDRNAM_CAPCHAIN ".SUNW_capchain(phdr)" @ MSG_PHDRNAM_DYN ".dynamic(phdr)" @ MSG_PHDRNAM_DYNSTR ".dynstr(phdr)" @ MSG_PHDRNAM_DYNSYM ".dynsym(phdr)"
--- a/usr/src/cmd/sgs/elfdump/common/fake_shdr.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/elfdump/common/fake_shdr.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -120,16 +120,18 @@ SINFO_T_VERSYM = 11, SINFO_T_INTERP = 12, SINFO_T_CAP = 13, - SINFO_T_UNWIND = 14, - SINFO_T_MOVE = 15, - SINFO_T_REL = 16, - SINFO_T_RELA = 17, - SINFO_T_PREINITARR = 18, - SINFO_T_INITARR = 19, - SINFO_T_FINIARR = 20, - SINFO_T_NOTE = 21, + SINFO_T_CAPINFO = 14, + SINFO_T_CAPCHAIN = 15, + SINFO_T_UNWIND = 16, + SINFO_T_MOVE = 17, + SINFO_T_REL = 18, + SINFO_T_RELA = 19, + SINFO_T_PREINITARR = 20, + SINFO_T_INITARR = 21, + SINFO_T_FINIARR = 22, + SINFO_T_NOTE = 23, - SINFO_T_NUM = 22 /* Count of items. Must come last */ + SINFO_T_NUM = 24 /* Count of items. Must come last */ } SINFO_TYPE; @@ -225,13 +227,21 @@ { MSG_ORIG(MSG_PHDRNAM_CAP), SHT_SUNW_cap, SHF_ALLOC, sizeof (Addr), sizeof (Cap), ELF_T_CAP }, + /* SINFO_T_CAPINFO */ + { MSG_ORIG(MSG_PHDRNAM_CAPINFO), SHT_SUNW_capinfo, SHF_ALLOC, + FAKE_M_WORD_ALIGN, sizeof (Capinfo), ELF_T_WORD }, + + /* SINFO_T_CAPCHAIN */ + { MSG_ORIG(MSG_PHDRNAM_CAPCHAIN), SHT_SUNW_capchain, SHF_ALLOC, + FAKE_M_WORD_ALIGN, sizeof (Capchain), ELF_T_WORD }, + /* SINFO_T_UNWIND */ { MSG_ORIG(MSG_PHDRNAM_UNWIND), SHT_AMD64_UNWIND, SHF_ALLOC, sizeof (Addr), 0, ELF_T_BYTE }, /* SINFO_T_MOVE */ { MSG_ORIG(MSG_PHDRNAM_MOVE), SHT_SUNW_move, SHF_ALLOC, - sizeof (Lword), sizeof (Move), ELF_T_MOVE }, + sizeof (Lword), sizeof (Move), ELF_T_MOVE }, /* SINFO_T_REL */ { MSG_ORIG(MSG_PHDRNAM_REL), SHT_REL, SHF_ALLOC, @@ -1091,6 +1101,8 @@ SINFO versym; SINFO interp; SINFO cap; + SINFO capinfo; + SINFO capchain; SINFO unwind; SINFO move; SINFO rel; @@ -1267,6 +1279,16 @@ sec.preinitarr.size = dyn->d_un.d_val; break; + case DT_SUNW_CAPINFO: + sec.capinfo.type = SINFO_T_CAPINFO; + sec.capinfo.vaddr = dyn->d_un.d_ptr; + break; + + case DT_SUNW_CAPCHAIN: + sec.capchain.type = SINFO_T_CAPCHAIN; + sec.capchain.vaddr = dyn->d_un.d_ptr; + break; + case DT_SUNW_SYMTAB: sec.ldynsym.type = SINFO_T_LDYNSYM; sec.ldynsym.vaddr = dyn->d_un.d_ptr;
--- a/usr/src/cmd/sgs/elfedit/Makefile.com Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/elfedit/Makefile.com Mon Mar 01 10:20:48 2010 -0800 @@ -46,7 +46,7 @@ $(CPPFLAGS.master) -I$(ELFCAP) LLDFLAGS = $(VAR_ELFEDIT_LLDFLAGS) LLDFLAGS64 = $(VAR_ELFEDIT_LLDFLAGS64) -LDFLAGS += $(VERSREF) $(USE_PROTO) -M$(MAPFILE) $(LLDFLAGS) +LDFLAGS += $(VERSREF) $(CC_USE_PROTO) -M$(MAPFILE) $(LLDFLAGS) LDLIBS += $(ELFLIBDIR) -lelf $(LDDBGLIBDIR) $(LDDBG_LIB) \ $(CONVLIBDIR) $(CONV_LIB) -ltecla
--- a/usr/src/cmd/sgs/elfedit/common/elfconst.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/elfedit/common/elfconst.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -408,8 +408,9 @@ LC(ELFEDIT_CONST_SYMINFO_BT, conv_iter_syminfo_boundto); LC(ELFEDIT_CONST_SYMINFO_FLG, conv_iter_syminfo_flags); LC(ELFEDIT_CONST_CA, conv_iter_cap_tags); - LC_MACH(ELFEDIT_CONST_AV, conv_iter_cap_val_hw1); + LC_MACH(ELFEDIT_CONST_HW1_SUNW, conv_iter_cap_val_hw1); LC(ELFEDIT_CONST_SF1_SUNW, conv_iter_cap_val_sf1); + LC_MACH(ELFEDIT_CONST_HW2_SUNW, conv_iter_cap_val_hw2); #undef LC #undef LC_OS
--- a/usr/src/cmd/sgs/elfedit/common/elfedit.msg Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/elfedit/common/elfedit.msg Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -86,7 +86,8 @@ @ MSG_DEBUG_UNLINKFILE "unlink unsaved output file: %s\n"; @ MSG_DEBUG_VERSION "%d-bit version\n" @ MSG_DEBUG_READONLY "session is readonly\n"; -@ MSG_DEBUG_NOFILE "no ELF object specified. Limited functionalty is available\n"; +@ MSG_DEBUG_NOFILE "no ELF object specified. Limited functionality is \ + available\n"; @ MSG_DEBUG_DIRTYEXIT "discarding unsaved edits\n"; @ MSG_DEBUG_FNDSEC "[%d: %s]: section\n" @ MSG_DEBUG_FNDCAP "[%d: %s]: capabilities section\n" @@ -244,7 +245,7 @@ @ MSG_HLPFMT_INFILERO "Input File: %s (readonly)\n" @ MSG_HLPFMT_INFILENONE "Input File: <not present>\n" @ MSG_HLPFMT_OUTFILE "Output File: %s\n" -@ MSG_HLPFMT_CNGPENDING " (changes pending)\n" +@ MSG_HLPFMT_CNGPENDING " (changes pending)\n" @ MSG_HLPFMT_VARHDR "\nOptions:\n" @ MSG_HLPFMT_AFLG " a (Autoprint): %s\n" @ MSG_HLPFMT_DFLG " d (Debug): %s\n" @@ -424,9 +425,6 @@ about the available modules and commands and how they can be used\n\ to edit ELF files.\n" - - - @ MSG_SYS_HELP_HELP " \ The sys:help command provides information on elfedit modules\n\ and commands:\n\ @@ -478,7 +476,7 @@ @ MSG_SYS_HELP_SET "\ Set options that control how elfedit works.\n\ \n\ - Most variables accept boolen (true/false) values. The sys:set\n\ + Most variables accept boolean (true/false) values. The sys:set\n\ command accepts any of the following as a boolean value:\n\ 0/1, true/false, t/f, yes/no, y/n, on/off.\n\ \n\
--- a/usr/src/cmd/sgs/elfedit/modules/Makefile.com Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/elfedit/modules/Makefile.com Mon Mar 01 10:20:48 2010 -0800 @@ -18,12 +18,11 @@ # # CDDL HEADER END # + # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# include ../../../../../lib/Makefile.lib include ../../../Makefile.com @@ -94,7 +93,7 @@ -I../$(SRCBASE)/lib/libc/inc -D_REENTRANT LLDFLAGS = '-R$$ORIGIN/../../../lib' LLDFLAGS64 = '-R$$ORIGIN/../../../../lib/$(MACH64)' -LDFLAGS += $(USE_PROTO) $(LLDFLAGS) +LDFLAGS += $(CC_USE_PROTO) $(LLDFLAGS) DYNFLAGS += $(VERSREF) LINTFLAGS += -uaxs $(LDLIBS)
--- a/usr/src/cmd/sgs/elfedit/modules/common/cap.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/elfedit/modules/common/cap.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -58,6 +58,7 @@ /* Commands that embody tag specific knowledge */ CAP_CMD_T_HW1 = 5, /* cap:hw1 */ CAP_CMD_T_SF1 = 6, /* cap:sf1 */ + CAP_CMD_T_HW2 = 7, /* cap:hw2 */ } CAP_CMD_T; @@ -102,9 +103,12 @@ typedef enum { CAP_OPT_F_AND = 1, /* -and: AND (&) values to dest */ CAP_OPT_F_CMP = 2, /* -cmp: Complement (~) values */ - CAP_OPT_F_CAPNDX = 4, /* -capndx: elt is tag index, */ + CAP_OPT_F_CAPID = 4, /* -capid id: elt limited to given */ + /* capabilities group */ + CAP_OPT_F_CAPNDX = 8, /* -capndx: elt is tag index, */ /* not name */ - CAP_OPT_F_OR = 8, /* -or: OR (|) values to dest */ + CAP_OPT_F_OR = 16, /* -or: OR (|) values to dest */ + CAP_OPT_F_STRVAL = 32 /* -s: value is string, not integer */ } cap_opt_t; @@ -119,7 +123,13 @@ elfedit_section_t *sec; /* Capabilities section reference */ Cap *data; /* Start of capabilities section data */ Word num; /* # Capabilities elts */ + Boolean grp_set; /* TRUE when cap group is set */ + Word grp_start_ndx; /* capabilities group starting index */ + Word grp_end_ndx; /* capabilities group ending index */ } cap; + struct { /* String table */ + elfedit_section_t *sec; + } str; cap_opt_t optmask; /* Mask of options used */ int argc; /* # of plain arguments */ const char **argv; /* Plain arguments */ @@ -128,6 +138,149 @@ /* + * Lookup the string table associated with the capabilities + * section. + * + * entry: + * argstate - Argument state block + * required - If TRUE, failure to obtain a string table should be + * considered to be an error. + * + * exit: + * If a string table is found, argstate->str is updated to reference it. + * If no string table is found, and required is TRUE, an error is issued + * and this routine does not return to the caller. Otherwise, this + * routine returns quietly without modifying argstate->str. + */ +static void +argstate_add_str(ARGSTATE *argstate, Boolean required) +{ + /* String table already loaded? */ + if (argstate->str.sec != NULL) + return; + + /* + * We can't proceed if the capabilities section does not have + * an associated string table. + */ + if (argstate->cap.sec->sec_shdr->sh_info == 0) { + /* Error if the operation requires a string table */ + if (required) + elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSTRTAB), + EC_WORD(argstate->cap.sec->sec_shndx), + argstate->cap.sec->sec_name); + return; + } + + argstate->str.sec = elfedit_sec_getstr(argstate->obj_state, + argstate->cap.sec->sec_shdr->sh_info, 0); +} + +/* + * Given an index into the capabilities array, locate the index of the + * initial element in its capabilities group, and the number of elements + * in the group. + */ +static void +cap_group_extents(ARGSTATE *argstate, Word ndx, Word *ret_start_ndx, + Word *ret_end_ndx) +{ + *ret_end_ndx = ndx; + + /* + * The group starts with a non-NULL tag that is either the + * first tag in the array, or is preceded by a NULL tag. + */ + while ((ndx > 0) && (argstate->cap.data[ndx].c_tag == CA_SUNW_NULL)) + ndx--; + while ((ndx > 0) && (argstate->cap.data[ndx - 1].c_tag != CA_SUNW_NULL)) + ndx--; + *ret_start_ndx = ndx; + + + /* + * The group is terminated by a series of 1 or more NULL tags. + */ + ndx = *ret_end_ndx; + while (((ndx + 1) < argstate->cap.num) && + (argstate->cap.data[ndx].c_tag != CA_SUNW_NULL)) + ndx++; + while (((ndx + 1) < argstate->cap.num) && + (argstate->cap.data[ndx + 1].c_tag == CA_SUNW_NULL)) + ndx++; + *ret_end_ndx = ndx; +} + +/* + * If a CA_SUNW_ID element exists within the current capabilities group + * in the given argument state, return the string pointer to the name. + * Otherwise return a pointer to a descriptive "noname" string. + */ +static const char * +cap_group_id(ARGSTATE *argstate) +{ + Word ndx = argstate->cap.grp_start_ndx; + Cap *cap = argstate->cap.data + ndx; + + for (; ndx <= argstate->cap.grp_end_ndx; ndx++, cap++) { + if (cap->c_tag == CA_SUNW_ID) { + argstate_add_str(argstate, TRUE); + return (elfedit_offset_to_str(argstate->str.sec, + cap->c_un.c_val, ELFEDIT_MSG_ERR, 0)); + break; + } + + if (cap->c_tag == CA_SUNW_NULL) + break; + } + + return ((argstate->cap.grp_start_ndx == 0) ? + MSG_INTL(MSG_STR_OBJECT) : MSG_INTL(MSG_STR_NONAME)); +} + + +/* + * Given an index into the capabilities array, set the argstate cap.grp_* + * fields to reflect the capabilities group containing the index. + * + * The group concept is used to limit operations to a related group + * of capabilities, and prevent insert/delete/move operations from + * spilling across groups. + */ +static void +argstate_cap_group(ARGSTATE *argstate, Word ndx) +{ + if (argstate->cap.grp_set == TRUE) + return; + + cap_group_extents(argstate, ndx, &argstate->cap.grp_start_ndx, + &argstate->cap.grp_end_ndx); + + argstate->cap.grp_set = TRUE; + elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CAPGRP), + EC_WORD(argstate->cap.sec->sec_shndx), argstate->cap.sec->sec_name, + EC_WORD(argstate->cap.grp_start_ndx), + EC_WORD(argstate->cap.grp_end_ndx), cap_group_id(argstate)); +} + +/* + * Given an index into the capabilities array, issue a group title for + * the capabilities group that contains it. + */ +static void +group_title(ARGSTATE *argstate, Word ndx) +{ + ARGSTATE loc_argstate; + + loc_argstate = *argstate; + cap_group_extents(argstate, ndx, &loc_argstate.cap.grp_start_ndx, + &loc_argstate.cap.grp_end_ndx); + elfedit_printf(MSG_INTL(MSG_FMT_CAPGRP), + EC_WORD(loc_argstate.cap.grp_start_ndx), + EC_WORD(loc_argstate.cap.grp_end_ndx), cap_group_id(&loc_argstate)); +} + +/* * Standard argument processing for cap module * * entry @@ -144,6 +297,7 @@ { elfedit_getopt_state_t getopt_state; elfedit_getopt_ret_t *getopt_ret; + const char *capid = NULL; bzero(argstate, sizeof (*argstate)); argstate->obj_state = obj_state; @@ -151,9 +305,13 @@ elfedit_getopt_init(&getopt_state, &argc, &argv); /* Add each new option to the options mask */ - while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) + while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) { argstate->optmask |= getopt_ret->gor_idmask; + if (getopt_ret->gor_idmask == CAP_OPT_F_CAPID) + capid = getopt_ret->gor_value; + } + /* If there may be an arbitrary amount of output, use a pager */ if (argc == 0) elfedit_pager_init(); @@ -165,6 +323,38 @@ /* Locate the capabilities section */ argstate->cap.sec = elfedit_sec_getcap(obj_state, &argstate->cap.data, &argstate->cap.num); + + /* + * If -capid was specified, locate the specified capabilities group, + * and narrow the section data to use only that group. Otherwise, + * use the whole array. + */ + if (capid != NULL) { + Word i; + Cap *cap = argstate->cap.data; + + /* + * -capid requires the capability section to have an + * associated string table. + */ + argstate_add_str(argstate, TRUE); + + for (i = 0; i < argstate->cap.num; i++, cap++) + if ((cap->c_tag == CA_SUNW_ID) && + (strcmp(capid, elfedit_offset_to_str( + argstate->str.sec, cap->c_un.c_val, + ELFEDIT_MSG_ERR, 0)) == 0)) + break; + + if (i == argstate->cap.num) + elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_BADCAPID), + EC_WORD(argstate->cap.sec->sec_shndx), + argstate->cap.sec->sec_name, capid); + argstate_cap_group(argstate, i); + } else { + argstate->cap.grp_start_ndx = 0; + argstate->cap.grp_end_ndx = argstate->cap.num - 1; + } } @@ -196,8 +386,7 @@ elfedit_outstyle_t outstyle; Word cnt, ndx, printed = 0; Cap *cap; - int header_done = 0; - Xword last_c_val = 0; + Boolean header_done = FALSE, null_seen = FALSE; if (autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0)) return; @@ -216,69 +405,134 @@ ndx = arg; cnt = 1; } else { - ndx = 0; - cnt = argstate->cap.num; + ndx = argstate->cap.grp_start_ndx; + cnt = argstate->cap.grp_end_ndx - ndx + 1; } + /* Load string table if there is one */ + argstate_add_str(argstate, FALSE); + cap = &argstate->cap.data[ndx]; for (; cnt--; cap++, ndx++) { /* * If we are only displaying certain tag types and * this isn't one of those, move on to next element. */ - if ((print_type == PRINT_CAP_T_TAG) && (cap->c_tag != arg)) + if ((print_type == PRINT_CAP_T_TAG) && (cap->c_tag != arg)) { + if (cap->c_tag == CA_SUNW_NULL) + null_seen = TRUE; continue; + } + + /* + * If capability type requires a string table, and we don't + * have one, force an error. + */ + switch (cap->c_tag) { + case CA_SUNW_PLAT: + case CA_SUNW_MACH: + case CA_SUNW_ID: + if (argstate->str.sec == NULL) + argstate_add_str(argstate, TRUE); + break; + } if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) { - if (header_done == 0) { - header_done = 1; + if (null_seen && (cap->c_tag != CA_SUNW_NULL)) { + null_seen = FALSE; + if (header_done) { + elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), + MSG_ORIG(MSG_STR_EMPTY)); + header_done = FALSE; + } + } + + if (header_done == FALSE) { + header_done = TRUE; + group_title(argstate, ndx); Elf_cap_title(0); } Elf_cap_entry(NULL, cap, ndx, + (const char *)argstate->str.sec->sec_data->d_buf, + argstate->str.sec->sec_data->d_size, argstate->obj_state->os_ehdr->e_machine); } else { /* - * In simple or numeric mode under a print type - * that is based on tag type rather than on index, - * quietly: If we've already printed this value, - * don't print it again. A common example of this - * is PRINT_CAP_T_RUNPATH when both CA_RPATH and - * CA_RUNPATH are present with the same value. + * If CAP_CMD_T_TAG, and not in default output + * style, display the tag rather than the value. */ - if ((print_type == PRINT_CAP_T_TAG) && printed && - (last_c_val == cap->c_un.c_val)) + if (cmd == CAP_CMD_T_TAG) { + if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { + Conv_inv_buf_t inv_buf; + + elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), + conv_cap_tag(cap->c_tag, 0, + &inv_buf)); + } else { + elfedit_printf( + MSG_ORIG(MSG_FMT_WORDVALNL), + EC_WORD(cap->c_tag)); + } + printed = 1; continue; + } + /* Displaying the value in simple or numeric mode */ if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { - union { - Conv_cap_val_hw1_buf_t hw1; - Conv_cap_val_sf1_buf_t sf1; - } c_buf; + Conv_cap_val_buf_t cap_val_buf; + + if (print_type == PRINT_CAP_T_TAG) { + elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), + conv_cap_val_hw1(cap->c_un.c_val, + argstate->obj_state->os_ehdr-> + e_machine, CONV_FMT_NOBKT, + &cap_val_buf.cap_val_hw1_buf)); + printed = 1; + continue; + } switch (cap->c_tag) { case CA_SUNW_HW_1: elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), conv_cap_val_hw1(cap->c_un.c_val, argstate->obj_state->os_ehdr-> - e_machine, - CONV_FMT_NOBKT, &c_buf.hw1)); + e_machine, CONV_FMT_NOBKT, + &cap_val_buf.cap_val_hw1_buf)); printed = 1; continue; case CA_SUNW_SF_1: elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), conv_cap_val_sf1(cap->c_un.c_val, argstate->obj_state->os_ehdr-> - e_machine, - CONV_FMT_NOBKT, &c_buf.sf1)); + e_machine, CONV_FMT_NOBKT, + &cap_val_buf.cap_val_sf1_buf)); + printed = 1; + continue; + case CA_SUNW_HW_2: + elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), + conv_cap_val_hw2(cap->c_un.c_val, + argstate->obj_state->os_ehdr-> + e_machine, CONV_FMT_NOBKT, + &cap_val_buf.cap_val_hw2_buf)); + printed = 1; + continue; + case CA_SUNW_PLAT: + case CA_SUNW_MACH: + case CA_SUNW_ID: + elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), + elfedit_offset_to_str( + argstate->str.sec, cap->c_un.c_val, + ELFEDIT_MSG_ERR, 0)); printed = 1; continue; } } elfedit_printf(MSG_ORIG(MSG_FMT_HEXXWORDNL), - cap->c_un.c_val); + EC_XWORD(cap->c_un.c_val)); } printed = 1; - last_c_val = cap->c_un.c_val; + if (cap->c_tag == CA_SUNW_NULL) + null_seen = TRUE; } /* @@ -286,11 +540,12 @@ * based on tag type, issue an error saying it doesn't exist. */ if (!printed && (print_type == PRINT_CAP_T_TAG)) { - Conv_inv_buf_t inv_buf; + Conv_inv_buf_t inv_buf; elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOCAELT), EC_WORD(argstate->cap.sec->sec_shndx), - argstate->cap.sec->sec_name, + argstate->cap.sec->sec_name, argstate->cap.grp_start_ndx, + argstate->cap.grp_end_ndx, cap_group_id(argstate), conv_cap_tag(arg, 0, &inv_buf)); } } @@ -327,16 +582,23 @@ arg_to_index(ARGSTATE *argstate, const char *arg, const char *argname, int print_request, PRINT_CAP_T *print_type) { - Word ndx, ca_value; + Word ndx, ca_value; /* Assume we are returning an index, alter as needed below */ *print_type = PRINT_CAP_T_NDX; - /* If -capndx was used, this is a simple numeric index */ - if ((argstate->optmask & CAP_OPT_F_CAPNDX) != 0) - return ((Word) elfedit_atoui_range(arg, argname, 0, - argstate->cap.num - 1, NULL)); + /* + * If -capndx was used, this is a simple numeric index. + * Determine its capability group because some operations + * (move, delete) are limited to operate within it. + */ + if ((argstate->optmask & CAP_OPT_F_CAPNDX) != 0) { + ndx = (Word) elfedit_atoui_range(arg, argname, 0, + argstate->cap.num - 1, NULL); + argstate_cap_group(argstate, ndx); + return (ndx); + } /* The argument is a CA_ tag type, not a numeric index */ ca_value = (Word) elfedit_atoconst(arg, ELFEDIT_CONST_CA); @@ -350,8 +612,20 @@ return (ca_value); } - /* Locate the first entry with the given tag type */ - for (ndx = 0; ndx < argstate->cap.num; ndx++) { + /* + * If we haven't determined a capability group yet, either via + * -capid, or -capndx, then make it the initial group, which + * represent the object capabilities. + */ + if (!argstate->cap.grp_set) + argstate_cap_group(argstate, 0); + + /* + * Locate the first entry with the given tag type within the + * capabilities group. + */ + for (ndx = argstate->cap.grp_start_ndx; + ndx <= argstate->cap.grp_end_ndx; ndx++) { if (argstate->cap.data[ndx].c_tag == ca_value) { elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CA2NDX), @@ -359,12 +633,36 @@ argstate->cap.sec->sec_name, EC_WORD(ndx), arg); return (ndx); } + + /* + * If we hit a NULL, then only more NULLs can follow it and + * there's no need to look further. If there is more than + * one NULL, we can grab the first one and turn it into + * an element of the desired type. + */ + if (argstate->cap.data[ndx].c_tag == CA_SUNW_NULL) { + if (ndx < argstate->cap.grp_end_ndx) { + Conv_inv_buf_t inv_buf; + + elfedit_msg(ELFEDIT_MSG_DEBUG, + MSG_INTL(MSG_DEBUG_CONVNULL), + EC_WORD(argstate->cap.sec->sec_shndx), + argstate->cap.sec->sec_name, EC_WORD(ndx), + conv_cap_tag(ca_value, 0, &inv_buf)); + argstate->cap.data[ndx].c_tag = ca_value; + bzero(&argstate->cap.data[ndx].c_un, + sizeof (argstate->cap.data[ndx].c_un)); + return (ndx); + } + break; + } } /* No room to create one, so we're out of options and must fail */ elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOCAELT), EC_WORD(argstate->cap.sec->sec_shndx), - argstate->cap.sec->sec_name, arg); + argstate->cap.sec->sec_name, argstate->cap.grp_start_ndx, + argstate->cap.grp_end_ndx, cap_group_id(argstate), arg); /*NOTREACHED*/ return (0); /* For lint */ @@ -404,7 +702,46 @@ return (flags); } +/* + * Common processing for capabilities value setting. + * + * entry: + * argstate - Argument state block + * cap - capabilities data pointer + * ndx - capabilities data index + * cap_ndx - capabilities section index + * cap_name - capabilities section name + * cap_tag - capabilities tag + * const_type - data conversion type + */ +static elfedit_cmdret_t +cap_set(ARGSTATE *argstate, Cap *cap, Word ndx, Word cap_ndx, + const char *cap_name, Xword cap_tag, elfedit_const_t const_type) +{ + Conv_cap_val_buf_t buf1, buf2; + Half mach = argstate->obj_state->os_ehdr->e_machine; + Xword ncap, ocap; + ncap = flag_bitop(argstate, cap[ndx].c_un.c_val, + elfedit_const_to_atoui(const_type)); + + /* Set the value */ + if ((ocap = cap[ndx].c_un.c_val) == ncap) { + elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_BSB_OK), + cap_ndx, cap_name, EC_WORD(ndx), + conv_cap_val(cap_tag, ocap, mach, CONV_FMT_NOBKT, &buf1)); + + return (ELFEDIT_CMDRET_NONE); + } else { + elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_BSB_CHG), + cap_ndx, cap_name, EC_WORD(ndx), + conv_cap_val(cap_tag, ocap, mach, CONV_FMT_NOBKT, &buf1), + conv_cap_val(cap_tag, ncap, mach, CONV_FMT_NOBKT, &buf2)); + + cap[ndx].c_un.c_val = ncap; + return (ELFEDIT_CMDRET_MOD); + } +} /* * Common body for the cap: module commands. These commands @@ -424,7 +761,7 @@ ARGSTATE argstate; Cap *cap; const char *cap_name; - Word cap_ndx, cap_num; + Word cap_ndx; elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; PRINT_CAP_T print_type = PRINT_CAP_T_ALL; Word ndx; @@ -435,7 +772,6 @@ process_args(obj_state, argc, argv, &argstate); cap = argstate.cap.data; - cap_num = argstate.cap.num; cap_name = argstate.cap.sec->sec_name; cap_ndx = argstate.cap.sec->sec_shndx; @@ -493,6 +829,13 @@ MSG_ORIG(MSG_STR_VALUE), print_only, &print_type); break; + case CAP_CMD_T_HW2: + print_only = (argstate.argc == 0); + ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( + ELFEDIT_CONST_CA, CA_SUNW_HW_2, 1), + MSG_ORIG(MSG_STR_VALUE), print_only, &print_type); + break; + default: /* Note expected: All commands should have been caught above */ elfedit_command_usage(); @@ -538,8 +881,16 @@ case CAP_CMD_T_VALUE: { - Xword c_val = (Xword) - elfedit_atoui(argstate.argv[1], NULL); + Xword c_val; + + if (argstate.optmask & CAP_OPT_F_STRVAL) { + argstate_add_str(&argstate, TRUE); + c_val = elfedit_strtab_insert(obj_state, + argstate.str.sec, NULL, argstate.argv[1]); + } else { + c_val = (Xword) + elfedit_atoui(argstate.argv[1], NULL); + } if (cap[ndx].c_un.c_val == c_val) { elfedit_msg(ELFEDIT_MSG_DEBUG, @@ -564,12 +915,34 @@ { Word cnt = (argstate.argc == 1) ? 1 : (Word) elfedit_atoui_range(argstate.argv[1], - MSG_ORIG(MSG_STR_COUNT), 1, cap_num - ndx, NULL); + MSG_ORIG(MSG_STR_COUNT), 1, + argstate.cap.grp_end_ndx - ndx + 1, NULL); const char *msg_prefix = elfedit_sec_msgprefix(argstate.cap.sec); - elfedit_array_elts_delete(msg_prefix, argstate.cap.data, - sizeof (Cap), cap_num, ndx, cnt); + /* + * We want to limit the deleted elements to be + * in the range of the current capabilities group, + * and for the resulting NULL elements to be inserted + * at the end of the group, rather than at the end + * of the section. To do this, we set the array length + * in the call to the delete function so that it thinks + * the array ends with the current group. + * + * The delete function will catch attempts to delete + * past this virtual end, but the error message will + * not make sense to the user. In order to prevent that, + * we check for the condition here and provide a more + * useful error. + */ + if ((ndx + cnt - 1) > argstate.cap.grp_end_ndx) + elfedit_msg(ELFEDIT_MSG_ERR, + MSG_INTL(MSG_ERR_GRPARRBNDS), msg_prefix, + argstate.cap.grp_start_ndx, + argstate.cap.grp_end_ndx, + cap_group_id(&argstate)); + elfedit_array_elts_delete(msg_prefix, cap, sizeof (Cap), + argstate.cap.grp_end_ndx + 1, ndx, cnt); ret = ELFEDIT_CMDRET_MOD; } break; @@ -584,17 +957,41 @@ dstndx = (Word) elfedit_atoui_range(argstate.argv[1], - MSG_ORIG(MSG_STR_DST_INDEX), 0, cap_num - 1, - NULL); + MSG_ORIG(MSG_STR_DST_INDEX), + argstate.cap.grp_start_ndx, + argstate.cap.grp_end_ndx, NULL); if (argstate.argc == 2) { cnt = 1; } else { + Word max; + + max = argstate.cap.grp_end_ndx - + ((ndx > dstndx) ? ndx : dstndx) + 1; cnt = (Word) elfedit_atoui_range( argstate.argv[2], MSG_ORIG(MSG_STR_COUNT), - 1, cap_num, NULL); + 1, max, NULL); } - elfedit_array_elts_move(msg_prefix, argstate.cap.data, - sizeof (save), cap_num, ndx, dstndx, cnt, &save); + + /* + * Moves are required to be self contained within + * the bounds of the selected capability group. + * The move utility function contains bounds checking, + * but is not sub-array aware. Hence, we bounds check + * check it here, and then hand of the validated + * operation to the move utility function to execute. + */ + if ((ndx < argstate.cap.grp_start_ndx) || + ((ndx + cnt) > argstate.cap.grp_end_ndx) || + (dstndx < argstate.cap.grp_start_ndx) || + ((dstndx + cnt) > argstate.cap.grp_end_ndx)) + elfedit_msg(ELFEDIT_MSG_ERR, + MSG_INTL(MSG_ERR_GRPARRBNDS), msg_prefix, + argstate.cap.grp_start_ndx, + argstate.cap.grp_end_ndx, + cap_group_id(&argstate)); + elfedit_array_elts_move(msg_prefix, cap, sizeof (save), + argstate.cap.grp_end_ndx + 1, ndx, dstndx, + cnt, &save); ret = ELFEDIT_CMDRET_MOD; } break; @@ -602,61 +999,22 @@ case CAP_CMD_T_HW1: { - Conv_cap_val_hw1_buf_t buf1, buf2; - Half mach = argstate.obj_state->os_ehdr->e_machine; - Xword hw1; - - hw1 = flag_bitop(&argstate, cap[ndx].c_un.c_val, - elfedit_const_to_atoui(ELFEDIT_CONST_AV)); - - /* Set the value */ - if (cap[ndx].c_un.c_val == hw1) { - elfedit_msg(ELFEDIT_MSG_DEBUG, - MSG_INTL(MSG_DEBUG_BSB_OK), cap_ndx, - cap_name, EC_WORD(ndx), - conv_cap_val_hw1(cap[ndx].c_un.c_val, mach, - CONV_FMT_NOBKT, &buf1)); - } else { - elfedit_msg(ELFEDIT_MSG_DEBUG, - MSG_INTL(MSG_DEBUG_BSB_CHG), - cap_ndx, cap_name, EC_WORD(ndx), - conv_cap_val_hw1(cap[ndx].c_un.c_val, mach, - CONV_FMT_NOBKT, &buf1), - conv_cap_val_hw1(hw1, mach, - CONV_FMT_NOBKT, &buf2)); - ret = ELFEDIT_CMDRET_MOD; - cap[ndx].c_un.c_val = hw1; - } + ret = cap_set(&argstate, cap, ndx, cap_ndx, cap_name, + CA_SUNW_HW_1, ELFEDIT_CONST_HW1_SUNW); } break; case CAP_CMD_T_SF1: { - Conv_cap_val_sf1_buf_t buf1, buf2; - Half mach = argstate.obj_state->os_ehdr->e_machine; - Xword sf1; - - sf1 = flag_bitop(&argstate, cap[ndx].c_un.c_val, - elfedit_const_to_atoui(ELFEDIT_CONST_SF1_SUNW)); + ret = cap_set(&argstate, cap, ndx, cap_ndx, cap_name, + CA_SUNW_SF_1, ELFEDIT_CONST_SF1_SUNW); + } + break; - /* Set the value */ - if (cap[ndx].c_un.c_val == sf1) { - elfedit_msg(ELFEDIT_MSG_DEBUG, - MSG_INTL(MSG_DEBUG_BSB_OK), cap_ndx, - cap_name, EC_WORD(ndx), - conv_cap_val_sf1(cap[ndx].c_un.c_val, mach, - CONV_FMT_NOBKT, &buf1)); - } else { - elfedit_msg(ELFEDIT_MSG_DEBUG, - MSG_INTL(MSG_DEBUG_BSB_CHG), - cap_ndx, cap_name, EC_WORD(ndx), - conv_cap_val_sf1(cap[ndx].c_un.c_val, mach, - CONV_FMT_NOBKT, &buf1), - conv_cap_val_sf1(sf1, mach, - CONV_FMT_NOBKT, &buf2)); - ret = ELFEDIT_CMDRET_MOD; - cap[ndx].c_un.c_val = sf1; - } + case CAP_CMD_T_HW2: + { + ret = cap_set(&argstate, cap, ndx, cap_ndx, cap_name, + CA_SUNW_HW_2, ELFEDIT_CONST_HW2_SUNW); } break; } @@ -681,6 +1039,38 @@ */ /* + * -capid command completion: Supply all CA_SUNW_ID names found in the object. + */ +static void +cpl_capid_opt(elfedit_obj_state_t *obj_state, void *cpldata, int argc, + const char *argv[], int num_opt) +{ + elfedit_section_t *cap_sec, *str_sec; + Cap *cap; + Word num; + + if (obj_state == NULL) /* No object available */ + return; + + if ((argc > num_opt) || (argc < 2) || + (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_CAPID)) != 0)) + return; + + cap_sec = elfedit_sec_getcap(obj_state, &cap, &num); + + /* If no associated string table, we have no strings to complete */ + if (cap_sec->sec_shdr->sh_info == 0) + return; + + str_sec = elfedit_sec_getstr(obj_state, cap_sec->sec_shdr->sh_info, 0); + + for (; num--; cap++) + if (cap->c_tag == CA_SUNW_ID) + elfedit_cpl_match(cpldata, elfedit_offset_to_str( + str_sec, cap->c_un.c_val, ELFEDIT_MSG_ERR, 0), 0); +} + +/* * Command completion for the first argument, which specifies * the capabilities element to use. Examines the options to see if * -capndx is present, and if not, supplies the completion @@ -691,7 +1081,13 @@ cpl_eltarg(elfedit_obj_state_t *obj_state, void *cpldata, int argc, const char *argv[], int num_opt) { - Word i; + Word i; + + /* -capid id_name */ + if (argc <= num_opt) { + cpl_capid_opt(obj_state, cpldata, argc, argv, num_opt); + return; + } /* Make sure it's the first argument */ if ((argc - num_opt) != 1) @@ -710,13 +1106,18 @@ elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_CA); } - /*ARGSUSED*/ static void cpl_tag(elfedit_obj_state_t *obj_state, void *cpldata, int argc, const char *argv[], int num_opt) { - /* First argument */ + /* -capid id_name */ + if (argc <= num_opt) { + cpl_capid_opt(obj_state, cpldata, argc, argv, num_opt); + return; + } + + /* First plain argument */ if ((argc - num_opt) == 1) { cpl_eltarg(obj_state, cpldata, argc, argv, num_opt); return; @@ -732,9 +1133,14 @@ cpl_hw1(elfedit_obj_state_t *obj_state, void *cpldata, int argc, const char *argv[], int num_opt) { - /* This routine allows multiple flags to be specified */ + /* -capid id_name */ + if (argc <= num_opt) { + cpl_capid_opt(obj_state, cpldata, argc, argv, num_opt); + return; + } - elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_AV); + /* This routine allows multiple flags to be specified */ + elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_HW1_SUNW); } /*ARGSUSED*/ @@ -742,10 +1148,30 @@ cpl_sf1(elfedit_obj_state_t *obj_state, void *cpldata, int argc, const char *argv[], int num_opt) { + /* -capid id_name */ + if (argc <= num_opt) { + cpl_capid_opt(obj_state, cpldata, argc, argv, num_opt); + return; + } + /* This routine allows multiple flags to be specified */ elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SF1_SUNW); } +/*ARGSUSED*/ +static void +cpl_hw2(elfedit_obj_state_t *obj_state, void *cpldata, int argc, + const char *argv[], int num_opt) +{ + /* -capid id_name */ + if (argc <= num_opt) { + cpl_capid_opt(obj_state, cpldata, argc, argv, num_opt); + return; + } + + /* This routine allows multiple flags to be specified */ + elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_HW2_SUNW); +} /* * Implementation functions for the commands @@ -792,16 +1218,25 @@ return (cmd_body(CAP_CMD_T_SF1, obj_state, argc, argv)); } - +static elfedit_cmdret_t +cmd_hw2(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) +{ + return (cmd_body(CAP_CMD_T_HW2, obj_state, argc, argv)); +} /*ARGSUSED*/ elfedit_module_t * elfedit_init(elfedit_module_version_t version) { - /* For commands that only accept -and, -cmp, -o, and -or */ - static elfedit_cmd_optarg_t opt_ostyle_bitop[] = { + /* For commands that only accept -capid, -and, -cmp, -o, and -or */ + static elfedit_cmd_optarg_t opt_ostyle_capid_bitop[] = { { ELFEDIT_STDOA_OPT_AND, NULL, ELFEDIT_CMDOA_F_INHERIT, CAP_OPT_F_AND, CAP_OPT_F_OR }, + { MSG_ORIG(MSG_STR_MINUS_CAPID), + /* MSG_INTL(MSG_OPTDESC_CAPID) */ + ELFEDIT_I18NHDL(MSG_OPTDESC_CAPID), ELFEDIT_CMDOA_F_VALUE, + CAP_OPT_F_CAPID, CAP_OPT_F_CAPNDX }, + { MSG_ORIG(MSG_STR_IDNAME), NULL, 0 }, { ELFEDIT_STDOA_OPT_CMP, NULL, ELFEDIT_CMDOA_F_INHERIT, CAP_OPT_F_CMP, 0 }, { ELFEDIT_STDOA_OPT_O, NULL, @@ -811,23 +1246,17 @@ { NULL } }; - /* For commands that only accept -capndx */ - static elfedit_cmd_optarg_t opt_capndx[] = { + /* For commands that only accept -capid and -capndx */ + static elfedit_cmd_optarg_t opt_capid_capndx[] = { + { MSG_ORIG(MSG_STR_MINUS_CAPID), + /* MSG_INTL(MSG_OPTDESC_CAPID) */ + ELFEDIT_I18NHDL(MSG_OPTDESC_CAPID), ELFEDIT_CMDOA_F_VALUE, + CAP_OPT_F_CAPID, CAP_OPT_F_CAPNDX }, + { MSG_ORIG(MSG_STR_IDNAME), NULL, 0 }, { MSG_ORIG(MSG_STR_MINUS_CAPNDX), /* MSG_INTL(MSG_OPTDESC_CAPNDX) */ ELFEDIT_I18NHDL(MSG_OPTDESC_CAPNDX), 0, - CAP_OPT_F_CAPNDX, 0 }, - { NULL } - }; - - /* For commands thataccept -capndx and output styles */ - static elfedit_cmd_optarg_t opt_ostyle_capndx[] = { - { MSG_ORIG(MSG_STR_MINUS_CAPNDX), - /* MSG_INTL(MSG_OPTDESC_CAPNDX) */ - ELFEDIT_I18NHDL(MSG_OPTDESC_CAPNDX), 0, - CAP_OPT_F_CAPNDX, 0 }, - { ELFEDIT_STDOA_OPT_O, NULL, - ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, + CAP_OPT_F_CAPNDX, CAP_OPT_F_CAPID }, { NULL } }; @@ -849,6 +1278,20 @@ /* cap:tag */ static const char *name_tag[] = { MSG_ORIG(MSG_CMD_TAG), NULL }; + static elfedit_cmd_optarg_t opt_tag[] = { + { MSG_ORIG(MSG_STR_MINUS_CAPID), + /* MSG_INTL(MSG_OPTDESC_CAPID) */ + ELFEDIT_I18NHDL(MSG_OPTDESC_CAPID), ELFEDIT_CMDOA_F_VALUE, + CAP_OPT_F_CAPID, CAP_OPT_F_CAPNDX }, + { MSG_ORIG(MSG_STR_IDNAME), NULL, 0 }, + { MSG_ORIG(MSG_STR_MINUS_CAPNDX), + /* MSG_INTL(MSG_OPTDESC_CAPNDX) */ + ELFEDIT_I18NHDL(MSG_OPTDESC_CAPNDX), 0, + CAP_OPT_F_CAPNDX, 0 }, + { ELFEDIT_STDOA_OPT_O, NULL, + ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, + { NULL } + }; static elfedit_cmd_optarg_t arg_tag[] = { { MSG_ORIG(MSG_STR_ELT), /* MSG_INTL(MSG_A1_TAG_ELT) */ @@ -864,6 +1307,24 @@ /* cap:value */ static const char *name_value[] = { MSG_ORIG(MSG_CMD_VALUE), NULL }; + static elfedit_cmd_optarg_t opt_value[] = { + { MSG_ORIG(MSG_STR_MINUS_CAPID), + /* MSG_INTL(MSG_OPTDESC_CAPID) */ + ELFEDIT_I18NHDL(MSG_OPTDESC_CAPID), ELFEDIT_CMDOA_F_VALUE, + CAP_OPT_F_CAPID, CAP_OPT_F_CAPNDX }, + { MSG_ORIG(MSG_STR_IDNAME), NULL, 0 }, + { MSG_ORIG(MSG_STR_MINUS_CAPNDX), + /* MSG_INTL(MSG_OPTDESC_CAPNDX) */ + ELFEDIT_I18NHDL(MSG_OPTDESC_CAPNDX), 0, + CAP_OPT_F_CAPNDX, 0 }, + { ELFEDIT_STDOA_OPT_O, NULL, + ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, + { MSG_ORIG(MSG_STR_MINUS_S), + /* MSG_INTL(MSG_OPTDESC_S) */ + ELFEDIT_I18NHDL(MSG_OPTDESC_S), 0, + CAP_OPT_F_STRVAL, 0 }, + { NULL } + }; static elfedit_cmd_optarg_t arg_value[] = { { MSG_ORIG(MSG_STR_ELT), /* MSG_INTL(MSG_ARGDESC_ELT) */ @@ -928,7 +1389,15 @@ { NULL } }; - + /* cap:hw2 */ + static const char *name_hw2[] = { MSG_ORIG(MSG_CMD_HW2), NULL }; + static elfedit_cmd_optarg_t arg_hw2[] = { + { MSG_ORIG(MSG_STR_VALUE), + /* MSG_INTL(MSG_A1_HW2_VALUE) */ + ELFEDIT_I18NHDL(MSG_A1_HW2_VALUE), + ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, + { NULL } + }; static elfedit_cmd_t cmds[] = { @@ -938,7 +1407,7 @@ ELFEDIT_I18NHDL(MSG_DESC_DUMP), /* MSG_INTL(MSG_HELP_DUMP) */ ELFEDIT_I18NHDL(MSG_HELP_DUMP), - opt_capndx, arg_dump }, + opt_capid_capndx, arg_dump }, /* cap:tag */ { cmd_tag, cpl_tag, name_tag, @@ -946,7 +1415,7 @@ ELFEDIT_I18NHDL(MSG_DESC_TAG), /* MSG_INTL(MSG_HELP_TAG) */ ELFEDIT_I18NHDL(MSG_HELP_TAG), - opt_ostyle_capndx, arg_tag }, + opt_tag, arg_tag }, /* cap:value */ { cmd_value, cpl_eltarg, name_value, @@ -954,7 +1423,7 @@ ELFEDIT_I18NHDL(MSG_DESC_VALUE), /* MSG_INTL(MSG_HELP_VALUE) */ ELFEDIT_I18NHDL(MSG_HELP_VALUE), - opt_ostyle_capndx, arg_value }, + opt_value, arg_value }, /* cap:delete */ { cmd_delete, cpl_eltarg, name_delete, @@ -962,7 +1431,7 @@ ELFEDIT_I18NHDL(MSG_DESC_DELETE), /* MSG_INTL(MSG_HELP_DELETE) */ ELFEDIT_I18NHDL(MSG_HELP_DELETE), - opt_capndx, arg_delete }, + opt_capid_capndx, arg_delete }, /* cap:move */ { cmd_move, cpl_eltarg, name_move, @@ -970,7 +1439,7 @@ ELFEDIT_I18NHDL(MSG_DESC_MOVE), /* MSG_INTL(MSG_HELP_MOVE) */ ELFEDIT_I18NHDL(MSG_HELP_MOVE), - opt_capndx, arg_move }, + opt_capid_capndx, arg_move }, /* cap:hw1 */ { cmd_hw1, cpl_hw1, name_hw1, @@ -978,7 +1447,7 @@ ELFEDIT_I18NHDL(MSG_DESC_HW1), /* MSG_INTL(MSG_HELP_HW1) */ ELFEDIT_I18NHDL(MSG_HELP_HW1), - opt_ostyle_bitop, arg_hw1 }, + opt_ostyle_capid_bitop, arg_hw1 }, /* cap:sf1 */ { cmd_sf1, cpl_sf1, name_sf1, @@ -986,7 +1455,15 @@ ELFEDIT_I18NHDL(MSG_DESC_SF1), /* MSG_INTL(MSG_HELP_SF1) */ ELFEDIT_I18NHDL(MSG_HELP_SF1), - opt_ostyle_bitop, arg_sf1 }, + opt_ostyle_capid_bitop, arg_sf1 }, + + /* cap:hw2 */ + { cmd_hw2, cpl_hw2, name_hw2, + /* MSG_INTL(MSG_DESC_HW2) */ + ELFEDIT_I18NHDL(MSG_DESC_HW2), + /* MSG_INTL(MSG_HELP_HW2) */ + ELFEDIT_I18NHDL(MSG_HELP_HW2), + opt_ostyle_capid_bitop, arg_hw2 }, { NULL } };
--- a/usr/src/cmd/sgs/elfedit/modules/common/cap.msg Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/elfedit/modules/common/cap.msg Mon Mar 01 10:20:48 2010 -0800 @@ -20,10 +20,9 @@ # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" @ _START_ @@ -40,20 +39,32 @@ @ MSG_DEBUG_BSB_CHG "[%d: %s][%d]: change from [%s] to [%s]\n" @ MSG_DEBUG_X_OK "[%d: %s][%d]: value unchanged: %#llx\n" @ MSG_DEBUG_X_CHG "[%d: %s][%d]: change from %#llx to %#llx\n" -@ MSG_DEBUG_CA2NDX "[%d: %s][%d]: Capability entry for tag: %s\n" - +@ MSG_DEBUG_CA2NDX "[%d: %s][%d]: capability entry for tag: %s\n" +@ MSG_DEBUG_CAPGRP "[%d: %s][%u-%u: %s]: capability group\n" +@ MSG_DEBUG_CONVNULL "[%d: %s][%d]: no existing %s to modify, converting \ + extra CA_SUNW_NULL\n" # Errors -@ MSG_ERR_NOCAELT "[%d: %s]: Capabilities section does not contain \ - tag: %s\n" - +@ MSG_ERR_NOCAELT "[%d: %s][%u-%u: %s]: capabilities group does not \ + contain tag: %s\n" +@ MSG_ERR_NOSTRTAB "[%d: %s]: capabilities section does not have an \ + associated string table\n" +@ MSG_ERR_BADCAPID "[%d: %s]: capabilities section does not contain \ + specified id: %s\n" +@ MSG_ERR_GRPARRBNDS "%s[%u-%u: %s]: attempt to access elements outside \ + of capabilities group\n" # Module description @ MSG_MOD_DESC "Capabilities Section" +# Strings +@ MSG_STR_OBJECT "<object>" +@ MSG_STR_NONAME "<noname>" +# Format strings +@ MSG_FMT_CAPGRP " Group[%u-%u]: %s\n" # 1-line description strings @@ -62,16 +73,30 @@ @ MSG_DESC_VALUE "Change element value" @ MSG_DESC_DELETE "Delete elements" @ MSG_DESC_MOVE "Move elements" -@ MSG_DESC_HW1 "Hardware capabilities bit values" -@ MSG_DESC_SF1 "Software capabilities bit values" +@ MSG_DESC_HW1 "Hardware capabilities (CA_SUNW_HW_1) bit values" +@ MSG_DESC_SF1 "Software capabilities (CA_SUNW_SF_1) bit values" +@ MSG_DESC_HW2 "Hardware capabilities (CA_SUNW_HW_2) bit values" -# Commmand option description strings +# Command option description strings @ MSG_OPTDESC_CAPNDX "\ Interpret the elt argument as a direct index into the\n\ capabilities section, rather than as a CA_ tag value.\n" +@ MSG_OPTDESC_CAPID "\ + Restrict the elt argument to the capability elements belonging\n\ + to the capabilities group with a CA_SUNW_ID entry matching the\n\ + specified id name.\n" + +@ MSG_OPTDESC_S "\ + Interpret the value argument as a string rather than an\n\ + integer. If the specified string already exists in the\n\ + string table, the offset of that string is stored in the\n\ + capability entry. If the string does not exist in the string\n\ + table, but there is room to add it, the new string is added\n\ + and then the offset is placed in the capability entry.\n" + # Command argument description strings @@ -98,7 +123,9 @@ can be specified using the well known CA_ symbolic constants\n\ from /usr/include/sys/elf.h, or as integers. If the -capndx\n\ option is specified, then elt is instead interpreted as a\n\ - direct numeric index into the capabilities section.\n" + direct numeric index into the capabilities section. If the\n\ + -capid option is specified, the search is limited to elements\n\ + within the named capabilities group.\n" @ MSG_A2_VALUE_VALUE "\ Value to set for specified capabilities section element.\n\ @@ -107,30 +134,34 @@ @ MSG_A2_DELETE_COUNT "\ Number of capabilities elements to delete, starting at the\n\ specified position. This value cannot exceed the number\n\ - of slots remaining in the table below the specified position.\n\ - If count is not supplied, a single element is deleted.\n" + of slots remaining in the capabilities group below the specified\n\ + position. If count is not supplied, a single element is deleted.\n" @ MSG_A2_MOVE_DST_INDEX "\ Numeric index within capabilities section to which the element(s)\n\ - should be moved.\n" + should be moved. The destination index must lie within the same\n\ + capabilities group as elt.\n" @ MSG_A3_MOVE_COUNT "\ Number of capabilities elements to move. This value cannot\n\ - exceed the number of slots remaining in the table below\n\ - the specified position. If count is not supplied, a\n\ + exceed the number of slots remaining in the capabilities group\n\ + below the specified position. If count is not supplied, a\n\ single element is moved.\n" @ MSG_A1_HW1_VALUE "\ - Hardware capability values. This can be an integer value,\n\ - any of the AV_386_ symbolic constants defined in\n\ + Hardware capability (CA_SUNW_HW_1) values. This can be an integer\n\ + value, any of the AV_386_ symbolic constants defined in\n\ /usr/include/sys/auxv_386.h, or the AV_SPARC symbolic\n\ - constants defined in /usr/include/sys/auxv_SPARC.h\n" + constants defined in /usr/include/sys/auxv_SPARC.h.\n" @ MSG_A1_SF1_VALUE "\ - Software capability values. This can be an integer value,\n\ - any of the SF1_SUNW_ symbolic constants defined in\n\ - /usr/include/sys/elf.h\n" + Software capability (CA_SUNW_SF_1) values. This can be an integer\n\ + value, any of the SF1_SUNW_ symbolic constants defined in\n\ + /usr/include/sys/elf.h.\n" +@ MSG_A1_HW2_VALUE "\ + Hardware capability (CA_SUNW_HW_2) values. This is available for\n\ + future expansion.\n" # Help strings @@ -165,14 +196,16 @@ @ MSG_HELP_DELETE " \ The cap:delete command is used to delete one or more elements\n\ - in the capabilities section. The elements following the deleted\n\ - items move up, and new CA_NULL elements are inserted at the\n\ - end of the capabilities section to fill the vacated space.\n" + from a capabilities group within the capabilities section. The\n\ + elements following the deleted items move up, and new CA_NULL\n\ + elements are inserted at the end of the capabilities group to\n\ + fill the vacated space.\n" @ MSG_HELP_MOVE " \ The cap:move command is used to move the position of one\n\ - or more elements in the capabilities section. The specified\n\ - number of elements are moved from elt to dst_index.\n" + or more elements in a capabilities group within in the\n\ + capabilities section. The specified number of elements are\n\ + moved from elt to dst_index.\n" @ MSG_HELP_HW1 " \ The cap:hw1 command is used to display or alter the\n\ @@ -214,6 +247,25 @@ \tvalue. If neither -and or -or are specified, the new value\n\ replaces the existing value.\n" +@ MSG_HELP_HW2 " \ + The cap:hw2 command is used to display or alter the\n\ + value of the hardware capabilities element (CA_SUNW_HW_2).\n\ + \n\ + If cap:hw2 is called without arguments, the current\n\ + value is shown. If one or more value arguments are present,\n\ + the following steps are taken:\n\ + \n \ + o\tAll the value arguments are OR'd together.\n\ + \n \ + o\tIf the -cmp option has been specified, the new value\n\ + \tis complemented.\n\ + \n \ + o\tThe CA_SUNW_HW_2 element of the capabilities section is\n\ + \tupdated with the new value. If -and is specified, the new\n\ + \tvalue is AND'd against the existing value. If -or is\n\ + \tspecified, the new value is OR'd against the existing\n\ + \tvalue. If neither -and or -or are specified, the new value\n\ + \treplaces the existing value.\n" @ _END_ @@ -227,12 +279,16 @@ @ MSG_STR_COUNT "count" @ MSG_STR_ELT "elt" @ MSG_STR_DST_INDEX "dst_index" +@ MSG_STR_MINUS_CAPID "-capid" @ MSG_STR_MINUS_CAPNDX "-capndx" +@ MSG_STR_MINUS_S "-s" @ MSG_STR_VALUE "value" +@ MSG_STR_IDNAME "id_name" # Format strings @ MSG_FMT_STRNL "%s\n" @ MSG_FMT_HEXXWORDNL "%#llx\n" +@ MSG_FMT_WORDVALNL "%u\n" # Module name @@ -249,3 +305,4 @@ @ MSG_CMD_MOVE "move" @ MSG_CMD_HW1 "hw1" @ MSG_CMD_SF1 "sf1" +@ MSG_CMD_HW2 "hw2"
--- a/usr/src/cmd/sgs/elfedit/modules/common/dyn.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/elfedit/modules/common/dyn.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -553,7 +553,7 @@ elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), name); } else { elfedit_printf(MSG_ORIG(MSG_FMT_HEXXWORDNL), - dyn->d_un.d_val); + EC_XWORD(dyn->d_un.d_val)); } } printed = 1;
--- a/usr/src/cmd/sgs/elfwrap/Makefile.com Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/elfwrap/Makefile.com Mon Mar 01 10:20:48 2010 -0800 @@ -51,7 +51,7 @@ CPPFLAGS = -I. -I../common -I../../include $(CPPFLAGS.master) -I$(ELFCAP) LLDFLAGS = LLDFLAGS64 = -LDFLAGS += $(VERSREF) $(USE_PROTO) $(MAPOPTS) $(LLDFLAGS) +LDFLAGS += $(VERSREF) $(CC_USE_PROTO) $(MAPOPTS) $(LLDFLAGS) LDLIBS += $(ELFLIBDIR) -lelf $(CONVLIBDIR) $(CONV_LIB) LINTFLAGS += -x
--- a/usr/src/cmd/sgs/include/_machelf.h Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/include/_machelf.h Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Wrapper around the <sys/machelf.h> header that adds @@ -30,8 +30,6 @@ #ifndef _MACHELF_H #define _MACHELF_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/machelf.h> #include <string.h> /* memcpy() */ @@ -61,6 +59,9 @@ #define ELF_M_SYM ELF64_M_SYM #define ELF_M_SIZE ELF64_M_SIZE #define ELF_M_INFO ELF64_M_INFO +#define ELF_C_SYM ELF64_C_SYM +#define ELF_C_GROUP ELF64_C_GROUP +#define ELF_C_INFO ELF64_C_INFO #define elf_checksum elf64_checksum #define elf_fsize elf64_fsize #define elf_getehdr elf64_getehdr @@ -84,6 +85,9 @@ #define ELF_M_SYM ELF32_M_SYM #define ELF_M_SIZE ELF32_M_SIZE #define ELF_M_INFO ELF32_M_INFO +#define ELF_C_SYM ELF32_C_SYM +#define ELF_C_GROUP ELF32_C_GROUP +#define ELF_C_INFO ELF32_C_INFO #define elf_checksum elf32_checksum #define elf_fsize elf32_fsize #define elf_getehdr elf32_getehdr
--- a/usr/src/cmd/sgs/include/conv.h Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/include/conv.h Mon Mar 01 10:20:48 2010 -0800 @@ -127,10 +127,10 @@ } Conv_reject_desc_buf_t; /* - * conv_cap_val_hw1() + * conv_cap_val_hw/sf() * - * This size is based on the maximum number of hardware capabilities - * that exist. See common/elfcap. + * These sizes are based on the maximum number of capabilities that exist. + * See common/elfcap. */ #define CONV_CAP_VAL_HW1_BUFSIZE 195 typedef union { @@ -138,12 +138,12 @@ char buf[CONV_CAP_VAL_HW1_BUFSIZE]; } Conv_cap_val_hw1_buf_t; -/* - * conv_cap_val_sf1() - * - * This size is based on the maximum number of software capabilities - * that exist. See common/elfcap. - */ +#define CONV_CAP_VAL_HW2_BUFSIZE CONV_INV_BUFSIZE /* for now */ +typedef union { + Conv_inv_buf_t inv_buf; + char buf[CONV_CAP_VAL_HW2_BUFSIZE]; +} Conv_cap_val_hw2_buf_t; + #define CONV_CAP_VAL_SF1_BUFSIZE 45 typedef union { Conv_inv_buf_t inv_buf; @@ -155,6 +155,7 @@ Conv_inv_buf_t inv_buf; Conv_cap_val_hw1_buf_t cap_val_hw1_buf; Conv_cap_val_sf1_buf_t cap_val_sf1_buf; + Conv_cap_val_hw2_buf_t cap_val_hw2_buf; } Conv_cap_val_buf_t; /* conv_config_feat() */ @@ -362,7 +363,7 @@ } Conv_ent_flags_buf_t; /* conv_ent_files_flags() */ -#define CONV_ENT_FILES_FLAGS_BUFSIZE 89 +#define CONV_ENT_FILES_FLAGS_BUFSIZE 89 typedef union { Conv_inv_buf_t inv_buf; char buf[CONV_ENT_FILES_FLAGS_BUFSIZE]; @@ -896,6 +897,8 @@ void *); extern conv_iter_ret_t conv_iter_cap_val_hw1(Half, Conv_fmt_flags_t, conv_iter_cb_t, void *); +extern conv_iter_ret_t conv_iter_cap_val_hw2(Half, Conv_fmt_flags_t, + conv_iter_cb_t, void *); extern conv_iter_ret_t conv_iter_cap_val_sf1(Conv_fmt_flags_t, conv_iter_cb_t, void *); @@ -962,6 +965,7 @@ #define conv_cap_tag conv64_cap_tag #define conv_cap_val conv64_cap_val #define conv_cap_val_hw1 conv64_cap_val_hw1 +#define conv_cap_val_hw2 conv64_cap_val_hw2 #define conv_cap_val_sf1 conv64_cap_val_sf1 #define conv_dyn_feature1 conv64_dyn_feature1 #define conv_dyn_flag1 conv64_dyn_flag1 @@ -979,6 +983,7 @@ #define conv_cap_tag conv32_cap_tag #define conv_cap_val conv32_cap_val #define conv_cap_val_hw1 conv32_cap_val_hw1 +#define conv_cap_val_hw2 conv32_cap_val_hw2 #define conv_cap_val_sf1 conv32_cap_val_sf1 #define conv_dyn_feature1 conv32_dyn_feature1 #define conv_dyn_flag1 conv32_dyn_flag1 @@ -1010,9 +1015,12 @@ */ extern const char *conv_cap_tag(Xword, Conv_fmt_flags_t, Conv_inv_buf_t *); -extern const char *conv_cap_val(Xword, Xword, Half, Conv_cap_val_buf_t *); +extern const char *conv_cap_val(Xword, Xword, Half, Conv_fmt_flags_t, + Conv_cap_val_buf_t *); extern const char *conv_cap_val_hw1(Xword, Half, Conv_fmt_flags_t, Conv_cap_val_hw1_buf_t *); +extern const char *conv_cap_val_hw2(Xword, Half, Conv_fmt_flags_t, + Conv_cap_val_hw2_buf_t *); extern const char *conv_cap_val_sf1(Xword, Half, Conv_fmt_flags_t, Conv_cap_val_sf1_buf_t *); extern const char *conv_dyn_flag1(Xword, Conv_fmt_flags_t,
--- a/usr/src/cmd/sgs/include/debug.h Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/include/debug.h Mon Mar 01 10:20:48 2010 -0800 @@ -133,6 +133,18 @@ #define DBG_BINFO_REF_PARENT 0x2000 /* reference to PARENT */ #define DBG_BINFO_REF_MSK 0xf000 +/* + * ld.so.1(1) symbol capabilities processing. + */ +#define DBG_CAP_DEFAULT 0 +#define DBG_CAP_USED 1 +#define DBG_CAP_CANDIDATE 2 +#define DBG_CAP_REJECTED 3 +#define DBG_CAP_HW_1 4 +#define DBG_CAP_SF_1 5 +#define DBG_CAP_HW_2 6 +#define DBG_CAP_PLAT 7 +#define DBG_CAP_MACH 8 #define DBG_REL_START 1 #define DBG_REL_FINISH 2 @@ -159,8 +171,8 @@ #define DBG_STATE_MOD_AFTER 5 /* modify (after) */ #define DBG_STATE_NEW 6 /* new */ #define DBG_STATE_NEW_IMPLICIT 7 /* new (implicit) */ -#define DBG_STATE_OUT 8 /* out */ -#define DBG_STATE_RESET 9 /* reset */ +#define DBG_STATE_RESET 8 /* reset */ +#define DBG_STATE_ORIGINAL 9 /* original */ #define DBG_STATE_RESOLVED 10 /* resolved */ #define DBG_STATE_NUM 11 @@ -280,14 +292,15 @@ #define Dbg_bind_reject Dbg64_bind_reject #define Dbg_bind_weak Dbg64_bind_weak -#define Dbg_cap_entry Dbg64_cap_entry -#define Dbg_cap_entry2 Dbg64_cap_entry2 -#define Dbg_cap_val_hw1 Dbg64_cap_val_hw1 -#define Dbg_cap_hw_candidate Dbg64_cap_hw_candidate -#define Dbg_cap_hw_filter Dbg64_cap_hw_filter +#define Dbg_cap_candidate Dbg64_cap_candidate +#define Dbg_cap_filter Dbg64_cap_filter +#define Dbg_cap_id Dbg64_cap_id #define Dbg_cap_mapfile_title Dbg64_cap_mapfile_title -#define Dbg_cap_out_title Dbg64_cap_out_title +#define Dbg_cap_post_title Dbg64_cap_post_title #define Dbg_cap_sec_title Dbg64_cap_sec_title +#define Dbg_cap_val Dbg64_cap_val +#define Dbg_cap_ptr_entry Dbg64_cap_ptr_entry +#define Dbg_cap_val_entry Dbg64_cap_val_entry #define Dbg_cb_iphdr_enter Dbg64_cb_iphdr_enter #define Dbg_cb_iphdr_callback Dbg64_cb_iphdr_callback @@ -435,6 +448,10 @@ #define Dbg_syms_ar_entry Dbg64_syms_ar_entry #define Dbg_syms_ar_resolve Dbg64_syms_ar_resolve #define Dbg_syms_ar_title Dbg64_syms_ar_title +#define Dbg_syms_cap_convert Dbg64_syms_cap_convert +#define Dbg_syms_cap_local Dbg64_syms_cap_local +#define Dbg_syms_cap_lookup Dbg64_syms_cap_lookup +#define Dbg_syms_cap_title Dbg64_syms_cap_title #define Dbg_syms_created Dbg64_syms_created #define Dbg_syms_discarded Dbg64_syms_discarded #define Dbg_syms_dlsym Dbg64_syms_dlsym @@ -502,14 +519,15 @@ #define Dbg_bind_reject Dbg32_bind_reject #define Dbg_bind_weak Dbg32_bind_weak -#define Dbg_cap_entry Dbg32_cap_entry -#define Dbg_cap_entry2 Dbg32_cap_entry2 -#define Dbg_cap_val_hw1 Dbg32_cap_val_hw1 -#define Dbg_cap_hw_candidate Dbg32_cap_hw_candidate -#define Dbg_cap_hw_filter Dbg32_cap_hw_filter +#define Dbg_cap_candidate Dbg32_cap_candidate +#define Dbg_cap_filter Dbg32_cap_filter +#define Dbg_cap_id Dbg32_cap_id #define Dbg_cap_mapfile_title Dbg32_cap_mapfile_title -#define Dbg_cap_out_title Dbg32_cap_out_title +#define Dbg_cap_post_title Dbg32_cap_post_title #define Dbg_cap_sec_title Dbg32_cap_sec_title +#define Dbg_cap_val Dbg32_cap_val +#define Dbg_cap_ptr_entry Dbg32_cap_ptr_entry +#define Dbg_cap_val_entry Dbg32_cap_val_entry #define Dbg_cb_iphdr_enter Dbg32_cb_iphdr_enter #define Dbg_cb_iphdr_callback Dbg32_cb_iphdr_callback @@ -657,6 +675,10 @@ #define Dbg_syms_ar_entry Dbg32_syms_ar_entry #define Dbg_syms_ar_resolve Dbg32_syms_ar_resolve #define Dbg_syms_ar_title Dbg32_syms_ar_title +#define Dbg_syms_cap_convert Dbg32_syms_cap_convert +#define Dbg_syms_cap_local Dbg32_syms_cap_local +#define Dbg_syms_cap_lookup Dbg32_syms_cap_lookup +#define Dbg_syms_cap_title Dbg32_syms_cap_title #define Dbg_syms_created Dbg32_syms_created #define Dbg_syms_discarded Dbg32_syms_discarded #define Dbg_syms_dlsym Dbg32_syms_dlsym @@ -754,14 +776,15 @@ extern void Dbg_bind_reject(Rt_map *, Rt_map *, const char *, int); extern void Dbg_bind_weak(Rt_map *, Addr, Addr, const char *); -extern void Dbg_cap_entry(Lm_list *, dbg_state_t, Xword, Xword, Half); -extern void Dbg_cap_entry2(Lm_list *, dbg_state_t, Xword, CapMask *, Half); -extern void Dbg_cap_hw_candidate(Lm_list *, const char *); -extern void Dbg_cap_hw_filter(Lm_list *, const char *, Rt_map *); +extern void Dbg_cap_candidate(Lm_list *, const char *); +extern void Dbg_cap_filter(Lm_list *, const char *, Rt_map *); +extern void Dbg_cap_id(Lm_list *, Lineno, const char *, const char *); extern void Dbg_cap_mapfile_title(Lm_list *, Lineno); -extern void Dbg_cap_out_title(Lm_list *); +extern void Dbg_cap_post_title(Lm_list *, int *); extern void Dbg_cap_sec_title(Lm_list *, const char *); -extern void Dbg_cap_val_hw1(Lm_list *, Xword, Half); +extern void Dbg_cap_val(Lm_list *, Syscapset *, Syscapset *, Half); +extern void Dbg_cap_ptr_entry(Lm_list *, dbg_state_t, Xword, const char *); +extern void Dbg_cap_val_entry(Lm_list *, dbg_state_t, Xword, Xword, Half); extern void Dbg_cb_iphdr_enter(Lm_list *, u_longlong_t, u_longlong_t); extern void Dbg_cb_iphdr_callback(Lm_list *, struct dl_phdr_info *); @@ -935,6 +958,12 @@ 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_cap_convert(Ofl_desc *, Word, const char *, Sym *); +extern void Dbg_syms_cap_local(Ofl_desc *, Word, const char *, Sym *, + Sym_desc *); +extern void Dbg_syms_cap_lookup(Rt_map *, uint_t, const char *, uint_t, + Half, Syscapset *); +extern void Dbg_syms_cap_title(Ofl_desc *); extern void Dbg_syms_created(Lm_list *, const char *); extern void Dbg_syms_discarded(Lm_list *, Sym_desc *); extern void Dbg_syms_dlsym(Rt_map *, const char *, int *, const char *, @@ -1099,7 +1128,8 @@ #endif -extern void Elf_cap_entry(Lm_list *, Cap *, int, Half); +extern void Elf_cap_entry(Lm_list *, Cap *, int, const char *, size_t, + Half); extern void Elf_cap_title(Lm_list *); extern const char \
--- a/usr/src/cmd/sgs/include/elfedit.h Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/include/elfedit.h Mon Mar 01 10:20:48 2010 -0800 @@ -736,10 +736,11 @@ ELFEDIT_CONST_SYMINFO_BT = 30, /* Syminfo boundto */ ELFEDIT_CONST_SYMINFO_FLG = 31, /* Syminfo flags */ ELFEDIT_CONST_CA = 32, /* Capabilities tags */ - ELFEDIT_CONST_AV = 33, /* hardware capabilities */ + ELFEDIT_CONST_HW1_SUNW = 33, /* hardware capabilities */ ELFEDIT_CONST_SF1_SUNW = 34, /* software capabilities */ + ELFEDIT_CONST_HW2_SUNW = 35, /* hardware capabilities */ - ELFEDIT_CONST_NUM = 35, /* # of constant types */ + ELFEDIT_CONST_NUM = 36, /* # of constant types */ } elfedit_const_t; /*
--- a/usr/src/cmd/sgs/include/i386/machdep_x86.h Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/include/i386/machdep_x86.h Mon Mar 01 10:20:48 2010 -0800 @@ -243,20 +243,23 @@ #define M_ID_NULL 0x00 #define M_ID_USER 0x01 -#define M_ID_INTERP 0x03 /* SHF_ALLOC */ -#define M_ID_CAP 0x04 +#define M_ID_INTERP 0x02 /* SHF_ALLOC */ +#define M_ID_CAP 0x03 + #define M_ID_UNWINDHDR 0x06 #define M_ID_UNWIND 0x07 -#define M_ID_SYMINFO 0x08 -#define M_ID_HASH 0x09 -#define M_ID_LDYNSYM 0x0a /* always right before DYNSYM */ -#define M_ID_DYNSYM 0x0b -#define M_ID_DYNSTR 0x0c -#define M_ID_VERSION 0x0d -#define M_ID_DYNSORT 0x0e -#define M_ID_REL 0x0f -#define M_ID_PLT 0x10 /* SHF_ALLOC + SHF_EXECISNTR */ -#define M_ID_TEXT 0x11 +#define M_ID_CAPINFO 0x08 +#define M_ID_CAPCHAIN 0x09 +#define M_ID_SYMINFO 0x0a +#define M_ID_HASH 0x0b +#define M_ID_LDYNSYM 0x0c /* always right before DYNSYM */ +#define M_ID_DYNSYM 0x0d +#define M_ID_DYNSTR 0x0e +#define M_ID_VERSION 0x0f +#define M_ID_DYNSORT 0x10 +#define M_ID_REL 0x11 +#define M_ID_PLT 0x12 /* SHF_ALLOC + SHF_EXECINSTR */ +#define M_ID_TEXT 0x13 #define M_ID_DATA 0x20 /* M_ID_USER 0x01 dual entry - listed above */
--- a/usr/src/cmd/sgs/include/libld.h Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/include/libld.h Mon Mar 01 10:20:48 2010 -0800 @@ -163,6 +163,50 @@ const char *wsn_wrapname; /* Wrap symbol name: __wrap_XXX */ } WrapSymNode; +/* + * Capabilities structures, used to maintain a capabilities set. + * + * Capabilities can be defined within input relocatable objects, and can be + * augmented or replaced by mapfile directives. In addition, mapfile directives + * can be used to exclude capabilities that would otherwise be carried over to + * the output object. + * + * CA_SUNW_HW_1, CA_SUNW_SF_1 and CA_SUNW_HW_2 values are bitmasks. A current + * value, and an exclude value are maintained for each capability. + * + * There can be multiple CA_SUNW_PLAT and CA_SUNW_MACH entries and thus Alists + * are used to collect these entries. A current list for each capability is + * maintained as Capstr entries, which provide for maintaining the strings + * eventual index into a string table. An exclude list is maintained as a + * list of string pointers. + */ +typedef struct { + elfcap_mask_t cm_val; /* bitmask value */ + elfcap_mask_t cm_exc; /* bits to exclude from final object */ +} Capmask; + +typedef struct { + Alist *cl_val; /* string (Capstr) value */ + APlist *cl_exc; /* strings to exclude from final */ +} Caplist; /* object */ + +typedef struct { + char *cs_str; /* platform or machine name */ + Word cs_ndx; /* the entries output Cap index */ +} Capstr; + +typedef uint_t oc_flag_t; +typedef struct { + Capmask oc_hw_1; /* CA_SUNW_HW_1 capabilities */ + Capmask oc_sf_1; /* CA_SUNW_SF_1 capabilities */ + Capmask oc_hw_2; /* CA_SUNW_HW_2 capabilities */ + Caplist oc_plat; /* CA_SUNW_PLAT capabilities */ + Caplist oc_mach; /* CA_SUNW_MACH capabilities */ + Capstr oc_id; /* CA_SUNW_ID capability */ + oc_flag_t oc_flags; +} Objcapset; + +#define FLG_OCS_USRDEFID 0x1 /* user defined CA_SUNW_ID */ /* * Bitmasks for a single capability. Capabilities come from input objects, @@ -277,6 +321,12 @@ Word ofl_dyntlssortcnt; /* no. ndx in .SUNW_dyntlssort */ Word ofl_dynshdrcnt; /* no. of output section in .dynsym */ Word ofl_shdrcnt; /* no. of output sections */ + Word ofl_caploclcnt; /* no. of local capabilities symbols */ + Word ofl_capsymcnt; /* no. of symbol capabilities entries */ + /* required */ + Word ofl_capchaincnt; /* no. of Capchain symbols */ + APlist *ofl_capgroups; /* list of capabilities groups */ + avl_tree_t *ofl_capfamilies; /* capability family AVL tree */ Str_tbl *ofl_shdrsttab; /* Str_tbl for shdr strtab */ Str_tbl *ofl_strtab; /* Str_tbl for symtab strtab */ Str_tbl *ofl_dynstrtab; /* Str_tbl for dymsym strtab */ @@ -313,6 +363,8 @@ Os_desc *ofl_ospreinitarray; /* .preinitarray output section */ Os_desc *ofl_osinterp; /* .interp output section */ Os_desc *ofl_oscap; /* .SUNW_cap output section */ + Os_desc *ofl_oscapinfo; /* .SUNW_capinfo output section */ + Os_desc *ofl_oscapchain; /* .SUNW_capchain output section */ Os_desc *ofl_osplt; /* .plt output section */ Os_desc *ofl_osmove; /* .SUNW_move output section */ Os_desc *ofl_osrelhead; /* first relocation section */ @@ -337,7 +389,7 @@ char *ofl_audit; /* object auditing required (-p) */ Alist *ofl_symfltrs; /* per-symbol filtees and their */ Alist *ofl_dtsfltrs; /* associated .dynamic/.dynstrs */ - Outcapset ofl_ocapset; /* object capabilities */ + Objcapset ofl_ocapset; /* object capabilities */ Lm_list *ofl_lml; /* runtime link-map list */ Gottable *ofl_gottable; /* debugging got information */ Rlxrel_cache ofl_sr_cache; /* Cache last result from */ @@ -395,8 +447,12 @@ #define FLG_OF_REDLSYM 0x004000000000 /* reduce local symbols */ #define FLG_OF_OS_ORDER 0x008000000000 /* output section ordering required */ #define FLG_OF_OSABI 0x010000000000 /* tag object as ELFOSABI_SOLARIS */ -#define FLG_OF_ADJOSCNT 0x020000000000 /* ajust ofl_shdrcnt to accommodate */ +#define FLG_OF_ADJOSCNT 0x020000000000 /* adjust ofl_shdrcnt to accommodate */ /* discarded sections */ +#define FLG_OF_OTOSCAP 0x040000000000 /* convert object capabilities to */ + /* symbol capabilities */ +#define FLG_OF_PTCAP 0x080000000000 /* PT_SUNWCAP required */ +#define FLG_OF_CAPSTRS 0x100000000000 /* capability strings are required */ /* * In the flags1 arena, establish any options that are applicable to archive @@ -418,7 +474,6 @@ #define FLG_OF1_NRLXREL 0x0000000200 /* -z norelaxreloc flag set */ #define FLG_OF1_RLXREL 0x0000000400 /* -z relaxreloc flag set */ #define FLG_OF1_IGNORE 0x0000000800 /* ignore unused dependencies */ - #define FLG_OF1_NOSGHND 0x0000001000 /* -z nosighandler flag set */ #define FLG_OF1_TEXTOFF 0x0000002000 /* text relocations are ok */ #define FLG_OF1_ABSEXEC 0x0000004000 /* -zabsexec set */ @@ -434,7 +489,7 @@ /* section */ #define FLG_OF1_MEMORY 0x0000200000 /* produce a memory model */ #define FLG_OF1_NGLBDIR 0x0000400000 /* no DT_1_DIRECT flag allowed */ -#define FLG_OF1_ENCDIFF 0x0000800000 /* Host running linker has different */ +#define FLG_OF1_ENCDIFF 0x0000800000 /* host running linker has different */ /* byte order than output object */ #define FLG_OF1_VADDR 0x0001000000 /* a segment defines explicit vaddr */ #define FLG_OF1_EXTRACT 0x0002000000 /* archive member has been extracted */ @@ -449,6 +504,9 @@ #define FLG_OF1_OVHWCAP1 0x0100000000 /* override CA_SUNW_HW_1 capabilities */ #define FLG_OF1_OVSFCAP1 0x0200000000 /* override CA_SUNW_SF_1 capabilities */ #define FLG_OF1_OVHWCAP2 0x0400000000 /* override CA_SUNW_HW_2 capabilities */ +#define FLG_OF1_OVMACHCAP 0x0800000000 /* override CA_SUNW_MACH capability */ +#define FLG_OF1_OVPLATCAP 0x1000000000 /* override CA_SUNW_PLAT capability */ +#define FLG_OF1_OVIDCAP 0x2000000000 /* override CA_SUNW_ID capability */ /* * Test to see if the output file would allow the presence of @@ -497,6 +555,7 @@ #define SYMTAB_LOC_CNT(_ofl) /* local .symtab entries */ \ (2 + /* NULL and STT_FILE */ \ (_ofl)->ofl_shdrcnt + /* section symbol */ \ + (_ofl)->ofl_caploclcnt + /* local capabilities */ \ (_ofl)->ofl_scopecnt + /* scoped symbols */ \ (_ofl)->ofl_locscnt) /* standard locals */ #define SYMTAB_ALL_CNT(_ofl) /* all .symtab entries */ \ @@ -506,6 +565,7 @@ #define DYNSYM_LOC_CNT(_ofl) /* local .dynsym entries */ \ (1 + /* NULL */ \ (_ofl)->ofl_dynshdrcnt + /* section symbols */ \ + (_ofl)->ofl_caploclcnt + /* local capabilities */ \ (_ofl)->ofl_lregsymcnt) /* local register symbols */ #define DYNSYM_ALL_CNT(_ofl) /* all .dynsym entries */ \ (DYNSYM_LOC_CNT(_ofl) + /* .dynsym locals */ \ @@ -598,7 +658,7 @@ * Symbol value descriptor. For relocatable objects, each symbols value is * its offset within its associated section. Therefore, to uniquely define * each symbol within a reloctable object, record and sort the sh_offset and - * symbol value. This information is used to seach for displacement + * symbol value. This information is used to search for displacement * relocations as part of copy relocation validation. */ typedef struct { @@ -634,6 +694,7 @@ APlist *ifl_verdesc; /* version descriptor list */ APlist *ifl_relsect; /* relocation section list */ Alist *ifl_groups; /* SHT_GROUP section list */ + Cap_desc *ifl_caps; /* capabilities descriptor */ }; #define FLG_IF_CMDLINE 0x00000001 /* full filename specified from the */ @@ -667,6 +728,8 @@ #define FLG_IF_GNUVER 0x00010000 /* file used GNU-style versioning */ #define FLG_IF_ORDERED 0x00020000 /* ordered section processing */ /* required */ +#define FLG_IF_OTOSCAP 0x00040000 /* convert object capabilities to */ + /* symbol capabilities */ struct is_desc { /* input section descriptor */ const char *is_name; /* original section name */ @@ -679,7 +742,7 @@ Is_desc *is_comdatkeep; /* If COMDAT section is discarded, */ /* this is section that was kept */ Word is_scnndx; /* original section index in file */ - Word is_ordndx; /* Index for section. Used to decide */ + Word is_ordndx; /* index for section. Used to decide */ /* where to insert section when */ /* reordering sections */ Word is_keyident; /* key for SHF_{ORDERED|LINK_ORDER} */ @@ -993,7 +1056,6 @@ #define FLG_SY_VERSPROM 0x00000080 /* version definition has been */ /* promoted to output file */ #define FLG_SY_PROT 0x00000100 /* stv_protected visibility seen */ - #define FLG_SY_MAPREF 0x00000200 /* symbol reference generated by user */ /* from mapfile */ #define FLG_SY_REFRSD 0x00000400 /* symbols sd_ref has been raised */ @@ -1068,6 +1130,14 @@ #define FLG_SY_DIR 0x0020000000000 /* global symbol, direct bindings */ #define FLG_SY_NDIR 0x0040000000000 /* global symbol, nondirect bindings */ #define FLG_SY_OVERLAP 0x0080000000000 /* move entry overlap detected */ +#define FLG_SY_CAP 0x0100000000000 /* symbol is associated with */ + /* capabilities */ + +/* + * A symbol can only be truly hidden if it is not a capabilities symbol. + */ +#define SYM_IS_HIDDEN(_sdp) \ + (((_sdp)->sd_flags & (FLG_SY_HIDDEN | FLG_SY_CAP)) == FLG_SY_HIDDEN) /* * Create a mask for (sym.st_other & visibility) since the gABI does not yet @@ -1142,7 +1212,7 @@ struct ver_index { const char *vi_name; /* dependency version name */ Half vi_flags; /* communicates availability */ - Half vi_overndx; /* Index asssigned to this version in */ + Half vi_overndx; /* index assigned to this version in */ /* output object Verneed section */ Ver_desc *vi_desc; /* cross reference to descriptor */ };
--- a/usr/src/cmd/sgs/include/rtld.h Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/include/rtld.h Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _RTLD_H @@ -38,6 +38,7 @@ #include <sys/avl.h> #include <alist.h> #include <libc_int.h> +#include <elfcap.h> #ifdef _SYSCALL32 #include <inttypes.h> @@ -59,6 +60,7 @@ typedef struct rt_map Rt_map; typedef struct slookup Slookup; +typedef struct sresult Sresult; /* * A binding descriptor. Establishes the binding relationship between two @@ -666,7 +668,7 @@ * END: Exposed to rtld_db - don't move, don't delete */ APlist *rt_alias; /* list of linked file names */ - APlist *rt_fpnode; /* list of FullpathNode AVL nodes */ + APlist *rt_fpnode; /* list of FullPathNode AVL nodes */ char *rt_runpath; /* LD_RUN_PATH and its equivalent */ Alist *rt_runlist; /* Pdesc structures */ APlist *rt_depends; /* list of dependencies */ @@ -707,8 +709,8 @@ uint_t rt_idx; /* hold index within linkmap list */ uint_t rt_lazy; /* number of lazy dependencies */ /* pending */ - Xword rt_hwcap; /* hardware capabilities */ - Xword rt_sfcap; /* software capabilities */ + Cap *rt_cap; /* capabilities data */ + Capchain *rt_capchain; /* capabilities chain data */ uint_t rt_cntl; /* link-map control list we belong to */ uint_t rt_aflags; /* auditor flags, see LML_TFLG_AUD_ */ /* address of _init */ @@ -716,7 +718,7 @@ /* address of _fini */ void (*rt_fini)(void); /* link map symbol interpreter */ - Sym *(*rt_symintp)(Slookup *, Rt_map **, uint_t *, int *); + int (*rt_symintp)(Slookup *, Sresult *, uint_t *, int *); }; #ifdef _SYSCALL32 @@ -781,8 +783,8 @@ uint32_t rt_relacount; uint32_t rt_idx; uint32_t rt_lazy; - uint32_t rt_hwcap; - uint32_t rt_sfcap; + uint32_t rt_cap; + uint32_t rt_capchain; uint32_t rt_cntl; uint32_t rt_aflags; uint32_t rt_init; @@ -808,7 +810,7 @@ * END: Exposed to rtld_db - don't move, don't delete */ #define FLG_RT_SETGROUP 0x00000008 /* group establishment required */ -#define FLG_RT_HWCAP 0x00000010 /* process $HWCAP expansion */ +#define FLG_RT_CAP 0x00000010 /* process $CAPABILITY expansion */ #define FLG_RT_OBJECT 0x00000020 /* object processing (ie. .o's) */ #define FLG_RT_NEWLOAD 0x00000040 /* object is newly loaded */ #define FLG_RT_NODUMP 0x00000080 /* object can't be dldump(3x)'ed */ @@ -839,13 +841,15 @@ #define FLG_RT_PRIHDL 0x40000000 /* either public or private */ #define FL1_RT_COPYTOOK 0x00000001 /* copy relocation taken */ - -#define FL1_RT_CONFSET 0x00000004 /* object was loaded by crle(1) */ -#define FL1_RT_NODEFLIB 0x00000008 /* ignore default library search */ -#define FL1_RT_ENDFILTE 0x00000010 /* filtee terminates filters search */ -#define FL1_RT_DISPREL 0x00000020 /* object has *disp* relocation */ -#define FL1_RT_DTFLAGS 0x00000040 /* DT_FLAGS element exists */ - +#define FL1_RT_ALTCHECK 0x00000002 /* alternative system capabilities */ + /* checked */ +#define FL1_RT_ALTCAP 0x00000004 /* alternative system capabilities */ + /* should be used */ +#define FL1_RT_CONFSET 0x00000008 /* object was loaded by crle(1) */ +#define FL1_RT_NODEFLIB 0x00000010 /* ignore default library search */ +#define FL1_RT_ENDFILTE 0x00000020 /* filtee terminates filters search */ +#define FL1_RT_DISPREL 0x00000040 /* object has *disp* relocation */ +#define FL1_RT_DTFLAGS 0x00000080 /* DT_FLAGS element exists */ #define FL1_RT_LDDSTUB 0x00000100 /* identify lddstub */ #define FL1_RT_NOINIFIN 0x00000200 /* no .init or .fini exists */ #define FL1_RT_USED 0x00000400 /* symbol referenced from this object */ @@ -965,8 +969,8 @@ #define IDX(X) ((X)->rt_idx) #define LAZY(X) ((X)->rt_lazy) #define CNTL(X) ((X)->rt_cntl) -#define HWCAP(X) ((X)->rt_hwcap) -#define SFCAP(X) ((X)->rt_sfcap) +#define CAP(X) ((X)->rt_cap) +#define CAPCHAIN(X) ((X)->rt_capchain) /* * Flags for tsorting. @@ -1004,6 +1008,7 @@ #define LKUP_STANDARD 0x2000 /* standard lookup - originated from */ /* head link-map element */ #define LKUP_WORLD 0x4000 /* ensure world lookup */ +#define LKUP_DLSYM 0x8000 /* lookup stems from dlsym() request */ /* * For the runtime linker to perform a symbol search, a number of data items @@ -1064,6 +1069,49 @@ sl.sl_flags = (flags)) /* + * After a symbol lookup has been resolved, the runtime linker needs to retain + * information regarding the bound definition. An Sresult data structure is + * used to provide this information. + * + * The symbol name (sr_name) may differ from the original referenced symbol if + * a symbol capabilities family member has resolved the binding. The defining + * object (sr_dmap) indicates the object in which the definition has been found. + * The symbol table entry (sr_sym) defines the bound symbol definition. + * + * Note, a symbol lookup may start with one Sresult buffer, but underlying + * routines (for example, those that probe filters) might employ their own + * Sresult buffer. If a binding is allowed, the latter buffer may get inherited + * by the former. Along with this chain of requests, binding info (binfo) and + * not-found information (in_nfavl), may be passed between all the associated + * functions. Hence, the binfo and in_nfavl data is not maintained as part of + * a Sresult structure. + */ +struct sresult { + const char *sr_name; /* symbol definition name */ + Rt_map *sr_dmap; /* defining objects link-map */ + Sym *sr_sym; /* symbol table pointer */ +}; + +#define SRESULT_INIT(sr, name) \ + (void) (sr.sr_name = (name), sr.sr_dmap = NULL, sr.sr_sym = NULL) + +/* + * Define a system capabilities structure for maintaining the various + * capabilities of the system. This structure follows the Objcapset definition + * from libld.h, however the system can only have one platform or machine + * hardware name, thus this structure is a little simpler. + */ +typedef struct { + elfcap_mask_t sc_hw_1; /* CA_SUNW_HW_1 capabilities */ + elfcap_mask_t sc_sf_1; /* CA_SUNW_SF_1 capabilities */ + elfcap_mask_t sc_hw_2; /* CA_SUNW_HW_2 capabilities */ + char *sc_plat; /* CA_SUNW_PLAT capability */ + size_t sc_platsz; /* and size */ + char *sc_mach; /* CA_SUNW_MACH capability */ + size_t sc_machsz; /* and size */ +} Syscapset; + +/* * Define a number of .plt lookup outcomes, for use in binding diagnostics. */ typedef enum { @@ -1089,7 +1137,7 @@ extern Pltbindtype elf_plt_write(uintptr_t, uintptr_t, void *, uintptr_t, Xword); extern Rt_map *is_so_loaded(Lm_list *, const char *, int *); -extern Sym *lookup_sym(Slookup *, Rt_map **, uint_t *, int *); +extern int lookup_sym(Slookup *, Sresult *, uint_t *, int *); extern int rt_dldump(Rt_map *, const char *, int, Addr); #ifdef __cplusplus
--- a/usr/src/cmd/sgs/include/sgs.h Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/include/sgs.h Mon Mar 01 10:20:48 2010 -0800 @@ -145,6 +145,18 @@ #endif /* + * CTF currently does not handle automatic array variables sized via function + * arguments (VLA arrays) properly, when the code is compiled with gcc. + * Adding 1 to the size is a workaround. VLA_SIZE, and its use, should be + * pulled when CTF is fixed or replaced. + */ +#ifdef __GNUC__ +#define VLA_SIZE(_arg) ((_arg) + 1) +#else +#define VLA_SIZE(_arg) (_arg) +#endif + +/* * 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 @@ -173,8 +185,12 @@ /* 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 */ -#define SGS_REJ_SFCAP_1 13 /* software capabilities mismatch */ +#define SGS_REJ_UNKCAP 12 /* unknown capabilities */ +#define SGS_REJ_HWCAP_1 13 /* hardware capabilities mismatch */ +#define SGS_REJ_SFCAP_1 14 /* software capabilities mismatch */ +#define SGS_REJ_MACHCAP 15 /* machine capability mismatch */ +#define SGS_REJ_PLATCAP 16 /* platform capability mismatch */ +#define SGS_REJ_HWCAP_2 17 /* hardware capabilities mismatch */ #define FLG_REJ_ALTER 0x01 /* object name is an alternative */ @@ -199,29 +215,30 @@ /* * Data structures (defined in libld.h). */ +typedef struct audit_desc Audit_desc; +typedef struct audit_info Audit_info; +typedef struct audit_list Audit_list; +typedef struct cap_desc Cap_desc; 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 os_desc Os_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 sec_order Sec_order; typedef struct sg_desc Sg_desc; typedef struct sort_desc Sort_desc; -typedef struct sec_order Sec_order; +typedef struct sym_avlnode Sym_avlnode; +typedef struct sym_aux Sym_aux; 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.
--- a/usr/src/cmd/sgs/include/sparc/machdep_sparc.h Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/include/sparc/machdep_sparc.h Mon Mar 01 10:20:48 2010 -0800 @@ -229,18 +229,20 @@ #define M_ID_INTERP 0x02 /* SHF_ALLOC */ #define M_ID_CAP 0x03 + #define M_ID_UNWINDHDR 0x06 #define M_ID_UNWIND 0x07 - -#define M_ID_SYMINFO 0x08 -#define M_ID_HASH 0x09 -#define M_ID_LDYNSYM 0x0a /* always right before DYNSYM */ -#define M_ID_DYNSYM 0x0b -#define M_ID_DYNSTR 0x0c -#define M_ID_VERSION 0x0d -#define M_ID_DYNSORT 0x0e -#define M_ID_REL 0x0f -#define M_ID_TEXT 0x10 /* SHF_ALLOC + SHF_EXECINSTR */ +#define M_ID_CAPINFO 0x08 +#define M_ID_CAPCHAIN 0x09 +#define M_ID_SYMINFO 0x0a +#define M_ID_HASH 0x0b +#define M_ID_LDYNSYM 0x0c /* always right before DYNSYM */ +#define M_ID_DYNSYM 0x0d +#define M_ID_DYNSTR 0x0e +#define M_ID_VERSION 0x0f +#define M_ID_DYNSORT 0x10 +#define M_ID_REL 0x11 +#define M_ID_TEXT 0x12 /* SHF_ALLOC + SHF_EXECINSTR */ #define M_ID_DATA 0x20 /* M_ID_USER 0x01 dual entry - listed above */
--- a/usr/src/cmd/sgs/ld/Makefile.com Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/ld/Makefile.com Mon Mar 01 10:20:48 2010 -0800 @@ -20,11 +20,9 @@ # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# PROG = ld @@ -40,7 +38,7 @@ MAPFILES = ../common/mapfile-intf $(MAPFILE.NGB) MAPOPTS = $(MAPFILES:%=-M%) -LDFLAGS += $(VERSREF) $(USE_PROTO) $(MAPOPTS) $(VAR_LD_LLDFLAGS) +LDFLAGS += $(VERSREF) $(CC_USE_PROTO) $(MAPOPTS) $(VAR_LD_LLDFLAGS) LDLIBS += $(LDLIBDIR) $(LD_LIB) $(ELFLIBDIR) -lelf \ $(LDDBGLIBDIR) $(LDDBG_LIB) $(CONVLIBDIR) $(CONV_LIB)
--- a/usr/src/cmd/sgs/ldd/Makefile.com Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/ldd/Makefile.com Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -43,7 +43,7 @@ $(CPPFLAGS.master) LLDFLAGS = '-R$$ORIGIN/../../lib' LLDFLAGS64 = '-R$$ORIGIN/../../../lib/$(MACH64)' -LDFLAGS += $(VERSREF) $(USE_PROTO) $(MAPOPTS) $(LLDFLAGS) +LDFLAGS += $(VERSREF) $(CC_USE_PROTO) $(MAPOPTS) $(LLDFLAGS) LDLIBS += $(CONVLIBDIR) $(CONV_LIB) -lelf $(DLLIB) LINTFLAGS += -x LINTFLAGS64 += -x
--- a/usr/src/cmd/sgs/ldprof/Makefile.com Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/ldprof/Makefile.com Mon Mar 01 10:20:48 2010 -0800 @@ -18,6 +18,7 @@ # # CDDL HEADER END # + # # Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. @@ -38,7 +39,7 @@ MAPFILES = mapfile-vers -DYNFLAGS += $(USE_PROTO) +DYNFLAGS += $(CC_USE_PROTO) CPPFLAGS= -I. -I../common -I../../include \ -I../../rtld/common \ -I../../include/$(MACH) \
--- a/usr/src/cmd/sgs/libconv/common/cap.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libconv/common/cap.c Mon Mar 01 10:20:48 2010 -0800 @@ -36,16 +36,20 @@ const conv_ds_t ** conv_cap_tag_strings(Conv_fmt_flags_t fmt_flags) { -#if (CA_SUNW_NUM != (CA_SUNW_HW_2 + 1)) +#if (CA_SUNW_NUM != (CA_SUNW_ID + 1)) #error "CA_SUNW_NUM has grown" #endif static const Msg tags_cf[] = { MSG_CA_SUNW_NULL_CF, MSG_CA_SUNW_HW_1_CF, - MSG_CA_SUNW_SF_1_CF, MSG_CA_SUNW_HW_2_CF + MSG_CA_SUNW_SF_1_CF, MSG_CA_SUNW_HW_2_CF, + MSG_CA_SUNW_PLAT_CF, MSG_CA_SUNW_MACH_CF, + MSG_CA_SUNW_ID_CF }; static const Msg tags_nf[] = { MSG_CA_SUNW_NULL_NF, MSG_CA_SUNW_HW_1_NF, MSG_CA_SUNW_SF_1_NF, MSG_CA_SUNW_HW_2_NF, + MSG_CA_SUNW_PLAT_NF, MSG_CA_SUNW_MACH_NF, + MSG_CA_SUNW_ID_NF }; static const conv_ds_msg_t ds_tags_cf = { CONV_DS_MSG_INIT(ELFCLASSNONE, tags_cf) }; @@ -108,7 +112,7 @@ } /* - * Iterate the strings for CA_SUNW_HW1 + * Iterate the strings for CA_SUNW_HW. */ conv_iter_ret_t conv_iter_cap_val_hw1(Half mach, Conv_fmt_flags_t fmt_flags, @@ -131,6 +135,14 @@ return (CONV_ITER_CONT); } +conv_iter_ret_t +/* ARGSUSED0 */ +conv_iter_cap_val_hw2(Half mach, Conv_fmt_flags_t fmt_flags, + conv_iter_cb_t func, void *uvalue) +{ + return (CONV_ITER_DONE); +} + /* * Iterate the strings for CA_SUNW_SF1 */
--- a/usr/src/cmd/sgs/libconv/common/cap.msg Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libconv/common/cap.msg Mon Mar 01 10:20:48 2010 -0800 @@ -32,6 +32,12 @@ @ MSG_CA_SUNW_SF_1_NF "sf_1" @ MSG_CA_SUNW_HW_2_CF "CA_SUNW_HW_2" # 3 @ MSG_CA_SUNW_HW_2_NF "hw_2" +@ MSG_CA_SUNW_PLAT_CF "CA_SUNW_PLAT" # 4 +@ MSG_CA_SUNW_PLAT_NF "plat" +@ MSG_CA_SUNW_MACH_CF "CA_SUNW_MACH" # 5 +@ MSG_CA_SUNW_MACH_NF "mach" +@ MSG_CA_SUNW_ID_CF "CA_SUNW_ID" # 6 +@ MSG_CA_SUNW_ID_NF "id" @ MSG_GBL_ZERO "0" @ MSG_GBL_OSQBRKT "0x%llx [ "
--- a/usr/src/cmd/sgs/libconv/common/cap_machelf.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libconv/common/cap_machelf.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -35,7 +35,7 @@ #include "_conv.h" static int -conv_cap_1(Xword val, char *str, size_t len, Half mach, +conv_cap(Xword val, char *str, size_t len, Half mach, Conv_fmt_flags_t fmt_flags, elfcap_to_str_func_t *fptr) { size_t _len; @@ -75,20 +75,33 @@ if (val == 0) return (MSG_ORIG(MSG_GBL_ZERO)); - if (conv_cap_1(val, cap_val_hw1_buf->buf, sizeof (cap_val_hw1_buf->buf), + if (conv_cap(val, cap_val_hw1_buf->buf, sizeof (cap_val_hw1_buf->buf), mach, fmt_flags, elfcap_hw1_to_str) == 0) return (conv_invalid_val(&cap_val_hw1_buf->inv_buf, val, 0)); return ((const char *)cap_val_hw1_buf->buf); } const char * +conv_cap_val_hw2(Xword val, Half mach, Conv_fmt_flags_t fmt_flags, + Conv_cap_val_hw2_buf_t *cap_val_hw2_buf) +{ + if (val == 0) + return (MSG_ORIG(MSG_GBL_ZERO)); + + if (conv_cap(val, cap_val_hw2_buf->buf, sizeof (cap_val_hw2_buf->buf), + mach, fmt_flags, elfcap_hw2_to_str) == 0) + return (conv_invalid_val(&cap_val_hw2_buf->inv_buf, val, 0)); + return ((const char *)cap_val_hw2_buf->buf); +} + +const char * conv_cap_val_sf1(Xword val, Half mach, Conv_fmt_flags_t fmt_flags, Conv_cap_val_sf1_buf_t *cap_val_sf1_buf) { if (val == 0) return (MSG_ORIG(MSG_GBL_ZERO)); - if (conv_cap_1(val, cap_val_sf1_buf->buf, sizeof (cap_val_sf1_buf->buf), + if (conv_cap(val, cap_val_sf1_buf->buf, sizeof (cap_val_sf1_buf->buf), mach, fmt_flags, elfcap_sf1_to_str) == 0) return (conv_invalid_val(&cap_val_sf1_buf->inv_buf, val, 0)); return ((const char *)cap_val_sf1_buf->buf); @@ -115,14 +128,23 @@ } const char * -conv_cap_val(Xword tag, Xword val, Half mach, Conv_cap_val_buf_t *cap_val_buf) +conv_cap_val(Xword tag, Xword val, Half mach, Conv_fmt_flags_t fmt_flags, + Conv_cap_val_buf_t *cap_val_buf) { - if (tag == CA_SUNW_HW_1) - return (conv_cap_val_hw1(val, mach, 0, + switch (tag) { + case CA_SUNW_HW_1: + return (conv_cap_val_hw1(val, mach, fmt_flags, &cap_val_buf->cap_val_hw1_buf)); - else if (tag == CA_SUNW_SF_1) - return (conv_cap_val_sf1(val, mach, 0, + + case CA_SUNW_SF_1: + return (conv_cap_val_sf1(val, mach, fmt_flags, &cap_val_buf->cap_val_sf1_buf)); - else + + case CA_SUNW_HW_2: + return (conv_cap_val_hw2(val, mach, fmt_flags, + &cap_val_buf->cap_val_hw2_buf)); + + default: return (conv_invalid_val(&cap_val_buf->inv_buf, val, 0)); + } }
--- a/usr/src/cmd/sgs/libconv/common/dynamic.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libconv/common/dynamic.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -548,9 +548,11 @@ MSG_DT_SUNW_SYMTAB_CF, MSG_DT_SUNW_SYMSZ_CF, MSG_DT_SUNW_SORTENT_CF, MSG_DT_SUNW_SYMSORT_CF, MSG_DT_SUNW_SYMSORTSZ_CF, MSG_DT_SUNW_TLSSORT_CF, - MSG_DT_SUNW_TLSSORTSZ_CF, 0, - MSG_DT_SUNW_STRPAD_CF, 0, - MSG_DT_SUNW_LDMACH_CF + MSG_DT_SUNW_TLSSORTSZ_CF, MSG_DT_SUNW_CAPINFO_CF, + MSG_DT_SUNW_STRPAD_CF, MSG_DT_SUNW_CAPCHAIN_CF, + MSG_DT_SUNW_LDMACH_CF, 0, + MSG_DT_SUNW_CAPCHAINENT_CF, 0, + MSG_DT_SUNW_CAPCHAINSZ_CF }; static const Msg tags_sunw_auxiliary_cfnp[] = { MSG_DT_SUNW_AUXILIARY_CFNP, MSG_DT_SUNW_RTLDINF_CFNP, @@ -558,9 +560,11 @@ MSG_DT_SUNW_SYMTAB_CFNP, MSG_DT_SUNW_SYMSZ_CFNP, MSG_DT_SUNW_SORTENT_CFNP, MSG_DT_SUNW_SYMSORT_CFNP, MSG_DT_SUNW_SYMSORTSZ_CFNP, MSG_DT_SUNW_TLSSORT_CFNP, - MSG_DT_SUNW_TLSSORTSZ_CFNP, 0, - MSG_DT_SUNW_STRPAD_CFNP, 0, - MSG_DT_SUNW_LDMACH_CFNP + MSG_DT_SUNW_TLSSORTSZ_CFNP, MSG_DT_SUNW_CAPINFO_CFNP, + MSG_DT_SUNW_STRPAD_CFNP, MSG_DT_SUNW_CAPCHAIN_CFNP, + MSG_DT_SUNW_LDMACH_CFNP, 0, + MSG_DT_SUNW_CAPCHAINENT_CFNP, 0, + MSG_DT_SUNW_CAPCHAINSZ_CFNP }; static const Msg tags_sunw_auxiliary_nf[] = { MSG_DT_SUNW_AUXILIARY_NF, MSG_DT_SUNW_RTLDINF_NF, @@ -568,9 +572,11 @@ MSG_DT_SUNW_SYMTAB_NF, MSG_DT_SUNW_SYMSZ_NF, MSG_DT_SUNW_SORTENT_NF, MSG_DT_SUNW_SYMSORT_NF, MSG_DT_SUNW_SYMSORTSZ_NF, MSG_DT_SUNW_TLSSORT_NF, - MSG_DT_SUNW_TLSSORTSZ_NF, 0, - MSG_DT_SUNW_STRPAD_NF, 0, - MSG_DT_SUNW_LDMACH_NF + MSG_DT_SUNW_TLSSORTSZ_NF, MSG_DT_SUNW_CAPINFO_NF, + MSG_DT_SUNW_STRPAD_NF, MSG_DT_SUNW_CAPCHAIN_NF, + MSG_DT_SUNW_LDMACH_NF, 0, + MSG_DT_SUNW_CAPCHAINENT_NF, 0, + MSG_DT_SUNW_CAPCHAINSZ_NF }; static const conv_ds_msg_t ds_sunw_auxiliary_cf = { CONV_DS_MSG_INIT(DT_SUNW_AUXILIARY, tags_sunw_auxiliary_cf) };
--- a/usr/src/cmd/sgs/libconv/common/dynamic.msg Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libconv/common/dynamic.msg Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -161,12 +161,25 @@ @ MSG_DT_SUNW_TLSSORTSZ_CF "DT_SUNW_TLSSORTSZ" # 0x60000017 @ MSG_DT_SUNW_TLSSORTSZ_CFNP "SUNW_TLSSORTSZ" @ MSG_DT_SUNW_TLSSORTSZ_NF "sunw_tlssortsz" +@ MSG_DT_SUNW_CAPINFO_CF "DT_SUNW_CAPINFO" # 0x60000018 +@ MSG_DT_SUNW_CAPINFO_CFNP "SUNW_CAPINFO" +@ MSG_DT_SUNW_CAPINFO_NF "sunw_capinfo" @ MSG_DT_SUNW_STRPAD_CF "DT_SUNW_STRPAD" # 0x60000019 @ MSG_DT_SUNW_STRPAD_CFNP "SUNW_STRPAD" @ MSG_DT_SUNW_STRPAD_NF "sunw_strpad" +@ MSG_DT_SUNW_CAPCHAIN_CF "DT_SUNW_CAPCHAIN" # 0x6000001a +@ MSG_DT_SUNW_CAPCHAIN_CFNP "SUNW_CAPCHAIN" +@ MSG_DT_SUNW_CAPCHAIN_NF "sunw_capchain" @ MSG_DT_SUNW_LDMACH_CF "DT_SUNW_LDMACH" # 0x6000001b @ MSG_DT_SUNW_LDMACH_CFNP "SUNW_LDMACH" @ MSG_DT_SUNW_LDMACH_NF "sunw_ldmach" +@ MSG_DT_SUNW_CAPCHAINENT_CF "DT_SUNW_CAPCHAINENT" # 0x6000001d +@ MSG_DT_SUNW_CAPCHAINENT_CFNP "SUNW_CAPCHAINENT" +@ MSG_DT_SUNW_CAPCHAINENT_NF "sunw_capchainent" +@ MSG_DT_SUNW_CAPCHAINSZ_CF "DT_SUNW_CAPCHAINSZ" # 0x6000001d +@ MSG_DT_SUNW_CAPCHAINSZ_CFNP "SUNW_CAPCHAINSZ" +@ MSG_DT_SUNW_CAPCHAINSZ_NF "sunw_capchainsz" + @ MSG_DT_GNU_PRELINKED_CF "DT_GNU_PRELINKED" # 0x6ffffdf5 @ MSG_DT_GNU_PRELINKED_CFNP "GNU_PRELINKED" @ MSG_DT_GNU_PRELINKED_NF "gnu_prelinked"
--- a/usr/src/cmd/sgs/libconv/common/elf.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libconv/common/elf.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -954,6 +954,9 @@ case SGS_REJ_STR: case SGS_REJ_HWCAP_1: case SGS_REJ_SFCAP_1: + case SGS_REJ_HWCAP_2: + case SGS_REJ_MACHCAP: + case SGS_REJ_PLATCAP: if (rej->rej_str) return ((const char *)rej->rej_str); else
--- a/usr/src/cmd/sgs/libconv/common/llib-lconv Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libconv/common/llib-lconv Mon Mar 01 10:20:48 2010 -0800 @@ -187,6 +187,8 @@ conv_iter_ret_t conv_iter_cap_tags(Conv_fmt_flags_t, conv_iter_cb_t, void *); conv_iter_ret_t conv_iter_cap_val_hw1(Half, Conv_fmt_flags_t, conv_iter_cb_t, void *); +conv_iter_ret_t conv_iter_cap_val_hw2(Half, Conv_fmt_flags_t, + conv_iter_cb_t, void *); conv_iter_ret_t conv_iter_cap_val_sf1(Conv_fmt_flags_t, conv_iter_cb_t, void *); conv_iter_ret_t conv_iter_dyn_feature1(Conv_fmt_flags_t, @@ -256,13 +258,17 @@ const char *conv64_cap_tag(Elf64_Xword, Conv_fmt_flags_t, Conv_inv_buf_t *); const char *conv32_cap_val(Elf32_Word, Elf32_Word, Half, - Conv_cap_val_buf_t *); + Conv_fmt_flags_t, Conv_cap_val_buf_t *); const char *conv64_cap_val(Elf64_Xword, Elf64_Xword, Half, - Conv_cap_val_buf_t *); + Conv_fmt_flags_t, Conv_cap_val_buf_t *); const char *conv32_cap_val_hw1(Elf32_Word, Half, Conv_fmt_flags_t, Conv_cap_val_hw1_buf_t *); +const char *conv32_cap_val_hw2(Elf32_Word, Half, Conv_fmt_flags_t, + Conv_cap_val_hw2_buf_t *); const char *conv64_cap_val_hw1(Elf64_Xword, Half, Conv_fmt_flags_t, Conv_cap_val_hw1_buf_t *); +const char *conv64_cap_val_hw2(Elf64_Xword, Half, Conv_fmt_flags_t, + Conv_cap_val_hw2_buf_t *); const char *conv32_cap_val_sf1(Elf32_Word, Half, Conv_fmt_flags_t, Conv_cap_val_sf1_buf_t *); const char *conv64_cap_val_sf1(Elf64_Xword, Half, Conv_fmt_flags_t,
--- a/usr/src/cmd/sgs/libconv/common/sections.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libconv/common/sections.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -106,6 +106,7 @@ static const Msg usecs_def[SHT_HISUNW - SHT_LOSUNW + 1] = { + MSG_SHT_SUNW_CAPCHAIN, MSG_SHT_SUNW_CAPINFO, MSG_SHT_SUNW_SYMSORT, MSG_SHT_SUNW_TLSSORT, MSG_SHT_SUNW_LDYNSYM, MSG_SHT_SUNW_DOF, MSG_SHT_SUNW_CAP, MSG_SHT_SUNW_SIGNATURE, @@ -116,6 +117,7 @@ MSG_SHT_SUNW_VERSYM }; static const Msg usecs_dmp[SHT_HISUNW - SHT_LOSUNW + 1] = { + MSG_SHT_SUNW_CAPCHAIN_DMP, MSG_SHT_SUNW_CAPINFO_DMP, MSG_SHT_SUNW_SYMSORT_DMP, MSG_SHT_SUNW_TLSSORT_DMP, MSG_SHT_SUNW_LDYNSYM_DMP, MSG_SHT_SUNW_DOF_DMP, MSG_SHT_SUNW_CAP_DMP, MSG_SHT_SUNW_SIGNATURE_DMP, @@ -126,6 +128,7 @@ MSG_SHT_SUNW_VERSYM_DMP }; static const Msg usecs_cf[SHT_HISUNW - SHT_LOSUNW + 1] = { + MSG_SHT_SUNW_CAPCHAIN_CF, MSG_SHT_SUNW_CAPINFO_CF, MSG_SHT_SUNW_SYMSORT_CF, MSG_SHT_SUNW_TLSSORT_CF, MSG_SHT_SUNW_LDYNSYM_CF, MSG_SHT_SUNW_DOF_CF, MSG_SHT_SUNW_CAP_CF, MSG_SHT_SUNW_SIGNATURE_CF, @@ -136,6 +139,7 @@ MSG_SHT_SUNW_VERSYM_CF }; static const Msg usecs_nf[SHT_HISUNW - SHT_LOSUNW + 1] = { + MSG_SHT_SUNW_CAPCHAIN_NF, MSG_SHT_SUNW_CAPINFO_NF, MSG_SHT_SUNW_SYMSORT_NF, MSG_SHT_SUNW_TLSSORT_NF, MSG_SHT_SUNW_LDYNSYM_NF, MSG_SHT_SUNW_DOF_NF, MSG_SHT_SUNW_CAP_NF, MSG_SHT_SUNW_SIGNATURE_NF, @@ -145,17 +149,17 @@ MSG_SHT_SUNW_VERDEF_NF, MSG_SHT_SUNW_VERNEED_NF, MSG_SHT_SUNW_VERSYM_NF }; -#if (SHT_LOSUNW != SHT_SUNW_symsort) +#if (SHT_LOSUNW != SHT_SUNW_capchain) #error "SHT_LOSUNW has moved" #endif static const conv_ds_msg_t ds_usecs_def = { - CONV_DS_MSG_INIT(SHT_SUNW_symsort, usecs_def) }; + CONV_DS_MSG_INIT(SHT_SUNW_capchain, usecs_def) }; static const conv_ds_msg_t ds_usecs_dmp = { - CONV_DS_MSG_INIT(SHT_SUNW_symsort, usecs_dmp) }; + CONV_DS_MSG_INIT(SHT_SUNW_capchain, usecs_dmp) }; static const conv_ds_msg_t ds_usecs_cf = { - CONV_DS_MSG_INIT(SHT_SUNW_symsort, usecs_cf) }; + CONV_DS_MSG_INIT(SHT_SUNW_capchain, usecs_cf) }; static const conv_ds_msg_t ds_usecs_nf = { - CONV_DS_MSG_INIT(SHT_SUNW_symsort, usecs_nf) }; + CONV_DS_MSG_INIT(SHT_SUNW_capchain, usecs_nf) }; /* The Linux osabi range has two separate sequences */
--- a/usr/src/cmd/sgs/libconv/common/sections.msg Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libconv/common/sections.msg Mon Mar 01 10:20:48 2010 -0800 @@ -1,5 +1,5 @@ # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # CDDL HEADER START @@ -100,6 +100,14 @@ @ MSG_SHT_SYMTAB_SHNDX_CF "SHT_SYMTAB_SHNDX" @ MSG_SHT_SYMTAB_SHNDX_NF "symtab_shndx" +@ MSG_SHT_SUNW_CAPCHAIN "[ SHT_SUNW_capchain ]" # 0x6fffffef +@ MSG_SHT_SUNW_CAPCHAIN_DMP "CAPCHAIN " +@ MSG_SHT_SUNW_CAPCHAIN_CF "SHT_SUNW_capchain" +@ MSG_SHT_SUNW_CAPCHAIN_NF "sunw_capchain" +@ MSG_SHT_SUNW_CAPINFO "[ SHT_SUNW_capinfo ]" # 0x6ffffff0 +@ MSG_SHT_SUNW_CAPINFO_DMP "CAPINFO " +@ MSG_SHT_SUNW_CAPINFO_CF "SHT_SUNW_capinfo" +@ MSG_SHT_SUNW_CAPINFO_NF "sunw_capinfo" @ MSG_SHT_SUNW_SYMSORT "[ SHT_SUNW_symsort ]" # 0x6ffffff1 @ MSG_SHT_SUNW_SYMSORT_DMP "SSRT" @ MSG_SHT_SUNW_SYMSORT_CF "SHT_SUNW_symsort"
--- a/usr/src/cmd/sgs/libconv/common/syminfo.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libconv/common/syminfo.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -73,6 +73,7 @@ { SYMINFO_FLG_NOEXTDIRECT, MSG_SYMINFO_FLG_NOEXTDIRECT_CF }, { SYMINFO_FLG_AUXILIARY, MSG_SYMINFO_FLG_AUXILIARY_CF }, { SYMINFO_FLG_INTERPOSE, MSG_SYMINFO_FLG_INTERPOSE_CF }, + { SYMINFO_FLG_CAP, MSG_SYMINFO_FLG_CAP_CF }, { 0 } }; static const Val_desc vda_cfnp[] = { @@ -84,6 +85,7 @@ { SYMINFO_FLG_NOEXTDIRECT, MSG_SYMINFO_FLG_NOEXTDIRECT_CFNP }, { SYMINFO_FLG_AUXILIARY, MSG_SYMINFO_FLG_AUXILIARY_CFNP }, { SYMINFO_FLG_INTERPOSE, MSG_SYMINFO_FLG_INTERPOSE_CFNP }, + { SYMINFO_FLG_CAP, MSG_SYMINFO_FLG_CAP_CFNP }, { 0 } }; static const Val_desc vda_nf[] = { @@ -95,6 +97,7 @@ { SYMINFO_FLG_NOEXTDIRECT, MSG_SYMINFO_FLG_NOEXTDIRECT_NF }, { SYMINFO_FLG_AUXILIARY, MSG_SYMINFO_FLG_AUXILIARY_NF }, { SYMINFO_FLG_INTERPOSE, MSG_SYMINFO_FLG_INTERPOSE_NF }, + { SYMINFO_FLG_CAP, MSG_SYMINFO_FLG_CAP_NF }, { 0 } };
--- a/usr/src/cmd/sgs/libconv/common/syminfo.msg Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libconv/common/syminfo.msg Mon Mar 01 10:20:48 2010 -0800 @@ -19,34 +19,37 @@ # CDDL HEADER END # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -@ MSG_SYMINFO_FLG_DIRECT_CF "SYMINFO_FLG_DIRECT" # 0x01 +@ MSG_SYMINFO_FLG_DIRECT_CF "SYMINFO_FLG_DIRECT" # 0x001 @ MSG_SYMINFO_FLG_DIRECT_CFNP "DIRECT" @ MSG_SYMINFO_FLG_DIRECT_NF "direct" -@ MSG_SYMINFO_FLG_FILTER_CF "SYMINFO_FLG_FILTER" # 0x02 +@ MSG_SYMINFO_FLG_FILTER_CF "SYMINFO_FLG_FILTER" # 0x002 @ MSG_SYMINFO_FLG_FILTER_CFNP "FILTER" @ MSG_SYMINFO_FLG_FILTER_NF "filter" -@ MSG_SYMINFO_FLG_COPY_CF "SYMINFO_FLG_COPY" # 0x04 +@ MSG_SYMINFO_FLG_COPY_CF "SYMINFO_FLG_COPY" # 0x004 @ MSG_SYMINFO_FLG_COPY_CFNP "COPY" @ MSG_SYMINFO_FLG_COPY_NF "copy" -@ MSG_SYMINFO_FLG_LAZYLOAD_CF "SYMINFO_FLG_LAZYLOAD" # 0x08 +@ MSG_SYMINFO_FLG_LAZYLOAD_CF "SYMINFO_FLG_LAZYLOAD" # 0x008 @ MSG_SYMINFO_FLG_LAZYLOAD_CFNP "LAZYLOAD" @ MSG_SYMINFO_FLG_LAZYLOAD_NF "lazyload" -@ MSG_SYMINFO_FLG_DIRECTBIND_CF "SYMINFO_FLG_DIRECTBIND" # 0x10 +@ MSG_SYMINFO_FLG_DIRECTBIND_CF "SYMINFO_FLG_DIRECTBIND" # 0x010 @ MSG_SYMINFO_FLG_DIRECTBIND_CFNP "DIRECTBIND" @ MSG_SYMINFO_FLG_DIRECTBIND_NF "directbind" -@ MSG_SYMINFO_FLG_NOEXTDIRECT_CF "SYMINFO_FLG_NOEXTDIRECT" # 0x20 +@ MSG_SYMINFO_FLG_NOEXTDIRECT_CF "SYMINFO_FLG_NOEXTDIRECT" # 0x020 @ MSG_SYMINFO_FLG_NOEXTDIRECT_CFNP "NOEXTDIRECT" @ MSG_SYMINFO_FLG_NOEXTDIRECT_NF "noextdirect" -@ MSG_SYMINFO_FLG_AUXILIARY_CF "SYMINFO_FLG_AUXILIARY" # 0x40 +@ MSG_SYMINFO_FLG_AUXILIARY_CF "SYMINFO_FLG_AUXILIARY" # 0x040 @ MSG_SYMINFO_FLG_AUXILIARY_CFNP "AUXILIARY" @ MSG_SYMINFO_FLG_AUXILIARY_NF "auxiliary" -@ MSG_SYMINFO_FLG_INTERPOSE_CF "SYMINFO_FLG_INTERPOSE" # 0x80 +@ MSG_SYMINFO_FLG_INTERPOSE_CF "SYMINFO_FLG_INTERPOSE" # 0x080 @ MSG_SYMINFO_FLG_INTERPOSE_CFNP "INTERPOSE" @ MSG_SYMINFO_FLG_INTERPOSE_NF "interpose" +@ MSG_SYMINFO_FLG_CAP_CF "SYMINFO_FLG_CAP" # 0x100 +@ MSG_SYMINFO_FLG_CAP_CFNP "CAP" +@ MSG_SYMINFO_FLG_CAP_NF "cap" @ MSG_SYMINFO_BT_EXTERN_CF "SYMINFO_BT_EXTERN" # 0xfffc @ MSG_SYMINFO_BT_EXTERN_CFNP "EXTERN"
--- a/usr/src/cmd/sgs/libcrle/Makefile.com Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libcrle/Makefile.com Mon Mar 01 10:20:48 2010 -0800 @@ -18,8 +18,9 @@ # # CDDL HEADER END # + # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -44,7 +45,7 @@ LINTFLAGS64 += -u CPPFLAGS += -I$(SRCBASE)/lib/libc/inc -I$(SRC)/common/sgsrtcid -DYNFLAGS += $(VERSREF) $(CONVLIBDIR) -lconv $(USE_PROTO) +DYNFLAGS += $(VERSREF) $(CONVLIBDIR) -lconv $(CC_USE_PROTO) BLTDEFS= msg.h
--- a/usr/src/cmd/sgs/libelf/common/xlate.m4 Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libelf/common/xlate.m4 Mon Mar 01 10:20:48 2010 -0800 @@ -20,12 +20,9 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - -#pragma ident "%Z%%M% %I% %E% SMI" - #include <memory.h> #include <libelf.h> #include <link.h> @@ -35,7 +32,6 @@ #include <msg.h> #include <sgs.h> - /* * fmsize: Array used to determine what size the the structures * are (for memory image & file image). @@ -722,6 +718,10 @@ return (ELF_T_BYTE); case SHT_SUNW_cap: return (ELF_T_CAP); + case SHT_SUNW_capchain: + return (ELF_T_WORD); + case SHT_SUNW_capinfo: + return (ELF_T_WORD); case SHT_SUNW_SIGNATURE: return (ELF_T_BYTE); case SHT_SUNW_ANNOTATE:
--- a/usr/src/cmd/sgs/libelf/common/xlate64.m4 Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libelf/common/xlate64.m4 Mon Mar 01 10:20:48 2010 -0800 @@ -20,12 +20,9 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - -#pragma ident "%Z%%M% %I% %E% SMI" - #include <memory.h> #include <libelf.h> #include <link.h> @@ -35,7 +32,6 @@ #include <msg.h> #include <sgs.h> - /* * fmsize: Array used to determine what size the the structures * are (for memory image & file image). @@ -779,6 +775,10 @@ return (ELF_T_BYTE); case SHT_SUNW_cap: return (ELF_T_CAP); + case SHT_SUNW_capchain: + return (ELF_T_WORD); + case SHT_SUNW_capinfo: + return (ELF_T_XWORD); case SHT_SUNW_SIGNATURE: return (ELF_T_BYTE); case SHT_SUNW_ANNOTATE:
--- a/usr/src/cmd/sgs/libld/Makefile.com Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libld/Makefile.com Mon Mar 01 10:20:48 2010 -0800 @@ -18,6 +18,7 @@ # # CDDL HEADER END # + # # Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. @@ -103,7 +104,7 @@ LINTFLAGS += -u -D_REENTRANT LINTFLAGS64 += -u -D_REENTRANT -DYNFLAGS += $(VERSREF) $(USE_PROTO) '-R$$ORIGIN' +DYNFLAGS += $(VERSREF) $(CC_USE_PROTO) '-R$$ORIGIN' native:= DYNFLAGS += $(CONVLIBDIR)
--- a/usr/src/cmd/sgs/libld/common/_libld.h Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libld/common/_libld.h Mon Mar 01 10:20:48 2010 -0800 @@ -113,6 +113,8 @@ Word id_array; Word id_bss; Word id_cap; + Word id_capinfo; + Word id_capchain; Word id_data; Word id_dynamic; Word id_dynsort; @@ -168,11 +170,11 @@ * target architecture, it may be desirable to instead fill with executable * NOP instructions. There are two reasons to do this: * - * - So that .init/.fini sections will not contain unexecutable gaps + * - So that .init/.fini sections will not contain unexecutable gaps * that cause the executing program to trap and die. * - * - To eliminate confusing garbage instructions between sections containing - * executable code when viewed with a dissassembler. + * - To eliminate confusing garbage instructions between sections containing + * executable code when viewed with a disassembler. * * The ff_execfill function is allowed to be NULL if the underlying target * does not require a special fill for executable sections. @@ -330,11 +332,88 @@ } Sfltr_desc; /* + * Capabilities descriptor, and capabilities group descriptor, used to track + * the symbol capabilities of any input files and the output file. + * + * A relocatable object input file may contain one or more symbol capabilities + * groups. The Cap_desc structures keep track of all unique groups that are + * collected for the output file. Relocatable objects that contain an object + * capabilities group, and the -z symbolcap option is in effect, have their + * object group translated to a symbol capabilities group. + * + * Individual capabilities groups are maintained with the Cap_group descriptor. + * A group can consist of one or more capabilities definitions. One or more + * symbols can be associated with each group. + * + * For the output file, capabilities families are used to track the symbols of + * a given family, each symbol being associated with a different group. This + * collection of data is used to create the final Capinfo structure, and for + * dynamic objects, the Capchain structure. + * + * For example, an object may contain two capabilities groups: + * + * CA_SUNW_MACH - sun4u CA_SUNW_MACH - sun4v + * + * Two symbols can be associated with each group: + * + * foo%sun4u foo%sun4v + * bar%sun4u bar%sun4v + * + * Two families are maintained, and include the generic, or lead, instance of + * the capabilities members: + * + * foo, foo%sun4u, foo%sun4v + * bar, bar%sun4u, bar%sun4v + */ +struct cap_desc { + APlist *ca_groups; /* capabilities groups (Cap_group) */ + APlist *ca_syms; /* copies of symbols that are being */ + /* translated from object to */ +}; /* symbol capabilities */ + +typedef struct { + Objcapset cg_set; /* unpacked SHT_SUNW_cap elements */ + APlist *cg_secs; /* sections, and hence files, that */ + /* use this descriptor */ + Word cg_num; /* number of comparable elements in */ + /* the group */ + Word cg_ndx; /* final capability group index */ +} Cap_group; + +/* + * A Capabilities family node, extends a symbol node, and provides for tracking + * capabilities families. A family is defined by its lead symbol (for example, + * a generic, non-capabilities aware foo()), and one or more capabilities + * members (for example, capabilities instances foo%sun4u(), foo%sun4v(), etc.). + * + * Each member associates a symbol with its group using a Cap_sym structure. + */ +typedef struct { + Sym_avlnode cn_symavlnode; + APlist *cn_members; + APlist *cn_aliases; +} Cap_avlnode; + +typedef struct { + Sym_desc *cs_sdp; /* capabilities symbol descriptor */ + Cap_group *cs_group; /* associated capabilities group */ +} Cap_sym; + +/* * Define Alist initialization sizes. */ #define AL_CNT_IFL_GROUPS 20 /* ifl_groups */ #define AL_CNT_IFL_RELSECS 6 /* ifl_relsect */ +#define AL_CNT_CAP_DESCS 4 /* symbol capabilities descriptors */ +#define AL_CNT_CAP_SYMS 20 /* capabilities symbols */ +#define AL_CNT_CAP_SECS 10 /* capabilities sections */ +#define AL_CNT_CAP_NAMES 10 /* Objcapset platform and machine */ + /* names */ +#define AL_CNT_CAP_MEMS 10 /* capability family members */ +#define AL_CNT_CAP_PAIRS 10 /* capability symbol pairs */ +#define AL_CNT_CAP_ALIASES 2 /* capability lead symbol aliases */ + #define AL_CNT_OFL_DTSFLTRS 4 /* ofl_dtsfltrs */ #define AL_CNT_OFL_SYMFLTRS 20 /* ofl_symfltrs */ #define AL_CNT_OFL_MAPSECS 10 /* ofl_map{text|data} */ @@ -582,6 +661,7 @@ */ extern char *add_string(char *, char *); extern const char *demangle(const char *); +extern int cap_names_match(Alist *, Alist *); extern void lds_atexit(Ofl_desc *, int); @@ -606,6 +686,8 @@ #define ld_assign_got_TLS ld64_assign_got_TLS #define ld_bswap_Word ld64_bswap_Word #define ld_bswap_Xword ld64_bswap_Xword +#define ld_cap_add_family ld64_cap_add_family +#define ld_cap_move_symtoobj ld64_cap_move_symtoobj #define ld_disp_errmsg ld64_disp_errmsg #define ld_ent_check ld64_ent_check #define ld_ent_lookup ld64_ent_lookup @@ -697,6 +779,8 @@ #define ld_assign_got_TLS ld32_assign_got_TLS #define ld_bswap_Word ld32_bswap_Word #define ld_bswap_Xword ld32_bswap_Xword +#define ld_cap_add_family ld32_cap_add_family +#define ld_cap_move_symtoobj ld32_cap_move_symtoobj #define ld_disp_errmsg ld32_disp_errmsg #define ld_ent_check ld32_ent_check #define ld_ent_lookup ld32_ent_lookup @@ -797,6 +881,10 @@ extern Word ld_bswap_Word(Word); extern Xword ld_bswap_Xword(Xword); +extern uintptr_t ld_cap_add_family(Ofl_desc *, Sym_desc *, Sym_desc *, + Cap_group *, APlist **); +extern void ld_cap_move_symtoobj(Ofl_desc *); + extern void ld_disp_errmsg(const char *, Rel_desc *, Ofl_desc *); extern void ld_ent_check(Ofl_desc *);
--- a/usr/src/cmd/sgs/libld/common/_map.h Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libld/common/_map.h Mon Mar 01 10:20:48 2010 -0800 @@ -330,7 +330,7 @@ * Support code shared between the different mapfile parsing code, used to * provide a common implementation manipulating link-editor state. */ -extern Boolean ld_map_cap_sanitize(Mapfile *, Word, CapMask *); +extern Boolean ld_map_cap_sanitize(Mapfile *, Word, Capmask *); extern void ld_map_cap_set_ovflag(Mapfile *, Word); extern void *ld_map_kwfind(const char *, void *, size_t, size_t); extern char *ld_map_kwnames(void *, size_t, size_t, char *, size_t);
--- a/usr/src/cmd/sgs/libld/common/args.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libld/common/args.c Mon Mar 01 10:20:48 2010 -0800 @@ -208,6 +208,7 @@ (void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZRS)); (void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZRSN)); (void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZRSGRP)); + (void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZSCAP)); (void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZTARG)); (void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZT)); (void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZTO)); @@ -305,6 +306,18 @@ ofl->ofl_flags |= FLG_OF_RELOBJ; } else { /* + * Translating object capabilities to symbol capabilities is + * only meaningful when creating a relocatable object. + */ + if (ofl->ofl_flags & FLG_OF_OTOSCAP) { + eprintf(ofl->ofl_lml, ERR_FATAL, + MSG_INTL(MSG_MARG_ONLY), + MSG_ORIG(MSG_ARG_ZSYMBOLCAP), + MSG_INTL(MSG_MARG_REL)); + ofl->ofl_flags |= FLG_OF_FATAL; + } + + /* * If the user hasn't explicitly requested that relocations * not be combined, combine them by default. */ @@ -1249,6 +1262,9 @@ } else if (strcmp(optarg, MSG_ORIG(MSG_ARG_NOSIGHANDLER)) == 0) { ofl->ofl_flags1 |= FLG_OF1_NOSGHND; + } else if (strcmp(optarg, + MSG_ORIG(MSG_ARG_SYMBOLCAP)) == 0) { + ofl->ofl_flags |= FLG_OF_OTOSCAP; /* * Check archive group usage
--- a/usr/src/cmd/sgs/libld/common/entry.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libld/common/entry.c Mon Mar 01 10:20:48 2010 -0800 @@ -193,38 +193,61 @@ * As with the segment descriptors, the EC_DESC_INIT macro is used * to reduce boilerplate clutter. */ -#define EC_DESC_INIT(ec_type, ec_attrmask, ec_attrbits, _seg_field, ec_flags) \ - { NULL, NULL, NULL, ec_type, ec_attrmask, ec_attrbits, \ +#define EC_DESC_INIT(ec_is_name, ec_type, ec_attrmask, ec_attrbits, \ + _seg_field, ec_flags) \ + { NULL, NULL, ec_is_name, ec_type, ec_attrmask, ec_attrbits, \ &sg_desc.psg_ ## _seg_field, 0, FLG_EC_BUILTIN | ec_flags } static const Ent_desc ent_desc[] = { - EC_DESC_INIT(SHT_NOTE, 0, 0, note, 0), - + EC_DESC_INIT(NULL, SHT_NOTE, 0, 0, note, 0), #if defined(_ELF64) /* (amd64-only) */ - EC_DESC_INIT(0, SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, + EC_DESC_INIT(NULL, 0, SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, SHF_ALLOC + SHF_AMD64_LARGE, lrodata, 0), #endif - EC_DESC_INIT(0, SHF_ALLOC + SHF_WRITE, SHF_ALLOC, text, 0), + EC_DESC_INIT(NULL, 0, SHF_ALLOC + SHF_WRITE, SHF_ALLOC, text, 0), - EC_DESC_INIT(SHT_NOBITS, SHF_ALLOC + SHF_WRITE, SHF_ALLOC + SHF_WRITE, - bss, 0), + /* + * Explicitly assign the .tdata section to bss. The design of TLS + * provides for initialized data being assigned to a .tdata section, + * and uninitialized data being assigned to a .tbss section. These + * sections should be laid out adjacent to each other, with little or + * no gap between them. A PT_TLS program header is created that + * defines the address range of the two sections. This header is + * passed to libc to instantiate the appropriate thread allocation. + * + * By default a separate bss segment is disabled, however users can + * trigger the creation of a bss segment with a mapfile. By default, + * all bss sections are assigned to the data segment, and the section + * identifiers of .tdata and .tbss ensure that these two sections are + * adjacent to each other. + * + * However, if a bss segment is enabled, the adjacency of the .tdata + * and .tbss sections can only be retained by having an explicit .tdata + * entrance criteria. + */ + EC_DESC_INIT(MSG_ORIG(MSG_SCN_TDATA), 0, SHF_ALLOC + SHF_WRITE, + SHF_ALLOC + SHF_WRITE, bss, 0), + + EC_DESC_INIT(NULL, SHT_NOBITS, SHF_ALLOC + SHF_WRITE, + SHF_ALLOC + SHF_WRITE, bss, 0), #if defined(_ELF64) /* (amd64-only) */ - EC_DESC_INIT(SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, + EC_DESC_INIT(NULL, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, data, 0), - EC_DESC_INIT(0, SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, + EC_DESC_INIT(NULL, 0, SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, ldata, 0), #endif - EC_DESC_INIT(0, SHF_ALLOC + SHF_WRITE, SHF_ALLOC + SHF_WRITE, data, 0), + EC_DESC_INIT(NULL, 0, SHF_ALLOC + SHF_WRITE, SHF_ALLOC + SHF_WRITE, + data, 0), /* * Final catchall rule sends remaining sections to "extra" * NULL segment, which has been tagged as FLG_SG_NODISABLE, * and which will therefore always accept them. */ - EC_DESC_INIT(0, 0, 0, extra, FLG_EC_CATCHALL) + EC_DESC_INIT(NULL, 0, 0, 0, extra, FLG_EC_CATCHALL) }; #undef EC_DESC_INIT @@ -375,7 +398,7 @@ /* * The data segment and stack permissions can differ: * - * - Architecural/ABI per-platform differences + * - Architectural/ABI per-platform differences * - Whether the object is built statically or dynamically * * Those segments so affected have their program header flags
--- a/usr/src/cmd/sgs/libld/common/files.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libld/common/files.c Mon Mar 01 10:20:48 2010 -0800 @@ -245,17 +245,17 @@ Xword badval; /* - * If a mapfile has established definitions to override any input - * capabilities, ignore any new input capabilities. + * If a mapfile has established definitions to override any object + * capabilities, ignore any new object capabilities. */ if (ofl->ofl_flags1 & FLG_OF1_OVSFCAP1) { - DBG_CALL(Dbg_cap_entry(ofl->ofl_lml, DBG_STATE_IGNORED, + DBG_CALL(Dbg_cap_val_entry(ofl->ofl_lml, DBG_STATE_IGNORED, CA_SUNW_SF_1, val, ld_targ.t_m.m_mach)); return; } #if !defined(_ELF64) - if (ifl->ifl_ehdr->e_type == ET_REL) { + if (ifl && (ifl->ifl_ehdr->e_type == ET_REL)) { /* * The SF1_SUNW_ADDR32 is only meaningful when building a 64-bit * object. Warn the user, and remove the setting, if we're @@ -309,7 +309,7 @@ * The runtime linker will refuse to use this dependency. */ if ((val & SF1_SUNW_ADDR32) && (ofl->ofl_flags & FLG_OF_EXEC) && - ((ofl->ofl_ocapset.c_sf_1.cm_value & + ((ofl->ofl_ocapset.oc_sf_1.cm_val & SF1_SUNW_ADDR32) == 0)) { eprintf(ofl->ofl_lml, ERR_WARNING, MSG_INTL(MSG_FIL_EXADDR32SF1), ifl->ifl_name, @@ -320,9 +320,9 @@ } if (DBG_ENABLED) { - Dbg_cap_entry2(ofl->ofl_lml, DBG_STATE_CURRENT, CA_SUNW_SF_1, - &ofl->ofl_ocapset.c_sf_1, ld_targ.t_m.m_mach); - Dbg_cap_entry(ofl->ofl_lml, DBG_STATE_NEW, CA_SUNW_SF_1, + Dbg_cap_val_entry(ofl->ofl_lml, DBG_STATE_CURRENT, CA_SUNW_SF_1, + ofl->ofl_ocapset.oc_sf_1.cm_val, ld_targ.t_m.m_mach); + Dbg_cap_val_entry(ofl->ofl_lml, DBG_STATE_NEW, CA_SUNW_SF_1, val, ld_targ.t_m.m_mach); } @@ -330,13 +330,13 @@ * Determine the resolution of the present frame pointer and the * new input relocatable objects frame pointer. */ - if ((ofl->ofl_ocapset.c_sf_1.cm_value & FP_FLAGS) == FP_FLAGS) { + if ((ofl->ofl_ocapset.oc_sf_1.cm_val & FP_FLAGS) == FP_FLAGS) { /* * If the new relocatable object isn't using a frame pointer, * reduce the present state to unused. */ if ((val & FP_FLAGS) != FP_FLAGS) - ofl->ofl_ocapset.c_sf_1.cm_value &= ~SF1_SUNW_FPUSED; + ofl->ofl_ocapset.oc_sf_1.cm_val &= ~SF1_SUNW_FPUSED; /* * Having processed the frame pointer bits, remove them from @@ -344,22 +344,22 @@ */ val &= ~FP_FLAGS; - } else if ((ofl->ofl_ocapset.c_sf_1.cm_value & SF1_SUNW_FPKNWN) == 0) { + } else if ((ofl->ofl_ocapset.oc_sf_1.cm_val & SF1_SUNW_FPKNWN) == 0) { /* * If the present frame pointer state is unknown, mask it out * and allow the values from the new relocatable object * to overwrite them. */ - ofl->ofl_ocapset.c_sf_1.cm_value &= ~FP_FLAGS; + ofl->ofl_ocapset.oc_sf_1.cm_val &= ~FP_FLAGS; } else { /* Do not take the frame pointer flags from the object */ val &= ~FP_FLAGS; } - ofl->ofl_ocapset.c_sf_1.cm_value |= val; - - DBG_CALL(Dbg_cap_entry2(ofl->ofl_lml, DBG_STATE_RESOLVED, CA_SUNW_SF_1, - &ofl->ofl_ocapset.c_sf_1, ld_targ.t_m.m_mach)); + ofl->ofl_ocapset.oc_sf_1.cm_val |= val; + + DBG_CALL(Dbg_cap_val_entry(ofl->ofl_lml, DBG_STATE_RESOLVED, + CA_SUNW_SF_1, ofl->ofl_ocapset.oc_sf_1.cm_val, ld_targ.t_m.m_mach)); #undef FP_FLAGS } @@ -371,15 +371,26 @@ * additive. */ static void -hw1_cap(Ofl_desc *ofl, Xword val) +hw_cap(Ofl_desc *ofl, Xword tag, Xword val) { + elfcap_mask_t *hwcap; + ofl_flag_t flags1; + + if (tag == CA_SUNW_HW_1) { + hwcap = &ofl->ofl_ocapset.oc_hw_1.cm_val; + flags1 = FLG_OF1_OVHWCAP1; + } else { + hwcap = &ofl->ofl_ocapset.oc_hw_2.cm_val; + flags1 = FLG_OF1_OVHWCAP2; + } + /* - * If a mapfile has established definitions to override any input - * capabilities, ignore any new input capabilities. + * If a mapfile has established definitions to override any object + * capabilities, ignore any new object capabilities. */ - if (ofl->ofl_flags1 & FLG_OF1_OVHWCAP1) { - DBG_CALL(Dbg_cap_entry(ofl->ofl_lml, DBG_STATE_IGNORED, - CA_SUNW_HW_1, val, ld_targ.t_m.m_mach)); + if (ofl->ofl_flags1 & flags1) { + DBG_CALL(Dbg_cap_val_entry(ofl->ofl_lml, DBG_STATE_IGNORED, + tag, val, ld_targ.t_m.m_mach)); return; } @@ -391,70 +402,878 @@ return; if (DBG_ENABLED) { - Dbg_cap_entry2(ofl->ofl_lml, DBG_STATE_CURRENT, CA_SUNW_HW_1, - &ofl->ofl_ocapset.c_hw_1, ld_targ.t_m.m_mach); - Dbg_cap_entry(ofl->ofl_lml, DBG_STATE_NEW, CA_SUNW_HW_1, val, - ld_targ.t_m.m_mach); + Dbg_cap_val_entry(ofl->ofl_lml, DBG_STATE_CURRENT, CA_SUNW_HW_1, + ofl->ofl_ocapset.oc_hw_1.cm_val, ld_targ.t_m.m_mach); + Dbg_cap_val_entry(ofl->ofl_lml, DBG_STATE_NEW, CA_SUNW_HW_1, + val, ld_targ.t_m.m_mach); + } + + *hwcap |= val; + + DBG_CALL(Dbg_cap_val_entry(ofl->ofl_lml, DBG_STATE_RESOLVED, tag, + *hwcap, ld_targ.t_m.m_mach)); +} + +/* + * Promote a machine capability or platform capability to the output file. + * Multiple instances of these names can be defined. + */ +static void +str_cap(Ofl_desc *ofl, char *pstr, ofl_flag_t flags, Xword tag, Caplist *list) +{ + Capstr *capstr; + Aliste idx; + Boolean found = FALSE; + + /* + * If a mapfile has established definitions to override this capability, + * ignore any new capability. + */ + if (ofl->ofl_flags1 & flags) { + DBG_CALL(Dbg_cap_ptr_entry(ofl->ofl_lml, DBG_STATE_IGNORED, + tag, pstr)); + return; + } + + for (ALIST_TRAVERSE(list->cl_val, idx, capstr)) { + DBG_CALL(Dbg_cap_ptr_entry(ofl->ofl_lml, + DBG_STATE_CURRENT, tag, capstr->cs_str)); + if (strcmp(capstr->cs_str, pstr) == 0) + found = TRUE; + } + + DBG_CALL(Dbg_cap_ptr_entry(ofl->ofl_lml, DBG_STATE_NEW, tag, pstr)); + + if (found == FALSE) { + if ((capstr = alist_append(&list->cl_val, NULL, + sizeof (Capstr), AL_CNT_CAP_NAMES)) == NULL) { + ofl->ofl_flags |= FLG_OF_FATAL; + return; + } + capstr->cs_str = pstr; + } + + if (DBG_ENABLED) { + for (ALIST_TRAVERSE(list->cl_val, idx, capstr)) { + DBG_CALL(Dbg_cap_ptr_entry(ofl->ofl_lml, + DBG_STATE_RESOLVED, tag, capstr->cs_str)); + } } - - ofl->ofl_ocapset.c_hw_1.cm_value |= val; - - DBG_CALL(Dbg_cap_entry2(ofl->ofl_lml, DBG_STATE_RESOLVED, CA_SUNW_HW_1, - &ofl->ofl_ocapset.c_hw_1, ld_targ.t_m.m_mach)); +} + +/* + * Promote a capability identifier to the output file. A capability group can + * only have one identifier, and thus only the first identifier seen from any + * input relocatable objects is retained. An explicit user defined identifier, + * rather than an an identifier fabricated by ld(1) with -z symbcap processing, + * takes precedence. Note, a user may have defined an identifier via a mapfile, + * in which case the mapfile identifier is retained. + */ +static void +id_cap(Ofl_desc *ofl, char *pstr, oc_flag_t flags) +{ + Objcapset *ocapset = &ofl->ofl_ocapset; + + if (ocapset->oc_id.cs_str) { + DBG_CALL(Dbg_cap_ptr_entry(ofl->ofl_lml, DBG_STATE_CURRENT, + CA_SUNW_ID, ocapset->oc_id.cs_str)); + + if ((ocapset->oc_flags & FLG_OCS_USRDEFID) || + ((flags & FLG_OCS_USRDEFID) == 0)) { + DBG_CALL(Dbg_cap_ptr_entry(ofl->ofl_lml, + DBG_STATE_IGNORED, CA_SUNW_ID, pstr)); + return; + } + } + + DBG_CALL(Dbg_cap_ptr_entry(ofl->ofl_lml, DBG_STATE_NEW, + CA_SUNW_ID, pstr)); + + ocapset->oc_id.cs_str = pstr; + ocapset->oc_flags |= flags; + + DBG_CALL(Dbg_cap_ptr_entry(ofl->ofl_lml, DBG_STATE_RESOLVED, + CA_SUNW_ID, pstr)); +} + +/* + * Promote a capabilities group to the object capabilities. This catches a + * corner case. An object capabilities file can be converted to symbol + * capabilities with -z symbolcap. However, if the user has indicated that all + * the symbols should be demoted, we'd be left with a symbol capabilities file, + * with no associated symbols. Catch this case by promoting the symbol + * capabilities back to object capabilities. + */ +void +ld_cap_move_symtoobj(Ofl_desc *ofl) +{ + Cap_group *cgp; + Aliste idx1; + + for (APLIST_TRAVERSE(ofl->ofl_capgroups, idx1, cgp)) { + Objcapset *scapset = &cgp->cg_set; + Capstr *capstr; + Aliste idx2; + + if (scapset->oc_id.cs_str) { + if (scapset->oc_flags & FLG_OCS_USRDEFID) + id_cap(ofl, scapset->oc_id.cs_str, + scapset->oc_flags); + } + if (scapset->oc_plat.cl_val) { + for (ALIST_TRAVERSE(scapset->oc_plat.cl_val, idx2, + capstr)) { + str_cap(ofl, capstr->cs_str, FLG_OF1_OVPLATCAP, + CA_SUNW_PLAT, &ofl->ofl_ocapset.oc_plat); + } + } + if (scapset->oc_mach.cl_val) { + for (ALIST_TRAVERSE(scapset->oc_mach.cl_val, idx2, + capstr)) { + str_cap(ofl, capstr->cs_str, FLG_OF1_OVMACHCAP, + CA_SUNW_MACH, &ofl->ofl_ocapset.oc_mach); + } + } + if (scapset->oc_hw_2.cm_val) + hw_cap(ofl, CA_SUNW_HW_2, scapset->oc_hw_2.cm_val); + + if (scapset->oc_hw_1.cm_val) + hw_cap(ofl, CA_SUNW_HW_1, scapset->oc_hw_1.cm_val); + + if (scapset->oc_sf_1.cm_val) + sf1_cap(ofl, scapset->oc_sf_1.cm_val, NULL, NULL); + } } /* - * Process a hardware/software capabilities section. Traverse the section - * updating the global capabilities variables as necessary. + * Determine whether a capabilities group already exists that describes this + * new capabilities group. + * + * Note, a capability group identifier, CA_SUNW_ID, isn't used as part of the + * comparison. This attribute simply assigns a diagnostic name to the group, + * and in the case of multiple identifiers, the first will be taken. */ -static void -process_cap(Ifl_desc *ifl, Is_desc *cisp, Ofl_desc *ofl) +static Cap_group * +get_cap_group(Objcapset *ocapset, Word cnum, Ofl_desc *ofl, Is_desc *isp) { - Cap *cdata; - Word ndx, cnum; + Aliste idx; + Cap_group *cgp; + Word ccnum = cnum; + + /* + * If the new capabilities contains a CA_SUNW_ID, drop the count of the + * number of comparable items. + */ + if (ocapset->oc_id.cs_str) + ccnum--; + + /* + * Traverse the existing symbols capabilities groups. + */ + for (APLIST_TRAVERSE(ofl->ofl_capgroups, idx, cgp)) { + Word onum = cgp->cg_num; + Alist *calp, *oalp; + + if (cgp->cg_set.oc_id.cs_str) + onum--; + + if (onum != ccnum) + continue; + + if (cgp->cg_set.oc_hw_1.cm_val != ocapset->oc_hw_1.cm_val) + continue; + if (cgp->cg_set.oc_sf_1.cm_val != ocapset->oc_sf_1.cm_val) + continue; + if (cgp->cg_set.oc_hw_2.cm_val != ocapset->oc_hw_2.cm_val) + continue; + + calp = cgp->cg_set.oc_plat.cl_val; + oalp = ocapset->oc_plat.cl_val; + if ((calp == NULL) && oalp) + continue; + if (calp && ((oalp == NULL) || cap_names_match(calp, oalp))) + continue; + + calp = cgp->cg_set.oc_mach.cl_val; + oalp = ocapset->oc_mach.cl_val; + if ((calp == NULL) && oalp) + continue; + if (calp && ((oalp == NULL) || cap_names_match(calp, oalp))) + continue; + + /* + * If a matching group is found, then this new group has + * already been supplied by a previous file, and hence the + * existing group can be used. Record this new input section, + * from which we can also derive the input file name, on the + * existing groups input sections. + */ + if (aplist_append(&(cgp->cg_secs), isp, + AL_CNT_CAP_SECS) == NULL) + return (NULL); + return (cgp); + } + + /* + * If a capabilities group is not found, create a new one. + */ + if (((cgp = libld_calloc(sizeof (Cap_group), 1)) == NULL) || + (aplist_append(&(ofl->ofl_capgroups), cgp, + AL_CNT_CAP_DESCS) == NULL)) + return (NULL); + + /* + * If we're converting object capabilities to symbol capabilities and + * no CA_SUNW_ID is defined, fabricate one. This identifier is appended + * to all symbol names that are converted into capabilities symbols, + * see ld_sym_process(). + */ + if ((isp->is_file->ifl_flags & FLG_IF_OTOSCAP) && + (ocapset->oc_id.cs_str == NULL)) { + size_t len; + + /* + * Create an identifier using the group number together with a + * default template. We allocate a buffer large enough for any + * possible number of items (way more than we need). + */ + len = MSG_STR_CAPGROUPID_SIZE + CONV_INV_BUFSIZE; + if ((ocapset->oc_id.cs_str = libld_malloc(len)) == NULL) + return (NULL); + + (void) snprintf(ocapset->oc_id.cs_str, len, + MSG_ORIG(MSG_STR_CAPGROUPID), + aplist_nitems(ofl->ofl_capgroups)); + cnum++; + } + + cgp->cg_set = *ocapset; + cgp->cg_num = cnum; + + /* + * Null the callers alist's as they've effectively been transferred + * to this new Cap_group. + */ + ocapset->oc_plat.cl_val = ocapset->oc_mach.cl_val = NULL; + + /* + * Keep track of which input section, and hence input file, established + * this group. + */ + if (aplist_append(&(cgp->cg_secs), isp, AL_CNT_CAP_SECS) == NULL) + return (NULL); + + /* + * Keep track of the number of symbol capabilities entries that will be + * required in the output file. Each group requires a terminating + * CA_SUNW_NULL. + */ + ofl->ofl_capsymcnt += (cnum + 1); + return (cgp); +} + +/* + * Capture symbol capability family information. This data structure is focal + * in maintaining all symbol capability relationships, and provides for the + * eventual creation of a capabilities information section, and possibly a + * capabilities chain section. + * + * Capabilities families are lead by a CAPINFO_SUNW_GLOB symbol. This symbol + * provides the visible global symbol that is referenced by all external + * callers. This symbol may have aliases. For example, a weak/global symbol + * pair, such as memcpy()/_memcpy() may lead the same capabilities family. + * Each family contains one or more local symbol members. These members provide + * the capabilities specific functions, and are associated to a capabilities + * group. For example, the capability members memcpy%sun4u and memcpy%sun4v + * might be associated with the memcpy() capability family. + * + * This routine is called when a relocatable object that provides object + * capabilities is transformed into a symbol capabilities object, using the + * -z symbolcap option. + * + * This routine is also called to collect the SUNW_capinfo section information + * of a relocatable object that contains symbol capability definitions. + */ +uintptr_t +ld_cap_add_family(Ofl_desc *ofl, Sym_desc *lsdp, Sym_desc *csdp, Cap_group *cgp, + APlist **csyms) +{ + Cap_avlnode qcav, *cav; + avl_tree_t *avlt; + avl_index_t where = 0; + Cap_sym *mcsp; + Aliste idx; + + /* + * Make sure the capability families have an initialized AVL tree. + */ + if ((avlt = ofl->ofl_capfamilies) == NULL) { + if ((avlt = libld_calloc(sizeof (avl_tree_t), 1)) == NULL) + return (S_ERROR); + avl_create(avlt, &ld_sym_avl_comp, sizeof (Cap_avlnode), + SGSOFFSETOF(Cap_avlnode, cn_symavlnode.sav_node)); + ofl->ofl_capfamilies = avlt; + + /* + * When creating a dynamic object, capability family members + * are maintained in a .SUNW_capchain, the first entry of + * which is the version number of the chain. + */ + ofl->ofl_capchaincnt = 1; + } + + /* + * Determine whether a family already exists, and if not, create one + * using the lead family symbol. + */ + qcav.cn_symavlnode.sav_hash = (Word)elf_hash(lsdp->sd_name); + qcav.cn_symavlnode.sav_name = lsdp->sd_name; + + if ((cav = avl_find(avlt, &qcav, &where)) == NULL) { + if ((cav = libld_calloc(sizeof (Cap_avlnode), 1)) == NULL) + return (S_ERROR); + cav->cn_symavlnode.sav_hash = qcav.cn_symavlnode.sav_hash; + cav->cn_symavlnode.sav_name = qcav.cn_symavlnode.sav_name; + cav->cn_symavlnode.sav_sdp = lsdp; + + avl_insert(avlt, cav, where); + + /* + * When creating a dynamic object, capability family members + * are maintained in a .SUNW_capchain, each family starts with + * this lead symbol, and is terminated with a 0 element. + */ + ofl->ofl_capchaincnt += 2; + } + + /* + * If no group information is provided then this request is to add a + * lead capability symbol, or lead symbol alias. If this is the lead + * symbol there's nothing more to do. Otherwise save the alias. + */ + if (cgp == NULL) { + if ((lsdp != csdp) && (aplist_append(&cav->cn_aliases, csdp, + AL_CNT_CAP_ALIASES) == NULL)) + return (S_ERROR); + + return (0); + } + + /* + * Determine whether a member of the same group as this new member is + * already defined within this family. If so, we have a multiply + * defined symbol. + */ + for (APLIST_TRAVERSE(cav->cn_members, idx, mcsp)) { + Sym_desc *msdp; + + if (cgp != mcsp->cs_group) + continue; + + /* + * Diagnose that a multiple symbol definition exists. + */ + msdp = mcsp->cs_sdp; + + eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_CAP_MULDEF), + demangle(lsdp->sd_name)); + eprintf(ofl->ofl_lml, ERR_NONE, MSG_INTL(MSG_CAP_MULDEFSYMS), + msdp->sd_file->ifl_name, msdp->sd_name, + csdp->sd_file->ifl_name, csdp->sd_name); + ofl->ofl_flags |= FLG_OF_FATAL; + } + + /* + * Add this capabilities symbol member to the family. + */ + if (((mcsp = libld_malloc(sizeof (Cap_sym))) == NULL) || + (aplist_append(&cav->cn_members, mcsp, AL_CNT_CAP_MEMS) == NULL)) + return (S_ERROR); + + mcsp->cs_sdp = csdp; + mcsp->cs_group = cgp; + + /* + * When creating a dynamic object, capability family members are + * maintained in a .SUNW_capchain. Account for this family member. + */ + ofl->ofl_capchaincnt++; + + /* + * If this input file is undergoing object capabilities to symbol + * capabilities conversion, then this member is a new local symbol + * that has been generated from an original global symbol. Keep track + * of this symbol so that the output file symbol table can be populated + * with these new symbol entries. + */ + if (csyms && (aplist_append(csyms, mcsp, AL_CNT_CAP_SYMS) == NULL)) + return (S_ERROR); + + return (0); +} + +/* + * Process a SHT_SUNW_cap capabilities section. + */ +static uintptr_t +process_cap(Ofl_desc *ofl, Ifl_desc *ifl, Is_desc *cisp) +{ + Objcapset ocapset = { 0 }; + Cap_desc *cdp; + Cap *data, *cdata; + char *strs; + Word ndx, cnum; + int objcapndx, descapndx, symcapndx; + int nulls, capstrs = 0; + + /* + * Determine the capabilities data and size. + */ + cdata = (Cap *)cisp->is_indata->d_buf; + cnum = (Word)(cisp->is_shdr->sh_size / cisp->is_shdr->sh_entsize); + + if ((cdata == NULL) || (cnum == 0)) + return (0); DBG_CALL(Dbg_cap_sec_title(ofl->ofl_lml, ifl->ifl_name)); /* - * The capabilities are supposed to be terminated with a CA_SUNW_NULL - * entry. However, the compilers have been known to not follow this - * convention. Use the section information to determine the number - * of capabilities, and skip any CA_SUNW_NULL entries. + * Traverse the section to determine what capabilities groups are + * available. + * + * A capabilities section can contain one or more, CA_SUNW_NULL + * terminated groups. + * + * - The first group defines the object capabilities. + * - Additional groups define symbol capabilities. + * - Since the initial group is always reserved for object + * capabilities, any object with symbol capabilities must also + * have an object capabilities group. If the object has no object + * capabilities, an empty object group is defined, consisting of a + * CA_SUNW_NULL element in index [0]. + * - If any capabilities require references to a named string, then + * the section header sh_info points to the associated string + * table. + * - If an object contains symbol capability groups, then the + * section header sh_link points to the associated capinfo table. */ - cdata = (Cap *)cisp->is_indata->d_buf; - cnum = (Word)(cisp->is_shdr->sh_size / cisp->is_shdr->sh_entsize); - - for (ndx = 0; ndx < cnum; cdata++, ndx++) { - switch (cdata->c_tag) { - case CA_SUNW_HW_1: - /* - * Only the hardware capabilities that are - * defined in a relocatable object become part - * of the hardware capabilities in the output - * file. - */ - if (ifl->ifl_ehdr->e_type == ET_REL) - hw1_cap(ofl, cdata->c_un.c_val); - break; - case CA_SUNW_SF_1: - /* - * Only the software capabilities that are - * defined in a relocatable object become part - * of the software capabilities in the output - * file. However, check the validity of the - * software capabilities of any dependencies. - */ - sf1_cap(ofl, cdata->c_un.c_val, ifl, cisp); - break; - case CA_SUNW_NULL: - break; - default: - eprintf(ofl->ofl_lml, ERR_WARNING, - MSG_INTL(MSG_FIL_UNKCAP), ifl->ifl_name, - EC_WORD(cisp->is_scnndx), cisp->is_name, - cdata->c_tag); + objcapndx = 0; + descapndx = symcapndx = -1; + nulls = 0; + + for (ndx = 0, data = cdata; ndx < cnum; ndx++, data++) { + switch (data->c_tag) { + case CA_SUNW_NULL: + /* + * If this is the first CA_SUNW_NULL entry, and no + * capabilities group has been found, then this object + * does not define any object capabilities. + */ + if (nulls++ == 0) { + if (ndx == 0) + objcapndx = -1; + } else if ((symcapndx == -1) && (descapndx != -1)) + symcapndx = descapndx; + + break; + + case CA_SUNW_PLAT: + case CA_SUNW_MACH: + case CA_SUNW_ID: + capstrs++; + /* FALLTHROUGH */ + + case CA_SUNW_HW_1: + case CA_SUNW_SF_1: + case CA_SUNW_HW_2: + /* + * If this is the start of a new group, save it. + */ + if (descapndx == -1) + descapndx = ndx; + break; + + default: + eprintf(ofl->ofl_lml, ERR_WARNING, + MSG_INTL(MSG_FIL_UNKCAP), ifl->ifl_name, + EC_WORD(cisp->is_scnndx), cisp->is_name, + data->c_tag); } } + + /* + * If a string capabilities entry has been found, the capabilities + * section must reference the associated string table. + */ + if (capstrs) { + Word info = cisp->is_shdr->sh_info; + + if ((info == 0) || (info > ifl->ifl_shnum)) { + eprintf(ofl->ofl_lml, ERR_FATAL, + MSG_INTL(MSG_FIL_INVSHINFO), ifl->ifl_name, + EC_WORD(cisp->is_scnndx), cisp->is_name, + EC_XWORD(info)); + ofl->ofl_flags |= FLG_OF_FATAL; + return (S_ERROR); + } + strs = (char *)ifl->ifl_isdesc[info]->is_indata->d_buf; + } + + /* + * The processing of capabilities groups is as follows: + * + * - if a relocatable object provides only object capabilities, and + * the -z symbolcap option is in effect, then the object + * capabilities are transformed into symbol capabilities and the + * symbol capabilities are carried over to the output file. + * - in all other cases, any capabilities present in an input + * relocatable object are carried from the input object to the + * output without any transformation or conversion. + * + * Capture any object capabilities that are to be carried over to the + * output file. + */ + if ((objcapndx == 0) && + ((symcapndx != -1) || ((ofl->ofl_flags & FLG_OF_OTOSCAP) == 0))) { + for (ndx = 0, data = cdata; ndx < cnum; ndx++, data++) { + /* + * Object capabilities end at the first null. + */ + if (data->c_tag == CA_SUNW_NULL) + break; + + /* + * Only the object software capabilities that are + * defined in a relocatable object become part of the + * object software capabilities in the output file. + * However, check the validity of any object software + * capabilities of any dependencies. + */ + if (data->c_tag == CA_SUNW_SF_1) { + sf1_cap(ofl, data->c_un.c_val, ifl, cisp); + continue; + } + + /* + * The remaining capability types must come from a + * relocatable object in order to contribute to the + * output. + */ + if (ifl->ifl_ehdr->e_type != ET_REL) + continue; + + switch (data->c_tag) { + case CA_SUNW_HW_1: + case CA_SUNW_HW_2: + hw_cap(ofl, data->c_tag, data->c_un.c_val); + break; + + case CA_SUNW_PLAT: + str_cap(ofl, strs + data->c_un.c_ptr, + FLG_OF1_OVPLATCAP, CA_SUNW_PLAT, + &ofl->ofl_ocapset.oc_plat); + break; + + case CA_SUNW_MACH: + str_cap(ofl, strs + data->c_un.c_ptr, + FLG_OF1_OVMACHCAP, CA_SUNW_MACH, + &ofl->ofl_ocapset.oc_mach); + break; + + case CA_SUNW_ID: + id_cap(ofl, strs + data->c_un.c_ptr, + FLG_OCS_USRDEFID); + break; + + default: + assert(0); /* Unknown capability type */ + } + } + + /* + * If there are no symbol capabilities, or this objects + * capabilities aren't being transformed into a symbol + * capabilities, then we're done. + */ + if ((symcapndx == -1) && + ((ofl->ofl_flags & FLG_OF_OTOSCAP) == 0)) + return (1); + } + + /* + * If these capabilities don't originate from a relocatable object + * there's no further processing required. + */ + if (ifl->ifl_ehdr->e_type != ET_REL) + return (1); + + /* + * If this object only defines an object capabilities group, and the + * -z symbolcap option is in effect, then all global function symbols + * and initialized global data symbols are renamed and assigned to the + * transformed symbol capabilities group. + */ + if ((objcapndx == 0) && + (symcapndx == -1) && (ofl->ofl_flags & FLG_OF_OTOSCAP)) + ifl->ifl_flags |= FLG_IF_OTOSCAP; + + /* + * Allocate a capabilities descriptor to collect the capabilities data + * for this input file. Allocate a mirror of the raw capabilities data + * that points to the individual symbol capabilities groups. An APlist + * is used, although it will be sparsely populated, as the list provides + * a convenient mechanism for traversal later. + */ + if (((cdp = libld_calloc(sizeof (Cap_desc), 1)) == NULL) || + (aplist_append(&(cdp->ca_groups), NULL, cnum) == NULL)) + return (S_ERROR); + + /* + * Clear the allocated APlist data array, and assign the number of + * items as the total number of array items. + */ + (void) memset(&cdp->ca_groups->apl_data[0], 0, + (cnum * sizeof (void *))); + cdp->ca_groups->apl_nitems = cnum; + + ifl->ifl_caps = cdp; + + /* + * Traverse the capabilities data, unpacking the data into a + * capabilities set. Process each capabilities set as a unique group. + */ + descapndx = -1; + nulls = 0; + + for (ndx = 0, data = cdata; ndx < cnum; ndx++, data++) { + Capstr *capstr; + + switch (data->c_tag) { + case CA_SUNW_NULL: + nulls++; + + /* + * Process the capabilities group that this null entry + * terminates. The capabilities group that is returned + * will either point to this file's data, or to a + * matching capabilities group that has already been + * processed. + * + * Note, if this object defines object capabilities, + * the first group descriptor points to these object + * capabilities. It is only necessary to save this + * descriptor when object capabilities are being + * transformed into symbol capabilities (-z symbolcap). + */ + if (descapndx != -1) { + if ((nulls > 1) || + (ifl->ifl_flags & FLG_IF_OTOSCAP)) { + APlist *alp = cdp->ca_groups; + + if ((alp->apl_data[descapndx] = + get_cap_group(&ocapset, + (ndx - descapndx), ofl, + cisp)) == NULL) + return (S_ERROR); + } + + /* + * Clean up the capabilities data in preparation + * for processing additional groups. If the + * collected capabilities strings were used to + * establish a new output group, they will have + * been saved in get_cap_group(). If these + * descriptors still exist, then an existing + * descriptor has been used to associate with + * this file, and these string descriptors can + * be freed. + */ + ocapset.oc_hw_1.cm_val = + ocapset.oc_sf_1.cm_val = + ocapset.oc_hw_2.cm_val = 0; + if (ocapset.oc_plat.cl_val) { + free((void *)ocapset.oc_plat.cl_val); + ocapset.oc_plat.cl_val = NULL; + } + if (ocapset.oc_mach.cl_val) { + free((void *)ocapset.oc_mach.cl_val); + ocapset.oc_mach.cl_val = NULL; + } + descapndx = -1; + } + continue; + + case CA_SUNW_HW_1: + ocapset.oc_hw_1.cm_val = data->c_un.c_val; + DBG_CALL(Dbg_cap_val_entry(ofl->ofl_lml, + DBG_STATE_ORIGINAL, CA_SUNW_HW_1, + ocapset.oc_hw_1.cm_val, ld_targ.t_m.m_mach)); + break; + + case CA_SUNW_SF_1: + ocapset.oc_sf_1.cm_val = data->c_un.c_val; + DBG_CALL(Dbg_cap_val_entry(ofl->ofl_lml, + DBG_STATE_ORIGINAL, CA_SUNW_SF_1, + ocapset.oc_sf_1.cm_val, ld_targ.t_m.m_mach)); + break; + + case CA_SUNW_HW_2: + ocapset.oc_hw_2.cm_val = data->c_un.c_val; + DBG_CALL(Dbg_cap_val_entry(ofl->ofl_lml, + DBG_STATE_ORIGINAL, CA_SUNW_HW_2, + ocapset.oc_hw_2.cm_val, ld_targ.t_m.m_mach)); + break; + + case CA_SUNW_PLAT: + if ((capstr = alist_append(&ocapset.oc_plat.cl_val, + NULL, sizeof (Capstr), AL_CNT_CAP_NAMES)) == NULL) + return (S_ERROR); + capstr->cs_str = strs + data->c_un.c_ptr; + DBG_CALL(Dbg_cap_ptr_entry(ofl->ofl_lml, + DBG_STATE_ORIGINAL, CA_SUNW_PLAT, capstr->cs_str)); + break; + + case CA_SUNW_MACH: + if ((capstr = alist_append(&ocapset.oc_mach.cl_val, + NULL, sizeof (Capstr), AL_CNT_CAP_NAMES)) == NULL) + return (S_ERROR); + capstr->cs_str = strs + data->c_un.c_ptr; + DBG_CALL(Dbg_cap_ptr_entry(ofl->ofl_lml, + DBG_STATE_ORIGINAL, CA_SUNW_MACH, capstr->cs_str)); + break; + + case CA_SUNW_ID: + ocapset.oc_id.cs_str = strs + data->c_un.c_ptr; + DBG_CALL(Dbg_cap_ptr_entry(ofl->ofl_lml, + DBG_STATE_ORIGINAL, CA_SUNW_ID, + ocapset.oc_id.cs_str)); + break; + } + + /* + * Save the start of this new group. + */ + if (descapndx == -1) + descapndx = ndx; + } + return (1); +} + +/* + * Capture any symbol capabilities symbols. An object file that contains symbol + * capabilities has an associated .SUNW_capinfo section. This section + * identifies which symbols are associated to which capabilities, together with + * their associated lead symbol. Each of these symbol pairs are recorded for + * processing later. + */ +static uintptr_t +process_capinfo(Ofl_desc *ofl, Ifl_desc *ifl, Is_desc *isp) +{ + Cap_desc *cdp = ifl->ifl_caps; + Capinfo *capinfo = isp->is_indata->d_buf; + Shdr *shdr = isp->is_shdr; + Word cndx, capinfonum; + + capinfonum = (Word)(shdr->sh_size / shdr->sh_entsize); + + if ((cdp == NULL) || (capinfo == NULL) || (capinfonum == 0)) + return (0); + + for (cndx = 1, capinfo++; cndx < capinfonum; cndx++, capinfo++) { + Sym_desc *sdp, *lsdp; + Word lndx; + uchar_t gndx; + + if ((gndx = (uchar_t)ELF_C_GROUP(*capinfo)) == 0) + continue; + lndx = (Word)ELF_C_SYM(*capinfo); + + /* + * Catch any anomalies. A capabilities symbol should be valid, + * and the capabilities lead symbol should also be global. + * Note, ld(1) -z symbolcap would create local capabilities + * symbols, but we don't enforce this so as to give the + * compilation environment a little more freedom. + */ + if ((sdp = ifl->ifl_oldndx[cndx]) == NULL) { + eprintf(ofl->ofl_lml, ERR_WARNING, + MSG_INTL(MSG_CAPINFO_INVALSYM), ifl->ifl_name, + EC_WORD(isp->is_scnndx), isp->is_name, cndx, + MSG_INTL(MSG_STR_UNKNOWN)); + continue; + } + if ((lndx == 0) || (lndx >= ifl->ifl_symscnt) || + ((lsdp = ifl->ifl_oldndx[lndx]) == NULL) || + (ELF_ST_BIND(lsdp->sd_sym->st_info) != STB_GLOBAL)) { + eprintf(ofl->ofl_lml, ERR_WARNING, + MSG_INTL(MSG_CAPINFO_INVALLEAD), ifl->ifl_name, + EC_WORD(isp->is_scnndx), isp->is_name, cndx, lsdp ? + demangle(lsdp->sd_name) : MSG_INTL(MSG_STR_UNKNOWN), + lndx); + continue; + } + + /* + * Indicate that this is a capabilities symbol. + */ + sdp->sd_flags |= FLG_SY_CAP; + + /* + * Save any global capability symbols. Global capability + * symbols are identified with a CAPINFO_SUNW_GLOB group id. + * The lead symbol for this global capability symbol is either + * the symbol itself, or an alias. + */ + if (gndx == CAPINFO_SUNW_GLOB) { + if (ld_cap_add_family(ofl, lsdp, sdp, + NULL, NULL) == S_ERROR) + return (S_ERROR); + continue; + } + + /* + * Track the number of non-global capabilities symbols, as these + * are used to size any symbol tables. If we're generating a + * dynamic object, this symbol will be added to the dynamic + * symbol table, therefore ensure there is space in the dynamic + * string table. + */ + ofl->ofl_caploclcnt++; + if (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) && + (st_insert(ofl->ofl_dynstrtab, sdp->sd_name) == -1)) + return (S_ERROR); + + /* + * As we're tracking this local symbol as a capabilities symbol, + * reduce the local symbol count to compensate. + */ + ofl->ofl_locscnt--; + + /* + * Determine whether the associated lead symbol indicates + * NODYNSORT. If so, remove this local entry from the + * SUNW_dynsort section too. NODYNSORT tagging can only be + * obtained from a mapfile symbol definition, and thus any + * global definition that has this tagging has already been + * instantiated and this instance resolved to it. + */ + if (lsdp->sd_flags & FLG_SY_NODYNSORT) { + Sym *lsym = lsdp->sd_sym; + uchar_t ltype = ELF_ST_TYPE(lsym->st_info); + + DYNSORT_COUNT(lsdp, lsym, ltype, --); + lsdp->sd_flags |= FLG_SY_NODYNSORT; + } + + /* + * Track this family member, together with its associated group. + */ + if (ld_cap_add_family(ofl, lsdp, sdp, + cdp->ca_groups->apl_data[gndx], NULL) == S_ERROR) + return (S_ERROR); + } + + return (0); } /* @@ -500,7 +1319,6 @@ return (1); } - /* * Process a string table section. A valid section contains an initial and * final null byte. @@ -949,8 +1767,9 @@ /* * Expand implicit references. Dependencies can be specified in terms of the - * $ORIGIN, $PLATFORM, $OSREL and $OSNAME tokens, either from their needed name, - * or via a runpath. In addition runpaths may also specify the $ISALIST token. + * $ORIGIN, $MACHINE, $PLATFORM, $OSREL and $OSNAME tokens, either from their + * needed name, or via a runpath. In addition runpaths may also specify the + * $ISALIST token. * * Probably the most common reference to explicit dependencies (via -L) will be * sufficient to find any associated implicit dependencies, but just in case we @@ -960,6 +1779,8 @@ * * This code is remarkably similar to expand() in rtld/common/paths.c. */ +static char *machine = NULL; +static size_t machine_sz = 0; static char *platform = NULL; static size_t platform_sz = 0; static Isa_desc *isa = NULL; @@ -1014,6 +1835,35 @@ optr += MSG_STR_ORIGIN_SIZE; expanded = _expanded = 1; + } else if (strncmp(optr, MSG_ORIG(MSG_STR_MACHINE), + MSG_STR_MACHINE_SIZE) == 0) { + /* + * Establish the machine from sysconf - like uname -i. + */ + if ((machine == NULL) && (machine_sz == 0)) { + char info[SYS_NMLN]; + long size; + + size = sysinfo(SI_MACHINE, info, SYS_NMLN); + if ((size != -1) && + (machine = libld_malloc((size_t)size))) { + (void) strcpy(machine, info); + machine_sz = (size_t)size - 1; + } else + machine_sz = 1; + } + if (machine) { + if (machine_sz >= nrem) + return ((char *)name); + + (void) strncpy(nptr, machine, machine_sz); + nptr = nptr + machine_sz; + nrem -= machine_sz; + + optr += MSG_STR_MACHINE_SIZE; + expanded = _expanded = 1; + } + } else if (strncmp(optr, MSG_ORIG(MSG_STR_PLATFORM), MSG_STR_PLATFORM_SIZE) == 0) { /* @@ -1625,7 +2475,8 @@ Word row, column; int ident; uintptr_t error; - Is_desc *vdfisp, *vndisp, *vsyisp, *sifisp, *capisp; + Is_desc *vdfisp, *vndisp, *vsyisp, *sifisp; + Is_desc *capinfoisp, *capisp; Sdf_desc *sdf; Place_path_info path_info_buf, *path_info; @@ -1700,7 +2551,7 @@ DBG_CALL(Dbg_file_generic(ofl->ofl_lml, ifl)); ndx = 0; - vdfisp = vndisp = vsyisp = sifisp = capisp = NULL; + vdfisp = vndisp = vsyisp = sifisp = capinfoisp = capisp = NULL; scn = NULL; while (scn = elf_nextscn(elf, scn)) { ndx++; @@ -1786,6 +2637,12 @@ return (S_ERROR); capisp = ifl->ifl_isdesc[ndx]; break; + case SHT_SUNW_capinfo: + if (process_section(name, ifl, shdr, scn, ndx, + ld_targ.t_id.id_null, ofl) == S_ERROR) + return (S_ERROR); + capinfoisp = ifl->ifl_isdesc[ndx]; + break; case SHT_SUNW_DEBUGSTR: case SHT_SUNW_DEBUG: if (process_debug(name, ifl, shdr, scn, @@ -1991,13 +2848,14 @@ } /* - * Process any hardware/software capabilities sections. Only the - * capabilities for input relocatable objects are propagated. If the - * relocatable objects don't contain any capabilities, any capability - * state that has already been gathered will prevail. + * Before symbol processing, process any capabilities. Capabilities + * can reference a string table, which is why this processing is + * carried out after the initial section processing. Capabilities, + * together with -z symbolcap, can require the conversion of global + * symbols to local symbols. */ - if (capisp) - process_cap(ifl, capisp, ofl); + if (capisp && (process_cap(ofl, ifl, capisp) == S_ERROR)) + return (S_ERROR); /* * Process any version dependencies. These will establish shared object @@ -2075,6 +2933,16 @@ } /* + * Following symbol processing, if this relocatable object input file + * provides symbol capabilities, tag the associated symbols so that + * the symbols can be re-assigned to the new capabilities symbol + * section that will be created for the output file. + */ + if (capinfoisp && (ifl->ifl_ehdr->e_type == ET_REL) && + (process_capinfo(ofl, ifl, capinfoisp) == S_ERROR)) + return (S_ERROR); + + /* * After processing any symbol resolution, and if this dependency * indicates it contains symbols that can't be directly bound to, * set the symbols appropriately.
--- a/usr/src/cmd/sgs/libld/common/globals.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libld/common/globals.c Mon Mar 01 10:20:48 2010 -0800 @@ -23,7 +23,7 @@ * Copyright (c) 1988 AT&T * All Rights Reserved * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -73,7 +73,12 @@ MSG_REJ_US3, /* MSG_INTL(MSG_REJ_US3) */ MSG_REJ_STR, /* MSG_INTL(MSG_REJ_STR) */ MSG_REJ_UNKFILE, /* MSG_INTL(MSG_REJ_UNKFILE) */ + MSG_REJ_UNKCAP, /* MSG_INTL(MSG_REJ_UNKCAP) */ MSG_REJ_HWCAP_1, /* MSG_INTL(MSG_REJ_HWCAP_1) */ + MSG_REJ_SFCAP_1, /* MSG_INTL(MSG_REJ_SFCAP_1) */ + MSG_REJ_MACHCAP, /* MSG_INTL(MSG_REJ_MACHCAP) */ + MSG_REJ_PLATCAP, /* MSG_INTL(MSG_REJ_PLATCAP) */ + MSG_REJ_HWCAP_2 /* MSG_INTL(MSG_REJ_HWCAP_2) */ }; /*
--- a/usr/src/cmd/sgs/libld/common/libld.msg Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libld/common/libld.msg Mon Mar 01 10:20:48 2010 -0800 @@ -220,6 +220,8 @@ \t\t\trescan specified archive group upon reaching\n\ \t\t\tthe end of the group, until no further\n\ \t\t\tmember extraction occurs\n" +@ MSG_ARG_DETAIL_ZSCAP "\t[-z symbolcap]\tconvert object capabilities to \ + symbol capabilities\n" @ MSG_ARG_DETAIL_ZTARG "\t[-z target=platform]\n\ \t\t\ttarget machine for cross linking\n" @ MSG_ARG_DETAIL_ZT "\t[-z text]\tdisallow output relocations against \ @@ -425,6 +427,7 @@ # Messages related to platform support + @ MSG_TARG_UNSUPPORTED "unsupported ELF machine type: %s" @@ -589,6 +592,17 @@ @ MSG_VER_ADDVER "\t%s" @ MSG_VER_CYCLIC "following versions generate cyclic dependency:" +# Capabilities messages + +@ MSG_CAP_MULDEF "capabilities symbol '%s' has multiply-defined members:" +@ MSG_CAP_MULDEFSYMS "\t(file %s symbol '%s'; file %s symbol '%s');" +@ MSG_CAP_REDUNDANT "file %s: section [%u]%s: symbol capabilities \ + redundant, as object capabilities are more restrictive" + +@ MSG_CAPINFO_INVALSYM "file %s: capabilities info section [%u]%s: index %d: \ + family member symbol '%s': invalid" +@ MSG_CAPINFO_INVALLEAD "file %s: capabilities info section [%u]%s: index %d: \ + family lead symbol '%s': invalid symbol index %d" # Basic strings @@ -635,7 +649,17 @@ @ MSG_REJ_US3 "file %s: Sun UltraSPARC III extensions required" @ MSG_REJ_STR "file %s: %s" @ MSG_REJ_UNKFILE "file %s: unknown file type" -@ MSG_REJ_HWCAP_1 "file %s: hardware capability unsupported: %s" +@ MSG_REJ_UNKCAP "file=%s; unknown capability: %d" +@ MSG_REJ_HWCAP_1 "file %s: hardware capability (CA_SUNW_HW_1) \ + unsupported: %s" +@ MSG_REJ_SFCAP_1 "file %s: software capability (CA_SUNW_SF_1) \ + unsupported: %s" +@ MSG_REJ_MACHCAP "file %s: machine capability (CA_SUNW_MACH) \ + unsupported: %s" +@ MSG_REJ_PLATCAP "file %s: platform capability (CA_SUNW_PLAT) \ + unsupported: %s" +@ MSG_REJ_HWCAP_2 "file %s: hardware capability (CA_SUNW_HW_2) \ + unsupported: %s" @ _END_ @@ -664,6 +688,7 @@ @ MSG_STR_SLASH "/" @ MSG_STR_DYNAMIC "(.dynamic)" @ MSG_STR_ORIGIN "$ORIGIN" +@ MSG_STR_MACHINE "$MACHINE" @ MSG_STR_PLATFORM "$PLATFORM" @ MSG_STR_ISALIST "$ISALIST" @ MSG_STR_OSNAME "$OSNAME" @@ -747,6 +772,8 @@ @ MSG_SCN_SUNWVERSION ".SUNW_version" @ MSG_SCN_SUNWVERSYM ".SUNW_versym" @ MSG_SCN_SUNWCAP ".SUNW_cap" +@ MSG_SCN_SUNWCAPINFO ".SUNW_capinfo" +@ MSG_SCN_SUNWCAPCHAIN ".SUNW_capchain" @ MSG_SCN_SYMTAB ".symtab" @ MSG_SCN_SYMTAB_SHNDX ".symtab_shndx" @ MSG_SCN_TBSS ".tbss" @@ -860,6 +887,7 @@ but no runpaths have been specified via %s" @ MSG_ARG_NOENTRY "entry point symbol '%s' is undefined" @ MSG_ARG_UNSUPPORTED "option %s is no longer supported; ignored" +@ MSG_MARG_ONLY "option %s can only be used with a %s" @ MSG_ARG_FLAGS "flags processing errors" @ MSG_ARG_FILES "file processing errors. No output written to %s" @@ -1199,7 +1227,7 @@ # Software identification. Note, the SGU strings is historic, and has -# little relevence. It is preserved as applications have used this +# little relevance. It is preserved as applications have used this # string to identify the Solaris link-editor. @ MSG_SGS_ID "ld: Software Generation Utilities - \ @@ -1222,6 +1250,7 @@ @ MSG_STR_PATH "%s/%s" @ MSG_STR_STRNL "%s\n" @ MSG_STR_NL "\n" +@ MSG_STR_CAPGROUPID "CAP_GROUP_%d" @ MSG_STR_LD_DYNAMIC "dynamic" @ MSG_STR_SYMBOLIC "symbolic" @@ -1243,7 +1272,6 @@ @ MSG_STR_OPTIONS "3:6:abc:d:e:f:h:il:mo:p:rstu:z:B:CD:F:GI:L:M:N:P:Q:R:\ S:VW:Y:?" - # Argument processing strings @ MSG_ARG_3 "-3" @@ -1283,6 +1311,7 @@ @ MSG_ARG_ZTEXTALL "-z[text|textwarn|textoff]" @ MSG_ARG_ZLOADFLTR "-zloadfltr" @ MSG_ARG_ZCOMBRELOC "-zcombreloc" +@ MSG_ARG_ZSYMBOLCAP "-zsymbolcap" @ MSG_ARG_ABSEXEC "absexec" @ MSG_ARG_ALTEXEC64 "altexec64" @@ -1345,6 +1374,7 @@ @ MSG_ARG_GROUP "group" @ MSG_ARG_REDUCE "reduce" @ MSG_ARG_STATIC "static" +@ MSG_ARG_SYMBOLCAP "symbolcap" @ MSG_ARG_LCOM "L," @ MSG_ARG_PCOM "P,"
--- a/usr/src/cmd/sgs/libld/common/machrel.amd.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libld/common/machrel.amd.c Mon Mar 01 10:20:48 2010 -0800 @@ -780,12 +780,19 @@ * Size relocations require the symbols size. */ value = sdp->sd_sym->st_size; - } else { + + } else if ((sdp->sd_flags & FLG_SY_CAP) && + sdp->sd_aux && sdp->sd_aux->sa_PLTndx) { /* - * Else the value is the symbols value. + * If this relocation is against a capabilities + * symbol, then we need to jump to an associated + * PLT, so that at runtime ld.so.1 is involved + * to determine the best binding choice. + * Otherwise, the value is the symbols value. */ + value = ld_calc_plt_addr(sdp, ofl); + } else value = sdp->sd_sym->st_value; - } /* * Relocation against the GLOBAL_OFFSET_TABLE. @@ -1097,9 +1104,11 @@ else ofl->ofl_flags1 |= FLG_OF1_TLSOREL; } else { - Os_desc *osp = sdp->sd_isc->is_osdesc; + Os_desc *osp; + Is_desc *isp = sdp->sd_isc; - if (osp && ((osp->os_flags & FLG_OS_OUTREL) == 0)) { + if (isp && ((osp = isp->is_osdesc) != NULL) && + ((osp->os_flags & FLG_OS_OUTREL) == 0)) { ofl->ofl_dynshdrcnt++; osp->os_flags |= FLG_OS_OUTREL; } @@ -1580,6 +1589,8 @@ M_ID_ARRAY, /* id_array */ M_ID_BSS, /* id_bss */ M_ID_CAP, /* id_cap */ + M_ID_CAPINFO, /* id_capinfo */ + M_ID_CAPCHAIN, /* id_capchain */ M_ID_DATA, /* id_data */ M_ID_DYNAMIC, /* id_dynamic */ M_ID_DYNSORT, /* id_dynsort */
--- a/usr/src/cmd/sgs/libld/common/machrel.intel.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libld/common/machrel.intel.c Mon Mar 01 10:20:48 2010 -0800 @@ -881,12 +881,20 @@ * Size relocations require the symbols size. */ value = sdp->sd_sym->st_size; - } else { + + } else if ((sdp->sd_flags & FLG_SY_CAP) && + sdp->sd_aux && sdp->sd_aux->sa_PLTndx) { /* - * Else the value is the symbols value. + * If this relocation is against a capabilities + * symbol, then we need to jump to an associated + * PLT, so that at runtime ld.so.1 is involved + * to determine the best binding choice. + * Otherwise, the value is the symbols value. */ + value = ld_calc_plt_addr(sdp, ofl); + + } else value = sdp->sd_sym->st_value; - } /* * Relocation against the GLOBAL_OFFSET_TABLE. @@ -1185,9 +1193,11 @@ else ofl->ofl_flags1 |= FLG_OF1_TLSOREL; } else { - Os_desc *osp = sdp->sd_isc->is_osdesc; + Os_desc *osp; + Is_desc *isp = sdp->sd_isc; - if (osp && ((osp->os_flags & FLG_OS_OUTREL) == 0)) { + if (isp && ((osp = isp->is_osdesc) != NULL) && + ((osp->os_flags & FLG_OS_OUTREL) == 0)) { ofl->ofl_dynshdrcnt++; osp->os_flags |= FLG_OS_OUTREL; } @@ -1677,6 +1687,8 @@ M_ID_ARRAY, /* id_array */ M_ID_BSS, /* id_bss */ M_ID_CAP, /* id_cap */ + M_ID_CAPINFO, /* id_capinfo */ + M_ID_CAPCHAIN, /* id_capchain */ M_ID_DATA, /* id_data */ M_ID_DYNAMIC, /* id_dynamic */ M_ID_DYNSORT, /* id_dynsort */
--- a/usr/src/cmd/sgs/libld/common/machrel.sparc.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libld/common/machrel.sparc.c Mon Mar 01 10:20:48 2010 -0800 @@ -1174,12 +1174,20 @@ * Size relocations require the symbols size. */ value = sdp->sd_sym->st_size; - } else { + + } else if ((sdp->sd_flags & FLG_SY_CAP) && + sdp->sd_aux && sdp->sd_aux->sa_PLTndx) { /* - * Else the value is the symbols value. + * If this relocation is against a capabilities + * symbol, then we need to jump to an associated + * PLT, so that at runtime ld.so.1 is involved + * to determine the best binding choice. + * Otherwise, the value is the symbols value. */ + value = ld_calc_plt_addr(sdp, ofl); + + } else value = sdp->sd_sym->st_value; - } /* * Relocation against the GLOBAL_OFFSET_TABLE. @@ -1506,9 +1514,11 @@ else ofl->ofl_flags1 |= FLG_OF1_TLSOREL; } else { - Os_desc *osp = sdp->sd_isc->is_osdesc; + Os_desc *osp; + Is_desc *isp = sdp->sd_isc; - if (osp && ((osp->os_flags & FLG_OS_OUTREL) == 0)) { + if (isp && ((osp = isp->is_osdesc) != NULL) && + ((osp->os_flags & FLG_OS_OUTREL) == 0)) { ofl->ofl_dynshdrcnt++; osp->os_flags |= FLG_OS_OUTREL; } @@ -2213,6 +2223,8 @@ M_ID_ARRAY, /* id_array */ M_ID_BSS, /* id_bss */ M_ID_CAP, /* id_cap */ + M_ID_CAPINFO, /* id_capinfo */ + M_ID_CAPCHAIN, /* id_capchain */ M_ID_DATA, /* id_data */ M_ID_DYNAMIC, /* id_dynamic */ M_ID_DYNSORT, /* id_dynsort */
--- a/usr/src/cmd/sgs/libld/common/map.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libld/common/map.c Mon Mar 01 10:20:48 2010 -0800 @@ -43,11 +43,13 @@ #include "_libld.h" #include "_map.h" - /* * Process a hardware/software capabilities segment declaration definition. * hwcap_1 = val,... [ OVERRIDE ] * sfcap_1 = val,... [ OVERRIDE ] + * hwcap_2 = val,... [ OVERRIDE ] + * platcap = name,... [ OVERRIDE ] + * machcap = name,... [ OVERRIDE ] * * The values can be defined as a list of machine specify tokens, or numerics. * Tokens are representations of the sys/auxv_$MACH.h capabilities, for example: @@ -58,15 +60,15 @@ * Or, the above two capabilities could be represented as V0x3. Note, the * OVERRIDE flag is used to ensure that only those values provided via this * mapfile entry are recorded in the final image, ie. this overrides any - * hardware capabilities that may be defined in the objects read as part of this - * link-edit. Specifying: + * hardware capabilities that may be defined in the objects read as part of + * this link-edit. Specifying: * * V0x0 OVERRIDE * * effectively removes any capabilities information from the final image. */ static Boolean -map_cap(Mapfile *mf, Word type, CapMask *capmask) +map_cap(Mapfile *mf, Word type, Capmask *capmask) { Token tok; /* Current token. */ Xword number; @@ -77,8 +79,8 @@ if (DBG_ENABLED) { Dbg_cap_mapfile_title(ofl->ofl_lml, mf->mf_lineno); - Dbg_cap_entry2(ofl->ofl_lml, DBG_STATE_CURRENT, CA_SUNW_HW_1, - capmask, ld_targ.t_m.m_mach); + Dbg_cap_val_entry(ofl->ofl_lml, DBG_STATE_CURRENT, CA_SUNW_HW_1, + capmask->cm_val, ld_targ.t_m.m_mach); } while ((tok = ld_map_gettoken(mf, TK_F_STRLC, &tkv)) != @@ -137,17 +139,14 @@ return (TRUE); } - Dbg_cap_entry(ofl->ofl_lml, DBG_STATE_NEW, type, value, - ld_targ.t_m.m_mach); - capmask->cm_value |= value; + DBG_CALL(Dbg_cap_val_entry(ofl->ofl_lml, DBG_STATE_NEW, type, value, + ld_targ.t_m.m_mach)); + capmask->cm_val |= value; /* Sanity check the resulting bits */ if (!ld_map_cap_sanitize(mf, type, capmask)) return (FALSE); - DBG_CALL(Dbg_cap_entry2(ofl->ofl_lml, DBG_STATE_RESOLVED, type, - capmask, ld_targ.t_m.m_mach)); - return (TRUE); } @@ -1318,18 +1317,16 @@ if (strcmp(sgp1->sg_name, MSG_ORIG(MSG_STR_HWCAP_1)) == 0) { if (!map_cap(mf, CA_SUNW_HW_1, - &ofl->ofl_ocapset.c_hw_1)) + &ofl->ofl_ocapset.oc_hw_1)) return (FALSE); continue; - } if (strcmp(sgp1->sg_name, MSG_ORIG(MSG_STR_SFCAP_1)) == 0) { if (!map_cap(mf, CA_SUNW_SF_1, - &ofl->ofl_ocapset.c_sf_1)) + &ofl->ofl_ocapset.oc_sf_1)) return (FALSE); continue; - } /*
--- a/usr/src/cmd/sgs/libld/common/map_support.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libld/common/map_support.c Mon Mar 01 10:20:48 2010 -0800 @@ -198,12 +198,14 @@ 0, /* CA_SUNW_NULL */ FLG_OF1_OVHWCAP1, /* CA_SUNW_HW_1 */ FLG_OF1_OVSFCAP1, /* CA_SUNW_SF_1 */ - FLG_OF1_OVHWCAP2 /* CA_SUNW_HW_2 */ + FLG_OF1_OVHWCAP2, /* CA_SUNW_HW_2 */ + FLG_OF1_OVPLATCAP, /* CA_SUNW_PLAT */ + FLG_OF1_OVMACHCAP, /* CA_SUNW_MACH */ + FLG_OF1_OVIDCAP /* CA_SUNW_ID */ }; -#if CA_SUNW_NUM != (CA_SUNW_HW_2 + 1) +#if CA_SUNW_NUM != (CA_SUNW_ID + 1) #error "CA_SUNW_NUM has grown" #endif - mf->mf_ofl->ofl_flags1 |= override_flag[type]; } @@ -211,7 +213,7 @@ * Sanity check the given capability bitmask. */ Boolean -ld_map_cap_sanitize(Mapfile *mf, Word type, CapMask *capmask) +ld_map_cap_sanitize(Mapfile *mf, Word type, Capmask *capmask) { elfcap_mask_t mask; @@ -224,16 +226,16 @@ * as the bits can affect each others meaning (see sf1_cap() * in files.c). */ - if ((mask = (capmask->cm_value & ~SF1_SUNW_MASK)) != 0) { + if ((mask = (capmask->cm_val & ~SF1_SUNW_MASK)) != 0) { mf_warn(mf, MSG_INTL(MSG_MAP_BADSF1), EC_XWORD(mask)); - capmask->cm_value &= SF1_SUNW_MASK; + capmask->cm_val &= SF1_SUNW_MASK; } - if ((capmask->cm_value & + if ((capmask->cm_val & (SF1_SUNW_FPKNWN | SF1_SUNW_FPUSED)) == SF1_SUNW_FPUSED) { mf_warn(mf, MSG_INTL(MSG_MAP_BADSF1), EC_XWORD(SF1_SUNW_FPUSED)); - capmask->cm_value &= ~SF1_SUNW_FPUSED; + capmask->cm_val &= ~SF1_SUNW_FPUSED; } #if !defined(_ELF64) /* @@ -241,9 +243,9 @@ * when building a 64-bit object. Warn the user, and remove the * setting, if we're building a 32-bit object. */ - if (capmask->cm_value & SF1_SUNW_ADDR32) { + if (capmask->cm_val & SF1_SUNW_ADDR32) { mf_warn0(mf, MSG_INTL(MSG_MAP_INADDR32SF1)); - capmask->cm_value &= ~SF1_SUNW_ADDR32; + capmask->cm_val &= ~SF1_SUNW_ADDR32; } #endif } @@ -946,7 +948,7 @@ scope = ld_map_kwfind(scope_name, scope_list, SGSOFFSETOF(scope_t, name), sizeof (scope_list[0])); if (scope == NULL) { - char buf[scope_list_bufsize]; + char buf[VLA_SIZE(scope_list_bufsize)]; mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SYMSCOPE), ld_map_kwnames(scope_list, SGSOFFSETOF(scope_t, name),
--- a/usr/src/cmd/sgs/libld/common/map_v2.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libld/common/map_v2.c Mon Mar 01 10:20:48 2010 -0800 @@ -219,11 +219,11 @@ } /* - * Apply one of the three equal tokens to a capabilities CapMask. + * Apply one of the three equal tokens to a capabilities Capmask. * * entry: * mf - Mapfile descriptor - * capmask - Address of CapMask variable to alter + * capmask - Address of Capmask variable to alter * eq_tok - One of TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ, representing * the operation to carry out. * type - Capability type (CA_SUNW_*) @@ -234,34 +234,35 @@ * On success, returns TRUE (1), otherwise FALSE (0) */ static Boolean -set_capmask(Mapfile *mf, CapMask *capmask, Token eq_tok, +set_capmask(Mapfile *mf, Capmask *capmask, Token eq_tok, Word type, elfcap_mask_t value, Boolean title) { if (title) DBG_CALL(Dbg_cap_mapfile_title(mf->mf_ofl->ofl_lml, mf->mf_lineno)); - DBG_CALL(Dbg_cap_entry2(mf->mf_ofl->ofl_lml, DBG_STATE_CURRENT, - type, capmask, ld_targ.t_m.m_mach)); + DBG_CALL(Dbg_cap_val_entry(mf->mf_ofl->ofl_lml, DBG_STATE_CURRENT, + type, capmask->cm_val, ld_targ.t_m.m_mach)); switch (eq_tok) { case TK_EQUAL: - capmask->cm_value = value; - capmask->cm_exclude = 0; + capmask->cm_val = value; + capmask->cm_exc = 0; ld_map_cap_set_ovflag(mf, type); - DBG_CALL(Dbg_cap_entry2(mf->mf_ofl->ofl_lml, - DBG_STATE_RESET, type, capmask, ld_targ.t_m.m_mach)); + DBG_CALL(Dbg_cap_val_entry(mf->mf_ofl->ofl_lml, + DBG_STATE_RESET, type, capmask->cm_val, + ld_targ.t_m.m_mach)); break; case TK_PLUSEQ: - DBG_CALL(Dbg_cap_entry(mf->mf_ofl->ofl_lml, DBG_STATE_ADD, - type, value, ld_targ.t_m.m_mach)); - capmask->cm_value |= value; - capmask->cm_exclude &= ~value; + DBG_CALL(Dbg_cap_val_entry(mf->mf_ofl->ofl_lml, + DBG_STATE_ADD, type, value, ld_targ.t_m.m_mach)); + capmask->cm_val |= value; + capmask->cm_exc &= ~value; break; case TK_MINUSEQ: - DBG_CALL(Dbg_cap_entry(mf->mf_ofl->ofl_lml, DBG_STATE_EXCLUDE, - type, value, ld_targ.t_m.m_mach)); - capmask->cm_value &= ~value; - capmask->cm_exclude |= value; + DBG_CALL(Dbg_cap_val_entry(mf->mf_ofl->ofl_lml, + DBG_STATE_EXCLUDE, type, value, ld_targ.t_m.m_mach)); + capmask->cm_val &= ~value; + capmask->cm_exc |= value; break; default: /*NOTREACHED*/ @@ -273,8 +274,159 @@ return (FALSE); /* Report the final configuration */ - DBG_CALL(Dbg_cap_entry2(mf->mf_ofl->ofl_lml, - DBG_STATE_RESOLVED, type, capmask, ld_targ.t_m.m_mach)); + DBG_CALL(Dbg_cap_val_entry(mf->mf_ofl->ofl_lml, + DBG_STATE_RESOLVED, type, capmask->cm_val, ld_targ.t_m.m_mach)); + + return (TRUE); +} + +/* + * Apply one of the three equal tokens to a capabilities Caplist. + * + * entry: + * mf - Mapfile descriptor + * caplist - Address of Caplist variable to alter + * eq_tok - One of TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ, representing + * the operation to carry out. + * type - Capability type (CA_SUNW_*) + * str - String for right hand side + * title - True if a title is needed, False otherwise. + * + * exit: + * On success, returns TRUE (1), otherwise FALSE (0) + */ +static Boolean +set_capstr(Mapfile *mf, Caplist *caplist, Token eq_tok, + Word type, APlist *strs) +{ + Capstr *capstr; + Aliste idx1; + char *str; + + DBG_CALL(Dbg_cap_mapfile_title(mf->mf_ofl->ofl_lml, mf->mf_lineno)); + + if ((caplist->cl_val == NULL) || (alist_nitems(caplist->cl_val) == 0)) { + DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml, + DBG_STATE_CURRENT, type, NULL)); + } else { + for (ALIST_TRAVERSE(caplist->cl_val, idx1, capstr)) { + DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml, + DBG_STATE_CURRENT, type, capstr->cs_str)); + } + } + + switch (eq_tok) { + case TK_EQUAL: + if (caplist->cl_val) { + (void) free(caplist->cl_val); + caplist->cl_val = NULL; + } + if (caplist->cl_exc) { + (void) free(caplist->cl_exc); + caplist->cl_exc = NULL; + } + if (strs) { + for (APLIST_TRAVERSE(strs, idx1, str)) { + if ((capstr = alist_append(&caplist->cl_val, + NULL, sizeof (Capstr), + AL_CNT_CAP_NAMES)) == NULL) + return (FALSE); + capstr->cs_str = str; + DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml, + DBG_STATE_RESET, type, capstr->cs_str)); + } + } else { + DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml, + DBG_STATE_RESET, type, NULL)); + } + ld_map_cap_set_ovflag(mf, type); + break; + case TK_PLUSEQ: + for (APLIST_TRAVERSE(strs, idx1, str)) { + Aliste idx2; + const char *ostr; + int found = 0; + + /* + * Add this name to the list of names, provided the + * name doesn't already exist. + */ + for (ALIST_TRAVERSE(caplist->cl_val, idx2, capstr)) { + if (strcmp(str, capstr->cs_str) == 0) { + found++; + break; + } + } + if ((found == 0) && ((capstr = + (Capstr *)alist_append(&caplist->cl_val, NULL, + sizeof (Capstr), AL_CNT_CAP_NAMES)) == NULL)) + return (FALSE); + capstr->cs_str = str; + + /* + * Remove this name from the list of excluded names, + * provided the name already exists. + */ + for (APLIST_TRAVERSE(caplist->cl_exc, idx2, ostr)) { + if (strcmp(str, ostr) == 0) { + aplist_delete(caplist->cl_exc, &idx2); + break; + } + } + DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml, + DBG_STATE_ADD, type, str)); + } + break; + case TK_MINUSEQ: + for (APLIST_TRAVERSE(strs, idx1, str)) { + Aliste idx2; + const char *ostr; + int found = 0; + + /* + * Delete this name from the list of names, provided + * the name already exists. + */ + for (ALIST_TRAVERSE(caplist->cl_val, idx2, capstr)) { + if (strcmp(str, capstr->cs_str) == 0) { + alist_delete(caplist->cl_val, &idx2); + break; + } + } + + /* + * Add this name to the list of excluded names, + * provided the name already exists. + */ + for (APLIST_TRAVERSE(caplist->cl_exc, idx2, ostr)) { + if (strcmp(str, ostr) == 0) { + found++; + break; + } + } + if ((found == 0) && (aplist_append(&caplist->cl_exc, + str, AL_CNT_CAP_NAMES) == NULL)) + return (FALSE); + + DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml, + DBG_STATE_EXCLUDE, type, str)); + } + break; + default: + /*NOTREACHED*/ + assert(0); + } + + /* Report the final configuration */ + if ((caplist->cl_val == NULL) || (alist_nitems(caplist->cl_val) == 0)) { + DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml, + DBG_STATE_RESOLVED, type, NULL)); + } else { + for (ALIST_TRAVERSE(caplist->cl_val, idx1, capstr)) { + DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml, + DBG_STATE_RESOLVED, type, capstr->cs_str)); + } + } return (TRUE); } @@ -555,7 +707,7 @@ default: bad_attr: { - char buf[attr_list_bufsize]; + char buf[VLA_SIZE(attr_list_bufsize)]; mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_ATTR), ld_map_kwnames(attr_list, @@ -679,7 +831,7 @@ default: bad_flag: { - char buf[flag_list_bufsize]; + char buf[VLA_SIZE(flag_list_bufsize)]; mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEGFLAG), ld_map_kwnames(flag_list, @@ -704,10 +856,9 @@ #undef PF_STACK } - /* - * Parse one of the capabilities attributes that corresponds directly - * to a capabilities bitmask value (HW_xxx, SF_xxx). Values can be + * Parse one of the capabilities attributes that corresponds directly to a + * capabilities bitmask value (CA_SUNW_HW_x, CA_SUNW_SF_xx). Values can be * integers, or symbolic names that correspond to the capabilities mask * in question. * @@ -715,7 +866,7 @@ * mf - Mapfile descriptor * eq_tok - One of TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ, representing * the operation to carry out. - * capmask - CapMask from output descriptor for capability being processed. + * capmask - Capmask from output descriptor for capability being processed. * type - Capability type (CA_SUNW_*) * elfcap_from_str_func - pointer to elfcap-string-to-value function * for capability being processed. @@ -724,7 +875,7 @@ * Returns TK_SEMICOLON or TK_RIGHTBKT for success, and TK_ERROR otherwise. */ static Token -parse_cap_mask(Mapfile *mf, Token eq_tok, CapMask *capmask, +parse_cap_mask(Mapfile *mf, Token eq_tok, Capmask *capmask, Word type, elfcap_from_str_func_t *elfcap_from_str_func) { int done; @@ -770,56 +921,51 @@ } /* - * XXXRIEXXX - * - * This routine is the name version of parse_cap_mask. You need to - * add the argument that corresponds to capmask. Also, remove the - * ARGSUSED lint comment. - */ -/* * Parse one of the capabilities attributes that manages lists of names - * (CA_SUNW_PLATFORM, CA_SUNW_MACHINE). + * (CA_SUNW_PLAT and CA_SUNW_MACH). Values are symbolic names that correspond + * to the capabilities mask in question. * * entry: * mf - Mapfile descriptor * eq_tok - One of TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ, representing * the operation to carry out. + * caplist - Caplist from output descriptor for capability being processed. * type - Capability type (CA_SUNW_*) * * exit: * Returns TK_SEMICOLON or TK_RIGHTBKT for success, and TK_ERROR otherwise. */ -/*ARGSUSED*/ static Token -parse_cap_list(Mapfile *mf, Token eq_tok, Word type) +parse_cap_list(Mapfile *mf, Token eq_tok, Caplist *caplist, + Word type) { - int done; + int done, found; Token tok; ld_map_tkval_t tkv; Conv_inv_buf_t inv_buf; - - /* - * XXXRIEXXX - * - * If eq_tok is TK_EQUAL, you must clear the value and exclude lists, - * and set the 'override' bit so that the capability from the input - * objects is ignored. See set_capmask() for the logic used for - * bitmasks. - */ - for (done = 0; done == 0; ) { + APlist *strs = NULL; + Aliste idx; + const char *str; + + for (done = 0, found = 0; done == 0; found = 0) { switch (tok = ld_map_gettoken(mf, 0, &tkv)) { case TK_ERROR: return (TK_ERROR); case TK_STRING: /* - * XXXRIEXXX - * - * The name is in tkv.tkv_str. If eq_tok is TK_MINUSEQ, - * you add the name to the exclude list, and remove it - * from the value list. Otherwise, you add it to the - * value list and remove it from the exclude list. + * The name is in tkv.tkv_str. Save this string for + * set_capstr() processing, but remove any duplicates. */ + for (APLIST_TRAVERSE(strs, idx, str)) { + if (strcmp(str, tkv.tkv_str) == 0) { + found++; + break; + } + } + if ((found == 0) && (aplist_append(&strs, tkv.tkv_str, + AL_CNT_CAP_NAMES) == NULL)) + return (TK_ERROR); break; case TK_SEMICOLON: @@ -834,6 +980,8 @@ } } + if (!set_capstr(mf, caplist, eq_tok, type, strs)) + return (TK_ERROR); return (tok); } @@ -883,10 +1031,10 @@ } } - if (!set_capmask(mf, &mf->mf_ofl->ofl_ocapset.c_hw_1, eq_tok, + if (!set_capmask(mf, &mf->mf_ofl->ofl_ocapset.oc_hw_1, eq_tok, CA_SUNW_HW_1, hw1, TRUE)) return (TK_ERROR); - if (!set_capmask(mf, &mf->mf_ofl->ofl_ocapset.c_hw_2, eq_tok, + if (!set_capmask(mf, &mf->mf_ofl->ofl_ocapset.oc_hw_2, eq_tok, CA_SUNW_HW_2, hw2, FALSE)) return (TK_ERROR); return (tok); @@ -900,7 +1048,7 @@ static Token at_cap_hw_1(Mapfile *mf, Token eq_tok, void *uvalue) { - return (parse_cap_mask(mf, eq_tok, &mf->mf_ofl->ofl_ocapset.c_hw_1, + return (parse_cap_mask(mf, eq_tok, &mf->mf_ofl->ofl_ocapset.oc_hw_1, CA_SUNW_HW_1, elfcap_hw1_from_str)); } @@ -912,7 +1060,7 @@ static Token at_cap_hw_2(Mapfile *mf, Token eq_tok, void *uvalue) { - return (parse_cap_mask(mf, eq_tok, &mf->mf_ofl->ofl_ocapset.c_hw_2, + return (parse_cap_mask(mf, eq_tok, &mf->mf_ofl->ofl_ocapset.oc_hw_2, CA_SUNW_HW_2, elfcap_hw2_from_str)); } @@ -957,7 +1105,7 @@ } } - if (!set_capmask(mf, &mf->mf_ofl->ofl_ocapset.c_sf_1, eq_tok, + if (!set_capmask(mf, &mf->mf_ofl->ofl_ocapset.oc_sf_1, eq_tok, CA_SUNW_SF_1, sf1, TRUE)) return (TK_ERROR); @@ -972,7 +1120,7 @@ static Token at_cap_sf_1(Mapfile *mf, Token eq_tok, void *uvalue) { - return (parse_cap_mask(mf, eq_tok, &mf->mf_ofl->ofl_ocapset.c_sf_1, + return (parse_cap_mask(mf, eq_tok, &mf->mf_ofl->ofl_ocapset.oc_sf_1, CA_SUNW_SF_1, elfcap_sf1_from_str)); } @@ -984,14 +1132,8 @@ static Token at_cap_mach(Mapfile *mf, Token eq_tok, void *uvalue) { - /* - * XXXRIEXXX - * - * Add the missing argument, and replace the 0 with - * CA_SUNW_MACH. - */ - return (parse_cap_list(mf, eq_tok, /* cap-list-goes-here, */ - /* CA_SUNW_MACH */0)); + return (parse_cap_list(mf, eq_tok, &mf->mf_ofl->ofl_ocapset.oc_mach, + CA_SUNW_MACH)); } /* @@ -1002,14 +1144,8 @@ static Token at_cap_plat(Mapfile *mf, Token eq_tok, void *uvalue) { - /* - * XXXRIEXXX - * - * Add the missing argument, and replace the 0 with - * CA_SUNW_PLAT. - */ - return (parse_cap_list(mf, eq_tok, /* cap-list-goes-here, */ - /* CA_SUNW_PLAT */0)); + return (parse_cap_list(mf, eq_tok, &mf->mf_ofl->ofl_ocapset.oc_plat, + CA_SUNW_PLAT)); } /* @@ -1032,6 +1168,7 @@ { MSG_ORIG(MSG_MAPKW_SF), at_cap_sf, ATTR_FMT_EQ_ALL }, { MSG_ORIG(MSG_MAPKW_SF_1), at_cap_sf_1, ATTR_FMT_EQ_ALL }, + /* List must be null terminated */ { 0 } }; @@ -1049,7 +1186,7 @@ KW_NAME_SIZE(MSG_MAPKW_SF) + KW_NAME_SIZE(MSG_MAPKW_SF_1); - const char *capid = NULL; + Capstr *capstr; Token tok; ld_map_tkval_t tkv; Conv_inv_buf_t inv_buf; @@ -1066,19 +1203,24 @@ return (TK_ERROR); case TK_STRING: + capstr = &mf->mf_ofl->ofl_ocapset.oc_id; + /* - * XXXRIEXXX - * - * The ID name is in tkv.tkv_str. It needs to be saved, - * and eventually converted into a CA_SUNW_ID entry. + * The ID name is in tkv.tkv_str. Save this name in the output + * capabilities structure. Note, should multiple ID entries + * be encounterd, the last entry wins. */ - capid = tkv.tkv_str; + DBG_CALL(Dbg_cap_id(mf->mf_ofl->ofl_lml, mf->mf_lineno, + capstr->cs_str, tkv.tkv_str)); + + capstr->cs_str = tkv.tkv_str; + mf->mf_ofl->ofl_ocapset.oc_flags |= FLG_OCS_USRDEFID; /* * The name can be followed by an opening '{', or a * terminating ';' */ - switch (tok = gettoken_optattr(mf, capid)) { + switch (tok = gettoken_optattr(mf, capstr->cs_str)) { case TK_SEMICOLON: return (TK_SEMICOLON); case TK_LEFTBKT: @@ -1497,7 +1639,7 @@ default: bad_flag: { - char buf[flag_list_bufsize]; + char buf[VLA_SIZE(flag_list_bufsize)]; mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SECFLAG), ld_map_kwnames(flag_list, @@ -2687,7 +2829,7 @@ default: bad_flag: { - char buf[symflag_list_bufsize]; + char buf[VLA_SIZE(symflag_list_bufsize)]; mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SYMFLAG), ld_map_kwnames(symflag_list, @@ -2762,7 +2904,7 @@ gts_efunc_at_sym_type(Mapfile *mf, Token tok, ld_map_tkval_t *tkv) { Conv_inv_buf_t inv_buf; - char buf[at_sym_type_list_bufsize]; + char buf[VLA_SIZE(at_sym_type_list_bufsize)]; mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SYMTYPE), ld_map_kwnames(at_sym_type_list, SGSOFFSETOF(at_sym_type_t, name), @@ -3165,7 +3307,7 @@ default: bad_dirtok: { - char buf[dirlist_bufsize]; + char buf[VLA_SIZE(dirlist_bufsize)]; mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_DIR), ld_map_kwnames(dirlist,
--- a/usr/src/cmd/sgs/libld/common/place.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libld/common/place.c Mon Mar 01 10:20:48 2010 -0800 @@ -595,7 +595,7 @@ /* * Define any sections that must be thought of as referenced. These - * sections may not be referenced externaly in a manner ld(1) can + * sections may not be referenced externally in a manner ld(1) can * discover, but they must be retained (ie. not removed by -zignore). */ static const Msg RefSecs[] = { @@ -614,7 +614,7 @@ DBG_CALL(Dbg_sec_in(ofl->ofl_lml, isp)); /* - * If this section identfies group members, or this section indicates + * If this section identifies group members, or this section indicates * that it is a member of a group, determine whether the section is * still required. */
--- a/usr/src/cmd/sgs/libld/common/relocate.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libld/common/relocate.c Mon Mar 01 10:20:48 2010 -0800 @@ -23,7 +23,7 @@ * Copyright (c) 1988 AT&T * All Rights Reserved * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -282,7 +282,7 @@ * either symbol. Note, this test is very similar to the test * used in ld_sym_adjust_vis(). */ - if ((rlocal == TRUE) && ((tsdp->sd_flags & FLG_SY_HIDDEN) || + if ((rlocal == TRUE) && (SYM_IS_HIDDEN(tsdp) || (ELF_ST_BIND(tsdp->sd_sym->st_info) != STB_GLOBAL) || ((ofl->ofl_flags & (FLG_OF_AUTOLCL | FLG_OF_AUTOELM)) && ((tsdp->sd_flags & MSK_SY_NOAUTO) == 0)))) @@ -1201,7 +1201,7 @@ ((ELF_ST_BIND(sdp->sd_sym->st_info) == STB_WEAK) || (sdp->sd_flags & FLG_SY_WEAKDEF)) && (!(sdp->sd_flags & FLG_SY_MVTOCOMM))) { - Sym_desc * _sdp; + Sym_desc *_sdp; _sdp = sdp->sd_file->ifl_oldndx[sap->sa_linkndx]; if (_sdp->sd_ref != REF_DYN_SEEN) @@ -1247,7 +1247,8 @@ } else if (!(flags & FLG_OF_RELOBJ) && (IS_LOCALBND(rtype) || IS_SEG_RELATIVE(rtype))) { local = TRUE; - } else if (sdp->sd_ref == REF_REL_NEED) { + } else if ((sdp->sd_ref == REF_REL_NEED) && + ((sdp->sd_flags & FLG_SY_CAP) == 0)) { /* * Global symbols may have been individually reduced in * scope. If the whole object is to be self contained, @@ -1350,7 +1351,9 @@ if (local) return ((*ld_targ.t_mr.mr_reloc_local)(reld, ofl)); - if (IS_PLT(rtype) && ((flags & FLG_OF_BFLAG) == 0)) + if ((IS_PLT(rtype) || ((sdp->sd_flags & FLG_SY_CAP) && + (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_FUNC))) && + ((flags & FLG_OF_BFLAG) == 0)) return (ld_reloc_plt(reld, ofl)); if ((sdp->sd_ref == REF_REL_NEED) ||
--- a/usr/src/cmd/sgs/libld/common/resolve.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libld/common/resolve.c Mon Mar 01 10:20:48 2010 -0800 @@ -23,7 +23,7 @@ * Copyright (c) 1988 AT&T * All Rights Reserved * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -414,13 +414,26 @@ if (nsym->st_shndx == SHN_UNDEF) { /* - * If this is an undefined symbol it must be a - * relocatable object overriding a shared object. In - * this case also override the reference name so that - * any undefined symbol diagnostics will refer to the - * relocatable object name. + * If this is an undefined symbol, then we can only be + * attempting to override an existing undefined symbol. + * The original symbol is either: + * + * - a mapfile definition + * - a previous relocatable object whose visibility + * or type should be overridden by this new symbol + * - a previous shared object + * + * If the original undefined symbol stems from a mapfile + * then don't alter the reference file name. Should we + * end up with some form of 'undefined' symbol error, + * the characteristics of that error are most likely to + * have originated from a mapfile. + * + * Otherwise, update the reference file name to indicate + * this symbol. */ - sdp->sd_aux->sa_rfile = ifl->ifl_name; + if ((sdp->sd_flags & FLG_SY_MAPREF) == 0) + sdp->sd_aux->sa_rfile = ifl->ifl_name; } else { /* * Under -Bnodirect, all exported interfaces that have @@ -513,7 +526,9 @@ { Sym *osym = sdp->sd_sym; uchar_t obind = ELF_ST_BIND(osym->st_info); + uchar_t otype = ELF_ST_TYPE(osym->st_info); uchar_t nbind = ELF_ST_BIND(nsym->st_info); + uchar_t ntype = ELF_ST_TYPE(nsym->st_info); /* * If two relocatable objects define a weak and non-weak undefined @@ -525,7 +540,7 @@ * take the other. */ if (((obind == STB_WEAK) && (nbind != STB_WEAK)) || - (obind == STT_NOTYPE) && (nbind != STT_NOTYPE)) { + (otype == STT_NOTYPE) && (ntype != STT_NOTYPE)) { sym_override(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags); return; } @@ -1079,6 +1094,7 @@ { int row, column; /* State table coordinates */ Sym *osym = sdp->sd_sym; + sd_flag_t osdflags = sdp->sd_flags; Is_desc *isp; Half vis = 0, nfile = ifl->ifl_ehdr->e_type; Half oref = sdp->sd_ref; @@ -1086,7 +1102,7 @@ /* * Determine the original symbols definition (defines row in Action[]). */ - if (sdp->sd_flags & FLG_SY_TENTSYM) + if (osdflags & FLG_SY_TENTSYM) row = SYM_TENTATIVE; else if ((sdp->sd_sym->st_shndx == SHN_UNDEF) || (sdp->sd_sym->st_shndx == SHN_SUNW_IGNORE)) @@ -1243,6 +1259,12 @@ sdp->sd_flags |= FLG_SY_MAPUSED; } + /* + * Make sure any special symbol requirements are carried over. + */ + if ((osdflags & FLG_SY_CAP) || (nsdflags & FLG_SY_CAP)) + sdp->sd_flags |= FLG_SY_CAP; + DBG_CALL(Dbg_syms_resolved(ofl, sdp)); return (1);
--- a/usr/src/cmd/sgs/libld/common/sections.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libld/common/sections.c Mon Mar 01 10:20:48 2010 -0800 @@ -129,7 +129,7 @@ * Global symbols can only be eliminated when the interfaces of * an object have been defined via versioning/scoping. */ - if ((sdp->sd_flags & FLG_SY_HIDDEN) == 0) + if (!SYM_IS_HIDDEN(sdp)) return; /* @@ -568,13 +568,25 @@ SET_SEC_INFO_WORD_ALIGN(ELF_T_CAP, SHF_ALLOC, sizeof (Cap)); break; + case SHT_SUNW_capchain: + ofl->ofl_flags |= FLG_OF_OSABI; + SET_SEC_INFO_WORD_ALIGN(ELF_T_WORD, SHF_ALLOC, + sizeof (Capchain)); + break; + + case SHT_SUNW_capinfo: + ofl->ofl_flags |= FLG_OF_OSABI; +#if _ELF64 + SET_SEC_INFO(ELF_T_XWORD, sizeof (Xword), SHF_ALLOC, + sizeof (Capinfo)); +#else + SET_SEC_INFO(ELF_T_WORD, sizeof (Word), SHF_ALLOC, + sizeof (Capinfo)); +#endif + break; + case SHT_SUNW_move: ofl->ofl_flags |= FLG_OF_OSABI; - /* - * The sh_info field of the SHT_*_syminfo section points - * to the header index of the associated .dynamic section, - * so we also set SHF_INFO_LINK. - */ SET_SEC_INFO(ELF_T_BYTE, sizeof (Lword), SHF_ALLOC | SHF_WRITE, sizeof (Move)); break; @@ -1215,11 +1227,26 @@ } /* - * Any hardware/software capabilities? + * Capabilities require a .dynamic entry for the .SUNW_cap + * section. */ if (ofl->ofl_oscap) cnt++; /* SUNW_CAP */ + /* + * Symbol capabilities require a .dynamic entry for the + * .SUNW_capinfo section. + */ + if (ofl->ofl_oscapinfo) + cnt++; /* SUNW_CAPINFO */ + + /* + * Capabilities chain information requires a .SUNW_capchain + * entry, an entry size, and total size. + */ + if (ofl->ofl_oscapchain) + cnt += 3; /* SUNW_CAPCHAIN/ENT/SZ */ + if (flags & FLG_OF_SYMBOLIC) cnt++; /* SYMBOLIC */ } @@ -1349,97 +1376,502 @@ } /* - * Output debugging information for the given capability mask. + * Common function used to build the SHT_SUNW_versym section, SHT_SUNW_syminfo + * section, and SHT_SUNW_capinfo section. Each of these sections provide + * additional symbol information, and their size parallels the associated + * symbol table. */ -static void -dbg_capmask(Ofl_desc *ofl, Word type, CapMask *capmask) -{ - /* - * If this capability has excluded bits, then show the current - * internal state. Otherwise, don't bother, because it's identical - * to the final output value. - */ - if (capmask->cm_exclude) - Dbg_cap_entry2(ofl->ofl_lml, DBG_STATE_CURRENT, type, - capmask, ld_targ.t_m.m_mach); - - Dbg_cap_entry(ofl->ofl_lml, DBG_STATE_OUT, type, - CAPMASK_VALUE(capmask), ld_targ.t_m.m_mach); -} - -/* - * Build a hardware/software capabilities section. - */ -static uintptr_t -make_cap(Ofl_desc *ofl) +static Os_desc * +make_sym_sec(Ofl_desc *ofl, const char *sectname, Word stype, int ident) { Shdr *shdr; Elf_Data *data; Is_desc *isec; - Os_desc *osec; - Cap *cap; - size_t size = 0; - elfcap_mask_t hw_1, sf_1; - - /* Final capability masks with excluded bits removed */ - hw_1 = CAPMASK_VALUE(&ofl->ofl_ocapset.c_hw_1); - sf_1 = CAPMASK_VALUE(&ofl->ofl_ocapset.c_sf_1); + + /* + * We don't know the size of this section yet, so set it to 0. The + * size gets filled in after the associated symbol table is sized. + */ + if (new_section(ofl, stype, sectname, 0, &isec, &shdr, &data) == + S_ERROR) + return ((Os_desc *)S_ERROR); + + return (ld_place_section(ofl, isec, NULL, ident, NULL)); +} + +/* + * Determine whether a symbol capability is redundant because the object + * capabilities are more restrictive. + */ +inline static int +is_cap_redundant(Objcapset *ocapset, Objcapset *scapset) +{ + Alist *oalp, *salp; + elfcap_mask_t omsk, smsk; + + /* + * Inspect any platform capabilities. If the object defines platform + * capabilities, then the object will only be loaded for those + * platforms. A symbol capability set that doesn't define the same + * platforms is redundant, and a symbol capability that does not provide + * at least one platform name that matches a platform name in the object + * capabilities will never execute (as the object wouldn't have been + * loaded). + */ + oalp = ocapset->oc_plat.cl_val; + salp = scapset->oc_plat.cl_val; + if (oalp && ((salp == NULL) || cap_names_match(oalp, salp))) + return (1); + + /* + * If the symbol capability set defines platforms, and the object + * doesn't, then the symbol set is more restrictive. + */ + if (salp && (oalp == NULL)) + return (0); + + /* + * Next, inspect any machine name capabilities. If the object defines + * machine name capabilities, then the object will only be loaded for + * those machines. A symbol capability set that doesn't define the same + * machine names is redundant, and a symbol capability that does not + * provide at least one machine name that matches a machine name in the + * object capabilities will never execute (as the object wouldn't have + * been loaded). + */ + oalp = ocapset->oc_plat.cl_val; + salp = scapset->oc_plat.cl_val; + if (oalp && ((salp == NULL) || cap_names_match(oalp, salp))) + return (1); + + /* + * If the symbol capability set defines machine names, and the object + * doesn't, then the symbol set is more restrictive. + */ + if (salp && (oalp == NULL)) + return (0); + + /* + * Next, inspect any hardware capabilities. If the objects hardware + * capabilities are greater than or equal to that of the symbols + * capabilities, then the symbol capability set is redundant. If the + * symbols hardware capabilities are greater that the objects, then the + * symbol set is more restrictive. + * + * Note that this is a somewhat arbitrary definition, as each capability + * bit is independent of the others, and some of the higher order bits + * could be considered to be less important than lower ones. However, + * this is the only reasonable non-subjective definition. + */ + omsk = ocapset->oc_hw_2.cm_val; + smsk = scapset->oc_hw_2.cm_val; + if ((omsk > smsk) || (omsk && (omsk == smsk))) + return (1); + if (omsk < smsk) + return (0); + + /* + * Finally, inspect the remaining hardware capabilities. + */ + omsk = ocapset->oc_hw_1.cm_val; + smsk = scapset->oc_hw_1.cm_val; + if ((omsk > smsk) || (omsk && (omsk == smsk))) + return (1); + + return (0); +} + +/* + * Capabilities values might have been assigned excluded values. These + * excluded values should be removed before calculating any capabilities + * sections size. + */ +static void +capmask_value(Lm_list *lml, Word type, Capmask *capmask, int *title) +{ + /* + * First determine whether any bits should be excluded. + */ + if ((capmask->cm_val & capmask->cm_exc) == 0) + return; + + DBG_CALL(Dbg_cap_post_title(lml, title)); + + DBG_CALL(Dbg_cap_val_entry(lml, DBG_STATE_CURRENT, type, + capmask->cm_val, ld_targ.t_m.m_mach)); + DBG_CALL(Dbg_cap_val_entry(lml, DBG_STATE_EXCLUDE, type, + capmask->cm_exc, ld_targ.t_m.m_mach)); + + capmask->cm_val &= ~capmask->cm_exc; + + DBG_CALL(Dbg_cap_val_entry(lml, DBG_STATE_RESOLVED, type, + capmask->cm_val, ld_targ.t_m.m_mach)); +} + +static void +capstr_value(Lm_list *lml, Word type, Caplist *caplist, int *title) +{ + Aliste idx1, idx2; + char *estr; + Capstr *capstr; + Boolean found = FALSE; /* - * Determine how many entries are required. + * First determine whether any strings should be excluded. + */ + for (APLIST_TRAVERSE(caplist->cl_exc, idx1, estr)) { + for (ALIST_TRAVERSE(caplist->cl_val, idx2, capstr)) { + if (strcmp(estr, capstr->cs_str) == 0) { + found = TRUE; + break; + } + } + } + + if (found == FALSE) + return; + + /* + * Traverse the current strings, then delete the excluded strings, + * and finally display the resolved strings. */ - if (hw_1) - size++; - if (sf_1) - size++; - if (size == 0) - return (1); - size++; /* Add CA_SUNW_NULL */ - + if (DBG_ENABLED) { + Dbg_cap_post_title(lml, title); + for (ALIST_TRAVERSE(caplist->cl_val, idx2, capstr)) { + Dbg_cap_ptr_entry(lml, DBG_STATE_CURRENT, type, + capstr->cs_str); + } + } + for (APLIST_TRAVERSE(caplist->cl_exc, idx1, estr)) { + for (ALIST_TRAVERSE(caplist->cl_val, idx2, capstr)) { + if (strcmp(estr, capstr->cs_str) == 0) { + DBG_CALL(Dbg_cap_ptr_entry(lml, + DBG_STATE_EXCLUDE, type, capstr->cs_str)); + alist_delete(caplist->cl_val, &idx2); + break; + } + } + } if (DBG_ENABLED) { - Dbg_cap_out_title(ofl->ofl_lml); - - if (hw_1) - dbg_capmask(ofl, CA_SUNW_HW_1, - &ofl->ofl_ocapset.c_hw_1); - - if (sf_1) - dbg_capmask(ofl, CA_SUNW_SF_1, - &ofl->ofl_ocapset.c_sf_1); + for (ALIST_TRAVERSE(caplist->cl_val, idx2, capstr)) { + Dbg_cap_ptr_entry(lml, DBG_STATE_RESOLVED, type, + capstr->cs_str); + } + } +} + +/* + * Build a capabilities section. + */ +#define CAP_UPDATE(cap, capndx, tag, val) \ + cap->c_tag = tag; \ + cap->c_un.c_val = val; \ + cap++, capndx++; + +static uintptr_t +make_cap(Ofl_desc *ofl, Word shtype, const char *shname, int ident) +{ + Shdr *shdr; + Elf_Data *data; + Is_desc *isec; + Cap *cap; + size_t size = 0; + Word capndx = 0; + Str_tbl *strtbl; + Objcapset *ocapset = &ofl->ofl_ocapset; + Aliste idx1; + Capstr *capstr; + int title = 0; + + /* + * Determine which string table to use for any CA_SUNW_MACH, + * CA_SUNW_PLAT, or CA_SUNW_ID strings. + */ + if (OFL_IS_STATIC_OBJ(ofl)) + strtbl = ofl->ofl_strtab; + else + strtbl = ofl->ofl_dynstrtab; + + /* + * If symbol capabilities have been collected, but no symbols are left + * referencing these capabilities, promote the capability groups back + * to an object capability definition. + */ + if ((ofl->ofl_flags & FLG_OF_OTOSCAP) && ofl->ofl_capsymcnt && + (ofl->ofl_capfamilies == NULL)) { + ld_cap_move_symtoobj(ofl); + ofl->ofl_capsymcnt = 0; + ofl->ofl_capgroups = NULL; } - - if (new_section(ofl, SHT_SUNW_cap, MSG_ORIG(MSG_SCN_SUNWCAP), size, - &isec, &shdr, &data) == S_ERROR) + /* + * Remove any excluded capabilities. + */ + capstr_value(ofl->ofl_lml, CA_SUNW_PLAT, &ocapset->oc_plat, &title); + capstr_value(ofl->ofl_lml, CA_SUNW_MACH, &ocapset->oc_mach, &title); + capmask_value(ofl->ofl_lml, CA_SUNW_HW_2, &ocapset->oc_hw_2, &title); + capmask_value(ofl->ofl_lml, CA_SUNW_HW_1, &ocapset->oc_hw_1, &title); + capmask_value(ofl->ofl_lml, CA_SUNW_SF_1, &ocapset->oc_sf_1, &title); + + /* + * Determine how many entries are required for any object capabilities. + */ + size += alist_nitems(ocapset->oc_plat.cl_val); + size += alist_nitems(ocapset->oc_mach.cl_val); + if (ocapset->oc_hw_2.cm_val) + size++; + if (ocapset->oc_hw_1.cm_val) + size++; + if (ocapset->oc_sf_1.cm_val) + size++; + + /* + * Only identify a capabilities group if the group has content. If a + * capabilities identifier exists, and no other capabilities have been + * supplied, remove the identifier. This scenario could exist if a + * user mistakenly defined a lone identifier, or if an identified group + * was overridden so as to clear the existing capabilities and the + * identifier was not also cleared. + */ + if (ocapset->oc_id.cs_str) { + if (size) + size++; + else + ocapset->oc_id.cs_str = NULL; + } + if (size) + size++; /* Add CA_SUNW_NULL */ + + /* + * Determine how many entries are required for any symbol capabilities. + */ + if (ofl->ofl_capsymcnt) { + /* + * If there are no object capabilities, a CA_SUNW_NULL entry + * is required before any symbol capabilities. + */ + if (size == 0) + size++; + size += ofl->ofl_capsymcnt; + } + + if (size == 0) + return (NULL); + + if (new_section(ofl, shtype, shname, size, &isec, + &shdr, &data) == S_ERROR) return (S_ERROR); if ((data->d_buf = libld_malloc(shdr->sh_size)) == NULL) return (S_ERROR); cap = (Cap *)data->d_buf; - if (hw_1) { - cap->c_tag = CA_SUNW_HW_1; - cap->c_un.c_val = hw_1; - cap++; + + /* + * Fill in any object capabilities. If there is an identifier, then the + * identifier comes first. The remaining items follow in precedence + * order, although the order isn't important for runtime verification. + */ + if (ocapset->oc_id.cs_str) { + ofl->ofl_flags |= FLG_OF_CAPSTRS; + if (st_insert(strtbl, ocapset->oc_id.cs_str) == -1) + return (S_ERROR); + ocapset->oc_id.cs_ndx = capndx; + CAP_UPDATE(cap, capndx, CA_SUNW_ID, 0); + } + if (ocapset->oc_plat.cl_val) { + ofl->ofl_flags |= (FLG_OF_PTCAP | FLG_OF_CAPSTRS); + + /* + * Insert any platform name strings in the appropriate string + * table. The capability value can't be filled in yet, as the + * final offset of the strings isn't known until later. + */ + for (ALIST_TRAVERSE(ocapset->oc_plat.cl_val, idx1, capstr)) { + if (st_insert(strtbl, capstr->cs_str) == -1) + return (S_ERROR); + capstr->cs_ndx = capndx; + CAP_UPDATE(cap, capndx, CA_SUNW_PLAT, 0); + } } - if (sf_1) { - cap->c_tag = CA_SUNW_SF_1; - cap->c_un.c_val = sf_1; - cap++; + if (ocapset->oc_mach.cl_val) { + ofl->ofl_flags |= (FLG_OF_PTCAP | FLG_OF_CAPSTRS); + + /* + * Insert the machine name strings in the appropriate string + * table. The capability value can't be filled in yet, as the + * final offset of the strings isn't known until later. + */ + for (ALIST_TRAVERSE(ocapset->oc_mach.cl_val, idx1, capstr)) { + if (st_insert(strtbl, capstr->cs_str) == -1) + return (S_ERROR); + capstr->cs_ndx = capndx; + CAP_UPDATE(cap, capndx, CA_SUNW_MACH, 0); + } } - cap->c_tag = CA_SUNW_NULL; - cap->c_un.c_val = 0; + if (ocapset->oc_hw_2.cm_val) { + ofl->ofl_flags |= FLG_OF_PTCAP; + CAP_UPDATE(cap, capndx, CA_SUNW_HW_2, ocapset->oc_hw_2.cm_val); + } + if (ocapset->oc_hw_1.cm_val) { + ofl->ofl_flags |= FLG_OF_PTCAP; + CAP_UPDATE(cap, capndx, CA_SUNW_HW_1, ocapset->oc_hw_1.cm_val); + } + if (ocapset->oc_sf_1.cm_val) { + ofl->ofl_flags |= FLG_OF_PTCAP; + CAP_UPDATE(cap, capndx, CA_SUNW_SF_1, ocapset->oc_sf_1.cm_val); + } + CAP_UPDATE(cap, capndx, CA_SUNW_NULL, 0); /* - * If we're not creating a relocatable object, save the output section - * to trigger the creation of an associated program header. + * Fill in any symbol capabilities. */ - osec = ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_cap, NULL); - if ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) - ofl->ofl_oscap = osec; - - return ((uintptr_t)osec); + if (ofl->ofl_capgroups) { + Cap_group *cgp; + + for (APLIST_TRAVERSE(ofl->ofl_capgroups, idx1, cgp)) { + Objcapset *scapset = &cgp->cg_set; + Aliste idx2; + Is_desc *isp; + + cgp->cg_ndx = capndx; + + if (scapset->oc_id.cs_str) { + ofl->ofl_flags |= FLG_OF_CAPSTRS; + /* + * Insert the identifier string in the + * appropriate string table. The capability + * value can't be filled in yet, as the final + * offset of the string isn't known until later. + */ + if (st_insert(strtbl, + scapset->oc_id.cs_str) == -1) + return (S_ERROR); + scapset->oc_id.cs_ndx = capndx; + CAP_UPDATE(cap, capndx, CA_SUNW_ID, 0); + } + + if (scapset->oc_plat.cl_val) { + ofl->ofl_flags |= FLG_OF_CAPSTRS; + + /* + * Insert the platform name string in the + * appropriate string table. The capability + * value can't be filled in yet, as the final + * offset of the string isn't known until later. + */ + for (ALIST_TRAVERSE(scapset->oc_plat.cl_val, + idx2, capstr)) { + if (st_insert(strtbl, + capstr->cs_str) == -1) + return (S_ERROR); + capstr->cs_ndx = capndx; + CAP_UPDATE(cap, capndx, + CA_SUNW_PLAT, 0); + } + } + if (scapset->oc_mach.cl_val) { + ofl->ofl_flags |= FLG_OF_CAPSTRS; + + /* + * Insert the machine name string in the + * appropriate string table. The capability + * value can't be filled in yet, as the final + * offset of the string isn't known until later. + */ + for (ALIST_TRAVERSE(scapset->oc_mach.cl_val, + idx2, capstr)) { + if (st_insert(strtbl, + capstr->cs_str) == -1) + return (S_ERROR); + capstr->cs_ndx = capndx; + CAP_UPDATE(cap, capndx, + CA_SUNW_MACH, 0); + } + } + if (scapset->oc_hw_2.cm_val) { + CAP_UPDATE(cap, capndx, CA_SUNW_HW_2, + scapset->oc_hw_2.cm_val); + } + if (scapset->oc_hw_1.cm_val) { + CAP_UPDATE(cap, capndx, CA_SUNW_HW_1, + scapset->oc_hw_1.cm_val); + } + if (scapset->oc_sf_1.cm_val) { + CAP_UPDATE(cap, capndx, CA_SUNW_SF_1, + scapset->oc_sf_1.cm_val); + } + CAP_UPDATE(cap, capndx, CA_SUNW_NULL, 0); + + /* + * If any object capabilities are available, determine + * whether these symbol capabilities are less + * restrictive, and hence redundant. + */ + if (((ofl->ofl_flags & FLG_OF_PTCAP) == 0) || + (is_cap_redundant(ocapset, scapset) == 0)) + continue; + + /* + * Indicate any files that provide redundant symbol + * capabilities. + */ + for (APLIST_TRAVERSE(cgp->cg_secs, idx2, isp)) { + eprintf(ofl->ofl_lml, ERR_WARNING, + MSG_INTL(MSG_CAP_REDUNDANT), + isp->is_file->ifl_name, + EC_WORD(isp->is_scnndx), isp->is_name); + } + } + } + + /* + * If capabilities strings are required, the sh_info field of the + * section header will be set to the associated string table. + */ + if (ofl->ofl_flags & FLG_OF_CAPSTRS) + shdr->sh_flags |= SHF_INFO_LINK; + + /* + * Place these capabilities in the output file. + */ + if ((ofl->ofl_oscap = ld_place_section(ofl, isec, + NULL, ident, NULL)) == (Os_desc *)S_ERROR) + return (S_ERROR); + + /* + * If symbol capabilities are required, then a .SUNW_capinfo section is + * also created. This table will eventually be sized to match the + * associated symbol table. + */ + if (ofl->ofl_capfamilies) { + if ((ofl->ofl_oscapinfo = make_sym_sec(ofl, + MSG_ORIG(MSG_SCN_SUNWCAPINFO), SHT_SUNW_capinfo, + ld_targ.t_id.id_capinfo)) == (Os_desc *)S_ERROR) + return (S_ERROR); + + /* + * If we're generating a dynamic object, capabilities family + * members are maintained in a .SUNW_capchain section. + */ + if (ofl->ofl_capchaincnt && + ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0)) { + if (new_section(ofl, SHT_SUNW_capchain, + MSG_ORIG(MSG_SCN_SUNWCAPCHAIN), + ofl->ofl_capchaincnt, &isec, &shdr, + &data) == S_ERROR) + return (S_ERROR); + + ofl->ofl_oscapchain = ld_place_section(ofl, isec, + NULL, ld_targ.t_id.id_capchain, NULL); + if (ofl->ofl_oscapchain == (Os_desc *)S_ERROR) + return (S_ERROR); + + } + } + return (1); } +#undef CAP_UPDATE /* * Build the PLT section and its associated relocation entries. @@ -1617,7 +2049,6 @@ return (1); } - /* * Build a dynamic symbol table. These tables reside in the text * segment of a dynamic executable or shared library. @@ -1893,7 +2324,6 @@ ofl->ofl_dynscopecnt++; } - /* * Account for any local, named register symbols. These locals are * required for reference from DT_REGISTER .dynamic entries. @@ -1907,7 +2337,7 @@ if ((sdp = ofl->ofl_regsyms[ndx]) == NULL) continue; - if (((sdp->sd_flags & FLG_SY_HIDDEN) == 0) && + if (!SYM_IS_HIDDEN(sdp) && (ELF_ST_BIND(sdp->sd_sym->st_info) != STB_LOCAL)) continue; @@ -2145,29 +2575,6 @@ } /* - * Common function used to build both the SHT_SUNW_versym - * section and the SHT_SUNW_syminfo section. Each of these sections - * provides additional symbol information. - */ -static Os_desc * -make_sym_sec(Ofl_desc *ofl, const char *sectname, Word stype, int ident) -{ - Shdr *shdr; - Elf_Data *data; - Is_desc *isec; - - /* - * We don't know the size of this section yet, so set it to 0. - * It gets filled in after the dynsym is sized. - */ - if (new_section(ofl, stype, sectname, 0, &isec, &shdr, &data) == - S_ERROR) - return ((Os_desc *)S_ERROR); - - return (ld_place_section(ofl, isec, NULL, ident, NULL)); -} - -/* * This routine is called when -z nopartial is in effect. */ uintptr_t @@ -2314,7 +2721,7 @@ * * exit: * On success, rel_alpp and sym_alpp are updated, and - * any strings in the mergable input sections referenced by + * any strings in the mergeable input sections referenced by * a relocation has been entered into mstrtab. True (1) is returned. * * On failure, False (0) is returned. @@ -2446,7 +2853,7 @@ * This routine has to make 3 passes: * * 1) Examine all relocations, insert strings from relocations - * to the mergable input sections into the string table. + * to the mergeable input sections into the string table. * 2) Modify the relocation values to be correct for the * new merged section. * 3) Modify the symbols used by the relocations to reference @@ -2691,9 +3098,16 @@ if (make_interp(ofl) == S_ERROR) return (S_ERROR); - if (make_cap(ofl) == S_ERROR) + /* + * Create a capabilities section if required. + */ + if (make_cap(ofl, SHT_SUNW_cap, MSG_ORIG(MSG_SCN_SUNWCAP), + ld_targ.t_id.id_cap) == S_ERROR) return (S_ERROR); + /* + * Create any init/fini array sections. + */ if (make_array(ofl, SHT_INIT_ARRAY, MSG_ORIG(MSG_SCN_INITARRAY), ofl->ofl_initarray) == S_ERROR) return (S_ERROR); @@ -2935,6 +3349,27 @@ update_data_size(ofl->ofl_ossyminfo, cnt); } + /* + * Now that we've created all output sections, adjust the size of the + * SHT_SUNW_capinfo, which is dependent on the associated symbol table + * size. + */ + if (ofl->ofl_oscapinfo) { + ulong_t cnt; + + /* + * Symbol capabilities symbols are placed directly after the + * STT_FILE symbol, section symbols, and any register symbols. + * Effectively these are the first of any series of demoted + * (scoped) symbols. + */ + if (OFL_IS_STATIC_OBJ(ofl)) + cnt = SYMTAB_ALL_CNT(ofl); + else + cnt = DYNSYM_ALL_CNT(ofl); + + update_data_size(ofl->ofl_oscapinfo, cnt); + } return (1); }
--- a/usr/src/cmd/sgs/libld/common/support.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libld/common/support.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -216,8 +216,8 @@ * hasn't nulled out data ld(1) will try and dereference. */ if ((npath != *opath) || (nfd != *ofd) || (nelf != *oelf)) { - Dbg_file_modified(ofl->ofl_lml, flp->fl_obj, *opath, - npath, *ofd, nfd, *oelf, nelf); + DBG_CALL(Dbg_file_modified(ofl->ofl_lml, flp->fl_obj, + *opath, npath, *ofd, nfd, *oelf, nelf)); if (npath) *opath = npath; if (nfile) @@ -289,10 +289,11 @@ * difference and return the new section header. */ if (nshdr != *oshdr) { - Dbg_shdr_modified(ofl->ofl_lml, flp->fl_obj, - ifl->ifl_ehdr->e_ident[EI_OSABI], - ifl->ifl_ehdr->e_machine, ndx, *oshdr, nshdr, - sname); + Ehdr *ehdr = ifl->ifl_ehdr; + + DBG_CALL(Dbg_shdr_modified(ofl->ofl_lml, flp->fl_obj, + ehdr->e_ident[EI_OSABI], ehdr->e_machine, ndx, + *oshdr, nshdr, sname)); *oshdr = nshdr; } }
--- a/usr/src/cmd/sgs/libld/common/syms.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libld/common/syms.c Mon Mar 01 10:20:48 2010 -0800 @@ -551,10 +551,10 @@ * The `sa_dfiles' list is used to maintain the list of files that * define the same symbol. This list can be used for two reasons: * - * - To save the first definition of a symbol that is not available + * - To save the first definition of a symbol that is not available * for this link-edit. * - * - To save all definitions of a symbol when the -m option is in + * - To save all definitions of a symbol when the -m option is in * effect. This is optional as it is used to list multiple * (interposed) definitions of a symbol (refer to ldmap_out()), * and can be quite expensive. @@ -674,7 +674,7 @@ * should be defined protected, whereas all other * special symbols are tagged as no-direct. */ - if (((usdp->sd_flags & FLG_SY_HIDDEN) == 0) && + if (!SYM_IS_HIDDEN(usdp) && (sdflags & FLG_SY_DEFAULT)) { usdp->sd_aux->sa_overndx = VER_NDX_GLOBAL; if (sdaux_id == SDAUX_ID_GOT) { @@ -764,7 +764,7 @@ * automatic scoping). The GOT should be defined protected, * whereas all other special symbols are tagged as no-direct. */ - if (((sdp->sd_flags & FLG_SY_HIDDEN) == 0) && + if (!SYM_IS_HIDDEN(sdp) && (sdflags & FLG_SY_DEFAULT)) { sdp->sd_aux->sa_overndx = VER_NDX_GLOBAL; if (sdaux_id == SDAUX_ID_GOT) { @@ -941,6 +941,68 @@ } /* + * Determine a potential capability symbol's visibility. + * + * The -z symbolcap option transforms an object capabilities relocatable object + * into a symbol capabilities relocatable object. Any global function symbols, + * or initialized global data symbols are candidates for transforming into local + * symbol capabilities definitions. However, if a user indicates that a symbol + * should be demoted to local using a mapfile, then there is no need to + * transform the associated global symbol. + * + * Normally, a symbol's visibility is determined after the symbol resolution + * process, after all symbol state has been gathered and resolved. However, + * for -z symbolcap, this determination is too late. When a global symbol is + * read from an input file we need to determine it's visibility so as to decide + * whether to create a local or not. + * + * If a user has explicitly defined this symbol as having local scope within a + * mapfile, then a symbol of the same name already exists. However, explicit + * local definitions are uncommon, as most mapfiles define the global symbol + * requirements together with an auto-reduction directive '*'. If this state + * has been defined, then we must make sure that the new symbol isn't a type + * that can not be demoted to local. + */ +static int +sym_cap_vis(const char *name, Word hash, Sym *sym, Ofl_desc *ofl) +{ + Sym_desc *sdp; + uchar_t vis; + avl_index_t where; + sd_flag_t sdflags = 0; + + /* + * Determine the visibility of the new symbol. + */ + vis = ELF_ST_VISIBILITY(sym->st_other); + switch (vis) { + case STV_EXPORTED: + sdflags |= FLG_SY_EXPORT; + break; + case STV_SINGLETON: + sdflags |= FLG_SY_SINGLE; + break; + } + + /* + * Determine whether a symbol definition already exists, and if so + * obtain the visibility. + */ + if ((sdp = ld_sym_find(name, hash, &where, ofl)) != NULL) + sdflags |= sdp->sd_flags; + + /* + * Determine whether the symbol flags indicate this symbol should be + * hidden. + */ + if ((ofl->ofl_flags & (FLG_OF_AUTOLCL | FLG_OF_AUTOELM)) && + ((sdflags & MSK_SY_NOAUTO) == 0)) + sdflags |= FLG_SY_HIDDEN; + + return ((sdflags & FLG_SY_HIDDEN) == 0); +} + +/* * This routine checks to see if a symbols visibility needs to be reduced to * either SYMBOLIC or LOCAL. This routine can be called from either * reloc_init() or sym_validate(). @@ -955,10 +1017,7 @@ (sdp->sd_sym->st_shndx != SHN_UNDEF)) { /* * If auto-reduction/elimination is enabled, reduce any - * non-versioned global symbols. This routine is called either - * from any initial relocation processing that references this - * symbol, or from the symbol validation processing. - * + * non-versioned, and non-local capabilities global symbols. * A symbol is a candidate for auto-reduction/elimination if: * * - the symbol wasn't explicitly defined within a mapfile @@ -1066,17 +1125,17 @@ * counting has been carried out (ie. no more symbols will be read, generated, * or modified), validate and count the relevant entries: * - * - check and print any undefined symbols remaining. Note that - * if a symbol has been defined by virtue of the inclusion of - * an implicit shared library, it is still classed as undefined. + * - check and print any undefined symbols remaining. Note that if a symbol + * has been defined by virtue of the inclusion of an implicit shared + * library, it is still classed as undefined. * - * - count the number of global needed symbols together with the - * size of their associated name strings (if scoping has been - * indicated these symbols may be reduced to locals). + * - count the number of global needed symbols together with the size of + * their associated name strings (if scoping has been indicated these + * symbols may be reduced to locals). * - * - establish the size and alignment requirements for the global - * .bss section (the alignment of this section is based on the - * first symbol that it will contain). + * - establish the size and alignment requirements for the global .bss + * section (the alignment of this section is based on the first symbol + * that it will contain). */ uintptr_t ld_sym_validate(Ofl_desc *ofl) @@ -1093,8 +1152,7 @@ Xword lbssalign = 0, lbsssize = 0; Boolean need_lbss; #endif - int ret; - int allow_ldynsym; + int ret, allow_ldynsym; uchar_t type; DBG_CALL(Dbg_basic_validate(ofl->ofl_lml)); @@ -1406,8 +1464,7 @@ if (sdp->sd_aux && sdp->sd_aux->sa_overndx) sdp->sd_aux->sa_overndx = 0; } else { - if ((!(sdp->sd_flags & FLG_SY_HIDDEN)) && - sdp->sd_aux && + if (!SYM_IS_HIDDEN(sdp) && sdp->sd_aux && (sdp->sd_aux->sa_overndx == 0)) { sym_undef_entry(ofl, sdp, NOVERSION); ofl->ofl_flags |= verdesc; @@ -1438,8 +1495,7 @@ */ if ((sym->st_shndx == SHN_COMMON) && (((oflags & FLG_OF_RELOBJ) == 0) || - ((sdp->sd_flags & FLG_SY_HIDDEN) && - (oflags & FLG_OF_PROCRED)))) { + (SYM_IS_HIDDEN(sdp) && (oflags & FLG_OF_PROCRED)))) { if ((sdp->sd_move == NULL) || ((sdp->sd_flags & FLG_SY_PAREXPN) == 0)) { if (type != STT_TLS) { @@ -1473,7 +1529,6 @@ lbssalign = sym->st_value; } #endif - /* * If a symbol was referenced via the command line * (ld -u <>, ...), then this counts as a reference against the @@ -1487,9 +1542,12 @@ /* * Update the symbol count and the associated name string size. + * Note, a capabilities symbol must remain as visible as a + * global symbol. However, the runtime linker recognizes the + * hidden requirement and ensures the symbol isn't made globally + * available at runtime. */ - if ((sdp->sd_flags & FLG_SY_HIDDEN) && - (oflags & FLG_OF_PROCRED)) { + if (SYM_IS_HIDDEN(sdp) && (oflags & FLG_OF_PROCRED)) { /* * If any reductions are being processed, keep a count * of eliminated symbols, and if the symbol is being @@ -1590,7 +1648,7 @@ if (sdp->sd_sym->st_name == 0) sdp->sd_name = MSG_ORIG(MSG_STR_EMPTY); - if ((sdp->sd_flags & FLG_SY_HIDDEN) || + if (SYM_IS_HIDDEN(sdp) || (ELF_ST_BIND(sdp->sd_sym->st_info) == STB_LOCAL)) ofl->ofl_lregsymcnt++; } @@ -1787,18 +1845,30 @@ ofl->ofl_flags |= flag; } +/* + * Global symbols that are candidates for translation to local capability + * symbols under -z symbolcap, are maintained on a local symbol list. Once + * all symbols of a file are processed, this list is traversed to cull any + * unnecessary weak symbol aliases. + */ +typedef struct { + Sym_desc *c_nsdp; /* new lead symbol */ + Sym_desc *c_osdp; /* original symbol */ + Cap_group *c_group; /* symbol capability group */ + Word c_ndx; /* symbol index */ +} Cap_pair; /* * Process the symbol table for the specified input file. At this point all * input sections from this input file have been assigned an input section * descriptor which is saved in the `ifl_isdesc' array. * - * - local symbols are saved (as is) if the input file is a - * relocatable object + * - local symbols are saved (as is) if the input file is a relocatable + * object * - * - global symbols are added to the linkers internal symbol - * table if they are not already present, otherwise a symbol - * resolution function is called upon to resolve the conflict. + * - global symbols are added to the linkers internal symbol table if they + * are not already present, otherwise a symbol resolution function is + * called upon to resolve the conflict. */ uintptr_t ld_sym_process(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl) @@ -1850,6 +1920,8 @@ Word symsecndx; avl_index_t where; int test_gnu_hidden_bit, weak; + Cap_desc *cdp = NULL; + Alist *cappairs = NULL; /* * Its possible that a file may contain more that one symbol table, @@ -2240,6 +2312,15 @@ (ifl->ifl_versym != NULL); /* + * Determine whether object capabilities for this file are being + * converted into symbol capabilities. If so, global function symbols, + * and initialized global data symbols, need special translation and + * processing. + */ + if ((etype == ET_REL) && (ifl->ifl_flags & FLG_IF_OTOSCAP)) + cdp = ifl->ifl_caps; + + /* * Now scan the global symbols entering them in the internal symbol * table or resolving them as necessary. */ @@ -2253,6 +2334,8 @@ Word shndx; int shndx_bad = 0; Sym *nsym = sym; + Cap_pair *cpp = NULL; + uchar_t ntype; /* * Determine and validate the associated section index. @@ -2276,8 +2359,7 @@ } /* - * Now that we have the name, if the section index - * was bad, report it. + * Now that we have the name, report an erroneous section index. */ if (shndx_bad) { eprintf(ofl->ofl_lml, ERR_WARNING, @@ -2289,7 +2371,6 @@ continue; } - /* * Test for the GNU hidden bit, and ignore symbols that * have it set. @@ -2323,8 +2404,8 @@ * The '-z wrap=XXX' option emulates the GNU ld --wrap=XXX * option. When XXX is the symbol to be wrapped: * - * - An undefined reference to XXX is converted to __wrap_XXX - * - An undefined reference to __real_XXX is converted to XXX + * - An undefined reference to XXX is converted to __wrap_XXX + * - An undefined reference to __real_XXX is converted to XXX * * The idea is that the user can supply a wrapper function * __wrap_XXX that does some work, and then uses the name @@ -2424,13 +2505,107 @@ } /* + * If object capabilities for this file are being converted + * into symbol capabilities, then: + * + * - Any global function, or initialized global data symbol + * definitions (ie., those that are not associated with + * special symbol types, ie., ABS, COMMON, etc.), and which + * have not been reduced to locals, are converted to symbol + * references (UNDEF). This ensures that any reference to + * the original symbol, for example from a relocation, get + * associated to a capabilities family lead symbol, ie., a + * generic instance. + * + * - For each global function, or object symbol definition, + * a new local symbol is created. The function or object + * is renamed using the capabilities CA_SUNW_ID definition + * (which might have been fabricated for this purpose - + * see get_cap_group()). The new symbol name is: + * + * <original name>%<capability group identifier> + * + * This symbol is associated to the same location, and + * becomes a capabilities family member. + */ + /* LINTED */ + hash = (Word)elf_hash(name); + + ntype = ELF_ST_TYPE(nsym->st_info); + if (cdp && (nsym->st_shndx != SHN_UNDEF) && + ((sdflags & FLG_SY_SPECSEC) == 0) && + ((ntype == STT_FUNC) || (ntype == STT_OBJECT))) { + /* + * Determine this symbol's visibility. If a mapfile has + * indicated this symbol should be local, then there's + * no point in transforming this global symbol to a + * capabilities symbol. Otherwise, create a symbol + * capability pair descriptor to record this symbol as + * a candidate for translation. + */ + if (sym_cap_vis(name, hash, sym, ofl) && + ((cpp = alist_append(&cappairs, NULL, + sizeof (Cap_pair), AL_CNT_CAP_PAIRS)) == NULL)) + return (S_ERROR); + } + + if (cpp) { + Sym *rsym; + + DBG_CALL(Dbg_syms_cap_convert(ofl, ndx, name, nsym)); + + /* + * Allocate a new symbol descriptor to represent the + * transformed global symbol. The descriptor points + * to the original symbol information (which might + * indicate a global or weak visibility). The symbol + * information will be transformed into a local symbol + * later, after any weak aliases are culled. + */ + if ((cpp->c_osdp = + libld_malloc(sizeof (Sym_desc))) == NULL) + return (S_ERROR); + + cpp->c_osdp->sd_name = name; + cpp->c_osdp->sd_sym = nsym; + cpp->c_osdp->sd_shndx = shndx; + cpp->c_osdp->sd_file = ifl; + cpp->c_osdp->sd_isc = ifl->ifl_isdesc[shndx]; + cpp->c_osdp->sd_ref = REF_REL_NEED; + + /* + * Save the capabilities group this symbol belongs to, + * and the original symbol index. + */ + cpp->c_group = cdp->ca_groups->apl_data[0]; + cpp->c_ndx = ndx; + + /* + * Replace the original symbol definition with a symbol + * reference. Make sure this reference isn't left as a + * weak. + */ + if ((rsym = libld_malloc(sizeof (Sym))) == NULL) + return (S_ERROR); + + *rsym = *nsym; + + rsym->st_info = ELF_ST_INFO(STB_GLOBAL, ntype); + rsym->st_shndx = shndx = SHN_UNDEF; + rsym->st_value = 0; + rsym->st_size = 0; + + sdflags |= FLG_SY_CAP; + + nsym = rsym; + } + + /* * If the symbol does not already exist in the internal symbol * table add it, otherwise resolve the conflict. If the symbol * from this file is kept, retain its symbol table index for * possible use in associating a global alias. */ - /* LINTED */ - hash = (Word)elf_hash((const char *)name); if ((sdp = ld_sym_find(name, hash, &where, ofl)) == NULL) { DBG_CALL(Dbg_syms_global(ofl->ofl_lml, ndx, name)); if ((sdp = ld_sym_enter(name, nsym, hash, ifl, ofl, ndx, @@ -2442,6 +2617,13 @@ return (S_ERROR); /* + * Now that we have a symbol descriptor, retain the descriptor + * for later use by symbol capabilities processing. + */ + if (cpp) + cpp->c_nsdp = sdp; + + /* * After we've compared a defined symbol in one shared * object, flag the symbol so we don't compare it again. */ @@ -2504,7 +2686,7 @@ /* * Associate weak (alias) symbols to their non-weak counterparts by - * scaning the global symbols one more time. + * scanning the global symbols one more time. * * This association is needed when processing the symbols from a shared * object dependency when a a weak definition satisfies a reference: @@ -2650,6 +2832,155 @@ } } } + + /* + * Having processed all symbols, under -z symbolcap, reprocess any + * symbols that are being translated from global to locals. The symbol + * pair that has been collected defines the original symbol (c_osdp), + * which will become a local, and the new symbol (c_nsdp), which will + * become a reference (UNDEF) for the original. + * + * Scan these symbol pairs looking for weak symbols, which have non-weak + * aliases. There is no need to translate both of these symbols to + * locals, only the global is necessary. + */ + if (cappairs) { + Aliste idx1; + Cap_pair *cpp1; + + for (ALIST_TRAVERSE(cappairs, idx1, cpp1)) { + Sym_desc *sdp1 = cpp1->c_osdp; + Sym *sym1 = sdp1->sd_sym; + uchar_t bind1 = ELF_ST_BIND(sym1->st_info); + Aliste idx2; + Cap_pair *cpp2; + + /* + * If this symbol isn't weak, it's capability member is + * retained for the creation of a local symbol. + */ + if (bind1 != STB_WEAK) + continue; + + /* + * If this is a weak symbol, traverse the capabilities + * list again to determine if a corresponding non-weak + * symbol exists. + */ + for (ALIST_TRAVERSE(cappairs, idx2, cpp2)) { + Sym_desc *sdp2 = cpp2->c_osdp; + Sym *sym2 = sdp2->sd_sym; + uchar_t bind2 = + ELF_ST_BIND(sym2->st_info); + + if ((cpp1 == cpp2) || + (cpp1->c_group != cpp2->c_group) || + (sym1->st_value != sym2->st_value) || + (bind2 == STB_WEAK)) + continue; + + /* + * The weak symbol (sym1) has a non-weak (sym2) + * counterpart. There's no point in translating + * both of these equivalent symbols to locals. + * Add this symbol capability alias to the + * capabilities family information, and remove + * the weak symbol. + */ + if (ld_cap_add_family(ofl, cpp2->c_nsdp, + cpp1->c_nsdp, NULL, NULL) == S_ERROR) + return (S_ERROR); + + free((void *)cpp1->c_osdp); + (void) alist_delete(cappairs, &idx1); + } + } + + DBG_CALL(Dbg_util_nl(ofl->ofl_lml, DBG_NL_STD)); + + /* + * The capability pairs information now represents all the + * global symbols that need transforming to locals. These + * local symbols are renamed using their group identifiers. + */ + for (ALIST_TRAVERSE(cappairs, idx1, cpp1)) { + Sym_desc *osdp = cpp1->c_osdp; + Objcapset *capset; + size_t nsize, tsize; + const char *oname; + char *cname, *idstr; + Sym *csym; + + /* + * If the local symbol has not yet been translated + * convert it to a local symbol with a name. + */ + if ((osdp->sd_flags & FLG_SY_CAP) != 0) + continue; + + /* + * As we're converting object capabilities to symbol + * capabilities, obtain the capabilities set for this + * object, so as to retrieve the CA_SUNW_ID value. + */ + capset = &cpp1->c_group->cg_set; + + /* + * Create a new name from the existing symbol and the + * capabilities group identifier. Note, the delimiter + * between the symbol name and identifier name is hard- + * coded here (%), so that we establish a convention + * for transformed symbol names. + */ + oname = osdp->sd_name; + + idstr = capset->oc_id.cs_str; + nsize = strlen(oname); + tsize = nsize + 1 + strlen(idstr) + 1; + if ((cname = libld_malloc(tsize)) == 0) + return (S_ERROR); + + (void) strcpy(cname, oname); + cname[nsize++] = '%'; + (void) strcpy(&cname[nsize], idstr); + + /* + * Allocate a new symbol table entry, transform this + * symbol to a local, and assign the new name. + */ + if ((csym = libld_malloc(sizeof (Sym))) == NULL) + return (S_ERROR); + + *csym = *osdp->sd_sym; + csym->st_info = ELF_ST_INFO(STB_LOCAL, + ELF_ST_TYPE(osdp->sd_sym->st_info)); + + osdp->sd_name = cname; + osdp->sd_sym = csym; + osdp->sd_flags = FLG_SY_CAP; + + /* + * Keep track of this new local symbol. As -z symbolcap + * can only be used to create a relocatable object, a + * dynamic symbol table can't exist. Ensure there is + * space reserved in the string table. + */ + ofl->ofl_caploclcnt++; + if (st_insert(ofl->ofl_strtab, cname) == -1) + return (S_ERROR); + + DBG_CALL(Dbg_syms_cap_local(ofl, cpp1->c_ndx, + cname, csym, osdp)); + + /* + * Establish this capability pair as a family. + */ + if (ld_cap_add_family(ofl, cpp1->c_nsdp, osdp, + cpp1->c_group, &ifl->ifl_caps->ca_syms) == S_ERROR) + return (S_ERROR); + } + } + return (1); #undef SYM_LOC_BADADDR @@ -2657,7 +2988,7 @@ /* * Add an undefined symbol to the symbol table. The reference originates from - * the location identifed by the message id (mid). These references can + * the location identified by the message id (mid). These references can * originate from command line options such as -e, -u, -initarray, etc. * (identified with MSG_INTL(MSG_STR_COMMAND)), or from internally generated * TLS relocation references (identified with MSG_INTL(MSG_STR_TLSREL)). @@ -2754,7 +3085,7 @@ * intervenes, we will reuse the string. * * entry: - * isc - Input section assocated with the symbol. + * isc - Input section associated with the symbol. * fmt - NULL, or format string to use. * * exit:
--- a/usr/src/cmd/sgs/libld/common/update.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libld/common/update.c Mon Mar 01 10:20:48 2010 -0800 @@ -130,7 +130,6 @@ } } - /* * Build and update any output symbol tables. Here we work on all the symbol * tables at once to reduce the duplication of symbol and string manipulation. @@ -168,10 +167,9 @@ _dynsort_arr = NULL; \ } \ if ((_dynsort_arr != NULL) && DYNSORT_TEST_ATTR(_sdp, _sym)) \ - _dynsort_arr[(*_dynsort_ndx)++] = _sym_ndx; \ + _dynsort_arr[(*_dynsort_ndx)++] = _sym_ndx; \ } - Sym_desc *sdp; Sym_avlnode *sav; Sg_desc *sgp, *tsgp = NULL, *dsgp = NULL, *esgp = NULL; @@ -218,7 +216,6 @@ Word *hashtab; /* hash table pointer */ Word *hashbkt; /* hash table bucket pointer */ Word *hashchain; /* hash table chain pointer */ - Word hashval; /* value of hash function */ Wk_desc *wkp; Alist *weak = NULL; ofl_flag_t flags = ofl->ofl_flags; @@ -373,7 +370,7 @@ if (DBG_ENABLED) { if ((ofl->ofl_gottable = gottable = libld_calloc(ofl->ofl_gotcnt, sizeof (Gottable))) == NULL) - return ((Addr)S_ERROR); + return ((Addr)S_ERROR); } /* @@ -485,7 +482,7 @@ if ((rsdp = ofl->ofl_regsyms[ndx]) == NULL) continue; - if (((rsdp->sd_flags & FLG_SY_HIDDEN) == 0) && + if (!SYM_IS_HIDDEN(rsdp) && (ELF_ST_BIND(rsdp->sd_sym->st_info) != STB_LOCAL)) continue; @@ -630,7 +627,8 @@ * assigning a new virtual address or displacement (value). */ for (APLIST_TRAVERSE(ofl->ofl_objs, idx1, ifl)) { - Xword lndx, local = ifl->ifl_locscnt; + Xword lndx, local = ifl->ifl_locscnt; + Cap_desc *cdp = ifl->ifl_caps; for (lndx = 1; lndx < local; lndx++) { Gotndx *gnp; @@ -697,7 +695,6 @@ if (ifl != sdp->sd_file) continue; - /* * Generate an output symbol to represent this input * symbol. Even if the symbol table is to be stripped @@ -716,6 +713,7 @@ if (!dynsym) sdp->sd_symndx = *symndx; symtab[symtab_ndx] = *sym; + /* * Provided this isn't an unnamed register * symbol, update its name. @@ -798,7 +796,7 @@ * If this isn't an UNDEF symbol (ie. an input section * is associated), update the symbols value and index. */ - if (((isc = sdp->sd_isc) != 0) && !update_done) { + if (((isc = sdp->sd_isc) != NULL) && !update_done) { Word sectndx; osp = isc->is_osdesc; @@ -852,7 +850,53 @@ ldynsym_ndx++; } } + + /* + * If this input file has undergone object to symbol + * capabilities conversion, supply any new capabilities symbols. + * These symbols are copies of the original global symbols, and + * follow the existing local symbols that are supplied from this + * input file (which are identified with a preceding STT_FILE). + */ + if (symtab && cdp && cdp->ca_syms) { + Aliste idx2; + Cap_sym *csp; + + for (APLIST_TRAVERSE(cdp->ca_syms, idx2, csp)) { + Is_desc *isp; + + sdp = csp->cs_sdp; + sym = sdp->sd_sym; + + if ((isp = sdp->sd_isc) != NULL) { + Os_desc *osp = isp->is_osdesc; + + /* + * Update the symbols value. + */ + /* LINTED */ + sym->st_value += + (Off)_elf_getxoff(isp->is_indata); + if ((flags & FLG_OF_RELOBJ) == 0) + sym->st_value += + osp->os_shdr->sh_addr; + + /* + * Update the symbols section index. + */ + sdp->sd_shndx = sym->st_shndx = + elf_ndxscn(osp->os_scn); + } + + symtab[symtab_ndx] = *sym; + (void) st_setstring(strtab, sdp->sd_name, + &stoff); + symtab[symtab_ndx].st_name = stoff; + sdp->sd_symndx = symtab_ndx++; + } + } } + symtab_gbl_bndx = symtab_ndx; /* .symtab index of 1st global entry */ /* @@ -921,7 +965,6 @@ lbssndx = elf_ndxscn(osp->os_scn); } #endif - /* * Assign .tlsbss information for use with updating COMMON symbols. */ @@ -972,7 +1015,7 @@ if (sdp->sd_ref == REF_DYN_SEEN) continue; - if ((sdp->sd_flags & FLG_SY_HIDDEN) && (flags & FLG_OF_PROCRED)) + if (SYM_IS_HIDDEN(sdp) && (flags & FLG_OF_PROCRED)) local = 1; else local = 0; @@ -1082,6 +1125,52 @@ } } + /* + * If this is a dynamic object then add any local capabilities symbols. + */ + if (dynsym && ofl->ofl_capfamilies) { + Cap_avlnode *cav; + + for (cav = avl_first(ofl->ofl_capfamilies); cav; + cav = AVL_NEXT(ofl->ofl_capfamilies, cav)) { + Cap_sym *csp; + Aliste idx; + + for (APLIST_TRAVERSE(cav->cn_members, idx, csp)) { + sdp = csp->cs_sdp; + + DBG_CALL(Dbg_syms_created(ofl->ofl_lml, + sdp->sd_name)); + DBG_CALL(Dbg_syms_entered(ofl, sdp->sd_sym, + sdp)); + + dynsym[dynsym_ndx] = *sdp->sd_sym; + + (void) st_setstring(dynstr, sdp->sd_name, + &stoff); + dynsym[dynsym_ndx].st_name = stoff; + + sdp->sd_sym = &dynsym[dynsym_ndx]; + sdp->sd_symndx = dynsym_ndx; + + /* + * Indicate that this is a capabilities symbol. + * Note, that this identification only provides + * information regarding the symbol that is + * visible from elfdump(1) -y. The association + * of a symbol to its capabilities is derived + * from a .SUNW_capinfo entry. + */ + if (syminfo) { + syminfo[dynsym_ndx].si_flags |= + SYMINFO_FLG_CAP; + } + + dynsym_ndx++; + } + } + } + if (ofl->ofl_hashbkts) { qsort(sorted_syms + ofl->ofl_scopecnt + ofl->ofl_elimcnt, ofl->ofl_globcnt, sizeof (Sym_s_list), @@ -1131,15 +1220,13 @@ } } - /* * If this symbol has been marked as being reduced to local * scope then it will have to be placed in the scoped portion * of the .symtab. Retain the appropriate index for use in * version symbol indexing and relocation. */ - if ((sdp->sd_flags & FLG_SY_HIDDEN) && - (flags & FLG_OF_PROCRED)) { + if (SYM_IS_HIDDEN(sdp) && (flags & FLG_OF_PROCRED)) { local = 1; if (!(sdp->sd_flags & FLG_SY_ELIM) && !dynsym) sdp->sd_symndx = scopesym_ndx; @@ -1177,12 +1264,11 @@ if (sdp->sd_flags & FLG_SY_MVTOCOMM) { vndx = VER_NDX_GLOBAL; } else if (sdp->sd_ref == REF_REL_NEED) { - sd_flag_t sdflags = sdp->sd_flags; - vndx = sap->sa_overndx; + if ((vndx == 0) && (sdp->sd_sym->st_shndx != SHN_UNDEF)) { - if (sdflags & FLG_SY_HIDDEN) + if (SYM_IS_HIDDEN(sdp)) vndx = VER_NDX_LOCAL; else vndx = VER_NDX_GLOBAL; @@ -1293,7 +1379,7 @@ * An auxiliary filter definition. By nature, * this definition is direct, in that should the * filtee lookup fail, we'll fall back to this - * object. It may still be necesssary to + * object. It may still be necessary to * prevent external direct bindings. */ syminfo[ndx].si_flags |= SYMINFO_FLG_AUXILIARY; @@ -1348,6 +1434,20 @@ syminfo[ndx].si_boundto = SYMINFO_BT_SELF; } + + /* + * Indicate that this is a capabilities symbol. + * Note, that this identification only provides + * information regarding the symbol that is + * visible from elfdump(1) -y. The association + * of a symbol to its capabilities is derived + * from a .SUNW_capinfo entry. + */ + if ((sdp->sd_flags & FLG_SY_CAP) && + ofl->ofl_oscapinfo) { + syminfo[ndx].si_flags |= + SYMINFO_FLG_CAP; + } } } @@ -1397,7 +1497,7 @@ dynsym[dynsym_ndx].st_name = stoff; if (stoff) { - Word _hashndx; + Word hashval, _hashndx; hashval = sap->sa_hash % ofl->ofl_hashbkts; @@ -1428,6 +1528,7 @@ ADD_TO_DYNSORT(sdp, sym, ELF_ST_TYPE(sym->st_info), ldynsym_cnt + dynsym_ndx); } + if (!enter_in_symtab && (!dynsym || (local && !dynlocal))) { if (!(sdp->sd_flags & FLG_SY_UPREQD)) continue; @@ -1435,7 +1536,6 @@ } else sdp->sd_flags &= ~FLG_SY_CLEAN; - /* * If we have a weak data symbol for which we need the real * symbol also, save this processing until later. @@ -1775,7 +1875,7 @@ * be local, otherwise if it's from a shared object then we need * to maintain the binding of the original reference. */ - if (sdp->sd_flags & FLG_SY_HIDDEN) { + if (SYM_IS_HIDDEN(sdp)) { if (flags & FLG_OF_PROCRED) bind = STB_LOCAL; else @@ -2357,14 +2457,14 @@ if (ofl->ofl_osmove) { shdr = ofl->ofl_osmove->os_shdr; - dyn->d_tag = DT_MOVEENT; - dyn->d_un.d_val = shdr->sh_entsize; + dyn->d_tag = DT_MOVETAB; + dyn->d_un.d_val = shdr->sh_addr; dyn++; dyn->d_tag = DT_MOVESZ; dyn->d_un.d_val = shdr->sh_size; dyn++; - dyn->d_tag = DT_MOVETAB; - dyn->d_un.d_val = shdr->sh_addr; + dyn->d_tag = DT_MOVEENT; + dyn->d_un.d_val = shdr->sh_entsize; dyn++; } if (ofl->ofl_regsymcnt) { @@ -2407,7 +2507,24 @@ dyn->d_un.d_val = ofl->ofl_oscap->os_shdr->sh_addr; dyn++; } - + if (ofl->ofl_oscapinfo) { + dyn->d_tag = DT_SUNW_CAPINFO; + dyn->d_un.d_val = ofl->ofl_oscapinfo->os_shdr->sh_addr; + dyn++; + } + if (ofl->ofl_oscapchain) { + shdr = ofl->ofl_oscapchain->os_shdr; + + dyn->d_tag = DT_SUNW_CAPCHAIN; + dyn->d_un.d_val = shdr->sh_addr; + dyn++; + dyn->d_tag = DT_SUNW_CAPCHAINSZ; + dyn->d_un.d_val = shdr->sh_size; + dyn++; + dyn->d_tag = DT_SUNW_CAPCHAINENT; + dyn->d_un.d_val = shdr->sh_entsize; + dyn++; + } if (flags & FLG_OF_SYMBOLIC) { dyn->d_tag = DT_SYMBOLIC; dyn->d_un.d_val = 0; @@ -3118,6 +3235,281 @@ } /* + * Update capabilities information. + * + * If string table capabilities exist, then the associated string must be + * translated into an offset into the string table. + */ +static void +update_oscap(Ofl_desc *ofl) +{ + Os_desc *strosp, *cosp; + Cap *cap; + Str_tbl *strtbl; + Capstr *capstr; + size_t stoff; + Aliste idx1; + + /* + * Determine which symbol table or string table is appropriate. + */ + if (OFL_IS_STATIC_OBJ(ofl)) { + strosp = ofl->ofl_osstrtab; + strtbl = ofl->ofl_strtab; + } else { + strosp = ofl->ofl_osdynstr; + strtbl = ofl->ofl_dynstrtab; + } + + /* + * If symbol capabilities exist, set the sh_link field of the .SUNW_cap + * section to the .SUNW_capinfo section. + */ + if (ofl->ofl_oscapinfo) { + cosp = ofl->ofl_oscap; + cosp->os_shdr->sh_link = + (Word)elf_ndxscn(ofl->ofl_oscapinfo->os_scn); + } + + /* + * If there are capability strings to process, set the sh_info + * field of the .SUNW_cap section to the associated string table, and + * proceed to process any CA_SUNW_PLAT entries. + */ + if ((ofl->ofl_flags & FLG_OF_CAPSTRS) == 0) + return; + + cosp = ofl->ofl_oscap; + cosp->os_shdr->sh_info = (Word)elf_ndxscn(strosp->os_scn); + + cap = ofl->ofl_oscap->os_outdata->d_buf; + + /* + * Determine whether an object capability identifier, or object + * machine/platform capabilities exists. + */ + capstr = &ofl->ofl_ocapset.oc_id; + if (capstr->cs_str) { + (void) st_setstring(strtbl, capstr->cs_str, &stoff); + cap[capstr->cs_ndx].c_un.c_ptr = stoff; + } + for (ALIST_TRAVERSE(ofl->ofl_ocapset.oc_plat.cl_val, idx1, capstr)) { + (void) st_setstring(strtbl, capstr->cs_str, &stoff); + cap[capstr->cs_ndx].c_un.c_ptr = stoff; + } + for (ALIST_TRAVERSE(ofl->ofl_ocapset.oc_mach.cl_val, idx1, capstr)) { + (void) st_setstring(strtbl, capstr->cs_str, &stoff); + cap[capstr->cs_ndx].c_un.c_ptr = stoff; + } + + /* + * Determine any symbol capability identifiers, or machine/platform + * capabilities. + */ + if (ofl->ofl_capgroups) { + Cap_group *cgp; + + for (APLIST_TRAVERSE(ofl->ofl_capgroups, idx1, cgp)) { + Objcapset *ocapset = &cgp->cg_set; + Aliste idx2; + + capstr = &ocapset->oc_id; + if (capstr->cs_str) { + (void) st_setstring(strtbl, capstr->cs_str, + &stoff); + cap[capstr->cs_ndx].c_un.c_ptr = stoff; + } + for (ALIST_TRAVERSE(ocapset->oc_plat.cl_val, idx2, + capstr)) { + (void) st_setstring(strtbl, capstr->cs_str, + &stoff); + cap[capstr->cs_ndx].c_un.c_ptr = stoff; + } + for (ALIST_TRAVERSE(ocapset->oc_mach.cl_val, idx2, + capstr)) { + (void) st_setstring(strtbl, capstr->cs_str, + &stoff); + cap[capstr->cs_ndx].c_un.c_ptr = stoff; + } + } + } +} + +/* + * Update the .SUNW_capinfo, and possibly the .SUNW_capchain sections. + */ +static void +update_oscapinfo(Ofl_desc *ofl) +{ + Os_desc *symosp, *ciosp, *ccosp = NULL; + Capinfo *ocapinfo; + Capchain *ocapchain; + Cap_avlnode *cav; + Word chainndx = 0; + + /* + * Determine which symbol table is appropriate. + */ + if (OFL_IS_STATIC_OBJ(ofl)) + symosp = ofl->ofl_ossymtab; + else + symosp = ofl->ofl_osdynsym; + + /* + * Update the .SUNW_capinfo sh_link to point to the appropriate symbol + * table section. If we're creating a dynamic object, the + * .SUNW_capinfo sh_info is updated to point to the .SUNW_capchain + * section. + */ + ciosp = ofl->ofl_oscapinfo; + ciosp->os_shdr->sh_link = (Word)elf_ndxscn(symosp->os_scn); + + if (OFL_IS_STATIC_OBJ(ofl) == 0) { + ccosp = ofl->ofl_oscapchain; + ciosp->os_shdr->sh_info = (Word)elf_ndxscn(ccosp->os_scn); + } + + /* + * Establish the data for each section. The first element of each + * section defines the section's version number. + */ + ocapinfo = ciosp->os_outdata->d_buf; + ocapinfo[0] = CAPINFO_CURRENT; + if (ccosp) { + ocapchain = ccosp->os_outdata->d_buf; + ocapchain[chainndx++] = CAPCHAIN_CURRENT; + } + + /* + * Traverse all capabilities families. Each member has a .SUNW_capinfo + * assignment. The .SUNW_capinfo entry differs for relocatable objects + * and dynamic objects. + * + * Relocatable objects: + * ELF_C_GROUP ELF_C_SYM + * + * Family lead: CAPINFO_SUNW_GLOB lead symbol index + * Family lead alias: CAPINFO_SUNW_GLOB lead symbol index + * Family member: .SUNW_cap index lead symbol index + * + * Dynamic objects: + * ELF_C_GROUP ELF_C_SYM + * + * Family lead: CAPINFO_SUNW_GLOB .SUNW_capchain index + * Family lead alias: CAPINFO_SUNW_GLOB .SUNW_capchain index + * Family member: .SUNW_cap index lead symbol index + * + * The ELF_C_GROUP field identifies a capabilities symbol. Lead + * capability symbols, and lead capability aliases are identified by + * a CAPINFO_SUNW_GLOB group identifier. For family members, the + * ELF_C_GROUP provides an index to the associate capabilities group + * (i.e, an index into the SUNW_cap section that defines a group). + * + * For relocatable objects, the ELF_C_SYM field identifies the lead + * capability symbol. For the lead symbol itself, the .SUNW_capinfo + * index is the same as the ELF_C_SYM value. For lead alias symbols, + * the .SUNW_capinfo index differs from the ELF_C_SYM value. This + * differentiation of CAPINFO_SUNW_GLOB symbols allows ld(1) to + * identify, and propagate lead alias symbols. For example, the lead + * capability symbol memcpy() would have the ELF_C_SYM for memcpy(), + * and the lead alias _memcpy() would also have the ELF_C_SYM for + * memcpy(). + * + * For dynamic objects, both a lead capability symbol, and alias symbol + * would have a ELF_C_SYM value that represents the same capability + * chain index. The capability chain allows ld.so.1 to traverse a + * family chain for a given lead symbol, and select the most appropriate + * family member. The .SUNW_capchain array contains a series of symbol + * indexes for each family member: + * + * chaincap[n] chaincap[n + 1] chaincap[n + 2] chaincap[n + x] + * foo() ndx foo%x() ndx foo%y() ndx 0 + * + * For family members, the ELF_C_SYM value associates the capability + * members with their family lead symbol. This association, although + * unused within a dynamic object, allows ld(1) to identify, and + * propagate family members when processing relocatable objects. + */ + for (cav = avl_first(ofl->ofl_capfamilies); cav; + cav = AVL_NEXT(ofl->ofl_capfamilies, cav)) { + Cap_sym *csp; + Aliste idx; + Sym_desc *asdp, *lsdp = cav->cn_symavlnode.sav_sdp; + + if (ccosp) { + /* + * For a dynamic object, identify this lead symbol, and + * point it to the head of a capability chain. Set the + * head of the capability chain to the same lead symbol. + */ + ocapinfo[lsdp->sd_symndx] = + ELF_C_INFO(chainndx, CAPINFO_SUNW_GLOB); + ocapchain[chainndx] = lsdp->sd_symndx; + } else { + /* + * For a relocatable object, identify this lead symbol, + * and set the lead symbol index to itself. + */ + ocapinfo[lsdp->sd_symndx] = + ELF_C_INFO(lsdp->sd_symndx, CAPINFO_SUNW_GLOB); + } + + /* + * Gather any lead symbol aliases. + */ + for (APLIST_TRAVERSE(cav->cn_aliases, idx, asdp)) { + if (ccosp) { + /* + * For a dynamic object, identify this lead + * alias symbol, and point it to the same + * capability chain index as the lead symbol. + */ + ocapinfo[asdp->sd_symndx] = + ELF_C_INFO(chainndx, CAPINFO_SUNW_GLOB); + } else { + /* + * For a relocatable object, identify this lead + * alias symbol, and set the lead symbol index + * to the lead symbol. + */ + ocapinfo[asdp->sd_symndx] = + ELF_C_INFO(lsdp->sd_symndx, + CAPINFO_SUNW_GLOB); + } + } + + chainndx++; + + /* + * Gather the family members. + */ + for (APLIST_TRAVERSE(cav->cn_members, idx, csp)) { + Sym_desc *msdp = csp->cs_sdp; + + /* + * Identify the members capability group, and the lead + * symbol of the family this symbol is a member of. + */ + ocapinfo[msdp->sd_symndx] = + ELF_C_INFO(lsdp->sd_symndx, csp->cs_group->cg_ndx); + if (ccosp) { + /* + * For a dynamic object, set the next capability + * chain to point to this family member. + */ + ocapchain[chainndx++] = msdp->sd_symndx; + } + } + + /* + * Any chain of family members is terminated with a 0 element. + */ + if (ccosp) + ocapchain[chainndx++] = 0; + } +} + +/* * Translate the shdr->sh_{link, info} from its input section value to that * of the corresponding shdr->sh_{link, info} output section value. */ @@ -3215,7 +3607,7 @@ */ if (ofl->ofl_flags & FLG_OF_EXEC) { #if defined(_ELF64) - if (ofl->ofl_ocapset.c_sf_1.cm_value & SF1_SUNW_ADDR32) + if (ofl->ofl_ocapset.oc_sf_1.cm_val & SF1_SUNW_ADDR32) vaddr = ld_targ.t_m.m_segm_aorigin; else #endif @@ -3287,7 +3679,8 @@ * virtual address. This is updated later. */ if (phdr->p_type == PT_SUNWCAP) { - if (ofl->ofl_oscap) { + if (ofl->ofl_oscap && (ofl->ofl_flags & FLG_OF_PTCAP) && + ((flags & FLG_OF_RELOBJ) == 0)) { capsgp = sgp; capsndx = segndx; cappndx = phdrndx++; @@ -3360,19 +3753,20 @@ */ if (phdr->p_type == PT_TLS) { Os_desc *tlsosp; - Shdr *firstshdr = NULL, *lastfileshdr = NULL; - Shdr *lastshdr; + Shdr *lastfileshdr = NULL; + Shdr *firstshdr = NULL, *lastshdr; Aliste idx; if (ofl->ofl_ostlsseg == NULL) continue; /* - * Scan through the sections that have contributed TLS. + * Scan the output sections that have contributed TLS. * Remember the first and last so as to determine the * TLS memory size requirement. Remember the last - * non-nobits section to determine the TLS data - * contribution, which determines the TLS file size. + * progbits section to determine the TLS data + * contribution, which determines the TLS program + * header filesz. */ for (APLIST_TRAVERSE(ofl->ofl_ostlsseg, idx, tlsosp)) { Shdr *tlsshdr = tlsosp->os_shdr; @@ -3389,14 +3783,26 @@ phdr->p_offset = firstshdr->sh_offset; phdr->p_align = firstshdr->sh_addralign; + /* + * Determine the initialized TLS data size. This + * address range is from the start of the TLS segment + * to the end of the last piece of initialized data. + */ if (lastfileshdr) phdr->p_filesz = lastfileshdr->sh_offset + lastfileshdr->sh_size - phdr->p_offset; else phdr->p_filesz = 0; - phdr->p_memsz = lastshdr->sh_offset + - lastshdr->sh_size - phdr->p_offset; + /* + * Determine the total TLS memory size. This includes + * all TLS data and TLS uninitialized data. This + * address range is from the start of the TLS segment + * to the memory address of the last piece of + * uninitialized data. + */ + phdr->p_memsz = lastshdr->sh_addr + + lastshdr->sh_size - phdr->p_vaddr; DBG_CALL(Dbg_seg_entry(ofl, segndx, sgp)); ofl->ofl_phdr[phdrndx] = *phdr; @@ -3407,7 +3813,7 @@ /* * If this is an empty segment declaration, it will occur after * all other loadable segments. As empty segments can be - * defind with fixed addresses, make sure that no loadable + * defined with fixed addresses, make sure that no loadable * segments overlap. This might occur as the object evolves * and the loadable segments grow, thus encroaching upon an * existing segment reservation. @@ -3737,7 +4143,8 @@ phdr->p_memsz = sdp->sd_sym->st_size; /* - * Take permisions of the segment the symbol is associated with. + * Take permissions from the segment that the symbol is + * associated with. */ aphdr = &sdp->sd_isc->is_osdesc->os_sgdesc->sg_phdr; assert(aphdr); @@ -3802,6 +4209,14 @@ } /* + * Update capabilities information if required. + */ + if (ofl->ofl_oscap) + update_oscap(ofl); + if (ofl->ofl_oscapinfo) + update_oscapinfo(ofl); + + /* * Sanity test: the first and last data byte of a string table * must be NULL. */
--- a/usr/src/cmd/sgs/libld/common/util.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libld/common/util.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -704,3 +704,36 @@ else return (name); } + +/* + * Compare a series of platform or machine hardware names. + */ +int +cap_names_match(Alist *alp1, Alist *alp2) +{ + Capstr *capstr1; + Aliste idx1; + int match = 0; + Word nitems; + + if ((nitems = alist_nitems(alp1)) != alist_nitems(alp2)) + return (1); + + for (ALIST_TRAVERSE(alp1, idx1, capstr1)) { + Capstr *capstr2; + Aliste idx2; + + for (ALIST_TRAVERSE(alp2, idx2, capstr2)) { + if (strcmp(capstr1->cs_str, capstr2->cs_str)) + continue; + + match++; + break; + } + } + + if (nitems == match) + return (0); + + return (1); +}
--- a/usr/src/cmd/sgs/libld/common/version.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libld/common/version.c Mon Mar 01 10:20:48 2010 -0800 @@ -919,7 +919,7 @@ } if (vndx == VER_NDX_GLOBAL) { - if ((sdp->sd_flags & FLG_SY_HIDDEN) == 0) + if (!SYM_IS_HIDDEN(sdp)) sdp->sd_flags |= (FLG_SY_DEFAULT | FLG_SY_EXPDEF); if (sdp->sd_aux->sa_overndx <= VER_NDX_GLOBAL) sdp->sd_aux->sa_overndx = VER_NDX_GLOBAL; @@ -937,7 +937,7 @@ return; } - if ((sdp->sd_flags & FLG_SY_HIDDEN) == 0) + if (!SYM_IS_HIDDEN(sdp)) sdp->sd_flags |= (FLG_SY_DEFAULT | FLG_SY_EXPDEF); /*
--- a/usr/src/cmd/sgs/liblddbg/Makefile.com Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/liblddbg/Makefile.com Mon Mar 01 10:20:48 2010 -0800 @@ -18,6 +18,7 @@ # # CDDL HEADER END # + # # Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. @@ -59,17 +60,9 @@ LINTFLAGS64 += -u -D_REENTRANT CPPFLAGS += -I$(SRCBASE)/lib/libc/inc $(VAR_LIBLDDBG_CPPFLAGS) -DYNFLAGS += $(VERSREF) '-R$$ORIGIN' +DYNFLAGS += $(VERSREF) $(CC_USE_PROTO) '-R$$ORIGIN' LDLIBS += $(CONVLIBDIR) $(CONV_LIB) -lc -# A bug in pmake causes redundancy when '+=' is conditionally assigned, so -# '=' is used with extra variables. -# $(DYNLIB) := DYNFLAGS += $(USE_PROTO) -# -XXXFLAGS= -$(DYNLIB) := XXXFLAGS= $(USE_PROTO) -DYNFLAGS += $(XXXFLAGS) - native := DYNFLAGS += $(CONVLIBDIR) BLTDEFS = msg.h
--- a/usr/src/cmd/sgs/liblddbg/common/cap.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/liblddbg/common/cap.c Mon Mar 01 10:20:48 2010 -0800 @@ -32,40 +32,117 @@ #include "_debug.h" void -Dbg_cap_hw_candidate(Lm_list *lml, const char *name) +Dbg_cap_candidate(Lm_list *lml, const char *name) { if (DBG_NOTCLASS(DBG_C_CAP | DBG_C_FILES)) return; - dbg_print(lml, MSG_INTL(MSG_CAP_HW_CANDIDATE), name); + dbg_print(lml, MSG_INTL(MSG_CAP_CANDIDATE), name); } void -Dbg_cap_hw_filter(Lm_list *lml, const char *dir, Rt_map *flmp) +Dbg_cap_filter(Lm_list *lml, const char *dir, Rt_map *flmp) { if (DBG_NOTCLASS(DBG_C_CAP | DBG_C_FILES)) return; Dbg_util_nl(lml, DBG_NL_STD); if (flmp) - dbg_print(lml, MSG_INTL(MSG_CAP_HWFILTR_1), dir, NAME(flmp)); + dbg_print(lml, MSG_INTL(MSG_CAP_FILTER_1), dir, NAME(flmp)); else - dbg_print(lml, MSG_INTL(MSG_CAP_HWFILTR_2), dir); + dbg_print(lml, MSG_INTL(MSG_CAP_FILTER_2), dir); } void -Dbg_cap_val_hw1(Lm_list *lml, Xword val, Half mach) +Dbg_cap_val(Lm_list *lml, Syscapset *sys, Syscapset *alt, Half mach) { - Conv_cap_val_hw1_buf_t cap_val_hw1_buf; + Conv_cap_val_buf_t cap_val_buf; + + if ((sys->sc_plat == NULL) && (sys->sc_mach == NULL) && + (sys->sc_hw_2 == 0) && (sys->sc_hw_1 == 0) && + (sys->sc_sf_1 == 0)) + return; Dbg_util_nl(lml, DBG_NL_FRC); - dbg_print(lml, MSG_INTL(MSG_CAP_VAL_HW1), - conv_cap_val_hw1(val, mach, 0, &cap_val_hw1_buf)); + + /* + * Print any capabilities in precedence order. + */ + if (sys->sc_plat) { + dbg_print(lml, MSG_INTL(MSG_CAP_SYS_PLAT), sys->sc_plat); + } + if (sys->sc_mach) { + dbg_print(lml, MSG_INTL(MSG_CAP_SYS_MACH), sys->sc_mach); + } + if (sys->sc_hw_2) { + dbg_print(lml, MSG_INTL(MSG_CAP_SYS_HW_2), + conv_cap_val_hw2(sys->sc_hw_2, mach, 0, + &cap_val_buf.cap_val_hw2_buf)); + } + if (sys->sc_hw_1) { + dbg_print(lml, MSG_INTL(MSG_CAP_SYS_HW_1), + conv_cap_val_hw1(sys->sc_hw_1, mach, 0, + &cap_val_buf.cap_val_hw1_buf)); + } + if (sys->sc_sf_1) { + dbg_print(lml, MSG_INTL(MSG_CAP_SYS_SF_1), + conv_cap_val_sf1(sys->sc_sf_1, mach, 0, + &cap_val_buf.cap_val_sf1_buf)); + } + + if (alt != sys) { + Dbg_util_nl(lml, DBG_NL_FRC); + if (alt->sc_plat != sys->sc_plat) { + dbg_print(lml, MSG_INTL(MSG_CAP_ALT_PLAT), + alt->sc_plat); + } + if (alt->sc_mach != sys->sc_mach) { + dbg_print(lml, MSG_INTL(MSG_CAP_ALT_MACH), + alt->sc_mach); + } + if (alt->sc_hw_2 != sys->sc_hw_2) { + dbg_print(lml, MSG_INTL(MSG_CAP_ALT_HW_2), + conv_cap_val_hw2(alt->sc_hw_2, mach, 0, + &cap_val_buf.cap_val_hw2_buf)); + } + if (alt->sc_hw_1 != sys->sc_hw_1) { + dbg_print(lml, MSG_INTL(MSG_CAP_ALT_HW_1), + conv_cap_val_hw1(alt->sc_hw_1, mach, 0, + &cap_val_buf.cap_val_hw1_buf)); + } + if (alt->sc_sf_1 != sys->sc_sf_1) { + dbg_print(lml, MSG_INTL(MSG_CAP_ALT_SF_1), + conv_cap_val_sf1(alt->sc_sf_1, mach, 0, + &cap_val_buf.cap_val_sf1_buf)); + } + } + Dbg_util_nl(lml, DBG_NL_FRC); } +/* + * This version takes a pointer to a Capmask, and will report the exclusion + * bits if they exist. + */ void -Dbg_cap_entry(Lm_list *lml, dbg_state_t dbg_state, Xword tag, Xword val, +Dbg_cap_ptr_entry(Lm_list *lml, dbg_state_t dbg_state, Xword tag, + const char *ptr) +{ + Conv_inv_buf_t inv_buf; + + if (DBG_NOTCLASS(DBG_C_CAP)) + return; + + dbg_print(lml, MSG_INTL(MSG_CAP_SEC_ENTRY), Dbg_state_str(dbg_state), + conv_cap_tag(tag, 0, &inv_buf), ptr); +} + +/* + * This version takes a pointer to a CapMask, and will report the exclusion + * bits if they exist. + */ +void +Dbg_cap_val_entry(Lm_list *lml, dbg_state_t dbg_state, Xword tag, Xword val, Half mach) { Conv_inv_buf_t inv_buf; @@ -74,40 +151,11 @@ if (DBG_NOTCLASS(DBG_C_CAP)) return; - dbg_print(lml, MSG_INTL(MSG_CAP_ENTRY), Dbg_state_str(dbg_state), - conv_cap_tag(tag, 0, &inv_buf), conv_cap_val(tag, val, mach, + dbg_print(lml, MSG_INTL(MSG_CAP_SEC_ENTRY), Dbg_state_str(dbg_state), + conv_cap_tag(tag, 0, &inv_buf), conv_cap_val(tag, val, mach, 0, &cap_val_buf)); } -/* - * This version takes a pointer to a CapMask, and will report the exclusion - * bits if they exist. - */ -void -Dbg_cap_entry2(Lm_list *lml, dbg_state_t dbg_state, Xword tag, CapMask *cmp, - Half mach) -{ - Conv_inv_buf_t inv_buf; - Conv_cap_val_buf_t cap_val_buf1, cap_val_buf2; - - if (DBG_NOTCLASS(DBG_C_CAP)) - return; - - /* If there is no exclusion mask, use the simpler format */ - if (cmp->cm_exclude == 0) { - dbg_print(lml, MSG_INTL(MSG_CAP_ENTRY), - Dbg_state_str(dbg_state), conv_cap_tag(tag, 0, &inv_buf), - conv_cap_val(tag, cmp->cm_value, mach, &cap_val_buf1)); - return; - } - - - dbg_print(lml, MSG_INTL(MSG_CAP_ENTRY_EXC), Dbg_state_str(dbg_state), - conv_cap_tag(tag, 0, &inv_buf), - conv_cap_val(tag, cmp->cm_value, mach, &cap_val_buf1), - conv_cap_val(tag, cmp->cm_exclude, mach, &cap_val_buf2)); -} - void Dbg_cap_sec_title(Lm_list *lml, const char *name) { @@ -119,16 +167,6 @@ } void -Dbg_cap_out_title(Lm_list *lml) -{ - if (DBG_NOTCLASS(DBG_C_CAP)) - return; - - Dbg_util_nl(lml, DBG_NL_STD); - dbg_print(lml, MSG_INTL(MSG_CAP_OUT_TITLE)); -} - -void Dbg_cap_mapfile_title(Lm_list *lml, Lineno lineno) { if (DBG_NOTCLASS(DBG_C_MAP | DBG_C_CAP)) @@ -138,20 +176,57 @@ } void +Dbg_cap_id(Lm_list *lml, Lineno lineno, const char *oid, const char *nid) +{ + Dbg_cap_mapfile_title(lml, lineno); + Dbg_cap_ptr_entry(lml, DBG_STATE_CURRENT, CA_SUNW_ID, oid); + Dbg_cap_ptr_entry(lml, DBG_STATE_NEW, CA_SUNW_ID, nid); + Dbg_cap_ptr_entry(lml, DBG_STATE_RESOLVED, CA_SUNW_ID, nid); +} + +void +Dbg_cap_post_title(Lm_list *lml, int *title) +{ + if (DBG_NOTCLASS(DBG_C_CAP)) + return; + + Dbg_util_nl(lml, DBG_NL_STD); + if ((*title)++ == 0) + dbg_print(lml, MSG_INTL(MSG_CAP_POST_TITLE)); +} + +void Elf_cap_title(Lm_list *lml) { dbg_print(lml, MSG_INTL(MSG_CAP_ELF_TITLE)); } void -Elf_cap_entry(Lm_list *lml, Cap *cap, int ndx, Half mach) +Elf_cap_entry(Lm_list *lml, Cap *cap, int ndx, const char *str, size_t str_size, + Half mach) { Conv_inv_buf_t inv_buf; Conv_cap_val_buf_t cap_val_buf; char index[INDEX_STR_SIZE]; (void) snprintf(index, INDEX_STR_SIZE, MSG_ORIG(MSG_FMT_INDEX), ndx); + + switch (cap->c_tag) { + case CA_SUNW_PLAT: + case CA_SUNW_MACH: + case CA_SUNW_ID: + /* If offset is in range, format as a string */ + if (str && (cap->c_un.c_ptr < str_size)) { + str += cap->c_un.c_ptr; + break; + } + /*FALLTHROUGH*/ + default: + /* Format numerically */ + str = conv_cap_val(cap->c_tag, cap->c_un.c_val, mach, 0, + &cap_val_buf); + } + dbg_print(lml, MSG_INTL(MSG_CAP_ELF_ENTRY), index, - conv_cap_tag(cap->c_tag, 0, &inv_buf), - conv_cap_val(cap->c_tag, cap->c_un.c_val, mach, &cap_val_buf)); + conv_cap_tag(cap->c_tag, 0, &inv_buf), str); }
--- a/usr/src/cmd/sgs/liblddbg/common/debug.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/liblddbg/common/debug.c Mon Mar 01 10:20:48 2010 -0800 @@ -563,8 +563,8 @@ MSG_STR_MOD_AFTER, /* MSG_INTL(MSG_STR_MOD_AFTER) */ MSG_STR_NEW, /* MSG_INTL(MSG_STR_NEW) */ MSG_STR_NEW_IMPLICIT, /* MSG_INTL(MSG_STR_NEW_IMPLICIT) */ - MSG_STR_OUT, /* MSG_INTL(MSG_STR_OUT) */ MSG_STR_RESET, /* MSG_INTL(MSG_STR_RESET) */ + MSG_STR_ORIGINAL, /* MSG_INTL(MSG_STR_ORIGINAL) */ MSG_STR_RESOLVED, /* MSG_INTL(MSG_STR_RESOLVED) */ }; #if DBG_STATE_NUM != (DBG_STATE_RESOLVED + 1)
--- a/usr/src/cmd/sgs/liblddbg/common/files.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/liblddbg/common/files.c Mon Mar 01 10:20:48 2010 -0800 @@ -574,6 +574,9 @@ Conv_config_feat_buf_t config_feat_buf; const char *str; + if (features == 0) + return; + switch (features & ~CONF_FEATMSK) { case DBG_CONF_IGNORE: str = MSG_INTL(MSG_FIL_CONFIG_ERR_1); @@ -732,7 +735,12 @@ MSG_REJ_US3, /* MSG_INTL(MSG_REJ_US3) */ MSG_REJ_STR, /* MSG_INTL(MSG_REJ_STR) */ MSG_REJ_UNKFILE, /* MSG_INTL(MSG_REJ_UNKFILE) */ + MSG_REJ_UNKCAP, /* MSG_INTL(MSG_REJ_UNKCAP) */ MSG_REJ_HWCAP_1, /* MSG_INTL(MSG_REJ_HWCAP_1) */ + MSG_REJ_SFCAP_1, /* MSG_INTL(MSG_REJ_SFCAP_1) */ + MSG_REJ_MACHCAP, /* MSG_INTL(MSG_REJ_MACHCAP) */ + MSG_REJ_PLATCAP, /* MSG_INTL(MSG_REJ_PLATCAP) */ + MSG_REJ_HWCAP_2 /* MSG_INTL(MSG_REJ_HWCAP_2) */ }; void
--- a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg Mon Mar 01 10:20:48 2010 -0800 @@ -393,7 +393,7 @@ # # all display information for all categories # basic basic trace information/warnings -# cap hardware/software capabilities +# cap platform/machine/hardware/software capabilities # files input file processing (files and libraries) # help this help message # libs library search paths; detail flag shows @@ -419,7 +419,8 @@ @ MSG_USE_R7_B " basic basic trace information/warnings" # TRANSLATION_NOTE -- do not translate the first token "cap". -@ MSG_USE_R7_C " cap hardware/software capabilities" +@ MSG_USE_R7_C " cap platform/machine/hardware/software \ + capabilities" # TRANSLATION_NOTE -- do not translate the first token "files". @ MSG_USE_R7_D " files input file processing (files \ @@ -745,8 +746,17 @@ required" @ MSG_REJ_STR "obj=%s; rejected: %s" @ MSG_REJ_UNKFILE "obj=%s; rejected: unknown file type" -@ MSG_REJ_HWCAP_1 "obj=%s; rejected: hardware capability unsupported: \ - %s" +@ MSG_REJ_UNKCAP "obj=%s; rejected: unknown capability: %d" +@ MSG_REJ_HWCAP_1 "obj=%s; rejected: hardware capability (CA_SUNW_HW_1) \ + unsupported: %s" +@ MSG_REJ_SFCAP_1 "obj=%s; rejected: software capability (CA_SUNW_SF_1) \ + unsupported: %s" +@ MSG_REJ_MACHCAP "obj=%s; rejected: machine capability (CA_SUNW_MACH) \ + unsupported: %s" +@ MSG_REJ_PLATCAP "obj=%s; rejected: platform capability (CA_SUNW_PLAT) \ + unsupported: %s" +@ MSG_REJ_HWCAP_2 "obj=%s; rejected: hardware capability (CA_SUNW_HW_2) \ + unsupported: %s" # Libs messages @@ -797,8 +807,8 @@ @ MSG_MAP_SORT_TITLE_O "before:" @ MSG_MAP_SORT_TITLE_S "after:" @ MSG_MAP_POST_TITLE "mapfile post processing" -@ MSG_MAP_ENT_ORD_TITLE "set entrance criteria input section sort keys \ - (ec_ordndx); segment=%s" +@ MSG_MAP_ENT_ORD_TITLE "set entrance criteria input section sort keys; \ + segment=%s" @ MSG_MAP_ID_ADD "%s: %lld: enter conditional expression id: %s" @ MSG_MAP_ID_CLEAR "%s: %lld: delete conditional expression id: %s" @@ -945,6 +955,8 @@ @ MSG_SYM_REDUCED "symbol table processing; reducing global symbols" @ MSG_SYM_RETAINING "symbol table processing; retaining local symbols" @ MSG_SYM_VERSION "symbol table processing; adding version symbols" +@ MSG_SYM_CAPABILITIES "symbol table processing; adding local capabilities \ + symbols" @ MSG_SYM_BASIC "symbol[%d]=%s" @ MSG_SYM_ADDING "symbol[%d]=%s (global); adding" @@ -962,7 +974,11 @@ discarded file=%s" @ MSG_SYM_DISCARD_DUP "symbol[%d]=%s; discarded duplicate: originates from \ file=%s" -@ MSG_SYM_WRAP "symbol[%d]=%s renamed to %s (-z wrap)" +@ MSG_SYM_WRAP "symbol[%d]=%s renamed to %s (-z wrap)" +@ MSG_SYM_CAP_ORIG "symbol[%d]=%s converting to symbol capability \ + (-z symbolcap)" +@ MSG_SYM_CAP_LOCAL "symbol[%d]=%s creating local capability \ + (-z symbolcap)" @ MSG_SYM_AOUT "symbol=%s; (original AOUT name)" @ MSG_SYM_LOOKUP "symbol=%s; lookup in file=%s [ %s ]" @@ -970,6 +986,21 @@ @ MSG_SYM_DLSYM_2 "symbol=%s; dlsym() called from file=%s; starting \ at file=%s %s %s" +@ MSG_CAP_SYM_DEFAULT " symbol=%s[%u]: capability family default" +@ MSG_CAP_SYM_USED " symbol=%s[%u]: used" +@ MSG_CAP_SYM_CANDIDATE " symbol=%s[%u]: capability candidate" +@ MSG_CAP_SYM_REJECTED " symbol=%s[%u]: capability rejected" +@ MSG_CAP_SYM_HW_1 " symbol=%s[%u]: capability specific \ + (CA_SUNW_HW_1): [ %s ]" +@ MSG_CAP_SYM_SF_1 " symbol=%s[%u]: capability specific \ + (CA_SUNW_SF_1): [ %s ]" +@ MSG_CAP_SYM_MACH " symbol=%s[%u]: capability specific \ + (CA_SUNW_MACH): [ %s ]" +@ MSG_CAP_SYM_PLAT " symbol=%s[%u]: capability specific \ + (CA_SUNW_PLAT): [ %s ]" +@ MSG_CAP_SYM_HW_2 " symbol=%s[%u]: capability specific \ + (CA_SUNW_HW_2): [ %s ]" + @ MSG_SYM_LAZY_RESCAN "rescanning for lazy dependencies for symbol: %s" @ MSG_SYM_DUPSORTADDR "section %s: symbol '%s' and symbol '%s' have the \ @@ -1065,6 +1096,7 @@ @ MSG_STR_IGNORE "ignored" @ MSG_STR_ENTERED "entered" +@ MSG_STR_ORIGINAL "original" @ MSG_STR_EXCLUDE "exclude" @ MSG_STR_RESET "reset" @ MSG_STR_IN " in" @@ -1122,20 +1154,28 @@ @ MSG_STATS_RELOCS_OUT " Relocations output: records=%lld" @ MSG_STATS_RELOCS_IN " Relocations input: records=%-10lld applied=%lld" -# Hardware/Software capabilities messages +# Capabilities messages -@ MSG_CAP_VAL_HW1 "hardware capabilities - %s" +@ MSG_CAP_SYS_HW_1 "hardware capabilities (CA_SUNW_HW_1) - %s" +@ MSG_CAP_SYS_SF_1 "software capabilities (CA_SUNW_SF_1) - %s" +@ MSG_CAP_SYS_MACH "machine capability (CA_SUNW_MACH) - %s" +@ MSG_CAP_SYS_PLAT "platform capability (CA_SUNW_PLAT) - %s" +@ MSG_CAP_SYS_HW_2 "hardware capabilities (CA_SUNW_HW_2) - %s" + +@ MSG_CAP_ALT_HW_1 "alternative hardware capabilities (CA_SUNW_HW_1) - %s" +@ MSG_CAP_ALT_SF_1 "alternative software capabilities (CA_SUNW_SF_1) - %s" +@ MSG_CAP_ALT_MACH "alternative machine capability (CA_SUNW_MACH) - %s" +@ MSG_CAP_ALT_PLAT "alternative platform capability (CA_SUNW_PLAT) - %s" +@ MSG_CAP_ALT_HW_2 "alternative hardware capabilities (CA_SUNW_HW_2) - %s" @ MSG_CAP_SEC_TITLE "capabilities; input file=%s" -@ MSG_CAP_OUT_TITLE "output capabilities" -@ MSG_CAP_ENTRY "%12.12s %-15.15s %s" -@ MSG_CAP_ENTRY_EXC "%12.12s %-15.15s %s, exclude %s" +@ MSG_CAP_SEC_ENTRY "%12.12s %-15.15s %s" -@ MSG_CAP_HW_CANDIDATE "obj=%s; hardware capabilities candidate" +@ MSG_CAP_CANDIDATE "obj=%s; capabilities candidate" +@ MSG_CAP_POST_TITLE "capabilities post processing" -@ MSG_CAP_HWFILTR_1 "dir=%s; hardware capability directory filtered by %s" -@ MSG_CAP_HWFILTR_2 "dir=%s; no hardware capability objects found" - +@ MSG_CAP_FILTER_1 "dir=%s; capability directory filtered by %s" +@ MSG_CAP_FILTER_2 "dir=%s; no capability objects found" @ MSG_ELF_HEADER "ELF Header" @@ -1146,7 +1186,6 @@ @ MSG_CAP_ELF_TITLE " index tag value" @ MSG_CAP_ELF_ENTRY "%10.10s %-15.15s %s" - # Dynamic entries. # TRANSLATION_NOTE - the following two entries provide for a series of one or # more dynamic table entries that align with the initial title. @@ -1154,7 +1193,6 @@ @ MSG_DYN_TITLE " index tag value" @ MSG_DYN_ENTRY "%10.10s %-16.16s %-#16llx %s" - # Symbol table entries. # TRANSLATION_NOTE - the following entries provide for a series of one or more # standard 32-bit symbol table entries that align with the initial title. @@ -1205,6 +1243,7 @@ bound to symbol" @ MSG_SYMINFO_ENTRY "%10.10s %-8s %7s %-24s %s" +@ MSG_SYMINFO_CAP "<symbol capabilities>" @ MSG_SYMINFO_SELF "<self>" @ MSG_SYMINFO_PARENT "<parent>" @ MSG_SYMINFO_EXTERN "<extern>"
--- a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg Mon Mar 01 10:20:48 2010 -0800 @@ -73,28 +73,22 @@ void Dbg32_bind_weak(Rt_map *, Elf32_Addr, Elf32_Addr, const char *); void Dbg64_bind_weak(Rt_map *, Elf64_Addr, Elf64_Addr, const char *); -void Dbg32_cap_entry(Lm_list *, uint_t, Elf32_Word, Elf32_Word, - Elf32_Half); -void Dbg64_cap_entry(Lm_list *, uint_t, Elf64_Xword, Elf64_Xword, - Elf64_Half); -void Dbg32_cap_entry2(Lm_list *, uint_t, Elf32_Word, CapMask *, - Elf32_Half); -void Dbg64_cap_entry2(Lm_list *, uint_t, Elf64_Xword, CapMask *, - Elf64_Half); -void Dbg32_cap_out_title(Lm_list *); -void Dbg64_cap_out_title(Lm_list *); -void Dbg32_cap_hw_candidate(Lm_list *, const char *); -void Dbg64_cap_hw_candidate(Lm_list *, const char *); -void Dbg32_cap_hw_filter(Lm_list *, const char *, Rt_map *); -void Dbg64_cap_hw_filter(Lm_list *, const char *, Rt_map *); +void Dbg32_cap_candidate(Lm_list *, const char *); +void Dbg64_cap_candidate(Lm_list *, const char *); +void Dbg32_cap_filter(Lm_list *, const char *, Rt_map *); +void Dbg64_cap_filter(Lm_list *, const char *, Rt_map *); +void Dbg32_cap_id(Lm_list *, Lineno, const char *, const char *); +void Dbg64_cap_id(Lm_list *, Lineno, const char *, const char *); void Dbg32_cap_mapfile_title(Lm_list *, Lineno); void Dbg64_cap_mapfile_title(Lm_list *, Lineno); +void Dbg32_cap_post_title(Lm_list *, int *); +void Dbg64_cap_post_title(Lm_list *, int *); void Dbg32_cap_out_title(Lm_list *); void Dbg64_cap_out_title(Lm_list *); void Dbg32_cap_sec_title(Lm_list *, const char *); void Dbg64_cap_sec_title(Lm_list *, const char *); -void Dbg32_cap_val_hw1(Lm_list *, Elf32_Word, Elf32_Half); -void Dbg64_cap_val_hw1(Lm_list *, Elf64_Xword, Elf64_Half); +void Dbg32_cap_val(Lm_list *, Syscapset *, Syscapset *, Elf32_Half); +void Dbg64_cap_val(Lm_list *, Syscapset *, Syscapset *, Elf64_Half); void Dbg32_cb_iphdr_callback(Lm_list *, struct dl_phdr_info *); void Dbg64_cb_iphdr_callback(Lm_list *, struct dl_phdr_info *); @@ -394,6 +388,16 @@ void Dbg64_syms_ar_resolve(Lm_list *, Xword, Elf_Arsym *, const char *, int); void Dbg32_syms_ar_title(Lm_list *, const char *, int); void Dbg64_syms_ar_title(Lm_list *, const char *, int); +void Dbg32_syms_cap_convert(Ofl_desc *, Word, const char *, Sym *); +void Dbg64_syms_cap_convert(Ofl_desc *, Word, const char *, Sym *); +void Dbg32_syms_cap_local(Ofl_desc *, Word, const char *, Sym *, Sym_desc *); +void Dbg64_syms_cap_local(Ofl_desc *, Word, const char *, Sym *, Sym_desc *); +void Dbg32_syms_cap_lookup(Rt_map *, uint_t, const char *, uint_t, Half, + Syscapset *); +void Dbg64_syms_cap_lookup(Rt_map *, uint_t, const char *, uint_t, Half, + Syscapset *); +void Dbg32_syms_cap_title(Ofl_desc *); +void Dbg64_syms_cap_title(Ofl_desc *); void Dbg32_syms_created(Lm_list *, const char *); void Dbg64_syms_created(Lm_list *, const char *); void Dbg32_syms_discarded(Lm_list *, Sym_desc *); @@ -510,8 +514,10 @@ void Elf_ver_line_4(Lm_list *, const char *); void Elf_ver_line_5(Lm_list *, const char *, const char *); -void Elf64_cap_entry(Lm_list *, Elf64_Cap *, int ndx, Elf64_Half); -void Elf32_cap_entry(Lm_list *, Elf32_Cap *, int ndx, Elf32_Half); +void Elf64_cap_entry(Lm_list *, Elf64_Cap *, int ndx, const char *, size_t, + Elf64_Half); +void Elf32_cap_entry(Lm_list *, Elf32_Cap *, int ndx, const char *, size_t, + Elf32_Half); void Elf64_cap_title(Lm_list *); void Elf32_cap_title(Lm_list *);
--- a/usr/src/cmd/sgs/liblddbg/common/map.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/liblddbg/common/map.c Mon Mar 01 10:20:48 2010 -0800 @@ -319,7 +319,6 @@ dbg_print(lml, MSG_INTL(MSG_MAP_POST_TITLE)); } - void Dbg_map_hdr_noalloc(Lm_list *lml, Lineno lineno) {
--- a/usr/src/cmd/sgs/liblddbg/common/mapfile-vers Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/liblddbg/common/mapfile-vers Mon Mar 01 10:20:48 2010 -0800 @@ -41,7 +41,7 @@ # MAPFILE HEADER END # -SUNWprivate_4.76 { +SUNWprivate_4.77 { global: dbg_desc = NODIRECT; # interposed - ld.so.1(1) dbg_print = NODIRECT; # interposed - ld(1) and ld.so.1(1) @@ -83,22 +83,24 @@ Dbg32_bind_weak; Dbg64_bind_weak; - Dbg32_cap_hw_candidate; - Dbg64_cap_hw_candidate; - Dbg32_cap_hw_filter; - Dbg64_cap_hw_filter; + Dbg32_cap_candidate; + Dbg64_cap_candidate; + Dbg32_cap_filter; + Dbg64_cap_filter; + Dbg32_cap_id; + Dbg64_cap_id; Dbg32_cap_mapfile_title; Dbg64_cap_mapfile_title; - Dbg32_cap_entry; - Dbg64_cap_entry; - Dbg32_cap_entry2; - Dbg64_cap_entry2; - Dbg32_cap_out_title; - Dbg64_cap_out_title; + Dbg32_cap_post_title; + Dbg64_cap_post_title; + Dbg32_cap_ptr_entry; + Dbg64_cap_ptr_entry; Dbg32_cap_sec_title; Dbg64_cap_sec_title; - Dbg32_cap_val_hw1; - Dbg64_cap_val_hw1; + Dbg32_cap_val; + Dbg64_cap_val; + Dbg32_cap_val_entry; + Dbg64_cap_val_entry; Dbg32_cb_iphdr_callback; Dbg64_cb_iphdr_callback; @@ -377,6 +379,14 @@ Dbg64_syms_ar_resolve; Dbg32_syms_ar_title; Dbg64_syms_ar_title; + Dbg32_syms_cap_convert; + Dbg64_syms_cap_convert; + Dbg32_syms_cap_local; + Dbg64_syms_cap_local; + Dbg32_syms_cap_lookup; + Dbg64_syms_cap_lookup; + Dbg32_syms_cap_title; + Dbg64_syms_cap_title; Dbg32_syms_created; Dbg64_syms_created; Dbg32_syms_discarded;
--- a/usr/src/cmd/sgs/liblddbg/common/syminfo.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/liblddbg/common/syminfo.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,11 +20,9 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sgs.h> #include <stdio.h> #include <debug.h> @@ -43,19 +41,26 @@ Elf_syminfo_entry(Lm_list *lml, Word ndx, Syminfo *sip, const char *name, const char *needed) { - const char *bndstr, *str; + const char *bndstr = NULL, *str; char flagstr[FLAGSZ], sndxstr[NDXSZ], dndxstr[NDXSZ]; int flgndx = 0; Half flags = sip->si_flags; + if (flags & SYMINFO_FLG_CAP) { + bndstr = MSG_INTL(MSG_SYMINFO_CAP); + flagstr[flgndx++] = 'S'; + flags &= ~SYMINFO_FLG_CAP; + } + if (flags & SYMINFO_FLG_DIRECT) { - if (sip->si_boundto == SYMINFO_BT_SELF) - bndstr = MSG_INTL(MSG_SYMINFO_SELF); - else if (sip->si_boundto == SYMINFO_BT_PARENT) - bndstr = MSG_INTL(MSG_SYMINFO_PARENT); - else - bndstr = needed; - + if (bndstr == NULL) { + if (sip->si_boundto == SYMINFO_BT_SELF) + bndstr = MSG_INTL(MSG_SYMINFO_SELF); + else if (sip->si_boundto == SYMINFO_BT_PARENT) + bndstr = MSG_INTL(MSG_SYMINFO_PARENT); + else + bndstr = needed; + } flagstr[flgndx++] = 'D'; flags &= ~SYMINFO_FLG_DIRECT; @@ -71,7 +76,7 @@ } else if (sip->si_boundto == SYMINFO_BT_EXTERN) bndstr = MSG_INTL(MSG_SYMINFO_EXTERN); - else + else if (bndstr == NULL) bndstr = MSG_ORIG(MSG_STR_EMPTY); if (flags & SYMINFO_FLG_DIRECTBIND) {
--- a/usr/src/cmd/sgs/liblddbg/common/syms.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/liblddbg/common/syms.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -55,6 +55,54 @@ NAME(lmp), type); } +static const Msg captype[DBG_CAP_MACH + 1] = { + MSG_CAP_SYM_DEFAULT, /* MSG_INTL(MSG_CAP_SYM_DEFAULT) */ + MSG_CAP_SYM_USED, /* MSG_INTL(MSG_CAP_SYM_USED) */ + MSG_CAP_SYM_CANDIDATE, /* MSG_INTL(MSG_CAP_SYM_CANDIDATE) */ + MSG_CAP_SYM_REJECTED, /* MSG_INTL(MSG_CAP_SYM_REJECTED) */ + MSG_CAP_SYM_HW_1, /* MSG_INTL(MSG_CAP_SYM_HW_1) */ + MSG_CAP_SYM_SF_1, /* MSG_INTL(MSG_CAP_SYM_SF_1) */ + MSG_CAP_SYM_HW_2, /* MSG_INTL(MSG_CAP_SYM_HW_2) */ + MSG_CAP_SYM_PLAT, /* MSG_INTL(MSG_CAP_SYM_PLAT) */ + MSG_CAP_SYM_MACH /* MSG_INTL(MSG_CAP_SYM_MACH) */ +}; + +void +Dbg_syms_cap_lookup(Rt_map *lmp, uint_t type, const char *name, uint_t ndx, + Half mach, Syscapset *scapset) +{ + Lm_list *lml = LIST(lmp); + const char *str = NULL; + Conv_cap_val_buf_t cap_val_buf; + + if (DBG_NOTCLASS(DBG_C_CAP | DBG_C_SYMBOLS)) + return; + + switch (type) { + case DBG_CAP_HW_1: + str = conv_cap_val_hw1(scapset->sc_hw_1, mach, 0, + &cap_val_buf.cap_val_hw1_buf); + break; + case DBG_CAP_SF_1: + str = conv_cap_val_sf1(scapset->sc_sf_1, mach, 0, + &cap_val_buf.cap_val_sf1_buf); + break; + case DBG_CAP_HW_2: + str = conv_cap_val_hw2(scapset->sc_hw_2, mach, 0, + &cap_val_buf.cap_val_hw2_buf); + break; + case DBG_CAP_MACH: + str = scapset->sc_mach; + break; + case DBG_CAP_PLAT: + str = scapset->sc_plat; + break; + } + + dbg_print(lml, MSG_INTL(captype[type]), Dbg_demangle_name(name), + ndx, str); +} + void Dbg_syms_ignore_gnuver(Rt_map *lmp, const char *name, Word symndx, Versym verndx) @@ -284,6 +332,46 @@ } void +Dbg_syms_cap_convert(Ofl_desc *ofl, Word ndx, const char *name, Sym *sym) +{ + if (DBG_NOTCLASS(DBG_C_CAP | DBG_C_SYMBOLS)) + return; + + dbg_print(ofl->ofl_lml, MSG_INTL(MSG_SYM_CAP_ORIG), EC_WORD(ndx), + Dbg_demangle_name(name)); + + if (DBG_NOTDETAIL()) + return; + + Elf_syms_table_entry(ofl->ofl_lml, ELF_DBG_LD, + MSG_INTL(MSG_STR_ORIGINAL), ofl->ofl_dehdr->e_ident[EI_OSABI], + ofl->ofl_dehdr->e_machine, sym, 0, 0, NULL, + MSG_ORIG(MSG_STR_EMPTY)); +} + +void +Dbg_syms_cap_local(Ofl_desc *ofl, Word ndx, const char *name, Sym *sym, + Sym_desc *sdp) +{ + Conv_inv_buf_t inv_buf; + + if (DBG_NOTCLASS(DBG_C_CAP | DBG_C_SYMBOLS)) + return; + + dbg_print(ofl->ofl_lml, MSG_INTL(MSG_SYM_CAP_LOCAL), EC_WORD(ndx), + Dbg_demangle_name(name)); + + if (DBG_NOTDETAIL()) + return; + + Elf_syms_table_entry(ofl->ofl_lml, ELF_DBG_LD, + MSG_INTL(MSG_STR_ENTERED), ofl->ofl_dehdr->e_ident[EI_OSABI], + ofl->ofl_dehdr->e_machine, sym, + sdp->sd_aux ? sdp->sd_aux->sa_overndx : 0, 0, NULL, + conv_def_tag(sdp->sd_ref, &inv_buf)); +} + +void Dbg_syms_wrap(Lm_list *lml, Word ndx, const char *orig_name, const char *name) { if (DBG_NOTCLASS(DBG_C_SYMBOLS)) @@ -617,3 +705,18 @@ sec, Elf_demangle_name(poststr)); } } + +void +Dbg_syms_cap_title(Ofl_desc *ofl) +{ + Lm_list *lml = ofl->ofl_lml; + + if (DBG_NOTCLASS(DBG_C_SYMBOLS)) + return; + if (DBG_NOTDETAIL()) + return; + + Dbg_util_nl(lml, DBG_NL_STD); + dbg_print(lml, MSG_INTL(MSG_SYM_CAPABILITIES)); + Elf_syms_table_title(lml, ELF_DBG_LD); +}
--- a/usr/src/cmd/sgs/libldmake/Makefile.com Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libldmake/Makefile.com Mon Mar 01 10:20:48 2010 -0800 @@ -18,12 +18,11 @@ # # CDDL HEADER END # + # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# LIBRARY= libldmake.a VERS= .1 @@ -39,7 +38,7 @@ SRCDIR = ../common -DYNFLAGS += $(USE_PROTO) +DYNFLAGS += $(CC_USE_PROTO) CFLAGS += $(C_PICFLAGS) CFLAGS64 += $(C_PICFLAGS64)
--- a/usr/src/cmd/sgs/libldstab/Makefile.com Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/libldstab/Makefile.com Mon Mar 01 10:20:48 2010 -0800 @@ -18,6 +18,7 @@ # # CDDL HEADER END # + # # Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. @@ -40,7 +41,7 @@ CPPFLAGS += -I$(ELFCAP) LDLIBS += $(CONVLIBDIR) $(CONV_LIB) $(ELFLIBDIR) -lelf -lc -DYNFLAGS += $(VERSREF) +DYNFLAGS += $(VERSREF) $(CC_USE_PROTO) LINTFLAGS += -erroff=E_NAME_DECL_NOT_USED_DEF2 \ -erroff=E_NAME_DEF_NOT_USED2 \ @@ -49,15 +50,6 @@ -erroff=E_NAME_DEF_NOT_USED2 \ -erroff=E_NAME_USED_NOT_DEF2 - -# A bug in pmake causes redundancy when '+=' is conditionally assigned, so -# '=' is used with extra variables. -# $(DYNLIB) := DYNFLAGS += -Yl,$(SGSPROTO) -# -XXXFLAGS= -$(DYNLIB) := XXXFLAGS= $(USE_PROTO) -DYNFLAGS += $(XXXFLAGS) - SRCS= $(COMOBJS:%.o=../common/%.c) LINTSRCS= $(SRCS)
--- a/usr/src/cmd/sgs/librtld/Makefile.com Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/librtld/Makefile.com Mon Mar 01 10:20:48 2010 -0800 @@ -18,12 +18,11 @@ # # CDDL HEADER END # + # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# LIBRARY= librtld.a VERS= .1 @@ -43,20 +42,12 @@ CPPFLAGS += -I../../rtld/common -I$(SRCBASE)/lib/libc/inc \ -I$(SRCBASE)/uts/common/krtld -I$(SRC)/common/sgsrtcid \ -I$(SRCBASE)/uts/sparc -DYNFLAGS += $(VERSREF) '-R$$ORIGIN' +DYNFLAGS += $(VERSREF) $(CC_USE_PROTO) '-R$$ORIGIN' LDLIBS += $(CONVLIBDIR) $(CONV_LIB) $(ELFLIBDIR) -lelf -lc LINTFLAGS += -u -erroff=E_NAME_DECL_NOT_USED_DEF2 LINTFLAGS64 += -u -erroff=E_NAME_DECL_NOT_USED_DEF2 -# A bug in pmake causes redundancy when '+=' is conditionally assigned, so -# '=' is used with extra variables. -# -XXXFLAGS= -$(DYNLIB) := XXXFLAGS= $(USE_PROTO) -DYNFLAGS += $(XXXFLAGS) - - BLTDEFS= msg.h BLTDATA= msg.c BLTMESG= $(SGSMSGDIR)/librtld
--- a/usr/src/cmd/sgs/librtld/common/relocate.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/librtld/common/relocate.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,10 +20,9 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" #include <libelf.h> #include <dlfcn.h> @@ -101,6 +100,7 @@ int _bound, _weak; ulong_t rsymndx = ELF_R_SYM(rel->r_info); Slookup sl; + Sresult sr; uint_t binfo; Sym *_sym, *sym = (syms + rsymndx); @@ -275,14 +275,19 @@ * users might be encouraged to set LD_FLAGS=loadavail (crle(1) * does this for them). * - * Initialize the symbol lookup data structure. + * Initialize the symbol lookup, and symbol result, data + * structures. */ SLOOKUP_INIT(sl, name, lmp, LIST(lmp)->lm_head, ld_entry_cnt, 0, rsymndx, sym, type, LKUP_STDRELOC); + SRESULT_INIT(sr, name); _bound = _weak = 0; _sym = sym; - if ((sym = lookup_sym(&sl, &_lmp, &binfo, NULL)) != 0) { + if (lookup_sym(&sl, &sr, &binfo, NULL)) { + _lmp = sr.sr_dmap; + sym = sr.sr_sym; + /* * Determine from the various relocation requirements * whether this binding is appropriate. If we're called
--- a/usr/src/cmd/sgs/link_audit/Makefile.com Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/link_audit/Makefile.com Mon Mar 01 10:20:48 2010 -0800 @@ -18,8 +18,9 @@ # # CDDL HEADER END # + # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -92,7 +93,7 @@ $(ROOTCCSLIB) := DIRMODE = 755 CPPFLAGS += -D_REENTRANT -LDFLAGS += $(USE_PROTO) +LDFLAGS += $(CC_USE_PROTO) DYNFLAGS += $(VERSREF) LINTFLAGS += -uaxs $(LDLIBS)
--- a/usr/src/cmd/sgs/moe/Makefile.com Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/moe/Makefile.com Mon Mar 01 10:20:48 2010 -0800 @@ -20,11 +20,9 @@ # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# PROG= moe @@ -39,7 +37,7 @@ MAPFILE= $(MAPFILE.NGB) MAPOPT= $(MAPFILE:%=-M%) -LDFLAGS += -Wl,$(VERSREF) $(USE_PROTO) $(MAPOPT) +LDFLAGS += -Wl,$(VERSREF) $(CC_USE_PROTO) $(MAPOPT) LDLIBS += $(CONVLIBDIR) $(CONV_LIB) LINTFLAGS += -x
--- a/usr/src/cmd/sgs/moe/common/moe.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/moe/common/moe.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -120,21 +120,23 @@ */ if ((handle = dlmopen(LM_ID_NEWLM, name, (RTLD_FIRST | RTLD_CONFGEN | RTLD_LAZY))) == 0) { - if (verbose) + if (verbose) { (void) fprintf(stderr, MSG_ORIG(MSG_FMT_VERBOSE), prog, modestr, trim_msg(dlerror())); (void) fflush(stderr); + } return (1); } if (silent == 0) { Link_map *lmp; if (dlinfo(handle, RTLD_DI_LINKMAP, &lmp) == -1) { - if (verbose) + if (verbose) { (void) fprintf(stderr, MSG_ORIG(MSG_FMT_VERBOSE), prog, modestr, trim_msg(dlerror())); (void) fflush(stderr); + } return (1); }
--- a/usr/src/cmd/sgs/packages/common/SUNWonld-README Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README Mon Mar 01 10:20:48 2010 -0800 @@ -829,6 +829,13 @@ Solaris/SunOS 5.8_sparc patch T109147-29 Solaris/SunOS 5.8_x86 patch T109148-29 -------------------------------------------------------------------------------- +All the above changes plus: + 6850124 dlopen reports "No such file or directory" in spite of ENOMEM + when mmap fails in anon_map() +are incorporated in the following patches: + Solaris/SunOS 5.9_sparc patch TXXXXXX-XX + Solaris/SunOS 5.9_x86 patch TXXXXXX-XX +-------------------------------------------------------------------------------- ---------- Solaris 10 @@ -1275,8 +1282,15 @@ 6786744 32-bit dbx failed with unknown rtld_db.so error on snv_104 -------------------------------------------------------------------------------- All the above changes are incorporated in the following patches: - Solaris/SunOS 5.10_sparc patch TXXXXXX-XX - Solaris/SunOS 5.10_x86 patch TXXXXXX-XX + Solaris/SunOS 5.10_sparc patch T141444-06 + Solaris/SunOS 5.10_x86 patch T141445-06 +-------------------------------------------------------------------------------- +All the above changes plus: + 6850124 dlopen reports "No such file or directory" in spite of ENOMEM + when mmap fails in anon_map() +are incorporated in the following patches: + Solaris/SunOS 5.10_sparc patch T143895-01 + Solaris/SunOS 5.10_x86 patch T143896-01 -------------------------------------------------------------------------------- -------------------------------------------- @@ -1436,7 +1450,7 @@ 6724311 dldump() mishandles R_AMD64_JUMP_SLOT relocations 6724774 elfdump -n doesn't print siginfo structure 6728555 Fix for amd64 aw (6617475) breaks pure gcc builds -6734598 ld(1) archive processing failure due to mismatched file descriptors +6734598 ld(1) archive processing failure due to mismatched file descriptors (D) 6684577 ld should propagate SHF_LINK_ORDER flag to ET_REL objects 6735939 ld(1) discarded symbol relocations errors (Studio and GNU). 6354160 Solaris linker includes more than one copy of code in binary when @@ -1522,8 +1536,8 @@ 6851224 elf_getshnum() and elf_getshstrndx() incompatible with 2002 ELF gABI agreement (D) PSARC/2009/363 replace elf_getphnum, elf_getshnum, and elf_getshstrndx -6853809 ld.so.1: rescan fallback optimization is invalid -6854158 ld.so.1: interposition can be skipped because of incorrect +6853809 ld.so.1: rescan fallback optimization is invalid +6854158 ld.so.1: interposition can be skipped because of incorrect caller/destination validation 6862967 rd_loadobj_iter() failing for core files 6856173 streams core dumps when compiled in 64bit with a very large static @@ -1551,3 +1565,6 @@ 6916788 ld version 2 mapfile syntax (D) PSARC/2009/688 Human readable and extensible ld mapfile syntax 6929607 ld generates incorrect VERDEF entries for ET_REL output objects +6924224 linker should ignore SUNW_dof when calculating the elf checksum +6918143 symbol capabilities (D) +6910387 .tdata and .tbss separation invalidates TLS program header information
--- a/usr/src/cmd/sgs/pvs/Makefile.com Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/pvs/Makefile.com Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -42,7 +42,7 @@ CPPFLAGS += -I$(SRCBASE)/lib/libc/inc LLDFLAGS = '-R$$ORIGIN/../lib' LLDFLAGS64 = '-R$$ORIGIN/../../lib/$(MACH64)' -LDFLAGS += $(VERSREF) $(USE_PROTO) $(MAPOPTS) $(LLDFLAGS) +LDFLAGS += $(VERSREF) $(CC_USE_PROTO) $(MAPOPTS) $(LLDFLAGS) LDLIBS += $(LDDBGLIBDIR) $(LDDBG_LIB) $(ELFLIBDIR) -lelf \ $(CONVLIBDIR) $(CONV_LIB) LINTFLAGS += -x
--- a/usr/src/cmd/sgs/rtld/Makefile.com Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/Makefile.com Mon Mar 01 10:20:48 2010 -0800 @@ -18,12 +18,11 @@ # # CDDL HEADER END # + # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# RTLD= ld.so.1 @@ -31,10 +30,12 @@ DTROBJ= dtrace_data.o TOOLOBJS= alist.o strhash.o BLTOBJ= msg.o +ELFCAPOBJ= elfcap.o OBJECTS= $(BLTOBJ) \ $(AVLOBJ) \ $(DTROBJ) \ $(TOOLOBJS) \ + $(ELFCAPOBJ) \ $(P_ASOBJS) $(P_COMOBJS) $(P_MACHOBJS) $(G_MACHOBJS) \ $(S_ASOBJS) $(S_COMOBJS) $(S_MACHOBJS) $(CP_MACHOBJS) @@ -47,6 +48,7 @@ include $(SRC)/cmd/sgs/Makefile.com SRCDIR = ../common +ELFCAP = $(SRC)/common/elfcap PLAT = $(VAR_PLAT_$(BASEPLAT)) # DTrace needs an executable data segment. @@ -79,6 +81,7 @@ -I$(SRCBASE)/uts/$(PLAT) \ -I$(SRCBASE)/uts/$(PLAT)/krtld \ -I$(SRC)/common/sgsrtcid \ + -I$(ELFCAP) \ $(CPPFEATUREMACROS) ASFLAGS= -P -D_ASM $(CPPFLAGS)
--- a/usr/src/cmd/sgs/rtld/Makefile.targ Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/Makefile.targ Mon Mar 01 10:20:48 2010 -0800 @@ -18,8 +18,9 @@ # # CDDL HEADER END # + # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -61,8 +62,12 @@ $(COMPILE.c) -o $@ $< $(POST_PROCESS_O) +pics/elfcap.o: $(ELFCAP)/elfcap.c + $(COMPILE.c) -o $@ $(ELFCAP)/elfcap.c + $(POST_PROCESS_O) + $(RTLD): pics $(PICS) $(CRTS) - $(SGSPROTO)/ld -o $@ -dy -G $(DYNFLAGS) $(CRTI) $(PICS) \ + $(LD_USE_PROTO)ld -o $@ -dy -G $(DYNFLAGS) $(CRTI) $(PICS) \ $(LDLIBS) $(CRTN) $(POST_PROCESS_SO)
--- a/usr/src/cmd/sgs/rtld/amd64/amd64_elf.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/amd64/amd64_elf.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,12 +20,10 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "@(#)amd64_elf.c 1.25 08/07/30 SMI" - /* * amd64 machine dependent and ELF file class dependent functions. * Contains routines for performing function binding and symbol relocations. @@ -219,6 +217,7 @@ Sym *rsym, *nsym; uint_t binfo, sb_flags = 0, dbg_class; Slookup sl; + Sresult sr; int entry, lmflags; Lm_list *lml; @@ -268,19 +267,25 @@ llmp = lml->lm_tail; /* - * Find definition for symbol. Initialize the symbol lookup data - * structure. + * Find definition for symbol. Initialize the symbol lookup, and + * symbol result, data structures. */ SLOOKUP_INIT(sl, name, lmp, lml->lm_head, ld_entry_cnt, 0, rsymndx, rsym, 0, LKUP_DEFT); + SRESULT_INIT(sr, name); - if ((nsym = lookup_sym(&sl, &nlmp, &binfo, NULL)) == 0) { + if (lookup_sym(&sl, &sr, &binfo, NULL) == 0) { eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NOSYM), NAME(lmp), demangle(name)); rtldexit(lml, 1); } + name = (char *)sr.sr_name; + nlmp = sr.sr_dmap; + nsym = sr.sr_sym; + symval = nsym->st_value; + if (!(FLAGS(nlmp) & FLG_RT_FIXED) && (nsym->st_shndx != SHN_ABS)) symval += ADDR(nlmp); @@ -431,6 +436,7 @@ */ if (plt) { Slookup sl; + Sresult sr; relbgn = pltbgn; relend = pltend; @@ -438,14 +444,17 @@ return (1); /* - * Initialize the symbol lookup data structure. + * Initialize the symbol lookup, and symbol result, data + * structures. */ SLOOKUP_INIT(sl, MSG_ORIG(MSG_SYM_PLT), lmp, lmp, ld_entry_cnt, elf_hash(MSG_ORIG(MSG_SYM_PLT)), 0, 0, 0, LKUP_DEFT); + SRESULT_INIT(sr, MSG_ORIG(MSG_SYM_PLT)); - if ((symdef = elf_find_sym(&sl, &_lmp, &binfo, NULL)) == 0) + if (elf_find_sym(&sl, &sr, &binfo, NULL) == 0) return (1); + symdef = sr.sr_sym; _pltbgn = symdef->st_value; if (!(FLAGS(lmp) & FLG_RT_FIXED) && (symdef->st_shndx != SHN_ABS)) @@ -622,7 +631,7 @@ */ if (ELF_ST_BIND(symref->st_info) == STB_LOCAL) { value = basebgn; - name = (char *)0; + name = NULL; /* * Special case TLS relocations. @@ -684,11 +693,12 @@ } } else { Slookup sl; + Sresult sr; /* * Lookup the symbol definition. - * Initialize the symbol lookup data - * structure. + * Initialize the symbol lookup, and + * symbol result, data structure. */ name = (char *)(STRTAB(lmp) + symref->st_name); @@ -696,9 +706,15 @@ SLOOKUP_INIT(sl, name, lmp, 0, ld_entry_cnt, 0, rsymndx, symref, rtype, LKUP_STDRELOC); + SRESULT_INIT(sr, name); + symdef = NULL; - symdef = lookup_sym(&sl, &_lmp, - &binfo, in_nfavl); + if (lookup_sym(&sl, &sr, &binfo, + in_nfavl)) { + name = (char *)sr.sr_name; + _lmp = sr.sr_dmap; + symdef = sr.sr_sym; + } /* * If the symbol is not found and the @@ -822,7 +838,8 @@ value = TLSMODID(lmp); } else value = basebgn; - name = (char *)0; + + name = NULL; } DBG_CALL(Dbg_reloc_in(LIST(lmp), ELF_DBG_RTLD, M_MACH,
--- a/usr/src/cmd/sgs/rtld/common/_a.out.h Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/common/_a.out.h Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _A_DOT_OUT_DOT_H @@ -44,7 +44,7 @@ */ extern ulong_t aout_bndr(caddr_t); extern int aout_get_mmap(Lm_list *, mmapobj_result_t *); -extern Sym *aout_lookup_sym(Slookup *, Rt_map **, uint_t *, int *); +extern int aout_lookup_sym(Slookup *, Sresult *, uint_t *, int *); extern Rt_map *aout_new_lmp(Lm_list *, Aliste, Fdesc *, Addr, size_t, void *, int *); extern void aout_plt_write(caddr_t, ulong_t);
--- a/usr/src/cmd/sgs/rtld/common/_elf.h Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/common/_elf.h Mon Mar 01 10:20:48 2010 -0800 @@ -23,7 +23,7 @@ * Copyright (c) 1988 AT&T * All Rights Reserved * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef __ELF_DOT_H @@ -31,6 +31,7 @@ #include <sys/types.h> #include <sys/mman.h> +#include <sgs.h> #include <elf.h> #include <_rtld.h> @@ -50,11 +51,11 @@ #endif extern int elf_copy_reloc(char *, Sym *, Rt_map *, void *, Sym *, Rt_map *, const void *); -extern Sym *elf_find_sym(Slookup *, Rt_map **, uint_t *, int *); -extern Sym *elf_lazy_find_sym(Slookup *, Rt_map **, uint_t *, int *); +extern int elf_find_sym(Slookup *, Sresult *, uint_t *, int *); +extern int elf_lazy_find_sym(Slookup *, Sresult *, uint_t *, int *); extern Rt_map *elf_lazy_load(Rt_map *, Slookup *, uint_t, const char *, uint_t, Grp_hdl **, int *); -extern Sym *elf_lookup_filtee(Slookup *, Rt_map **, uint_t *, uint_t, +extern int elf_lookup_filtee(Slookup *, Sresult *, uint_t *, uint_t, int *); extern int elf_mach_flags_check(Rej_desc *, Ehdr *); extern Rt_map *elf_new_lmp(Lm_list *, Aliste, Fdesc *, Addr, size_t, void *, @@ -126,6 +127,10 @@ ulong_t e_syminent; /* syminfo entry size */ void *e_pltpad; /* PLTpad table */ void *e_pltpadend; /* end of PLTpad table */ + Syscapset e_capset; /* capabilities set */ + Capinfo *e_capinfo; /* symbol capabilities information */ + uint_t e_capchainent; /* size of capabilities chain entry */ + uint_t e_capchainsz; /* size of capabilities chain data */ } Rt_elfp; /* @@ -161,6 +166,10 @@ #define SUNWSORTENT(X) (((Rt_elfp *)(X)->rt_priv)->e_sunwsortent) #define SUNWSYMSORT(X) (((Rt_elfp *)(X)->rt_priv)->e_sunwsymsort) #define SUNWSYMSORTSZ(X) (((Rt_elfp *)(X)->rt_priv)->e_sunwsymsortsz) +#define CAPSET(X) (((Rt_elfp *)(X)->rt_priv)->e_capset) +#define CAPINFO(X) (((Rt_elfp *)(X)->rt_priv)->e_capinfo) +#define CAPCHAINENT(X) (((Rt_elfp *)(X)->rt_priv)->e_capchainent) +#define CAPCHAINSZ(X) (((Rt_elfp *)(X)->rt_priv)->e_capchainsz) /* * Most of the above macros are used from ELF specific routines, however there
--- a/usr/src/cmd/sgs/rtld/common/_rtld.h Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/common/_rtld.h Mon Mar 01 10:20:48 2010 -0800 @@ -85,7 +85,7 @@ int (*fct_needed)(Lm_list *, Aliste, Rt_map *, int *); /* Look up a symbol for the object. */ - Sym *(*fct_lookup_sym)(Slookup *, Rt_map **, uint_t *, int *); + int (*fct_lookup_sym)(Slookup *, Sresult *, uint_t *, int *); /* Relocate the object. */ int (*fct_reloc)(Rt_map *, uint_t, int *, APlist **); @@ -107,8 +107,7 @@ void (*fct_dladdr)(ulong_t, Rt_map *, Dl_info *, void **, int); /* Process a dlsym(3c) request within the object. */ - Sym *(*fct_dlsym)(Grp_hdl *, Slookup *, Rt_map **, uint_t *, - int *); + int (*fct_dlsym)(Grp_hdl *, Slookup *, Sresult *, uint_t *, int *); }; /* @@ -157,7 +156,7 @@ #define AL_CNT_FILTEES 2 /* filtee path */ #define AL_CNT_HANDLES 1 /* hdl_list[] */ #define AL_CNT_FREELIST 80 /* free_alp */ -#define AL_CNT_HWCAP 10 /* hwcap candidate */ +#define AL_CNT_CAP 10 /* capabilities candidate */ #define AL_CNT_SPATH 4 /* search path */ #define AL_CNT_DYNLIST 2 /* dynlm_list */ #define AL_CNT_PENDING 2 /* pending tsort list (INITFIRST) */ @@ -237,7 +236,7 @@ rtld_ino_t fd_ino; /* file inode number */ uint_t fd_flags; avl_index_t fd_avlwhere; /* avl tree insertion index */ - Xword fd_hwcap; /* hardware capabilities value */ + Syscapset fd_scapset; /* capabilities */ mmapobj_result_t *fd_mapp; /* mapping pointer */ uint_t fd_mapn; /* mapping number */ }; @@ -245,6 +244,10 @@ #define FLG_FD_ALTER 0x0001 /* file is an alternate */ #define FLG_FD_SLASH 0x0002 /* file contains a "/" */ #define FLG_FD_RESOLVED 0x0004 /* fd_nname has been resolved */ +#define FLG_FD_ALTCHECK 0x0008 /* alternative system capabilities */ + /* checked */ +#define FLG_FD_ALTCAP 0x0010 /* alternative system capabilities */ + /* should be used */ /* * File descriptor availability flag. @@ -389,8 +392,10 @@ #define PD_TKN_OSNAME 0x00004000 /* $OSNAME expansion has occurred */ #define PD_TKN_OSREL 0x00008000 /* $OSREL expansion has occurred */ #define PD_TKN_ISALIST 0x00010000 /* $ISALIST expansion has occurred */ -#define PD_TKN_HWCAP 0x00020000 /* $HWCAP expansion has occurred */ -#define PD_TKN_RESOLVED 0x00040000 /* resolvepath() expansion has */ +#define PD_TKN_CAP 0x00020000 /* $CAPABILITY/$HWCAP expansion has */ + /* occurred */ +#define PD_TKN_MACHINE 0x00040000 /* $MACHINE expansion has occurred */ +#define PD_TKN_RESOLVED 0x00080000 /* resolvepath() expansion has */ /* occurred */ #define PD_MSK_EXPAND 0x000ff000 /* mask for all expansions */ @@ -514,8 +519,6 @@ extern const char *rtldname; /* name of the dynamic linker */ extern APlist *hdl_alp[]; /* dlopen() handle list */ extern size_t syspagsz; /* system page size */ -extern char *platform; /* platform name */ -extern size_t platform_sz; /* platform name string size */ extern Isa_desc *isa; /* isalist descriptor */ extern Uts_desc *uts; /* utsname descriptor */ extern uint_t rtld_flags; /* status flags for RTLD */ @@ -573,6 +576,7 @@ extern const Msg err_reject[]; /* rejection error message tables */ extern const Msg ldd_reject[]; +extern const Msg ldd_warn[]; extern const char *profile_name; /* object being profiled */ extern const char *profile_out; /* profile output file */ @@ -585,10 +589,24 @@ /* diagnostic error string headers */ extern const char *nosym_str; /* MSG_GEN_NOSYM message cache */ -extern ulong_t hwcap; /* hardware capabilities */ -extern ulong_t sfcap; /* software capabilities */ +extern Syscapset *org_scapset; /* original system capabilities */ +extern Syscapset *alt_scapset; /* alternative system capabilities */ + +extern const char *rpl_hwcap; /* replaceable hwcap str */ +extern const char *rpl_sfcap; /* replaceable sfcap str */ +extern const char *rpl_machcap; /* replaceable machcap str */ +extern const char *rpl_platcap; /* replaceable platcap str */ +extern const char *rpl_cap_files; /* associated files */ -extern avl_tree_t *nfavl; /* not-found AVL path name tree */ +extern const char *prm_hwcap; /* permanent hwcap str */ +extern const char *prm_sfcap; /* permanent sfcap str */ +extern const char *prm_machcap; /* permanent machcap str */ +extern const char *prm_platcap; /* permanent platcap str */ +extern const char *prm_cap_files; /* associated files */ + +extern avl_tree_t *capavl; /* capabilities files */ +extern avl_tree_t *nfavl; /* not-found path names */ +extern avl_tree_t *spavl; /* secure path names */ extern u_longlong_t cnt_map; /* Incr. for each object mapped */ extern u_longlong_t cnt_unmap; /* Incr. for each object unmapped */ @@ -609,7 +627,12 @@ extern Rt_map *_caller(caddr_t, int); extern caddr_t caller(void); extern void *calloc(size_t, size_t); -extern void cap_assign(Cap *, Rt_map *); +extern int cap_alternative(void); +extern int cap_check_fdesc(Fdesc *, Cap *, char *, Rej_desc *); +extern int cap_check_lmp(Rt_map *, Rej_desc *); +extern int cap_filtees(Alist **, Aliste, const char *, Aliste, + Rt_map *, const char *, int, uint_t, int *); +extern int cap_match(Sresult *, uint_t, Sym *, char *); extern const char *_conv_reloc_type(uint_t rel); extern Aliste create_cntl(Lm_list *, int); extern void defrag(void); @@ -617,8 +640,8 @@ extern const char *demangle(const char *); extern int dlclose_intn(Grp_hdl *, Rt_map *); extern int dlclose_core(Grp_hdl *, Rt_map *, Lm_list *); -extern Sym *dlsym_handle(Grp_hdl *, Slookup *, Rt_map **, - uint_t *, int *); +extern int dlsym_handle(Grp_hdl *, Slookup *, Sresult *, uint_t *, + int *); extern void *dlsym_intn(void *, const char *, Rt_map *, Rt_map **); extern Grp_hdl *dlmopen_intn(Lm_list *, const char *, int, Rt_map *, uint_t, uint_t); @@ -647,9 +670,8 @@ extern Grp_hdl *hdl_create(Lm_list *, Rt_map *, Rt_map *, uint_t, uint_t, uint_t); extern int hdl_initialize(Grp_hdl *, Rt_map *, int, int); -extern int hwcap_check(Xword, Rej_desc *); -extern int hwcap_filtees(Alist **, Aliste, const char *, Aliste, - Rt_map *, const char *, int, uint_t, int *); +extern int hwcap1_check(Syscapset *, Xword, Rej_desc *); +extern int hwcap2_check(Syscapset *, Xword, Rej_desc *); extern void is_dep_init(Rt_map *, Rt_map *); extern int is_move_data(caddr_t); extern int is_path_secure(char *, Rt_map *, uint_t, uint_t); @@ -661,22 +683,27 @@ extern void lm_delete(Lm_list *, Rt_map *); extern void lm_move(Lm_list *, Aliste, Aliste, Lm_cntl *, Lm_cntl *); +extern Rt_map *load_cap(Lm_list *, Aliste, const char *, Rt_map *, + uint_t, uint_t, Grp_hdl **, Rej_desc *, int *); extern void load_completion(Rt_map *); extern Rt_map *load_file(Lm_list *, Aliste, Fdesc *, int *); -extern Rt_map *load_hwcap(Lm_list *, Aliste, const char *, Rt_map *, - uint_t, uint_t, Grp_hdl **, Rej_desc *, int *); extern Rt_map *load_path(Lm_list *, Aliste, Rt_map *, int, uint_t, Grp_hdl **, Fdesc *, Rej_desc *, int *); extern Rt_map *load_one(Lm_list *, Aliste, Alist *, Rt_map *, int, uint_t, Grp_hdl **, int *); extern const char *load_trace(Lm_list *, Pdesc *, Rt_map *, Fdesc *); extern void nfavl_insert(const char *, avl_index_t); -extern int nfavl_recorded(const char *, uint_t, avl_index_t *); extern void *nu_map(Lm_list *, caddr_t, size_t, int, int); extern Fct *map_obj(Lm_list *, Fdesc *, size_t, const char *, int, Rej_desc *); extern void *malloc(size_t); +extern int machcap_check(Syscapset *, const char *, Rej_desc *); +extern void machine_name(Syscapset *); extern int move_data(Rt_map *, APlist **); +extern int platcap_check(Syscapset *, const char *, Rej_desc *); +extern void platform_name(Syscapset *); +extern int pnavl_recorded(avl_tree_t **, const char *, uint_t, + avl_index_t *); extern void rd_event(Lm_list *, rd_event_e, r_state_e); extern int readenv_user(const char **, Word *, Word *, int); extern int readenv_config(Rtc_env *, Addr, int); @@ -718,8 +745,7 @@ uid_t, uid_t, gid_t, gid_t, void *, int, uint_t); extern const char *stravl_insert(const char *, uint_t, size_t, int); extern void spavl_insert(const char *); -extern int spavl_recorded(const char *, avl_index_t *); -extern int sfcap_check(Xword, Rej_desc *); +extern int sfcap1_check(Syscapset *, Xword, Rej_desc *); extern int tls_assign(Lm_list *, Rt_map *, Phdr *); extern void tls_modaddrem(Rt_map *, uint_t); extern int tls_statmod(Lm_list *, Rt_map *);
--- a/usr/src/cmd/sgs/rtld/common/a.out.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/common/a.out.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -69,15 +69,14 @@ * Defines for local functions. */ static void aout_dladdr(ulong_t, Rt_map *, Dl_info *, void **, int); -static Sym *aout_dlsym_handle(Grp_hdl *, Slookup *, Rt_map **, uint_t *, - int *l); +static int aout_dlsym_handle(Grp_hdl *, Slookup *, Sresult *, uint_t *, + int *); static Addr aout_entry_point(void); -static Sym *aout_find_sym(Slookup *, Rt_map **, uint_t *, int *); +static int aout_find_sym(Slookup *, Sresult *, uint_t *, int *); static int aout_fix_name(const char *, Rt_map *, Alist **, Aliste, uint_t); static Alist **aout_get_def_dirs(void); static Alist **aout_get_sec_dirs(void); static char *aout_get_so(const char *, const char *, size_t, size_t); -extern Sym *aout_lookup_sym(Slookup *, Rt_map **, uint_t *, int *); static int aout_needed(Lm_list *, Aliste, Rt_map *, int *); /* @@ -441,8 +440,8 @@ * ii. .bar -> .bar (LKUP_LDOT) * iii. nuts -> .nuts */ -Sym * -aout_lookup_sym(Slookup *slp, Rt_map **dlmp, uint_t *binfo, int *in_nfavl) +int +aout_lookup_sym(Slookup *slp, Sresult *srp, uint_t *binfo, int *in_nfavl) { char name[PATH_MAX]; Slookup sl = *slp; @@ -463,15 +462,15 @@ * Call the generic lookup routine to cycle through the specified * link maps. */ - return (lookup_sym(&sl, dlmp, binfo, in_nfavl)); + return (lookup_sym(&sl, srp, binfo, in_nfavl)); } /* * Symbol lookup for an a.out format module. */ /* ARGSUSED3 */ -static Sym * -aout_find_sym(Slookup *slp, Rt_map **dlmp, uint_t *binfo, int *in_nfavl) +static int +aout_find_sym(Slookup *slp, Sresult *srp, uint_t *binfo, int *in_nfavl) { const char *name = slp->sl_name; Rt_map *ilmp = slp->sl_imap; @@ -486,14 +485,15 @@ */ if (sp->n_type == (N_EXT + N_UNDF)) { if ((sp = aout_find_com(sp, name)) == 0) - return (NULL); + return (0); } - *dlmp = ilmp; + srp->sr_dmap = ilmp; + srp->sr_sym = aout_symconvert(sp); *binfo |= DBG_BINFO_FOUND; - return (aout_symconvert(sp)); + return (1); } } - return (NULL); + return (0); } /* @@ -677,19 +677,15 @@ * individual link-maps we don't need to supply a starting link-map to the * lookup routine (see lookup_sym():analyze.c). */ -static Sym * -aout_dlsym_handle(Grp_hdl *ghp, Slookup *slp, Rt_map **_lmp, uint_t *binfo, +static int +aout_dlsym_handle(Grp_hdl *ghp, Slookup *slp, Sresult *srp, uint_t *binfo, int *in_nfavl) { - Sym *sym; char buffer[PATH_MAX]; Slookup sl; - buffer[0] = '_'; - (void) strcpy(&buffer[1], slp->sl_name); - - if ((sym = dlsym_handle(ghp, slp, _lmp, binfo, in_nfavl)) != 0) - return (sym); + if (dlsym_handle(ghp, slp, srp, binfo, in_nfavl)) + return (1); /* * Symbol not found as supplied. However, most of our symbols will @@ -697,10 +693,13 @@ * to the symbol as it emits it. Therefore, attempt to find the * symbol with the "_" prepend. */ + buffer[0] = '_'; + (void) strcpy(&buffer[1], slp->sl_name); + sl = *slp; sl.sl_name = (const char *)buffer; - return (dlsym_handle(ghp, &sl, _lmp, binfo, in_nfavl)); + return (dlsym_handle(ghp, &sl, srp, binfo, in_nfavl)); } /*
--- a/usr/src/cmd/sgs/rtld/common/analyze.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/common/analyze.c Mon Mar 01 10:20:48 2010 -0800 @@ -67,16 +67,24 @@ Slookup sl; /* - * Initialize the symbol lookup data structure. + * Initialize the symbol lookup data structure. Note, no symbol + * name is supplied. This NULL name causes filters to be loaded + * but no symbol to be searched for. */ SLOOKUP_INIT(sl, 0, lmp, lmp, ld_entry_cnt, 0, 0, 0, 0, 0); for (cnt = 0; cnt < max; cnt++, dip++) { + uint_t binfo; + Sresult sr; + + SRESULT_INIT(sr, NULL); + if (((dip->di_flags & MSK_DI_FILTER) == 0) || ((dip->di_flags & FLG_DI_AUXFLTR) && (rtld_flags & RT_FL_NOAUXFLTR))) continue; - (void) elf_lookup_filtee(&sl, 0, 0, cnt, in_nfavl); + (void) elf_lookup_filtee(&sl, &sr, &binfo, cnt, + in_nfavl); } } } @@ -490,8 +498,8 @@ * may be involved. Under the first pass, RTLD_CONFGEN is set. Under * this pass, crle() loads objects into the process address space. No * relocation is necessary at this point, we simply need to analyze the - * objects to insure any directly bound dependencies, filtees, etc. - * get loaded. Although we skip the relocation, fall through to insure + * objects to ensure any directly bound dependencies, filtees, etc. + * get loaded. Although we skip the relocation, fall through to ensure * any control lists are maintained appropriately. * * If objects are to be dldump(3c)'ed, crle(1) makes a second pass, @@ -761,7 +769,7 @@ * * A traversal through the callers link-map list is carried out, and from each * link-map, a comparison is made against all of the various names by which the - * object has been referenced. is_so_matched() is used to compares the link-map + * object has been referenced. is_so_matched() is used to compare the link-map * names against the name being searched for. Whether the search name is a full * path name or a simple file name, governs what comparisons are made. * @@ -791,7 +799,7 @@ ((FLAGS(lmp) & (FLG_RT_OBJECT | FLG_RT_DELETE)) == 0)) return (lmp); - if (nfavl_recorded(name, hash, 0)) { + if (pnavl_recorded(&nfavl, name, hash, NULL)) { /* * For dlopen() and dlsym() fall backs, indicate that * a registered not-found path has indicated that this @@ -827,7 +835,7 @@ /* * Tracing is enabled by the LD_TRACE_LOADED_OPTIONS environment variable which * is normally set from ldd(1). For each link map we load, print the load name - * and the full pathname of the shared object. + * and the full pathname of the associated object. */ /* ARGSUSED4 */ static void @@ -892,7 +900,6 @@ reject); } - /* * Establish a link-map mode, initializing it if it has just been loaded, or * potentially updating it if it already exists. @@ -1158,14 +1165,14 @@ fdp->fd_lmp = nlmp; return (1); } - if (nfavl_recorded(nname, hash, &nfavlwhere)) { + if (pnavl_recorded(&nfavl, nname, hash, &nfavlwhere)) { /* * For dlopen() and dlsym() fall backs, indicate that * a registered not-found path has indicated that this * object does not exist. If this path has been - * constructed as part of expanding a HWCAP directory, - * this is a silent failure, where no rejection message - * is created. + * constructed as part of expanding a CAPABILITY + * directory, this is a silent failure, where no + * rejection message is created. */ if (in_nfavl) (*in_nfavl)++; @@ -1179,12 +1186,12 @@ /* * If this path has been constructed as part of expanding a - * HWCAP directory, ignore any subdirectories. As this is a - * silent failure, no rejection message is created. For any - * other reference that expands to a directory, fall through - * to construct a meaningful rejection message. + * CAPABILITY directory, ignore any subdirectories. As this + * is a silent failure, no rejection message is created. For + * any other reference that expands to a directory, fall + * through to construct a meaningful rejection message. */ - if ((flags & FLG_RT_HWCAP) && + if ((flags & FLG_RT_CAP) && ((status.st_mode & S_IFMT) == S_IFDIR)) return (0); @@ -1305,14 +1312,6 @@ if (fdp->fd_ftp != NULL) { fdp->fd_dev = status.st_dev; fdp->fd_ino = status.st_ino; - - /* - * Trace that this open has succeeded. - */ - if (lml->lm_flags & LML_FLG_TRC_ENABLE) { - trace_so(clmp, 0, oname, nname, - (fdp->fd_flags & FLG_FD_ALTER), 0); - } return (1); } } @@ -1977,12 +1976,12 @@ clmp = lml_rtld.lm_head; /* - * If this path resulted from a $HWCAP specification, then the best - * hardware capability object has already been establish, and is - * available in the calling file descriptor. Perform some minor book- - * keeping so that we can fall through into common code. + * If this path resulted from a $CAPABILITY specification, then the + * best capability object has already been establish, and is available + * in the calling file descriptor. Perform some minor book-keeping so + * that we can fall through into common code. */ - if (flags & FLG_RT_HWCAP) { + if (flags & FLG_RT_CAP) { /* * If this object is already loaded, we're done. */ @@ -2086,12 +2085,19 @@ } /* - * Finish mapping the file and return the link-map descriptor. Note, - * if this request originated from a HWCAP request, re-establish the - * fdesc information. For single paged objects, such as filters, the - * original mapping may have been sufficient to capture the file, thus - * this mapping needs to be reset to insure it doesn't mistakenly get - * unmapped as part of HWCAP cleanup. + * Trace that this successfully opened file is about to be processed. + * Note, as part of processing a family of hardware capabilities filtees + * a number of candidates may have been opened and mapped to determine + * their capability requirements. At this point we've decided which + * of the candidates to use. + */ + if (lml->lm_flags & LML_FLG_TRC_ENABLE) { + trace_so(clmp, 0, fdp->fd_oname, fdp->fd_nname, + (fdp->fd_flags & FLG_FD_ALTER), 0); + } + + /* + * Finish mapping the file and return the link-map descriptor. */ return (load_file(lml, lmco, fdp, in_nfavl)); } @@ -2430,7 +2436,7 @@ * If this file has been found, reset the not-found load count. * Although a search for this file might have inspected a number * of non-existent path names, the file has been found so there - * is no need to to accumulate a non-found count, as this may + * is no need to accumulate a non-found count, as this may * trigger unnecessary fall back (retry) processing. */ if (in_nfavl) @@ -2530,8 +2536,8 @@ /* * Load one object from a possible list of objects. Typically, for requests * such as NEEDED's, only one object is specified. However, this object could - * be specified using $ISALIST or $HWCAP, in which case only the first object - * that can be loaded is used (ie. the best). + * be specified using $ISALIST or $CAPABILITY, in which case only the first + * object that can be loaded is used (ie. the best). */ Rt_map * load_one(Lm_list *lml, Aliste lmco, Alist *palp, Rt_map *clmp, int mode, @@ -2546,12 +2552,12 @@ Rt_map *lmp = NULL; /* - * A Hardware capabilities requirement can itself expand into - * a number of candidates. + * A $CAPABILITY/$HWCAP requirement can expand into a number of + * candidates. */ - if (pdp->pd_flags & PD_TKN_HWCAP) { - lmp = load_hwcap(lml, lmco, pdp->pd_pname, clmp, - mode, (flags | FLG_RT_HWCAP), hdl, &rej, in_nfavl); + if (pdp->pd_flags & PD_TKN_CAP) { + lmp = load_cap(lml, lmco, pdp->pd_pname, clmp, + mode, (flags | FLG_RT_CAP), hdl, &rej, in_nfavl); } else { Fdesc fd = { 0 }; @@ -2612,11 +2618,11 @@ * which we've bound can be interposed upon. In this context, copy relocations * are a form of interposition. */ -static Sym * -lookup_sym_interpose(Slookup *slp, Rt_map **dlmp, uint_t *binfo, Sym *osym, - int *in_nfavl) +static int +lookup_sym_interpose(Slookup *slp, Sresult *srp, uint_t *binfo, int *in_nfavl) { - Rt_map *lmp, *clmp; + Rt_map *lmp, *clmp, *dlmp = srp->sr_dmap; + Sym *osym = srp->sr_sym; Slookup sl; Lm_list *lml; @@ -2625,17 +2631,18 @@ * this binding to the original copy reference. Fabricate an inter- * position diagnostic, as this is a legitimate form of interposition. */ - if (osym && (FLAGS1(*dlmp) & FL1_RT_COPYTOOK)) { + if (osym && (FLAGS1(dlmp) & FL1_RT_COPYTOOK)) { Rel_copy *rcp; Aliste idx; - for (ALIST_TRAVERSE(COPY_R(*dlmp), idx, rcp)) { + for (ALIST_TRAVERSE(COPY_R(dlmp), idx, rcp)) { if ((osym == rcp->r_dsym) || (osym->st_value && (osym->st_value == rcp->r_dsym->st_value))) { - *dlmp = rcp->r_rlmp; + srp->sr_dmap = rcp->r_rlmp; + srp->sr_sym = rcp->r_rsym; *binfo |= (DBG_BINFO_INTERPOSE | DBG_BINFO_COPYREF); - return (rcp->r_rsym); + return (1); } } } @@ -2646,7 +2653,7 @@ * original caller. */ if (osym) - clmp = *dlmp; + clmp = dlmp; else clmp = slp->sl_cmap; @@ -2676,10 +2683,16 @@ if (osym && ((FLAGS1(lmp) & FL1_RT_DTFLAGS) == 0) && (FCT(lmp) == &elf_fct) && (ELF_ST_TYPE(osym->st_info) != STT_FUNC) && - are_bits_zero(*dlmp, osym, 0)) { - Rt_map *ilmp; - Sym *isym; - + are_bits_zero(dlmp, osym, 0)) { + Sresult sr; + + /* + * Initialize a local symbol result descriptor, using the + * original symbol name. Initialize a local symbol lookup + * descriptor, using the original lookup information, and a + * new initial link-map. + */ + SRESULT_INIT(sr, slp->sl_name); sl = *slp; sl.sl_imap = lmp; @@ -2688,13 +2701,17 @@ * executable, that the size and type of symbol are the same, * and that the symbol is also associated with .bss. */ - if (((isym = SYMINTP(lmp)(&sl, &ilmp, binfo, - in_nfavl)) != NULL) && (isym->st_size == osym->st_size) && - (isym->st_info == osym->st_info) && - are_bits_zero(lmp, isym, 1)) { - *dlmp = lmp; - *binfo |= (DBG_BINFO_INTERPOSE | DBG_BINFO_COPYREF); - return (isym); + if (SYMINTP(lmp)(&sl, &sr, binfo, in_nfavl)) { + Sym *isym = sr.sr_sym; + + if ((isym->st_size == osym->st_size) && + (isym->st_info == osym->st_info) && + are_bits_zero(lmp, isym, 1)) { + *srp = sr; + *binfo |= + (DBG_BINFO_INTERPOSE | DBG_BINFO_COPYREF); + return (1); + } } } @@ -2724,7 +2741,7 @@ * If we had already bound to this object, there's no point in * searching it again, we're done. */ - if (lmp == *dlmp) + if (lmp == dlmp) break; /* @@ -2732,11 +2749,21 @@ * the symbol within the interposer. */ if (callable(clmp, lmp, 0, sl.sl_flags)) { - Rt_map *ilmp; - Sym *isym; - + Sresult sr; + + /* + * Initialize a local symbol result descriptor, using + * the original symbol name. Initialize a local symbol + * lookup descriptor, using the original lookup + * information, and a new initial link-map. + */ + SRESULT_INIT(sr, slp->sl_name); sl.sl_imap = lmp; - if (isym = SYMINTP(lmp)(&sl, &ilmp, binfo, in_nfavl)) { + + if (SYMINTP(lmp)(&sl, &sr, binfo, in_nfavl)) { + Sym *isym = sr.sr_sym; + Rt_map *ilmp = sr.sr_dmap; + /* * If this object provides individual symbol * interposers, make sure that the symbol we @@ -2750,13 +2777,13 @@ * Indicate this binding has occurred to an * interposer, and return the symbol. */ + *srp = sr; *binfo |= DBG_BINFO_INTERPOSE; - *dlmp = ilmp; - return (isym); + return (1); } } } - return (NULL); + return (0); } /* @@ -2764,12 +2791,12 @@ * describing where each binding was established during link-editing, and the * object was built -Bdirect), then look for the symbol in the specific object. */ -static Sym * -lookup_sym_direct(Slookup *slp, Rt_map **dlmp, uint_t *binfo, Syminfo *sip, +static int +lookup_sym_direct(Slookup *slp, Sresult *srp, uint_t *binfo, Syminfo *sip, Rt_map *lmp, int *in_nfavl) { - Rt_map *clmp = slp->sl_cmap; - Sym *sym; + Rt_map *dlmp, *clmp = slp->sl_cmap; + int ret; Slookup sl; /* @@ -2789,11 +2816,11 @@ */ if (((slp->sl_flags & LKUP_COPY) == 0) && (sip->si_flags & SYMINFO_FLG_COPY)) { - slp->sl_imap = LIST(clmp)->lm_head; - if (sym = SYMINTP(clmp)(slp, dlmp, binfo, in_nfavl)) + + if (ret = SYMINTP(clmp)(slp, srp, binfo, in_nfavl)) *binfo |= (DBG_BINFO_DIRECT | DBG_BINFO_COPYREF); - return (sym); + return (ret); } /* @@ -2802,7 +2829,7 @@ */ sl = *slp; sl.sl_flags |= LKUP_DIRECT; - sym = NULL; + ret = 0; if (sip->si_boundto == SYMINFO_BT_PARENT) { Aliste idx1; @@ -2815,8 +2842,7 @@ */ for (APLIST_TRAVERSE(CALLERS(clmp), idx1, bdp)) { sl.sl_imap = lmp = bdp->b_caller; - if ((sym = SYMINTP(lmp)(&sl, dlmp, binfo, - in_nfavl)) != NULL) + if (ret = SYMINTP(lmp)(&sl, srp, binfo, in_nfavl)) goto found; } @@ -2835,8 +2861,8 @@ if ((gdp->gd_flags & GPD_PARENT) == 0) continue; sl.sl_imap = lmp = gdp->gd_depend; - if ((sym = SYMINTP(lmp)(&sl, dlmp, - binfo, in_nfavl)) != NULL) + if (ret = SYMINTP(lmp)(&sl, srp, binfo, + in_nfavl)) goto found; } } @@ -2851,10 +2877,10 @@ sl.sl_imap = lmp; if (lmp) - sym = SYMINTP(lmp)(&sl, dlmp, binfo, in_nfavl); + ret = SYMINTP(lmp)(&sl, srp, binfo, in_nfavl); } found: - if (sym) + if (ret) *binfo |= DBG_BINFO_DIRECT; /* @@ -2863,20 +2889,18 @@ * a reference to a directly bound symbol is satisfied, then determine * whether that object can be interposed upon for this symbol. */ - if ((sym == NULL) || ((LIST(*dlmp)->lm_head != *dlmp) && - (LIST(*dlmp) == LIST(clmp)))) { - Sym *isym; - - if ((isym = lookup_sym_interpose(slp, dlmp, binfo, sym, - in_nfavl)) != 0) - return (isym); + dlmp = srp->sr_dmap; + if ((ret == 0) || (dlmp && (LIST(dlmp)->lm_head != dlmp) && + (LIST(dlmp) == LIST(clmp)))) { + if (lookup_sym_interpose(slp, srp, binfo, in_nfavl)) + return (1); } - return (sym); + return (ret); } -static Sym * -core_lookup_sym(Rt_map *ilmp, Slookup *slp, Rt_map **dlmp, uint_t *binfo, +static int +core_lookup_sym(Rt_map *ilmp, Slookup *slp, Sresult *srp, uint_t *binfo, Aliste off, int *in_nfavl) { Rt_map *lmp; @@ -2892,20 +2916,18 @@ for (; lmp; lmp = NEXT_RT_MAP(lmp)) { if (callable(slp->sl_cmap, lmp, 0, slp->sl_flags)) { - Sym *sym; slp->sl_imap = lmp; - if (((sym = SYMINTP(lmp)(slp, dlmp, binfo, - in_nfavl)) != NULL) || + if ((SYMINTP(lmp)(slp, srp, binfo, in_nfavl)) || (*binfo & BINFO_MSK_TRYAGAIN)) - return (sym); + return (1); } } - return (NULL); + return (0); } -static Sym * -rescan_lazy_find_sym(Rt_map *ilmp, Slookup *slp, Rt_map **dlmp, uint_t *binfo, +static int +rescan_lazy_find_sym(Rt_map *ilmp, Slookup *slp, Sresult *srp, uint_t *binfo, int *in_nfavl) { Rt_map *lmp; @@ -2914,26 +2936,24 @@ if (LAZY(lmp) == 0) continue; if (callable(slp->sl_cmap, lmp, 0, slp->sl_flags)) { - Sym *sym; slp->sl_imap = lmp; - if ((sym = elf_lazy_find_sym(slp, dlmp, binfo, - in_nfavl)) != 0) - return (sym); + if (elf_lazy_find_sym(slp, srp, binfo, in_nfavl)) + return (1); } } - return (NULL); + return (0); } -static Sym * -_lookup_sym(Slookup *slp, Rt_map **dlmp, uint_t *binfo, int *in_nfavl) +static int +_lookup_sym(Slookup *slp, Sresult *srp, uint_t *binfo, int *in_nfavl) { const char *name = slp->sl_name; Rt_map *clmp = slp->sl_cmap; Lm_list *lml = LIST(clmp); Rt_map *ilmp = slp->sl_imap, *lmp; ulong_t rsymndx; - Sym *sym; + int ret; Syminfo *sip; Slookup sl; @@ -2944,7 +2964,7 @@ * the link map). */ if (slp->sl_flags & LKUP_FIRST) - return (SYMINTP(ilmp)(slp, dlmp, binfo, in_nfavl)); + return (SYMINTP(ilmp)(slp, srp, binfo, in_nfavl)); /* * Determine whether this lookup can be satisfied by an objects direct, @@ -3004,7 +3024,7 @@ ((slp->sl_flags & LKUP_SINGLETON) == 0))) && ((FLAGS1(clmp) & FL1_RT_DIRECT) || (sip->si_flags & SYMINFO_FLG_DIRECTBIND))) { - sym = lookup_sym_direct(slp, dlmp, binfo, + ret = lookup_sym_direct(slp, srp, binfo, sip, lmp, in_nfavl); /* @@ -3023,7 +3043,7 @@ */ if (((*binfo & BINFO_MSK_REJECTED) == 0) || (*binfo & BINFO_MSK_TRYAGAIN)) - return (sym); + return (ret); *binfo &= ~BINFO_MSK_REJECTED; } @@ -3043,21 +3063,23 @@ */ if ((FLAGS1(clmp) & FL1_RT_SYMBOLIC) && ((sl.sl_flags & LKUP_SINGLETON) == 0)) { + sl.sl_imap = clmp; - if (sym = SYMINTP(clmp)(&sl, dlmp, binfo, in_nfavl)) { - ulong_t dsymndx = (((ulong_t)sym - - (ulong_t)SYMTAB(*dlmp)) / SYMENT(*dlmp)); + if (SYMINTP(clmp)(&sl, srp, binfo, in_nfavl)) { + Rt_map *dlmp = srp->sr_dmap; + ulong_t dsymndx = (((ulong_t)srp->sr_sym - + (ulong_t)SYMTAB(dlmp)) / SYMENT(dlmp)); /* * Make sure this symbol hasn't explicitly been defined * as nodirect. */ - if (((sip = SYMINFO(*dlmp)) == 0) || + if (((sip = SYMINFO(dlmp)) == 0) || /* LINTED */ ((sip = (Syminfo *)((char *)sip + - (dsymndx * SYMINENT(*dlmp)))) == 0) || + (dsymndx * SYMINENT(dlmp)))) == 0) || ((sip->si_flags & SYMINFO_FLG_NOEXTDIRECT) == 0)) - return (sym); + return (1); } } @@ -3073,16 +3095,16 @@ Aliste off; Lm_cntl *lmc; - sym = NULL; + ret = 0; for (ALIST_TRAVERSE_BY_OFFSET(lml->lm_lists, off, lmc)) { - if (((sym = core_lookup_sym(lmc->lc_head, &sl, dlmp, - binfo, off, in_nfavl)) != NULL) || + if (((ret = core_lookup_sym(lmc->lc_head, &sl, srp, + binfo, off, in_nfavl)) != 0) || (*binfo & BINFO_MSK_TRYAGAIN)) break; } } else - sym = core_lookup_sym(ilmp, &sl, dlmp, binfo, ALIST_OFF_DATA, + ret = core_lookup_sym(ilmp, &sl, srp, binfo, ALIST_OFF_DATA, in_nfavl); /* @@ -3090,7 +3112,7 @@ * be repeated. */ if (*binfo & BINFO_MSK_TRYAGAIN) - return (sym); + return (0); /* * To allow transitioning into a world of lazy loading dependencies see @@ -3100,7 +3122,7 @@ * the reference can be satisfied. Use of dlsym(RTLD_PROBE) sets the * LKUP_NOFALLBACK flag, and this flag disables this fall back. */ - if ((sym == NULL) && ((sl.sl_flags & LKUP_NOFALLBACK) == 0)) { + if ((ret == 0) && ((sl.sl_flags & LKUP_NOFALLBACK) == 0)) { if ((lmp = ilmp) == 0) lmp = LIST(clmp)->lm_head; @@ -3116,7 +3138,7 @@ * initial link-map. */ if (sl.sl_flags & LKUP_NEXT) - sym = rescan_lazy_find_sym(clmp, &sl, dlmp, binfo, + ret = rescan_lazy_find_sym(clmp, &sl, srp, binfo, in_nfavl); else { Aliste idx; @@ -3124,13 +3146,13 @@ for (ALIST_TRAVERSE(lml->lm_lists, idx, lmc)) { sl.sl_flags |= LKUP_NOFALLBACK; - if ((sym = rescan_lazy_find_sym(lmc->lc_head, - &sl, dlmp, binfo, in_nfavl)) != NULL) + if (ret = rescan_lazy_find_sym(lmc->lc_head, + &sl, srp, binfo, in_nfavl)) break; } } } - return (sym); + return (ret); } /* @@ -3139,31 +3161,53 @@ * pointer to the link map of the enclosing object, and information relating * to the type of binding. Else return a null pointer. * - * To improve elf performance, we first compute the elf hash value and pass - * it to each find_sym() routine. The elf function will use this value to + * To improve ELF performance, we first compute the ELF hash value and pass + * it to each _lookup_sym() routine. The ELF function will use this value to * locate the symbol, the a.out function will simply ignore it. */ -Sym * -lookup_sym(Slookup *slp, Rt_map **dlmp, uint_t *binfo, int *in_nfavl) +int +lookup_sym(Slookup *slp, Sresult *srp, uint_t *binfo, int *in_nfavl) { Rt_map *clmp = slp->sl_cmap; - Sym *rsym = slp->sl_rsym, *sym = NULL; - uchar_t rtype = slp->sl_rtype; - int mode; + Sym *rsym = slp->sl_rsym; + uchar_t rtype = slp->sl_rtype, vis; + int ret, mode; if (slp->sl_hash == 0) slp->sl_hash = elf_hash(slp->sl_name); *binfo = 0; - /* - * Establish any state that might be associated with a symbol reference. - */ if (rsym) { + vis = ELF_ST_VISIBILITY(rsym->st_other); + + /* + * Symbols that are defined as protected, or hidden, within an + * object usually have any relocation references from within + * the same object bound at link-edit time. Therefore, ld.so.1 + * is not involved. However, if a reference is to a + * capabilities symbol, this reference must be resolved at + * runtime. In this case look directly within the calling + * object, and only within the calling object, for these + * symbols. Note, an object may still use dlsym() to search + * externally for a symbol which is defined as protected within + * the same object. + */ + if ((rsym->st_shndx != SHN_UNDEF) && + ((slp->sl_flags & LKUP_DLSYM) == 0) && + ((vis == STV_PROTECTED) || (vis == STV_HIDDEN))) { + slp->sl_imap = clmp; + return (SYMINTP(clmp)(slp, srp, binfo, in_nfavl)); + } + + /* + * Establish any state that might be associated with a symbol + * reference. + */ if ((slp->sl_flags & LKUP_STDRELOC) && (ELF_ST_BIND(rsym->st_info) == STB_WEAK)) slp->sl_flags |= LKUP_WEAK; - if (ELF_ST_VISIBILITY(rsym->st_other) == STV_SINGLETON) + if (vis == STV_SINGLETON) slp->sl_flags |= LKUP_SINGLETON; } @@ -3200,7 +3244,7 @@ * Carry out an initial symbol search. This search takes into account * all the modes of the requested search. */ - if (((sym = _lookup_sym(slp, dlmp, binfo, in_nfavl)) == NULL) && + if (((ret = _lookup_sym(slp, srp, binfo, in_nfavl)) == 0) && (*binfo & BINFO_MSK_TRYAGAIN)) { Slookup sl = *slp; @@ -3226,7 +3270,7 @@ } *binfo &= ~BINFO_MSK_REJECTED; - sym = _lookup_sym(&sl, dlmp, binfo, in_nfavl); + ret = _lookup_sym(&sl, srp, binfo, in_nfavl); } /* @@ -3234,14 +3278,11 @@ * determine if it is necessary to follow a binding from outside of * the group. */ - if ((mode & (RTLD_GROUP | RTLD_WORLD)) == RTLD_GROUP) { - Sym *isym; - - if ((isym = lookup_sym_interpose(slp, dlmp, binfo, sym, - in_nfavl)) != NULL) - return (isym); - } - return (sym); + if (((mode & (RTLD_GROUP | RTLD_WORLD)) == RTLD_GROUP) && + (lookup_sym_interpose(slp, srp, binfo, in_nfavl))) + return (1); + + return (ret); } /*
--- a/usr/src/cmd/sgs/rtld/common/audit.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/common/audit.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Audit interfaces. Auditing can be enabled in two ways: @@ -885,22 +885,23 @@ static Addr audit_symget(Audit_list *alp, int info, int *in_nfavl) { - Rt_map *_lmp, *lmp = alp->al_lmp; + Rt_map *lmp = alp->al_lmp; const char *sname = MSG_ORIG(aud_info[info].sname); uint_t alflag = aud_info[info].alflag; uint_t auflag = aud_info[info].auflag; uint_t binfo; - Sym *sym; Slookup sl; + Sresult sr; /* - * Initialize the symbol lookup data structure. + * Initialize the symbol lookup, and symbol result, data structures. */ SLOOKUP_INIT(sl, sname, lml_rtld.lm_head, lmp, ld_entry_cnt, - 0, 0, 0, 0, LKUP_FIRST); + 0, 0, 0, 0, (LKUP_FIRST | LKUP_DLSYM)); + SRESULT_INIT(sr, sname); - if (sym = LM_LOOKUP_SYM(lmp)(&sl, &_lmp, &binfo, in_nfavl)) { - Addr addr = sym->st_value; + if (LM_LOOKUP_SYM(lmp)(&sl, &sr, &binfo, in_nfavl)) { + Addr addr = sr.sr_sym->st_value; if (!(FLAGS(lmp) & FLG_RT_FIXED)) addr += ADDR(lmp); @@ -911,10 +912,10 @@ audit_flags |= auflag; DBG_CALL(Dbg_audit_interface(LIST(alp->al_lmp), - alp->al_libname, sname)); + alp->al_libname, sr.sr_name)); return (addr); - } else - return (0); + } + return (0); } /*
--- a/usr/src/cmd/sgs/rtld/common/cap.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/common/cap.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -33,49 +33,112 @@ #include <limits.h> #include <debug.h> #include <conv.h> +#include <elfcap.h> #include "_rtld.h" +#include "_elf.h" #include "_audit.h" #include "msg.h" /* - * qsort(3c) comparison function. + * qsort(3c) capability comparison function. */ static int -compare(const void *fdesc1, const void *fdesc2) +compare(const void *fdp_a, const void *fdp_b) { - Xword hwcap1 = ((Fdesc *)fdesc1)->fd_hwcap; - Xword hwcap2 = ((Fdesc *)fdesc2)->fd_hwcap; + char *strcap_a, *strcap_b; + Xword hwcap_a, hwcap_b; + + /* + * First, investigate any platform capability. + */ + strcap_a = ((Fdesc *)fdp_a)->fd_scapset.sc_plat; + strcap_b = ((Fdesc *)fdp_b)->fd_scapset.sc_plat; - if (hwcap1 && (hwcap2 == 0)) + if (strcap_a && (strcap_b == NULL)) + return (-1); + if (strcap_b && (strcap_a == NULL)) + return (1); + + /* + * Second, investigate any machine capability. + */ + strcap_a = ((Fdesc *)fdp_a)->fd_scapset.sc_mach; + strcap_b = ((Fdesc *)fdp_b)->fd_scapset.sc_mach; + + if (strcap_a && (strcap_b == NULL)) return (-1); - if ((hwcap1 == 0) && hwcap2) + if (strcap_b && (strcap_a == NULL)) return (1); - if ((hwcap1 == 0) && (hwcap2 == 0)) - return (0); + + /* + * Third, investigate any CA_SUNW_HW_2 hardware capabilities. + */ + hwcap_a = ((Fdesc *)fdp_a)->fd_scapset.sc_hw_2; + hwcap_b = ((Fdesc *)fdp_b)->fd_scapset.sc_hw_2; - if (hwcap1 > hwcap2) + if (hwcap_a > hwcap_b) return (-1); - if (hwcap1 < hwcap2) + if (hwcap_a < hwcap_b) return (1); + + /* + * Finally, investigate any CA_SUNW_HW_1 hardware capabilities. + */ + hwcap_a = ((Fdesc *)fdp_a)->fd_scapset.sc_hw_1; + hwcap_b = ((Fdesc *)fdp_b)->fd_scapset.sc_hw_1; + + if (hwcap_a > hwcap_b) + return (-1); + if (hwcap_a < hwcap_b) + return (1); + return (0); } /* - * Process any hardware capabilities. + * Determine whether HWCAP1 capabilities value is supported. */ int -hwcap_check(Xword val, Rej_desc *rej) +hwcap1_check(Syscapset *scapset, Xword val, Rej_desc *rej) { Xword mval; /* * Ensure that the kernel can cope with the required capabilities. */ - if ((rtld_flags2 & RT_FL2_HWCAP) && ((mval = (val & ~hwcap)) != 0)) { - static Conv_cap_val_hw1_buf_t cap_buf; + if ((rtld_flags2 & RT_FL2_HWCAP) && + ((mval = (val & ~scapset->sc_hw_1)) != 0)) { + if (rej) { + static Conv_cap_val_hw1_buf_t cap_buf; + + rej->rej_type = SGS_REJ_HWCAP_1; + rej->rej_str = conv_cap_val_hw1(mval, + M_MACH, 0, &cap_buf); + } + return (0); + } + return (1); +} - rej->rej_type = SGS_REJ_HWCAP_1; - rej->rej_str = conv_cap_val_hw1(mval, M_MACH, 0, &cap_buf); +/* + * Determine whether HWCAP2 capabilities value is supported. + */ +int +hwcap2_check(Syscapset *scapset, Xword val, Rej_desc *rej) +{ + Xword mval; + + /* + * Ensure that the kernel can cope with the required capabilities. + */ + if ((mval = (val & ~scapset->sc_hw_2)) != 0) { + if (rej) { + static Conv_cap_val_hw2_buf_t cap_buf; + + rej->rej_type = SGS_REJ_HWCAP_2; + rej->rej_str = conv_cap_val_hw2(mval, + M_MACH, 0, &cap_buf); + } return (0); } return (1); @@ -86,7 +149,7 @@ */ /* ARGSUSED0 */ int -sfcap_check(Xword val, Rej_desc *rej) +sfcap1_check(Syscapset *scapset, Xword val, Rej_desc *rej) { #if defined(_ELF64) /* @@ -96,11 +159,13 @@ * established this requirement. */ if ((val & SF1_SUNW_ADDR32) && ((rtld_flags2 & RT_FL2_ADDR32) == 0)) { - static Conv_cap_val_sf1_buf_t cap_buf; + if (rej) { + static Conv_cap_val_sf1_buf_t cap_buf; - rej->rej_type = SGS_REJ_SFCAP_1; - rej->rej_str = - conv_cap_val_sf1(SF1_SUNW_ADDR32, M_MACH, 0, &cap_buf); + rej->rej_type = SGS_REJ_SFCAP_1; + rej->rej_str = conv_cap_val_sf1(SF1_SUNW_ADDR32, + M_MACH, 0, &cap_buf); + } return (0); } #endif @@ -108,11 +173,324 @@ } /* - * When $HWCAP is used to represent dependencies, take the associated directory - * and analyze all the files it contains. + * Process any platform capability. + */ +int +platcap_check(Syscapset *scapset, const char *str, Rej_desc *rej) +{ + /* + * If the platform name hasn't been set, try and obtain it. + */ + if ((scapset->sc_plat == NULL) && + (scapset->sc_platsz == 0)) + platform_name(scapset); + + if ((scapset->sc_plat == NULL) || + (str && strcmp(scapset->sc_plat, str))) { + if (rej) { + /* + * Note, the platform name points to a string within an + * objects string table, and if that object can't be + * loaded, it will be unloaded and thus invalidate the + * string. Duplicate the string here for rejection + * message inheritance. + */ + rej->rej_type = SGS_REJ_PLATCAP; + rej->rej_str = stravl_insert(str, 0, 0, 0); + } + return (0); + } + return (1); +} + +/* + * Process any machine capability. + */ +int +machcap_check(Syscapset *scapset, const char *str, Rej_desc *rej) +{ + /* + * If the machine name hasn't been set, try and obtain it. + */ + if ((scapset->sc_mach == NULL) && + (scapset->sc_machsz == 0)) + machine_name(scapset); + + if ((scapset->sc_mach == NULL) || + (str && strcmp(scapset->sc_mach, str))) { + if (rej) { + /* + * Note, the machine name points to a string within an + * objects string table, and if that object can't be + * loaded, it will be unloaded and thus invalidate the + * string. Duplicate the string here for rejection + * message inheritance. + */ + rej->rej_type = SGS_REJ_MACHCAP; + rej->rej_str = stravl_insert(str, 0, 0, 0); + } + return (0); + } + return (1); +} + +/* + * Generic front-end to capabilities validation. */ static int -hwcap_dir(Alist **fdalpp, Lm_list *lml, const char *dname, Rt_map *clmp, +cap_check(Cap *cptr, char *strs, int alt, Fdesc *fdp, Rej_desc *rej) +{ + Syscapset *scapset; + int totplat, ivlplat, totmach, ivlmach; + + /* + * If the caller has no capabilities, then the object is valid. + */ + if (cptr == NULL) + return (1); + + if (alt) + scapset = alt_scapset; + else + scapset = org_scapset; + + totplat = ivlplat = totmach = ivlmach = 0; + + while (cptr->c_tag != CA_SUNW_NULL) { + Xword val = cptr->c_un.c_val; + char *str; + + switch (cptr->c_tag) { + case CA_SUNW_HW_1: + if (hwcap1_check(scapset, val, rej) == 0) + return (0); + if (fdp) + fdp->fd_scapset.sc_hw_1 = val; + break; + case CA_SUNW_SF_1: + if (sfcap1_check(scapset, val, rej) == 0) + return (0); + if (fdp) + fdp->fd_scapset.sc_sf_1 = val; + break; + case CA_SUNW_HW_2: + if (hwcap2_check(scapset, val, rej) == 0) + return (0); + if (fdp) + fdp->fd_scapset.sc_hw_2 = val; + break; + case CA_SUNW_PLAT: + /* + * A capabilities group can define multiple platform + * names that are appropriate. Only if all the names + * are deemed invalid is the group determined + * inappropriate. + */ + if (totplat == ivlplat) { + totplat++; + + str = strs + val; + + if (platcap_check(scapset, str, rej) == 0) + ivlplat++; + else if (fdp) + fdp->fd_scapset.sc_plat = str; + } + break; + case CA_SUNW_MACH: + /* + * A capabilities group can define multiple machine + * names that are appropriate. Only if all the names + * are deemed invalid is the group determined + * inappropriate. + */ + if (totmach == ivlmach) { + totmach++; + + str = strs + val; + + if (machcap_check(scapset, str, rej) == 0) + ivlmach++; + else if (fdp) + fdp->fd_scapset.sc_mach = str; + } + break; + case CA_SUNW_ID: + /* + * Capabilities identifiers provide for diagnostics, + * but are not attributes that must be compared with + * the system. They are ignored. + */ + break; + default: + rej->rej_type = SGS_REJ_UNKCAP; + rej->rej_info = cptr->c_tag; + return (0); + } + cptr++; + } + + /* + * If any platform names, or machine names were found, and all were + * invalid, indicate that the object is inappropriate. + */ + if ((totplat && (totplat == ivlplat)) || + (totmach && (totmach == ivlmach))) + return (0); + + return (1); +} + +#define HWAVL_RECORDED(n) pnavl_recorded(&capavl, n, NULL, NULL) + +/* + * Determine whether a link-map should use alternative system capabilities. + */ +static void +cap_check_lmp_init(Rt_map *lmp) +{ + int alt = 0; + + /* + * If an alternative set of system capabilities have been established, + * and only specific files should use these alternative system + * capabilities, determine whether this file is one of those specified. + */ + if (capavl) { + const char *file; + + /* + * The simplest way to reference a file is to use its file name + * (soname), however try all of the names that this file is + * known by. + */ + if ((file = strrchr(NAME(lmp), '/')) != NULL) + file++; + else + file = NULL; + + if ((file && (HWAVL_RECORDED(file) != 0)) || + (HWAVL_RECORDED(NAME(lmp)) != 0) || + ((PATHNAME(lmp) != NAME(lmp)) && + (HWAVL_RECORDED(PATHNAME(lmp)) != 0))) + alt = 1; + + if (alt == 0) { + Aliste idx; + const char *cp; + + for (APLIST_TRAVERSE(ALIAS(lmp), idx, cp)) { + if ((alt = HWAVL_RECORDED(cp)) != 0) + break; + } + } + } + + /* + * Indicate if this link-map should use alternative system capabilities, + * and that the alternative system capabilities check has been carried + * out. + */ + if ((org_scapset != alt_scapset) && ((capavl == NULL) || alt)) + FLAGS1(lmp) |= FL1_RT_ALTCAP; + FLAGS1(lmp) |= FL1_RT_ALTCHECK; +} + +/* + * Validate the capabilities requirements of a link-map. + * + * This routine is called for main, where a link-map is constructed from the + * mappings returned from exec(), and for any symbol capabilities comparisons. + */ +int +cap_check_lmp(Rt_map *lmp, Rej_desc *rej) +{ + if ((FLAGS1(lmp) & FL1_RT_ALTCHECK) == 0) + cap_check_lmp_init(lmp); + + return (cap_check(CAP(lmp), STRTAB(lmp), + (FLAGS1(lmp) & FL1_RT_ALTCAP), NULL, rej)); +} + +/* + * Validate the capabilities requirements of a file under inspection. + * This file is still under the early stages of loading, and has no link-map + * yet. The file must have an object capabilities definition (PT_SUNWCAP), to + * have gotten us here. The logic here is the same as cap_check_lmp(). + */ +int +cap_check_fdesc(Fdesc *fdp, Cap *cptr, char *strs, Rej_desc *rej) +{ + int alt = 0; + + /* + * If an alternative set of system capabilities have been established, + * and only specific files should use these alternative system + * capabilities, determine whether this file is one of those specified. + */ + if (capavl) { + const char *file; + + /* + * The simplest way to reference a file is to use its file name + * (soname), however try all of the names that this file is + * known by. + */ + if ((file = strrchr(fdp->fd_oname, '/')) != NULL) + file++; + else + file = NULL; + + if ((file && (HWAVL_RECORDED(file) != 0)) || + (fdp->fd_oname && (HWAVL_RECORDED(fdp->fd_oname) != 0)) || + (fdp->fd_nname && (HWAVL_RECORDED(fdp->fd_nname) != 0)) || + (fdp->fd_pname && (fdp->fd_pname != fdp->fd_nname) && + (HWAVL_RECORDED(fdp->fd_pname) != 0))) + alt = 1; + } + + /* + * Indicate if this file descriptor should use alternative system + * capabilities, and that the alternative system capabilities check has + * been carried out. + */ + if ((org_scapset != alt_scapset) && ((capavl == NULL) || alt)) + fdp->fd_flags |= FLG_FD_ALTCAP; + fdp->fd_flags |= FLG_FD_ALTCHECK; + + /* + * Verify that the required capabilities are supported by the reference. + */ + return (cap_check(cptr, strs, (fdp->fd_flags & FLG_FD_ALTCAP), + fdp, rej)); +} + +/* + * Free a file descriptor list. As part of building this list, the original + * names for each capabilities candidate were duplicated for use in later + * diagnostics. These names need to be freed. + */ +void +free_fd(Alist *fdalp) +{ + if (fdalp) { + Aliste idx; + Fdesc *fdp; + + for (ALIST_TRAVERSE(fdalp, idx, fdp)) { + if (fdp->fd_oname) + free((void *)fdp->fd_oname); + } + free(fdalp); + } +} + +/* + * When $CAPABILITY (or $HWCAP) is used to represent dependencies, take the + * associated directory and analyze all the files it contains. + */ +static int +cap_dir(Alist **fdalpp, Lm_list *lml, const char *dname, Rt_map *clmp, uint_t flags, Rej_desc *rej, int *in_nfavl) { char path[PATH_MAX], *dst; @@ -187,18 +565,24 @@ continue; } - DBG_CALL(Dbg_cap_hw_candidate(lml, fd.fd_nname)); + DBG_CALL(Dbg_cap_candidate(lml, fd.fd_nname)); /* - * If this object has already been loaded, obtain the hardware - * capabilities for later sorting. Otherwise we have a new - * candidate. + * If this object has already been loaded, save the capabilities + * for later sorting. Otherwise we have a new candidate. */ if (fd.fd_lmp) - fd.fd_hwcap = HWCAP(fd.fd_lmp); + fd.fd_scapset = CAPSET(fd.fd_lmp); - if (alist_append(&fdalp, &fd, sizeof (Fdesc), - AL_CNT_HWCAP) == NULL) { + /* + * Duplicate the original name, as this may be required for + * later diagnostics. Keep a copy of the file descriptor for + * analysis once all capabilities candidates have been + * determined. + */ + if (((fd.fd_oname = strdup(fd.fd_oname)) == NULL) || + (alist_append(&fdalp, &fd, sizeof (Fdesc), + AL_CNT_CAP) == NULL)) { error = 1; break; } @@ -212,7 +596,7 @@ */ if ((fdalp == NULL) || error) { if (fdalp) - free(fdalp); + free_fd(fdalp); return (0); } @@ -227,7 +611,7 @@ } int -hwcap_filtees(Alist **alpp, Aliste oidx, const char *dir, Aliste nlmco, +cap_filtees(Alist **alpp, Aliste oidx, const char *dir, Aliste nlmco, Rt_map *flmp, const char *ref, int mode, uint_t flags, int *in_nfavl) { Alist *fdalp = NULL; @@ -237,7 +621,7 @@ int unused = 0; Rej_desc rej = { 0 }; - if (hwcap_dir(&fdalp, lml, dir, flmp, flags, &rej, in_nfavl) == 0) + if (cap_dir(&fdalp, lml, dir, flmp, flags, &rej, in_nfavl) == 0) return (0); /* @@ -348,15 +732,15 @@ } } - free(fdalp); + free_fd(fdalp); return (1); } /* - * Load an individual hardware capabilities object. + * Load an individual capabilities object. */ Rt_map * -load_hwcap(Lm_list *lml, Aliste lmco, const char *dir, Rt_map *clmp, +load_cap(Lm_list *lml, Aliste lmco, const char *dir, Rt_map *clmp, uint_t mode, uint_t flags, Grp_hdl **hdl, Rej_desc *rej, int *in_nfavl) { Alist *fdalp = NULL; @@ -368,7 +752,7 @@ /* * Obtain the sorted list of hardware capabilities objects available. */ - if (hwcap_dir(&fdalp, lml, dir, clmp, flags, rej, in_nfavl) == 0) + if (cap_dir(&fdalp, lml, dir, clmp, flags, rej, in_nfavl) == 0) return (NULL); /* @@ -383,6 +767,605 @@ found++; } - free(fdalp); + free_fd(fdalp); return (lmp); } + +/* + * Use a case insensitive string match when looking up capability mask + * values by name, and omit the AV_ prefix. + */ +#define ELFCAP_STYLE ELFCAP_STYLE_LC | ELFCAP_STYLE_F_ICMP + +/* + * To aid in the development and testing of capabilities, an alternative system + * capabilities group can be specified. This alternative set is initialized + * from the system capabilities that are normally used to validate all object + * loading. However, the user can disable, enable or override flags within + * this alternative set, and thus affect object loading. + * + * This technique is usually combined with defining the family of objects + * that should be compared against this alternative set. Without defining the + * family of objects, all objects loaded by ld.so.1 are validated against the + * alternative set. This can prevent the loading of critical system objects + * like libc, and thus prevent process execution. + */ +typedef enum { + CAP_OVERRIDE = 0, /* override existing capabilities */ + CAP_ENABLE = 1, /* enable capabilities */ + CAP_DISABLE = 2 /* disable capabilities */ +} cap_mode; + +static struct { + elfcap_mask_t cs_val[3]; /* value settings, and indicator for */ + int cs_set[3]; /* OVERRIDE, ENABLE and DISABLE */ + elfcap_mask_t *cs_aval; /* alternative variable for final */ + /* update */ +} cap_settings[3] = { + { { 0, 0, 0 }, { 0, 0, 0 }, NULL }, /* CA_SUNW_HW_1 */ + { { 0, 0, 0 }, { 0, 0, 0 }, NULL }, /* CA_SUNW_SF_1 */ + { { 0, 0, 0 }, { 0, 0, 0 }, NULL } /* CA_SUNW_HW_2 */ +}; + +static int +cap_modify(Xword tag, const char *str) +{ + char *caps, *ptr, *next; + cap_mode mode = CAP_OVERRIDE; + Xword ndx; + + if ((caps = strdup(str)) == NULL) + return (0); + + ptr = strtok_r(caps, MSG_ORIG(MSG_CAP_DELIMIT), &next); + do { + Xword val = 0; + + /* + * Determine whether this token should be enabled (+), + * disabled (-), or override any existing settings. + */ + if (*ptr == '+') { + mode = CAP_ENABLE; + ptr++; + } else if (*ptr == '-') { + mode = CAP_DISABLE; + ptr++; + } + + /* + * Process the capabilities as directed by the calling tag. + */ + switch (tag) { + case CA_SUNW_HW_1: + /* + * Determine whether the capabilities string matches + * a known hardware capability mask. Note, the caller + * indicates that these are hardware capabilities by + * passing in the CA_SUNW_HW_1 tag. However, the + * tokens could be CA_SUNW_HW_1 or CA_SUNW_HW_2. + */ + if ((val = (Xword)elfcap_hw2_from_str(ELFCAP_STYLE, + ptr, M_MACH)) != 0) { + ndx = CA_SUNW_HW_2; + break; + } + if ((val = (Xword)elfcap_hw1_from_str(ELFCAP_STYLE, + ptr, M_MACH)) != 0) + ndx = CA_SUNW_HW_1; + break; + case CA_SUNW_SF_1: + /* + * Determine whether the capabilities string matches a + * known software capability mask. Note, the callers + * indication of what capabilities to process are + * triggered by a tag of CA_SUNW_SF_1, but the tokens + * processed could be CA_SUNW_SF_1, CA_SUNW_SF_2, etc. + */ + if ((val = (Xword)elfcap_sf1_from_str(ELFCAP_STYLE, + ptr, M_MACH)) != 0) + ndx = CA_SUNW_SF_1; + break; + } + + /* + * If a capabilities token has not been matched, interpret the + * string as a number. To provide for setting the various + * families (CA_SUNW_HW_1, CA_SUNW_HW_2), the number can be + * prefixed with the (bracketed) family index. + * + * LD_HWCAP=[1]0x40 sets CA_SUNW_HW_1 with 0x40 + * LD_HWCAP=[2]0x80 sets CA_SUNW_HW_2 with 0x80 + * + * Invalid indexes are ignored. + */ + if (val == 0) { + if ((*ptr == '[') && (*(ptr + 2) == ']')) { + if (*(ptr + 1) == '1') { + ndx = tag; + ptr += 3; + } else if (*(ptr + 1) == '2') { + if (tag == CA_SUNW_HW_1) { + ndx = CA_SUNW_HW_2; + ptr += 3; + } else { + /* invalid index */ + continue; + } + } else { + /* invalid index */ + continue; + } + } else + ndx = tag; + + errno = 0; + if (((val = strtol(ptr, NULL, 16)) == 0) && errno) + continue; + } + cap_settings[ndx - 1].cs_val[mode] |= val; + cap_settings[ndx - 1].cs_set[mode]++; + + } while ((ptr = strtok_r(NULL, + MSG_ORIG(MSG_CAP_DELIMIT), &next)) != NULL); + + /* + * If the "override" token was supplied, set the alternative + * system capabilities, then enable or disable others. + */ + for (ndx = 0; ndx < CA_SUNW_HW_2; ndx++) { + if (cap_settings[ndx].cs_set[CAP_OVERRIDE]) + *(cap_settings[ndx].cs_aval) = + cap_settings[ndx].cs_val[CAP_OVERRIDE]; + if (cap_settings[ndx].cs_set[CAP_ENABLE]) + *(cap_settings[ndx].cs_aval) |= + cap_settings[ndx].cs_val[CAP_ENABLE]; + if (cap_settings[ndx].cs_set[CAP_DISABLE]) + *(cap_settings[ndx].cs_aval) &= + ~cap_settings[ndx].cs_val[CAP_DISABLE]; + } + free(caps); + return (1); +} +#undef ELFCAP_STYLE + +/* + * Create an AVL tree of objects that are to be validated against an alternative + * system capabilities value. + */ +static int +cap_files(const char *str) +{ + char *caps, *name, *next; + + if ((caps = strdup(str)) == NULL) + return (0); + + name = strtok_r(caps, MSG_ORIG(MSG_CAP_DELIMIT), &next); + do { + avl_index_t where; + PathNode *pnp; + uint_t hash = sgs_str_hash(name); + + /* + * Determine whether this pathname has already been recorded. + */ + if (pnavl_recorded(&capavl, name, hash, &where)) + continue; + + if ((pnp = calloc(sizeof (PathNode), 1)) != NULL) { + pnp->pn_name = name; + pnp->pn_hash = hash; + avl_insert(capavl, pnp, where); + } + } while ((name = strtok_r(NULL, + MSG_ORIG(MSG_CAP_DELIMIT), &next)) != NULL); + + return (1); +} + +/* + * Set alternative system capabilities. A user can establish alternative system + * capabilities from the environment, or from a configuration file. This + * routine is called in each instance. Environment variables only set the + * replaceable (rpl) variables. Configuration files can set both replaceable + * (rpl) and permanent (prm) variables. + */ +int +cap_alternative(void) +{ + /* + * If no capabilities have been set, we're done. + */ + if ((rpl_hwcap == NULL) && (rpl_sfcap == NULL) && + (rpl_machcap == NULL) && (rpl_platcap == NULL) && + (prm_hwcap == NULL) && (prm_sfcap == NULL) && + (prm_machcap == NULL) && (prm_platcap == NULL)) + return (1); + + /* + * If the user has requested to modify any capabilities, establish a + * unique set from the present system capabilities. + */ + if ((alt_scapset = malloc(sizeof (Syscapset))) == NULL) + return (0); + *alt_scapset = *org_scapset; + + cap_settings[CA_SUNW_HW_1 - 1].cs_aval = &alt_scapset->sc_hw_1; + cap_settings[CA_SUNW_SF_1 - 1].cs_aval = &alt_scapset->sc_sf_1; + cap_settings[CA_SUNW_HW_2 - 1].cs_aval = &alt_scapset->sc_hw_2; + + /* + * Process any replaceable variables. + */ + if (rpl_hwcap && (cap_modify(CA_SUNW_HW_1, rpl_hwcap) == 0)) + return (0); + if (rpl_sfcap && (cap_modify(CA_SUNW_SF_1, rpl_sfcap) == 0)) + return (0); + + if (rpl_platcap) { + alt_scapset->sc_plat = (char *)rpl_platcap; + alt_scapset->sc_platsz = strlen(rpl_platcap); + } + if (rpl_machcap) { + alt_scapset->sc_mach = (char *)rpl_machcap; + alt_scapset->sc_machsz = strlen(rpl_machcap); + } + + if (rpl_cap_files && (cap_files(rpl_cap_files) == 0)) + return (0); + + /* + * Process any permanent variables. + */ + if (prm_hwcap && (cap_modify(CA_SUNW_HW_1, prm_hwcap) == 0)) + return (0); + if (prm_sfcap && (cap_modify(CA_SUNW_SF_1, prm_sfcap) == 0)) + return (0); + + if (prm_platcap) { + alt_scapset->sc_plat = (char *)prm_platcap; + alt_scapset->sc_platsz = strlen(prm_platcap); + } + if (prm_machcap) { + alt_scapset->sc_mach = (char *)prm_machcap; + alt_scapset->sc_machsz = strlen(prm_machcap); + } + + if (prm_cap_files && (cap_files(prm_cap_files) == 0)) + return (0); + + /* + * Reset the replaceable variables. If this is the environment variable + * processing, these variables are now available for configuration file + * initialization. + */ + rpl_hwcap = rpl_sfcap = rpl_machcap = rpl_platcap = + rpl_cap_files = NULL; + + return (1); +} + +/* + * Take the index from a Capinfo entry and determine the associated capabilities + * set. Verify that the capabilities are available for this system. + */ +static int +sym_cap_check(Cap *cptr, uint_t cndx, Syscapset *bestcapset, Rt_map *lmp, + const char *name, uint_t ndx) +{ + Syscapset *scapset; + int totplat, ivlplat, totmach, ivlmach, capfail = 0; + + /* + * Determine whether this file requires validation against alternative + * system capabilities. + */ + if ((FLAGS1(lmp) & FL1_RT_ALTCHECK) == 0) + cap_check_lmp_init(lmp); + + if (FLAGS1(lmp) & FL1_RT_ALTCAP) + scapset = alt_scapset; + else + scapset = org_scapset; + + totplat = ivlplat = totmach = ivlmach = 0; + + /* + * A capabilities index points to a capabilities group that can consist + * of one or more capabilities, terminated with a CA_SUNW_NULL entry. + */ + for (cptr += cndx; cptr->c_tag != CA_SUNW_NULL; cptr++) { + Xword val = cptr->c_un.c_val; + char *str; + + switch (cptr->c_tag) { + case CA_SUNW_HW_1: + bestcapset->sc_hw_1 = val; + DBG_CALL(Dbg_syms_cap_lookup(lmp, DBG_CAP_HW_1, + name, ndx, M_MACH, bestcapset)); + + if (hwcap1_check(scapset, val, NULL) == 0) + capfail++; + break; + case CA_SUNW_SF_1: + bestcapset->sc_sf_1 = val; + DBG_CALL(Dbg_syms_cap_lookup(lmp, DBG_CAP_SF_1, + name, ndx, M_MACH, bestcapset)); + + if (sfcap1_check(scapset, val, NULL) == 0) + capfail++; + break; + case CA_SUNW_HW_2: + bestcapset->sc_hw_2 = val; + DBG_CALL(Dbg_syms_cap_lookup(lmp, DBG_CAP_HW_2, + name, ndx, M_MACH, bestcapset)); + + if (hwcap2_check(scapset, val, NULL) == 0) + capfail++; + break; + case CA_SUNW_PLAT: + /* + * A capabilities set can define multiple platform names + * that are appropriate. Only if all the names are + * deemed invalid is the group determined inappropriate. + */ + if (totplat == ivlplat) { + totplat++; + + str = STRTAB(lmp) + val; + bestcapset->sc_plat = str; + + DBG_CALL(Dbg_syms_cap_lookup(lmp, DBG_CAP_PLAT, + name, ndx, M_MACH, bestcapset)); + + if (platcap_check(scapset, str, NULL) == 0) + ivlplat++; + } + break; + case CA_SUNW_MACH: + /* + * A capabilities set can define multiple machine names + * that are appropriate. Only if all the names are + * deemed invalid is the group determined inappropriate. + */ + if (totmach == ivlmach) { + totmach++; + + str = STRTAB(lmp) + val; + bestcapset->sc_mach = str; + + DBG_CALL(Dbg_syms_cap_lookup(lmp, DBG_CAP_MACH, + name, ndx, M_MACH, bestcapset)); + + if (machcap_check(scapset, str, NULL) == 0) + ivlmach++; + } + break; + default: + break; + } + } + + /* + * If any platform definitions, or machine definitions were found, and + * all were invalid, indicate that the object is inappropriate. + */ + if (capfail || (totplat && (totplat == ivlplat)) || + (totmach && (totmach == ivlmach))) { + DBG_CALL(Dbg_syms_cap_lookup(lmp, DBG_CAP_REJECTED, name, ndx, + M_MACH, NULL)); + return (0); + } + + DBG_CALL(Dbg_syms_cap_lookup(lmp, DBG_CAP_CANDIDATE, name, ndx, + M_MACH, NULL)); + return (1); +} + +/* + * Determine whether a symbols capabilities are more significant than any that + * have already been validated. The precedence of capabilities are: + * + * PLATCAP -> MACHCAP -> HWCAP_2 -> HWCAP_1 + * + * + * Presently we make no comparisons of software capabilities. However, should + * this symbol capability have required the SF1_SUNW_ADDR32 attribute, then + * this would have been validated as appropriate or not. + * + * bestcapset is the presently available 'best' capabilities group, and + * symcapset is the present capabilities group under investigation. Return 0 + * if the bestcapset should remain in affect, or 1 if the symcapset is better. + */ +inline static int +is_sym_the_best(Syscapset *bestcapset, Syscapset *symcapset) +{ + /* + * Check any platform capability. If the new symbol isn't associated + * with a CA_SUNW_PLAT capability, and the best symbol is, then retain + * the best capabilities group. If the new symbol is associated with a + * CA_SUNW_PLAT capability, and the best symbol isn't, then the new + * symbol needs to be taken. + */ + if (bestcapset->sc_plat && (symcapset->sc_plat == NULL)) + return (0); + + if ((bestcapset->sc_plat == NULL) && symcapset->sc_plat) + return (1); + + /* + * Check any machine name capability. If the new symbol isn't + * associated with a CA_SUNW_MACH capability, and the best symbol is, + * then retain the best capabilities group. If the new symbol is + * associated with a CA_SUNW_MACH capability, and the best symbol isn't, + * then the new symbol needs to be taken. + */ + if (bestcapset->sc_mach && (symcapset->sc_mach == NULL)) + return (0); + + if ((bestcapset->sc_mach == NULL) && symcapset->sc_mach) + return (1); + + /* + * Check the hardware capabilities. If the best symbols CA_SUNW_HW_2 + * capabilities are greater than the new symbols capabilities, then + * retain the best capabilities group. If the new symbols CA_SUNW_HW_2 + * capabilities are greater than the best symbol, then the new symbol + * needs to be taken. + */ + if (bestcapset->sc_hw_2 > symcapset->sc_hw_2) + return (0); + + if (bestcapset->sc_hw_2 < symcapset->sc_hw_2) + return (1); + + /* + * Check the remaining hardware capabilities. If the best symbols + * CA_SUNW_HW_1 capabilities are greater than the new symbols + * capabilities, then retain the best capabilities group. If the new + * symbols CA_SUNW_HW_1 capabilities are greater than the best symbol, + * then the new symbol needs to be taken. + */ + if (bestcapset->sc_hw_1 > symcapset->sc_hw_1) + return (0); + + if (bestcapset->sc_hw_1 < symcapset->sc_hw_1) + return (1); + + /* + * Both capabilities are the same. Retain the best on a first-come + * first-served basis. + */ + return (0); +} + +/* + * Initiate symbol capabilities processing. If an initial symbol lookup + * results in binding to a symbol that has an associated SUNW_capinfo entry, + * we arrive here. + * + * The standard model is that this initial symbol is the lead capabilities + * symbol (defined as CAPINFO_SUNW_GLOB) of a capabilities family. This lead + * symbol's SUNW_capinfo information points to the SUNW_capchain entry that + * provides the family symbol indexes. We traverse this chain, looking at + * each family member, to discover the best capabilities instance. This + * instance name and symbol information is returned to establish the final + * symbol binding. + * + * If the symbol that got us here is not CAPINFO_SUNW_GLOB, then we've bound + * directly to a capabilities symbol which must be verified. This is not the + * model created by ld(1) using -z symbolcap, but might be created directly + * within a relocatable object by the compilation system. + */ +int +cap_match(Sresult *srp, uint_t symndx, Sym *symtabptr, char *strtabptr) +{ + Rt_map *ilmp = srp->sr_dmap; + Sym *bsym = NULL; + const char *bname; + Syscapset bestcapset = { 0 }; + Cap *cap; + Capchain *capchain; + uchar_t grpndx; + uint_t ochainndx, nchainndx, bndx; + + cap = CAP(ilmp); + capchain = CAPCHAIN(ilmp); + + grpndx = (uchar_t)ELF_C_GROUP(CAPINFO(ilmp)[symndx]); + + /* + * If this symbols capability group is not a lead symbol, then simply + * verify the symbol. + */ + if (grpndx != CAPINFO_SUNW_GLOB) { + Syscapset symcapset = { 0 }; + + return (sym_cap_check(cap, grpndx, &symcapset, ilmp, + srp->sr_name, symndx)); + } + + /* + * If there is no capabilities chain, return the lead symbol. + */ + if (capchain == NULL) + return (1); + + ochainndx = (uint_t)ELF_C_SYM(CAPINFO(ilmp)[symndx]); + + /* + * If there is only one member for this family, take it. Once a family + * has been processed, the best family instance is written to the head + * of the chain followed by a null entry. This caching ensures that the + * same family comparison doesn't have to be undertaken more than once. + */ + if (capchain[ochainndx] && (capchain[ochainndx + 1] == 0)) { + Sym *fsym = symtabptr + capchain[ochainndx]; + const char *fname = strtabptr + fsym->st_name; + + DBG_CALL(Dbg_syms_cap_lookup(ilmp, DBG_CAP_USED, fname, + capchain[ochainndx], M_MACH, NULL)); + + srp->sr_sym = fsym; + srp->sr_name = fname; + return (1); + } + + /* + * As this symbol is the lead symbol of a capabilities family, it is + * considered the generic member, and therefore forms the basic + * fall-back for the capabilities family. + */ + DBG_CALL(Dbg_syms_cap_lookup(ilmp, DBG_CAP_DEFAULT, srp->sr_name, + symndx, M_MACH, NULL)); + bsym = srp->sr_sym; + bname = srp->sr_name; + bndx = symndx; + + /* + * Traverse the capabilities chain analyzing each family member. + */ + for (nchainndx = ochainndx + 1, symndx = capchain[nchainndx]; symndx; + nchainndx++, symndx = capchain[nchainndx]) { + Sym *nsym = symtabptr + symndx; + const char *nname = strtabptr + nsym->st_name; + Syscapset symcapset = { 0 }; + + if ((grpndx = + (uchar_t)ELF_C_GROUP(CAPINFO(ilmp)[symndx])) == 0) + continue; + + if (sym_cap_check(cap, grpndx, &symcapset, ilmp, + nname, symndx) == 0) + continue; + + /* + * Determine whether a symbol's capabilities are more + * significant than any that have already been validated. + */ + if (is_sym_the_best(&bestcapset, &symcapset)) { + bestcapset = symcapset; + bsym = nsym; + bname = nname; + bndx = symndx; + } + } + + DBG_CALL(Dbg_syms_cap_lookup(ilmp, DBG_CAP_USED, bname, bndx, + M_MACH, NULL)); + + /* + * Having found the best symbol, cache the results by overriding the + * first element of the associated chain. + */ + capchain[ochainndx] = bndx; + capchain[ochainndx + 1] = 0; + + /* + * Update the symbol result information for return to the user. + */ + srp->sr_sym = bsym; + srp->sr_name = bname; + return (1); +}
--- a/usr/src/cmd/sgs/rtld/common/config_elf.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/common/config_elf.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -230,7 +230,7 @@ * Expand any configuration string. */ if ((tkns = expand(&estr, &size, 0, 0, - (PD_TKN_ISALIST | PD_TKN_HWCAP), lmp)) == 0) + (PD_TKN_ISALIST | PD_TKN_CAP), lmp)) == 0) return (0); /* @@ -332,7 +332,7 @@ } #endif if (expand_paths(lmp, str, &elf_def_dirs, AL_CNT_SEARCH, - (LA_SER_DEFAULT | LA_SER_CONFIG), PD_TKN_HWCAP) != NULL) + (LA_SER_DEFAULT | LA_SER_CONFIG), PD_TKN_CAP) != NULL) features |= CONF_EDLIBPATH; } if (head->ch_eslibpath) { @@ -350,20 +350,20 @@ } #endif if (expand_paths(lmp, str, &elf_sec_dirs, AL_CNT_SEARCH, - (LA_SER_SECURE | LA_SER_CONFIG), PD_TKN_HWCAP) != NULL) + (LA_SER_SECURE | LA_SER_CONFIG), PD_TKN_CAP) != NULL) features |= CONF_ESLIBPATH; } #if defined(__sparc) && !defined(_ELF64) if (head->ch_adlibpath) { str = (const char *)(head->ch_adlibpath + addr); if (expand_paths(lmp, str, &aout_def_dirs, AL_CNT_SEARCH, - (LA_SER_DEFAULT | LA_SER_CONFIG), PD_TKN_HWCAP) != NULL) + (LA_SER_DEFAULT | LA_SER_CONFIG), PD_TKN_CAP) != NULL) features |= CONF_ADLIBPATH; } if (head->ch_aslibpath) { str = (const char *)(head->ch_aslibpath + addr); if (expand_paths(lmp, str, &aout_sec_dirs, AL_CNT_SEARCH, - (LA_SER_SECURE | LA_SER_CONFIG), PD_TKN_HWCAP) != NULL) + (LA_SER_SECURE | LA_SER_CONFIG), PD_TKN_CAP) != NULL) features |= CONF_ASLIBPATH; } #endif
--- a/usr/src/cmd/sgs/rtld/common/dlfcns.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/common/dlfcns.c Mon Mar 01 10:20:48 2010 -0800 @@ -1035,17 +1035,16 @@ /* * Handle processing for dlsym. */ -Sym * -dlsym_handle(Grp_hdl *ghp, Slookup *slp, Rt_map **_lmp, uint_t *binfo, +int +dlsym_handle(Grp_hdl *ghp, Slookup *slp, Sresult *srp, uint_t *binfo, int *in_nfavl) { Rt_map *nlmp, * lmp = ghp->gh_ownlmp; Rt_map *clmp = slp->sl_cmap; const char *name = slp->sl_name; - Sym *sym = NULL; Slookup sl = *slp; - sl.sl_flags = (LKUP_FIRST | LKUP_SPEC); + sl.sl_flags = (LKUP_FIRST | LKUP_DLSYM | LKUP_SPEC); /* * Continue processing a dlsym request. Lookup the required symbol in @@ -1077,7 +1076,7 @@ * first object check whether we're done. */ if ((nlmp != lmp) && (ghp->gh_flags & GPH_FIRST)) - return (NULL); + return (0); if (!(MODE(nlmp) & RTLD_GLOBAL)) continue; @@ -1086,9 +1085,8 @@ continue; sl.sl_imap = nlmp; - if (sym = LM_LOOKUP_SYM(clmp)(&sl, _lmp, binfo, - in_nfavl)) - return (sym); + if (LM_LOOKUP_SYM(clmp)(&sl, srp, binfo, in_nfavl)) + return (1); /* * Keep track of any global pending lazy loads. @@ -1118,9 +1116,9 @@ continue; sl.sl_imap = nlmp; - if (sym = elf_lazy_find_sym(&sl, _lmp, binfo, + if (elf_lazy_find_sym(&sl, srp, binfo, in_nfavl)) - return (sym); + return (1); } } } else { @@ -1139,12 +1137,11 @@ continue; sl.sl_imap = nlmp; - if (sym = LM_LOOKUP_SYM(clmp)(&sl, _lmp, binfo, - in_nfavl)) - return (sym); + if (LM_LOOKUP_SYM(clmp)(&sl, srp, binfo, in_nfavl)) + return (1); if (ghp->gh_flags & GPH_FIRST) - return (NULL); + return (0); /* * Keep track of any pending lazy loads associated @@ -1169,25 +1166,27 @@ continue; sl.sl_imap = nlmp; - if (sym = elf_lazy_find_sym(&sl, _lmp, - binfo, in_nfavl)) - return (sym); + if (elf_lazy_find_sym(&sl, srp, binfo, + in_nfavl)) + return (1); } } } - return (NULL); + return (0); } /* * Core dlsym activity. Selects symbol lookup method from handle. */ -void * +static void * dlsym_core(void *handle, const char *name, Rt_map *clmp, Rt_map **dlmp, int *in_nfavl) { Sym *sym = NULL; + int ret = 0; Syminfo *sip; Slookup sl; + Sresult sr; uint_t binfo; /* @@ -1207,14 +1206,18 @@ */ SLOOKUP_INIT(sl, name, clmp, clmp, ld_entry_cnt, elf_hash(name), 0, 0, 0, LKUP_SYMNDX); + SRESULT_INIT(sr, name); - if (THIS_IS_ELF(clmp) && - ((sym = SYMINTP(clmp)(&sl, 0, 0, NULL)) != NULL)) { + if (THIS_IS_ELF(clmp) && SYMINTP(clmp)(&sl, &sr, &binfo, NULL)) { + sym = sr.sr_sym; + sl.sl_rsymndx = (((ulong_t)sym - (ulong_t)SYMTAB(clmp)) / SYMENT(clmp)); sl.sl_rsym = sym; } + SRESULT_INIT(sr, name); + if (sym && (ELF_ST_VISIBILITY(sym->st_other) == STV_SINGLETON)) { Rt_map *hlmp = LIST(clmp)->lm_head; @@ -1230,7 +1233,7 @@ sl.sl_flags = LKUP_SPEC; if (handle == RTLD_PROBE) sl.sl_flags |= LKUP_NOFALLBACK; - sym = LM_LOOKUP_SYM(clmp)(&sl, dlmp, &binfo, in_nfavl); + ret = LM_LOOKUP_SYM(clmp)(&sl, &sr, &binfo, in_nfavl); } else if (handle == RTLD_NEXT) { Rt_map *nlmp; @@ -1277,7 +1280,7 @@ return (0); sl.sl_flags = LKUP_NEXT; - sym = LM_LOOKUP_SYM(clmp)(&sl, dlmp, &binfo, in_nfavl); + ret = LM_LOOKUP_SYM(clmp)(&sl, &sr, &binfo, in_nfavl); } else if (handle == RTLD_SELF) { /* @@ -1288,7 +1291,7 @@ sl.sl_imap = clmp; sl.sl_flags = (LKUP_SPEC | LKUP_SELF); - sym = LM_LOOKUP_SYM(clmp)(&sl, dlmp, &binfo, in_nfavl); + ret = LM_LOOKUP_SYM(clmp)(&sl, &sr, &binfo, in_nfavl); } else if (handle == RTLD_DEFAULT) { Rt_map *hlmp = LIST(clmp)->lm_head; @@ -1302,7 +1305,7 @@ sl.sl_imap = hlmp; sl.sl_flags = LKUP_SPEC; - sym = LM_LOOKUP_SYM(clmp)(&sl, dlmp, &binfo, in_nfavl); + ret = LM_LOOKUP_SYM(clmp)(&sl, &sr, &binfo, in_nfavl); } else if (handle == RTLD_PROBE) { Rt_map *hlmp = LIST(clmp)->lm_head; @@ -1321,7 +1324,7 @@ sl.sl_imap = hlmp; sl.sl_flags = (LKUP_SPEC | LKUP_NOFALLBACK); - sym = LM_LOOKUP_SYM(clmp)(&sl, dlmp, &binfo, in_nfavl); + ret = LM_LOOKUP_SYM(clmp)(&sl, &sr, &binfo, in_nfavl); } else { Grp_hdl *ghp = (Grp_hdl *)handle; @@ -1333,13 +1336,14 @@ DBG_CALL(Dbg_syms_dlsym(clmp, name, in_nfavl, NAME(ghp->gh_ownlmp), DBG_DLSYM_DEF)); - sym = LM_DLSYM(clmp)(ghp, &sl, dlmp, &binfo, in_nfavl); + ret = LM_DLSYM(clmp)(ghp, &sl, &sr, &binfo, in_nfavl); } - if (sym) { + if (ret && ((sym = sr.sr_sym) != NULL)) { Lm_list *lml = LIST(clmp); Addr addr = sym->st_value; + *dlmp = sr.sr_dmap; if (!(FLAGS(*dlmp) & FLG_RT_FIXED)) addr += ADDR(*dlmp); @@ -1350,7 +1354,7 @@ FLAGS1(*dlmp) |= FL1_RT_USED; DBG_CALL(Dbg_bind_global(clmp, 0, 0, (Xword)-1, PLT_T_NONE, - *dlmp, addr, sym->st_value, name, binfo)); + *dlmp, addr, sym->st_value, sr.sr_name, binfo)); if ((lml->lm_tflags | AFLAGS(clmp)) & LML_TFLG_AUD_SYMBIND) { uint_t sb_flags = LA_SYMB_DLSYM; @@ -1361,8 +1365,9 @@ &sb_flags); } return ((void *)addr); - } else - return (0); + } + + return (NULL); } /*
--- a/usr/src/cmd/sgs/rtld/common/elf.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/common/elf.c Mon Mar 01 10:20:48 2010 -0800 @@ -163,50 +163,62 @@ } /* - * Determine whether this object requires any hardware or software capabilities. + * Determine whether this object requires capabilities. */ -static int +inline static int elf_cap_check(Fdesc *fdp, Ehdr *ehdr, Rej_desc *rej) { Phdr *phdr; + Cap *cap = NULL; + Dyn *dyn = NULL; + char *str = NULL; + Addr base; int cnt; + /* + * If this is a shared object, the base address of the shared object is + * added to all address values defined within the object. Otherwise, if + * this is an executable, all object addresses are used as is. + */ + if (ehdr->e_type == ET_EXEC) + base = 0; + else + base = (Addr)ehdr; + /* LINTED */ phdr = (Phdr *)((char *)ehdr + ehdr->e_phoff); for (cnt = 0; cnt < ehdr->e_phnum; cnt++, phdr++) { - Cap *cptr; - - if (phdr->p_type != PT_SUNWCAP) - continue; - - /* LINTED */ - cptr = (Cap *)((char *)ehdr + phdr->p_offset); - while (cptr->c_tag != CA_SUNW_NULL) { - if (cptr->c_tag == CA_SUNW_HW_1) { - /* - * Verify the hardware capabilities. - */ - if (hwcap_check(cptr->c_un.c_val, rej) == 0) - return (0); - - /* - * Retain this hardware capabilities value for - * possible later inspection should this object - * be processed as a filtee. - */ - fdp->fd_hwcap = cptr->c_un.c_val; - } - if (cptr->c_tag == CA_SUNW_SF_1) { - /* - * Verify the software capabilities. - */ - if (sfcap_check(cptr->c_un.c_val, rej) == 0) - return (0); - } - cptr++; + if (phdr->p_type == PT_DYNAMIC) { + /* LINTED */ + dyn = (Dyn *)((uintptr_t)phdr->p_vaddr + base); + } else if (phdr->p_type == PT_SUNWCAP) { + /* LINTED */ + cap = (Cap *)((uintptr_t)phdr->p_vaddr + base); } } - return (1); + + if (cap) { + /* + * From the .dynamic section, determine the associated string + * table. Required for CA_SUNW_MACH and CA_SUNW_PLAT + * processing. + */ + while (dyn) { + if (dyn->d_tag == DT_NULL) { + break; + } else if (dyn->d_tag == DT_STRTAB) { + str = (char *)(dyn->d_un.d_ptr + base); + break; + } + dyn++; + } + } + + /* + * Establish any alternative capabilities, and validate this object + * if it defines it's own capabilities information. + */ + return (cap_check_fdesc(fdp, cap, str, rej)); } /* @@ -272,23 +284,19 @@ return (NULL); /* - * Verify any hardware/software capability requirements. Note, if this - * object is an explicitly defined shared object under inspection by - * ldd(1), and contains an incompatible hardware capabilities - * requirement, then inform the user, but continue processing. + * Verify any capability requirements. Note, if this object is a shared + * object that is explicitly defined on the ldd(1) command line, and it + * contains an incompatible capabilities requirement, then inform the + * user, but continue processing. */ if (elf_cap_check(fdp, ehdr, rej) == 0) { Rt_map *lmp = lml_main.lm_head; if ((lml_main.lm_flags & LML_FLG_TRC_LDDSTUB) && lmp && (FLAGS1(lmp) & FL1_RT_LDDSTUB) && (NEXT(lmp) == NULL)) { - const char *fmt; - - if (rej->rej_type == SGS_REJ_HWCAP_1) - fmt = MSG_INTL(MSG_LDD_GEN_HWCAP_1); - else - fmt = MSG_INTL(MSG_LDD_GEN_SFCAP_1); - (void) printf(fmt, name, rej->rej_str); + /* LINTED */ + (void) printf(MSG_INTL(ldd_warn[rej->rej_type]), name, + rej->rej_str); return (&elf_fct); } return (NULL); @@ -542,7 +550,7 @@ * * Such versions are recorded in the object for the * benefit of VERSYM entries that refer to them. This - * provides a purely diagnositic benefit. + * provides a purely diagnostic benefit. */ if (vnap->vna_flags & VER_FLG_INFO) continue; @@ -783,10 +791,10 @@ * A null symbol interpretor. Used if a filter has no associated filtees. */ /* ARGSUSED0 */ -static Sym * -elf_null_find_sym(Slookup *slp, Rt_map **dlmp, uint_t *binfo, int *in_nfavl) +static int +elf_null_find_sym(Slookup *slp, Sresult *srp, uint_t *binfo, int *in_nfavl) { - return (NULL); + return (0); } /* @@ -833,8 +841,8 @@ * * A symbol name of 0 is used to trigger filtee loading. */ -static Sym * -_elf_lookup_filtee(Slookup *slp, Rt_map **dlmp, uint_t *binfo, uint_t ndx, +static int +_elf_lookup_filtee(Slookup *slp, Sresult *srp, uint_t *binfo, uint_t ndx, int *in_nfavl) { const char *name = slp->sl_name, *filtees; @@ -883,10 +891,10 @@ */ filtees = (char *)STRTAB(ilmp) + DYN(ilmp)[ndx].d_un.d_val; if (dip->di_info == NULL) { - if (rtld_flags2 & RT_FL2_FLTCFG) + if (rtld_flags2 & RT_FL2_FLTCFG) { elf_config_flt(lml, PATHNAME(ilmp), filtees, (Alist **)&dip->di_info, AL_CNT_FILTEES); - + } if (dip->di_info == NULL) { DBG_CALL(Dbg_file_filter(lml, NAME(ilmp), filtees, 0)); if ((lml->lm_flags & @@ -898,7 +906,7 @@ if (expand_paths(ilmp, filtees, (Alist **)&dip->di_info, AL_CNT_FILTEES, 0, 0) == 0) { elf_disable_filtee(ilmp, dip); - return (NULL); + return (0); } } } @@ -934,11 +942,10 @@ mode |= RTLD_PARENT; /* - * Process any hardware capability directory. Establish a new - * link-map control list from which to analyze any newly added - * objects. + * Process any capability directory. Establish a new link-map + * control list from which to analyze any newly added objects. */ - if ((pdp->pd_info == NULL) && (pdp->pd_flags & PD_TKN_HWCAP)) { + if ((pdp->pd_info == NULL) && (pdp->pd_flags & PD_TKN_CAP)) { const char *dir = pdp->pd_pname; Aliste lmco; @@ -949,40 +956,38 @@ return (NULL); /* - * Determine the hardware capability filtees. If none - * can be found, provide suitable diagnostics. + * Determine the capability filtees. If none can be + * found, provide suitable diagnostics. */ - DBG_CALL(Dbg_cap_hw_filter(lml, dir, ilmp)); - if (hwcap_filtees((Alist **)&dip->di_info, idx, dir, + DBG_CALL(Dbg_cap_filter(lml, dir, ilmp)); + if (cap_filtees((Alist **)&dip->di_info, idx, dir, lmco, ilmp, filtees, mode, - (FLG_RT_PUBHDL | FLG_RT_HWCAP), in_nfavl) == 0) { + (FLG_RT_PUBHDL | FLG_RT_CAP), in_nfavl) == 0) { if ((lml->lm_flags & LML_FLG_TRC_ENABLE) && (dip->di_flags & FLG_DI_AUXFLTR) && (rtld_flags & RT_FL_WARNFLTR)) { (void) printf( - MSG_INTL(MSG_LDD_HWCAP_NFOUND), - dir); + MSG_INTL(MSG_LDD_CAP_NFOUND), dir); } - DBG_CALL(Dbg_cap_hw_filter(lml, dir, 0)); + DBG_CALL(Dbg_cap_filter(lml, dir, 0)); } /* - * Re-establish the originating path name descriptor, as - * the expansion of hardware capabilities filtees may - * have re-allocated the controlling Alist. Mark this + * Re-establish the originating path name descriptor, + * as the expansion of capabilities filtees may have + * re-allocated the controlling Alist. Mark this * original pathname descriptor as unused so that the * descriptor isn't revisited for processing. Any real - * hardware capabilities filtees have been added as new - * pathname descriptors following this descriptor. + * capabilities filtees have been added as new pathname + * descriptors following this descriptor. */ pdp = alist_item((Alist *)dip->di_info, idx); - pdp->pd_flags &= ~PD_TKN_HWCAP; + pdp->pd_flags &= ~PD_TKN_CAP; pdp->pd_plen = 0; /* - * Now that any hardware capability objects have been - * processed, remove any temporary link-map control - * list. + * Now that any capability objects have been processed, + * remove any temporary link-map control list. */ if (lmco != ALIST_OFF_DATA) remove_cntl(lml, lmco); @@ -1199,16 +1204,17 @@ ghp = (Grp_hdl *)pdp->pd_info; /* - * If we're just here to trigger filtee loading skip the symbol - * lookup so we'll continue looking for additional filtees. + * If name is NULL, we're here to trigger filtee loading. + * Skip the symbol lookup so that we'll continue looking for + * additional filtees. */ if (name) { Grp_desc *gdp; - Sym *sym = NULL; + int ret = 0; Aliste idx; Slookup sl = *slp; - sl.sl_flags |= LKUP_FIRST; + sl.sl_flags |= (LKUP_FIRST | LKUP_DLSYM); any++; /* @@ -1231,8 +1237,8 @@ if ((sl.sl_imap = gdp->gd_depend) == ilmp) continue; - if (((sym = SYMINTP(sl.sl_imap)(&sl, dlmp, - binfo, in_nfavl)) != NULL) || + if (((ret = SYMINTP(sl.sl_imap)(&sl, srp, binfo, + in_nfavl)) != 0) || (ghp->gh_flags & GPH_FIRST)) break; } @@ -1241,9 +1247,9 @@ * If a symbol has been found, indicate the binding * and return the symbol. */ - if (sym) { + if (ret) { *binfo |= DBG_BINFO_FILTEE; - return (sym); + return (1); } } @@ -1259,7 +1265,7 @@ * If we're just here to trigger filtee loading then we're done. */ if (name == NULL) - return (NULL); + return (0); /* * If no filtees have been found for a filter, clean up any path name @@ -1271,10 +1277,9 @@ if (any == 0) { remove_plist((Alist **)&(dip->di_info), 1); elf_disable_filtee(ilmp, dip); - return (NULL); } - return (NULL); + return (0); } /* @@ -1282,8 +1287,8 @@ * auxiliary filter allows for filtee use, but provides a fallback should a * filtee not exist (or fail to load), any errors generated as a consequence of * trying to load the filtees are typically suppressed. Setting RT_FL_SILENCERR - * suppresses errors generated by eprint(), but insures a debug diagnostic is - * produced. ldd(1) employs printf(), and here, the selection of whether to + * suppresses errors generated by eprintf(), but ensures a debug diagnostic is + * produced. ldd(1) employs printf(), and here the selection of whether to * print a diagnostic in regards to auxiliary filters is a little more complex. * * - The determination of whether to produce an ldd message, or a fatal @@ -1291,21 +1296,18 @@ * - More detailed ldd messages may also be driven off of LML_FLG_TRC_WARN, * (ldd -d/-r), LML_FLG_TRC_VERBOSE (ldd -v), LML_FLG_TRC_SEARCH (ldd -s), * and LML_FLG_TRC_UNREF/LML_FLG_TRC_UNUSED (ldd -U/-u). - * * - If the calling object is lddstub, then several classes of message are * suppressed. The user isn't trying to diagnose lddstub, this is simply * a stub executable employed to preload a user specified library against. - * * - If RT_FL_SILENCERR is in effect then any generic ldd() messages should * be suppressed. All detailed ldd messages should still be produced. */ -Sym * -elf_lookup_filtee(Slookup *slp, Rt_map **dlmp, uint_t *binfo, uint_t ndx, +int +elf_lookup_filtee(Slookup *slp, Sresult *srp, uint_t *binfo, uint_t ndx, int *in_nfavl) { - Sym *sym; Dyninfo *dip = &DYNINFO(slp->sl_imap)[ndx]; - int silent = 0; + int ret, silent = 0; /* * Make sure this entry is still acting as a filter. We may have tried @@ -1314,7 +1316,7 @@ * that are yet to be completed. */ if (dip->di_flags == 0) - return (NULL); + return (0); /* * Indicate whether an error message is required should this filtee not @@ -1326,12 +1328,12 @@ silent = 1; } - sym = _elf_lookup_filtee(slp, dlmp, binfo, ndx, in_nfavl); + ret = _elf_lookup_filtee(slp, srp, binfo, ndx, in_nfavl); if (silent) rtld_flags &= ~RT_FL_SILENCERR; - return (sym); + return (ret); } /* @@ -1364,20 +1366,17 @@ } /* - * If flag argument has LKUP_SPEC set, we treat undefined symbols of type - * function specially in the executable - if they have a value, even though - * undefined, we use that value. This allows us to associate all references - * to a function's address to a single place in the process: the plt entry - * for that function in the executable. Calls to lookup from plt binding - * routines do NOT set LKUP_SPEC in the flag. + * Look up a symbol. The callers lookup information is passed in the Slookup + * structure, and any resultant binding information is returned in the Sresult + * structure. */ -Sym * -elf_find_sym(Slookup *slp, Rt_map **dlmp, uint_t *binfo, int *in_nfavl) +int +elf_find_sym(Slookup *slp, Sresult *srp, uint_t *binfo, int *in_nfavl) { const char *name = slp->sl_name; Rt_map *ilmp = slp->sl_imap; ulong_t hash = slp->sl_hash; - uint_t ndx, htmp, buckets, *chainptr; + uint_t ndx, hashoff, buckets, *chainptr; Sym *sym, *symtabptr; char *strtabptr, *strtabname; uint_t flags1; @@ -1391,18 +1390,18 @@ DBG_CALL(Dbg_syms_lookup(ilmp, name, MSG_ORIG(MSG_STR_ELF))); if (HASH(ilmp) == NULL) - return (NULL); + return (0); buckets = HASH(ilmp)[0]; /* LINTED */ - htmp = (uint_t)hash % buckets; + hashoff = ((uint_t)hash % buckets) + 2; /* - * Get the first symbol on hash chain and initialize the string + * Get the first symbol from the hash chain and initialize the string * and symbol table pointers. */ - if ((ndx = HASH(ilmp)[htmp + 2]) == 0) - return (NULL); + if ((ndx = HASH(ilmp)[hashoff]) == 0) + return (0); chainptr = HASH(ilmp) + 2 + buckets; strtabptr = STRTAB(ilmp); @@ -1417,12 +1416,26 @@ * names don't match continue with the next hash entry. */ if ((*strtabname++ != *name) || strcmp(strtabname, &name[1])) { + hashoff = ndx + buckets + 2; if ((ndx = chainptr[ndx]) != 0) continue; - return (NULL); + return (0); } /* + * Symbols that are defined as hidden within an object usually + * have any references from within the same object bound at + * link-edit time, thus ld.so.1 is not involved. However, if + * these are capabilities symbols, then references to them must + * be resolved at runtime. A hidden symbol can only be bound + * to by the object that defines the symbol. + */ + if ((sym->st_shndx != SHN_UNDEF) && + (ELF_ST_VISIBILITY(sym->st_other) == STV_HIDDEN) && + (slp->sl_cmap != ilmp)) + return (0); + + /* * The Solaris ld does not put DT_VERSYM in the dynamic * section, but the GNU ld does. The GNU runtime linker * interprets the top bit of the 16-bit Versym value @@ -1436,28 +1449,30 @@ * it allows, but we honor the hidden bit in GNU ld * produced objects in order to interoperate with them. */ - if ((VERSYM(ilmp) != NULL) && - ((VERSYM(ilmp)[ndx] & 0x8000) != 0)) { + if (VERSYM(ilmp) && (VERSYM(ilmp)[ndx] & 0x8000)) { DBG_CALL(Dbg_syms_ignore_gnuver(ilmp, name, ndx, VERSYM(ilmp)[ndx])); - if ((ndx = chainptr[ndx]) != 0) - continue; - return (NULL); + return (0); } /* - * If we're only here to establish a symbols index, we're done. + * If we're only here to establish a symbol's index, we're done. */ - if (slp->sl_flags & LKUP_SYMNDX) - return (sym); + if (slp->sl_flags & LKUP_SYMNDX) { + srp->sr_dmap = ilmp; + srp->sr_sym = sym; + return (1); + } /* - * If we find a match and the symbol is defined, return the + * If we find a match and the symbol is defined, capture the * symbol pointer and the link map in which it was found. */ if (sym->st_shndx != SHN_UNDEF) { - *dlmp = ilmp; + srp->sr_dmap = ilmp; + srp->sr_sym = sym; *binfo |= DBG_BINFO_FOUND; + if ((FLAGS(ilmp) & FLG_RT_OBJINTPO) || ((FLAGS(ilmp) & FLG_RT_SYMINTPO) && is_sym_interposer(ilmp, sym))) @@ -1475,19 +1490,21 @@ } else if ((slp->sl_flags & LKUP_SPEC) && (FLAGS(ilmp) & FLG_RT_ISMAIN) && (sym->st_value != 0) && (ELF_ST_TYPE(sym->st_info) == STT_FUNC)) { - *dlmp = ilmp; + srp->sr_dmap = ilmp; + srp->sr_sym = sym; *binfo |= (DBG_BINFO_FOUND | DBG_BINFO_PLTADDR); + if ((FLAGS(ilmp) & FLG_RT_OBJINTPO) || ((FLAGS(ilmp) & FLG_RT_SYMINTPO) && is_sym_interposer(ilmp, sym))) *binfo |= DBG_BINFO_INTERPOSE; - return (sym); + return (1); } /* * Undefined symbol. */ - return (NULL); + return (0); } /* @@ -1512,7 +1529,7 @@ DBG_BNDREJ_SINGLE)); *binfo |= BINFO_REJSINGLE; *binfo &= ~DBG_BINFO_MSK; - return (NULL); + return (0); } /* @@ -1528,7 +1545,7 @@ DBG_BNDREJ_DIRECT)); *binfo |= BINFO_REJDIRECT; *binfo &= ~DBG_BINFO_MSK; - return (NULL); + return (0); } /* @@ -1557,14 +1574,24 @@ DBG_BNDREJ_GROUP)); *binfo |= BINFO_REJGROUP; *binfo &= ~DBG_BINFO_MSK; - return (NULL); + return (0); } /* + * If this symbol is associated with capabilities, then each of the + * capabilities instances needs to be compared against the system + * capabilities. The best instance will be chosen to satisfy this + * binding. + */ + if (CAP(ilmp) && CAPINFO(ilmp) && ELF_C_GROUP(CAPINFO(ilmp)[ndx]) && + (cap_match(srp, ndx, symtabptr, strtabptr) == 0)) + return (0); + + /* * Determine whether this object is acting as a filter. */ if (((flags1 = FLAGS1(ilmp)) & MSK_RT_FILTER) == 0) - return (sym); + return (1); /* * Determine if this object offers per-symbol filtering, and if so, @@ -1579,12 +1606,18 @@ */ if ((sip->si_flags & SYMINFO_FLG_FILTER) && (SYMSFLTRCNT(ilmp) == 0)) - return (NULL); + return (0); if ((sip->si_flags & SYMINFO_FLG_FILTER) || ((sip->si_flags & SYMINFO_FLG_AUXILIARY) && SYMAFLTRCNT(ilmp))) { - Sym *fsym; + Sresult sr; + + /* + * Initialize a local symbol result descriptor, using + * the original symbol name. + */ + SRESULT_INIT(sr, slp->sl_name); /* * This symbol has an associated filtee. Lookup the @@ -1593,11 +1626,13 @@ * filter, return an error, otherwise fall through to * catch any object filtering that may be available. */ - if ((fsym = elf_lookup_filtee(slp, dlmp, binfo, - sip->si_boundto, in_nfavl)) != NULL) - return (fsym); + if (elf_lookup_filtee(slp, &sr, binfo, sip->si_boundto, + in_nfavl)) { + *srp = sr; + return (1); + } if (sip->si_flags & SYMINFO_FLG_FILTER) - return (NULL); + return (0); } } @@ -1605,9 +1640,15 @@ * Determine if this object provides global filtering. */ if (flags1 & (FL1_RT_OBJSFLTR | FL1_RT_OBJAFLTR)) { - Sym *fsym; + if (OBJFLTRNDX(ilmp) != FLTR_DISABLED) { + Sresult sr; - if (OBJFLTRNDX(ilmp) != FLTR_DISABLED) { + /* + * Initialize a local symbol result descriptor, using + * the original symbol name. + */ + SRESULT_INIT(sr, slp->sl_name); + /* * This object has an associated filtee. Lookup the * symbol in the filtee, and if it is found return it. @@ -1615,15 +1656,17 @@ * filter, return and error, otherwise return the symbol * within the filter itself. */ - if ((fsym = elf_lookup_filtee(slp, dlmp, binfo, - OBJFLTRNDX(ilmp), in_nfavl)) != NULL) - return (fsym); + if (elf_lookup_filtee(slp, &sr, binfo, OBJFLTRNDX(ilmp), + in_nfavl)) { + *srp = sr; + return (1); + } } if (flags1 & FL1_RT_OBJSFLTR) - return (NULL); + return (0); } - return (sym); + return (1); } /* @@ -1983,7 +2026,7 @@ * Global auditing is only meaningful when * specified by the initiating object of the * process - typically the dynamic executable. - * If this is the initiaiting object, its link- + * If this is the initiating object, its link- * map will not yet have been added to the * link-map list, and consequently the link-map * list is empty. (see setup()). @@ -2064,6 +2107,22 @@ case M_DT_REGISTER: FLAGS(lmp) |= FLG_RT_REGSYMS; break; + case DT_SUNW_CAP: + CAP(lmp) = (void *)(dyn->d_un.d_ptr + base); + break; + case DT_SUNW_CAPINFO: + CAPINFO(lmp) = (void *)(dyn->d_un.d_ptr + base); + break; + case DT_SUNW_CAPCHAIN: + CAPCHAIN(lmp) = (void *)(dyn->d_un.d_ptr + + base); + break; + case DT_SUNW_CAPCHAINENT: + CAPCHAINENT(lmp) = dyn->d_un.d_val; + break; + case DT_SUNW_CAPCHAINSZ: + CAPCHAINSZ(lmp) = dyn->d_un.d_val; + break; } } @@ -2171,8 +2230,80 @@ return (NULL); } - if (cap) - cap_assign(cap, lmp); + /* + * A capabilities section should be identified by a DT_SUNW_CAP entry, + * and if non-empty object capabilities are included, a PT_SUNWCAP + * header should reference the section. Make sure CAP() is set + * regardless. + */ + if ((CAP(lmp) == NULL) && cap) + CAP(lmp) = cap; + + /* + * Make sure any capabilities information or chain can be handled. + */ + if (CAPINFO(lmp) && (CAPINFO(lmp)[0] > CAPINFO_CURRENT)) + CAPINFO(lmp) = NULL; + if (CAPCHAIN(lmp) && (CAPCHAIN(lmp)[0] > CAPCHAIN_CURRENT)) + CAPCHAIN(lmp) = NULL; + + /* + * As part of processing dependencies, a file descriptor is populated + * with capabilities information following validation. + */ + if (fdp->fd_flags & FLG_FD_ALTCHECK) { + FLAGS1(lmp) |= FL1_RT_ALTCHECK; + CAPSET(lmp) = fdp->fd_scapset; + + if (fdp->fd_flags & FLG_FD_ALTCAP) + FLAGS1(lmp) |= FL1_RT_ALTCAP; + + } else if ((cap = CAP(lmp)) != NULL) { + /* + * Processing of the a.out and ld.so.1 does not involve a file + * descriptor as exec() did all the work, so capture the + * capabilities for these cases. + */ + while (cap->c_tag != CA_SUNW_NULL) { + switch (cap->c_tag) { + case CA_SUNW_HW_1: + CAPSET(lmp).sc_hw_1 = cap->c_un.c_val; + break; + case CA_SUNW_SF_1: + CAPSET(lmp).sc_sf_1 = cap->c_un.c_val; + break; + case CA_SUNW_HW_2: + CAPSET(lmp).sc_hw_2 = cap->c_un.c_val; + break; + case CA_SUNW_PLAT: + CAPSET(lmp).sc_plat = STRTAB(lmp) + + cap->c_un.c_ptr; + break; + case CA_SUNW_MACH: + CAPSET(lmp).sc_mach = STRTAB(lmp) + + cap->c_un.c_ptr; + break; + } + cap++; + } + } + + /* + * If a capabilities chain table exists, duplicate it. The chain table + * is inspected for each initial call to a capabilities family lead + * symbol. From this chain, each family member is inspected to + * determine the 'best' family member. The chain table is then updated + * so that the best member is immediately selected for any further + * family searches. + */ + if (CAPCHAIN(lmp)) { + Capchain *capchain; + + if ((capchain = calloc(CAPCHAINSZ(lmp), 1)) == NULL) + return (NULL); + (void) memcpy(capchain, CAPCHAIN(lmp), CAPCHAINSZ(lmp)); + CAPCHAIN(lmp) = capchain; + } /* * Add the mapped object to the end of the link map list. @@ -2191,24 +2322,6 @@ } /* - * Assign hardware/software capabilities. - */ -void -cap_assign(Cap *cap, Rt_map *lmp) -{ - while (cap->c_tag != CA_SUNW_NULL) { - switch (cap->c_tag) { - case CA_SUNW_HW_1: - HWCAP(lmp) = cap->c_un.c_val; - break; - case CA_SUNW_SF_1: - SFCAP(lmp) = cap->c_un.c_val; - } - cap++; - } -} - -/* * Build full pathname of shared object from given directory name and filename. */ static char * @@ -2512,10 +2625,9 @@ * pending, this routine loads the dependencies in an attempt to locate the * symbol. */ -Sym * -elf_lazy_find_sym(Slookup *slp, Rt_map **_lmp, uint_t *binfo, int *in_nfavl) +int +elf_lazy_find_sym(Slookup *slp, Sresult *srp, uint_t *binfo, int *in_nfavl) { - Sym *sym = NULL; static APlist *alist = NULL; Aliste idx1; Rt_map *lmp1, *lmp = slp->sl_imap, *clmp = slp->sl_cmap; @@ -2571,6 +2683,7 @@ Grp_desc *gdp; Rt_map *nlmp, *llmp; Slookup sl2; + Sresult sr; Aliste idx2; if (((dip->di_flags & FLG_DI_LAZY) == 0) || @@ -2641,9 +2754,16 @@ sl1.sl_imap = NEXT_RT_MAP(llmp); sl1.sl_flags &= ~LKUP_STDRELOC; - if ((sym = lookup_sym(&sl1, _lmp, binfo, - in_nfavl)) != NULL) - return (sym); + /* + * Initialize a local symbol result descriptor, + * using the original symbol name. + */ + SRESULT_INIT(sr, slp->sl_name); + + if (lookup_sym(&sl1, &sr, binfo, in_nfavl)) { + *srp = sr; + return (1); + } } /* @@ -2661,9 +2781,18 @@ sl2.sl_imap = gdp->gd_depend; sl2.sl_flags |= LKUP_FIRST; - if ((sym = lookup_sym(&sl2, _lmp, binfo, - in_nfavl)) != NULL) - return (sym); + /* + * Initialize a local symbol result + * descriptor, using the original + * symbol name. + */ + SRESULT_INIT(sr, slp->sl_name); + + if (lookup_sym(&sl2, &sr, binfo, + in_nfavl)) { + *srp = sr; + return (1); + } } } @@ -2676,11 +2805,11 @@ continue; if (aplist_test(&alist, nlmp, AL_CNT_LAZYFIND) == NULL) - return (NULL); + return (0); } } - return (NULL); + return (0); } /*
--- a/usr/src/cmd/sgs/rtld/common/globals.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/common/globals.c Mon Mar 01 10:20:48 2010 -0800 @@ -23,7 +23,7 @@ * Copyright (c) 1988 AT&T * All Rights Reserved * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -81,10 +81,7 @@ * END: Exposed to rtld_db */ -Reglist *reglist = NULL; /* list of register symbols */ - -ulong_t hwcap = 0; /* hardware capabilities */ -ulong_t sfcap = 0; /* software capabilities */ +Reglist *reglist = NULL; /* list of register symbols */ /* * Set of integers to track how many of what type of PLT's have been bound. @@ -98,9 +95,11 @@ uint32_t pltcntfar = 0; /* - * Provide for recording not-found path names. + * AVL tree pointers. */ -avl_tree_t *nfavl = NULL; +avl_tree_t *capavl = NULL; /* capabilities files */ +avl_tree_t *nfavl = NULL; /* not-found path names */ +avl_tree_t *spavl = NULL; /* secure path names */ /* * Various other global data. @@ -119,8 +118,6 @@ APlist *hdl_alp[HDLIST_SZ+2]; /* dlopen() handle list */ size_t syspagsz = 0; /* system page size */ ulong_t at_flags = 0; /* machine specific file flags */ -char *platform = NULL; /* platform name from AT_SUN_PLATFORM */ -size_t platform_sz = 0; /* platform string length */ Uts_desc *uts = NULL; /* utsname descriptor */ Isa_desc *isa = NULL; /* isalist descriptor */ @@ -148,6 +145,30 @@ APlist *free_alp = NULL; /* defragmentation list */ /* + * Capabilities are provided by the system. However, users can define an + * alternative set of system capabilities, where they can add, subtract, or + * override the system capabilities for testing purposes. Furthermore, these + * alternative capabilities can be specified such that they only apply to + * specified files rather than to all objects. + */ +static Syscapset scapset = { 0 }; +Syscapset *org_scapset = &scapset; /* original system and */ +Syscapset *alt_scapset = &scapset; /* alternative system */ + /* capabilities */ + +const char *rpl_hwcap = NULL; /* replaceable hwcap str */ +const char *rpl_sfcap = NULL; /* replaceable sfcap str */ +const char *rpl_machcap = NULL; /* replaceable machcap str */ +const char *rpl_platcap = NULL; /* replaceable platcap str */ +const char *rpl_cap_files = NULL; /* associated files */ + +const char *prm_hwcap = NULL; /* permanent hwcap str */ +const char *prm_sfcap = NULL; /* permanent sfcap str */ +const char *prm_machcap = NULL; /* permanent machcap str */ +const char *prm_platcap = NULL; /* permanent platcap str */ +const char *prm_cap_files = NULL; /* associated files */ + +/* * Note, the debugging descriptor interposes on the default definition provided * by liblddbg. This is required as ld.so.1 must only have outstanding relative * relocations. @@ -200,8 +221,12 @@ MSG_LDD_REJ_US3, /* MSG_INTL(MSG_LDD_REJ_US3) */ MSG_LDD_REJ_STR, /* MSG_INTL(MSG_LDD_REJ_STR) */ MSG_LDD_REJ_UNKFILE, /* MSG_INTL(MSG_LDD_REJ_UNKFILE) */ + MSG_LDD_REJ_UNKCAP, /* MSG_INTL(MSG_LDD_REJ_UNKCAP) */ MSG_LDD_REJ_HWCAP_1, /* MSG_INTL(MSG_LDD_REJ_HWCAP_1) */ MSG_LDD_REJ_SFCAP_1, /* MSG_INTL(MSG_LDD_REJ_SFCAP_1) */ + MSG_LDD_REJ_MACHCAP, /* MSG_INTL(MSG_LDD_REJ_MACHCAP) */ + MSG_LDD_REJ_PLATCAP, /* MSG_INTL(MSG_LDD_REJ_PLATCAP) */ + MSG_LDD_REJ_HWCAP_2 /* MSG_INTL(MSG_LDD_REJ_HWCAP_2) */ }; const Msg @@ -218,6 +243,32 @@ MSG_ERR_REJ_US3, /* MSG_INTL(MSG_ERR_REJ_US3) */ MSG_ERR_REJ_STR, /* MSG_INTL(MSG_ERR_REJ_STR) */ MSG_ERR_REJ_UNKFILE, /* MSG_INTL(MSG_ERR_REJ_UNKFILE) */ + MSG_ERR_REJ_UNKCAP, /* MSG_INTL(MSG_ERR_REJ_UNKCAP) */ MSG_ERR_REJ_HWCAP_1, /* MSG_INTL(MSG_ERR_REJ_HWCAP_1) */ MSG_ERR_REJ_SFCAP_1, /* MSG_INTL(MSG_ERR_REJ_SFCAP_1) */ + MSG_ERR_REJ_MACHCAP, /* MSG_INTL(MSG_ERR_REJ_MACHCAP) */ + MSG_ERR_REJ_PLATCAP, /* MSG_INTL(MSG_ERR_REJ_PLATCAP) */ + MSG_ERR_REJ_HWCAP_2 /* MSG_INTL(MSG_ERR_REJ_HWCAP_2) */ }; + +const Msg +ldd_warn[] = { + MSG_STR_EMPTY, + MSG_STR_EMPTY, + MSG_STR_EMPTY, + MSG_STR_EMPTY, + MSG_STR_EMPTY, + MSG_STR_EMPTY, + MSG_STR_EMPTY, + MSG_STR_EMPTY, + MSG_STR_EMPTY, + MSG_STR_EMPTY, + MSG_STR_EMPTY, + MSG_STR_EMPTY, + MSG_LDD_WARN_UNKCAP, /* MSG_INTL(MSG_LDD_WARN_UNKCAP) */ + MSG_LDD_WARN_HWCAP_1, /* MSG_INTL(MSG_LDD_WARN_HWCAP_1) */ + MSG_LDD_WARN_SFCAP_1, /* MSG_INTL(MSG_LDD_WARN_SFCAP_1) */ + MSG_LDD_WARN_MACHCAP, /* MSG_INTL(MSG_LDD_WARN_MACHCAP) */ + MSG_LDD_WARN_PLATCAP, /* MSG_INTL(MSG_LDD_WARN_PLATCAP) */ + MSG_LDD_WARN_HWCAP_2 /* MSG_INTL(MSG_LDD_WARN_HWCAP_2) */ + };
--- a/usr/src/cmd/sgs/rtld/common/object.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/common/object.c Mon Mar 01 10:20:48 2010 -0800 @@ -197,6 +197,35 @@ } /* + * Ensure any platform or machine capability names are valid. + */ +inline static int +check_plat_names(Syscapset *scapset, Alist *caps, Rej_desc *rej) +{ + Capstr *capstr; + Aliste idx; + + for (ALIST_TRAVERSE(caps, idx, capstr)) { + if (platcap_check(scapset, capstr->cs_str, rej) == 1) + return (1); + } + return (0); +} + +inline static int +check_mach_names(Syscapset *scapset, Alist *caps, Rej_desc *rej) +{ + Capstr *capstr; + Aliste idx; + + for (ALIST_TRAVERSE(caps, idx, capstr)) { + if (machcap_check(scapset, capstr->cs_str, rej) == 1) + return (1); + } + return (0); +} + +/* * Finish relocatable object processing. Having already initially processed one * or more objects, complete the generation of a shared object image by calling * the appropriate link-edit functionality (refer to sgs/ld/common/main.c). @@ -217,7 +246,9 @@ Fdesc fd = { 0 }; Grp_hdl *ghp; Rej_desc rej = { 0 }; - elfcap_mask_t cap_value; + Syscapset *scapset; + elfcap_mask_t omsk; + Alist *oalp; DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD)); @@ -228,24 +259,28 @@ /* * At this point, all input section processing is complete. If any - * hardware or software capabilities have been established, ensure that - * they are appropriate for this platform. + * capabilities have been established, ensure that they are appropriate + * for this system. */ - cap_value = CAPMASK_VALUE(&ofl->ofl_ocapset.c_hw_1); - if (cap_value && (hwcap_check(cap_value, &rej) == 0)) { + if (pnavl_recorded(&capavl, ofl->ofl_name, NULL, NULL)) + scapset = alt_scapset; + else + scapset = org_scapset; + + if ((((omsk = ofl->ofl_ocapset.oc_hw_1.cm_val) != 0) && + (hwcap1_check(scapset, omsk, &rej) == 0)) || + (((omsk = ofl->ofl_ocapset.oc_sf_1.cm_val) != 0) && + (sfcap1_check(scapset, omsk, &rej) == 0)) || + (((omsk = ofl->ofl_ocapset.oc_hw_2.cm_val) != 0) && + (hwcap2_check(scapset, omsk, &rej) == 0)) || + (((oalp = ofl->ofl_ocapset.oc_plat.cl_val) != NULL) && + (check_plat_names(scapset, oalp, &rej) == 0)) || + (((oalp = ofl->ofl_ocapset.oc_mach.cl_val) != NULL) && + (check_mach_names(scapset, oalp, &rej) == 0))) { if ((lml_main.lm_flags & LML_FLG_TRC_LDDSTUB) && lmp && (FLAGS1(lmp) & FL1_RT_LDDSTUB) && (NEXT(lmp) == NULL)) { - (void) printf(MSG_INTL(MSG_LDD_GEN_HWCAP_1), - ofl->ofl_name, rej.rej_str); - } - return (NULL); - } - - cap_value = CAPMASK_VALUE(&ofl->ofl_ocapset.c_sf_1); - if (cap_value && (sfcap_check(cap_value, &rej) == 0)) { - if ((lml_main.lm_flags & LML_FLG_TRC_LDDSTUB) && lmp && - (FLAGS1(lmp) & FL1_RT_LDDSTUB) && (NEXT(lmp) == NULL)) { - (void) printf(MSG_INTL(MSG_LDD_GEN_SFCAP_1), + /* LINTED */ + (void) printf(MSG_INTL(ldd_reject[rej.rej_type]), ofl->ofl_name, rej.rej_str); } return (NULL);
--- a/usr/src/cmd/sgs/rtld/common/paths.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/common/paths.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -38,7 +38,6 @@ #include <limits.h> #include <fcntl.h> #include <string.h> -#include <sys/systeminfo.h> #include <debug.h> #include <conv.h> #include "_rtld.h" @@ -173,7 +172,7 @@ */ (void) expand_paths(lmp, rpl_libpath, &rpl_libdirs, AL_CNT_SEARCH, mode, - PD_TKN_HWCAP); + PD_TKN_CAP); } dalpp = &rpl_libdirs; } @@ -214,7 +213,7 @@ */ (void) expand_paths(lmp, prm_libpath, &prm_libdirs, AL_CNT_SEARCH, mode, - PD_TKN_HWCAP); + PD_TKN_CAP); } dalpp = &prm_libdirs; } @@ -251,7 +250,7 @@ */ (void) expand_paths(lmp, RPATH(lmp), &RLIST(lmp), AL_CNT_SEARCH, LA_SER_RUNPATH, - PD_TKN_HWCAP); + PD_TKN_CAP); } dalpp = &RLIST(lmp); } @@ -278,7 +277,7 @@ } /* - * Get the next directory in the search rules path. The seach path "cookie" + * Get the next directory in the search rules path. The search path "cookie" * provided by the caller (sdp) maintains the state of a search in progress. * * Typically, a search consists of a series of rules that govern the order of @@ -418,31 +417,30 @@ } else if (strncmp(optr, MSG_ORIG(MSG_TKN_PLATFORM), MSG_TKN_PLATFORM_SIZE) == 0) { + Syscapset *scapset; + + if (FLAGS1(lmp) & FL1_RT_ALTCAP) + scapset = alt_scapset; + else + scapset = org_scapset; + token = (char *)MSG_ORIG(MSG_TKN_PLATFORM); /* - * $PLATFORM expansion required. This would have been - * established from the AT_SUN_PLATFORM aux vector, but - * if not attempt to get it from sysconf(). + * $PLATFORM expansion required. */ if (((omit & PD_TKN_PLATFORM) == 0) && - ((platform == 0) && (platform_sz == 0))) { - char _info[SYS_NMLN]; - long _size; + ((scapset->sc_plat == NULL) && + (scapset->sc_platsz == 0))) + platform_name(scapset); - _size = sysinfo(SI_PLATFORM, _info, SYS_NMLN); - if ((_size != -1) && ((platform = - malloc((size_t)_size)) != NULL)) { - (void) strcpy(platform, _info); - platform_sz = (size_t)_size - 1; - } - } if (((omit & PD_TKN_PLATFORM) == 0) && - (platform != 0)) { - if ((nlen += platform_sz) < PATH_MAX) { - (void) strncpy(nptr, platform, - platform_sz); - nptr = nptr + platform_sz; + scapset->sc_plat) { + nlen += scapset->sc_platsz; + if (nlen < PATH_MAX) { + (void) strncpy(nptr, scapset->sc_plat, + scapset->sc_platsz); + nptr = nptr + scapset->sc_platsz; olen += MSG_TKN_PLATFORM_SIZE; optr += MSG_TKN_PLATFORM_SIZE; _flags |= PD_TKN_PLATFORM; @@ -454,6 +452,43 @@ } } + } else if (strncmp(optr, MSG_ORIG(MSG_TKN_MACHINE), + MSG_TKN_MACHINE_SIZE) == 0) { + Syscapset *scapset; + + if (FLAGS1(lmp) & FL1_RT_ALTCAP) + scapset = alt_scapset; + else + scapset = org_scapset; + + token = (char *)MSG_ORIG(MSG_TKN_MACHINE); + + /* + * $MACHINE expansion required. + */ + if (((omit & PD_TKN_MACHINE) == 0) && + ((scapset->sc_mach == NULL) && + (scapset->sc_machsz == 0))) + machine_name(scapset); + + if (((omit & PD_TKN_MACHINE) == 0) && + scapset->sc_mach) { + nlen += scapset->sc_machsz; + if (nlen < PATH_MAX) { + (void) strncpy(nptr, scapset->sc_mach, + scapset->sc_machsz); + nptr = nptr + scapset->sc_machsz; + olen += MSG_TKN_MACHINE_SIZE; + optr += MSG_TKN_MACHINE_SIZE; + _flags |= PD_TKN_MACHINE; + } else { + eprintf(lml, ERR_FATAL, + MSG_INTL(MSG_ERR_EXPAND1), + NAME(lmp), oname); + return (0); + } + } + } else if (strncmp(optr, MSG_ORIG(MSG_TKN_OSNAME), MSG_TKN_OSNAME_SIZE) == 0) { token = (char *)MSG_ORIG(MSG_TKN_OSNAME); @@ -581,6 +616,32 @@ } } + } else if (strncmp(optr, MSG_ORIG(MSG_TKN_CAPABILITY), + MSG_TKN_CAPABILITY_SIZE) == 0) { + char *bptr = nptr - 1; + char *eptr = optr + MSG_TKN_CAPABILITY_SIZE; + token = (char *)MSG_ORIG(MSG_TKN_CAPABILITY); + + /* + * $CAPABILITY expansion required. Expansion is only + * allowed for non-simple path names (must contain a + * '/'), with the token itself being the last element + * of the path. Therefore, all we need do is test the + * existence of the string "/$CAPABILITY\0". + */ + if (((omit & PD_TKN_CAP) == 0) && + ((bptr > _name) && (*bptr == '/') && + ((*eptr == '\0') || (*eptr == ':')))) { + /* + * Decrement the present pointer so that the + * directories trailing "/" gets nuked later. + */ + nptr--, nlen--; + olen += MSG_TKN_CAPABILITY_SIZE; + optr += MSG_TKN_CAPABILITY_SIZE; + _flags |= PD_TKN_CAP; + } + } else if (strncmp(optr, MSG_ORIG(MSG_TKN_HWCAP), MSG_TKN_HWCAP_SIZE) == 0) { char *bptr = nptr - 1; @@ -588,7 +649,8 @@ token = (char *)MSG_ORIG(MSG_TKN_HWCAP); /* - * $HWCAP expansion required. For compatibility with + * $HWCAP expansion required. This token has been + * superseeded by $CAPABILITY. For compatibility with * older environments, only expand this token when hard- * ware capability information is available. This * expansion is only allowed for non-simple path names @@ -596,7 +658,7 @@ * last element of the path. Therefore, all we need do * is test the existence of the string "/$HWCAP\0". */ - if (((omit & PD_TKN_HWCAP) == 0) && + if (((omit & PD_TKN_CAP) == 0) && (rtld_flags2 & RT_FL2_HWCAP) && ((bptr > _name) && (*bptr == '/') && ((*eptr == '\0') || (*eptr == ':')))) { @@ -607,7 +669,7 @@ nptr--, nlen--; olen += MSG_TKN_HWCAP_SIZE; optr += MSG_TKN_HWCAP_SIZE; - _flags |= PD_TKN_HWCAP; + _flags |= PD_TKN_CAP; } } else { @@ -820,7 +882,7 @@ * other dependencies, to be used. */ if ((flags & PD_TKN_ORIGIN) && - spavl_recorded(npath, 0)) { + pnavl_recorded(&spavl, npath, 0, NULL)) { DBG_CALL(Dbg_libs_insecure(lml, npath, 1)); return (1); } @@ -850,7 +912,7 @@ if ((lml->lm_flags & LML_FLG_RTLDLM) && is_rtld_setuid()) return (1); - else if (spavl_recorded(opath, 0)) { + else if (pnavl_recorded(&spavl, opath, 0, NULL)) { DBG_CALL(Dbg_libs_insecure(lml, opath, 1)); return (1); }
--- a/usr/src/cmd/sgs/rtld/common/remove.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/common/remove.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -221,7 +221,7 @@ void remove_so(Lm_list *lml, Rt_map *lmp) { - Dyninfo *dip; + Dyninfo *dip; if (lmp == NULL) return; @@ -377,6 +377,9 @@ if (FLAGS(lmp) & FLG_RT_IMGALLOC) free((void *)ADDR(lmp)); + if (CAPCHAIN(lmp)) + free((void *)CAPCHAIN(lmp)); + if (MMAPS(lmp)) { if ((FLAGS(lmp) & FLG_RT_IMGALLOC) == 0) unmap_obj(MMAPS(lmp), MMAPCNT(lmp));
--- a/usr/src/cmd/sgs/rtld/common/rtld.msg Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/common/rtld.msg Mon Mar 01 10:20:48 2010 -0800 @@ -72,9 +72,6 @@ @ MSG_GEN_ALTER "%s: alternate file in use" @ MSG_GEN_NOSYM "%s: can't find symbol" @ MSG_GEN_NODUMP "%s: DF_1_NODUMP tagged object may not be dldump()'ed" -@ MSG_GEN_BADHWCAP_1 "hardware capability unsupported: %s" -@ MSG_GEN_BADSFCAP_1 "software capability unsupported: %s" - # Move related messages @@ -151,7 +148,7 @@ @ MSG_LDD_FIL_ILLEGAL "\t%s =>\t (illegal insecure pathname)\n" @ MSG_LDD_FIL_ALTER " (alternate)" -@ MSG_LDD_HWCAP_NFOUND "\t%s =>\t (no hardware capability objects found)\n" +@ MSG_LDD_CAP_NFOUND "\t%s =>\t (no capability objects found)\n" @ MSG_LDD_SEC_NFOUND "\t%s =>\t (file not found in secure directories)\n" @@ -191,11 +188,24 @@ @ MSG_LDD_REJ_US3 " - Sun UltraSPARC III extensions required" @ MSG_LDD_REJ_STR " - %s" @ MSG_LDD_REJ_UNKFILE " - unknown file type" -@ MSG_LDD_REJ_HWCAP_1 " - hardware capability unsupported: %s" -@ MSG_LDD_REJ_SFCAP_1 " - software capability unsupported: %s" +@ MSG_LDD_REJ_UNKCAP " - unknown capability: %d" +@ MSG_LDD_REJ_HWCAP_1 " - hardware capability (CA_SUNW_HW_1) unsupported: %s" +@ MSG_LDD_REJ_SFCAP_1 " - software capability (CA_SUNW_SF_1) unsupported: %s" +@ MSG_LDD_REJ_MACHCAP " - machine capability (CA_SUNW_MACH) unsupported: %s" +@ MSG_LDD_REJ_PLATCAP " - platform capability (CA_SUNW_PLAT) unsupported: %s" +@ MSG_LDD_REJ_HWCAP_2 " - hardware capability (CA_SUNW_HW_2) unsupported: %s" -@ MSG_LDD_GEN_HWCAP_1 "%s: warning: hardware capability unsupported: %s\n" -@ MSG_LDD_GEN_SFCAP_1 "%s: warning: hardware capability unsupported: %s\n" +@ MSG_LDD_WARN_UNKCAP "%s: unknown capability: %d" +@ MSG_LDD_WARN_HWCAP_1 "%s: warning: hardware capability (CA_SUNW_HW_1) \ + unsupported: %s\n" +@ MSG_LDD_WARN_SFCAP_1 "%s: warning: software capability (CA_SUNW_SF_1) \ + unsupported: %s\n" +@ MSG_LDD_WARN_MACHCAP "%s: warning: machine capability (CA_SUNW_MACH) \ + unsupported: %s\n" +@ MSG_LDD_WARN_PLATCAP "%s: warning: platform capability (CA_SUNW_PLAT) \ + unsupported: %s\n" +@ MSG_LDD_WARN_HWCAP_2 "%s: warning: hardware capability (CA_SUNW_HW_2) \ + unsupported: %s\n" # Error rejection messages. @@ -210,8 +220,12 @@ @ MSG_ERR_REJ_US3 "%s: Sun UltraSPARC III extensions required" @ MSG_ERR_REJ_STR "%s: %s" @ MSG_ERR_REJ_UNKFILE "%s: unknown file type" -@ MSG_ERR_REJ_HWCAP_1 "%s: hardware capability unsupported: %s" -@ MSG_ERR_REJ_SFCAP_1 "%s: software capability unsupported: %s" +@ MSG_ERR_REJ_UNKCAP "%s: unknown capability: %d" +@ MSG_ERR_REJ_HWCAP_1 "%s: hardware capability (CA_SUNW_HW_1) unsupported: %s" +@ MSG_ERR_REJ_SFCAP_1 "%s: software capability (CA_SUNW_SF_1) unsupported: %s" +@ MSG_ERR_REJ_MACHCAP "%s: machine capability (CA_SUNW_MACH) unsupported: %s" +@ MSG_ERR_REJ_PLATCAP "%s: platform capability (CA_SUNW_PLAT) unsupported: %s" +@ MSG_ERR_REJ_HWCAP_2 "%s: hardware capability (CA_SUNW_HW_2) unsupported: %s" # Error TLS failures @@ -253,6 +267,10 @@ @ _END_ +# The following strings represent reserved words, files, pathnames and symbols. +# Reference to this strings is via the MSG_ORIG() macro, and thus no message +# translation is required. + @ MSG_LDD_FIL_PATH "\t%s%s%s\n" @ MSG_LDD_FIL_EQUIV "\t%s =>\t %s%s%s\n" @ MSG_LDD_FMT_PATH1 "%s" @@ -260,11 +278,6 @@ @ MSG_LDD_INIT_FMT_FILE "\t%s\n" @ MSG_LDD_VER_FOUND "\t%s (%s) =>\t %s\n" - -# The following strings represent reserved words, files, pathnames and symbols. -# Reference to this strings is via the MSG_ORIG() macro, and thus no message -# translation is required. - @ MSG_STR_EMPTY "" @ MSG_STR_NEGATE "-" @ MSG_STR_ZERO "0" @@ -277,9 +290,13 @@ @ MSG_STR_SLASH "/" @ MSG_STR_DELIMIT ": " +@ MSG_CAP_DELIMIT "," + @ MSG_SUNW_OST_SGS "SUNW_OST_SGS" @ MSG_SUNW_OST_OSLIB "SUNW_OST_OSLIB" +@ MSG_TKN_CAPABILITY "CAPABILITY" +@ MSG_TKN_MACHINE "MACHINE" @ MSG_TKN_PLATFORM "PLATFORM" @ MSG_TKN_ORIGIN "ORIGIN" @ MSG_TKN_ISALIST "ISALIST" @@ -335,15 +352,18 @@ @ MSG_LD_BIND_NOT "BIND_NOT" @ MSG_LD_BINDINGS "BINDINGS" @ MSG_LD_CONFGEN "CONFGEN" +@ MSG_LD_CAP_FILES "CAP_FILES" @ MSG_LD_CONFIG "CONFIG" @ MSG_LD_DEBUG "DEBUG" @ MSG_LD_DEBUG_OUTPUT "DEBUG_OUTPUT" @ MSG_LD_DEMANGLE "DEMANGLE" @ MSG_LD_FLAGS "FLAGS" +@ MSG_LD_HWCAP "HWCAP" @ MSG_LD_INIT "INIT" @ MSG_LD_LIBPATH "LIBRARY_PATH" @ MSG_LD_LOADAVAIL "LOADAVAIL" @ MSG_LD_LOADFLTR "LOADFLTR" +@ MSG_LD_MACHCAP "MACHCAP" @ MSG_LD_NOAUDIT "NOAUDIT" @ MSG_LD_NOAUXFLTR "NOAUXFLTR" @ MSG_LD_NOBAPLT "NOBAPLT" @@ -357,9 +377,11 @@ @ MSG_LD_NOPAREXT "NOPAREXT" @ MSG_LD_NOUNRESWEAK "NOUNRESWEAK" @ MSG_LD_NOVERSION "NOVERSION" +@ MSG_LD_PLATCAP "PLATCAP" @ MSG_LD_PRELOAD "PRELOAD" @ MSG_LD_PROFILE "PROFILE" @ MSG_LD_PROFILE_OUTPUT "PROFILE_OUTPUT" +@ MSG_LD_SFCAP "SFCAP" @ MSG_LD_SIGNAL "SIGNAL" @ MSG_LD_TRACE_OBJS "TRACE_LOADED_OBJECTS" @ MSG_LD_TRACE_OBJS_E "TRACE_LOADED_OBJECTS_E"
--- a/usr/src/cmd/sgs/rtld/common/setup.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/common/setup.c Mon Mar 01 10:20:48 2010 -0800 @@ -42,7 +42,6 @@ #include <sys/stat.h> #include <sys/mman.h> #include <string.h> -#include <stdio.h> #include <unistd.h> #include <dlfcn.h> #include <sys/sysconfig.h> @@ -291,7 +290,14 @@ * Initialize any global variables. */ at_flags = _flags; - platform = _platform; + + if ((org_scapset->sc_plat = _platform) != NULL) + org_scapset->sc_platsz = strlen(_platform); + + if (org_scapset->sc_plat == NULL) + platform_name(org_scapset); + if (org_scapset->sc_mach == NULL) + machine_name(org_scapset); /* * If pagesize is unspecified find its value. @@ -338,15 +344,6 @@ security(uid, euid, gid, egid, auxflags); /* - * Initialize a hardware capability descriptor for use in comparing - * each loaded object. - */ - if (auxflags & AF_SUN_HWCAPVERIFY) { - rtld_flags2 |= RT_FL2_HWCAP; - hwcap = (ulong_t)hwcap_1; - } - - /* * Look for environment strings (allows things like LD_NOAUDIT to be * established, although debugging isn't enabled until later). */ @@ -355,6 +352,19 @@ return (0); /* + * Initialize a hardware capability descriptor for use in comparing + * each loaded object. The aux vector must provide AF_SUN_HWCAPVERIFY, + * as prior to this setting any hardware capabilities that were found + * could not be relied upon. Set any alternative system capabilities. + */ + if (auxflags & AF_SUN_HWCAPVERIFY) { + rtld_flags2 |= RT_FL2_HWCAP; + org_scapset->sc_hw_1 = (Xword)hwcap_1; + } + if (cap_alternative() == 0) + return (0); + + /* * Create a mapping descriptor for ld.so.1. We can determine our * two segments information from known symbols. */ @@ -676,7 +686,7 @@ size_t len = strlen(interp->i_name); if (expand(&interp->i_name, &len, 0, 0, - (PD_TKN_ISALIST | PD_TKN_HWCAP), rlmp) & PD_TKN_RESOLVED) + (PD_TKN_ISALIST | PD_TKN_CAP), rlmp) & PD_TKN_RESOLVED) fdr.fd_flags |= FLG_FD_RESOLVED; } fdr.fd_pname = interp->i_name; @@ -721,36 +731,23 @@ * that are restricted to a 32-bit address space can only be loaded if * the executable has established this requirement. */ - if (SFCAP(mlmp) & SF1_SUNW_ADDR32) + if (CAPSET(mlmp).sc_sf_1 & SF1_SUNW_ADDR32) rtld_flags2 |= RT_FL2_ADDR32; #endif /* - * Validate any hardware capabilities information. + * Establish any alternative capabilities, and validate this object + * if it defines it's own capabilities information. */ - if (HWCAP(mlmp) && (hwcap_check(HWCAP(mlmp), &rej) == 0)) { + if (cap_check_lmp(mlmp, &rej) == 0) { if (lml_main.lm_flags & LML_FLG_TRC_ENABLE) { - (void) printf(MSG_INTL(MSG_LDD_GEN_HWCAP_1), + /* LINTED */ + (void) printf(MSG_INTL(ldd_warn[rej.rej_type]), NAME(mlmp), rej.rej_str); } else { + /* LINTED */ eprintf(&lml_main, ERR_FATAL, - MSG_INTL(MSG_GEN_BADHWCAP_1), rej.rej_str); - return (0); - } - } - - /* - * Validate any software capabilities information, other than - * SF1_SUNW_ADDR32. Only dependencies need check their SF1_SUNW_ADDR32 - * use against the application enabling a 32-bit address space. - */ - if ((SFCAP(mlmp) & ~SF1_SUNW_ADDR32) && - (sfcap_check(SFCAP(mlmp), &rej) == 0)) { - if (lml_main.lm_flags & LML_FLG_TRC_ENABLE) { - (void) printf(MSG_INTL(MSG_LDD_GEN_SFCAP_1), + MSG_INTL(err_reject[rej.rej_type]), NAME(mlmp), rej.rej_str); - } else { - eprintf(&lml_main, ERR_FATAL, - MSG_INTL(MSG_GEN_BADSFCAP_1), rej.rej_str); return (0); } } @@ -813,9 +810,6 @@ r_debug.rtd_rdebug.r_ldbase = r_debug.rtd_rdebug.r_ldsomap->l_addr; r_debug.rtd_dynlmlst = &dynlm_list; - if (platform) - platform_sz = strlen(platform); - /* * Determine the dev/inode information for the executable to complete * load_so() checking for those who might dlopen(a.out). @@ -831,6 +825,9 @@ if (!(rtld_flags & RT_FL_NOCFG)) { if ((features = elf_config(mlmp, (aoutdyn != 0))) == -1) return (0); + + if (cap_alternative() == 0) + return (0); } /* @@ -900,13 +897,12 @@ * Now that debugging is enabled generate any diagnostics from any * previous events. */ - if (hwcap) - DBG_CALL(Dbg_cap_val_hw1(&lml_main, hwcap, M_MACH)); - if (features) + if (DBG_ENABLED) { + DBG_CALL(Dbg_cap_val(&lml_main, org_scapset, alt_scapset, + M_MACH)); DBG_CALL(Dbg_file_config_dis(&lml_main, config->c_name, features)); - if (DBG_ENABLED) { DBG_CALL(Dbg_file_ldso(rlmp, envp, auxv, LIST(rlmp)->lm_lmidstr, ALIST_OFF_DATA)); @@ -1137,14 +1133,14 @@ * Without this flag we only support one copy of the linker in a * process because by default the linker will always try to * initialize at one primary link map The copy of libc which is - * initialized on a primary link map will initalize global TLS + * initialized on a primary link map will initialize global TLS * data which can be shared with other copies of libc in the * process. The problem is that if there is more than one copy * of the linker, only one copy should link libc onto a primary * link map, otherwise libc will attempt to re-initialize global * TLS data. So when a copy of the linker is loaded with this * flag set, it will not initialize any primary link maps since - * persumably another copy of the linker will do this. + * presumably another copy of the linker will do this. * * Note that this flag only allows multiple copies of the -same- * -version- of the linker (and libc) to coexist. This approach
--- a/usr/src/cmd/sgs/rtld/common/util.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/common/util.c Mon Mar 01 10:20:48 2010 -0800 @@ -33,6 +33,7 @@ * Utility routines for run-time linker. some are duplicated here from libc * (with different names) to avoid name space collisions. */ +#include <sys/systeminfo.h> #include <stdio.h> #include <sys/time.h> #include <sys/types.h> @@ -382,6 +383,32 @@ } /* + * Determine whether a PathNode is recorded. + */ +int +pnavl_recorded(avl_tree_t **pnavl, const char *name, uint_t hash, + avl_index_t *where) +{ + PathNode pn; + + /* + * Create the avl tree if required. + */ + if ((*pnavl == NULL) && + ((*pnavl = pnavl_create(sizeof (PathNode))) == NULL)) + return (0); + + pn.pn_name = name; + if ((pn.pn_hash = hash) == 0) + pn.pn_hash = sgs_str_hash(name); + + if (avl_find(*pnavl, &pn, where) == NULL) + return (0); + + return (1); +} + +/* * Determine if a pathname has already been recorded on the full path name * AVL tree. This tree maintains a node for each path name that ld.so.1 has * successfully loaded. If the path name does not exist in this AVL tree, then @@ -473,38 +500,14 @@ } /* - * Determine if a pathname has already been recorded on the not-found AVL tree. + * Insert a path name into the not-found AVL tree. + * * This tree maintains a node for each path name that ld.so.1 has explicitly * inspected, but has failed to load during a single ld.so.1 operation. If the * path name does not exist in this AVL tree, then the next insertion point is * deposited in "where". This value can be used by nfavl_insert() to expedite * the insertion. */ -int -nfavl_recorded(const char *name, uint_t hash, avl_index_t *where) -{ - PathNode pn; - - /* - * Create the avl tree if required. - */ - if ((nfavl == NULL) && - ((nfavl = pnavl_create(sizeof (PathNode))) == NULL)) - return (NULL); - - pn.pn_name = name; - if ((pn.pn_hash = hash) == 0) - pn.pn_hash = sgs_str_hash(name); - - if (avl_find(nfavl, &pn, where) == NULL) - return (0); - - return (1); -} - -/* - * Insert a name into the not-found AVL tree. - */ void nfavl_insert(const char *name, avl_index_t where) { @@ -513,7 +516,7 @@ if (where == 0) { /* LINTED */ - int in_nfavl = nfavl_recorded(name, hash, &where); + int in_nfavl = pnavl_recorded(&nfavl, name, hash, &where); /* * We better not get a hit now, we do not want duplicates in @@ -532,39 +535,14 @@ } } -static avl_tree_t *spavl = NULL; - /* - * Search for a path name within the secure path AVL tree. This tree is used - * to maintain a list of directories in which the dependencies of a secure - * process have been found. This list provides a fall-back in the case that a - * $ORIGIN expansion is deemed insecure, when the expansion results in a path - * name that has already provided dependencies. - */ -int -spavl_recorded(const char *name, avl_index_t *where) -{ - PathNode pn; - - /* - * Create the avl tree if required. - */ - if ((spavl == NULL) && - ((spavl = pnavl_create(sizeof (PathNode))) == NULL)) - return (0); - - pn.pn_name = name; - pn.pn_hash = sgs_str_hash(name); - - if (avl_find(spavl, &pn, where) == NULL) - return (0); - - return (1); -} - -/* - * Insert the directory name, of a full path name, into the secure path AVL + * Insert the directory name, of a full path name, into the secure path AVL * tree. + * + * This tree is used to maintain a list of directories in which the dependencies + * of a secure process have been found. This list provides a fall-back in the + * case that a $ORIGIN expansion is deemed insecure, when the expansion results + * in a path name that has already provided dependencies. */ void spavl_insert(const char *name) @@ -573,6 +551,7 @@ size_t size; avl_index_t where; PathNode *pnp; + uint_t hash; /* * Separate the directory name from the path name. @@ -584,12 +563,13 @@ (void) strncpy(buffer, name, size); buffer[size] = '\0'; + hash = sgs_str_hash(buffer); /* * Determine whether this directory name is already recorded, or if * not, 'where" will provide the insertion point for the new string. */ - if (spavl_recorded(buffer, &where)) + if (pnavl_recorded(&spavl, buffer, hash, &where)) return; /* @@ -597,7 +577,7 @@ */ if ((pnp = calloc(sizeof (PathNode), 1)) != NULL) { pnp->pn_name = strdup(buffer); - pnp->pn_hash = sgs_str_hash(buffer); + pnp->pn_hash = hash; avl_insert(spavl, pnp, where); } } @@ -1444,46 +1424,50 @@ /* * Identify all environment variables. */ -#define ENV_FLG_AUDIT 0x0000000001ULL -#define ENV_FLG_AUDIT_ARGS 0x0000000002ULL -#define ENV_FLG_BIND_NOW 0x0000000004ULL -#define ENV_FLG_BIND_NOT 0x0000000008ULL -#define ENV_FLG_BINDINGS 0x0000000010ULL - -#define ENV_FLG_CONFGEN 0x0000000040ULL -#define ENV_FLG_CONFIG 0x0000000080ULL -#define ENV_FLG_DEBUG 0x0000000100ULL -#define ENV_FLG_DEBUG_OUTPUT 0x0000000200ULL -#define ENV_FLG_DEMANGLE 0x0000000400ULL -#define ENV_FLG_FLAGS 0x0000000800ULL -#define ENV_FLG_INIT 0x0000001000ULL -#define ENV_FLG_LIBPATH 0x0000002000ULL -#define ENV_FLG_LOADAVAIL 0x0000004000ULL -#define ENV_FLG_LOADFLTR 0x0000008000ULL -#define ENV_FLG_NOAUDIT 0x0000010000ULL -#define ENV_FLG_NOAUXFLTR 0x0000020000ULL -#define ENV_FLG_NOBAPLT 0x0000040000ULL -#define ENV_FLG_NOCONFIG 0x0000080000ULL -#define ENV_FLG_NODIRCONFIG 0x0000100000ULL -#define ENV_FLG_NODIRECT 0x0000200000ULL -#define ENV_FLG_NOENVCONFIG 0x0000400000ULL -#define ENV_FLG_NOLAZY 0x0000800000ULL -#define ENV_FLG_NOOBJALTER 0x0001000000ULL -#define ENV_FLG_NOVERSION 0x0002000000ULL -#define ENV_FLG_PRELOAD 0x0004000000ULL -#define ENV_FLG_PROFILE 0x0008000000ULL -#define ENV_FLG_PROFILE_OUTPUT 0x0010000000ULL -#define ENV_FLG_SIGNAL 0x0020000000ULL -#define ENV_FLG_TRACE_OBJS 0x0040000000ULL -#define ENV_FLG_TRACE_PTHS 0x0080000000ULL -#define ENV_FLG_UNREF 0x0100000000ULL -#define ENV_FLG_UNUSED 0x0200000000ULL -#define ENV_FLG_VERBOSE 0x0400000000ULL -#define ENV_FLG_WARN 0x0800000000ULL -#define ENV_FLG_NOFLTCONFIG 0x1000000000ULL -#define ENV_FLG_BIND_LAZY 0x2000000000ULL -#define ENV_FLG_NOUNRESWEAK 0x4000000000ULL -#define ENV_FLG_NOPAREXT 0x8000000000ULL +#define ENV_FLG_AUDIT 0x0000000000001ULL +#define ENV_FLG_AUDIT_ARGS 0x0000000000002ULL +#define ENV_FLG_BIND_NOW 0x0000000000004ULL +#define ENV_FLG_BIND_NOT 0x0000000000008ULL +#define ENV_FLG_BINDINGS 0x0000000000010ULL +#define ENV_FLG_CONFGEN 0x0000000000020ULL +#define ENV_FLG_CONFIG 0x0000000000040ULL +#define ENV_FLG_DEBUG 0x0000000000080ULL +#define ENV_FLG_DEBUG_OUTPUT 0x0000000000100ULL +#define ENV_FLG_DEMANGLE 0x0000000000200ULL +#define ENV_FLG_FLAGS 0x0000000000400ULL +#define ENV_FLG_INIT 0x0000000000800ULL +#define ENV_FLG_LIBPATH 0x0000000001000ULL +#define ENV_FLG_LOADAVAIL 0x0000000002000ULL +#define ENV_FLG_LOADFLTR 0x0000000004000ULL +#define ENV_FLG_NOAUDIT 0x0000000008000ULL +#define ENV_FLG_NOAUXFLTR 0x0000000010000ULL +#define ENV_FLG_NOBAPLT 0x0000000020000ULL +#define ENV_FLG_NOCONFIG 0x0000000040000ULL +#define ENV_FLG_NODIRCONFIG 0x0000000080000ULL +#define ENV_FLG_NODIRECT 0x0000000100000ULL +#define ENV_FLG_NOENVCONFIG 0x0000000200000ULL +#define ENV_FLG_NOLAZY 0x0000000400000ULL +#define ENV_FLG_NOOBJALTER 0x0000000800000ULL +#define ENV_FLG_NOVERSION 0x0000001000000ULL +#define ENV_FLG_PRELOAD 0x0000002000000ULL +#define ENV_FLG_PROFILE 0x0000004000000ULL +#define ENV_FLG_PROFILE_OUTPUT 0x0000008000000ULL +#define ENV_FLG_SIGNAL 0x0000010000000ULL +#define ENV_FLG_TRACE_OBJS 0x0000020000000ULL +#define ENV_FLG_TRACE_PTHS 0x0000040000000ULL +#define ENV_FLG_UNREF 0x0000080000000ULL +#define ENV_FLG_UNUSED 0x0000100000000ULL +#define ENV_FLG_VERBOSE 0x0000200000000ULL +#define ENV_FLG_WARN 0x0000400000000ULL +#define ENV_FLG_NOFLTCONFIG 0x0000800000000ULL +#define ENV_FLG_BIND_LAZY 0x0001000000000ULL +#define ENV_FLG_NOUNRESWEAK 0x0002000000000ULL +#define ENV_FLG_NOPAREXT 0x0004000000000ULL +#define ENV_FLG_HWCAP 0x0008000000000ULL +#define ENV_FLG_SFCAP 0x0010000000000ULL +#define ENV_FLG_MACHCAP 0x0020000000000ULL +#define ENV_FLG_PLATCAP 0x0040000000000ULL +#define ENV_FLG_CAP_FILES 0x0080000000000ULL #define SEL_REPLACE 0x0001 #define SEL_PERMANT 0x0002 @@ -1585,10 +1569,16 @@ } } /* - * LD_CONFIG family. + * LD_CAP_FILES and LD_CONFIG family. */ else if (*s1 == 'C') { - if ((len == MSG_LD_CONFGEN_SIZE) && (strncmp(s1, + if ((len == MSG_LD_CAP_FILES_SIZE) && (strncmp(s1, + MSG_ORIG(MSG_LD_CAP_FILES), MSG_LD_CAP_FILES_SIZE) == 0)) { + select |= SEL_ACT_STR; + str = (select & SEL_REPLACE) ? + &rpl_cap_files : &prm_cap_files; + variable = ENV_FLG_CAP_FILES; + } else if ((len == MSG_LD_CONFGEN_SIZE) && (strncmp(s1, MSG_ORIG(MSG_LD_CONFGEN), MSG_LD_CONFGEN_SIZE) == 0)) { /* * Set by crle(1) to indicate it's building a @@ -1649,6 +1639,18 @@ } } /* + * LD_HWCAP. + */ + else if (*s1 == 'H') { + if ((len == MSG_LD_HWCAP_SIZE) && (strncmp(s1, + MSG_ORIG(MSG_LD_HWCAP), MSG_LD_HWCAP_SIZE) == 0)) { + select |= SEL_ACT_STR; + str = (select & SEL_REPLACE) ? + &rpl_hwcap : &prm_hwcap; + variable = ENV_FLG_HWCAP; + } + } + /* * LD_INIT (internal, used by ldd(1)). */ else if (*s1 == 'I') { @@ -1685,6 +1687,18 @@ } } /* + * LD_MACHCAP. + */ + else if (*s1 == 'M') { + if ((len == MSG_LD_MACHCAP_SIZE) && (strncmp(s1, + MSG_ORIG(MSG_LD_MACHCAP), MSG_LD_MACHCAP_SIZE) == 0)) { + select |= SEL_ACT_STR; + str = (select & SEL_REPLACE) ? + &rpl_machcap : &prm_machcap; + variable = ENV_FLG_MACHCAP; + } + } + /* * The LD_NO family. */ else if (*s1 == 'N') { @@ -1764,10 +1778,16 @@ } } /* - * LD_PRELOAD and LD_PROFILE family. + * LD_PLATCAP, LD_PRELOAD and LD_PROFILE family. */ else if (*s1 == 'P') { - if ((len == MSG_LD_PRELOAD_SIZE) && (strncmp(s1, + if ((len == MSG_LD_PLATCAP_SIZE) && (strncmp(s1, + MSG_ORIG(MSG_LD_PLATCAP), MSG_LD_PLATCAP_SIZE) == 0)) { + select |= SEL_ACT_STR; + str = (select & SEL_REPLACE) ? + &rpl_platcap : &prm_platcap; + variable = ENV_FLG_PLATCAP; + } else if ((len == MSG_LD_PRELOAD_SIZE) && (strncmp(s1, MSG_ORIG(MSG_LD_PRELOAD), MSG_LD_PRELOAD_SIZE) == 0)) { select |= SEL_ACT_STR; str = (select & SEL_REPLACE) ? &rpl_preload : @@ -1792,14 +1812,19 @@ } } /* - * LD_SIGNAL. + * LD_SFCAP and LD_SIGNAL. */ else if (*s1 == 'S') { - if (rtld_flags & RT_FL_SECURE) - return; - if ((len == MSG_LD_SIGNAL_SIZE) && + if ((len == MSG_LD_SFCAP_SIZE) && (strncmp(s1, + MSG_ORIG(MSG_LD_SFCAP), MSG_LD_SFCAP_SIZE) == 0)) { + select |= SEL_ACT_STR; + str = (select & SEL_REPLACE) ? + &rpl_sfcap : &prm_sfcap; + variable = ENV_FLG_SFCAP; + } else if ((len == MSG_LD_SIGNAL_SIZE) && (strncmp(s1, MSG_ORIG(MSG_LD_SIGNAL), - MSG_LD_SIGNAL_SIZE) == 0)) { + MSG_LD_SIGNAL_SIZE) == 0) && + ((rtld_flags & RT_FL_SECURE) == 0)) { select |= SEL_ACT_SPEC_2; variable = ENV_FLG_SIGNAL; } @@ -3420,19 +3445,21 @@ void set_environ(Lm_list *lml) { - Rt_map *dlmp; - Sym *sym; Slookup sl; + Sresult sr; uint_t binfo; /* - * Initialize the symbol lookup data structure. + * Initialize the symbol lookup, and symbol result, data structures. */ SLOOKUP_INIT(sl, MSG_ORIG(MSG_SYM_ENVIRON), lml->lm_head, lml->lm_head, ld_entry_cnt, 0, 0, 0, 0, LKUP_WEAK); - - if (sym = LM_LOOKUP_SYM(lml->lm_head)(&sl, &dlmp, &binfo, 0)) { - lml->lm_environ = (char ***)sym->st_value; + SRESULT_INIT(sr, MSG_ORIG(MSG_SYM_ENVIRON)); + + if (LM_LOOKUP_SYM(lml->lm_head)(&sl, &sr, &binfo, 0)) { + Rt_map *dlmp = sr.sr_dmap; + + lml->lm_environ = (char ***)sr.sr_sym->st_value; if (!(FLAGS(dlmp) & FLG_RT_FIXED)) lml->lm_environ = @@ -3502,6 +3529,50 @@ } /* + * Determine that systems platform name. Normally, this name is provided from + * the AT_SUN_PLATFORM aux vector from the kernel. This routine provides a + * fall back. + */ +void +platform_name(Syscapset *scapset) +{ + char info[SYS_NMLN]; + size_t size; + + if ((scapset->sc_platsz = size = + sysinfo(SI_PLATFORM, info, SYS_NMLN)) == (size_t)-1) + return; + + if ((scapset->sc_plat = malloc(size)) == NULL) { + scapset->sc_platsz = (size_t)-1; + return; + } + (void) strcpy(scapset->sc_plat, info); +} + +/* + * Determine that systems machine name. Normally, this name is provided from + * the AT_SUN_MACHINE aux vector from the kernel. This routine provides a + * fall back. + */ +void +machine_name(Syscapset *scapset) +{ + char info[SYS_NMLN]; + size_t size; + + if ((scapset->sc_machsz = size = + sysinfo(SI_MACHINE, info, SYS_NMLN)) == (size_t)-1) + return; + + if ((scapset->sc_mach = malloc(size)) == NULL) { + scapset->sc_machsz = (size_t)-1; + return; + } + (void) strcpy(scapset->sc_mach, info); +} + +/* * _REENTRANT code gets errno redefined to a function so provide for return * of the thread errno if applicable. This has no meaning in ld.so.1 which * is basically singled threaded. Provide the interface for our dependencies.
--- a/usr/src/cmd/sgs/rtld/i386/i386_elf.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/i386/i386_elf.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -200,6 +200,7 @@ Sym *rsym, *nsym; uint_t binfo, sb_flags = 0, dbg_class; Slookup sl; + Sresult sr; int entry, lmflags; Lm_list *lml; @@ -247,19 +248,25 @@ llmp = lml->lm_tail; /* - * Find definition for symbol. Initialize the symbol lookup data - * structure. + * Find definition for symbol. Initialize the symbol lookup, and + * symbol result, data structures. */ SLOOKUP_INIT(sl, name, lmp, lml->lm_head, ld_entry_cnt, 0, rsymndx, rsym, 0, LKUP_DEFT); + SRESULT_INIT(sr, name); - if ((nsym = lookup_sym(&sl, &nlmp, &binfo, NULL)) == 0) { + if (lookup_sym(&sl, &sr, &binfo, NULL) == 0) { eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NOSYM), NAME(lmp), demangle(name)); rtldexit(lml, 1); } + name = (char *)sr.sr_name; + nlmp = sr.sr_dmap; + nsym = sr.sr_sym; + symval = nsym->st_value; + if (!(FLAGS(nlmp) & FLG_RT_FIXED) && (nsym->st_shndx != SHN_ABS)) symval += ADDR(nlmp); @@ -408,6 +415,7 @@ */ if (plt) { Slookup sl; + Sresult sr; relbgn = pltbgn; relend = pltend; @@ -415,14 +423,17 @@ return (1); /* - * Initialize the symbol lookup data structure. + * Initialize the symbol lookup, and symbol result, data + * structures. */ SLOOKUP_INIT(sl, MSG_ORIG(MSG_SYM_PLT), lmp, lmp, ld_entry_cnt, elf_hash(MSG_ORIG(MSG_SYM_PLT)), 0, 0, 0, LKUP_DEFT); + SRESULT_INIT(sr, MSG_ORIG(MSG_SYM_PLT)); - if ((symdef = elf_find_sym(&sl, &_lmp, &binfo, NULL)) == 0) + if (elf_find_sym(&sl, &sr, &binfo, NULL) == 0) return (1); + symdef = sr.sr_sym; _pltbgn = symdef->st_value; if (!(FLAGS(lmp) & FLG_RT_FIXED) && (symdef->st_shndx != SHN_ABS)) @@ -581,7 +592,7 @@ */ if (ELF_ST_BIND(symref->st_info) == STB_LOCAL) { value = basebgn; - name = (char *)0; + name = NULL; /* * Special case TLS relocations. @@ -642,11 +653,12 @@ } } else { Slookup sl; + Sresult sr; /* * Lookup the symbol definition. - * Initialize the symbol lookup data - * structure. + * Initialize the symbol lookup, and + * symbol result, data structures. */ name = (char *)(STRTAB(lmp) + symref->st_name); @@ -654,9 +666,15 @@ SLOOKUP_INIT(sl, name, lmp, 0, ld_entry_cnt, 0, rsymndx, symref, rtype, LKUP_STDRELOC); + SRESULT_INIT(sr, name); + symdef = NULL; - symdef = lookup_sym(&sl, &_lmp, - &binfo, in_nfavl); + if (lookup_sym(&sl, &sr, &binfo, + in_nfavl)) { + name = (char *)sr.sr_name; + _lmp = sr.sr_dmap; + symdef = sr.sr_sym; + } /* * If the symbol is not found and the @@ -779,7 +797,8 @@ value = TLSMODID(lmp); } else value = basebgn; - name = (char *)0; + + name = NULL; } DBG_CALL(Dbg_reloc_in(LIST(lmp), ELF_DBG_RTLD, M_MACH, @@ -892,26 +911,34 @@ Rt_map *_lmp; Rel rel; Slookup sl; + Sresult sr; uint_t binfo; /* * Determine if the special symbol exists as a reference in the dynamic * executable, and that an associated definition exists in libc.so.1. * - * Initialize the symbol lookup data structure. + * Initialize the symbol lookup, and symbol result, data structures. */ SLOOKUP_INIT(sl, name, rlmp, rlmp, ld_entry_cnt, 0, 0, 0, 0, LKUP_FIRST); + SRESULT_INIT(sr, name); - if ((symref = lookup_sym(&sl, &_lmp, &binfo, NULL)) == 0) + if (lookup_sym(&sl, &sr, &binfo, NULL) == 0) + return (1); + symref = sr.sr_sym; + + SLOOKUP_INIT(sl, name, rlmp, dlmp, ld_entry_cnt, 0, 0, 0, 0, + LKUP_DEFT); + SRESULT_INIT(sr, name); + + if (lookup_sym(&sl, &sr, &binfo, NULL) == 0) return (1); - sl.sl_imap = dlmp; - sl.sl_flags = LKUP_DEFT; + _lmp = sr.sr_dmap; + symdef = sr.sr_sym; - if ((symdef = lookup_sym(&sl, &_lmp, &binfo, NULL)) == 0) - return (1); - if (strcmp(NAME(_lmp), MSG_ORIG(MSG_PTH_LIBC))) + if (strcmp(NAME(sr.sr_dmap), MSG_ORIG(MSG_PTH_LIBC))) return (1); /* @@ -921,7 +948,7 @@ if (!(FLAGS(rlmp) & FLG_RT_FIXED)) ref += ADDR(rlmp); def = (void *)(symdef->st_value); - if (!(FLAGS(_lmp) & FLG_RT_FIXED)) + if (!(FLAGS(sr.sr_dmap) & FLG_RT_FIXED)) def += ADDR(_lmp); /*
--- a/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -49,7 +49,7 @@ { MSG_ORIG(MSG_FLG_IMGALLOC), FLG_RT_IMGALLOC, FLG_RT_IMGALLOC}, { MSG_ORIG(MSG_FLG_RELOCED), FLG_RT_RELOCED, FLG_RT_RELOCED}, { MSG_ORIG(MSG_FLG_SETGROUP), FLG_RT_SETGROUP, FLG_RT_SETGROUP}, - { MSG_ORIG(MSG_FLG_HWCAP), FLG_RT_HWCAP, FLG_RT_HWCAP}, + { MSG_ORIG(MSG_FLG_CAP), FLG_RT_CAP, FLG_RT_CAP}, { MSG_ORIG(MSG_FLG_OBJECT), FLG_RT_OBJECT, FLG_RT_OBJECT}, { MSG_ORIG(MSG_FLG_NEWLOAD), FLG_RT_NEWLOAD, FLG_RT_NEWLOAD}, { MSG_ORIG(MSG_FLG_NODUMP), FLG_RT_NODUMP, FLG_RT_NODUMP}, @@ -81,6 +81,8 @@ static const mdb_bitmask_t rtflags1_bits[] = { { MSG_ORIG(MSG_FL1_COPYTOOK), FL1_RT_COPYTOOK, FL1_RT_COPYTOOK}, + { MSG_ORIG(MSG_FL1_ALTCHECK), FL1_RT_ALTCHECK, FL1_RT_ALTCHECK}, + { MSG_ORIG(MSG_FL1_ALTCAP), FL1_RT_ALTCAP, FL1_RT_ALTCAP}, { MSG_ORIG(MSG_FL1_CONFSET), FL1_RT_CONFSET, FL1_RT_CONFSET }, { MSG_ORIG(MSG_FL1_NODEFLIB), FL1_RT_NODEFLIB, FL1_RT_NODEFLIB }, { MSG_ORIG(MSG_FL1_ENDFILTE), FL1_RT_ENDFILTE, FL1_RT_ENDFILTE },
--- a/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.msg Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.msg Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -64,7 +64,7 @@ @ MSG_FLG_IMGALLOC "IMAGE-ALLOCATED" @ MSG_FLG_RELOCED "RELOCED" @ MSG_FLG_SETGROUP "SET-GROUP" -@ MSG_FLG_HWCAP "HWCAP" +@ MSG_FLG_CAP "CAP" @ MSG_FLG_OBJECT "OBJECT" @ MSG_FLG_NEWLOAD "NEWLOAD" @ MSG_FLG_NODUMP "NODUMP" @@ -93,6 +93,8 @@ @ MSG_FLG_PRIHDL "PRIVATE-HANDLE" @ MSG_FL1_COPYTOOK "COPYTOOK" +@ MSG_FL1_ALTCHECK "ALT-CAP-CHECKED" +@ MSG_FL1_ALTCAP "ALT-CAP-REQUIRED" @ MSG_FL1_CONFSET "CONFSET" @ MSG_FL1_NODEFLIB "NO-DEFAULT-LIBPATH" @ MSG_FL1_ENDFILTE "END-FILTEE"
--- a/usr/src/cmd/sgs/rtld/sparc/sparc_a.out.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/sparc/sparc_a.out.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -74,6 +74,7 @@ int rndx, entry; ulong_t symval; Slookup sl; + Sresult sr; uint_t binfo; Lm_list *lml; @@ -116,14 +117,20 @@ */ SLOOKUP_INIT(sl, name, lmp, lml->lm_head, ld_entry_cnt, 0, 0, 0, 0, LKUP_DEFT); + SRESULT_INIT(sr, name); - if ((sym = aout_lookup_sym(&sl, &nlmp, &binfo, NULL)) == 0) { + if (aout_lookup_sym(&sl, &sr, &binfo, NULL) == 0) { eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NOSYM), NAME(lmp), demangle(name)); rtldexit(lml, 1); } + name = (char *)sr.sr_name; + nlmp = sr.sr_dmap; + sym = sr.sr_sym; + symval = sym->st_value; + if (!(FLAGS(nlmp) & FLG_RT_FIXED) && (sym->st_shndx != SHN_ABS)) symval += (int)(ADDR(nlmp)); @@ -259,10 +266,11 @@ * Perform the relocation. */ if (rp->r_extern == 0) { - name = (char *)0; + name = NULL; value = ADDR(lmp); } else { Slookup sl; + Sresult sr; uint_t binfo; if (rp->r_type == RELOC_JMP_SLOT) @@ -276,9 +284,9 @@ */ SLOOKUP_INIT(sl, name, lmp, 0, ld_entry_cnt, 0, 0, 0, 0, LKUP_STDRELOC); + SRESULT_INIT(sr, name); - if ((sym = aout_lookup_sym(&sl, &_lmp, - &binfo, in_nfavl)) == 0) { + if (aout_lookup_sym(&sl, &sr, &binfo, in_nfavl) == 0) { if (lml->lm_flags & LML_FLG_TRC_WARN) { (void) printf(MSG_INTL(MSG_LDD_SYM_NFOUND), @@ -297,6 +305,10 @@ * If symbol was found in an object other than the * referencing object then record the binding. */ + name = (char *)sr.sr_name; + _lmp = sr.sr_dmap; + sym = sr.sr_sym; + if ((lmp != _lmp) && ((FLAGS1(_lmp) & FL1_RT_NOINIFIN) == 0)) { if (aplist_test(&bound, _lmp,
--- a/usr/src/cmd/sgs/rtld/sparc/sparc_elf.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/sparc/sparc_elf.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -358,6 +358,7 @@ Xword pltndx; uint_t binfo, sb_flags = 0, dbg_class; Slookup sl; + Sresult sr; Pltbindtype pbtype; int entry, lmflags; Lm_list *lml; @@ -419,19 +420,25 @@ llmp = lml->lm_tail; /* - * Find definition for symbol. Initialize the symbol lookup data - * structure. + * Find definition for symbol. Initialize the symbol lookup, and + * symbol result, data structures. */ SLOOKUP_INIT(sl, name, lmp, lml->lm_head, ld_entry_cnt, 0, rsymndx, rsym, 0, LKUP_DEFT); + SRESULT_INIT(sr, name); - if ((nsym = lookup_sym(&sl, &nlmp, &binfo, NULL)) == 0) { + if (lookup_sym(&sl, &sr, &binfo, NULL) == 0) { eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NOSYM), NAME(lmp), demangle(name)); rtldexit(lml, 1); } + name = (char *)sr.sr_name; + nlmp = sr.sr_dmap; + nsym = sr.sr_sym; + symval = nsym->st_value; + if (!(FLAGS(nlmp) & FLG_RT_FIXED) && (nsym->st_shndx != SHN_ABS)) symval += ADDR(nlmp); @@ -590,11 +597,11 @@ * of this table. There are two different interpretations of * the ABI at this point: * - * o The REL table and its associated RELSZ indicate the + * - The REL table and its associated RELSZ indicate the * concatenation of *all* relocation sections (this is the * model our link-editor constructs). * - * o The REL table and its associated RELSZ indicate the + * - The REL table and its associated RELSZ indicate the * concatenation of all *but* the .plt relocations. These * relocations are specified individually by the JMPREL and * PLTRELSZ entries. @@ -741,7 +748,7 @@ */ if (ELF_ST_BIND(symref->st_info) == STB_LOCAL) { value = basebgn; - name = (char *)0; + name = NULL; /* * Special case TLS relocations. @@ -801,11 +808,12 @@ } } else { Slookup sl; + Sresult sr; /* * Lookup the symbol definition. - * Initialize the symbol lookup data - * structure. + * Initialize the symbol lookup, and + * symbol result, data structures. */ name = (char *)(STRTAB(lmp) + symref->st_name); @@ -813,9 +821,15 @@ SLOOKUP_INIT(sl, name, lmp, 0, ld_entry_cnt, 0, rsymndx, symref, rtype, LKUP_STDRELOC); + SRESULT_INIT(sr, name); + symdef = NULL; - symdef = lookup_sym(&sl, &_lmp, - &binfo, in_nfavl); + if (lookup_sym(&sl, &sr, &binfo, + in_nfavl)) { + name = (char *)sr.sr_name; + _lmp = sr.sr_dmap; + symdef = sr.sr_sym; + } /* * If the symbol is not found and the @@ -947,7 +961,8 @@ value = TLSMODID(lmp); } else value = basebgn; - name = (char *)0; + + name = NULL; } DBG_CALL(Dbg_reloc_in(LIST(lmp), ELF_DBG_RTLD, M_MACH,
--- a/usr/src/cmd/sgs/rtld/sparcv9/sparc_elf.c Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/rtld/sparcv9/sparc_elf.c Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -484,6 +484,7 @@ uint_t binfo, sb_flags = 0, dbg_class; ulong_t rsymndx; Slookup sl; + Sresult sr; Pltbindtype pbtype; int entry, lmflags, farplt = 0; Lm_list *lml; @@ -558,19 +559,25 @@ llmp = lml->lm_tail; /* - * Find definition for symbol. Initialize the symbol lookup data - * structure. + * Find definition for symbol. Initialize the symbol lookup, and symbol + * result, data structures. */ SLOOKUP_INIT(sl, name, lmp, lml->lm_head, ld_entry_cnt, 0, rsymndx, rsym, 0, LKUP_DEFT); + SRESULT_INIT(sr, name); - if ((nsym = lookup_sym(&sl, &nlmp, &binfo, NULL)) == 0) { + if (lookup_sym(&sl, &sr, &binfo, NULL) == 0) { eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NOSYM), NAME(lmp), demangle(name)); rtldexit(lml, 1); } + name = (char *)sr.sr_name; + nlmp = sr.sr_dmap; + nsym = sr.sr_sym; + symval = nsym->st_value; + if (!(FLAGS(nlmp) & FLG_RT_FIXED) && (nsym->st_shndx != SHN_ABS)) symval += ADDR(nlmp); @@ -967,7 +974,7 @@ */ if (ELF_ST_BIND(symref->st_info) == STB_LOCAL) { value = basebgn; - name = (char *)0; + name = NULL; /* * Special case TLS relocations. @@ -1029,11 +1036,12 @@ } } else { Slookup sl; + Sresult sr; /* * Lookup the symbol definition. - * Initialize the symbol lookup data - * structure. + * Initialize the symbol lookup, and + * symbol result, data structures. */ name = (char *)(STRTAB(lmp) + symref->st_name); @@ -1041,9 +1049,15 @@ SLOOKUP_INIT(sl, name, lmp, 0, ld_entry_cnt, 0, rsymndx, symref, rtype, LKUP_STDRELOC); + SRESULT_INIT(sr, name); + symdef = NULL; - symdef = lookup_sym(&sl, &_lmp, - &binfo, in_nfavl); + if (lookup_sym(&sl, &sr, &binfo, + in_nfavl)) { + name = (char *)sr.sr_name; + _lmp = sr.sr_dmap; + symdef = sr.sr_sym; + } /* * If the symbol is not found and the @@ -1179,7 +1193,8 @@ value = TLSMODID(lmp); } else value = basebgn; - name = (char *)0; + + name = NULL; } DBG_CALL(Dbg_reloc_in(LIST(lmp), ELF_DBG_RTLD, M_MACH,
--- a/usr/src/cmd/sgs/tools/Makefile.com Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/cmd/sgs/tools/Makefile.com Mon Mar 01 10:20:48 2010 -0800 @@ -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. @@ -19,12 +18,13 @@ # # CDDL HEADER END # -# -# ident "%Z%%M% %I% %E% SMI" + # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # + +# # Makefile to support tools used for linker development: # # o sgsmsg creates message headers/arrays/catalogs (a native tool). @@ -59,7 +59,7 @@ SRCS= $(COMOBJS:%.o=../common/%.c) $(NATOBJS:%.o=../common/%.c) CPPFLAGS += $(VAR_TOOLS_CPPFLAGS) -LDFLAGS += $(USE_PROTO) +LDFLAGS += $(CC_USE_PROTO) CLEANFILES += $(LINTOUT) $(SGSMSG_OBJS) LINTFLAGS= -ax
--- a/usr/src/head/link.h Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/head/link.h Mon Mar 01 10:20:48 2010 -0800 @@ -264,7 +264,7 @@ #endif /* _LP64 */ #endif /* __STDC__ */ - +#ifdef __STDC__ /* * The ElfW() macro is a GNU/Linux feature, provided as support for * the dl_phdr_info structure used by dl_phdr_iterate(), which also @@ -318,6 +318,7 @@ extern int dl_iterate_phdr(int (*)(struct dl_phdr_info *, size_t, void *), void *); +#endif /* __STDC__ */ #endif /* _ASM */ #endif /* _KERNEL */
--- a/usr/src/uts/common/sys/elf.h Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/uts/common/sys/elf.h Mon Mar 01 10:20:48 2010 -0800 @@ -421,7 +421,9 @@ /* Solaris ABI specific values */ #define SHT_LOOS 0x60000000 /* OS specific range */ -#define SHT_LOSUNW 0x6ffffff1 +#define SHT_LOSUNW 0x6fffffef +#define SHT_SUNW_capchain 0x6fffffef +#define SHT_SUNW_capinfo 0x6ffffff0 #define SHT_SUNW_symsort 0x6ffffff1 #define SHT_SUNW_tlssort 0x6ffffff2 #define SHT_SUNW_LDYNSYM 0x6ffffff3 @@ -519,7 +521,7 @@ #define STN_UNDEF 0 /* - * The macros compose and decompose values for S.st_info + * Macros to compose and decompose values for S.st_info * * bind = ELF32_ST_BIND(S.st_info) * type = ELF32_ST_TYPE(S.st_info) @@ -557,7 +559,7 @@ #define STT_HIPROC 15 /* - * The macros decompose values for S.st_other + * Macros to decompose values for S.st_other * * visibility = ELF32_ST_VISIBILITY(S.st_other) */ @@ -604,7 +606,7 @@ /* - * The macros compose and decompose values for Rel.r_info, Rela.f_info + * Macros to compose and decompose values for Rel.r_info, Rela.f_info * * sym = ELF32_R_SYM(R.r_info) * type = ELF32_R_TYPE(R.r_info) @@ -670,7 +672,7 @@ } Elf32_Move; /* - * The macros compose and decompose values for Move.r_info + * Macros to compose and decompose values for Move.r_info * * sym = ELF32_M_SYM(M.m_info) * size = ELF32_M_SIZE(M.m_info) @@ -695,7 +697,7 @@ /* - * Hardware/Software capabilities entry + * Capabilities entry, Capabilities info and Capabilities chain. */ #ifndef _ASM typedef struct { @@ -706,6 +708,21 @@ } c_un; } Elf32_Cap; +typedef Elf32_Word Elf32_Capinfo; +typedef Elf32_Word Elf32_Capchain; + +/* + * Macros to compose and decompose values for capabilities info. + * + * sym = ELF32_C_SYM(info) + * grp = ELF32_C_GROUP(info) + * info = ELF32_C_INFO(sym, grp) + */ +#define ELF32_C_SYM(info) ((info)>>8) +#define ELF32_C_GROUP(info) ((unsigned char)(info)) +#define ELF32_C_INFO(sym, grp) (((sym)<<8)+(unsigned char)(grp)) + + #if defined(_LP64) || defined(_LONGLONG_TYPE) typedef struct { Elf64_Xword c_tag; /* how to interpret value */ @@ -714,14 +731,55 @@ Elf64_Addr c_ptr; } c_un; } Elf64_Cap; + +typedef Elf64_Xword Elf64_Capinfo; +typedef Elf64_Word Elf64_Capchain; + +/* + * Macros to compose and decompose values for capabilities info. + * + * sym = ELF64_C_SYM(info) + * grp = ELF64_C_GROUP(info) + * info = ELF64_C_INFO(sym, grp) + */ +#define ELF64_C_SYM(info) ((info)>>32) +#define ELF64_C_GROUP(info) ((Elf64_Word)(info)) +#define ELF64_C_INFO(sym, grp) (((Elf64_Xword)(sym)<<32)+(Elf64_Xword)(grp)) + #endif /* defined(_LP64) || defined(_LONGLONG_TYPE) */ #endif +/* + * Version numbers for SHT_SUNW_capinfo and SHT_SUNW_capchain. + */ +#define CAPINFO_NONE 0 +#define CAPINFO_CURRENT 1 +#define CAPINFO_NUM 2 + +#define CAPCHAIN_NONE 0 +#define CAPCHAIN_CURRENT 1 +#define CAPCHAIN_NUM 2 + +/* + * A SHT_SUNW_capinfo table mirrors a symbol table. A capabilities symbol has + * a SHT_SUNW_capinfo table entry that provides an index into the associated + * SHT_SUNW_cap capabilities group, and the symbol index of the associated lead + * symbol. A capabilities symbol is a local symbol. A global lead capabilities + * symbol is tagged with a group CAPINFO_SUNW_GLOB. + */ +#define CAPINFO_SUNW_GLOB 0xff + +/* + * Capabilities values. + */ #define CA_SUNW_NULL 0 #define CA_SUNW_HW_1 1 /* first hardware capabilities entry */ #define CA_SUNW_SF_1 2 /* first software capabilities entry */ #define CA_SUNW_HW_2 3 /* second hardware capabilities entry */ -#define CA_SUNW_NUM 4 +#define CA_SUNW_PLAT 4 /* platform capability entry */ +#define CA_SUNW_MACH 5 /* machine capability entry */ +#define CA_SUNW_ID 6 /* capability identifier */ +#define CA_SUNW_NUM 7 /* * Define software capabilities (CA_SUNW_SF_1 values). Note, hardware @@ -735,7 +793,6 @@ /* * Known values for note entry types (e_type == ET_CORE) */ - #define NT_PRSTATUS 1 /* prstatus_t <sys/old_procfs.h> */ #define NT_PRFPREG 2 /* prfpregset_t <sys/old_procfs.h> */ #define NT_PRPSINFO 3 /* prpsinfo_t <sys/old_procfs.h> */
--- a/usr/src/uts/common/sys/link.h Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/uts/common/sys/link.h Mon Mar 01 10:20:48 2010 -0800 @@ -150,11 +150,14 @@ #define DT_SUNW_SYMSORTSZ 0x60000015 /* size of SUNW_SYMSORT */ #define DT_SUNW_TLSSORT 0x60000016 /* tls sym ndx sort by offset */ #define DT_SUNW_TLSSORTSZ 0x60000017 /* size of SUNW_TLSSORT */ - +#define DT_SUNW_CAPINFO 0x60000018 /* capabilities symbols */ #define DT_SUNW_STRPAD 0x60000019 /* # of unused bytes at the */ /* end of dynstr */ +#define DT_SUNW_CAPCHAIN 0x6000001a /* capabilities chain info */ #define DT_SUNW_LDMACH 0x6000001b /* EM_ machine code of linker */ /* that produced object */ +#define DT_SUNW_CAPCHAINENT 0x6000001d /* capabilities chain entry */ +#define DT_SUNW_CAPCHAINSZ 0x6000001f /* capabilities chain size */ /* * DT_* encoding rules do not apply between DT_HIOS and DT_LOPROC @@ -468,6 +471,7 @@ #define SYMINFO_FLG_AUXILIARY 0x0040 /* symbol ref is associated to a */ /* auxiliary filter */ #define SYMINFO_FLG_INTERPOSE 0x0080 /* symbol defines an interposer */ +#define SYMINFO_FLG_CAP 0x0100 /* symbol is capabilities specific */ /* * Syminfo.si_boundto values.
--- a/usr/src/uts/common/sys/machelf.h Thu Feb 25 18:07:30 2010 -0800 +++ b/usr/src/uts/common/sys/machelf.h Mon Mar 01 10:20:48 2010 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -90,6 +90,8 @@ typedef Elf64_Versym Versym; typedef Elf64_Move Move; typedef Elf64_Cap Cap; +typedef Elf64_Capinfo Capinfo; +typedef Elf64_Capchain Capchain; #endif /* _ASM */ #else /* _ILP32 */ @@ -135,6 +137,8 @@ typedef Elf32_Versym Versym; typedef Elf32_Move Move; typedef Elf32_Cap Cap; +typedef Elf32_Capinfo Capinfo; +typedef Elf32_Capchain Capchain; #endif /* _ASM */ #endif /* _ILP32 */