diff --git a/winsup/utils/ChangeLog b/winsup/utils/ChangeLog index 0d8e4681b..65c1207a7 100644 --- a/winsup/utils/ChangeLog +++ b/winsup/utils/ChangeLog @@ -1,3 +1,21 @@ +2009-03-17 Christopher Faylor + + * ldd.cc (load_dll): Start helper program rather than ldd.exe. + (set_entry_point_break): Rename from get_entry_point. + (print_dlls): Rename from print_dlls_and_kill_inferior. Avoid printing + specific dll name if we're looking at a dll. + (report): Always dump dlls on process exit. Don't allow thread + creation. Accommodate get_entry_point rename. + (start_process): Start process with DEBUG_ONLY_THIS_PROCESS. + (longopts): Eliminate "dll" option. + (main): Ditto. + +2009-03-17 Corinna Vinschen + Christopher Faylor + + * ldd.cc: Use wide character Win32 paths throughout. + (load_dll): Fix size expression (add fn) in realloc. + 2009-03-14 Christopher Faylor * ldd.cc (longopts): Add --dll option. diff --git a/winsup/utils/Makefile.in b/winsup/utils/Makefile.in index d4c5309eb..bf5905f9a 100644 --- a/winsup/utils/Makefile.in +++ b/winsup/utils/Makefile.in @@ -57,12 +57,12 @@ CYGWIN_BINS := ${addsuffix .exe,cygpath getfacl ldd kill mkgroup \ # List all binaries to be linked in MinGW mode. Each binary on this list # must have a corresponding .o of the same name. -MINGW_BINS := ${addsuffix .exe,strace cygcheck} +MINGW_BINS := ${addsuffix .exe,cygcheck ldh strace} # List all objects to be compiled in MinGW mode. Any object not on this # list will will be compiled in Cygwin mode implicitly, so there is no # need for a CYGWIN_OBJS. -MINGW_OBJS := bloda.o cygcheck.o dump_setup.o path.o strace.o +MINGW_OBJS := bloda.o cygcheck.o dump_setup.o ldh.o path.o strace.o # If a binary should link in any objects besides the .o with the same # name as the binary, then list those here. @@ -75,6 +75,9 @@ cygpath.exe: ALL_LDFLAGS += -lntdll ldd.exe: ALL_LDFLAGS += -lpsapi +ldh.exe: MINGW_LDLIBS := +ldh.exe: MINGW_LDFLAGS := -nostdlib -lkernel32 + # Check for dumper's requirements and enable it if found. LIBICONV := @libiconv@ libbfd := ${shell $(CC) -B$(bupdir2)/bfd/ --print-file-name=libbfd.a} diff --git a/winsup/utils/ldd.cc b/winsup/utils/ldd.cc index aaebe8413..b880c7cbb 100644 --- a/winsup/utils/ldd.cc +++ b/winsup/utils/ldd.cc @@ -30,6 +30,9 @@ #include #include #include +#include +#undef wcscasecmp /* Disable definition from Cygwin's internal wchar.h. */ +#include #include #include #include @@ -50,13 +53,12 @@ struct option longopts[] = {"help", no_argument, NULL, 0}, {"version", no_argument, NULL, 0}, {"data-relocs", no_argument, NULL, 'd'}, - {"dll", no_argument, NULL, 'D'}, {"function-relocs", no_argument, NULL, 'r'}, {"unused", no_argument, NULL, 'u'}, {0, no_argument, NULL, 0} }; -static int process_file (const char *); +static int process_file (const wchar_t *); static int usage (const char *fmt, ...) @@ -84,13 +86,13 @@ usage (const char *fmt, ...) static HANDLE hProcess; -static char * +static wchar_t * get_module_filename (HANDLE hp, HMODULE hm) { size_t len; - char *buf = NULL; + wchar_t *buf = NULL; DWORD res; - for (len = 1024; (res = GetModuleFileNameEx (hp, hm, (buf = (char *) realloc (buf, len)), len)) == len; len += 1024) + for (len = 1024; (res = GetModuleFileNameExW (hp, hm, (buf = (wchar_t *) realloc (buf, len * sizeof (wchar_t))), len)) == len; len += 1024) continue; if (!res) { @@ -100,33 +102,42 @@ get_module_filename (HANDLE hp, HMODULE hm) return buf; } -static char * -load_dll (const char *fn) +static wchar_t * +load_dll (const wchar_t *fn) { - char *buf = get_module_filename (GetCurrentProcess (), NULL); + wchar_t *buf = get_module_filename (GetCurrentProcess (), NULL); if (!buf) { printf ("ldd: GetModuleFileName returned an error %lu\n", GetLastError ()); exit (1); /* FIXME */ } - buf = (char *) realloc (buf, sizeof (" \"--dll\" \"\"") + strlen (buf)); - strcat (buf, " --dll \""); - strcat (buf, fn); - strcat (buf, "\""); - return buf; + + wchar_t *newbuf = (wchar_t *) malloc ((sizeof (L"\"\" -- ") + wcslen (buf) + wcslen (fn)) * sizeof (wchar_t)); + newbuf[0] = L'"'; + wcscpy (newbuf + 1, buf); + wchar_t *p = wcsstr (newbuf, L"\\ldd"); + if (!p) + { + printf ("ldd: can't parse my own filename \"%ls\"\n", buf); + exit (1); + } + p[3] = L'h'; + wcscat (newbuf, L"\" -- "); + wcscat (newbuf, fn); + free (buf); + return newbuf; } - static int -start_process (const char *fn, bool& isdll) +start_process (const wchar_t *fn, bool& isdll) { - STARTUPINFO si = {}; + STARTUPINFOW si = {}; PROCESS_INFORMATION pi; si.cb = sizeof (si); - CHAR *cmd; - if (strlen (fn) < 4 || strcasecmp (strchr (fn, '\0') - 4, ".dll") != 0) + wchar_t *cmd; + if (wcslen (fn) < 4 || wcscasecmp (wcschr (fn, L'\0') - 4, L".dll") != 0) { - cmd = strdup (fn); + cmd = wcsdup (fn); isdll = false; } else @@ -134,7 +145,7 @@ start_process (const char *fn, bool& isdll) cmd = load_dll (fn); isdll = true; } - if (CreateProcess (NULL, cmd, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &si, &pi)) + if (CreateProcessW (NULL, cmd, NULL, NULL, FALSE, DEBUG_ONLY_THIS_PROCESS, NULL, NULL, &si, &pi)) { free (cmd); hProcess = pi.hProcess; @@ -147,7 +158,7 @@ start_process (const char *fn, bool& isdll) } static int -get_entry_point () +set_entry_point_break () { HMODULE hm; DWORD cb; @@ -172,57 +183,55 @@ struct dlls #define SLOP strlen (" (?)") char * -tocyg (char *win_fn) +tocyg (wchar_t *win_fn) { - win_fn[MAX_PATH] = '\0'; - ssize_t cwlen = cygwin_conv_path (CCP_WIN_A_TO_POSIX, win_fn, NULL, 0); + ssize_t cwlen = cygwin_conv_path (CCP_WIN_W_TO_POSIX, win_fn, NULL, 0); char *fn; if (cwlen <= 0) - fn = strdup (win_fn); + { + int len = wcstombs (NULL, win_fn, 0) + 1; + if ((fn = (char *) malloc (len))) + wcstombs (fn, win_fn, len); + } else { char *fn_cyg = (char *) malloc (cwlen + SLOP + 1); - if (cygwin_conv_path (CCP_WIN_A_TO_POSIX, win_fn, fn_cyg, cwlen) == 0) + if (cygwin_conv_path (CCP_WIN_W_TO_POSIX, win_fn, fn_cyg, cwlen) == 0) fn = fn_cyg; else { free (fn_cyg); - fn = (char *) malloc (strlen (win_fn) + SLOP + 1); - strcpy (fn, win_fn); + int len = wcstombs (NULL, win_fn, 0); + fn = (char *) malloc (len + SLOP + 1); + wcstombs (fn, win_fn, len + SLOP + 1); } } return fn; } -#define CYGWIN_DLL_LEN (strlen ("\\cygwin1.dll")) +#define CYGWIN_DLL_LEN (wcslen (L"\\cygwin1.dll")) static int -print_dlls_and_kill_inferior (dlls *dll, const char *dllfn, const char *process_fn) +print_dlls (dlls *dll, const wchar_t *dllfn, const wchar_t *process_fn) { - bool printit = !dllfn; while ((dll = dll->next)) { char *fn; - char *fullpath = get_module_filename (hProcess, (HMODULE) dll->lpBaseOfDll); + wchar_t *fullpath = get_module_filename (hProcess, (HMODULE) dll->lpBaseOfDll); if (!fullpath) fn = strdup ("???"); + else if (dllfn && wcscmp (fullpath, dllfn) == 0) + { + free (fullpath); + continue; + } else { - if (printit) - fn = tocyg (fullpath); - else if (strcasecmp (fullpath, dllfn) != 0) - continue; - else - { - printit = true; - free (fullpath); - continue; - } + fn = tocyg (fullpath); free (fullpath); } printf ("\t%s => %s (%p)\n", basename (fn), fn, dll->lpBaseOfDll); free (fn); } - TerminateProcess (hProcess, 0); if (process_fn) return process_file (process_fn); return 0; @@ -237,14 +246,21 @@ report (const char *in_fn, bool multiple) if (!fn) print_errno_error_and_return (in_fn); - ssize_t len = cygwin_conv_path (CCP_POSIX_TO_WIN_A, fn, NULL, 0); + ssize_t len = cygwin_conv_path (CCP_POSIX_TO_WIN_W, fn, NULL, 0); if (len <= 0) print_errno_error_and_return (fn); bool isdll; - char fn_win[len + 1]; - if (cygwin_conv_path (CCP_POSIX_TO_WIN_A, fn, fn_win, len)) + wchar_t fn_win_buf[len + 1]; + if (cygwin_conv_path (CCP_POSIX_TO_WIN_W, fn, fn_win_buf, len)) print_errno_error_and_return (fn); + wchar_t *fn_win = fn_win_buf + 4; + + if (wcsncmp (fn_win_buf, L"\\\\?\\UNC\\", 8) == 0) + { + fn_win += 2; + *fn_win = L'\\'; + } if (!fn || start_process (fn_win, isdll)) print_errno_error_and_return (in_fn); @@ -255,25 +271,18 @@ report (const char *in_fn, bool multiple) dlls dll_list = {}; dlls *dll_last = &dll_list; - const char *process_fn = NULL; + const wchar_t *process_fn = NULL; while (1) { - if (WaitForDebugEvent (&ev, 1000)) - /* ok */; - else - switch (GetLastError ()) - { - case WAIT_TIMEOUT: - continue; - default: - usleep (100000); - goto out; - } + bool exitnow = false; + DWORD cont = DBG_CONTINUE; + if (!WaitForDebugEvent (&ev, INFINITE)) + break; switch (ev.dwDebugEventCode) { case LOAD_DLL_DEBUG_EVENT: if (!isdll && ++dll_count == 2) - get_entry_point (); + set_entry_point_break (); dll_last->next = (dlls *) malloc (sizeof (dlls)); dll_last->next->lpBaseOfDll = ev.u.LoadDll.lpBaseOfDll; dll_last->next->next = NULL; @@ -287,21 +296,27 @@ report (const char *in_fn, bool multiple) break; case STATUS_BREAKPOINT: if (!isdll) - print_dlls_and_kill_inferior (&dll_list, isdll ? fn_win : NULL, process_fn); + cont = DBG_EXCEPTION_NOT_HANDLED; break; } break; + case CREATE_THREAD_DEBUG_EVENT: + TerminateProcess (hProcess, 0); + break; case EXIT_PROCESS_DEBUG_EVENT: - print_dlls_and_kill_inferior (&dll_list, isdll ? fn_win : NULL, process_fn); + print_dlls (&dll_list, isdll ? fn_win : NULL, process_fn); + exitnow = true; break; default: break; } - if (!ContinueDebugEvent (ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE)) + if (!ContinueDebugEvent (ev.dwProcessId, ev.dwThreadId, cont)) { cygwin_internal (CW_SETERRNO, __FILE__, __LINE__ - 2); print_errno_error_and_return (in_fn); } + if (exitnow) + break; } out: @@ -314,6 +329,7 @@ main (int argc, char **argv) { int optch; int index; + setlocale (LC_ALL, ""); while ((optch = getopt_long (argc, argv, "dru", longopts, &index)) != -1) switch (optch) { @@ -322,10 +338,6 @@ main (int argc, char **argv) case 'u': usage ("option not implemented `-%c'", optch); exit (1); - case 'D': - if (!LoadLibrary (argv[optind])) - exit (1); - exit (0); case 0: if (index == 1) { @@ -403,16 +415,21 @@ dump_import_directory (const void *const section_base, /* continue until address inaccessible or there's no DLL name */ for (; !IsBadReadPtr (imp, sizeof (*imp)) && imp->Name; imp++) { - char full_path[MAX_PATH]; - char *dummy; + wchar_t full_path[PATH_MAX]; + wchar_t *dummy; char *fn = (char *) adr (imp->Name); if (saw_file (fn)) continue; + int len = mbstowcs (NULL, fn, 0); + if (len <= 0) + continue; + wchar_t fnw[len + 1]; + mbstowcs (fnw, fn, len + 1); /* output DLL's name */ char *print_fn; - if (!SearchPath (NULL, fn, NULL, sizeof (full_path), full_path, &dummy)) + if (!SearchPathW (NULL, fnw, NULL, PATH_MAX, full_path, &dummy)) { print_fn = strdup ("not found"); printing = true; @@ -437,14 +454,14 @@ dump_import_directory (const void *const section_base, return pointer to loaded file 0 if no success */ static void * -map_file (const char *filename) +map_file (const wchar_t *filename) { HANDLE hFile, hMapping; void *basepointer; - if ((hFile = CreateFile (filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, + if ((hFile = CreateFileW (filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0)) == INVALID_HANDLE_VALUE) { - fprintf (stderr, "couldn't open %s\n", filename); + fprintf (stderr, "couldn't open %ls\n", filename); return 0; } if (!(hMapping = CreateFileMapping (hFile, 0, PAGE_READONLY | SEC_COMMIT, 0, 0, 0))) @@ -515,7 +532,7 @@ get_directory_index (const unsigned dir_rva, /* dump imports of a single file Returns 0 if successful, !=0 else */ static int -process_file (const char *filename) +process_file (const wchar_t *filename) { void *basepointer; /* Points to loaded PE file * This is memory mapped stuff