[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Detecting transitive ABI dependencies with libabigail?



Hi -

Thanks for your detailed answer.

I think I agree that case 1.a is not solvable with libabigail.
However, I think it isn't necessary to solve that one.

Imagine a new entity, call it "app.cpp" and compiling to app, that
includes user.hpp and picks up a transitive dependency on
provider.hpp. The app.cpp file makes use of some of the APIs in
user.hpp. If it calls an API method from user.hpp that is defined in
user.cpp then that may or may not induce a dependency on libprovider,
depending on whether those calls make use of things defined in
libprovider. That is the case that I think we can detect using
libabigail (your type 1.b). However, if app.cpp makes any calls to
functions that are defined in libprovider.h directly (i.e. not as a
side effect of calling things declared in user.hpp) then this is your
case 1.a. In that case, I'd argue that app should simply directly
depend on libprovider - things from libuser didn't enter the picture,
and so we shouldn't declare that linking to libuser should
automatically induce a link to libprovider.

I think another way to look at it would be that if you ran the
include-what-you-use tool on app.cpp when it contained a type 1.a
usage, then it would suggest that you add provider.hpp to your list of
includes rather than picking it up indirectly via user.hpp. After
which, it wouldn't be surprising to find that app should link directly
to libprovider.

So I think it is reasonable to exclude case 1.a from consideration and
restrict the tool to type 1.b usages.

Does that make sense?

One question that this does raise for me is whether libagibail is the
correct tool to use for the job. I wonder whether writing a clang/llvm
based tool (like include-what-you-use) might be better?

Thanks,
Andrew

On Thu, Nov 2, 2017 at 11:22 AM, Dodji Seketeli <dodji@seketeli.org> wrote:
> "Andrew C. Morrow" <andrew.c.morrow@gmail.com> a écrit:
>
>> Could libabigail be leveraged to answer the following question:
>>
>> Given a library libprovider.so and a library libuser.so, I'd like to
>> know whether the ABI of libuser.so requires knowledge of types,
>> functions, or values exported by the ABI of libprovider.so. In other
>> words, is it the case that to meaningfully use the ABI of libuser.so
>> one must link to libprovider.so?
>>
>> In particular, I'd like to distinguish the case where libuser.so makes
>> use of libprovider.so purely internally, meaning that someone linking
>> to libuser.so does not necessarily need to link explicitly to
>> libprovider.so, from the case where libuser.so makes use of objects
>> from libprovider.so in its ABI, and therefore does induce such a
>> transitive dependency on libprovider.so.
>
> If I understand correctly, the case where libuser.so makes use of types
> (or functions/variables) from libprovider in its ABI happens when:
>
>     1/ libuser.so "exports" a header file user.h that includes a header
>     file provider.h from libprovider.so, and users of libuser.so *have*
>     to use artifacts (types, functions or variables) from provider.h for
>     a particular feature provided by libuser.so.
>
> So 1/ is the general case.
>
> Let's look at what I see as a possible breakdown of the different
> possibilities covered by 1/.
>
> 1.a/ libuser.so header file user.h exports a function or variable 'foo'
> that is actually declared in provider.h and defined in libprovider.so
>
>  In other words, user.h includes provider.h.  Users of libuser.so can
> thus use 'foo' and become dependent on libprovider.so.
>
> As foo is not present (defined) in the binary libuser.so, looking at
> that binary won't give us any meaningful information about it.
>
> foo could be used by libuser.so itself, though.  That is, foo could be
> seen as an undefined symbol, needed by libuser.so.  But that doesn't
> give us much information because it could mean that libuser.so just
> needs foo privately.
>
> We thus need to have access to the header files of both libuser.so and
> libprovider.so to detect this case.  And we need a way to parse those
> header files to to so, I think.
>
> 1.b/ libuser.so header file user.h declares a function (or variable)
> 'bar'.  bar is defined in libuser.so and exported from there.  The
> interface of bar then uses a type 'provider_type' that is declared (or
> defined) in provider.h.
>
> If 'provided_type' is *used* in a public interface defined in
> libprovider.so, then we could detect that provided_type, used by a
> public interface of libuser.so is also used by a public interface of
> libprovider.so.  We can do that with libabigail, yes, without having to
> have access to header files.
>
> [...]
>
>> I'm hoping to build something which can act as a lint tool to evaluate
>> whether a given project is using the CMake style
>> public/private/interface library dependency annotations correctly.
>> Most notably, I'd like to be able to find library dependencies that
>> are declared public, but could/should be weakened to private.
>
> I see.  It makes sense.
>
>
> [...]
>
>> - Is the information provided by running abidw on both libuser.so and
>> libprovider.so sufficient to answer this question?
>
> For the 1.a case, I am afraid that we don't have enough information by
> just looking at the binaries.  We'd need access to header files and a
> way to parse them.  And libabigail doesn't parse header files.  It just
> analyzes binaries.
>
> For 1.b, though, I think we could answer the question, yes.
>
>> - How would one approach writing such a tool given the facilities
>> already available in libabigail?
>
> For 1.b, I think one could walk the type tree reachable from
> functions/variables exported from libuser.so [1] and build the set of
> types reachable from those interfaces.
>
> One could lookup those types from libprovider.so to see if anyone of
> them is actually "defined" (or even declared) in libprovider.so.  If
> there is one, then we have found one of these problematic cases.
>
> I am not sure if I have answered your question completely, or if I am
> forgetting something.
>
> In any case, please do not hesitate to ask :-)
>
>
> [1]: Please note that this type tree walk would be a shallow one,
> though.  That is, one should not follow pointers -- but this is a
> detail I this point, I guess.
>
>
> Cheers,
>
> --
>                 Dodji