FreeBSD/cddl/contrib/opensolaris/tools/ctf/cvt/output.c
/*
 * If we have a weak symbol, attempt to find the strong symbol it will
 * resolve to.  Note: the code where this actually happens is in
 * sym_process() in cmd/sgs/libld/common/syms.c
 *
 * Finding the matching symbol is unfortunately not trivial.  For a
 * symbol to be a candidate, it must:
 *
 * - have the same type (function, object)
 * - have the same value (address)
 * - have the same size
 * - not be another weak symbol
 * - belong to the same section (checked via section index)
 *
 * If such a candidate is global, then we assume we've found it.  The
 * linker generates the symbol table such that the curfile might be
 * incorrect; this is OK for global symbols, since find_iidesc() doesn't
 * need to check for the source file for the symbol.
 *
 * We might have found a strong local symbol, where the curfile is
 * accurate and matches that of the weak symbol.  We assume this is a
 * reasonable match.
 *
 * If we've got a local symbol with a non-matching curfile, there are
 * two possibilities.  Either this is a completely different symbol, or
 * it's a once-global symbol that was scoped to local via a mapfile.  In
 * the latter case, curfile is likely inaccurate since the linker does
 * not preserve the needed curfile in the order of the symbol table (see
 * the comments about locally scoped symbols in libld's update_osym()).
 * As we can't tell this case from the former one, we use this symbol
 * iff no other matching symbol is found.
 *
 * What we really need here is a SUNW section containing weak<->strong
 * mappings that we can consume.
 */
If we have a weak symbol, attempt to find the strong symbol it will
resolve to.  Note: the code where this actually happens is in
sym_process() in cmd/sgs/libld/common/syms.c

Finding the matching symbol is unfortunately not trivial.  For a
symbol to be a candidate, it must.



If such a candidate is global, then we assume we've found it.  The
linker generates the symbol table such that the curfile might be
incorrect; this is OK for global symbols, since find_iidesc() doesn't
need to check for the source file for the symbol.

We might have found a strong local symbol, where the curfile is
accurate and matches that of the weak symbol.  We assume this is a
reasonable match.

If we've got a local symbol with a non-matching curfile, there are
two possibilities.  Either this is a completely different symbol, or
it's a once-global symbol that was scoped to local via a mapfile.  In
the latter case, curfile is likely inaccurate since the linker does
not preserve the needed curfile in the order of the symbol table (see
the comments about locally scoped symbols in libld's update_osym()).
As we can't tell this case from the former one, we use this symbol
iff no other matching symbol is found.


If we have a weak symbol attempt to find the strong symbol it will resolve to . Note : the code where this actually happens is in sym_process () in cmd / sgs / libld / common / syms . c Finding the matching symbol is unfortunately not trivial . For a symbol to be a candidate it must . If such a candidate is global then we assume we ' ve found it . The linker generates the symbol table such that the curfile might be incorrect ; this is OK for global symbols since find_iidesc () doesn ' t need to check for the source file for the symbol . We might have found a strong local symbol where the curfile is accurate and matches that of the weak symbol . We assume this is a reasonable match . If we ' ve got a local symbol with a non - matching curfile there are two possibilities . Either this is a completely different symbol or it ' s a once - global symbol that was scoped to local via a mapfile . In the latter case curfile is likely inaccurate since the linker does not preserve the needed curfile in the order of the symbol table ( see the comments about locally scoped symbols in libld ' s update_osym () ) . As we can ' t tell this case from the former one we use this symbol iff no other matching symbol is found .
static int
check_for_weak(GElf_Sym *weak, char const *weakfile,
    Elf_Data *data, int nent, Elf_Data *strdata,
    GElf_Sym *retsym, char **curfilep)
{
	char *curfile = NULL;
	char *tmpfile1 = NULL;
	GElf_Sym tmpsym;
	int candidate = 0;
	int i;
	tmpsym.st_info = 0;
	tmpsym.st_name = 0;
	if (GELF_ST_BIND(weak->st_info) != STB_WEAK)
		return (0);
	for (i = 0; i < nent; i++) {
		GElf_Sym sym;
		uchar_t type;
		if (gelf_getsym(data, i, &sym) == NULL)
			continue;
		type = GELF_ST_TYPE(sym.st_info);
		if (type == STT_FILE)
			curfile = (char *)strdata->d_buf + sym.st_name;
		if (GELF_ST_TYPE(weak->st_info) != type ||
		    weak->st_value != sym.st_value)
			continue;
		if (weak->st_size != sym.st_size)
			continue;
		if (GELF_ST_BIND(sym.st_info) == STB_WEAK)
			continue;
		if (sym.st_shndx != weak->st_shndx)
			continue;
		if (GELF_ST_BIND(sym.st_info) == STB_LOCAL &&
		    (curfile == NULL || weakfile == NULL ||
		    strcmp(curfile, weakfile) != 0)) {
			candidate = 1;
			tmpfile1 = curfile;
			tmpsym = sym;
			continue;
		}
		*curfilep = curfile;
		*retsym = sym;
		return (1);
	}
	if (candidate) {
		*curfilep = tmpfile1;
		*retsym = tmpsym;
		return (1);
	}
	return (0);
}
static int check_for_weak ( GElf_Sym * weak , char const * weakfile , Elf_Data * data , int nent , Elf_Data * strdata , GElf_Sym * retsym , char * * curfilep ) { char * curfile = NULL ; char * tmpfile1 = NULL ; GElf_Sym tmpsym ; int candidate = 0 ; int i ; tmpsym . st_info = 0 ; tmpsym . st_name = 0 ; if ( GELF_ST_BIND ( weak -> st_info ) != STB_WEAK ) return ( 0 ) ; for ( i = 0 ; i < nent ; i ++ ) { GElf_Sym sym ; uchar_t type ; if ( gelf_getsym ( data , i , & sym ) == NULL ) continue ; type = GELF_ST_TYPE ( sym . st_info ) ; if ( type == STT_FILE ) curfile = ( char * ) strdata -> d_buf + sym . st_name ; if ( GELF_ST_TYPE ( weak -> st_info ) != type || weak -> st_value != sym . st_value ) continue ; if ( weak -> st_size != sym . st_size ) continue ; if ( GELF_ST_BIND ( sym . st_info ) == STB_WEAK ) continue ; if ( sym . st_shndx != weak -> st_shndx ) continue ; if ( GELF_ST_BIND ( sym . st_info ) == STB_LOCAL && ( curfile == NULL || weakfile == NULL || strcmp ( curfile , weakfile ) != 0 ) ) { candidate = 1 ; tmpfile1 = curfile ; tmpsym = sym ; continue ; } * curfilep = curfile ; * retsym = sym ; return ( 1 ) ; } if ( candidate ) { * curfilep = tmpfile1 ; * retsym = tmpsym ; return ( 1 ) ; } return ( 0 ) ; }
If we have a weak symbol, attempt to find the strong symbol it will
 resolve to.
If we have a weak symbol attempt to find the strong symbol it will resolve to .