Thread: How to use the pciutils headers and objects?

  1. #1
    Registered User
    Join Date
    May 2013
    Posts
    228

    How to use the pciutils headers and objects?

    Hey.
    I git cloned the pciutils repository (see here), and now I want to write my own version of lspci.
    What do I need to do in order for this wonderful library to be available for me?
    Note: I am not interested in compiling the repo. I know how to do that.
    What I want is for these headers and objects files to be available for me when I run gcc $my_file.
    (the same way I can, for example, include the math.h header to any of my source files and compile with -lmath)
    Thanks!

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,195
    1. You run the top-level makefile, because the lib makefile says this
    > # Expects to be invoked from the top-level Makefile and uses lots of its variables.

    You should end up with a library file (.so and/or .a)

    You might end up with a separate include directory, containing only those header files which describe the public interface to the library. If not, you need to experiment a little.

    Eg
    Code:
    #include <pci.h>
    int main ( ) {
        struct pci_access pci;
        pci_init(&pci);
    }

    The way you use it would be
    gcc -I/path/to/pciutils/include -L/path/to/pciutils/lib prog.c -lpciutils

    The red path is the directory where pci.h is included from.
    The green path is the directory where the library is located.
    The actual library name is libpciutils.so
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    May 2013
    Posts
    228
    Hey Salem. Thanks for the help.
    I ran the top level makefile, and it looks like it creates some object files into pciutils/lib/, plus the pci.h is also at pciutils/lib.
    So I ran the above example with:
    Code:
    $ gcc test.c -Iproject/pciutils/lib/ -Lproject/pciutils/lib/ -lpciutils
    (project/pciutils is the correct relative path)
    and I get a linker error:
    Code:
    /usr/bin/ld: cannot find -lpciutils
    collect2: error: ld returned 1 exit status
    Should I have override the PREFIX variable when running 'make' for this to find the pciutils.so? Where is it located anyway?

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,195
    Does it actually create a .so file?
    If so, where is it? (make the -L option point to it).
    Also, check it's name is of the form libfoo.so (then pass -lfoo as the option to the compiler).
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    May 2009
    Posts
    3,897
    I have spent about 5 minutes looking at the build files and it looks like the library might be called "libpci".

    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  6. #6
    Registered User
    Join Date
    Jun 2015
    Posts
    1,643
    In the README:
    Just run "make" to compile the package and then "make install" to install it.
    ...
    "make install-lib" installs the library together with its header files for use by other programs.
    In the top Makefile:
    # Build libpci as a shared library (yes/no; or local for testing; requires GCC)
    SHARED=no
    And the library does seem to be called libpci.

  7. #7
    Registered User
    Join Date
    May 2013
    Posts
    228
    Thanks for your help guys.
    This is going to be long, but please bare with me. This is very important for me, and is actually just a small part of a greater project I have already written (in python).

    I don't know how I missed that in the README...

    Anyway, this is what I did:
    Code:
    $ sudo make SHARED=no install-lib
    [sudo] password for absurd: 
    make -C lib all
    make[1]: Entering directory `/home/absurd/Documents/Programming/project/pciutils/lib'
    make[1]: Nothing to be done for `all'.
    make[1]: Leaving directory `/home/absurd/Documents/Programming/project/pciutils/lib'
    install -d -m 755 /usr/local/lib
    install -c -m 644 lib/libpci.a /usr/local/lib
    install -d -m 755 /usr/local/include/pci /usr/local/lib/pkgconfig
    install -c -m 644 lib/config.h lib/header.h lib/pci.h lib/types.h /usr/local/include/pci
    install -c -m 644 lib/libpci.pc /usr/local/lib/pkgconfig
    And this is how "my_example.c" (slightly changed "example.c") looks like:
    Code:
    #include <stdio.h>
    #include <pci.h>
    #include <internal.h>
    
    int main(int argc, char* argv[]) {
        struct pci_access *pacc;
        struct pci_dev *dev;
        u8 cfg_space[4096] = {0};
    
        pacc = pci_alloc();  /* Get the pci_access structure */
    
        /* Set all options you want -- here we stick with the defaults */
    
        pci_init(pacc);     /* Initialize the PCI library */
        pci_scan_bus(pacc); /* We want to get the list of devices */
    
        for (dev=pacc->devices; dev; dev=dev->next)    { /* Iterate over all devices */
    
            if (!pci_read_block(dev, 0x0, cfg_space, 2)) {
                // handle error
                return 1;
            }
            printf("vendor id=%x%x\n", cfg_space[0], cfg_space[1]);
    
        }
    
        pci_cleanup(pacc);
        return 0;
    }
    And when I run it with:
    Code:
    $ gcc my_example.c -Iproject/pciutils/lib/ -lpci
    It compiles and run, but:
    1. Why do I have to specify -Iproject/pciutils/lib/ ?
      It seems like when I don't specify it, the preprocessor can't find the headers:

      Code:
      $ gcc my_example.c -lpci
      my_example.c:2:17: fatal error: pci.h: No such file or directory
      #include <pci.h>
               ^
      compilation terminated.
      Now, it is true that I can omit the -Iproject/pciutils/lib/ and do:
      Code:
      #include <pci/pci.h>
      but then; a) the pci.h that is used is the one at /usr/include/pci/pci.h which is not the same as the one I just downloaded with the repo (project/pciutils/lib/pci.h), and b) there's no /usr/include/pci/internal.h in /usr/include/pci/, which is used in example.c (and consequently in my_example.c) (CORRECTION: internal.h is not included in example.c, but is required if I want to gain access to some more low-level elements.)
    2. The previous item led me to suspect that when I linked the libpci with -lpci I wasn't actually linking the newly installed library, but rather some old one that I already had. so I did an experiment:
      I added printf("flag\n"); in void pci_scan_bus(struct pci_access *a) (you can see that it is invoked in my_example.c):
      Code:
      $ git diff
      diff --git a/lib/access.c b/lib/access.c
      index d991129..cc52dd9 100644
      --- a/lib/access.c
      +++ b/lib/access.c
      @@ -16,6 +16,7 @@
       void
       pci_scan_bus(struct pci_access *a)
       {
      +       printf("flag\n");
         a->methods->scan(a);
       }
      recompiled and reinstalled:
      Code:
      $ make 
      make -C lib all
      make[1]: Entering directory `/home/absurd/Documents/Programming/project/pciutils/lib'
      gcc -O2 -Wall -W -Wno-parentheses -Wstrict-prototypes -Wmissing-prototypes   -c -o access.o access.c
      rm -f libpci.a
      ar rcs libpci.a init.o access.o generic.o dump.o names.o filter.o names-hash.o names-parse.o names-net.o names-cache.o names-hwdb.o params.o caps.o sysfs.o proc.o i386-ports.o
      ranlib libpci.a
      make[1]: Leaving directory `/home/absurd/Documents/Programming/project/pciutils/lib'
      gcc   lspci.o ls-vpd.o ls-caps.o ls-caps-vendor.o ls-ecaps.o ls-kernel.o ls-tree.o ls-map.o common.o lib/libpci.a  -lz -lresolv -ludev  -o lspci
      gcc   setpci.o common.o lib/libpci.a  -lz -lresolv -ludev -o setpci
      gcc   example.o lib/libpci.a  -lz -lresolv -ludev -o example
      $ sudo make SHARED=no install-lib
      [sudo] password for absurd: 
      make -C lib all
      make[1]: Entering directory `/home/absurd/Documents/Programming/project/pciutils/lib'
      make[1]: Nothing to be done for `all'.
      make[1]: Leaving directory `/home/absurd/Documents/Programming/project/pciutils/lib'
      install -d -m 755 /usr/local/lib
      install -c -m 644 lib/libpci.a /usr/local/lib
      install -d -m 755 /usr/local/include/pci /usr/local/lib/pkgconfig
      install -c -m 644 lib/config.h lib/header.h lib/pci.h lib/types.h /usr/local/include/pci
      install -c -m 644 lib/libpci.pc /usr/local/lib/pkgconfig
      And then when I recompile my_example.c too:
      Code:
      gcc my_example.c -Iproject/pciutils/lib/ -lpci
      running ./a.out, I couldn't see the 'flag' printed out.
      So that got me to suspect that I am not linking the correct library...


    Any help would be greatly apprecieated.
    Last edited by Absurd; 03-04-2017 at 03:02 AM.

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,195
    gcc -M my_example.c -Iproject/pciutils/lib/ -lpci
    This will show you which include files get included.

    gcc -Wl,-t my_example.c -Iproject/pciutils/lib/ -lpci
    This will show you which files/libs are being processed by the linker.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  9. #9
    Registered User
    Join Date
    May 2013
    Posts
    228
    The header file that is used when I do:
    Code:
    $ gcc -M my_example.c -Iproject/pciutils/lib/ -lpci
    is project/pciutils/lib/pci.h, (meaning the one in project/pciutils/lib/), but that's just because I helped gcc by providing the -I flag...

    The library that is used when I do:
    Code:
    $ gcc -Wl,-t my_example.c -Iproject/pciutils/lib/ -lpci
    is /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libpci.so, how can I tell if that's the one that was installed? (it's probably not, so how do I know where is the newly installed and how do I use it instead of /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libpci.so)?

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,195
    > how can I tell if that's the one that was installed?
    Read the log of the install.

    install -c -m 644 lib/libpci.a /usr/local/lib
    Use the -L option to direct the linker towards a different place (see post #2).
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  11. #11
    Registered User
    Join Date
    May 2013
    Posts
    228
    When I directed the linker to /usr/local/lib, it threw another thousand linking errors for some reason...

    Code:
    $ gcc my_example.c -L/usr/local/lib -Iproject/pciutils/lib/ -lpci
    /usr/local/lib/libpci.a(names-parse.o): In function `id_parse_list':
    names-parse.c:(.text+0xcc): undefined reference to `gzgets'
    names-parse.c:(.text+0x10c): undefined reference to `gzeof'
    /usr/local/lib/libpci.a(names-parse.o): In function `pci_load_name_list':
    names-parse.c:(.text+0x5f5): undefined reference to `gzopen'
    names-parse.c:(.text+0x621): undefined reference to `gzclose'
    names-parse.c:(.text+0x6c3): undefined reference to `gzopen'
    names-parse.c:(.text+0x6f1): undefined reference to `gzerror'
    names-parse.c:(.text+0x701): undefined reference to `gzclose'
    names-parse.c:(.text+0x726): undefined reference to `zError'
    names-parse.c:(.text+0x731): undefined reference to `gzclose'
    names-parse.c:(.text+0x752): undefined reference to `gzclose'
    /usr/local/lib/libpci.a(names-hwdb.o): In function `pci_id_hwdb_lookup':
    names-hwdb.c:(.text+0xcc): undefined reference to `udev_hwdb_get_properties_list_entry'
    names-hwdb.c:(.text+0xe1): undefined reference to `udev_list_entry_get_next'
    names-hwdb.c:(.text+0xf5): undefined reference to `udev_list_entry_get_name'
    names-hwdb.c:(.text+0x10c): undefined reference to `udev_list_entry_get_value'
    names-hwdb.c:(.text+0x243): undefined reference to `udev_new'
    names-hwdb.c:(.text+0x250): undefined reference to `udev_hwdb_new'
    /usr/local/lib/libpci.a(names-hwdb.o): In function `pci_id_hwdb_free':
    names-hwdb.c:(.text+0x27e): undefined reference to `udev_hwdb_unref'
    names-hwdb.c:(.text+0x294): undefined reference to `udev_unref'
    collect2: error: ld returned 1 exit status
    I don't even recognize these references...

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,195
    Progressions.

    Code:
    $ gcc example2.c
    example2.c:2:17: fatal error: pci.h: No such file or directory
    compilation terminated.
    Oh, didn't find where to include pci.h from, so add a -I path.
    Code:
    $ gcc -I./lib example2.c
    /tmp/ccTriEvn.o: In function `main':
    example2.c:(.text+0x3f): undefined reference to `pci_alloc'
    example2.c:(.text+0x55): undefined reference to `pci_init'
    example2.c:(.text+0x64): undefined reference to `pci_scan_bus'
    example2.c:(.text+0x98): undefined reference to `pci_read_block'
    example2.c:(.text+0xf2): undefined reference to `pci_cleanup'
    collect2: error: ld returned 1 exit status
    Better, but missing the pci library. So add the -L and -l options.
    Code:
    $ gcc -I./lib -L./lib example2.c -lpci
    ./lib/libpci.a(names-parse.o): In function `id_parse_list':
    names-parse.c:(.text+0xcc): undefined reference to `gzgets'
    names-parse.c:(.text+0x240): undefined reference to `gzeof'
    names-parse.c:(.text+0x45f): undefined reference to `gzeof'
    ./lib/libpci.a(names-parse.o): In function `pci_load_name_list':
    names-parse.c:(.text+0x5d5): undefined reference to `gzopen'
    names-parse.c:(.text+0x5ff): undefined reference to `gzclose'
    names-parse.c:(.text+0x6b3): undefined reference to `gzopen'
    names-parse.c:(.text+0x6d9): undefined reference to `gzerror'
    names-parse.c:(.text+0x6e9): undefined reference to `gzclose'
    names-parse.c:(.text+0x70e): undefined reference to `zError'
    names-parse.c:(.text+0x719): undefined reference to `gzclose'
    names-parse.c:(.text+0x73a): undefined reference to `gzclose'
    ./lib/libpci.a(names-hwdb.o): In function `pci_id_hwdb_lookup':
    names-hwdb.c:(.text+0xd4): undefined reference to `udev_hwdb_get_properties_list_entry'
    names-hwdb.c:(.text+0xe9): undefined reference to `udev_list_entry_get_next'
    names-hwdb.c:(.text+0xfd): undefined reference to `udev_list_entry_get_name'
    names-hwdb.c:(.text+0x114): undefined reference to `udev_list_entry_get_value'
    names-hwdb.c:(.text+0x249): undefined reference to `udev_new'
    names-hwdb.c:(.text+0x256): undefined reference to `udev_hwdb_new'
    ./lib/libpci.a(names-hwdb.o): In function `pci_id_hwdb_free':
    names-hwdb.c:(.text+0x27e): undefined reference to `udev_hwdb_unref'
    names-hwdb.c:(.text+0x294): undefined reference to `udev_unref'
    collect2: error: ld returned 1 exit status
    Now we're missing other dependent libraries as well. Find out where they're resolved.
    Obviously, 'gz' and 'udev' are common themes, so pick a symbol from each. Where one is, the rest are pretty sure to be found.
    Code:
    $ find /lib /usr/lib -name "*.a" | xargs nm --print-file-name --extern-only --defined-only 2>/dev/null | grep gzclose
    /usr/lib/x86_64-linux-gnu/libz.a:gzclose.o:0000000000000000 T gzclose
    /usr/lib/x86_64-linux-gnu/libz.a:gzread.o:0000000000000ea0 T gzclose_r
    /usr/lib/x86_64-linux-gnu/libz.a:gzwrite.o:0000000000001170 T gzclose_w
    $ find /lib /usr/lib -name "*.a" | xargs nm --print-file-name --extern-only --defined-only 2>/dev/null | grep udev_hwdb_get_properties_list_entry
    On my system, libz is installed, but there is nothing for udev. At this point, you hit google to find out the appropriate package name for the missing library.

    So anyway, let's try half of it.
    Code:
    $ gcc -I./lib -L./lib example2.c -lpci -lz
    ./lib/libpci.a(names-hwdb.o): In function `pci_id_hwdb_lookup':
    names-hwdb.c:(.text+0xd4): undefined reference to `udev_hwdb_get_properties_list_entry'
    names-hwdb.c:(.text+0xe9): undefined reference to `udev_list_entry_get_next'
    names-hwdb.c:(.text+0xfd): undefined reference to `udev_list_entry_get_name'
    names-hwdb.c:(.text+0x114): undefined reference to `udev_list_entry_get_value'
    names-hwdb.c:(.text+0x249): undefined reference to `udev_new'
    names-hwdb.c:(.text+0x256): undefined reference to `udev_hwdb_new'
    ./lib/libpci.a(names-hwdb.o): In function `pci_id_hwdb_free':
    names-hwdb.c:(.text+0x27e): undefined reference to `udev_hwdb_unref'
    names-hwdb.c:(.text+0x294): undefined reference to `udev_unref'
    collect2: error: ld returned 1 exit status
    Good, -lz resolved all the 'z' functions. All that is needed now is to obtain libudev (or whatever it's called).
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  13. #13
    Registered User
    Join Date
    May 2013
    Posts
    228
    You are a genius!
    Code:
    $ gcc my_example.c -L/usr/local/lib -Iproject/pciutils/lib/ -lpci -lz -ludev
    $ ./a.out
    flag
    vendor id=ec10
    vendor id=8c16
    vendor id=8680
    vendor id=8680
    vendor id=8680
    vendor id=8680
    vendor id=8680
    vendor id=8680
    vendor id=8680
    vendor id=8680
    vendor id=8680
    vendor id=8680
    vendor id=8680
    $
    The second 'find' command came up with nothing, but I tried adding -ludev anyway and it worked...
    Thanks!

  14. #14
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,195
    Yeah, the find command for .so files would be this.
    Code:
    $ find /lib /usr/lib -name "*.so" | xargs nm --dynamic --print-file-name --extern-only --defined-only 2>/dev/null | grep udev_hwdb_get_properties_list_entry
    Glad you're up and running
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help with pciutils-dev
    By Absurd in forum Linux Programming
    Replies: 9
    Last Post: 01-02-2016, 02:59 AM
  2. Replies: 9
    Last Post: 03-07-2014, 09:36 PM
  3. headers and objects/classes
    By l2u in forum C++ Programming
    Replies: 2
    Last Post: 08-12-2007, 06:38 AM
  4. Replies: 4
    Last Post: 06-18-2005, 02:26 PM
  5. including headers inside headers
    By kromozom in forum C++ Programming
    Replies: 5
    Last Post: 04-18-2005, 10:56 AM

Tags for this Thread