* dbxread.c, partial-stab.h (near N_SO): SO stabs with blank
authorStu Grossman <grossman@cygnus>
Tue, 28 Jun 1994 23:36:52 +0000 (23:36 +0000)
committerStu Grossman <grossman@cygnus>
Tue, 28 Jun 1994 23:36:52 +0000 (23:36 +0000)
names mean end of .o file.
* infrun.c (wait_for_inferior):  Clean up multi-thread logic near
top of routine.  Handle new thread notification cleanly.
* lynx-nat.c (child_wait):  General cleanups, handle new LynxOS
thread notification scheme.
* (child_resume):  General cleanups, handle resumption of all
threads properly.

gdb/ChangeLog
gdb/dbxread.c
gdb/infrun.c
gdb/lynx-nat.c

index 4d84f37d2b2a4118d5ef1467fa4e7b2b9304a69d..2a65fb5b9d2f780fde01c4a0c374d3d1af8cc707 100644 (file)
@@ -1,3 +1,14 @@
+Tue Jun 28 15:28:01 1994  Stu Grossman  (grossman@cygnus.com)
+
+       * dbxread.c, partial-stab.h (near N_SO):  SO stabs with blank
+       names mean end of .o file.
+       * infrun.c (wait_for_inferior):  Clean up multi-thread logic near
+       top of routine.  Handle new thread notification cleanly.
+       * lynx-nat.c (child_wait):  General cleanups, handle new LynxOS
+       thread notification scheme.
+       * (child_resume):  General cleanups, handle resumption of all
+       threads properly.
+
 Mon Jun 27 09:57:23 1994  Steve Chamberlain  (sac@cirdan.cygnus.com)
 
        * ser-go32.c: Rewrite to run under windows.
index a77f646f107d1c9a60cb7e7416b55faa49d5b768..5445c8a0a5c5559cb75f9944c11055f608821d66 100644 (file)
@@ -1903,11 +1903,16 @@ process_one_symbol (type, desc, valu, name, section_offsets, objfile)
          end_symtab (valu, 0, 0, objfile, SECT_OFF_TEXT);
          end_stabs ();
        }
+
+      /* Null name means this just marks the end of text for this .o file.
+        Don't start a new symtab in this case.  */
+      if (*name == '\000')
+       break;
+
       start_stabs ();
       start_symtab (name, NULL, valu);
       break;
 
-
     case N_SOL:
       /* This type of symbol indicates the start of data for
         a sub-source-file, one whose contents were copied or
@@ -2358,12 +2363,13 @@ elfstab_build_psymtabs (objfile, section_offsets, mainline,
 
 void
 stabsect_build_psymtabs (objfile, section_offsets, mainline, stab_name,
-                        stabstr_name)
+                        stabstr_name, text_name)
      struct objfile *objfile;
      struct section_offsets *section_offsets;
      int mainline;
      char *stab_name;
      char *stabstr_name;
+     char *text_name;
 {
   int val;
   bfd *sym_bfd = objfile->obfd;
@@ -2384,9 +2390,9 @@ stabsect_build_psymtabs (objfile, section_offsets, mainline, stab_name,
   objfile->sym_stab_info = (PTR) xmalloc (sizeof (struct dbx_symfile_info));
   memset (DBX_SYMFILE_INFO (objfile), 0, sizeof (struct dbx_symfile_info));
 
-  DBX_TEXT_SECT (objfile) = bfd_get_section_by_name (sym_bfd, ".text");
+  DBX_TEXT_SECT (objfile) = bfd_get_section_by_name (sym_bfd, text_name);
   if (!DBX_TEXT_SECT (objfile))
-    error ("Can't find .text section in symbol file");
+    error ("Can't find %s section in symbol file", text_name);
 
   DBX_SYMBOL_SIZE    (objfile) = sizeof (struct external_nlist);
   DBX_SYMCOUNT       (objfile) = bfd_section_size (sym_bfd, stabsect)
@@ -2422,36 +2428,6 @@ stabsect_build_psymtabs (objfile, section_offsets, mainline, stab_name,
   dbx_symfile_read (objfile, section_offsets, 0);
 }
 \f
-/* Scan and build partial symbols for a SOM symbol file.
-   This SOM file has already been processed to get its minimal symbols.
-
-   OBJFILE is the object file we are reading symbols from.
-   ADDR is the address relative to which the symbols are (e.g.
-   the base address of the text segment).
-   MAINLINE is true if we are reading the main symbol
-   table (as opposed to a shared lib or dynamically loaded file).
-
-   */
-
-void
-somstab_build_psymtabs (objfile, section_offsets, mainline)
-     struct objfile *objfile;
-     struct section_offsets *section_offsets;
-     int mainline;
-{
-  free_header_files ();
-  init_header_files ();
-
-  /* This is needed to debug objects assembled with gas2.  */
-  processing_acc_compilation = 1;
-
-  /* In a SOM file, we've already installed the minimal symbols that came
-     from the SOM (non-stab) symbol table, so always act like an
-     incremental load here. */
-
-  dbx_symfile_read (objfile, section_offsets, mainline);
-}
-\f
 /* Parse the user's idea of an offset for dynamic linking, into our idea
    of how to represent it for fast symbol reading.  */
 
