Cygwin: ldd: Try harder to get dll names

Borrow a trick from strace to lessen occurrences of "??? => ???" in ldd
output.  Specifically, if the module name isn't found in the usual place
in the mapped image, use the file handle we have to look up the name.
This commit is contained in:
Mark Geisert 2019-08-14 22:59:43 -07:00 committed by Corinna Vinschen
parent 3a929f27f8
commit e3ca53d9db
2 changed files with 44 additions and 2 deletions

View File

@ -101,7 +101,7 @@ cygpath.exe: CYGWIN_LDFLAGS += -lcygwin -luserenv -lntdll
ps.exe: CYGWIN_LDFLAGS += -lcygwin -lpsapi -lntdll
strace.exe: MINGW_LDFLAGS += -lntdll
ldd.exe:CYGWIN_LDFLAGS += -lpsapi
ldd.exe:CYGWIN_LDFLAGS += -lpsapi -lntdll
pldd.exe: CYGWIN_LDFLAGS += -lpsapi
minidumper.exe: CYGWIN_LDFLAGS += -ldbghelp

View File

@ -39,6 +39,7 @@
#define _WIN32_WINNT 0x0a00
#include <windows.h>
#include <winternl.h>
#include <imagehlp.h>
#include <psapi.h>
@ -55,6 +56,7 @@ struct option longopts[] =
const char *opts = "dhruvV";
static int process_file (const wchar_t *);
static void *drive_map;
static int
error (const char *fmt, ...)
@ -152,6 +154,32 @@ get_module_filename (HANDLE hp, HMODULE hm)
return buf;
}
static BOOL
GetFileNameFromHandle(HANDLE hFile, WCHAR pszFilename[MAX_PATH+1])
{
BOOL result = FALSE;
ULONG len = 0;
OBJECT_NAME_INFORMATION *ntfn = (OBJECT_NAME_INFORMATION *) alloca (65536);
NTSTATUS status = NtQueryObject (hFile, ObjectNameInformation,
ntfn, 65536, &len);
if (NT_SUCCESS (status))
{
PWCHAR win32path = ntfn->Name.Buffer;
win32path[ntfn->Name.Length / sizeof (WCHAR)] = L'\0';
/* NtQueryObject returns a native NT path. (Try to) convert to Win32. */
if (!drive_map)
drive_map = (void *) cygwin_internal (CW_ALLOC_DRIVE_MAP);
if (drive_map)
win32path = (PWCHAR) cygwin_internal (CW_MAP_DRIVE_MAP, drive_map,
win32path);
pszFilename[0] = L'\0';
wcsncat (pszFilename, win32path, MAX_PATH);
result = TRUE;
}
return result;
}
static wchar_t *
load_dll (const wchar_t *fn)
{
@ -215,6 +243,7 @@ start_process (const wchar_t *fn, bool& isdll)
struct dlls
{
LPVOID lpBaseOfDll;
HANDLE hFile;
struct dlls *next;
};
@ -256,7 +285,17 @@ print_dlls (dlls *dll, const wchar_t *dllfn, const wchar_t *process_fn)
char *fn;
wchar_t *fullpath = get_module_filename (hProcess, (HMODULE) dll->lpBaseOfDll);
if (!fullpath)
fn = strdup ("???");
{
// if no path found yet, try getting it from an open handle to the DLL
wchar_t dllname[MAX_PATH+1];
if (GetFileNameFromHandle (dll->hFile, dllname))
{
fn = tocyg (dllname);
saw_file (basename (fn));
}
else
fn = strdup ("???");
}
else if (dllfn && wcscmp (fullpath, dllfn) == 0)
{
free (fullpath);
@ -340,6 +379,7 @@ report (const char *in_fn, bool multiple)
case LOAD_DLL_DEBUG_EVENT:
dll_last->next = (dlls *) malloc (sizeof (dlls));
dll_last->next->lpBaseOfDll = ev.u.LoadDll.lpBaseOfDll;
dll_last->next->hFile = ev.u.LoadDll.hFile;
dll_last->next->next = NULL;
dll_last = dll_last->next;
break;
@ -423,6 +463,8 @@ main (int argc, char **argv)
while ((fn = *argv++))
if (report (fn, multiple))
ret = 1;
if (drive_map)
cygwin_internal (CW_FREE_DRIVE_MAP, drive_map);
exit (ret);
}