Finding DLLs used by a Cygwin program

This post is also available at my personal web site: http://milosophical.me/blog/2007/03/09/finding-dlls-used-by-a-cygwin-program.html


I don’t know how many other people get this issue, but it comes up at my work a bit: Some co-worker asks me if I know of a tool to do such-and-such, and invariably I think “well, that’s easy to do on Unix, but on Windows…”.

Then I remember Cygwin, and quickly find a Cygwin utility that does it, or can be scripted to do it with a small amount of work. So then co-worker asks if they can have a copy of this utility, and of course Cygwin is Free, so I say “sure, go download from www.cygwin.com.” Then they say, “yeah, but I don’t want to install all of Cygwin, can’t you just give me that one program?”

Well, the Cygwin command-line tools can be run from a Windows CMD.EXE shell, so this is quite possible to do. However, they all require the Cygwin POSIX layer, which at a minimum means I should also give them cygwin1.dll. But what other DLLs might the program use?

MJL2008-09-10T14:37+1000 Update: since this page gets a lot of hits, here’s the quick answer: use cygcheck, i.e:

cygcheck grep

Find it under Happy hacker discovery #2. Keep reading if you’re bored…

In the past, I used to just give the person the cygwin1.dll DLL and a program (SPLIT.EXE,say), let the person run it on their computer, explaining that it will crash with an error about a missing DLL. Then they would come back to me and say that they also need cygintl-8.dll and try again. It will crash again because cygintl-8.dll just happens to link to cygiconv-2.dll. After supplying this third DLL file, my co-worker can finally run SPLIT.EXE and break their huge data set into manageable chunks. Everyone’s happy.

The whole process is a bit embarrassing for me and annoying for them (though they could just download the base Cygwin install like I asked…) So, to solve this problem somewhat, I set about thinking “I wonder if there’s a Cygwin tool that can find DLLs in a program?”.

Well, a quick look at info binutils reveals that there is nothing that directly solves my problem of listing which DLLs a program links to. There is this thing called dlltool, but it is for creating PE dynamic libraries, not for listing the libraries used by a PE executable. Bummer.

Happy hacker discovery #0

Well, there is also a tool called strings, which will list text strings in binary files. Now, Windows PE executables happen to contain the name of their linked DLLs as text strings, yay! So all I need to do, is pass strings over a given program, filter for DLL names (to strip out error messages and such) and I have my list.

Oh, but then I’ll need to repeat for each DLL as well. So I need a script to do it:

#!/bin/bash
#
# finds all the DLL files linked by a Win32 PE executable.
# Useful for finding needed DLLs to supply with a Cygwin program when
# sharing just that program with other people.
#

if [ x"$1" = x ]; then
    PROG=`basename $0`
    printf "Usage:  $PROG <command to list DLLs for>\\n"
    printf "        (you should not add '.exe' to the end).\\n"
    exit 1
fi

SEARCH_FILE=`which $1`.exe

# This is not perfect, as it's too permissive, but should be good enough
DLL_REGEXP='^[[:alnum:][:punct:]]*\\.[Dd][Ll][Ll]$'

# We don't care about the Win32 kernel API library...
KERNEL_REGEXP='[Kk][Ee][Rr][Nn][Ee][Ll]32\\.[Dd][Ll][Ll]'

# Get list of program's DLLs:
DLL_LIST=`strings -n 5 $SEARCH_FILE \\
          |grep $DLL_REGEXP \\
          |grep -v $KERNEL_REGEXP`

# Print the DLLs used directly by the program
printf "$SEARCH_FILE:\\n"
for I in $DLL_LIST; do
   printf "\\t$I\\n"
done
printf "\\t(KERNEL32.DLL)\\n\\n"

#Now find each DLL's dependencies (only one level deep though)
for CURR_DLL in $DLL_LIST; do
    SEARCH_DLL=`which $CURR_DLL`
    DLL_DLL_LIST=`strings -n 5 $SEARCH_DLL \\
                  |grep $DLL_REGEXP \\
                  |grep -v $KERNEL_REGEXP \\
                  |grep -v $CURR_DLL`
    printf " -->\\t$CURR_DLL:\\n"
    for I in $DLL_DLL_LIST; do
       printf "\\t\\t$I\\n"
    done
    printf "\\t\\t(KERNEL32.DLL)\\n\\n"
done

There we are, a list of DLLs used by a given program, and the DLLs that those DLLs use.

It’s not perfect: it is not recursive, so only goes one level deep, but this should cover most cases. One day I might come back to this, when I figure out how to write a recursive function in bash.

So now I know which DLLs to give to my co-worker along with the nifty tool they want. But where on my system are they? Cygwin installs most DLLs into /usr/bin. But sometimes they can be in /usr/lib. So do I have to make a search?

Happy hacker discovery #1

Well, no I don’t. Cygwin’s which command also works for DLLs, yay! You just have to go:

  $ which cygwin1.dll
  /usr/bin/cygwin1.dll
  $ which cygintl-8.dll
  /usr/bin/cygintl-8.dll
  $ which cygiconv-2.dll
  /usr/bin/cygiconv-2.dll

There, problem solved.

Happy hacker discovery #2

Update: 2008-01-21 09:56+1100: There’s an awesome tool that comes with Cygwin, called cygcheck(1), that does exactly what I need. Thanks for the tip, Leni! Here’s a sample output for the SPLIT.EXE example:

$ cygcheck split
Found: d:\cygwin\bin\split.exe
d:\cygwin\bin\split.exe
  d:\cygwin\bin\cygwin1.dll
    C:\WINDOWS\system32\ADVAPI32.DLL
      C:\WINDOWS\system32\ntdll.dll
      C:\WINDOWS\system32\KERNEL32.dll
      C:\WINDOWS\system32\RPCRT4.dll
        C:\WINDOWS\system32\Secur32.dll
  d:\cygwin\bin\cygintl-8.dll
    d:\cygwin\bin\cygiconv-2.dll
Advertisements

4 thoughts on “Finding DLLs used by a Cygwin program

  1. Hello,I’m Laurie. I’m sorry to bother you with a problem I met when I install Cygwin: After installing it and I run it, but it poped up the error message “Cygwin doesn’t run, missing cygintl-8.dll”.

    I’m just a beginner with Cygwin. Expect your answer.
    Thank in advance.

    • @Laurie: Hi. I’m not quite sure how to answer this politely. Here goes.

      I’ve never seen this exact error, have you copied it down, or are you paraphrasing? If you installed Cygwin using it’s setup.exe installer, it should be able to run and find the DLLs.

      You will need to run the Cygwin shortcut that the installer placed on your desktop and/or your Quicklaunch in the task bar, as that sets up the Windows environment properly. Don’t just click on one of the programs in c:\cygwin\bin, for instance.

      If that doesn’t work, have a careful read of the installation instructions or subscribe to the mailing list. Please also heed the advice on asking questions in that list and using etiquite. No-one is paid to provide support and hand-holding of Cygwin (especially me, I’m not involved in Cygwin in any way!), “Expect your answer” will not normally get you a response, and might even get you flames or misdirections if people are having a bad day. It’s a free system, provided to you at no cost, you are expected to at least read the instructions.

      Happy hacking!

Comments are closed.