index 08e3bfdefdeba14abc83689542fd8a695c0c9ef4..9a9e35c7e0805e752dc46e37e3f8cbc8a4487803 100644 (file)
@@ -294,6 +294,24 @@ proceed (addr, siggnal, step)
   else
     write_pc (addr);
 
+#ifdef PREPARE_TO_PROCEED
+  /* In a multi-threaded task we may select another thread and then continue.
+     
+     In this case the thread that stopped at a breakpoint will immediately
+     cause another stop, if it is not stepped over first. On the other hand,
+     if (ADDR != -1) we only want to single step over the breakpoint if we did
+     switch to another thread.
+
+     If we are single stepping, don't do any of the above.
+     (Note that in the current implementation single stepping another
+     thread after a breakpoint and then continuing will cause the original
+     breakpoint to be hit again, but you can always continue, so it's not
+     a big deal.)  */
+
+  if (! step && PREPARE_TO_PROCEED && breakpoint_here_p (read_pc ()))
+    oneproc = 1;
+#endif /* PREPARE_TO_PROCEED */
+
   if (trap_expected_after_continue)
     {
       /* If (step == 0), a trap will be automatically generated after
@@ -437,11 +455,25 @@ wait_for_inferior ()
 
   while (1)
     {
+      /* We have to invalidate the registers BEFORE calling target_wait because
+        they can be loaded from the target while in target_wait.  This makes
+        remote debugging a bit more efficient for those targets that provide
+        critical registers as part of their normal status mechanism. */
+
+      registers_changed ();
+
       pid = target_wait (-1, &w);
 
-      /* Clean up saved state that will become invalid.  */
       flush_cached_frames ();
-      registers_changed ();
+
+      /* If it's a new process, add it to the thread database */
+
+      if (pid != inferior_pid
+         && !in_thread_list (pid))
+       {
+         fprintf_unfiltered (gdb_stderr, "[New %s]\n", target_pid_to_str (pid));
+         add_thread (pid);
+       }
 
       switch (w.kind)
        {
@@ -507,125 +539,104 @@ wait_for_inferior ()
 
       stop_signal = w.value.sig;
 
-      if (pid != inferior_pid)
-       {
-         int save_pid = inferior_pid;
+      stop_pc = read_pc_pid (pid);
 
-         inferior_pid = pid;   /* Setup for target memory/regs */
-         registers_changed ();
-         stop_pc = read_pc ();
-         inferior_pid = save_pid;
-         registers_changed ();
-       }
-      else
-       stop_pc = read_pc ();
+      /* See if a thread hit a thread-specific breakpoint that was meant for
+        another thread.  If so, then step that thread past the breakpoint,
+        and continue it.  */
 
       if (stop_signal == TARGET_SIGNAL_TRAP
+         && breakpoints_inserted
          && breakpoint_here_p (stop_pc - DECR_PC_AFTER_BREAK))
        {
+         random_signal = 0;
          if (!breakpoint_thread_match (stop_pc - DECR_PC_AFTER_BREAK, pid))
            {
              /* Saw a breakpoint, but it was hit by the wrong thread.  Just continue. */
-             if (breakpoints_inserted)
-               {
-                 if (pid != inferior_pid)
-                   {
-                     int save_pid = inferior_pid;
-
-                     inferior_pid = pid;
-                     registers_changed ();
-                     write_pc (stop_pc - DECR_PC_AFTER_BREAK);
-                     inferior_pid = save_pid;
-                     registers_changed ();
-                   }
-                 else
-                   write_pc (stop_pc - DECR_PC_AFTER_BREAK);
-
-                 remove_breakpoints ();
-                 target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
-                 /* FIXME: What if a signal arrives instead of the single-step
-                    happening?  */
-                 target_wait (pid, &w);
-                 insert_breakpoints ();
-               }
-             target_resume (-1, 0, TARGET_SIGNAL_0);
+             write_pc (stop_pc - DECR_PC_AFTER_BREAK);
+
+             remove_breakpoints ();
+             target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
+             /* FIXME: What if a signal arrives instead of the single-step
+                happening?  */
+             target_wait (pid, &w);
+             insert_breakpoints ();
+             target_resume (pid, 0, TARGET_SIGNAL_0);
              continue;
            }
-         else
-           if (pid != inferior_pid)
-             goto switch_thread;
        }
+      else
+       random_signal = 1;
+
+      /* See if something interesting happened to the non-current thread.  If
+         so, then switch to that thread, and eventually give control back to
+        the user.  */
 
       if (pid != inferior_pid)
        {
          int printed = 0;
 
-         if (!in_thread_list (pid))
+         /* If it's a random signal for a non-current thread, notify user
+            if he's expressed an interest.  */
+
+         if (random_signal
+             && signal_print[stop_signal])
            {
-             fprintf_unfiltered (gdb_stderr, "[New %s]\n", target_pid_to_str (pid));
-             add_thread (pid);
+             printed = 1;
+             target_terminal_ours_for_output ();
+             printf_filtered ("\nProgram received signal %s, %s.\n",
+                              target_signal_to_name (stop_signal),
+                              target_signal_to_string (stop_signal));
+             gdb_flush (gdb_stdout);
+           }
+
+         /* If it's not SIGTRAP and not a signal we want to stop for, then
+            continue the thread. */
+
+         if (stop_signal != TARGET_SIGNAL_TRAP
+             && !signal_stop[stop_signal])
+           {
+             if (printed)
+               target_terminal_inferior ();
 
-             target_resume (-1, 0, TARGET_SIGNAL_0);
+             /* Clear the signal if it should not be passed.  */
+             if (signal_program[stop_signal] == 0)
+               stop_signal = TARGET_SIGNAL_0;
+
+             target_resume (pid, 0, stop_signal);
              continue;
            }
-         else
+
+         /* It's a SIGTRAP or a signal we're interested in.  Switch threads,
+            and fall into the rest of wait_for_inferior().  */
+
+         inferior_pid = pid;
+         printf_filtered ("[Switching to %s]\n", target_pid_to_str (pid));
+
+         flush_cached_frames ();
+         trap_expected = 0;
+         if (step_resume_breakpoint)
            {
-             if (signal_print[stop_signal])
-               {
-                 printed = 1;
-                 target_terminal_ours_for_output ();
-                 printf_filtered ("\nProgram received signal %s, %s.\n",
-                                  target_signal_to_name (stop_signal),
-                                  target_signal_to_string (stop_signal));
-                 gdb_flush (gdb_stdout);
-               }
-
-             if (stop_signal == TARGET_SIGNAL_TRAP
-                 || signal_stop[stop_signal])
-               {
-switch_thread:
-                 inferior_pid = pid;
-                 printf_filtered ("[Switching to %s]\n", target_pid_to_str (pid));
-
-                 flush_cached_frames ();
-                 registers_changed ();
-                 trap_expected = 0;
-                 if (step_resume_breakpoint)
-                   {
-                     delete_breakpoint (step_resume_breakpoint);
-                     step_resume_breakpoint = NULL;
-                   }
-
-                 /* Not sure whether we need to blow this away too,
-                    but probably it is like the step-resume
-                    breakpoint.  */
-                 if (through_sigtramp_breakpoint)
-                   {
-                     delete_breakpoint (through_sigtramp_breakpoint);
-                     through_sigtramp_breakpoint = NULL;
-                   }
-                 prev_pc = 0;
-                 prev_sp = 0;
-                 prev_func_name = NULL;
-                 step_range_start = 0;
-                 step_range_end = 0;
-                 step_frame_address = 0;
-                 handling_longjmp = 0;
-                 another_trap = 0;
-               }
-             else
-               {
-                 if (printed)
-                   target_terminal_inferior ();
-
-                 /* Clear the signal if it should not be passed.  */
-                 if (signal_program[stop_signal] == 0)
-                   stop_signal = TARGET_SIGNAL_0;
-
-                 target_resume (pid, 0, stop_signal);
-                 continue;
-               }
+             delete_breakpoint (step_resume_breakpoint);
+             step_resume_breakpoint = NULL;
            }
+
+         /* Not sure whether we need to blow this away too,
+            but probably it is like the step-resume
+            breakpoint.  */
+         if (through_sigtramp_breakpoint)
+           {
+             delete_breakpoint (through_sigtramp_breakpoint);
+             through_sigtramp_breakpoint = NULL;
+           }
+         prev_pc = 0;
+         prev_sp = 0;
+         prev_func_name = NULL;
+         step_range_start = 0;
+         step_range_end = 0;
+         step_frame_address = 0;
+         handling_longjmp = 0;
+         another_trap = 0;
        }
 
 #ifdef NO_SINGLE_STEP
@@ -1061,12 +1072,19 @@ switch_thread:
          goto keep_going;
        }
 
+#if 1
       if (stop_func_start)
        {
+         struct symtab *s;
+
          /* Do this after the IN_SIGTRAMP check; it might give
             an error.  */
          prologue_pc = stop_func_start;
-         SKIP_PROLOGUE (prologue_pc);
+
+         /* Don't skip the prologue if this is assembly source */
+         s = find_pc_symtab (stop_pc);
+         if (s && s->language != language_asm)
+           SKIP_PROLOGUE (prologue_pc);
        }
 
       if ((/* Might be a non-recursive call.  If the symbols are missing
@@ -1105,6 +1123,14 @@ switch_thread:
                 which can no longer happen here as long as the
                 handling_longjmp stuff is working.  */
              ))
+#else
+/* This is experimental code which greatly simplifies the subroutine call
+   test.  I've actually tested on the Alpha, and it works great. -Stu */
+
+       if (in_prologue (stop_pc, NULL)
+           || (prev_func_start != 0
+               && stop_func_start == 0))
+#endif
        {
          /* It's a subroutine call.  */
 
@@ -1166,7 +1192,13 @@ step_over_function:
 step_into_function:
          /* Subroutine call with source code we should not step over.
             Do step to the first line of code in it.  */
-         SKIP_PROLOGUE (stop_func_start);
+         {
+           struct symtab *s;
+
+           s = find_pc_symtab (stop_pc);
+           if (s && s->language != language_asm)
+             SKIP_PROLOGUE (stop_func_start);
+         }
          sal = find_pc_line (stop_func_start, 0);
          /* Use the step_resume_break to step until
             the end of the prologue, even if that involves jumps
index 49f361d3c2d295b2f9778b951b5c4129391d1f68..3d7c92d9eb31e99aa50b6f16dc805d054abcf6f6 100644 (file)
@@ -597,7 +597,7 @@ child_wait (pid, ourstatus)
 {
   int save_errno;
   int thread;
-  int status;
+  union wait status;
 
   while (1)
     {
@@ -632,8 +632,7 @@ child_wait (pid, ourstatus)
       if (pid != PIDGET (inferior_pid))        /* Some other process?!? */
        continue;
 
-/*      thread = WIFTID (status);*/
-      thread = status >> 16;
+      thread = status.w_tid;   /* Get thread id from status */
 
       /* Initial thread value can only be acquired via wait, so we have to
         resort to this hack.  */
@@ -646,7 +645,26 @@ child_wait (pid, ourstatus)
 
       pid = BUILDPID (pid, thread);
 
-      store_waitstatus (ourstatus, status);
+      if (WIFSTOPPED(status)
+         && WSTOPSIG(status) == SIGTRAP
+         && !in_thread_list (pid))
+       {
+         int realsig;
+
+         realsig = ptrace (PTRACE_GETTRACESIG, pid, 0);
+
+         if (realsig == SIGNEWTHREAD)
+           {
+             /* Simply ignore new thread notification, as we can't do anything
+                useful with such threads.  All ptrace calls at this point just
+                fail for no apparent reason.  The thread will eventually get a
+                real signal when it becomes real.  */
+             child_resume (pid, 0, TARGET_SIGNAL_0);
+             continue;
+           }
+       }
+
+      store_waitstatus (ourstatus, status.w_status);
 
       return pid;
     }
@@ -662,13 +680,18 @@ child_resume (pid, step, signal)
      int step;
      enum target_signal signal;
 {
+  int func;
+
   errno = 0;
 
   if (pid == -1)
-    /* Resume all threads.  */
-    /* I think this only gets used in the non-threaded case, where "resume
-       all threads" and "resume inferior_pid" are the same.  */
-    pid = inferior_pid;
+    {
+      /* Resume all threads.  */
+
+      pid = inferior_pid;
+    }
+
+  func = step ? PTRACE_SINGLESTEP_ONE : PTRACE_CONT;
 
   /* An address of (PTRACE_ARG3_TYPE)1 tells ptrace to continue from where
      it was.  (If GDB wanted it to start some other way, we have already
@@ -679,12 +702,7 @@ child_resume (pid, step, signal)
      continue request (by setting breakpoints on all possible successor
      instructions), so we don't have to worry about that here.  */
 
-  if (step)
-    ptrace (PTRACE_SINGLESTEP_ONE,     pid, (PTRACE_ARG3_TYPE) 1,
-           target_signal_to_host (signal));
-  else
-    ptrace (PTRACE_CONT_ONE, pid, (PTRACE_ARG3_TYPE) 1,
-           target_signal_to_host (signal));
+  ptrace (func, pid, (PTRACE_ARG3_TYPE) 1, target_signal_to_host (signal));
 
   if (errno)
     perror_with_name ("ptrace");