Ambiguity in version scripts

Ian Lance Taylor iant@google.com
Sat Jan 9 22:32:00 GMT 2010


A version script logically matches a symbol name to a single version
tag.  I've tried to take advantage of that in gold to speed up version
script handling.  Unfortunately, I've discovered that version scripts
in actual use are ambiguous.  So I've tried to write down the rules
that the GNU linker uses.  This is what I've come up with.  I think
this is moderately insane.  I would be interested in any corrections
to this, and also in any thoughts on what gold should do in this area.


// A version script essentially maps a symbol name to a version tag
// and an indication of whether symbol is global or local within that
// version tag.  Each symbol maps to at most one version tag.
// Unfortunately, in practice, version scripts are ambiguous, and list
// symbols multiple times.  Thus, we have to document the matching
// process.

// The GNU linker walks through the version tags in the order in which
// they appear in the version script.  For each tag, it first walks
// through the global patterns for that tag, then the local patterns.
// When looking at a single pattern, it first applies any language
// specific demangling as specified for the pattern, and then matches
// the resulting symbol name to the pattern.  If it finds an exact
// match for a literal pattern (a pattern enclosed in quotes or with
// no wildcard characters), then that is the match that it uses.  If
// finds a match with a wildcard pattern, then it saves it and
// continues searching.  Wildcard patterns that are exactly "*" are
// saved separately.

// If no exact match with a literal pattern is ever found, then if a
// wildcard match with a global pattern was found it is used,
// otherwise if a wildcard match with a local pattern was found it is
// used.

// This is the result:
//   * If there is an exact match, then we use the first tag in the
//     version script where it matches.
//     + If the exact match in that tag is global, it is used.
//     + Otherwise the exact match in that tag is local, and is used.
//   * Otherwise, if there is any match with a global wildcard pattern:
//     + If there is any match with a wildcard pattern which is not
//       "*", then we use the tag in which the *last* such pattern
//       appears.
//     + Otherwise, we matched "*".  If there is no match with a local
//       wildcard pattern which is not "*", then we use the *last*
//       match with a global "*".  Otherwise, continue.
//   * Otherwise, if there is any match with a local wildcard pattern:
//     + If there is any match with a wildcard pattern which is not
//       "*", then we use the tag in which the *last* such pattern
//       appears.
//     + Otherwise, we matched "*", and we use the tag in which the
//       *last* such match occurred.

// There is an additional wrinkle.  When the GNU linker finds a symbol
// with a version defined in an object file due to a .symver
// directive, it looks up that symbol name in that version tag.  If it
// finds it, it matches the symbol name against the patterns for that
// version.  If there is no match with a global pattern, but there is
// a match with a local pattern, then the GNU linker marks the symbol
// as local.


Ian



More information about the Binutils mailing list