+2009-03-14 Christopher Faylor <me+cygwin@cgf.cx>
+
+ * ldd.cc (longopts): Add --dll option.
+ (get_module_filename): Generalized wrapper function which avoid path
+ length restrictions.
+ (load_dll): Handle special-case of inspecting a DLL.
+ (start_process): Accept an output parameter "isdll". Detect when file
+ to start is a DLL and start a wrapper instead.
+ (print_dlls_and_kill_inferior): When dealing with a DLL, avoid printing
+ everything before the DLL itself first appears. (This is not strictly
+ correct and should be fixed eventually)
+ (report): Deal with DLLs. Don't set a breakpoint for DLLs, just let
+ captive ldd process terminate normally. Pass dll info to
+ print_dlls_and_kill_inferior.
+ (main): Handle special-case "--dll" option by loading the DLL and
+ exiting.
+
2009-03-14 Corinna Vinschen <corinna@vinschen.de>
* path.cc (from_fstab): Use wcstombs/mbstowcs instead of
{"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 HANDLE hProcess;
+static char *
+get_module_filename (HANDLE hp, HMODULE hm)
+{
+ size_t len;
+ char *buf = NULL;
+ DWORD res;
+ for (len = 1024; (res = GetModuleFileNameEx (hp, hm, (buf = (char *) realloc (buf, len)), len)) == len; len += 1024)
+ continue;
+ if (!res)
+ {
+ free (buf);
+ buf = NULL;
+ }
+ return buf;
+}
+
+static char *
+load_dll (const char *fn)
+{
+ char *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;
+}
+
+
static int
-start_process (const char *fn)
+start_process (const char *fn, bool& isdll)
{
STARTUPINFO si = {};
PROCESS_INFORMATION pi;
si.cb = sizeof (si);
- if (CreateProcess (NULL, (CHAR *) fn, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &si, &pi))
+ CHAR *cmd;
+ if (strlen (fn) < 4 || strcasecmp (strchr (fn, '\0') - 4, ".dll") != 0)
{
+ cmd = strdup (fn);
+ isdll = false;
+ }
+ else
+ {
+ cmd = load_dll (fn);
+ isdll = true;
+ }
+ if (CreateProcess (NULL, cmd, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &si, &pi))
+ {
+ free (cmd);
hProcess = pi.hProcess;
DebugSetProcessKillOnExit (true);
return 0;
}
+ free (cmd);
set_errno_and_return (1);
}
return fn;
}
+#define CYGWIN_DLL_LEN (strlen ("\\cygwin1.dll"))
static int
-print_dlls_and_kill_inferior (dlls *dll, const char *process_fn)
+print_dlls_and_kill_inferior (dlls *dll, const char *dllfn, const char *process_fn)
{
+ bool printit = !dllfn;
while ((dll = dll->next))
{
char *fn;
- char fnbuf[MAX_PATH + 1];
- DWORD len = GetModuleFileNameEx (hProcess, (HMODULE) dll->lpBaseOfDll, fnbuf, sizeof(fnbuf) - 1);
- if (!len)
+ char *fullpath = get_module_filename (hProcess, (HMODULE) dll->lpBaseOfDll);
+ if (!fullpath)
fn = strdup ("???");
else
- fn = tocyg (fnbuf);
+ {
+ if (printit)
+ fn = tocyg (fullpath);
+ else if (strcasecmp (fullpath, dllfn) != 0)
+ continue;
+ else
+ {
+ printit = true;
+ free (fullpath);
+ continue;
+ }
+ free (fullpath);
+ }
printf ("\t%s => %s (%p)\n", basename (fn), fn, dll->lpBaseOfDll);
free (fn);
}
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))
print_errno_error_and_return (fn);
- if (!fn || start_process (fn_win))
+ if (!fn || start_process (fn_win, isdll))
print_errno_error_and_return (in_fn);
DEBUG_EVENT ev;
switch (ev.dwDebugEventCode)
{
case LOAD_DLL_DEBUG_EVENT:
- if (++dll_count == 2)
+ if (!isdll && ++dll_count == 2)
get_entry_point ();
dll_last->next = (dlls *) malloc (sizeof (dlls));
dll_last->next->lpBaseOfDll = ev.u.LoadDll.lpBaseOfDll;
dll_last = dll_last->next;
break;
case EXCEPTION_DEBUG_EVENT:
- if (ev.u.Exception.ExceptionRecord.ExceptionCode == STATUS_DLL_NOT_FOUND)
- process_fn = fn_win;
- else
- print_dlls_and_kill_inferior (&dll_list, process_fn);
+ switch (ev.u.Exception.ExceptionRecord.ExceptionCode)
+ {
+ case STATUS_DLL_NOT_FOUND:
+ process_fn = fn_win;
+ break;
+ case STATUS_BREAKPOINT:
+ if (!isdll)
+ print_dlls_and_kill_inferior (&dll_list, isdll ? fn_win : NULL, process_fn);
+ break;
+ }
+ break;
+ case EXIT_PROCESS_DEBUG_EVENT:
+ print_dlls_and_kill_inferior (&dll_list, isdll ? fn_win : NULL, process_fn);
break;
default:
break;
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)
{