]> sourceware.org Git - newlib-cygwin.git/blobdiff - winsup/utils/ldd.cc
Cygwin: add 3.2.1 release file and add fixes up to this point
[newlib-cygwin.git] / winsup / utils / ldd.cc
index de98658bcaa9f7f11b22b68cc96ab87f374dd044..1e1863c1c0a6c3bb3fc755695330483ccb2214a2 100644 (file)
@@ -5,11 +5,11 @@
   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:
 
-       * Redistributions of source code must retain the above copyright
-       notice, this list of conditions and the following disclaimer.
-       * Neither the name of the owner nor the names of its
-       contributors may be used to endorse or promote products derived from
-       this software without specific prior written permission.
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
 
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 #include <unistd.h>
 #include <libgen.h>
 
-#define _WIN32_WINNT 0x0501
+#define _WIN32_WINNT 0x0a00
 #include <windows.h>
+#include <winternl.h>
 #include <imagehlp.h>
 #include <psapi.h>
 
-#ifndef STATUS_DLL_NOT_FOUND
-#define STATUS_DLL_NOT_FOUND (0xC0000135L)
-#endif
-
 struct option longopts[] =
 {
   {"help", no_argument, NULL, 'h'},
@@ -59,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, ...)
@@ -71,7 +69,7 @@ error (const char *fmt, ...)
   exit (1);
 }
 
-static void
+static void __attribute__ ((__noreturn__))
 usage ()
 {
   printf ("Usage: %s [OPTION]... FILE...\n\
@@ -87,6 +85,7 @@ Print shared library dependencies\n\
   -v, --verbose           print all information\n\
                           (currently unimplemented)\n",
           program_invocation_short_name);
+  exit (0);
 }
 
 static void
@@ -156,6 +155,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)
 {
@@ -216,28 +241,10 @@ start_process (const wchar_t *fn, bool& isdll)
   set_errno_and_return (1);
 }
 
-static int
-set_entry_point_break ()
-{
-  HMODULE hm;
-  DWORD cbe;
-  SIZE_T cbw;
-  if (!EnumProcessModules (hProcess, &hm, sizeof (hm), &cbe) || !cbe)
-    set_errno_and_return (1);
-
-  MODULEINFO mi = {};
-  if (!GetModuleInformation (hProcess, hm, &mi, sizeof (mi)) || !mi.EntryPoint)
-    set_errno_and_return (1);
-
-  static const unsigned char int3 = 0xcc;
-  if (!WriteProcessMemory (hProcess, mi.EntryPoint, &int3, 1, &cbw) || cbw != 1)
-    set_errno_and_return (1);
-  return 0;
-}
-
 struct dlls
   {
     LPVOID lpBaseOfDll;
+    HANDLE hFile;
     struct dlls *next;
   };
 
@@ -279,7 +286,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);
@@ -322,11 +339,12 @@ report (const char *in_fn, bool multiple)
 
   DEBUG_EVENT ev;
 
-  unsigned dll_count = 0;
-
   dlls dll_list = {};
   dlls *dll_last = &dll_list;
   const wchar_t *process_fn = NULL;
+
+  int res = 0;
+
   while (1)
     {
       bool exitnow = false;
@@ -335,30 +353,63 @@ report (const char *in_fn, bool multiple)
        break;
       switch (ev.dwDebugEventCode)
        {
+       case CREATE_PROCESS_DEBUG_EVENT:
+         if (!isdll)
+           {
+             PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER) alloca (4096);
+             PIMAGE_NT_HEADERS nt_header;
+             PVOID entry_point;
+             static const unsigned char int3 = 0xcc;
+             SIZE_T bytes;
+
+             if (!ReadProcessMemory (hProcess,
+                                     ev.u.CreateProcessInfo.lpBaseOfImage,
+                                     dos_header, 4096, &bytes))
+               print_errno_error_and_return (in_fn);
+
+             nt_header = PIMAGE_NT_HEADERS (PBYTE (dos_header)
+                                            + dos_header->e_lfanew);
+             entry_point = (PVOID)
+                 ((caddr_t) ev.u.CreateProcessInfo.lpBaseOfImage
+                  + nt_header->OptionalHeader.AddressOfEntryPoint);
+
+             if (!WriteProcessMemory (hProcess, entry_point, &int3, 1, &bytes))
+               print_errno_error_and_return (in_fn);
+           }
+         break;
        case LOAD_DLL_DEBUG_EVENT:
-         if (!isdll && ++dll_count == 2)
-           set_entry_point_break ();
          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;
        case EXCEPTION_DEBUG_EVENT:
          switch (ev.u.Exception.ExceptionRecord.ExceptionCode)
            {
+           case STATUS_ENTRYPOINT_NOT_FOUND:
+             /* A STATUS_ENTRYPOINT_NOT_FOUND might be encountered right after
+                loading all DLLs.  We have to handle it here, otherwise ldd
+                runs into an endless loop. */
+             goto print_and_exit;
            case STATUS_DLL_NOT_FOUND:
              process_fn = fn_win;
              break;
            case STATUS_BREAKPOINT:
              if (!isdll)
-               cont = DBG_EXCEPTION_NOT_HANDLED;
+               TerminateProcess (hProcess, 0);
              break;
            }
-         break;
-       case CREATE_THREAD_DEBUG_EVENT:
-         TerminateProcess (hProcess, 0);
+         if (ev.u.Exception.ExceptionRecord.ExceptionFlags &
+             EXCEPTION_NONCONTINUABLE) {
+           res = 1;
+           goto print_and_exit;
+         }
          break;
        case EXIT_PROCESS_DEBUG_EVENT:
+         if (ev.u.ExitProcess.dwExitCode != 0)
+           process_fn = fn_win;
+print_and_exit:
          print_dlls (&dll_list, isdll ? fn_win : NULL, process_fn);
          exitnow = true;
          break;
@@ -374,7 +425,7 @@ report (const char *in_fn, bool multiple)
        break;
     }
 
-  return 0;
+  return res;
 }
 
 int
@@ -396,7 +447,6 @@ main (int argc, char **argv)
        exit (1);
       case 'h':
        usage ();
-       exit (0);
       case 'V':
        print_version ();
        return 0;
@@ -415,6 +465,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);
 }
 
This page took 0.028823 seconds and 5 git commands to generate.