From mboxrd@z Thu Jan 1 00:00:00 1970 From: Stan Shebs To: dan@cgsoftware.com Cc: gdb-patches@sourceware.cygnus.com, Fernando Nasser Subject: Re: [RFA]: Apropos patch Date: Wed, 22 Mar 2000 18:28:00 -0000 Message-id: <38D9815A.FC4E178E@apple.com> References: <1z52tswd.fsf@dan.resnet.rochester.edu> X-SW-Source: 2000-03/msg00492.html "Daniel Berlin+list.gdb-patches" wrote: > > It includes documentation, a test case (which uses a slightly weird > regexp so it only finds one thing, and we make sure it only found one > thing), and all the apropriate changelog entries. You're going to hate this, but now that I see the example in the manual, I'm wondering why "prefix:" and "command:" are on separate lines? Why not just imitate the syntax that comes out of the help command - set symbol-reloading -- show symbol-reloading -- Another advantage is that users can then cut-n-paste from the apropos output more easily. > Let me know if i can check it in, i believe it needs approval from > Stan Shebs, and Fernando Nasser. Just needs approval from one of us, not both! I must confess to being a bit mystified by the test though - why use "handle" as the match string, and do I understand right, you're requiring that it be the first output from apropos? Stan >From dan@cgsoftware.com Wed Mar 22 19:25:00 2000 From: dan@cgsoftware.com (Daniel Berlin+list.gdb-patches) To: shebs@apple.com Cc: dan@cgsoftware.com, gdb-patches@sourceware.cygnus.com, Fernando Nasser Subject: Re: [RFA]: Apropos patch Date: Wed, 22 Mar 2000 19:25:00 -0000 Message-id: References: <1z52tswd.fsf@dan.resnet.rochester.edu> <38D9815A.FC4E178E@apple.com> X-SW-Source: 2000-03/msg00493.html Content-length: 1985 Stan Shebs writes: > "Daniel Berlin+list.gdb-patches" wrote: > > > > It includes documentation, a test case (which uses a slightly weird > > regexp so it only finds one thing, and we make sure it only found one > > thing), and all the apropriate changelog entries. > > You're going to hate this, but now that I see the example in the manual, > I'm wondering why "prefix:" and "command:" are on separate lines? No particular reason, i can make it go away if you like, it's simple. > Why not just imitate the syntax that comes out of the help command - > > set symbol-reloading -- > show symbol-reloading -- I thought of this, but the problem is that the help command only displays the first line, and the match may not be there. If something wanted to say, highlight the match, or something, it might not have appeared in the first line, and thus, not in the output. > > Another advantage is that users can then cut-n-paste from the apropos > output more easily. > > > Let me know if i can check it in, i believe it needs approval from > > Stan Shebs, and Fernando Nasser. > > Just needs approval from one of us, not both! I must confess to being > a bit mystified by the test though - why use "handle" as the match > string, and do I understand right, you're requiring that it be the > first output from apropos? That regexp gets rid of every command with "print" in the name or doc string, except one. Handle happened to be that one when i got done removing commands by adding to the regexp, and i figured it should be available on every single platform (even platforms where signals basically were ignored when it came to gdb, like BeOS), so why not use that? If it come out to be some weird command, i would have changed the regex. The [^:]+ just makes sure it doesn't catch another command. It's kinda a crappy test, i'll revise it as soon as some consensus is reached as to what the output should be like. > > Stan >From ezannoni@cygnus.com Wed Mar 22 19:52:00 2000 From: Elena Zannoni To: Elena Zannoni Cc: "Philippe De Muyter" , ac131313@cygnus.com (Andrew Cagney), gdb-patches@sourceware.cygnus.com Subject: Re: HAVE_POLL is not enough - RFA Date: Wed, 22 Mar 2000 19:52:00 -0000 Message-id: <14553.37904.686232.810079@kwikemart.cygnus.com> References: <38D5BE1D.7BB02C99@cygnus.com> <200003211559.QAA16996@mail.macqel.be> <14553.28151.426657.410579@kwikemart.cygnus.com> X-SW-Source: 2000-03/msg00494.html Content-length: 23076 I committed the following: Same as original patch except for the USE_POLL thing, and I also added a comment explaining the reason for the run time test for poll(). Elena Index: event-loop.c =================================================================== RCS file: /cvs/src/src/gdb/event-loop.c,v retrieving revision 1.4 diff -c -r1.4 event-loop.c *** event-loop.c 2000/03/20 19:59:38 1.4 --- event-loop.c 2000/03/23 03:42:24 *************** *** 25,34 **** #include "event-top.h" #ifdef HAVE_POLL #include ! #else #include #include - #endif #include #include #include --- 25,33 ---- #include "event-top.h" #ifdef HAVE_POLL #include ! #endif #include #include #include #include #include *************** *** 166,201 **** /* As of 1999-04-30 only the input file descriptor is registered with the event loop. */ #ifdef HAVE_POLL ! /* Poll based implementation of the notifier. */ static struct { /* Ptr to head of file handler list. */ file_handler *first_file_handler; /* Ptr to array of pollfd structures. */ struct pollfd *poll_fds; - /* Number of file descriptors to monitor. */ - int num_fds; - /* Timeout in milliseconds for calls to poll(). */ ! int timeout; ! ! /* Flag to tell whether the timeout value shuld be used. */ ! int timeout_valid; ! } ! gdb_notifier; ! ! #else /* ! HAVE_POLL */ ! ! /* Select based implementation of the notifier. */ ! ! static struct ! { ! /* Ptr to head of file handler list. */ ! file_handler *first_file_handler; /* Masks to be used in the next call to select. Bits are set in response to calls to create_file_handler. */ --- 165,191 ---- /* As of 1999-04-30 only the input file descriptor is registered with the event loop. */ + /* Do we use poll or select ? */ #ifdef HAVE_POLL ! #define USE_POLL 1 ! #else ! #define USE_POLL 0 ! #endif /* HAVE_POLL */ + static unsigned char use_poll = USE_POLL; + static struct { /* Ptr to head of file handler list. */ file_handler *first_file_handler; + #ifdef HAVE_POLL /* Ptr to array of pollfd structures. */ struct pollfd *poll_fds; /* Timeout in milliseconds for calls to poll(). */ ! int poll_timeout; ! #endif /* Masks to be used in the next call to select. Bits are set in response to calls to create_file_handler. */ *************** *** 204,222 **** /* What file descriptors were found ready by select. */ fd_set ready_masks[3]; ! /* Number of valid bits (highest fd value + 1). */ int num_fds; /* Time structure for calls to select(). */ ! struct timeval timeout; ! /* Flag to tell whether the timeout struct should be used. */ int timeout_valid; } gdb_notifier; - #endif /* HAVE_POLL */ - /* Structure associated with a timer. PROC will be executed at the first occasion after WHEN. */ struct gdb_timer --- 194,211 ---- /* What file descriptors were found ready by select. */ fd_set ready_masks[3]; ! /* Number of file descriptors to monitor. (for poll) */ ! /* Number of valid bits (highest fd value + 1). (for select) */ int num_fds; /* Time structure for calls to select(). */ ! struct timeval select_timeout; ! /* Flag to tell whether the timeout should be used. */ int timeout_valid; } gdb_notifier; /* Structure associated with a timer. PROC will be executed at the first occasion after WHEN. */ struct gdb_timer *************** *** 384,390 **** } free ((char *) event_ptr); ! /* Now call the procedure associted with the event. */ (*proc) (fd); return 1; } --- 373,379 ---- } free ((char *) event_ptr); ! /* Now call the procedure associated with the event. */ (*proc) (fd); return 1; } *************** *** 473,482 **** add_file_handler (int fd, handler_func * proc, gdb_client_data client_data) { #ifdef HAVE_POLL ! create_file_handler (fd, POLLIN, proc, client_data); #else ! create_file_handler (fd, GDB_READABLE | GDB_EXCEPTION, proc, client_data); #endif } /* Add a file handler/descriptor to the list of descriptors we are --- 462,496 ---- add_file_handler (int fd, handler_func * proc, gdb_client_data client_data) { #ifdef HAVE_POLL ! struct pollfd fds; ! #endif ! ! if (use_poll) ! { ! #ifdef HAVE_POLL ! /* Check to see if poll () is usable. If not, we'll switch to ! use select. This can happen on systems like ! m68k-motorola-sys, `poll' cannot be used to wait for `stdin'. ! On m68k-motorola-sysv, tty's are not stream-based and not ! `poll'able.*/ ! fds.fd = fd; ! fds.events = POLLIN; ! if (poll (&fds, 1, 0) == 1 && (fds.revents & POLLNVAL)) ! use_poll = 0; ! #else ! internal_error ("event-loop.c : use_poll without HAVE_POLL"); ! #endif /* HAVE_POLL */ ! } ! if (use_poll) ! { ! #ifdef HAVE_POLL ! create_file_handler (fd, POLLIN, proc, client_data); #else ! internal_error ("event-loop.c : use_poll without HAVE_POLL"); #endif + } + else + create_file_handler (fd, GDB_READABLE | GDB_EXCEPTION, proc, client_data); } /* Add a file handler/descriptor to the list of descriptors we are *************** *** 512,559 **** file_ptr->ready_mask = 0; file_ptr->next_file = gdb_notifier.first_file_handler; gdb_notifier.first_file_handler = file_ptr; - #ifdef HAVE_POLL - gdb_notifier.num_fds++; - #endif } file_ptr->proc = proc; file_ptr->client_data = client_data; file_ptr->mask = mask; #ifdef HAVE_POLL ! ! if (gdb_notifier.poll_fds) ! gdb_notifier.poll_fds = ! (struct pollfd *) realloc (gdb_notifier.poll_fds, ! (gdb_notifier.num_fds) * sizeof (struct pollfd)); ! else ! gdb_notifier.poll_fds = ! (struct pollfd *) xmalloc (sizeof (struct pollfd)); ! (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->fd = fd; ! (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->events = mask; ! (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->revents = 0; ! ! #else /* ! HAVE_POLL */ ! ! if (mask & GDB_READABLE) ! FD_SET (fd, &gdb_notifier.check_masks[0]); ! else ! FD_CLR (fd, &gdb_notifier.check_masks[0]); ! ! if (mask & GDB_WRITABLE) ! FD_SET (fd, &gdb_notifier.check_masks[1]); else ! FD_CLR (fd, &gdb_notifier.check_masks[1]); ! if (mask & GDB_EXCEPTION) ! FD_SET (fd, &gdb_notifier.check_masks[2]); ! else ! FD_CLR (fd, &gdb_notifier.check_masks[2]); ! if (gdb_notifier.num_fds <= fd) ! gdb_notifier.num_fds = fd + 1; ! #endif /* HAVE_POLL */ } /* Remove the file descriptor FD from the list of monitored fd's: --- 526,574 ---- file_ptr->ready_mask = 0; file_ptr->next_file = gdb_notifier.first_file_handler; gdb_notifier.first_file_handler = file_ptr; } file_ptr->proc = proc; file_ptr->client_data = client_data; file_ptr->mask = mask; + if (use_poll) + { #ifdef HAVE_POLL ! gdb_notifier.num_fds++; ! if (gdb_notifier.poll_fds) ! gdb_notifier.poll_fds = ! (struct pollfd *) realloc (gdb_notifier.poll_fds, ! (gdb_notifier.num_fds) * sizeof (struct pollfd)); ! else ! gdb_notifier.poll_fds = ! (struct pollfd *) xmalloc (sizeof (struct pollfd)); ! (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->fd = fd; ! (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->events = mask; ! (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->revents = 0; ! #else ! internal_error ("event-loop.c : use_poll without HAVE_POLL"); ! #endif /* HAVE_POLL */ ! } else ! { ! if (mask & GDB_READABLE) ! FD_SET (fd, &gdb_notifier.check_masks[0]); ! else ! FD_CLR (fd, &gdb_notifier.check_masks[0]); ! if (mask & GDB_WRITABLE) ! FD_SET (fd, &gdb_notifier.check_masks[1]); ! else ! FD_CLR (fd, &gdb_notifier.check_masks[1]); ! if (mask & GDB_EXCEPTION) ! FD_SET (fd, &gdb_notifier.check_masks[2]); ! else ! FD_CLR (fd, &gdb_notifier.check_masks[2]); ! if (gdb_notifier.num_fds <= fd) ! gdb_notifier.num_fds = fd + 1; ! } } /* Remove the file descriptor FD from the list of monitored fd's: *************** *** 580,630 **** if (file_ptr == NULL) return; #ifdef HAVE_POLL ! /* Create a new poll_fds array by copying every fd's information but the ! one we want to get rid of. */ ! new_poll_fds = ! (struct pollfd *) xmalloc ((gdb_notifier.num_fds - 1) * sizeof (struct pollfd)); ! for (i = 0, j = 0; i < gdb_notifier.num_fds; i++) ! { ! if ((gdb_notifier.poll_fds + i)->fd != fd) { ! (new_poll_fds + j)->fd = (gdb_notifier.poll_fds + i)->fd; ! (new_poll_fds + j)->events = (gdb_notifier.poll_fds + i)->events; ! (new_poll_fds + j)->revents = (gdb_notifier.poll_fds + i)->revents; ! j++; } } ! free (gdb_notifier.poll_fds); ! gdb_notifier.poll_fds = new_poll_fds; ! gdb_notifier.num_fds--; ! ! #else /* ! HAVE_POLL */ ! ! if (file_ptr->mask & GDB_READABLE) ! FD_CLR (fd, &gdb_notifier.check_masks[0]); ! if (file_ptr->mask & GDB_WRITABLE) ! FD_CLR (fd, &gdb_notifier.check_masks[1]); ! if (file_ptr->mask & GDB_EXCEPTION) ! FD_CLR (fd, &gdb_notifier.check_masks[2]); ! /* Find current max fd. */ ! if ((fd + 1) == gdb_notifier.num_fds) ! { ! gdb_notifier.num_fds--; ! for (i = gdb_notifier.num_fds; i; i--) { ! if (FD_ISSET (i - 1, &gdb_notifier.check_masks[0]) ! || FD_ISSET (i - 1, &gdb_notifier.check_masks[1]) ! || FD_ISSET (i - 1, &gdb_notifier.check_masks[2])) ! break; } - gdb_notifier.num_fds = i; } - #endif /* HAVE_POLL */ /* Deactivate the file descriptor, by clearing its mask, so that it will not fire again. */ --- 595,650 ---- if (file_ptr == NULL) return; + if (use_poll) + { #ifdef HAVE_POLL ! /* Create a new poll_fds array by copying every fd's information but the ! one we want to get rid of. */ ! new_poll_fds = ! (struct pollfd *) xmalloc ((gdb_notifier.num_fds - 1) * sizeof (struct pollfd)); ! for (i = 0, j = 0; i < gdb_notifier.num_fds; i++) { ! if ((gdb_notifier.poll_fds + i)->fd != fd) ! { ! (new_poll_fds + j)->fd = (gdb_notifier.poll_fds + i)->fd; ! (new_poll_fds + j)->events = (gdb_notifier.poll_fds + i)->events; ! (new_poll_fds + j)->revents = (gdb_notifier.poll_fds + i)->revents; ! j++; ! } } + free (gdb_notifier.poll_fds); + gdb_notifier.poll_fds = new_poll_fds; + gdb_notifier.num_fds--; + #else + internal_error ("event-loop.c : use_poll without HAVE_POLL"); + #endif /* HAVE_POLL */ } ! else ! { ! if (file_ptr->mask & GDB_READABLE) ! FD_CLR (fd, &gdb_notifier.check_masks[0]); ! if (file_ptr->mask & GDB_WRITABLE) ! FD_CLR (fd, &gdb_notifier.check_masks[1]); ! if (file_ptr->mask & GDB_EXCEPTION) ! FD_CLR (fd, &gdb_notifier.check_masks[2]); ! /* Find current max fd. */ ! if ((fd + 1) == gdb_notifier.num_fds) { ! gdb_notifier.num_fds--; ! for (i = gdb_notifier.num_fds; i; i--) ! { ! if (FD_ISSET (i - 1, &gdb_notifier.check_masks[0]) ! || FD_ISSET (i - 1, &gdb_notifier.check_masks[1]) ! || FD_ISSET (i - 1, &gdb_notifier.check_masks[2])) ! break; ! } ! gdb_notifier.num_fds = i; } } /* Deactivate the file descriptor, by clearing its mask, so that it will not fire again. */ *************** *** 675,711 **** /* See if the desired events (mask) match the received events (ready_mask). */ - - #ifdef HAVE_POLL - error_mask = POLLHUP | POLLERR | POLLNVAL; - mask = (file_ptr->ready_mask & file_ptr->mask) | - (file_ptr->ready_mask & error_mask); - error_mask_returned = mask & error_mask; ! if (error_mask_returned != 0) { ! /* Work in progress. We may need to tell somebody what ! kind of error we had. */ ! if (error_mask_returned & POLLHUP) ! printf_unfiltered ("Hangup detected on fd %d\n", file_ptr->fd); ! if (error_mask_returned & POLLERR) ! printf_unfiltered ("Error detected on fd %d\n", file_ptr->fd); ! if (error_mask_returned & POLLNVAL) ! printf_unfiltered ("Invalid or non-`poll'able fd %d\n", file_ptr->fd); ! file_ptr->error = 1; } else - file_ptr->error = 0; - #else /* ! HAVE_POLL */ - if (file_ptr->ready_mask & GDB_EXCEPTION) { ! printf_unfiltered ("Exception condition detected on fd %d\n", file_ptr->fd); ! file_ptr->error = 1; } - else - file_ptr->error = 0; - mask = file_ptr->ready_mask & file_ptr->mask; - #endif /* HAVE_POLL */ /* Clear the received events for next time around. */ file_ptr->ready_mask = 0; --- 695,738 ---- /* See if the desired events (mask) match the received events (ready_mask). */ ! if (use_poll) { ! #ifdef HAVE_POLL ! error_mask = POLLHUP | POLLERR | POLLNVAL; ! mask = (file_ptr->ready_mask & file_ptr->mask) | ! (file_ptr->ready_mask & error_mask); ! error_mask_returned = mask & error_mask; ! ! if (error_mask_returned != 0) ! { ! /* Work in progress. We may need to tell somebody what ! kind of error we had. */ ! if (error_mask_returned & POLLHUP) ! printf_unfiltered ("Hangup detected on fd %d\n", file_ptr->fd); ! if (error_mask_returned & POLLERR) ! printf_unfiltered ("Error detected on fd %d\n", file_ptr->fd); ! if (error_mask_returned & POLLNVAL) ! printf_unfiltered ("Invalid or non-`poll'able fd %d\n", file_ptr->fd); ! file_ptr->error = 1; ! } ! else ! file_ptr->error = 0; ! #else ! internal_error ("event-loop.c : use_poll without HAVE_POLL"); ! #endif /* HAVE_POLL */ } else { ! if (file_ptr->ready_mask & GDB_EXCEPTION) ! { ! printf_unfiltered ("Exception condition detected on fd %d\n", file_ptr->fd); ! file_ptr->error = 1; ! } ! else ! file_ptr->error = 0; ! mask = file_ptr->ready_mask & file_ptr->mask; } /* Clear the received events for next time around. */ file_ptr->ready_mask = 0; *************** *** 731,739 **** file_handler *file_ptr; gdb_event *file_event_ptr; int num_found = 0; - #ifdef HAVE_POLL int i; - #endif /* Make sure all output is done before getting another event. */ gdb_flush (gdb_stdout); --- 758,764 ---- *************** *** 742,849 **** if (gdb_notifier.num_fds == 0) return -1; #ifdef HAVE_POLL ! num_found = ! poll (gdb_notifier.poll_fds, ! (unsigned long) gdb_notifier.num_fds, ! gdb_notifier.timeout_valid ? gdb_notifier.timeout : -1); ! ! /* Don't print anything if we get out of poll because of a ! signal. */ ! if (num_found == -1 && errno != EINTR) ! perror_with_name ("Poll"); ! ! #else /* ! HAVE_POLL */ ! ! gdb_notifier.ready_masks[0] = gdb_notifier.check_masks[0]; ! gdb_notifier.ready_masks[1] = gdb_notifier.check_masks[1]; ! gdb_notifier.ready_masks[2] = gdb_notifier.check_masks[2]; ! ! num_found = select (gdb_notifier.num_fds, ! & gdb_notifier.ready_masks[0], ! & gdb_notifier.ready_masks[1], ! & gdb_notifier.ready_masks[2], ! gdb_notifier.timeout_valid ! ? &gdb_notifier.timeout : NULL); ! ! /* Clear the masks after an error from select. */ ! if (num_found == -1) ! { ! FD_ZERO (&gdb_notifier.ready_masks[0]); ! FD_ZERO (&gdb_notifier.ready_masks[1]); ! FD_ZERO (&gdb_notifier.ready_masks[2]); ! /* Dont print anything is we got a signal, let gdb handle it. */ ! if (errno != EINTR) ! perror_with_name ("Select"); ! } #endif /* HAVE_POLL */ /* Enqueue all detected file events. */ #ifdef HAVE_POLL ! for (i = 0; (i < gdb_notifier.num_fds) && (num_found > 0); i++) ! { ! if ((gdb_notifier.poll_fds + i)->revents) ! num_found--; ! else ! continue; for (file_ptr = gdb_notifier.first_file_handler; ! file_ptr != NULL; file_ptr = file_ptr->next_file) { ! if (file_ptr->fd == (gdb_notifier.poll_fds + i)->fd) ! break; ! } ! if (file_ptr) ! { /* Enqueue an event only if this is still a new event for this fd. */ if (file_ptr->ready_mask == 0) { file_event_ptr = create_file_event (file_ptr->fd); async_queue_event (file_event_ptr, TAIL); } } - - file_ptr->ready_mask = (gdb_notifier.poll_fds + i)->revents; - } - - #else /* ! HAVE_POLL */ - - for (file_ptr = gdb_notifier.first_file_handler; - (file_ptr != NULL) && (num_found > 0); - file_ptr = file_ptr->next_file) - { - int mask = 0; - - if (FD_ISSET (file_ptr->fd, &gdb_notifier.ready_masks[0])) - mask |= GDB_READABLE; - if (FD_ISSET (file_ptr->fd, &gdb_notifier.ready_masks[1])) - mask |= GDB_WRITABLE; - if (FD_ISSET (file_ptr->fd, &gdb_notifier.ready_masks[2])) - mask |= GDB_EXCEPTION; - - if (!mask) - continue; - else - num_found--; - - /* Enqueue an event only if this is still a new event for - this fd. */ - - if (file_ptr->ready_mask == 0) - { - file_event_ptr = create_file_event (file_ptr->fd); - async_queue_event (file_event_ptr, TAIL); - } - file_ptr->ready_mask = mask; } - - #endif /* HAVE_POLL */ - return 0; } --- 767,880 ---- if (gdb_notifier.num_fds == 0) return -1; + if (use_poll) + { #ifdef HAVE_POLL ! num_found = ! poll (gdb_notifier.poll_fds, ! (unsigned long) gdb_notifier.num_fds, ! gdb_notifier.timeout_valid ? gdb_notifier.poll_timeout : -1); ! ! /* Don't print anything if we get out of poll because of a ! signal. */ ! if (num_found == -1 && errno != EINTR) ! perror_with_name ("Poll"); ! #else ! internal_error ("event-loop.c : use_poll without HAVE_POLL"); #endif /* HAVE_POLL */ + } + else + { + gdb_notifier.ready_masks[0] = gdb_notifier.check_masks[0]; + gdb_notifier.ready_masks[1] = gdb_notifier.check_masks[1]; + gdb_notifier.ready_masks[2] = gdb_notifier.check_masks[2]; + num_found = select (gdb_notifier.num_fds, + & gdb_notifier.ready_masks[0], + & gdb_notifier.ready_masks[1], + & gdb_notifier.ready_masks[2], + gdb_notifier.timeout_valid + ? &gdb_notifier.select_timeout : NULL); + + /* Clear the masks after an error from select. */ + if (num_found == -1) + { + FD_ZERO (&gdb_notifier.ready_masks[0]); + FD_ZERO (&gdb_notifier.ready_masks[1]); + FD_ZERO (&gdb_notifier.ready_masks[2]); + /* Dont print anything is we got a signal, let gdb handle it. */ + if (errno != EINTR) + perror_with_name ("Select"); + } + } /* Enqueue all detected file events. */ + if (use_poll) + { #ifdef HAVE_POLL + for (i = 0; (i < gdb_notifier.num_fds) && (num_found > 0); i++) + { + if ((gdb_notifier.poll_fds + i)->revents) + num_found--; + else + continue; ! for (file_ptr = gdb_notifier.first_file_handler; ! file_ptr != NULL; ! file_ptr = file_ptr->next_file) ! { ! if (file_ptr->fd == (gdb_notifier.poll_fds + i)->fd) ! break; ! } ! ! if (file_ptr) ! { ! /* Enqueue an event only if this is still a new event for ! this fd. */ ! if (file_ptr->ready_mask == 0) ! { ! file_event_ptr = create_file_event (file_ptr->fd); ! async_queue_event (file_event_ptr, TAIL); ! } ! } + file_ptr->ready_mask = (gdb_notifier.poll_fds + i)->revents; + } + #else + internal_error ("event-loop.c : use_poll without HAVE_POLL"); + #endif /* HAVE_POLL */ + } + else + { for (file_ptr = gdb_notifier.first_file_handler; ! (file_ptr != NULL) && (num_found > 0); file_ptr = file_ptr->next_file) { ! int mask = 0; ! if (FD_ISSET (file_ptr->fd, &gdb_notifier.ready_masks[0])) ! mask |= GDB_READABLE; ! if (FD_ISSET (file_ptr->fd, &gdb_notifier.ready_masks[1])) ! mask |= GDB_WRITABLE; ! if (FD_ISSET (file_ptr->fd, &gdb_notifier.ready_masks[2])) ! mask |= GDB_EXCEPTION; ! ! if (!mask) ! continue; ! else ! num_found--; ! /* Enqueue an event only if this is still a new event for this fd. */ + if (file_ptr->ready_mask == 0) { file_event_ptr = create_file_event (file_ptr->fd); async_queue_event (file_event_ptr, TAIL); } + file_ptr->ready_mask = mask; } } return 0; } *************** *** 1125,1136 **** /* Now we need to update the timeout for select/ poll, because we don't want to sit there while this timer is expiring. */ #ifdef HAVE_POLL ! gdb_notifier.timeout = delta.tv_sec * 1000; #else ! gdb_notifier.timeout.tv_sec = delta.tv_sec; ! gdb_notifier.timeout.tv_usec = delta.tv_usec; ! #endif gdb_notifier.timeout_valid = 1; } else --- 1156,1174 ---- /* Now we need to update the timeout for select/ poll, because we don't want to sit there while this timer is expiring. */ + if (use_poll) + { #ifdef HAVE_POLL ! gdb_notifier.poll_timeout = delta.tv_sec * 1000; #else ! internal_error ("event-loop.c : use_poll without HAVE_POLL"); ! #endif /* HAVE_POLL */ ! } ! else ! { ! gdb_notifier.select_timeout.tv_sec = delta.tv_sec; ! gdb_notifier.select_timeout.tv_usec = delta.tv_usec; ! } gdb_notifier.timeout_valid = 1; } else Index: ChangeLog =================================================================== RCS file: /cvs/src/src/gdb/ChangeLog,v retrieving revision 1.164 diff -c -r1.164 ChangeLog *** ChangeLog 2000/03/22 20:55:15 1.164 --- ChangeLog 2000/03/23 03:42:24 *************** *** 1,3 **** --- 1,17 ---- + 2000-03-22 Elena Zannoni + + From Philippe De Muyter + + * event-loop.c (sys/types.h): File now included unconditionally. + (use_poll): New variable.. + (gdb_notifier): poll- and select-versions merged. + (add_file_handler): If HAVE_POLL, check whether poll is usable, + and reset `use_poll' if not. + (create_file_handler): Select poll- or select-version according to + `use_poll'. + (delete_file_handler, handle_file_event): Likewise. + (gdb_wait_for_event, poll_timers): Likewise. + 2000-03-22 Peter Schauer * printcmd.c (print_scalar_formatted): Truncate addresses to the >From kevinb@cygnus.com Wed Mar 22 20:40:00 2000 From: Kevin Buettner To: gdb-patches@sourceware.cygnus.com Subject: [PATCH] HFA, function descriptor handling for IA-64 Date: Wed, 22 Mar 2000 20:40:00 -0000 Message-id: <1000323044022.ZM30003@ocotillo.lan> X-SW-Source: 2000-03/msg00495.html Content-length: 16374 I've just committed the patches below. BTW, HFAs are Homogeneous Floating-point Aggregates which are merely structs, or arrays, or arrays of structs, or structs of arrays, etc. all of which contain the same type of float. The calling conventions of the IA-64 architecture require that the floating point values constituting an HFA be passed in floating point registers. Upon return, HFAs of up to four elements are also returned in registers. So, e.g, a complex type (which is simply a pair of floating point values) is passed and returned very efficiently. * ia64-linux-nat.c: Fix copyright. (fill_gregset): Minor formatting fix. * ia64-tdep.c (template_encoding_table, fetch_instruction, examine_prologue): Clean up some compiler warnings. (is_float_or_hfa_type_recurse, is_float_or_hfa_type, find_func_descr, find_global_pointer, find_extant_func_descr): New functions. (ia64_use_struct_convention, ia64_extract_return_value, ia64_push_arguments): Handle HFAs. (ia64_push_arguments): Find (or build) a function descriptor when given a function address. (ia64_push_return_address): Moved code for finding the global pointer into its own function, find_global_pointer (). Index: ia64-linux-nat.c =================================================================== RCS file: /cvs/src/src/gdb/ia64-linux-nat.c,v retrieving revision 1.1 diff -u -p -r1.1 ia64-linux-nat.c --- ia64-linux-nat.c 2000/03/21 00:11:10 1.1 +++ ia64-linux-nat.c 2000/03/23 04:14:18 @@ -1,5 +1,5 @@ -/* Functions specific to running gdb native on IA64 running Linux. - Copyright 1999 Free Software Foundation, Inc. +/* Functions specific to running gdb native on IA-64 running Linux. + Copyright 1999, 2000 Free Software Foundation, Inc. This file is part of GDB. @@ -394,6 +394,6 @@ fill_gregset (gregsetp, regno) gregset_t *gregsetp; int regno; { - fprintf(stderr, "Warning: fill_gregset not implemented!\n"); + fprintf (stderr, "Warning: fill_gregset not implemented!\n"); /* FIXME: Implement later */ } Index: ia64-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/ia64-tdep.c,v retrieving revision 1.1 diff -u -p -r1.1 ia64-tdep.c --- ia64-tdep.c 2000/03/21 00:11:10 1.1 +++ ia64-tdep.c 2000/03/23 04:14:20 @@ -87,8 +87,8 @@ static gdbarch_push_arguments_ftype ia64 static gdbarch_push_return_address_ftype ia64_push_return_address; static gdbarch_pop_frame_ftype ia64_pop_frame; static gdbarch_saved_pc_after_call_ftype ia64_saved_pc_after_call; - static void ia64_pop_frame_regular (struct frame_info *frame); +static struct type *is_float_or_hfa_type (struct type *t); static int ia64_num_regs = 590; @@ -384,7 +384,7 @@ replace_slotN_contents (unsigned char *b replace_bit_field (bundle, instr, 5+41*slotnum, 41); } -static template_encoding_table[32][3] = +static enum instruction_type template_encoding_table[32][3] = { { M, I, I }, /* 00 */ { M, I, I }, /* 01 */ @@ -445,7 +445,7 @@ fetch_instruction (CORE_ADDR addr, instr template = extract_bit_field (bundle, 0, 5); *it = template_encoding_table[(int)template][slotnum]; - if (slotnum == 2 || slotnum == 1 && *it == L) + if (slotnum == 2 || (slotnum == 1 && *it == L)) addr += 16; else addr += (slotnum + 1) * SLOT_MULTIPLIER; @@ -639,7 +639,6 @@ examine_prologue (CORE_ADDR pc, CORE_ADD { CORE_ADDR next_pc; CORE_ADDR last_prologue_pc = pc; - int done = 0; instruction_type it; long long instr; int do_fsr_stuff = 0; @@ -1137,20 +1136,45 @@ ia64_get_saved_register (char *raw_buffe int ia64_use_struct_convention (int gcc_p, struct type *type) { - /* FIXME: Need to check for HFAs; structures containing (only) up to 8 - floating point values of the same size are returned in floating point - registers. */ + struct type *float_elt_type; + + /* HFAs are structures (or arrays) consisting entirely of floating + point values of the same length. Up to 8 of these are returned + in registers. Don't use the struct convention when this is the + case. */ + float_elt_type = is_float_or_hfa_type (type); + if (float_elt_type != NULL + && TYPE_LENGTH (type) / TYPE_LENGTH (float_elt_type) <= 8) + return 0; + + /* Other structs of length 32 or less are returned in r8-r11. + Don't use the struct convention for those either. */ return TYPE_LENGTH (type) > 32; } void ia64_extract_return_value (struct type *type, char *regbuf, char *valbuf) { - if (TYPE_CODE (type) == TYPE_CODE_FLT) - ia64_register_convert_to_virtual (IA64_FR8_REGNUM, type, - ®buf[REGISTER_BYTE (IA64_FR8_REGNUM)], valbuf); + struct type *float_elt_type; + + float_elt_type = is_float_or_hfa_type (type); + if (float_elt_type != NULL) + { + int offset = 0; + int regnum = IA64_FR8_REGNUM; + int n = TYPE_LENGTH (type) / TYPE_LENGTH (float_elt_type); + + while (n-- > 0) + { + ia64_register_convert_to_virtual (regnum, float_elt_type, + ®buf[REGISTER_BYTE (regnum)], valbuf + offset); + offset += TYPE_LENGTH (float_elt_type); + regnum++; + } + } else - memcpy (valbuf, ®buf[REGISTER_BYTE (IA64_GR8_REGNUM)], TYPE_LENGTH (type)); + memcpy (valbuf, ®buf[REGISTER_BYTE (IA64_GR8_REGNUM)], + TYPE_LENGTH (type)); } /* FIXME: Turn this into a stack of some sort. Unfortunately, something @@ -1219,7 +1243,6 @@ ia64_init_extra_frame_info (int fromleaf else { struct frame_info *frn = frame->next; - CORE_ADDR cfm_addr; FRAME_INIT_SAVED_REGS (frn); @@ -1242,9 +1265,200 @@ ia64_init_extra_frame_info (int fromleaf frame->extra_info->mem_stack_frame_size = -1; /* Not yet determined */ frame->extra_info->fp_reg = 0; } + +static int +is_float_or_hfa_type_recurse (struct type *t, struct type **etp) +{ + switch (TYPE_CODE (t)) + { + case TYPE_CODE_FLT: + if (*etp) + return TYPE_LENGTH (*etp) == TYPE_LENGTH (t); + else + { + *etp = t; + return 1; + } + break; + case TYPE_CODE_ARRAY: + return is_float_or_hfa_type_recurse (TYPE_TARGET_TYPE (t), etp); + break; + case TYPE_CODE_STRUCT: + { + int i; + + for (i = 0; i < TYPE_NFIELDS (t); i++) + if (!is_float_or_hfa_type_recurse (TYPE_FIELD_TYPE (t, i), etp)) + return 0; + return 1; + } + break; + default: + return 0; + break; + } +} + +/* Determine if the given type is one of the floating point types or + and HFA (which is a struct, array, or combination thereof whose + bottom-most elements are all of the same floating point type.) */ + +static struct type * +is_float_or_hfa_type (struct type *t) +{ + struct type *et = 0; + + return is_float_or_hfa_type_recurse (t, &et) ? et : 0; +} + + +/* Attempt to find (and return) the global pointer for the given + function. + + This is a rather nasty bit of code searchs for the .dynamic section + in the objfile corresponding to the pc of the function we're trying + to call. Once it finds the addresses at which the .dynamic section + lives in the child process, it scans the Elf64_Dyn entries for a + DT_PLTGOT tag. If it finds one of these, the corresponding + d_un.d_ptr value is the global pointer. */ + +static CORE_ADDR +find_global_pointer (CORE_ADDR faddr) +{ + struct partial_symtab *pst; + + pst = find_pc_psymtab (faddr); + if (pst != NULL) + { + struct obj_section *osect; + + ALL_OBJFILE_OSECTIONS (pst->objfile, osect) + { + if (strcmp (osect->the_bfd_section->name, ".dynamic") == 0) + break; + } + + if (osect < pst->objfile->sections_end) + { + CORE_ADDR addr; + + addr = osect->addr; + while (addr < osect->endaddr) + { + int status; + LONGEST tag; + char buf[8]; + + status = target_read_memory (addr, buf, sizeof (buf)); + if (status != 0) + break; + tag = extract_signed_integer (buf, sizeof (buf)); + + if (tag == DT_PLTGOT) + { + CORE_ADDR global_pointer; + + status = target_read_memory (addr + 8, buf, sizeof (buf)); + if (status != 0) + break; + global_pointer = extract_address (buf, sizeof (buf)); + + /* The payoff... */ + return global_pointer; + } + + if (tag == DT_NULL) + break; + + addr += 16; + } + } + } + return 0; +} + +/* Given a function's address, attempt to find (and return) the + corresponding (canonical) function descriptor. Return 0 if + not found. */ +static CORE_ADDR +find_extant_func_descr (CORE_ADDR faddr) +{ + struct partial_symtab *pst; + struct obj_section *osect; + + /* Return early if faddr is already a function descriptor */ + osect = find_pc_section (faddr); + if (osect && strcmp (osect->the_bfd_section->name, ".opd") == 0) + return faddr; + + pst = find_pc_psymtab (faddr); + if (pst != NULL) + { + ALL_OBJFILE_OSECTIONS (pst->objfile, osect) + { + if (strcmp (osect->the_bfd_section->name, ".opd") == 0) + break; + } + + if (osect < pst->objfile->sections_end) + { + CORE_ADDR addr; + + addr = osect->addr; + while (addr < osect->endaddr) + { + int status; + LONGEST faddr2; + char buf[8]; + + status = target_read_memory (addr, buf, sizeof (buf)); + if (status != 0) + break; + faddr2 = extract_signed_integer (buf, sizeof (buf)); + + if (faddr == faddr2) + return addr; + + addr += 16; + } + } + } + return 0; +} + +/* Attempt to find a function descriptor corresponding to the + given address. If none is found, construct one on the + stack using the address at fdaptr */ + +static CORE_ADDR +find_func_descr (CORE_ADDR faddr, CORE_ADDR *fdaptr) +{ + CORE_ADDR fdesc; + + fdesc = find_extant_func_descr (faddr); + + if (fdesc == 0) + { + CORE_ADDR global_pointer; + char buf[16]; + + fdesc = *fdaptr; + *fdaptr += 16; -#define ROUND_UP(n,a) (((n)+(a)-1) & ~((a)-1)) + global_pointer = find_global_pointer (faddr); + if (global_pointer == 0) + global_pointer = read_register (IA64_GR1_REGNUM); + + store_address (buf, 8, faddr); + store_address (buf + 8, 8, global_pointer); + + write_memory (fdesc, buf, 16); + } + + return fdesc; +} + CORE_ADDR ia64_push_arguments (int nargs, value_ptr *args, CORE_ADDR sp, int struct_return, CORE_ADDR struct_addr) @@ -1253,11 +1467,12 @@ ia64_push_arguments (int nargs, value_pt value_ptr arg; struct type *type; int len, argoffset; - int nslots, rseslots, memslots, slotnum; + int nslots, rseslots, memslots, slotnum, nfuncargs; int floatreg; - CORE_ADDR bsp, cfm, pfs, new_bsp; + CORE_ADDR bsp, cfm, pfs, new_bsp, funcdescaddr; nslots = 0; + nfuncargs = 0; /* Count the number of slots needed for the arguments */ for (argno = 0; argno < nargs; argno++) { @@ -1270,12 +1485,17 @@ ia64_push_arguments (int nargs, value_pt if (len > 8 && (nslots & 1)) nslots++; + if (TYPE_CODE (type) == TYPE_CODE_FUNC) + nfuncargs++; + nslots += (len + 7) / 8; } + /* Divvy up the slots between the RSE and the memory stack */ rseslots = (nslots > 8) ? 8 : nslots; memslots = nslots - rseslots; + /* Allocate a new RSE frame */ cfm = read_register (IA64_CFM_REGNUM); bsp = read_register (IA64_BSP_REGNUM); @@ -1292,18 +1512,51 @@ ia64_push_arguments (int nargs, value_pt cfm |= rseslots; write_register (IA64_CFM_REGNUM, cfm); - - - sp = sp - 16 - memslots * 8; + /* We will attempt to find function descriptors in the .opd segment, + but if we can't we'll construct them ourselves. That being the + case, we'll need to reserve space on the stack for them. */ + funcdescaddr = sp - nfuncargs * 16; + funcdescaddr &= ~0xfLL; + + /* Adjust the stack pointer to it's new value. The calling conventions + require us to have 16 bytes of scratch, plus whatever space is + necessary for the memory slots and our function descriptors */ + sp = sp - 16 - (memslots + nfuncargs) * 8; sp &= ~0xfLL; /* Maintain 16 byte alignment */ + /* Place the arguments where they belong. The arguments will be + either placed in the RSE backing store or on the memory stack. + In addition, floating point arguments or HFAs are placed in + floating point registers. */ slotnum = 0; floatreg = IA64_FR8_REGNUM; for (argno = 0; argno < nargs; argno++) { + struct type *float_elt_type; + arg = args[argno]; type = check_typedef (VALUE_TYPE (arg)); len = TYPE_LENGTH (type); + + /* Special handling for function parameters */ + if (len == 8 + && TYPE_CODE (type) == TYPE_CODE_PTR + && TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC) + { + char val_buf[8]; + + store_address (val_buf, 8, + find_func_descr (extract_address (VALUE_CONTENTS (arg), 8), + &funcdescaddr)); + if (slotnum < rseslots) + write_memory (rse_address_add (bsp, slotnum), val_buf, 8); + else + write_memory (sp + 16 + 8 * (slotnum - rseslots), val_buf, 8); + slotnum++; + continue; + } + + /* Normal slots */ if (len > 8 && (slotnum & 1)) slotnum++; argoffset = 0; @@ -1323,22 +1576,36 @@ ia64_push_arguments (int nargs, value_pt len -= 8; slotnum++; } - if (TYPE_CODE (type) == TYPE_CODE_FLT && floatreg < IA64_FR16_REGNUM) - { - ia64_register_convert_to_raw (type, floatreg, VALUE_CONTENTS (arg), - ®isters[REGISTER_BYTE (floatreg)]); - floatreg++; + + /* Handle floating point types (including HFAs) */ + float_elt_type = is_float_or_hfa_type (type); + if (float_elt_type != NULL) + { + argoffset = 0; + len = TYPE_LENGTH (type); + while (len > 0 && floatreg < IA64_FR16_REGNUM) + { + ia64_register_convert_to_raw ( + float_elt_type, + floatreg, + VALUE_CONTENTS (arg) + argoffset, + ®isters[REGISTER_BYTE (floatreg)]); + floatreg++; + argoffset += TYPE_LENGTH (float_elt_type); + len -= TYPE_LENGTH (float_elt_type); + } } } + /* Store the struct return value in r8 if necessary. */ if (struct_return) { store_address (®isters[REGISTER_BYTE (IA64_GR8_REGNUM)], REGISTER_RAW_SIZE (IA64_GR8_REGNUM), struct_addr); } - + /* Sync gdb's idea of what the registers are with the target. */ target_store_registers (-1); /* FIXME: This doesn't belong here! Instead, SAVE_DUMMY_FRAME_TOS needs @@ -1359,64 +1626,10 @@ ia64_push_arguments (int nargs, value_pt CORE_ADDR ia64_push_return_address (CORE_ADDR pc, CORE_ADDR sp) { - struct partial_symtab *pst; - - /* Attempt to determine and set global pointer (r1) for this pc. - - This rather nasty bit of code searchs for the .dynamic section - in the objfile corresponding to the pc of the function we're - trying to call. Once it finds the addresses at which the .dynamic - section lives in the child process, it scans the Elf64_Dyn entries - for a DT_PLTGOT tag. If it finds one of these, the corresponding - d_un.d_ptr value is the global pointer. */ - pst = find_pc_psymtab (pc); - if (pst != NULL) - { - struct obj_section *osect; - - ALL_OBJFILE_OSECTIONS (pst->objfile, osect) - { - if (strcmp (osect->the_bfd_section->name, ".dynamic") == 0) - break; - } - - if (osect < pst->objfile->sections_end) - { - CORE_ADDR addr; - - addr = osect->addr; - while (addr < osect->endaddr) - { - int status; - LONGEST tag; - char buf[8]; + CORE_ADDR global_pointer = find_global_pointer (pc); - status = target_read_memory (addr, buf, sizeof (buf)); - if (status != 0) - break; - tag = extract_signed_integer (buf, sizeof (buf)); - - if (tag == DT_PLTGOT) - { - CORE_ADDR global_pointer; - - status = target_read_memory (addr + 8, buf, sizeof (buf)); - if (status != 0) - break; - global_pointer = extract_address (buf, sizeof (buf)); - - /* The payoff... */ - write_register (IA64_GR1_REGNUM, global_pointer); - break; - } - - if (tag == DT_NULL) - break; - - addr += 16; - } - } - } + if (global_pointer != 0) + write_register (IA64_GR1_REGNUM, global_pointer); write_register (IA64_BR0_REGNUM, CALL_DUMMY_ADDRESS ()); return sp;