1

Is there a ready-made solution for getting a list of the archive members that got used (or would be used) while linking in an archive (i.e. a static library)?

Say if I have an object file that provides main and depends on a and b. If I link it against a static lib lib.a, providing a, b, c, d in archive members a.o, b.o, c.o, and d.o respectively, then I would like to get a list with a.o and b.o, either as a side product of linking the library or by running command_to_get_members main.o lib.a

Are there solutions for this or do I need to parse nm outputs and resolve the symbols against the archive members manually?

Petr Skocik
  • 58,047
  • 6
  • 95
  • 142
  • maybe you looking for this [man ldd](http://man7.org/linux/man-pages/man1/ldd.1.html) or [man strings](https://linux.die.net/man/1/strings) – Stargateur Dec 06 '16 at 14:12
  • @Stargateur I think the closest thing to what I'm looking for is passing `-M` to the linker with `-Wl,-M`. It prints a map that includes a list of how symbols resolve to archive members. Not ideal as I still have to do some text processing on it but I think I'll go with that unless a better solution comes up. – Petr Skocik Dec 06 '16 at 14:15
  • Oh I better see what you want, indeed nm can do that with --defined-only and --extern-only. Maybe this could help you http://stackoverflow.com/questions/6687630/how-to-remove-unused-c-c-symbols-with-gcc-and-ld. I don't know other solution. – Stargateur Dec 06 '16 at 14:35

1 Answers1

1

Here is a suggestion, a script that uses nm (with --defined-only and --undefined-only) to collate which archive objects contain symbols needed by one of the object files specified:

#!/bin/bash
export LANG=C LC_ALL=C

objs=()
libs=()
for file in "$@" ; do
    [ -r "$file" ] || continue
    if [ "$file" = "${file%.*}.o" ]; then
        objs+=("$file")
    elif [ "$file" = "${file%.*}.a" ]; then
        libs+=("$file")
    else
        printf '%s: Unknown file type. Skipping.\n' "$file" >&2
    fi
done

nm --defined-only "${libs[@]}" 2>/dev/null | awk -v needsyms="$(nm -u "${objs[@]}" 2>/dev/null | sed -ne 's|^[\t ]*U[\t ]*||p')" \
   'BEGIN {
        split("", objlist)
        n = split(needsyms, symlist)
        for (i = 1; i <= n; i++) need[symlist[i]] = ""
    }
    /\.o:$/ {
        name = $0
        sub(/:$/, "", name)
        next
    }

    (NF >= 3) && ($3 in need) {
        need[$3] = name
        objlist[name] = objlist[name] " " $3
    }

    END {
        # Print symbols found and their source objects:
        # for (name in need) printf "%s: %s\n", need[name], name

        # Print source objects from the archive, with symbols used from it:
        for (name in objlist) printf "%s:%s\n", name, objlist[name]
    }'

Files which have a suffix .a are considered archive objects providing the symbols, and files with suffix .o are object files having undefined symbols.

Nominal Animal
  • 38,216
  • 5
  • 59
  • 86