This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Generating an interface description for libraries


> From: Simon Watts <simon.watts@marconi.com>
> To: gcc@gcc.gnu.org
> Date: 02 Nov 2001 14:42:35 +0000

> Is there any way to generate or characterize the external interface
> presented by a set of source which is intended to form a shared
> library (which may have version numbering implications)?

> This information is in the source, in the form of the external function
> and object interfaces.  We can *nearly* get this information by using
> "nm" on the object files or resultant library.  But there are a number
> of limitations to this:
> *	Symbols for C functions doesn't capture the return or input
> parameters.
> *	Similarly, C++ doesn't capture the return types.
> *	The type of globals isn't incorporated.
> ...and probable other stuff as well.

> What I am after is some characterization of an interface, which can then
> be compared to a previous version to determine whether it is equivalent,
> a superset (backwards compatible), a subset, intersection, or separate.

> This is me being very lazy, and wondering about automatic versioning and
> compatibility management of versioned libraries.

First, a disclaimer, it is technically impossible for an automated
tool to always get the right answer.  So, first you have to admit that
the tool you create will give you an approximate answer.

Starting with that, there is a continuum of answers, from blatantly
easy to write, that is correct maybe half the time:

echo "Not compatible"

to slightly harder to write:

abi() {
  nm $1 | sed -n 's/^[0-9a-f]* \([TDBR] \)/\1/p' | sort
}

abi $1 > $1.abi
abi $2 > $2.abi
if diff $1.abi $2.abi 2>/dev/null; then
  echo "Compatible"
else
  echo "Not compatible"
fi

but slightly more accurate.  Beyond this, you can include more and
more advanced techniques in the abi routine.  For example, you can use
readelf --debug-dump or objdump --debugging to show you way more
information about the source code.  You decide what is important for
abi purposes, for example, if you want all functions (including
parameters in C and return values):

abi() {
  objdump --debugging $1 | grep ')$' | sed 's,/\* [^*]*\*/,,g' | sort
}

or if you want the above except with just the non static functions:

abi() {
  objdump --debugging $1 | grep ')$' | sed 's,/\* [^*]*\*/,,g' | grep -v '^static ' | sort
}

you get the idea.  Next, try your hand at including typedefs.

No, I mean now, before you read the next part.

Here it is:

abi() {
  objdump --debugging $1 | grep '^typedef ' | sed 's,/\* [^*]*\*/,,g' | sort
}

Next, try both, all external functions and all typedefs:

abi() {
  objdump --debugging $1 | grep '^typedef ' | sed 's,/\* [^*]*\*/,,g' | sort
  objdump --debugging $1 | grep ')$' | sed 's,/\* [^*]*\*/,,g' | grep -v '^static ' | sort
}

Now, try your hand at all data structures.  I'll leave this as a
homework assignment.  It is much to trivial to give the answer here.

You'll notice that any difference just prints Not compatible.  You can
include forward/backward compatible with just a slight bit of
cleverness:

abi $1 > $1.abi
abi $2 > $2.abi
diff -u0 | grep -v '^--' | grep '^-' >abidiff
if diff $1.abi $2.abi 2>/dev/null; then
  echo "Forwand and backward Compatible"
elif diff abidiff /dev/null 2>/dev/null; then
  echo "Backward Compatible"
else
  echo "Not compatible"
fi

Easy enough.  After this, you can write code crack the abiness out of
a source file, and then use it in the abi routine instead of objdump.

Now, for extra credit produce an abi checker for libstdc++ and
libgcc.so so that we never blow abi compatibility with it and submit
it for inclusion into gcc.  :-)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]