+/* Encapsulate the information required in a call to
+ symbol_file_add_args */
+struct safe_symbol_file_add_args
+{
+ char *name;
+ int from_tty;
+ struct section_addr_info *addrs;
+ int mainline;
+ int flags;
+ struct ui_file *err, *out;
+ struct objfile *ret;
+};
+
+/* Maintain a linked list of "so" information. */
+struct so_stuff
+{
+ struct so_stuff *next;
+ DWORD load_addr;
+ int loaded;
+ struct objfile *objfile;
+ char name[1];
+} solib_start, *solib_end;
+
+/* Call symbol_file_add with stderr redirected. We don't care if there
+ are errors. */
+static int
+safe_symbol_file_add_stub (void *argv)
+{
+#define p ((struct safe_symbol_file_add_args *)argv)
+ struct so_stuff *so = &solib_start;
+
+ while ((so = so->next))
+ if (so->loaded && strcasecmp (so->name, p->name) == 0)
+ return 0;
+ p->ret = symbol_file_add (p->name, p->from_tty, p->addrs, p->mainline, p->flags);
+ return !!p->ret;
+#undef p
+}
+
+/* Restore gdb's stderr after calling symbol_file_add */
+static void
+safe_symbol_file_add_cleanup (void *p)
+{
+#define sp ((struct safe_symbol_file_add_args *)p)
+ gdb_flush (gdb_stderr);
+ gdb_flush (gdb_stdout);
+ ui_file_delete (gdb_stderr);
+ ui_file_delete (gdb_stdout);
+ gdb_stderr = sp->err;
+ gdb_stdout = sp->out;
+#undef sp
+}
+
+/* symbol_file_add wrapper that prevents errors from being displayed. */
+static struct objfile *
+safe_symbol_file_add (char *name, int from_tty,
+ struct section_addr_info *addrs,
+ int mainline, int flags)
+{
+ struct safe_symbol_file_add_args p;
+ struct cleanup *cleanup;
+
+ cleanup = make_cleanup (safe_symbol_file_add_cleanup, &p);
+
+ p.err = gdb_stderr;
+ p.out = gdb_stdout;
+ gdb_flush (gdb_stderr);
+ gdb_flush (gdb_stdout);
+ gdb_stderr = ui_file_new ();
+ gdb_stdout = ui_file_new ();
+ p.name = name;
+ p.from_tty = from_tty;
+ p.addrs = addrs;
+ p.mainline = mainline;
+ p.flags = flags;
+ catch_errors (safe_symbol_file_add_stub, &p, "", RETURN_MASK_ERROR);
+
+ do_cleanups (cleanup);
+ return p.ret;
+}
+
+/* Remember the maximum DLL length for printing in info dll command. */
+int max_dll_name_len;
+
+static void
+register_loaded_dll (const char *name, DWORD load_addr)
+{
+ struct so_stuff *so;
+ char ppath[MAX_PATH + 1];
+ char buf[MAX_PATH + 1];
+ char cwd[MAX_PATH + 1];
+ char *p;
+ WIN32_FIND_DATA w32_fd;
+ HANDLE h = FindFirstFile(name, &w32_fd);
+ size_t len;
+
+ if (h == INVALID_HANDLE_VALUE)
+ strcpy (buf, name);
+ else
+ {
+ FindClose (h);
+ strcpy (buf, name);
+ if (GetCurrentDirectory (MAX_PATH + 1, cwd))
+ {
+ p = strrchr (buf, '\\');
+ if (p)
+ p[1] = '\0';
+ SetCurrentDirectory (buf);
+ GetFullPathName (w32_fd.cFileName, MAX_PATH, buf, &p);
+ SetCurrentDirectory (cwd);
+ }
+ }
+
+ cygwin_conv_to_posix_path (buf, ppath);
+ so = (struct so_stuff *) xmalloc (sizeof (struct so_stuff) + strlen (ppath) + 8 + 1);
+ so->loaded = 0;
+ so->load_addr = load_addr;
+ so->next = NULL;
+ so->objfile = NULL;
+ strcpy (so->name, ppath);
+
+ solib_end->next = so;
+ solib_end = so;
+ len = strlen (ppath);
+ if (len > max_dll_name_len)
+ max_dll_name_len = len;
+}
+
+char *
+get_image_name (HANDLE h, void *address, int unicode)
+{
+ static char buf[(2 * MAX_PATH) + 1];
+ DWORD size = unicode ? sizeof (WCHAR) : sizeof (char);
+ char *address_ptr;
+ int len = 0;
+ char b[2];
+ DWORD done;
+
+ /* Attempt to read the name of the dll that was detected.
+ This is documented to work only when actively debugging
+ a program. It will not work for attached processes. */
+ if (address == NULL)
+ return NULL;
+
+ ReadProcessMemory (h, address, &address_ptr, sizeof (address_ptr), &done);
+
+ /* See if we could read the address of a string, and that the
+ address isn't null. */
+
+ if (done != sizeof (address_ptr) || !address_ptr)
+ return NULL;
+
+ /* Find the length of the string */
+ do
+ {
+ ReadProcessMemory (h, address_ptr + len * size, &b, size, &done);
+ len++;
+ }
+ while ((b[0] != 0 || b[size - 1] != 0) && done == size);
+
+ if (!unicode)
+ ReadProcessMemory (h, address_ptr, buf, len, &done);
+ else
+ {
+ WCHAR *unicode_address = (WCHAR *) alloca (len * sizeof (WCHAR));
+ ReadProcessMemory (h, address_ptr, unicode_address, len * sizeof (WCHAR),
+ &done);
+
+ WideCharToMultiByte (CP_ACP, 0, unicode_address, len, buf, len, 0, 0);
+ }
+
+ return buf;
+}
+