From gclayton at apple.com Mon Jan 16 16:21:29 2012 From: gclayton at apple.com (Greg Clayton) Date: Mon, 16 Jan 2012 22:21:29 -0000 Subject: [Lldb-commits] [lldb] r148257 - /lldb/trunk/examples/interposing/darwin/fd_interposing/FDInterposing.cpp Message-ID: <20120116222129.EB7892A6C12C@llvm.org> Author: gclayton Date: Mon Jan 16 16:21:29 2012 New Revision: 148257 URL: http://llvm.org/viewvc/llvm-project?rev=148257&view=rev Log: More improvements to not follow child processes and improved logging that always shows the process info. Modified: lldb/trunk/examples/interposing/darwin/fd_interposing/FDInterposing.cpp Modified: lldb/trunk/examples/interposing/darwin/fd_interposing/FDInterposing.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/interposing/darwin/fd_interposing/FDInterposing.cpp?rev=148257&r1=148256&r2=148257&view=diff ============================================================================== --- lldb/trunk/examples/interposing/darwin/fd_interposing/FDInterposing.cpp (original) +++ lldb/trunk/examples/interposing/darwin/fd_interposing/FDInterposing.cpp Mon Jan 16 16:21:29 2012 @@ -77,6 +77,13 @@ TypeName(const TypeName&); \ const TypeName& operator=(const TypeName&) +extern "C" { + int accept$NOCANCEL (int, struct sockaddr * __restrict, socklen_t * __restrict); + int close$NOCANCEL(int); + int open$NOCANCEL(const char *, int, ...); + int __open_extended(const char *, int, uid_t, gid_t, int, struct kauth_filesec *); +} + namespace fd_interposing { //---------------------------------------------------------------------- @@ -314,8 +321,9 @@ // We compact the file descriptor events by default. Set the environment // varible "FileDescriptorStackLoggingNoCompact" to keep a full history. static int g_compact = 1; -// The name of the process -static char g_program_path[PATH_MAX] = {0}; +// The current process ID +static int g_pid = -1; +static bool g_enabled = true; //---------------------------------------------------------------------- // Mutex class that will lock a mutex when it is constructed, and unlock // it when is goes out of scope @@ -357,6 +365,9 @@ backtrace_log (const char *format, ...) __attribute__ ((format (printf, 1, 2))); static void +backtrace_error (const char *format, ...) __attribute__ ((format (printf, 1, 2))); + +static void log_to_fd (int log_fd, const char *format, ...) __attribute__ ((format (printf, 2, 3))); static inline size_t @@ -373,44 +384,87 @@ return frame_buffer.size(); } +static int g_log_fd = STDOUT_FILENO; +static int g_initialized = 0; + +const char * +get_process_fullpath (bool force = false) +{ + static char g_process_fullpath[PATH_MAX] = {0}; + if (force || g_process_fullpath[0] == '\0') + { + // If DST is NULL, then return the number of bytes needed. + uint32_t len = sizeof(g_process_fullpath); + if (_NSGetExecutablePath (g_process_fullpath, &len) != 0) + strncpy (g_process_fullpath, "", sizeof(g_process_fullpath)); + } + return g_process_fullpath; +} + +// Returns the current process ID, or -1 if inserposing not enabled for +// this process +static int +get_interposed_pid() +{ + if (!g_enabled) + return -1; + + const pid_t pid = getpid(); + if (g_pid != pid) + { + if (g_pid == -1) + { + g_pid = pid; + log ("Interposing file descriptor create and delete functions for %s (pid=%i)\n", get_process_fullpath (true), pid); + } + else + { + log ("pid=%i: disabling interposing file descriptor create and delete functions for child process %s (pid=%i)\n", g_pid, get_process_fullpath (true), pid); + g_enabled = false; + return -1; + } + // Log when our process changes + } + return g_pid; +} + static int get_logging_fd () { - static int g_log_fd = STDOUT_FILENO; - static int initialized = 0; + if (!g_enabled) + return -1; - if (!initialized) + if (!g_initialized) { - initialized = 1; + g_initialized = 1; - // Keep all stack info around for all fd create and delete calls. - // Otherwise we will remove the fd create call when a corresponding - // fd delete call is received - if (getenv("FileDescriptorStackLoggingNoCompact")) - g_compact = 0; + const pid_t pid = get_interposed_pid(); - if (getenv("FileDescriptorMinimalLogging")) - g_log_all_calls = 0; + if (g_enabled) + { + // Keep all stack info around for all fd create and delete calls. + // Otherwise we will remove the fd create call when a corresponding + // fd delete call is received + if (getenv("FileDescriptorStackLoggingNoCompact")) + g_compact = 0; + + if (getenv("FileDescriptorMinimalLogging")) + g_log_all_calls = 0; + + const char *log_path = getenv ("FileDescriptorLogFile"); + if (log_path) + g_log_fd = ::creat (log_path, 0660); + else + g_log_fd = STDOUT_FILENO; - char program_basename[PATH_MAX]; - // If DST is NULL, then return the number of bytes needed. - uint32_t len = sizeof(g_program_path); - if (_NSGetExecutablePath (g_program_path, &len) == 0) + // Only let this interposing happen on the first time this matches + // and stop this from happening so any child processes don't also + // log their file descriptors + ::unsetenv ("DYLD_INSERT_LIBRARIES"); + } + else { - strncpy (program_basename, g_program_path, sizeof(program_basename)); - const char *program_basename_cstr = basename(program_basename); - if (program_basename_cstr) - { - // Only let this interposing happen on the first time this matches - // and stop this from happening so any child processes don't also - // log their file descriptors - ::unsetenv ("DYLD_INSERT_LIBRARIES"); - const char *log_path = getenv ("FileDescriptorLogFile"); - if (log_path) - g_log_fd = ::creat (log_path, 0660); - if (g_log_fd >= 0) - log ("Logging file descriptor functions process '%s' (pid = %i)\n", g_program_path, getpid()); - } + log ("pid=%i: logging disabled\n", getpid()); } } return g_log_fd; @@ -513,7 +567,30 @@ } void -save_backtrace (int fd, int err, const StringSP &string_sp, bool is_create); +backtrace_error (const char *format, ...) +{ + const int pid = get_interposed_pid(); + if (pid >= 0) + { + const int log_fd = get_logging_fd (); + if (log_fd >= 0) + { + log ("\nerror: %s (pid=%i): ", get_process_fullpath (), pid); + + if (format && format[0]) + { + va_list args; + va_start (args, format); + log (format, args); + va_end (args); + } + + Frames frames; + if (get_backtrace(frames, 2)) + ::backtrace_symbols_fd (frames.data(), frames.size(), log_fd); + } + } +} void save_backtrace (int fd, int err, const StringSP &string_sp, bool is_create) @@ -586,19 +663,27 @@ extern "C" int socket$__interposed__ (int domain, int type, int protocol) { - Locker locker (&g_mutex); - const int fd = ::socket (domain, type, protocol); - InvalidFDErrno fd_errno(fd); - StringSP description_sp(new String); - if (fd == -1) - description_sp->printf("socket (domain = %i, type = %i, protocol = %i) => fd=%i errno = %i", domain, type, protocol, fd, fd_errno.get_errno()); - else - description_sp->printf("socket (domain = %i, type = %i, protocol = %i) => fd=%i", domain, type, protocol, fd); - if (g_log_all_calls) - description_sp->log (get_logging_fd()); - if (fd >= 0) - save_backtrace (fd, fd_errno.get_errno(), description_sp, true); - return fd; + const int pid = get_interposed_pid(); + if (pid >= 0) + { + Locker locker (&g_mutex); + const int fd = ::socket (domain, type, protocol); + InvalidFDErrno fd_errno(fd); + StringSP description_sp(new String); + if (fd == -1) + description_sp->printf("pid=%i: socket (domain = %i, type = %i, protocol = %i) => fd=%i errno = %i", pid, domain, type, protocol, fd, fd_errno.get_errno()); + else + description_sp->printf("pid=%i: socket (domain = %i, type = %i, protocol = %i) => fd=%i", pid, domain, type, protocol, fd); + if (g_log_all_calls) + description_sp->log (get_logging_fd()); + if (fd >= 0) + save_backtrace (fd, fd_errno.get_errno(), description_sp, true); + return fd; + } + else + { + return ::socket (domain, type, protocol); + } } //---------------------------------------------------------------------- @@ -607,19 +692,27 @@ extern "C" int socketpair$__interposed__ (int domain, int type, int protocol, int fds[2]) { - Locker locker (&g_mutex); - fds[0] = -1; - fds[1] = -1; - const int err = socketpair (domain, type, protocol, fds); - NegativeErrorErrno err_errno(err); - StringSP description_sp(new String ("socketpair (domain=%i, type=%i, protocol=%i, {fd=%i, fd=%i}) -> err=%i", domain, type, protocol, fds[0], fds[1], err)); - if (g_log_all_calls) - description_sp->log (get_logging_fd()); - if (fds[0] >= 0) - save_backtrace (fds[0], err_errno.get_errno(), description_sp, true); - if (fds[1] >= 0) - save_backtrace (fds[1], err_errno.get_errno(), description_sp, true); - return err; + const int pid = get_interposed_pid(); + if (pid >= 0) + { + Locker locker (&g_mutex); + fds[0] = -1; + fds[1] = -1; + const int err = socketpair (domain, type, protocol, fds); + NegativeErrorErrno err_errno(err); + StringSP description_sp(new String ("pid=%i: socketpair (domain=%i, type=%i, protocol=%i, {fd=%i, fd=%i}) -> err=%i", pid, domain, type, protocol, fds[0], fds[1], err)); + if (g_log_all_calls) + description_sp->log (get_logging_fd()); + if (fds[0] >= 0) + save_backtrace (fds[0], err_errno.get_errno(), description_sp, true); + if (fds[1] >= 0) + save_backtrace (fds[1], err_errno.get_errno(), description_sp, true); + return err; + } + else + { + return socketpair (domain, type, protocol, fds); + } } //---------------------------------------------------------------------- @@ -628,48 +721,61 @@ extern "C" int open$__interposed__ (const char *path, int oflag, int mode) { - Locker locker (&g_mutex); - int fd = -2; - StringSP description_sp(new String); - if (oflag & O_CREAT) + const int pid = get_interposed_pid(); + if (pid >= 0) { - fd = open (path, oflag, mode); - description_sp->printf("open (path = '%s', oflag = %i, mode = %i) -> fd=%i", path, oflag, mode, fd); + Locker locker (&g_mutex); + int fd = -2; + StringSP description_sp(new String); + if (oflag & O_CREAT) + { + fd = ::open (path, oflag, mode); + description_sp->printf("pid=%i: open (path = '%s', oflag = %i, mode = %i) -> fd=%i", pid, path, oflag, mode, fd); + } + else + { + fd = ::open (path, oflag); + description_sp->printf("pid=%i: open (path = '%s', oflag = %i) -> fd=%i", pid, path, oflag, fd); + } + + InvalidFDErrno fd_errno(fd); + if (g_log_all_calls) + description_sp->log (get_logging_fd()); + if (fd >= 0) + save_backtrace (fd, fd_errno.get_errno(), description_sp, true); + return fd; } else { - fd = open (path, oflag); - description_sp->printf("open (path = '%s', oflag = %i) -> fd=%i", path, oflag, fd); + return ::open (path, oflag, mode); } - - InvalidFDErrno fd_errno(fd); - if (g_log_all_calls) - description_sp->log (get_logging_fd()); - if (fd >= 0) - save_backtrace (fd, fd_errno.get_errno(), description_sp, true); - return fd; } //---------------------------------------------------------------------- // open$NOCANCEL() interpose function //---------------------------------------------------------------------- -extern "C" int open$NOCANCEL(const char *, int, ...); -extern "C" int __open_nocancel(const char *, int, ...); extern "C" int open$NOCANCEL$__interposed__ (const char *path, int oflag, int mode) { - Locker locker (&g_mutex); - const int fd = open$NOCANCEL (path, oflag, mode); - InvalidFDErrno fd_errno(fd); - StringSP description_sp(new String ("open$NOCANCEL (path = '%s', oflag = %i, mode = %i) -> fd=%i", path, oflag, mode, fd)); - if (g_log_all_calls) - description_sp->log (get_logging_fd()); - if (fd >= 0) - save_backtrace (fd, fd_errno.get_errno(), description_sp, true); - return fd; + const int pid = get_interposed_pid(); + if (pid >= 0) + { + Locker locker (&g_mutex); + const int fd = ::open$NOCANCEL (path, oflag, mode); + InvalidFDErrno fd_errno(fd); + StringSP description_sp(new String ("pid=%i: open$NOCANCEL (path = '%s', oflag = %i, mode = %i) -> fd=%i", pid, path, oflag, mode, fd)); + if (g_log_all_calls) + description_sp->log (get_logging_fd()); + if (fd >= 0) + save_backtrace (fd, fd_errno.get_errno(), description_sp, true); + return fd; + } + else + { + return ::open$NOCANCEL (path, oflag, mode); + } } -extern "C" int __open_extended(const char *, int, uid_t, gid_t, int, struct kauth_filesec *); //---------------------------------------------------------------------- // __open_extended() interpose function @@ -677,15 +783,23 @@ extern "C" int __open_extended$__interposed__ (const char *path, int oflag, uid_t uid, gid_t gid, int mode, struct kauth_filesec *fsacl) { - Locker locker (&g_mutex); - const int fd = __open_extended (path, oflag, uid, gid, mode, fsacl); - InvalidFDErrno fd_errno(fd); - StringSP description_sp(new String ("__open_extended (path='%s', oflag=%i, uid=%i, gid=%i, mode=%i, fsacl=%p) -> fd=%i", path, oflag, uid, gid, mode, fsacl, fd)); - if (g_log_all_calls) - description_sp->log (get_logging_fd()); - if (fd >= 0) - save_backtrace (fd, fd_errno.get_errno(), description_sp, true); - return fd; + const int pid = get_interposed_pid(); + if (pid >= 0) + { + Locker locker (&g_mutex); + const int fd = ::__open_extended (path, oflag, uid, gid, mode, fsacl); + InvalidFDErrno fd_errno(fd); + StringSP description_sp(new String ("pid=%i: __open_extended (path='%s', oflag=%i, uid=%i, gid=%i, mode=%i, fsacl=%p) -> fd=%i", pid, path, oflag, uid, gid, mode, fsacl, fd)); + if (g_log_all_calls) + description_sp->log (get_logging_fd()); + if (fd >= 0) + save_backtrace (fd, fd_errno.get_errno(), description_sp, true); + return fd; + } + else + { + return ::__open_extended (path, oflag, uid, gid, mode, fsacl); + } } //---------------------------------------------------------------------- @@ -694,16 +808,23 @@ extern "C" int kqueue$__interposed__ (void) { - Locker locker (&g_mutex); - const int fd = ::kqueue (); - InvalidFDErrno fd_errno(fd); - StringSP description_sp(new String ("kqueue () -> fd=%i", fd)); - if (g_log_all_calls) - description_sp->log (get_logging_fd()); - if (fd >= 0) - save_backtrace (fd, fd_errno.get_errno(), description_sp, true); - return fd; - + const int pid = get_interposed_pid(); + if (pid >= 0) + { + Locker locker (&g_mutex); + const int fd = ::kqueue (); + InvalidFDErrno fd_errno(fd); + StringSP description_sp(new String ("pid=%i: kqueue () -> fd=%i", pid, fd)); + if (g_log_all_calls) + description_sp->log (get_logging_fd()); + if (fd >= 0) + save_backtrace (fd, fd_errno.get_errno(), description_sp, true); + return fd; + } + else + { + return ::kqueue (); + } } //---------------------------------------------------------------------- @@ -712,15 +833,23 @@ extern "C" int shm_open$__interposed__ (const char *path, int oflag, int mode) { - Locker locker (&g_mutex); - const int fd = shm_open (path, oflag, mode); - InvalidFDErrno fd_errno(fd); - StringSP description_sp(new String ("shm_open (path = '%s', oflag = %i, mode = %i) -> fd=%i", path, oflag, mode, fd)); - if (g_log_all_calls) - description_sp->log (get_logging_fd()); - if (fd >= 0) - save_backtrace (fd, fd_errno.get_errno(), description_sp, true); - return fd; + const int pid = get_interposed_pid(); + if (pid >= 0) + { + Locker locker (&g_mutex); + const int fd = ::shm_open (path, oflag, mode); + InvalidFDErrno fd_errno(fd); + StringSP description_sp(new String ("pid=%i: shm_open (path = '%s', oflag = %i, mode = %i) -> fd=%i", pid, path, oflag, mode, fd)); + if (g_log_all_calls) + description_sp->log (get_logging_fd()); + if (fd >= 0) + save_backtrace (fd, fd_errno.get_errno(), description_sp, true); + return fd; + } + else + { + return ::shm_open (path, oflag, mode); + } } //---------------------------------------------------------------------- @@ -729,34 +858,49 @@ extern "C" int accept$__interposed__ (int socket, struct sockaddr *address, socklen_t *address_len) { - Locker locker (&g_mutex); - const int fd = accept (socket, address, address_len); - InvalidFDErrno fd_errno(fd); - StringSP description_sp(new String ("accept (socket=%i, ...) -> fd=%i", socket, fd)); - if (g_log_all_calls) - description_sp->log (get_logging_fd()); - if (fd >= 0) - save_backtrace (fd, fd_errno.get_errno(), description_sp, true); - return fd; + const int pid = get_interposed_pid(); + if (pid >= 0) + { + Locker locker (&g_mutex); + const int fd = ::accept (socket, address, address_len); + InvalidFDErrno fd_errno(fd); + StringSP description_sp(new String ("pid=%i: accept (socket=%i, ...) -> fd=%i", pid, socket, fd)); + if (g_log_all_calls) + description_sp->log (get_logging_fd()); + if (fd >= 0) + save_backtrace (fd, fd_errno.get_errno(), description_sp, true); + return fd; + } + else + { + return ::accept (socket, address, address_len); + } } //---------------------------------------------------------------------- // accept$NOCANCEL() interpose function //---------------------------------------------------------------------- -extern "C" int accept$NOCANCEL (int, struct sockaddr * __restrict, socklen_t * __restrict); extern "C" int accept$NOCANCEL$__interposed__ (int socket, struct sockaddr *address, socklen_t *address_len) { - Locker locker (&g_mutex); - const int fd = accept$NOCANCEL (socket, address, address_len); - InvalidFDErrno fd_errno(fd); - StringSP description_sp(new String ("accept$NOCANCEL (socket=%i, ...) -> fd=%i", socket, fd)); - if (g_log_all_calls) - description_sp->log (get_logging_fd()); - if (fd >= 0) - save_backtrace (fd, fd_errno.get_errno(), description_sp, true); - return fd; + const int pid = get_interposed_pid(); + if (pid >= 0) + { + Locker locker (&g_mutex); + const int fd = ::accept$NOCANCEL (socket, address, address_len); + InvalidFDErrno fd_errno(fd); + StringSP description_sp(new String ("pid=%i: accept$NOCANCEL (socket=%i, ...) -> fd=%i", pid, socket, fd)); + if (g_log_all_calls) + description_sp->log (get_logging_fd()); + if (fd >= 0) + save_backtrace (fd, fd_errno.get_errno(), description_sp, true); + return fd; + } + else + { + return ::accept$NOCANCEL (socket, address, address_len); + } } //---------------------------------------------------------------------- @@ -765,15 +909,23 @@ extern "C" int dup$__interposed__ (int fd2) { - Locker locker (&g_mutex); - const int fd = dup (fd2); - InvalidFDErrno fd_errno(fd); - StringSP description_sp(new String ("dup (fd2=%i) -> fd=%i", fd2, fd)); - if (g_log_all_calls) - description_sp->log (get_logging_fd()); - if (fd >= 0) - save_backtrace (fd, fd_errno.get_errno(), description_sp, true); - return fd; + const int pid = get_interposed_pid(); + if (pid >= 0) + { + Locker locker (&g_mutex); + const int fd = ::dup (fd2); + InvalidFDErrno fd_errno(fd); + StringSP description_sp(new String ("pid=%i: dup (fd2=%i) -> fd=%i", pid, fd2, fd)); + if (g_log_all_calls) + description_sp->log (get_logging_fd()); + if (fd >= 0) + save_backtrace (fd, fd_errno.get_errno(), description_sp, true); + return fd; + } + else + { + return ::dup (fd2); + } } //---------------------------------------------------------------------- @@ -782,24 +934,32 @@ extern "C" int dup2$__interposed__ (int fd1, int fd2) { - Locker locker (&g_mutex); - // If "fd2" is already opened, it will be closed during the - // dup2 call below, so we need to see if we have fd2 in our - // open map and treat it as a close(fd2) - FDEventMap::iterator pos = g_fd_event_map.find (fd2); - StringSP dup2_close_description_sp(new String ("dup2 (fd1=%i, fd2=%i) -> will close (fd=%i)", fd1, fd2, fd2)); - if (pos != g_fd_event_map.end() && pos->second.back()->IsCreateEvent()) - save_backtrace (fd2, 0, dup2_close_description_sp, false); - - const int fd = dup2(fd1, fd2); - InvalidFDErrno fd_errno(fd); - StringSP description_sp(new String ("dup2 (fd1=%i, fd2=%i) -> fd=%i", fd1, fd2, fd)); - if (g_log_all_calls) - description_sp->log (get_logging_fd()); - - if (fd >= 0) - save_backtrace (fd, fd_errno.get_errno(), description_sp, true); - return fd; + const int pid = get_interposed_pid(); + if (pid >= 0) + { + Locker locker (&g_mutex); + // If "fd2" is already opened, it will be closed during the + // dup2 call below, so we need to see if we have fd2 in our + // open map and treat it as a close(fd2) + FDEventMap::iterator pos = g_fd_event_map.find (fd2); + StringSP dup2_close_description_sp(new String ("pid=%i: dup2 (fd1=%i, fd2=%i) -> will close (fd=%i)", pid, fd1, fd2, fd2)); + if (pos != g_fd_event_map.end() && pos->second.back()->IsCreateEvent()) + save_backtrace (fd2, 0, dup2_close_description_sp, false); + + const int fd = ::dup2(fd1, fd2); + InvalidFDErrno fd_errno(fd); + StringSP description_sp(new String ("pid=%i: dup2 (fd1=%i, fd2=%i) -> fd=%i", pid, fd1, fd2, fd)); + if (g_log_all_calls) + description_sp->log (get_logging_fd()); + + if (fd >= 0) + save_backtrace (fd, fd_errno.get_errno(), description_sp, true); + return fd; + } + else + { + return ::dup2(fd1, fd2); + } } //---------------------------------------------------------------------- @@ -808,76 +968,90 @@ extern "C" int close$__interposed__ (int fd) { - Locker locker (&g_mutex); - const int err = close(fd); - NegativeErrorErrno err_errno(err); - StringSP description_sp (new String); - if (err == -1) - description_sp->printf("close (fd=%i) => %i errno = %i (%s))", fd, err, err_errno.get_errno(), strerror(err_errno.get_errno())); - else - description_sp->printf("close (fd=%i) => %i", fd, err); - if (g_log_all_calls) - description_sp->log (get_logging_fd()); - - if (err == 0) - { - if (fd >= 0) - save_backtrace (fd, err, description_sp, false); - } - else if (err == -1) + const int pid = get_interposed_pid(); + if (pid >= 0) { - if (err_errno.get_errno() == EBADF && fd != -1) - { - backtrace_log ("\nerror: close on fd=%d resulted in EBADF in process %s (pid = %i)\n", fd, g_program_path, getpid()); + Locker locker (&g_mutex); + const int err = close(fd); + NegativeErrorErrno err_errno(err); + StringSP description_sp (new String); + if (err == -1) + description_sp->printf("pid=%i: close (fd=%i) => %i errno = %i (%s))", pid, fd, err, err_errno.get_errno(), strerror(err_errno.get_errno())); + else + description_sp->printf("pid=%i: close (fd=%i) => %i", pid, fd, err); + if (g_log_all_calls) + description_sp->log (get_logging_fd()); - FDEventMap::iterator pos = g_fd_event_map.find (fd); - if (pos != g_fd_event_map.end()) + if (err == 0) + { + if (fd >= 0) + save_backtrace (fd, err, description_sp, false); + } + else if (err == -1) + { + if (err_errno.get_errno() == EBADF && fd != -1) { - log (get_logging_fd(), pos->second.back().get(), "\nfd=%d was previously %s with this event:\n", fd, pos->second.back()->IsCreateEvent() ? "opened" : "closed"); + backtrace_error ("close (fd=%d) resulted in EBADF:\n", fd); + + FDEventMap::iterator pos = g_fd_event_map.find (fd); + if (pos != g_fd_event_map.end()) + { + log (get_logging_fd(), pos->second.back().get(), "\nfd=%d was previously %s with this event:\n", fd, pos->second.back()->IsCreateEvent() ? "opened" : "closed"); + } } } + return err; + } + else + { + return close (fd); } - return err; } //---------------------------------------------------------------------- // close$NOCANCEL() interpose function //---------------------------------------------------------------------- -extern "C" int close$NOCANCEL(int); extern "C" int close$NOCANCEL$__interposed__ (int fd) { - Locker locker (&g_mutex); - const int err = close$NOCANCEL(fd); - NegativeErrorErrno err_errno(err); - StringSP description_sp (new String); - if (err == -1) - description_sp->printf("close$NOCANCEL (fd=%i) => %i errno = %i (%s))", fd, err, err_errno.get_errno(), strerror(err_errno.get_errno())); - else - description_sp->printf("close$NOCANCEL (fd=%i) => %i", fd, err); - if (g_log_all_calls) - description_sp->log (get_logging_fd()); - - if (err == 0) - { - if (fd >= 0) - save_backtrace (fd, err, description_sp, false); - } - else if (err == -1) + const int pid = get_interposed_pid(); + if (pid >= 0) { - if (err_errno.get_errno() == EBADF && fd != -1) + Locker locker (&g_mutex); + const int err = close$NOCANCEL(fd); + NegativeErrorErrno err_errno(err); + StringSP description_sp (new String); + if (err == -1) + description_sp->printf("pid=%i: close$NOCANCEL (fd=%i) => %i errno = %i (%s))", pid, fd, err, err_errno.get_errno(), strerror(err_errno.get_errno())); + else + description_sp->printf("pid=%i: close$NOCANCEL (fd=%i) => %i", pid, fd, err); + if (g_log_all_calls) + description_sp->log (get_logging_fd()); + + if (err == 0) { - backtrace_log ("\nerror: close$NOCANCEL on fd=%d resulted in EBADF in process %s (pid = %i)\n", fd, g_program_path, getpid()); - - FDEventMap::iterator pos = g_fd_event_map.find (fd); - if (pos != g_fd_event_map.end()) + if (fd >= 0) + save_backtrace (fd, err, description_sp, false); + } + else if (err == -1) + { + if (err_errno.get_errno() == EBADF && fd != -1) { - log (get_logging_fd(), pos->second.back().get(), "\nfd=%d was previously %s with this event:\n", fd, pos->second.back()->IsCreateEvent() ? "opened" : "closed"); + backtrace_error ("close$NOCANCEL (fd=%d) resulted in EBADF\n:", fd); + + FDEventMap::iterator pos = g_fd_event_map.find (fd); + if (pos != g_fd_event_map.end()) + { + log (get_logging_fd(), pos->second.back().get(), "\nfd=%d was previously %s with this event:\n", fd, pos->second.back()->IsCreateEvent() ? "opened" : "closed"); + } } } + return err; } - return err; - + else + { + return close$NOCANCEL(fd); + } } //---------------------------------------------------------------------- @@ -886,20 +1060,28 @@ extern "C" int pipe$__interposed__ (int fds[2]) { - Locker locker (&g_mutex); - fds[0] = -1; - fds[1] = -1; - const int err = pipe (fds); - const int saved_errno = errno; - StringSP description_sp(new String ("pipe ({fd=%i, fd=%i}) -> err=%i", fds[0], fds[1], err)); - if (g_log_all_calls) - description_sp->log (get_logging_fd()); - if (fds[0] >= 0) - save_backtrace (fds[0], saved_errno, description_sp, true); - if (fds[1] >= 0) - save_backtrace (fds[1], saved_errno, description_sp, true); - errno = saved_errno; - return err; + const int pid = get_interposed_pid(); + if (pid >= 0) + { + Locker locker (&g_mutex); + fds[0] = -1; + fds[1] = -1; + const int err = pipe (fds); + const int saved_errno = errno; + StringSP description_sp(new String ("pid=%i: pipe ({fd=%i, fd=%i}) -> err=%i", pid, fds[0], fds[1], err)); + if (g_log_all_calls) + description_sp->log (get_logging_fd()); + if (fds[0] >= 0) + save_backtrace (fds[0], saved_errno, description_sp, true); + if (fds[1] >= 0) + save_backtrace (fds[1], saved_errno, description_sp, true); + errno = saved_errno; + return err; + } + else + { + return pipe (fds); + } } //---------------------------------------------------------------------- @@ -955,7 +1137,6 @@ DYLD_INTERPOSE(kqueue$__interposed__, kqueue); DYLD_INTERPOSE(open$__interposed__, open); DYLD_INTERPOSE(open$NOCANCEL$__interposed__, open$NOCANCEL); -DYLD_INTERPOSE(open$NOCANCEL$__interposed__, __open_nocancel); DYLD_INTERPOSE(__open_extended$__interposed__, __open_extended); DYLD_INTERPOSE(pipe$__interposed__, pipe); DYLD_INTERPOSE(shm_open$__interposed__, shm_open); From johnny.chen at apple.com Mon Jan 16 18:58:08 2012 From: johnny.chen at apple.com (Johnny Chen) Date: Tue, 17 Jan 2012 00:58:08 -0000 Subject: [Lldb-commits] [lldb] r148269 - /lldb/trunk/test/make/Makefile.rules Message-ID: <20120117005808.A0AB92A6C12C@llvm.org> Author: johnny Date: Mon Jan 16 18:58:08 2012 New Revision: 148269 URL: http://llvm.org/viewvc/llvm-project?rev=148269&view=rev Log: Add usage example from test/functionalities/archives/Makefile. Modified: lldb/trunk/test/make/Makefile.rules Modified: lldb/trunk/test/make/Makefile.rules URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/make/Makefile.rules?rev=148269&r1=148268&r2=148269&view=diff ============================================================================== --- lldb/trunk/test/make/Makefile.rules (original) +++ lldb/trunk/test/make/Makefile.rules Mon Jan 16 18:58:08 2012 @@ -12,10 +12,15 @@ # the building of the a.out executable program. For example, # DYLIB_ONLY := YES # -# And also might be of interest: +# Also might be of interest: # FRAMEWORK_INCLUDES (Darwin only) := # CFLAGS_EXTRAS := # LD_EXTRAS := +# +# And test/functionalities/archives/Makefile: +# MAKE_DSYM := NO +# ARCHIVE_NAME := libfoo.a +# ARCHIVE_C_SOURCES := a.c b.c # Uncomment line below for debugging shell commands # SHELL = /bin/sh -x From johnny.chen at apple.com Mon Jan 16 19:26:06 2012 From: johnny.chen at apple.com (Johnny Chen) Date: Tue, 17 Jan 2012 01:26:06 -0000 Subject: [Lldb-commits] [lldb] r148273 - /lldb/trunk/test/dotest.py Message-ID: <20120117012606.7629E2A6C12C@llvm.org> Author: johnny Date: Mon Jan 16 19:26:06 2012 New Revision: 148273 URL: http://llvm.org/viewvc/llvm-project?rev=148273&view=rev Log: Add usage example of specifying the full path to the compiler used while building the debuggees for running the test suite. Modified: lldb/trunk/test/dotest.py Modified: lldb/trunk/test/dotest.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/dotest.py?rev=148273&r1=148272&r2=148273&view=diff ============================================================================== --- lldb/trunk/test/dotest.py (original) +++ lldb/trunk/test/dotest.py Mon Jan 16 19:26:06 2012 @@ -181,6 +181,7 @@ -A x86_64^i386 => launch inferior with x86_64 and i386 architectures -C : specify the compiler(s) used to build the inferior executable -C clang => build debuggee using clang compiler + -C /my/full/path/to/clang => specify a full path to the clang binary -C clang^gcc => build debuggee using clang and gcc compilers -D : dump the Python sys.path variable -a : don't do lldb Python API tests From jingham at apple.com Mon Jan 16 20:17:45 2012 From: jingham at apple.com (Jim Ingham) Date: Tue, 17 Jan 2012 02:17:45 -0000 Subject: [Lldb-commits] [lldb] r148280 - /lldb/trunk/test/lang/objc/objc-ivar-offsets/TestObjCIvarOffsets.py Message-ID: <20120117021745.D76652A6C12C@llvm.org> Author: jingham Date: Mon Jan 16 20:17:45 2012 New Revision: 148280 URL: http://llvm.org/viewvc/llvm-project?rev=148280&view=rev Log: Fix the test properly now that SBValue::GetValueAsUnsigned works for bitfields. Modified: lldb/trunk/test/lang/objc/objc-ivar-offsets/TestObjCIvarOffsets.py Modified: lldb/trunk/test/lang/objc/objc-ivar-offsets/TestObjCIvarOffsets.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/objc-ivar-offsets/TestObjCIvarOffsets.py?rev=148280&r1=148279&r2=148280&view=diff ============================================================================== --- lldb/trunk/test/lang/objc/objc-ivar-offsets/TestObjCIvarOffsets.py (original) +++ lldb/trunk/test/lang/objc/objc-ivar-offsets/TestObjCIvarOffsets.py Mon Jan 16 20:17:45 2012 @@ -76,10 +76,6 @@ mine_flag2 = mine.GetChildMemberWithName ("flag2") self.assertTrue(mine_flag2, "Found mine->flag2 local variable.") - flag2_value = int (mine_flag2.GetValue (), 0) - self.assertTrue (flag2_value == 7) - - # GetValueAsUnsigned fails for bit-fields: flag2_value = mine_flag2.GetValueAsUnsigned (error) self.assertTrue (error.Success()) self.assertTrue (flag2_value == 7) From johnny.chen at apple.com Tue Jan 17 23:15:00 2012 From: johnny.chen at apple.com (Johnny Chen) Date: Wed, 18 Jan 2012 05:15:00 -0000 Subject: [Lldb-commits] [lldb] r148379 - /lldb/trunk/test/dotest.py Message-ID: <20120118051500.983942A6C12C@llvm.org> Author: johnny Date: Tue Jan 17 23:15:00 2012 New Revision: 148379 URL: http://llvm.org/viewvc/llvm-project?rev=148379&view=rev Log: Add a '-X excluded-dir' option to the test driver to exclude a directory from consideration during test discovery. For example: ./dotest.py -X types -v from the test dir will ignore test cases under test/types. Modified: lldb/trunk/test/dotest.py Modified: lldb/trunk/test/dotest.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/dotest.py?rev=148379&r1=148378&r2=148379&view=diff ============================================================================== --- lldb/trunk/test/dotest.py (original) +++ lldb/trunk/test/dotest.py Tue Jan 17 23:15:00 2012 @@ -110,6 +110,9 @@ # The benchamrk iteration count, as specified by the '-y' option. bmIterationCount = -1 +# By default, don't exclude any directories. Use '-X' to add one excluded directory. +excluded = set(['.svn', '.git']) + # By default, failfast is False. Use '-F' to overwrite it. failfast = False @@ -227,6 +230,9 @@ timestamp as the session dir name -t : turn on tracing of lldb command and other detailed test executions -v : do verbose mode of unittest framework (print out each test case invocation) +-X : exclude a directory from consideration for test discovery + -X types => if 'types' appear in the pathname components of a potential testfile + it will be ignored -x : specify the breakpoint specification for the benchmark executable; see also '-e', which provides the full path of the executable -y : specify the iteration count used to collect our benchmarks; an example is @@ -503,6 +509,13 @@ elif sys.argv[index].startswith('-w'): os.environ["LLDB_WAIT_BETWEEN_TEST_CASES"] = 'YES' index += 1 + elif sys.argv[index].startswith('-X'): + # Increment by 1 to fetch an excluded directory. + index += 1 + if index >= len(sys.argv): + usage() + excluded.add(sys.argv[index]) + index += 1 elif sys.argv[index].startswith('-x'): # Increment by 1 to fetch the breakpoint specification of the benchmark executable. index += 1 @@ -781,6 +794,11 @@ global regexp global filters global fs4all + global excluded + + if set(dir.split(os.sep)).intersection(excluded): + #print "Detected an excluded dir component: %s" % dir + return for name in names: if os.path.isdir(os.path.join(dir, name)): From jmolenda at apple.com Tue Jan 17 23:19:16 2012 From: jmolenda at apple.com (Jason Molenda) Date: Wed, 18 Jan 2012 05:19:16 -0000 Subject: [Lldb-commits] [lldb] r148380 - in /lldb/trunk: lldb.xcodeproj/project.pbxproj resources/LLDB-Info.plist Message-ID: <20120118051916.437F92A6C12C@llvm.org> Author: jmolenda Date: Tue Jan 17 23:19:15 2012 New Revision: 148380 URL: http://llvm.org/viewvc/llvm-project?rev=148380&view=rev Log: Bump version number past lldb-107. Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj lldb/trunk/resources/LLDB-Info.plist Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=148380&r1=148379&r2=148380&view=diff ============================================================================== --- lldb/trunk/lldb.xcodeproj/project.pbxproj (original) +++ lldb/trunk/lldb.xcodeproj/project.pbxproj Tue Jan 17 23:19:15 2012 @@ -3733,9 +3733,9 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CURRENT_PROJECT_VERSION = 106; + CURRENT_PROJECT_VERSION = 107; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 106; + DYLIB_CURRENT_VERSION = 107; EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3793,10 +3793,10 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CURRENT_PROJECT_VERSION = 106; + CURRENT_PROJECT_VERSION = 107; DEAD_CODE_STRIPPING = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 106; + DYLIB_CURRENT_VERSION = 107; EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3852,8 +3852,8 @@ 2689FFD513353D7A00698AC0 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 106; - DYLIB_CURRENT_VERSION = 106; + CURRENT_PROJECT_VERSION = 107; + DYLIB_CURRENT_VERSION = 107; EXECUTABLE_EXTENSION = a; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3881,8 +3881,8 @@ 2689FFD613353D7A00698AC0 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 106; - DYLIB_CURRENT_VERSION = 106; + CURRENT_PROJECT_VERSION = 107; + DYLIB_CURRENT_VERSION = 107; EXECUTABLE_EXTENSION = a; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3910,8 +3910,8 @@ 2689FFD713353D7A00698AC0 /* BuildAndIntegration */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 106; - DYLIB_CURRENT_VERSION = 106; + CURRENT_PROJECT_VERSION = 107; + DYLIB_CURRENT_VERSION = 107; EXECUTABLE_EXTENSION = a; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3991,7 +3991,7 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 106; + CURRENT_PROJECT_VERSION = 107; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"", @@ -4022,10 +4022,10 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 106; + CURRENT_PROJECT_VERSION = 107; DEAD_CODE_STRIPPING = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 106; + DYLIB_CURRENT_VERSION = 107; EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -4269,7 +4269,7 @@ 26F5C26C10F3D9A5009D5894 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 106; + CURRENT_PROJECT_VERSION = 107; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"", @@ -4299,7 +4299,7 @@ 26F5C26D10F3D9A5009D5894 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 106; + CURRENT_PROJECT_VERSION = 107; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"", Modified: lldb/trunk/resources/LLDB-Info.plist URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/resources/LLDB-Info.plist?rev=148380&r1=148379&r2=148380&view=diff ============================================================================== --- lldb/trunk/resources/LLDB-Info.plist (original) +++ lldb/trunk/resources/LLDB-Info.plist Tue Jan 17 23:19:15 2012 @@ -17,7 +17,7 @@ CFBundleSignature ???? CFBundleVersion - 106 + 107 CFBundleName ${EXECUTABLE_NAME} From johnny.chen at apple.com Wed Jan 18 13:07:08 2012 From: johnny.chen at apple.com (Johnny Chen) Date: Wed, 18 Jan 2012 19:07:08 -0000 Subject: [Lldb-commits] [lldb] r148403 - /lldb/trunk/test/settings/TestSettings.py Message-ID: <20120118190708.7EB632A6C12C@llvm.org> Author: johnny Date: Wed Jan 18 13:07:08 2012 New Revision: 148403 URL: http://llvm.org/viewvc/llvm-project?rev=148403&view=rev Log: Add a test case where 'settings set frame-format' supplies a format string containing, among other things, a single backtick character. rdar://problem/10712130 Modified: lldb/trunk/test/settings/TestSettings.py Modified: lldb/trunk/test/settings/TestSettings.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/settings/TestSettings.py?rev=148403&r1=148402&r2=148403&view=diff ============================================================================== --- lldb/trunk/test/settings/TestSettings.py (original) +++ lldb/trunk/test/settings/TestSettings.py Wed Jan 18 13:07:08 2012 @@ -57,6 +57,27 @@ self.expect("settings show", SETTING_MSG("term-width"), substrs = ["term-width (int) = 70"]) + #rdar://problem/10712130 + @unittest2.expectedFailure + def test_set_frame_format(self): + """Test that 'set frame-format' with a backtick char in the format string works as well as fullpath.""" + self.buildDefault() + + exe = os.path.join(os.getcwd(), "a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + format_string = "frame #${frame.index}: ${frame.pc}{ ${module.file.basename}`${function.name-with-args}{${function.pc-offset}}}{ at ${line.file.fullpath}:${line.number}}\n" + self.runCmd("settings set frame-format %s" % format_string) + + # Immediately test the setting. + self.expect("settings show frame-format", SETTING_MSG("frame-format"), + substrs = [format_string]) + + self.runCmd("breakpoint set -n main") + self.runCmd("run") + self.expect("thread backtrace", + substrs = ["`main", os.getcwd()]) + def test_set_auto_confirm(self): """Test that after 'set auto-confirm true', manual confirmation should not kick in.""" self.buildDefault() From gclayton at apple.com Wed Jan 18 14:58:13 2012 From: gclayton at apple.com (Greg Clayton) Date: Wed, 18 Jan 2012 20:58:13 -0000 Subject: [Lldb-commits] [lldb] r148413 - in /lldb/trunk/source/Plugins/SymbolFile/DWARF: HashedNameToDIE.h SymbolFileDWARF.cpp Message-ID: <20120118205813.2733D2A6C12C@llvm.org> Author: gclayton Date: Wed Jan 18 14:58:12 2012 New Revision: 148413 URL: http://llvm.org/viewvc/llvm-project?rev=148413&view=rev Log: Fixed an issue where we might not find the one true ObjC definition. Now we do things much smarter by extracting search results more efficiently and by properly obeying the must_be_implementation bool in the SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE() function. Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h?rev=148413&r1=148412&r2=148413&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h Wed Jan 18 14:58:12 2012 @@ -96,21 +96,6 @@ } } } - - static void - ExtractTypesFromDIEArray (const DIEInfoArray &die_info_array, - uint32_t type_flag_mask, - uint32_t type_flag_value, - DIEArray &die_offsets) - { - const size_t count = die_info_array.size(); - for (size_t i=0; iFindCompleteObjCClassByName (name_cstr, die_offsets); + m_apple_types_ap->FindCompleteObjCClassByName (name_cstr, die_offsets, must_be_implementation); } } else From johnny.chen at apple.com Wed Jan 18 15:20:03 2012 From: johnny.chen at apple.com (Johnny Chen) Date: Wed, 18 Jan 2012 21:20:03 -0000 Subject: [Lldb-commits] [lldb] r148417 - /lldb/trunk/test/python_api/hello_world/TestHelloWorld.py Message-ID: <20120118212003.E91E02A6C12C@llvm.org> Author: johnny Date: Wed Jan 18 15:20:03 2012 New Revision: 148417 URL: http://llvm.org/viewvc/llvm-project?rev=148417&view=rev Log: Modify the test cases so that each uses a unique executable name for the debugger to attach/launch. I've see cases where there are lingering processes ("hello_world") staying around and the test_with_dsym_and_attach_to_process_with_name_api() test case just hangs. Modified: lldb/trunk/test/python_api/hello_world/TestHelloWorld.py Modified: lldb/trunk/test/python_api/hello_world/TestHelloWorld.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/hello_world/TestHelloWorld.py?rev=148417&r1=148416&r2=148417&view=diff ============================================================================== --- lldb/trunk/test/python_api/hello_world/TestHelloWorld.py (original) +++ lldb/trunk/test/python_api/hello_world/TestHelloWorld.py Wed Jan 18 15:20:03 2012 @@ -16,7 +16,8 @@ Use dsym info and process launch API. """ - self.buildDsym() + self.buildDsym(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) self.hello_world_python() @python_api_test @@ -25,7 +26,8 @@ Use dwarf debug map and process launch API. """ - self.buildDwarf() + self.buildDwarf(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) self.hello_world_python() @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") @@ -35,7 +37,8 @@ Use dsym info and attach to process with id API. """ - self.buildDsym() + self.buildDsym(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) self.hello_world_attach_with_id_api() @python_api_test @@ -44,7 +47,8 @@ Use dwarf map (no dsym) and attach to process with id API. """ - self.buildDwarf() + self.buildDwarf(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) self.hello_world_attach_with_id_api() @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") @@ -54,7 +58,8 @@ Use dsym info and attach to process with name API. """ - self.buildDsym() + self.buildDsym(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) self.hello_world_attach_with_name_api() @python_api_test @@ -63,14 +68,16 @@ Use dwarf map (no dsym) and attach to process with name API. """ - self.buildDwarf() + self.buildDwarf(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) self.hello_world_attach_with_name_api() def setUp(self): # Call super's setUp(). TestBase.setUp(self) - # Get the full path to our executable to be debugged. - self.exe = os.path.join(os.getcwd(), "hello_world") + # Get the full path to our executable to be attached/debugged. + self.exe = os.path.join(os.getcwd(), self.testMethodName) + self.d = {'EXE': self.testMethodName} # Find a couple of the line numbers within main.c. self.line1 = line_number('main.c', '// Set break point at this line.') self.line2 = line_number('main.c', '// Waiting to be attached...') From johnny.chen at apple.com Wed Jan 18 15:22:38 2012 From: johnny.chen at apple.com (Johnny Chen) Date: Wed, 18 Jan 2012 21:22:38 -0000 Subject: [Lldb-commits] [lldb] r148418 - /lldb/trunk/test/python_api/hello_world/Makefile Message-ID: <20120118212238.DB31C2A6C12C@llvm.org> Author: johnny Date: Wed Jan 18 15:22:38 2012 New Revision: 148418 URL: http://llvm.org/viewvc/llvm-project?rev=148418&view=rev Log: Add comment regarding TestHelloWorld.py's use of a dictionary to specify/overwrite the EXE name. Modified: lldb/trunk/test/python_api/hello_world/Makefile Modified: lldb/trunk/test/python_api/hello_world/Makefile URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/hello_world/Makefile?rev=148418&r1=148417&r2=148418&view=diff ============================================================================== --- lldb/trunk/test/python_api/hello_world/Makefile (original) +++ lldb/trunk/test/python_api/hello_world/Makefile Wed Jan 18 15:22:38 2012 @@ -1,6 +1,7 @@ LEVEL = ../../make C_SOURCES := main.c +# See TestHelloWorld.py, which specifies the executable name with a dictionary. EXE := hello_world include $(LEVEL)/Makefile.rules From gclayton at apple.com Wed Jan 18 15:56:18 2012 From: gclayton at apple.com (Greg Clayton) Date: Wed, 18 Jan 2012 21:56:18 -0000 Subject: [Lldb-commits] [lldb] r148425 - /lldb/trunk/source/Core/Debugger.cpp Message-ID: <20120118215618.C2C222A6C12C@llvm.org> Author: gclayton Date: Wed Jan 18 15:56:18 2012 New Revision: 148425 URL: http://llvm.org/viewvc/llvm-project?rev=148425&view=rev Log: Fixed an issue in the debugger format strings that include "${function.name-with-args}" where we grabbed the variable list size from the wrong list (we needed it from "args" and we were getting it from "variable_list_sp"). Modified: lldb/trunk/source/Core/Debugger.cpp Modified: lldb/trunk/source/Core/Debugger.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=148425&r1=148424&r2=148425&view=diff ============================================================================== --- lldb/trunk/source/Core/Debugger.cpp (original) +++ lldb/trunk/source/Core/Debugger.cpp Wed Jan 18 15:56:18 2012 @@ -1957,7 +1957,7 @@ s.PutCString (cstr); s.PutChar ('('); } - const size_t num_args = variable_list_sp->GetSize(); + const size_t num_args = args.GetSize(); for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) { VariableSP var_sp (args.GetVariableAtIndex (arg_idx)); From gclayton at apple.com Wed Jan 18 17:40:49 2012 From: gclayton at apple.com (Greg Clayton) Date: Wed, 18 Jan 2012 23:40:49 -0000 Subject: [Lldb-commits] [lldb] r148435 - /lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Message-ID: <20120118234050.15B882A6C12C@llvm.org> Author: gclayton Date: Wed Jan 18 17:40:49 2012 New Revision: 148435 URL: http://llvm.org/viewvc/llvm-project?rev=148435&view=rev Log: Be sure to use the one and only trusted source for chopping up objective C class names when extracting the class name, selector and name without category for objective C full class and instance method names. Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=148435&r1=148434&r2=148435&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Wed Jan 18 17:40:49 2012 @@ -4897,20 +4897,15 @@ bool type_handled = false; if (tag == DW_TAG_subprogram) { - if (ObjCLanguageRuntime::IsPossibleObjCMethodName (type_name_cstr)) + ConstString class_name; + + if (ObjCLanguageRuntime::ParseMethodName (type_name_cstr, &class_name, NULL, NULL)) { - // We need to find the DW_TAG_class_type or - // DW_TAG_struct_type by name so we can add this - // as a member function of the class. - const char *class_name_start = type_name_cstr + 2; - const char *class_name_end = ::strchr (class_name_start, ' '); SymbolContext empty_sc; clang_type_t class_opaque_type = NULL; - if (class_name_start < class_name_end) + if (class_name) { - ConstString class_name (class_name_start, class_name_end - class_name_start); TypeList types; - TypeSP complete_objc_class_type_sp (FindCompleteObjCDefinitionTypeForDIE (NULL, class_name, true)); if (!complete_objc_class_type_sp) complete_objc_class_type_sp = FindCompleteObjCDefinitionTypeForDIE (NULL, class_name, false); From gclayton at apple.com Wed Jan 18 18:52:59 2012 From: gclayton at apple.com (Greg Clayton) Date: Thu, 19 Jan 2012 00:52:59 -0000 Subject: [Lldb-commits] [lldb] r148445 - in /lldb/trunk: include/lldb/Target/ObjCLanguageRuntime.h source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp source/Symbol/Symtab.cpp source/Target/ObjCLanguageRuntime.cpp Message-ID: <20120119005259.5DA002A6C12C@llvm.org> Author: gclayton Date: Wed Jan 18 18:52:59 2012 New Revision: 148445 URL: http://llvm.org/viewvc/llvm-project?rev=148445&view=rev Log: Added an extra way to chop up an objective C prototype and use it where necessary. Modified: lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp lldb/trunk/source/Symbol/Symtab.cpp lldb/trunk/source/Target/ObjCLanguageRuntime.cpp Modified: lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h?rev=148445&r1=148444&r2=148445&view=diff ============================================================================== --- lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h (original) +++ lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h Wed Jan 18 18:52:59 2012 @@ -103,7 +103,11 @@ // sub-parts that are passed in non-NULL. The base_name means the name stripped of // category attributes. static bool - ParseMethodName (const char *name, ConstString *class_name, ConstString *method_name, ConstString *base_name); + ParseMethodName (const char *name, + ConstString *class_name, // Class name (with category if there is one) + ConstString *selector_name, // selector only + ConstString *name_sans_category, // full function name with no category + ConstString *class_name_sans_category);// Class name without category (empty if no category) static bool IsPossibleObjCMethodName (const char *name) Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp?rev=148445&r1=148444&r2=148445&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp Wed Jan 18 18:52:59 2012 @@ -737,12 +737,16 @@ ConstString objc_class_name; ConstString objc_selector_name; ConstString objc_fullname_no_category_name; + ConstString objc_class_name_no_category; if (ObjCLanguageRuntime::ParseMethodName (name, &objc_class_name, &objc_selector_name, - &objc_fullname_no_category_name)) + &objc_fullname_no_category_name, + &objc_class_name_no_category)) { objc_class_selectors.Insert(objc_class_name, die.GetOffset()); + if (objc_class_name_no_category) + objc_class_selectors.Insert(objc_class_name_no_category, die.GetOffset()); func_selectors.Insert (objc_selector_name, die.GetOffset()); func_fullnames.Insert (ConstString(name), die.GetOffset()); Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=148445&r1=148444&r2=148445&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Wed Jan 18 18:52:59 2012 @@ -4898,17 +4898,14 @@ if (tag == DW_TAG_subprogram) { ConstString class_name; - - if (ObjCLanguageRuntime::ParseMethodName (type_name_cstr, &class_name, NULL, NULL)) + if (ObjCLanguageRuntime::ParseMethodName (type_name_cstr, NULL, NULL, NULL, &class_name)) { SymbolContext empty_sc; clang_type_t class_opaque_type = NULL; if (class_name) { TypeList types; - TypeSP complete_objc_class_type_sp (FindCompleteObjCDefinitionTypeForDIE (NULL, class_name, true)); - if (!complete_objc_class_type_sp) - complete_objc_class_type_sp = FindCompleteObjCDefinitionTypeForDIE (NULL, class_name, false); + TypeSP complete_objc_class_type_sp (FindCompleteObjCDefinitionTypeForDIE (NULL, class_name, false)); if (complete_objc_class_type_sp) { Modified: lldb/trunk/source/Symbol/Symtab.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/Symtab.cpp?rev=148445&r1=148444&r2=148445&view=diff ============================================================================== --- lldb/trunk/source/Symbol/Symtab.cpp (original) +++ lldb/trunk/source/Symbol/Symtab.cpp Wed Jan 18 18:52:59 2012 @@ -313,7 +313,8 @@ if (ObjCLanguageRuntime::ParseMethodName (entry.cstring, NULL, NULL, - &objc_base_name) + &objc_base_name, + NULL) && !objc_base_name.IsEmpty()) { entry.cstring = objc_base_name.GetCString(); Modified: lldb/trunk/source/Target/ObjCLanguageRuntime.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ObjCLanguageRuntime.cpp?rev=148445&r1=148444&r2=148445&view=diff ============================================================================== --- lldb/trunk/source/Target/ObjCLanguageRuntime.cpp (original) +++ lldb/trunk/source/Target/ObjCLanguageRuntime.cpp Wed Jan 18 18:52:59 2012 @@ -103,13 +103,19 @@ bool ObjCLanguageRuntime::ParseMethodName (const char *name, - ConstString *class_name, - ConstString *selector_name, - ConstString *name_sans_category) + ConstString *class_name, // Class name (with category if any) + ConstString *selector_name, // selector on its own + ConstString *name_sans_category, // Full function prototype with no category + ConstString *class_name_sans_category)// Class name with no category (or empty if no category as answer will be in "class_name" { - if (class_name) { class_name->Clear(); } - if (selector_name) { selector_name->Clear(); } - if (name_sans_category) { name_sans_category->Clear(); } + if (class_name) + class_name->Clear(); + if (selector_name) + selector_name->Clear(); + if (name_sans_category) + name_sans_category->Clear(); + if (class_name_sans_category) + class_name_sans_category->Clear(); if (IsPossibleObjCMethodName (name)) { @@ -122,8 +128,7 @@ // "]" suffix if (name_len >= 6 && name[name_len - 1] == ']') { - const char *selector_name_ptr; - selector_name_ptr = strchr (name, ' '); + const char *selector_name_ptr = strchr (name, ' '); if (selector_name_ptr) { if (class_name) @@ -140,18 +145,21 @@ // Also see if this is a "category" on our class. If so strip off the category name, // and add the class name without it to the basename table. - if (name_sans_category) + if (name_sans_category || class_name_sans_category) { - const char *first_paren = (char *) memchr (name, '(', selector_name_ptr - name); - if (first_paren) + const char *open_paren = strchr (name, '('); + const char *close_paren = NULL; + if (open_paren) { - const char *second_paren = (char *) memchr (first_paren, ')', selector_name_ptr - first_paren); - if (second_paren) + if (class_name_sans_category) + class_name_sans_category->SetCStringWithLength (name + 2, open_paren - name - 2); + close_paren = strchr (name, ')'); + if (close_paren) { - std::string buffer (name, first_paren - name); - buffer.append (second_paren + 1); + std::string buffer (name, open_paren - name); + buffer.append (close_paren + 1); name_sans_category->SetCString (buffer.c_str()); - + } } } @@ -160,6 +168,5 @@ } return false; } - else - return false; + return false; } From scallanan at apple.com Wed Jan 18 19:10:27 2012 From: scallanan at apple.com (Sean Callanan) Date: Thu, 19 Jan 2012 01:10:27 -0000 Subject: [Lldb-commits] [lldb] r148450 - /lldb/trunk/source/Target/ObjCLanguageRuntime.cpp Message-ID: <20120119011027.4B9982A6C12C@llvm.org> Author: spyffe Date: Wed Jan 18 19:10:27 2012 New Revision: 148450 URL: http://llvm.org/viewvc/llvm-project?rev=148450&view=rev Log: Fix to ensure that methods aren't called on NULL objects. Modified: lldb/trunk/source/Target/ObjCLanguageRuntime.cpp Modified: lldb/trunk/source/Target/ObjCLanguageRuntime.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ObjCLanguageRuntime.cpp?rev=148450&r1=148449&r2=148450&view=diff ============================================================================== --- lldb/trunk/source/Target/ObjCLanguageRuntime.cpp (original) +++ lldb/trunk/source/Target/ObjCLanguageRuntime.cpp Wed Jan 18 19:10:27 2012 @@ -148,18 +148,20 @@ if (name_sans_category || class_name_sans_category) { const char *open_paren = strchr (name, '('); - const char *close_paren = NULL; if (open_paren) { if (class_name_sans_category) class_name_sans_category->SetCStringWithLength (name + 2, open_paren - name - 2); - close_paren = strchr (name, ')'); - if (close_paren) + + if (name_sans_category) { - std::string buffer (name, open_paren - name); - buffer.append (close_paren + 1); - name_sans_category->SetCString (buffer.c_str()); - + const char *close_paren = strchr (name, ')'); + if (close_paren) + { + std::string buffer (name, open_paren - name); + buffer.append (close_paren + 1); + name_sans_category->SetCString (buffer.c_str()); + } } } } From scallanan at apple.com Wed Jan 18 20:17:41 2012 From: scallanan at apple.com (Sean Callanan) Date: Thu, 19 Jan 2012 02:17:41 -0000 Subject: [Lldb-commits] [lldb] r148457 - in /lldb/trunk: include/lldb/Expression/ClangASTSource.h include/lldb/Symbol/ClangASTImporter.h source/Expression/ClangASTSource.cpp source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp source/Symbol/ClangASTImporter.cpp Message-ID: <20120119021741.8D3992A6C12C@llvm.org> Author: spyffe Date: Wed Jan 18 20:17:40 2012 New Revision: 148457 URL: http://llvm.org/viewvc/llvm-project?rev=148457&view=rev Log: Fixed a problem where maintaining the ObjCInterfaceMap for each ObjCInterfaceDecl was imposing performance penalties for Objective-C apps. Instead, we now use the normal function query mechanisms, which use the relevant accelerator tables. This fix also includes some modifications to the SymbolFile which allow us to find Objective-C methods and report their Clang Decls correctly. Modified: lldb/trunk/include/lldb/Expression/ClangASTSource.h lldb/trunk/include/lldb/Symbol/ClangASTImporter.h lldb/trunk/source/Expression/ClangASTSource.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp lldb/trunk/source/Symbol/ClangASTImporter.cpp Modified: lldb/trunk/include/lldb/Expression/ClangASTSource.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangASTSource.h?rev=148457&r1=148456&r2=148457&view=diff ============================================================================== --- lldb/trunk/include/lldb/Expression/ClangASTSource.h (original) +++ lldb/trunk/include/lldb/Expression/ClangASTSource.h Wed Jan 18 20:17:40 2012 @@ -170,24 +170,6 @@ const ConstString &name, ClangASTImporter::NamespaceMapSP &parent_map) const; - //------------------------------------------------------------------ - /// Look up all instances of a given Objective-C interface in all - /// symbol files and put the appropriate entries in the namespace - /// map. - /// - /// @param[in] namespace_map - /// The map to be completed. - /// - /// @param[in] name - /// The name of the namespace to be found. - /// - /// @param[in] parent_map - /// The map for the namespace's parent namespace, if there is - /// one. - //------------------------------------------------------------------ - void CompleteObjCInterfaceMap (ClangASTImporter::ObjCInterfaceMapSP &objc_interface_map, - const ConstString &name) const; - // // Helper APIs // Modified: lldb/trunk/include/lldb/Symbol/ClangASTImporter.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangASTImporter.h?rev=148457&r1=148456&r2=148457&view=diff ============================================================================== --- lldb/trunk/include/lldb/Symbol/ClangASTImporter.h (original) +++ lldb/trunk/include/lldb/Symbol/ClangASTImporter.h Wed Jan 18 20:17:40 2012 @@ -96,18 +96,7 @@ void BuildNamespaceMap (const clang::NamespaceDecl *decl); // - // Objective-C interface maps - // - - typedef std::vector ObjCInterfaceMap; - typedef lldb::SharedPtr::Type ObjCInterfaceMapSP; - - void BuildObjCInterfaceMap (const clang::ObjCInterfaceDecl *decl); - - ObjCInterfaceMapSP GetObjCInterfaceMap (const clang::ObjCInterfaceDecl *decl); - - // - // Completers for the namespace and Objective-C interface maps + // Comleters for maps // class MapCompleter @@ -118,9 +107,6 @@ virtual void CompleteNamespaceMap (NamespaceMapSP &namespace_map, const ConstString &name, NamespaceMapSP &parent_map) const = 0; - - virtual void CompleteObjCInterfaceMap (ObjCInterfaceMapSP &objc_interface_map, - const ConstString &name) const = 0; }; void InstallMapCompleter (clang::ASTContext *dst_ctx, MapCompleter &completer) @@ -210,7 +196,6 @@ typedef lldb::SharedPtr::Type MinionSP; typedef std::map MinionMap; typedef std::map NamespaceMetaMap; - typedef std::map ObjCInterfaceMetaMap; struct ASTContextMetadata { @@ -219,7 +204,6 @@ m_minions (), m_origins (), m_namespace_maps (), - m_objc_interface_maps (), m_map_completer (NULL) { } @@ -230,8 +214,6 @@ NamespaceMetaMap m_namespace_maps; MapCompleter *m_map_completer; - - ObjCInterfaceMetaMap m_objc_interface_maps; }; typedef lldb::SharedPtr::Type ASTContextMetadataSP; Modified: lldb/trunk/source/Expression/ClangASTSource.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangASTSource.cpp?rev=148457&r1=148456&r2=148457&view=diff ============================================================================== --- lldb/trunk/source/Expression/ClangASTSource.cpp (original) +++ lldb/trunk/source/Expression/ClangASTSource.cpp Wed Jan 18 20:17:40 2012 @@ -663,107 +663,80 @@ m_ast_context, interface_decl->getNameAsString().c_str(), selector_name.AsCString()); - - ClangASTImporter::ObjCInterfaceMapSP interface_map = m_ast_importer->GetObjCInterfaceMap(interface_decl); + SymbolContextList sc_list; + + const bool include_symbols = false; + const bool append = false; - if (interface_map) + std::string interface_name = interface_decl->getNameAsString(); + + do { - for (ClangASTImporter::ObjCInterfaceMap::iterator i = interface_map->begin(), e = interface_map->end(); - i != e; - ++i) + StreamString ms; + ms.Printf("-[%s %s]", interface_name.c_str(), selector_name.AsCString()); + ms.Flush(); + ConstString instance_method_name(ms.GetData()); + + m_target->GetImages().FindFunctions(instance_method_name, lldb::eFunctionNameTypeFull, include_symbols, append, sc_list); + + if (sc_list.GetSize()) + break; + + ms.Clear(); + ms.Printf("+[%s %s]", interface_name.c_str(), selector_name.AsCString()); + ms.Flush(); + ConstString class_method_name(ms.GetData()); + + m_target->GetImages().FindFunctions(class_method_name, lldb::eFunctionNameTypeFull, include_symbols, append, sc_list); + + if (sc_list.GetSize()) + break; + + // Fall back and check for methods in categories. If we find methods this way, we need to check that they're actually in + // categories on the desired class. + + SymbolContextList candidate_sc_list; + + m_target->GetImages().FindFunctions(selector_name, lldb::eFunctionNameTypeSelector, include_symbols, append, candidate_sc_list); + + for (uint32_t ci = 0, ce = candidate_sc_list.GetSize(); + ci != ce; + ++ci) { - lldb::clang_type_t backing_type = i->GetOpaqueQualType(); + SymbolContext candidate_sc; - if (!backing_type) + if (!candidate_sc_list.GetContextAtIndex(ci, candidate_sc)) continue; - QualType backing_qual_type = QualType::getFromOpaquePtr(backing_type); - - const ObjCInterfaceType *backing_interface_type = backing_qual_type.getTypePtr()->getAs(); - - if (!backing_interface_type) - continue; - - const ObjCInterfaceDecl *backing_interface_decl = backing_interface_type->getDecl(); - - if (!backing_interface_decl) + if (!candidate_sc.function) continue; - if (backing_interface_decl->decls_begin() == backing_interface_decl->decls_end()) - continue; // don't waste time creating a DeclarationName here - - clang::ASTContext &backing_ast_context = backing_interface_decl->getASTContext(); - - llvm::SmallVector selector_components; - int num_arguments = 0; - - if (decl_name.isObjCZeroArgSelector()) - { - selector_components.push_back (&backing_ast_context.Idents.get(decl_name.getAsString().c_str())); - } - else if (decl_name.isObjCOneArgSelector()) - { - selector_components.push_back (&backing_ast_context.Idents.get(decl_name.getAsString().c_str())); - num_arguments = 1; - } - else - { - clang::Selector sel = decl_name.getObjCSelector(); - - for (unsigned i = 0, e = sel.getNumArgs(); - i != e; - ++i) - { - llvm::StringRef r = sel.getNameForSlot(i); - - selector_components.push_back (&backing_ast_context.Idents.get(r.str().c_str())); - num_arguments++; - } - } - - Selector backing_selector = backing_interface_decl->getASTContext().Selectors.getSelector(num_arguments, selector_components.data()); - DeclarationName backing_decl_name = DeclarationName(backing_selector); + const char *candidate_name = candidate_sc.function->GetName().AsCString(); - DeclContext::lookup_const_result lookup_result = backing_interface_decl->lookup(backing_decl_name); + const char *cursor = candidate_name; - if (lookup_result.first == lookup_result.second) + if (*cursor != '+' && *cursor != '-') continue; - ObjCMethodDecl *method_decl = dyn_cast(*lookup_result.first); + ++cursor; - if (!method_decl) + if (*cursor != '[') continue; - Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &backing_ast_context, *lookup_result.first); + ++cursor; - if (!copied_decl) - { - if (log) - log->Printf(" CAS::FOMD[%d] couldn't import method from symbols", current_id); - continue; - } - - ObjCMethodDecl *copied_method_decl = dyn_cast (copied_decl); + size_t interface_len = interface_name.length(); - if (!copied_method_decl) + if (strncmp(cursor, interface_name.c_str(), interface_len)) continue; - if (log) - { - ASTDumper dumper((Decl*)copied_method_decl); - log->Printf(" CAS::FOMD[%d] found (in symbols) %s", current_id, dumper.GetCString()); - } + cursor += interface_len; - context.AddNamedDecl(copied_method_decl); + if (*cursor == ' ' || *cursor == '(') + sc_list.Append(candidate_sc); } } - - SymbolContextList sc_list; - - const bool include_symbols = false; - const bool append = false; - - m_target->GetImages().FindFunctions(selector_name, lldb::eFunctionNameTypeSelector, include_symbols, append, sc_list); + while (0); for (uint32_t i = 0, e = sc_list.GetSize(); i != e; @@ -809,7 +782,7 @@ ASTDumper dumper((Decl*)copied_method_decl); log->Printf(" CAS::FOMD[%d] found (in debug info) %s", current_id, dumper.GetCString()); } - + context.AddNamedDecl(copied_method_decl); } } @@ -970,29 +943,6 @@ } } -void -ClangASTSource::CompleteObjCInterfaceMap (ClangASTImporter::ObjCInterfaceMapSP &objc_interface_map, - const ConstString &name) const -{ - SymbolContext null_sc; - - TypeList types; - - m_target->GetImages().FindTypes(null_sc, name, true, UINT32_MAX, types); - - for (uint32_t i = 0, e = types.GetSize(); - i != e; - ++i) - { - lldb::TypeSP mapped_type_sp = types.GetTypeAtIndex(i); - - if (!mapped_type_sp || !mapped_type_sp->GetClangFullType()) - continue; - - objc_interface_map->push_back (ClangASTType(mapped_type_sp->GetClangAST(), mapped_type_sp->GetClangFullType())); - } -} - NamespaceDecl * ClangASTSource::AddNamespace (NameSearchContext &context, ClangASTImporter::NamespaceMapSP &namespace_decls) { Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h?rev=148457&r1=148456&r2=148457&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h Wed Jan 18 20:17:40 2012 @@ -124,7 +124,7 @@ for (size_t i=0; iSupports_DW_AT_APPLE_objc_complete_type()) + if (must_be_implementation && type_cu->Supports_DW_AT_APPLE_objc_complete_type()) try_resolving_type = type_die->GetAttributeValueAsUnsigned (this, type_cu, DW_AT_APPLE_objc_complete_type, 0); if (try_resolving_type) Modified: lldb/trunk/source/Symbol/ClangASTImporter.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTImporter.cpp?rev=148457&r1=148456&r2=148457&view=diff ============================================================================== --- lldb/trunk/source/Symbol/ClangASTImporter.cpp (original) +++ lldb/trunk/source/Symbol/ClangASTImporter.cpp Wed Jan 18 20:17:40 2012 @@ -306,38 +306,6 @@ return; } -ClangASTImporter::ObjCInterfaceMapSP -ClangASTImporter::GetObjCInterfaceMap (const clang::ObjCInterfaceDecl *decl) -{ - ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext()); - - ObjCInterfaceMetaMap &objc_interface_maps = context_md->m_objc_interface_maps; - - ObjCInterfaceMetaMap::iterator iter = objc_interface_maps.find(decl); - - if (iter != objc_interface_maps.end()) - return iter->second; - else - return ObjCInterfaceMapSP(); -} - -void -ClangASTImporter::BuildObjCInterfaceMap (const clang::ObjCInterfaceDecl *decl) -{ - ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext()); - - ObjCInterfaceMapSP new_map(new ObjCInterfaceMap); - - if (context_md->m_map_completer) - { - std::string namespace_string = decl->getDeclName().getAsString(); - - context_md->m_map_completer->CompleteObjCInterfaceMap(new_map, ConstString(namespace_string.c_str())); - } - - context_md->m_objc_interface_maps[decl] = new_map; -} - void ClangASTImporter::Minion::ImportDefinitionTo (clang::Decl *to, clang::Decl *from) { @@ -455,9 +423,7 @@ if (isa(from)) { ObjCInterfaceDecl *to_interface_decl = dyn_cast(to); - - m_master.BuildObjCInterfaceMap(to_interface_decl); - + to_interface_decl->setHasExternalLexicalStorage(); to_interface_decl->setHasExternalVisibleStorage(); From gclayton at apple.com Wed Jan 18 21:24:53 2012 From: gclayton at apple.com (Greg Clayton) Date: Thu, 19 Jan 2012 03:24:53 -0000 Subject: [Lldb-commits] [lldb] r148460 - in /lldb/trunk: include/lldb/Core/Disassembler.h include/lldb/Target/ObjCLanguageRuntime.h source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp source/Plugins/Disassembler/llvm/DisassemblerLLVM.h source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp source/Symbol/Symtab.cpp source/Target/ObjCLanguageRuntime.cpp Message-ID: <20120119032453.BA8492A6C12C@llvm.org> Author: gclayton Date: Wed Jan 18 21:24:53 2012 New Revision: 148460 URL: http://llvm.org/viewvc/llvm-project?rev=148460&view=rev Log: Fixed an issue with the Instruction subclasses where the strings might be fetched too many times and the DisassemblerLLVM was appending to strings when the opcode, mnemonic and comment accessors were called multiple times and if any of the strings were empty. Also fixed the test suite failures from recent Objective C modifications. Modified: lldb/trunk/include/lldb/Core/Disassembler.h lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h lldb/trunk/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp lldb/trunk/source/Plugins/Disassembler/llvm/DisassemblerLLVM.h lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp lldb/trunk/source/Symbol/Symtab.cpp lldb/trunk/source/Target/ObjCLanguageRuntime.cpp Modified: lldb/trunk/include/lldb/Core/Disassembler.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Disassembler.h?rev=148460&r1=148459&r2=148460&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/Disassembler.h (original) +++ lldb/trunk/include/lldb/Core/Disassembler.h Wed Jan 18 21:24:53 2012 @@ -44,35 +44,26 @@ const char * GetMnemonic (ExecutionContextScope *exe_scope) { - if (m_opcode_name.empty()) - CalculateMnemonic(exe_scope); + CalculateMnemonicOperandsAndCommentIfNeeded (exe_scope); return m_opcode_name.c_str(); } const char * GetOperands (ExecutionContextScope *exe_scope) { - if (m_mnemocics.empty()) - CalculateOperands(exe_scope); + CalculateMnemonicOperandsAndCommentIfNeeded (exe_scope); return m_mnemocics.c_str(); } const char * GetComment (ExecutionContextScope *exe_scope) { - if (m_comment.empty()) - CalculateComment(exe_scope); + CalculateMnemonicOperandsAndCommentIfNeeded (exe_scope); return m_comment.c_str(); } virtual void - CalculateMnemonic (ExecutionContextScope *exe_scope) = 0; + CalculateMnemonicOperandsAndComment (ExecutionContextScope *exe_scope) = 0; - virtual void - CalculateOperands (ExecutionContextScope *exe_scope) = 0; - - virtual void - CalculateComment (ExecutionContextScope *exe_scope) = 0; - AddressClass GetAddressClass (); @@ -144,7 +135,17 @@ std::string m_opcode_name; std::string m_mnemocics; std::string m_comment; + bool m_calculated_strings; + void + CalculateMnemonicOperandsAndCommentIfNeeded (ExecutionContextScope *exe_scope) + { + if (!m_calculated_strings) + { + m_calculated_strings = true; + CalculateMnemonicOperandsAndComment(exe_scope); + } + } }; @@ -205,23 +206,13 @@ DoesBranch () const; virtual void - CalculateMnemonic(ExecutionContextScope *exe_scope) + CalculateMnemonicOperandsAndComment (ExecutionContextScope *exe_scope) { - // TODO: fill this in and put opcode name into Instruction::m_opcode_name + // TODO: fill this in and put opcode name into Instruction::m_opcode_name, + // mnemonic into Instruction::m_mnemonics, and any comment into + // Instruction::m_comment } - virtual void - CalculateOperands(ExecutionContextScope *exe_scope) - { - // TODO: fill this in and put opcode name into Instruction::m_mnemonics - } - - virtual void - CalculateComment(ExecutionContextScope *exe_scope) - { - // TODO: fill this in and put opcode name into Instruction::m_comment - } - virtual size_t Decode (const Disassembler &disassembler, const DataExtractor &data, Modified: lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h?rev=148460&r1=148459&r2=148460&view=diff ============================================================================== --- lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h (original) +++ lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h Wed Jan 18 21:24:53 2012 @@ -99,14 +99,68 @@ virtual size_t GetByteOffsetForIvar (ClangASTType &parent_qual_type, const char *ivar_name); - // If the passed in "name" is an ObjC method, return true. Also, fill in any of the - // sub-parts that are passed in non-NULL. The base_name means the name stripped of - // category attributes. - static bool + //------------------------------------------------------------------ + /// Chop up an objective C function prototype. + /// + /// Chop up an objective C function fullname and optionally fill in + /// any non-NULL ConstString objects. If a ConstString * is NULL, + /// then this name doesn't get filled in + /// + /// @param[in] name + /// A fully specified objective C function name. The string might + /// contain a category and it includes the leading "+" or "-" and + /// the square brackets, no types for the arguments, just the plain + /// selector. A few examples: + /// "-[NSStringDrawingContext init]" + /// "-[NSStringDrawingContext addString:inRect:]" + /// "-[NSString(NSStringDrawing) sizeWithAttributes:]" + /// "+[NSString(NSStringDrawing) usesFontLeading]" + /// + /// @param[out] class_name + /// If non-NULL, this string will be filled in with the class + /// name including the category. The examples above would return: + /// "NSStringDrawingContext" + /// "NSStringDrawingContext" + /// "NSString(NSStringDrawing)" + /// "NSString(NSStringDrawing)" + /// + /// @param[out] selector_name + /// If non-NULL, this string will be filled in with the selector + /// name. The examples above would return: + /// "init" + /// "addString:inRect:" + /// "sizeWithAttributes:" + /// "usesFontLeading" + /// + /// @param[out] name_sans_category + /// If non-NULL, this string will be filled in with the class + /// name _without_ the category. If there is no category, and empty + /// string will be returned (as the result would be normally returned + /// in the "class_name" argument). The examples above would return: + /// + /// + /// "-[NSString sizeWithAttributes:]" + /// "+[NSString usesFontLeading]" + /// + /// @param[out] class_name_sans_category + /// If non-NULL, this string will be filled in with the prototype + /// name _without_ the category. If there is no category, and empty + /// string will be returned (as this is already the value that was + /// passed in). The examples above would return: + /// + /// + /// "NSString" + /// "NSString" + /// + /// @return + /// Returns the number of strings that were successfully filled + /// in. + //------------------------------------------------------------------ + static uint32_t ParseMethodName (const char *name, ConstString *class_name, // Class name (with category if there is one) ConstString *selector_name, // selector only - ConstString *name_sans_category, // full function name with no category + ConstString *name_sans_category, // full function name with no category (empty if no category) ConstString *class_name_sans_category);// Class name without category (empty if no category) static bool Modified: lldb/trunk/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp?rev=148460&r1=148459&r2=148460&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp (original) +++ lldb/trunk/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp Wed Jan 18 21:24:53 2012 @@ -437,7 +437,7 @@ } void -InstructionLLVM::CalculateMnemonic (ExecutionContextScope *exe_scope) +InstructionLLVM::CalculateMnemonicOperandsAndComment (ExecutionContextScope *exe_scope) { const int num_tokens = EDNumTokens(m_inst); if (num_tokens > 0) @@ -560,20 +560,6 @@ } } -void -InstructionLLVM::CalculateOperands(ExecutionContextScope *exe_scope) -{ - // Do all of the work in CalculateMnemonic() - CalculateMnemonic (exe_scope); -} - -void -InstructionLLVM::CalculateComment(ExecutionContextScope *exe_scope) -{ - // Do all of the work in CalculateMnemonic() - CalculateMnemonic (exe_scope); -} - bool InstructionLLVM::DoesBranch() const { Modified: lldb/trunk/source/Plugins/Disassembler/llvm/DisassemblerLLVM.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Disassembler/llvm/DisassemblerLLVM.h?rev=148460&r1=148459&r2=148460&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Disassembler/llvm/DisassemblerLLVM.h (original) +++ lldb/trunk/source/Plugins/Disassembler/llvm/DisassemblerLLVM.h Wed Jan 18 21:24:53 2012 @@ -44,14 +44,8 @@ uint32_t data_offset); virtual void - CalculateMnemonic (lldb_private::ExecutionContextScope *exe_scope); + CalculateMnemonicOperandsAndComment (lldb_private::ExecutionContextScope *exe_scope); - virtual void - CalculateOperands (lldb_private::ExecutionContextScope *exe_scope); - - virtual void - CalculateComment (lldb_private::ExecutionContextScope *exe_scope); - protected: EDDisassemblerRef m_disassembler; EDInstRef m_inst; Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp?rev=148460&r1=148459&r2=148460&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp Wed Jan 18 21:24:53 2012 @@ -744,16 +744,15 @@ &objc_fullname_no_category_name, &objc_class_name_no_category)) { - objc_class_selectors.Insert(objc_class_name, die.GetOffset()); + func_fullnames.Insert (ConstString(name), die.GetOffset()); + if (objc_class_name) + objc_class_selectors.Insert(objc_class_name, die.GetOffset()); if (objc_class_name_no_category) objc_class_selectors.Insert(objc_class_name_no_category, die.GetOffset()); - - func_selectors.Insert (objc_selector_name, die.GetOffset()); - func_fullnames.Insert (ConstString(name), die.GetOffset()); + if (objc_selector_name) + func_selectors.Insert (objc_selector_name, die.GetOffset()); if (objc_fullname_no_category_name) - { func_fullnames.Insert (objc_fullname_no_category_name, die.GetOffset()); - } } } // If we have a mangled name, then the DW_AT_name attribute Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=148460&r1=148459&r2=148460&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Wed Jan 18 21:24:53 2012 @@ -4898,8 +4898,13 @@ if (tag == DW_TAG_subprogram) { ConstString class_name; - if (ObjCLanguageRuntime::ParseMethodName (type_name_cstr, NULL, NULL, NULL, &class_name)) + ConstString class_name_no_category; + if (ObjCLanguageRuntime::ParseMethodName (type_name_cstr, &class_name, NULL, NULL, &class_name_no_category)) { + // Use the class name with no category if there is one + if (class_name_no_category) + class_name = class_name_no_category; + SymbolContext empty_sc; clang_type_t class_opaque_type = NULL; if (class_name) Modified: lldb/trunk/source/Symbol/Symtab.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/Symtab.cpp?rev=148460&r1=148459&r2=148460&view=diff ============================================================================== --- lldb/trunk/source/Symbol/Symtab.cpp (original) +++ lldb/trunk/source/Symbol/Symtab.cpp Wed Jan 18 21:24:53 2012 @@ -314,8 +314,7 @@ NULL, NULL, &objc_base_name, - NULL) - && !objc_base_name.IsEmpty()) + NULL)) { entry.cstring = objc_base_name.GetCString(); m_name_to_index.Append (entry); Modified: lldb/trunk/source/Target/ObjCLanguageRuntime.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ObjCLanguageRuntime.cpp?rev=148460&r1=148459&r2=148460&view=diff ============================================================================== --- lldb/trunk/source/Target/ObjCLanguageRuntime.cpp (original) +++ lldb/trunk/source/Target/ObjCLanguageRuntime.cpp Wed Jan 18 21:24:53 2012 @@ -101,7 +101,7 @@ } -bool +uint32_t ObjCLanguageRuntime::ParseMethodName (const char *name, ConstString *class_name, // Class name (with category if any) ConstString *selector_name, // selector on its own @@ -117,6 +117,8 @@ if (class_name_sans_category) class_name_sans_category->Clear(); + uint32_t result = 0; + if (IsPossibleObjCMethodName (name)) { int name_len = strlen (name); @@ -132,7 +134,10 @@ if (selector_name_ptr) { if (class_name) + { class_name->SetCStringWithLength (name + 2, selector_name_ptr - name - 2); + ++result; + } // Skip the space ++selector_name_ptr; @@ -140,7 +145,10 @@ // accelerator tables size_t selector_name_len = name_len - (selector_name_ptr - name) - 1; if (selector_name) + { selector_name->SetCStringWithLength (selector_name_ptr, selector_name_len); + ++result; + } // Also see if this is a "category" on our class. If so strip off the category name, // and add the class name without it to the basename table. @@ -151,24 +159,26 @@ if (open_paren) { if (class_name_sans_category) + { class_name_sans_category->SetCStringWithLength (name + 2, open_paren - name - 2); + ++result; + } if (name_sans_category) { - const char *close_paren = strchr (name, ')'); - if (close_paren) + const char *close_paren = strchr (open_paren, ')'); + if (open_paren < close_paren) { std::string buffer (name, open_paren - name); buffer.append (close_paren + 1); name_sans_category->SetCString (buffer.c_str()); + ++result; } } } } } - return true; } - return false; } - return false; + return result; } From gclayton at apple.com Wed Jan 18 22:44:00 2012 From: gclayton at apple.com (Greg Clayton) Date: Thu, 19 Jan 2012 04:44:00 -0000 Subject: [Lldb-commits] [lldb] r148461 - in /lldb/trunk: include/lldb/Utility/SharingPtr.h source/Utility/SharingPtr.cpp Message-ID: <20120119044400.9AD1A2A6C12C@llvm.org> Author: gclayton Date: Wed Jan 18 22:44:00 2012 New Revision: 148461 URL: http://llvm.org/viewvc/llvm-project?rev=148461&view=rev Log: Allow a way to track all allocations for our intrusive ref counted pointers. It is disabled by default, but can be enabled to track down shared pointer cycles. Modified: lldb/trunk/include/lldb/Utility/SharingPtr.h lldb/trunk/source/Utility/SharingPtr.cpp Modified: lldb/trunk/include/lldb/Utility/SharingPtr.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Utility/SharingPtr.h?rev=148461&r1=148460&r2=148461&view=diff ============================================================================== --- lldb/trunk/include/lldb/Utility/SharingPtr.h (original) +++ lldb/trunk/include/lldb/Utility/SharingPtr.h Wed Jan 18 22:44:00 2012 @@ -13,6 +13,13 @@ #include #include +//#define ENABLE_SP_LOGGING 1 // DON'T CHECK THIS LINE IN UNLESS COMMENTED OUT +#if defined (ENABLE_SP_LOGGING) + +extern "C" void track_sp (void *sp_this, void *ptr, long count); + +#endif + namespace lldb_private { namespace imp { @@ -706,6 +713,10 @@ swap (IntrusiveSharingPtr& rhs) { std::swap(ptr_, rhs.ptr_); +#if defined (ENABLE_SP_LOGGING) + track_sp (this, ptr_, use_count()); + track_sp (&rhs, rhs.ptr_, rhs.use_count()); +#endif } void @@ -730,18 +741,28 @@ private: element_type *ptr_; - + void add_shared() { if (ptr_) + { ptr_->add_shared(); +#if defined (ENABLE_SP_LOGGING) + track_sp (this, ptr_, ptr_->use_count()); +#endif + } } void release_shared() { if (ptr_) + { +#if defined (ENABLE_SP_LOGGING) + track_sp (this, NULL, ptr_->use_count() - 1); +#endif ptr_->release_shared(); + } } }; Modified: lldb/trunk/source/Utility/SharingPtr.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Utility/SharingPtr.cpp?rev=148461&r1=148460&r2=148461&view=diff ============================================================================== --- lldb/trunk/source/Utility/SharingPtr.cpp (original) +++ lldb/trunk/source/Utility/SharingPtr.cpp Wed Jan 18 22:44:00 2012 @@ -9,6 +9,117 @@ #include "lldb/Utility/SharingPtr.h" +#if defined (ENABLE_SP_LOGGING) + +// If ENABLE_SP_LOGGING is defined, then log all shared pointer assignements +// and allow them to be queried using a pointer by a call to: +#include +#include +#include +#include "lldb/Host/Mutex.h" + +#include + +class Backtrace +{ +public: + Backtrace (); + + ~Backtrace (); + + void + GetFrames (); + + void + Dump () const; + +private: + void *m_sp_this; + std::vector m_frames; +}; + + +Backtrace::Backtrace () : m_frames() +{ +} + +Backtrace::~Backtrace () +{ +} + +void +Backtrace::GetFrames () +{ + void *frames[1024]; + const int count = ::backtrace (frames, sizeof(frames)/sizeof(void*)); + if (count > 2) + m_frames.assign (frames + 2, frames + (count - 2)); +} + +void +Backtrace::Dump () const +{ + if (!m_frames.empty()) + ::backtrace_symbols_fd (m_frames.data(), m_frames.size(), STDOUT_FILENO); + write (STDOUT_FILENO, "\n\n", 2); +} + +extern "C" void track_sp (void *sp_this, void *ptr, long use_count) +{ + typedef std::pair PtrBacktracePair; + typedef std::map PtrToBacktraceMap; + static lldb_private::Mutex g_mutex(lldb_private::Mutex::eMutexTypeNormal); + lldb_private::Mutex::Locker locker (g_mutex); + static PtrToBacktraceMap g_map; + + if (sp_this) + { + printf ("sp(%p) -> %p %lu\n", sp_this, ptr, use_count); + + if (ptr) + { + Backtrace bt; + bt.GetFrames(); + g_map[sp_this] = std::make_pair(ptr, bt); + } + else + { + g_map.erase (sp_this); + } + } + else + { + if (ptr) + printf ("Searching for shared pointers that are tracking %p: ", ptr); + else + printf ("Dump all live shared pointres: "); + + uint32_t matches = 0; + PtrToBacktraceMap::iterator pos, end = g_map.end(); + for (pos = g_map.begin(); pos != end; ++pos) + { + if (ptr == NULL || pos->second.first == ptr) + { + ++matches; + printf ("\nsp(%p): %p\n", pos->first, pos->second.first); + pos->second.second.Dump(); + } + } + if (matches == 0) + { + printf ("none.\n"); + } + } +} +extern "C" void dump_sp_refs (void *ptr) +{ + // Use a specially crafted call to "track_sp" which will + // dump info on all live shared pointers that reference "ptr" + track_sp (NULL, ptr, 0); +} + +#endif + namespace lldb_private { namespace imp From scallanan at apple.com Thu Jan 19 12:23:06 2012 From: scallanan at apple.com (Sean Callanan) Date: Thu, 19 Jan 2012 18:23:06 -0000 Subject: [Lldb-commits] [lldb] r148488 - /lldb/trunk/source/Symbol/ClangASTImporter.cpp Message-ID: <20120119182306.CCAAA2A6C12C@llvm.org> Author: spyffe Date: Thu Jan 19 12:23:06 2012 New Revision: 148488 URL: http://llvm.org/viewvc/llvm-project?rev=148488&view=rev Log: Fixed a problem where Objective-C classes that were originally imported from symbols for the expression parser didn't get their superclasses set properly. Modified: lldb/trunk/source/Symbol/ClangASTImporter.cpp Modified: lldb/trunk/source/Symbol/ClangASTImporter.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTImporter.cpp?rev=148488&r1=148487&r2=148488&view=diff ============================================================================== --- lldb/trunk/source/Symbol/ClangASTImporter.cpp (original) +++ lldb/trunk/source/Symbol/ClangASTImporter.cpp Thu Jan 19 12:23:06 2012 @@ -312,6 +312,44 @@ ASTImporter::Imported(from, to); ImportDefinition(from); + + // If we're dealing with an Objective-C class, ensure that the inheritance has + // been set up correctly. The ASTImporter may not do this correctly if the + // class was originally sourced from symbols. + + if (ObjCInterfaceDecl *to_objc_interface = dyn_cast(to)) + { + do + { + ObjCInterfaceDecl *to_superclass = to_objc_interface->getSuperClass(); + + if (to_superclass) + break; // we're not going to override it if it's set + + ObjCInterfaceDecl *from_objc_interface = dyn_cast(from); + + if (!from_objc_interface) + break; + + ObjCInterfaceDecl *from_superclass = from_objc_interface->getSuperClass(); + + if (!from_superclass) + break; + + Decl *imported_from_superclass_decl = Import(from_superclass); + + if (!imported_from_superclass_decl) + break; + + ObjCInterfaceDecl *imported_from_superclass = dyn_cast(imported_from_superclass_decl); + + if (!imported_from_superclass) + break; + + to_objc_interface->setSuperClass(imported_from_superclass); + } + while (0); + } } clang::Decl From johnny.chen at apple.com Thu Jan 19 13:22:41 2012 From: johnny.chen at apple.com (Johnny Chen) Date: Thu, 19 Jan 2012 19:22:41 -0000 Subject: [Lldb-commits] [lldb] r148491 - in /lldb/trunk: source/Commands/CommandObjectSettings.cpp source/Commands/CommandObjectSettings.h source/Interpreter/Args.cpp test/functionalities/abbreviation/TestAbbreviations.py test/functionalities/abbreviation/change_prompt.lldb test/settings/TestSettings.py Message-ID: <20120119192241.93D372A6C12C@llvm.org> Author: johnny Date: Thu Jan 19 13:22:41 2012 New Revision: 148491 URL: http://llvm.org/viewvc/llvm-project?rev=148491&view=rev Log: rdar://problem/10712130 Fixed an issue where backtick char is not properly honored when setting the frame-format variable, like the following: (lldb) settings set frame-format frame #${frame.index}: ${frame.pc}{ ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}{ at ${line.file.basename}:${line.number}}\n (lldb) settings show frame-format frame-format (string) = "frame #${frame.index}: ${frame.pc}{ `${module.file.basename}{${function.name-with-args}${function.pc-offset}}}{` at ${line.file.basename}:${line.number}}\n" (lldb) o CommandObjectSettings.h/.cpp: Modify the command object impl to require raw command string instead of parsed command string, which also fixes an outstanding issue that customizing the prompt with trailing spaces doesn't work. o Args.cpp: During CommandInterpreter::HandleCommand(), there is a PreprocessCommand phase which already strips/processes pairs of backticks as an expression eval step. There's no need to treat a backtick as starting a quote. o TestAbbreviations.py and change_prompt.lldb: Fixed incorrect test case/logic. o TestSettings.py: Remove expectedFailure decorator. Modified: lldb/trunk/source/Commands/CommandObjectSettings.cpp lldb/trunk/source/Commands/CommandObjectSettings.h lldb/trunk/source/Interpreter/Args.cpp lldb/trunk/test/functionalities/abbreviation/TestAbbreviations.py lldb/trunk/test/functionalities/abbreviation/change_prompt.lldb lldb/trunk/test/settings/TestSettings.py Modified: lldb/trunk/source/Commands/CommandObjectSettings.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectSettings.cpp?rev=148491&r1=148490&r2=148491&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectSettings.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectSettings.cpp Thu Jan 19 13:22:41 2012 @@ -108,13 +108,24 @@ } +#include "llvm/ADT/StringRef.h" +static inline void StripLeadingSpaces(llvm::StringRef &Str) +{ + while (!Str.empty() && isspace(Str[0])) + Str = Str.substr(1); +} bool -CommandObjectSettingsSet::Execute (Args& command, CommandReturnObject &result) +CommandObjectSettingsSet::ExecuteRawCommandString (const char *raw_command, CommandReturnObject &result) { UserSettingsControllerSP usc_sp (Debugger::GetSettingsController ()); - const int argc = command.GetArgumentCount (); + Args cmd_args(raw_command); + + // Process possible options. + if (!ParseOptions (cmd_args, result)) + return false; + const int argc = cmd_args.GetArgumentCount (); if ((argc < 2) && (!m_options.m_reset)) { result.AppendError ("'settings set' takes more arguments"); @@ -122,8 +133,7 @@ return false; } - const char *var_name = command.GetArgumentAtIndex (0); - std::string var_name_string; + const char *var_name = cmd_args.GetArgumentAtIndex (0); if ((var_name == NULL) || (var_name[0] == '\0')) { result.AppendError ("'settings set' command requires a valid variable name; No value supplied"); @@ -131,17 +141,15 @@ return false; } - var_name_string = var_name; - command.Shift(); - - const char *var_value; - std::string value_string; - - command.GetQuotedCommandString (value_string); - var_value = value_string.c_str(); + // Split the raw command into var_name and value pair. + std::string var_name_string = var_name; + llvm::StringRef raw_str(raw_command); + llvm::StringRef value_str = raw_str.split(var_name_string).second; + StripLeadingSpaces(value_str); + std::string value_string = value_str.str(); if (!m_options.m_reset - && var_value == NULL) + && value_string.empty()) { result.AppendError ("'settings set' command requires a valid variable value unless using '--reset' option;" " No value supplied"); @@ -150,7 +158,7 @@ else { Error err = usc_sp->SetVariable (var_name_string.c_str(), - var_value, + value_string.c_str(), eVarSetOperationAssign, m_options.m_override, m_interpreter.GetDebugger().GetInstanceName().AsCString()); Modified: lldb/trunk/source/Commands/CommandObjectSettings.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectSettings.h?rev=148491&r1=148490&r2=148491&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectSettings.h (original) +++ lldb/trunk/source/Commands/CommandObjectSettings.h Thu Jan 19 13:22:41 2012 @@ -50,7 +50,15 @@ virtual bool Execute (Args& command, - CommandReturnObject &result); + CommandReturnObject &result) + { return false; } + + virtual bool + WantsRawCommandString() { return true; } + + virtual bool + ExecuteRawCommandString (const char *raw_command, + CommandReturnObject &result); virtual Options * GetOptions (); Modified: lldb/trunk/source/Interpreter/Args.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/Args.cpp?rev=148491&r1=148490&r2=148491&view=diff ============================================================================== --- lldb/trunk/source/Interpreter/Args.cpp (original) +++ lldb/trunk/source/Interpreter/Args.cpp Thu Jan 19 13:22:41 2012 @@ -168,7 +168,7 @@ if (command && command[0]) { static const char *k_space_separators = " \t"; - static const char *k_space_separators_with_slash_and_quotes = " \t \\'\"`"; + static const char *k_space_separators_with_slash_and_quotes = " \t \\'\""; const char *arg_end = NULL; const char *arg_pos; for (arg_pos = command; @@ -280,10 +280,7 @@ first_quote_char = quote_char; arg_pos = arg_end; - - if (quote_char != '`') - ++arg_pos; // Skip the quote character if it is not a backtick - + ++arg_pos; // Skip the quote character arg_piece_start = arg_pos; // Note we are starting from later in the string // Skip till the next quote character @@ -298,13 +295,7 @@ if (end_quote) { if (end_quote > arg_piece_start) - { - // Keep the backtick quote on commands - if (quote_char == '`') - arg.append (arg_piece_start, end_quote + 1 - arg_piece_start); - else - arg.append (arg_piece_start, end_quote - arg_piece_start); - } + arg.append (arg_piece_start, end_quote - arg_piece_start); // If the next character is a space or the end of // string, this argument is complete... Modified: lldb/trunk/test/functionalities/abbreviation/TestAbbreviations.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/abbreviation/TestAbbreviations.py?rev=148491&r1=148490&r2=148491&view=diff ============================================================================== --- lldb/trunk/test/functionalities/abbreviation/TestAbbreviations.py (original) +++ lldb/trunk/test/functionalities/abbreviation/TestAbbreviations.py Thu Jan 19 13:22:41 2012 @@ -38,7 +38,7 @@ patterns = ["Executing commands in '.*change_prompt.lldb'"]) self.expect("settings show prompt", - startstr = 'prompt (string) = "[old-oak]"') + startstr = 'prompt (string) = "[with-three-trailing-spaces] "') self.runCmd("settings set -r prompt") @@ -51,7 +51,7 @@ self.runCmd("se se prompt Sycamore> ") self.expect("se sh prompt", - startstr = 'prompt (string) = "Sycamore>"') + startstr = 'prompt (string) = "Sycamore> "') self.runCmd("se se -r prompt") self.expect("set sh prompt", Modified: lldb/trunk/test/functionalities/abbreviation/change_prompt.lldb URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/abbreviation/change_prompt.lldb?rev=148491&r1=148490&r2=148491&view=diff ============================================================================== --- lldb/trunk/test/functionalities/abbreviation/change_prompt.lldb (original) +++ lldb/trunk/test/functionalities/abbreviation/change_prompt.lldb Thu Jan 19 13:22:41 2012 @@ -1 +1,2 @@ -settings set prompt [old-oak] +settings set prompt [with-three-trailing-spaces] + Modified: lldb/trunk/test/settings/TestSettings.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/settings/TestSettings.py?rev=148491&r1=148490&r2=148491&view=diff ============================================================================== --- lldb/trunk/test/settings/TestSettings.py (original) +++ lldb/trunk/test/settings/TestSettings.py Thu Jan 19 13:22:41 2012 @@ -58,7 +58,6 @@ substrs = ["term-width (int) = 70"]) #rdar://problem/10712130 - @unittest2.expectedFailure def test_set_frame_format(self): """Test that 'set frame-format' with a backtick char in the format string works as well as fullpath.""" self.buildDefault() From jingham at apple.com Thu Jan 19 15:10:56 2012 From: jingham at apple.com (Jim Ingham) Date: Thu, 19 Jan 2012 21:10:56 -0000 Subject: [Lldb-commits] [lldb] r148494 - /lldb/trunk/source/Core/ValueObject.cpp Message-ID: <20120119211056.B40302A6C12C@llvm.org> Author: jingham Date: Thu Jan 19 15:10:56 2012 New Revision: 148494 URL: http://llvm.org/viewvc/llvm-project?rev=148494&view=rev Log: ValueObjectRegister type value objects should obey the format in ValueAsCString. Modified: lldb/trunk/source/Core/ValueObject.cpp Modified: lldb/trunk/source/Core/ValueObject.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=148494&r1=148493&r2=148494&view=diff ============================================================================== --- lldb/trunk/source/Core/ValueObject.cpp (original) +++ lldb/trunk/source/Core/ValueObject.cpp Thu Jan 19 15:10:56 2012 @@ -1080,8 +1080,17 @@ const RegisterInfo *reg_info = m_value.GetRegisterInfo(); if (reg_info) { + lldb::Format my_format = GetFormat(); + if (m_format == lldb::eFormatDefault) + { + if (m_last_value_format) + my_format = m_last_value_format->GetFormat(); + else + my_format = reg_info->format; + } + StreamString reg_sstr; - m_data.Dump(®_sstr, 0, reg_info->format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0, GetExecutionContextScope()); + m_data.Dump(®_sstr, 0, my_format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0, GetExecutionContextScope()); m_value_str.swap(reg_sstr.GetString()); } } From johnny.chen at apple.com Thu Jan 19 16:16:06 2012 From: johnny.chen at apple.com (Johnny Chen) Date: Thu, 19 Jan 2012 22:16:06 -0000 Subject: [Lldb-commits] [lldb] r148500 - in /lldb/trunk: include/lldb/Interpreter/CommandObject.h source/Commands/CommandObjectSettings.h source/Interpreter/CommandObject.cpp Message-ID: <20120119221606.605572A6C12C@llvm.org> Author: johnny Date: Thu Jan 19 16:16:06 2012 New Revision: 148500 URL: http://llvm.org/viewvc/llvm-project?rev=148500&view=rev Log: rdar://problem/10724187 http://llvm.org/viewvc/llvm-project?rev=148491&view=rev check in broke the argument completion for "settings set th", followed by TAB. Provide a way for commands who want raw commands to hook into the completion mechanism. Modified: lldb/trunk/include/lldb/Interpreter/CommandObject.h lldb/trunk/source/Commands/CommandObjectSettings.h lldb/trunk/source/Interpreter/CommandObject.cpp Modified: lldb/trunk/include/lldb/Interpreter/CommandObject.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/CommandObject.h?rev=148500&r1=148499&r2=148500&view=diff ============================================================================== --- lldb/trunk/include/lldb/Interpreter/CommandObject.h (original) +++ lldb/trunk/include/lldb/Interpreter/CommandObject.h Thu Jan 19 16:16:06 2012 @@ -141,6 +141,12 @@ virtual bool WantsRawCommandString() { return false; } + // By default, WantsCompletion = !WantsRawCommandString. + // Subclasses who want raw command string but desire, for example, + // argument completion should override this method to return true. + virtual bool + WantsCompletion() { return !WantsRawCommandString(); } + virtual Options * GetOptions (); Modified: lldb/trunk/source/Commands/CommandObjectSettings.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectSettings.h?rev=148500&r1=148499&r2=148500&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectSettings.h (original) +++ lldb/trunk/source/Commands/CommandObjectSettings.h Thu Jan 19 16:16:06 2012 @@ -56,6 +56,10 @@ virtual bool WantsRawCommandString() { return true; } + // Overrides base class's behavior where WantsCompletion = !WantsRawCommandString. + virtual bool + WantsCompletion() { return true; } + virtual bool ExecuteRawCommandString (const char *raw_command, CommandReturnObject &result); Modified: lldb/trunk/source/Interpreter/CommandObject.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandObject.cpp?rev=148500&r1=148499&r2=148500&view=diff ============================================================================== --- lldb/trunk/source/Interpreter/CommandObject.cpp (original) +++ lldb/trunk/source/Interpreter/CommandObject.cpp Thu Jan 19 16:16:06 2012 @@ -344,7 +344,7 @@ StringList &matches ) { - if (WantsRawCommandString()) + if (WantsRawCommandString() && !WantsCompletion()) { // FIXME: Abstract telling the completion to insert the completion character. matches.Clear(); From scallanan at apple.com Thu Jan 19 17:54:24 2012 From: scallanan at apple.com (Sean Callanan) Date: Thu, 19 Jan 2012 23:54:24 -0000 Subject: [Lldb-commits] [lldb] r148512 - in /lldb/trunk: include/lldb/Symbol/ClangASTContext.h source/Symbol/ClangASTContext.cpp Message-ID: <20120119235424.B76062A6C12C@llvm.org> Author: spyffe Date: Thu Jan 19 17:54:24 2012 New Revision: 148512 URL: http://llvm.org/viewvc/llvm-project?rev=148512&view=rev Log: Made IsArrayOfScalarType handle typedefs correctly. We should ultimately introduce GetAs...Type functions in all cases where we have Is...Type functions that know how to look inside typedefs. Modified: lldb/trunk/include/lldb/Symbol/ClangASTContext.h lldb/trunk/source/Symbol/ClangASTContext.cpp Modified: lldb/trunk/include/lldb/Symbol/ClangASTContext.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangASTContext.h?rev=148512&r1=148511&r2=148512&view=diff ============================================================================== --- lldb/trunk/include/lldb/Symbol/ClangASTContext.h (original) +++ lldb/trunk/include/lldb/Symbol/ClangASTContext.h Thu Jan 19 17:54:24 2012 @@ -782,8 +782,18 @@ static bool IsFunctionPointerType (lldb::clang_type_t clang_type); + static lldb::clang_type_t + GetAsArrayType (lldb::clang_type_t clang_type, + lldb::clang_type_t *member_type = NULL, + uint64_t *size = NULL); + static bool - IsArrayType (lldb::clang_type_t clang_type, lldb::clang_type_t *member_type = NULL, uint64_t *size = NULL); + IsArrayType (lldb::clang_type_t clang_type, + lldb::clang_type_t *member_type = NULL, + uint64_t *size = NULL) + { + return GetAsArrayType(clang_type, member_type, size) != 0; + } //------------------------------------------------------------------ // Typedefs Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=148512&r1=148511&r2=148512&view=diff ============================================================================== --- lldb/trunk/source/Symbol/ClangASTContext.cpp (original) +++ lldb/trunk/source/Symbol/ClangASTContext.cpp Thu Jan 19 17:54:24 2012 @@ -5537,7 +5537,9 @@ bool ClangASTContext::IsArrayOfScalarType (lldb::clang_type_t clang_type) { - if (!IsArrayType(clang_type)) + clang_type = GetAsArrayType(clang_type); + + if (clang_type == 0) return false; QualType qual_type (QualType::getFromOpaquePtr(clang_type)); @@ -5708,11 +5710,11 @@ return 0; } -bool -ClangASTContext::IsArrayType (clang_type_t clang_type, clang_type_t*member_type, uint64_t *size) +clang_type_t +ClangASTContext::GetAsArrayType (clang_type_t clang_type, clang_type_t*member_type, uint64_t *size) { if (!clang_type) - return false; + return 0; QualType qual_type (QualType::getFromOpaquePtr(clang_type)); @@ -5727,40 +5729,40 @@ *member_type = cast(qual_type)->getElementType().getAsOpaquePtr(); if (size) *size = cast(qual_type)->getSize().getLimitedValue(ULLONG_MAX); - return true; + return clang_type; case clang::Type::IncompleteArray: if (member_type) *member_type = cast(qual_type)->getElementType().getAsOpaquePtr(); if (size) *size = 0; - return true; + return clang_type; case clang::Type::VariableArray: if (member_type) *member_type = cast(qual_type)->getElementType().getAsOpaquePtr(); if (size) *size = 0; - return true; + return clang_type; case clang::Type::DependentSizedArray: if (member_type) *member_type = cast(qual_type)->getElementType().getAsOpaquePtr(); if (size) *size = 0; - return true; + return clang_type; case clang::Type::Typedef: - return ClangASTContext::IsArrayType (cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), - member_type, - size); + return ClangASTContext::GetAsArrayType (cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), + member_type, + size); case clang::Type::Elaborated: - return ClangASTContext::IsArrayType (cast(qual_type)->getNamedType().getAsOpaquePtr(), - member_type, - size); + return ClangASTContext::GetAsArrayType (cast(qual_type)->getNamedType().getAsOpaquePtr(), + member_type, + size); } - return false; + return 0; } From johnny.chen at apple.com Thu Jan 19 18:59:20 2012 From: johnny.chen at apple.com (Johnny Chen) Date: Fri, 20 Jan 2012 00:59:20 -0000 Subject: [Lldb-commits] [lldb] r148521 - /lldb/trunk/source/Interpreter/CommandObject.cpp Message-ID: <20120120005920.11D1C2A6C12C@llvm.org> Author: johnny Date: Thu Jan 19 18:59:19 2012 New Revision: 148521 URL: http://llvm.org/viewvc/llvm-project?rev=148521&view=rev Log: Add comment describing the interaction of WantsRawCommandString()/WantsCompletion() with the completion mechanism. Modified: lldb/trunk/source/Interpreter/CommandObject.cpp Modified: lldb/trunk/source/Interpreter/CommandObject.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandObject.cpp?rev=148521&r1=148520&r2=148521&view=diff ============================================================================== --- lldb/trunk/source/Interpreter/CommandObject.cpp (original) +++ lldb/trunk/source/Interpreter/CommandObject.cpp Thu Jan 19 18:59:19 2012 @@ -344,6 +344,10 @@ StringList &matches ) { + // Default implmentation of WantsCompletion() is !WantsRawCommandString(). + // Subclasses who want raw command string but desire, for example, + // argument completion should override WantsCompletion() to return true, + // instead. if (WantsRawCommandString() && !WantsCompletion()) { // FIXME: Abstract telling the completion to insert the completion character. From gclayton at apple.com Thu Jan 19 19:31:25 2012 From: gclayton at apple.com (Greg Clayton) Date: Fri, 20 Jan 2012 01:31:25 -0000 Subject: [Lldb-commits] [lldb] r148523 - in /lldb/trunk/examples/darwin: ./ heap_find/ heap_find/Makefile heap_find/heap_find.c Message-ID: <20120120013125.293B62A6C12C@llvm.org> Author: gclayton Date: Thu Jan 19 19:31:24 2012 New Revision: 148523 URL: http://llvm.org/viewvc/llvm-project?rev=148523&view=rev Log: Added a new tool that can be loaded into a user space darwin application and allows you to find data on the heap. To use this, make the project and then when stopped in your lldb debug session: (lldb) process load /path/to/libheap.dylib (lldb) find_pointer_in_heap (0x112233000000) This will grep everything in all active allocation blocks and print and malloc blocks that contain the pointer 0x112233000000. This can also work for c strings: (lldb) find_cstring_in_heap ("hello") Added: lldb/trunk/examples/darwin/ lldb/trunk/examples/darwin/heap_find/ lldb/trunk/examples/darwin/heap_find/Makefile lldb/trunk/examples/darwin/heap_find/heap_find.c Added: lldb/trunk/examples/darwin/heap_find/Makefile URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/darwin/heap_find/Makefile?rev=148523&view=auto ============================================================================== --- lldb/trunk/examples/darwin/heap_find/Makefile (added) +++ lldb/trunk/examples/darwin/heap_find/Makefile Thu Jan 19 19:31:24 2012 @@ -0,0 +1,7 @@ +LEVEL = ../../../test/make + +DYLIB_NAME := heap +DYLIB_ONLY := YES +DYLIB_C_SOURCES := heap_find.c + +include $(LEVEL)/Makefile.rules Added: lldb/trunk/examples/darwin/heap_find/heap_find.c URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/darwin/heap_find/heap_find.c?rev=148523&view=auto ============================================================================== --- lldb/trunk/examples/darwin/heap_find/heap_find.c (added) +++ lldb/trunk/examples/darwin/heap_find/heap_find.c Thu Jan 19 19:31:24 2012 @@ -0,0 +1,193 @@ +#include +#include +#include +#include +#include +#include + +struct range_callback_info_t; + +typedef void range_callback_t (task_t task, void *baton, unsigned type, uint64_t ptr_addr, uint64_t ptr_size); +typedef void zone_callback_t (void *info, const malloc_zone_t *zone); + +typedef struct range_callback_info_tag +{ + zone_callback_t *zone_callback; + range_callback_t *range_callback; + void *baton; +} range_callback_info_t; + +typedef enum data_type +{ + eDataTypeBytes, + eDataTypeCStr, + eDataTypeInteger +} data_type_t; + +typedef struct range_contains_data_callback_info_tag +{ + const uint8_t *data; + const size_t data_len; + const uint32_t align; + const data_type_t data_type; + uint32_t match_count; +} range_contains_data_callback_info_t; + + +static kern_return_t +task_peek (task_t task, vm_address_t remote_address, vm_size_t size, void **local_memory) +{ + *local_memory = (void*) remote_address; + return KERN_SUCCESS; +} + + +static const void +foreach_zone_in_this_process (range_callback_info_t *info) +{ + //printf ("foreach_zone_in_this_process ( info->zone_callback = %p, info->range_callback = %p, info->baton = %p)", info->zone_callback, info->range_callback, info->baton); + if (info == NULL || info->zone_callback == NULL) + return; + + vm_address_t *zones = NULL; + unsigned int num_zones = 0; + + kern_return_t err = malloc_get_all_zones (0, task_peek, &zones, &num_zones); + if (KERN_SUCCESS == err) + { + for (unsigned int i=0; izone_callback (info, (const malloc_zone_t *)zones[i]); + } + } +} + +static void +range_callback (task_t task, void *baton, unsigned type, uint64_t ptr_addr, uint64_t ptr_size) +{ + printf ("task = 0x%4.4x: baton = %p, type = %u, ptr_addr = 0x%llx + 0x%llu\n", task, baton, type, ptr_addr, ptr_size); +} + +static void +ranges_callback (task_t task, void *baton, unsigned type, vm_range_t *ptrs, unsigned count) +{ + range_callback_info_t *info = (range_callback_info_t *)baton; + while(count--) { + info->range_callback (task, info->baton, type, ptrs->address, ptrs->size); + ptrs++; + } +} + +static void +enumerate_range_in_zone (void *baton, const malloc_zone_t *zone) +{ + range_callback_info_t *info = (range_callback_info_t *)baton; + + if (zone && zone->introspect) + zone->introspect->enumerator (mach_task_self(), + info, + MALLOC_PTR_IN_USE_RANGE_TYPE, + (vm_address_t)zone, + task_peek, + ranges_callback); +} + +const void +foreach_range_in_this_process (range_callback_t *callback, void *baton) +{ + range_callback_info_t info = { enumerate_range_in_zone, callback ? callback : range_callback, baton }; + foreach_zone_in_this_process (&info); +} + +static void +range_contains_ptr_callback (task_t task, void *baton, unsigned type, uint64_t ptr_addr, uint64_t ptr_size) +{ + uint8_t *data = NULL; + range_contains_data_callback_info_t *data_info = (range_contains_data_callback_info_t *)baton; + if (data_info->data_len <= 0) + { + printf ("error: invalid data size: %zu\n", data_info->data_len); + } + else if (data_info->data_len > ptr_size) + { + // This block is too short to contain the data we are looking for... + return; + } + else if (task_peek (task, ptr_addr, ptr_size, (void **)&data) == KERN_SUCCESS) + { + assert (data); + const uint64_t end_addr = ptr_addr + ptr_size; + for (uint64_t addr = ptr_addr; + addr < end_addr && ((end_addr - addr) >= data_info->data_len); + addr += data_info->align, data += data_info->align) + { + if (memcmp (data_info->data, data, data_info->data_len) == 0) + { + ++data_info->match_count; + printf ("0x%llx: ", addr); + uint32_t i; + switch (data_info->data_type) + { + case eDataTypeInteger: + { + // NOTE: little endian specific, but all darwin platforms are little endian now.. + for (i=0; idata_len; ++i) + printf (i ? "%2.2x" : "0x%2.2x", data[data_info->data_len - (i + 1)]); + } + break; + case eDataTypeBytes: + { + for (i=0; idata_len; ++i) + printf (" %2.2x", data[i]); + } + break; + case eDataTypeCStr: + { + putchar ('"'); + for (i=0; idata_len; ++i) + { + if (isprint (data[i])) + putchar (data[i]); + else + printf ("\\x%2.2x", data[i]); + } + putchar ('"'); + } + break; + + } + printf (" found in malloc block 0x%llx + %llu (malloc_size = %llu)\n", ptr_addr, addr - ptr_addr, ptr_size); + } + } + } + else + { + printf ("0x%llx: error: couldn't read %llu bytes\n", ptr_addr, ptr_size); + } +} + +uint32_t +find_pointer_in_heap (intptr_t addr) +{ + range_contains_data_callback_info_t data_info = { (uint8_t *)&addr, sizeof(addr), sizeof(addr), eDataTypeInteger, 0}; + range_callback_info_t info = { enumerate_range_in_zone, range_contains_ptr_callback, &data_info }; + foreach_zone_in_this_process (&info); + return data_info.match_count; +} + +uint32_t +find_cstring_in_heap (const char *s) +{ + if (s && s[0]) + { + range_contains_data_callback_info_t data_info = { (uint8_t *)s, strlen(s), 1, eDataTypeCStr, 0}; + range_callback_info_t info = { enumerate_range_in_zone, range_contains_ptr_callback, &data_info }; + foreach_zone_in_this_process (&info); + return data_info.match_count; + } + else + { + printf ("error: invalid argument (empty cstring)\n"); + } + return 0; +} From gclayton at apple.com Thu Jan 19 20:10:53 2012 From: gclayton at apple.com (Greg Clayton) Date: Fri, 20 Jan 2012 02:10:53 -0000 Subject: [Lldb-commits] [lldb] r148527 - /lldb/trunk/examples/darwin/heap_find/heap_find.c Message-ID: <20120120021053.30B2B2A6C12C@llvm.org> Author: gclayton Date: Thu Jan 19 20:10:52 2012 New Revision: 148527 URL: http://llvm.org/viewvc/llvm-project?rev=148527&view=rev Log: Add some usage documentation to the top of the source file. Modified: lldb/trunk/examples/darwin/heap_find/heap_find.c Modified: lldb/trunk/examples/darwin/heap_find/heap_find.c URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/darwin/heap_find/heap_find.c?rev=148527&r1=148526&r2=148527&view=diff ============================================================================== --- lldb/trunk/examples/darwin/heap_find/heap_find.c (original) +++ lldb/trunk/examples/darwin/heap_find/heap_find.c Thu Jan 19 20:10:52 2012 @@ -1,3 +1,36 @@ +//===-- head_find.c ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file compiles into a dylib and can be used on darwin to find data that +// is contained in active malloc blocks. To use this make the project, then +// load the shared library in a debug session while you are stopped: +// +// (lldb) process load /path/to/libheap.dylib +// +// Now you can use the "find_pointer_in_heap" and "find_cstring_in_heap" +// functions in the expression parser. +// +// This will grep everything in all active allocation blocks and print and +// malloc blocks that contain the pointer 0x112233000000: +// +// (lldb) expression find_pointer_in_heap (0x112233000000) +// +// This will grep everything in all active allocation blocks and print and +// malloc blocks that contain the C string "hello" (as a substring, no +// NULL termination included): +// +// (lldb) expression find_cstring_in_heap ("hello") +// +// The results will be printed to the STDOUT of the inferior program. +// +//===----------------------------------------------------------------------===// + #include #include #include From gclayton at apple.com Thu Jan 19 21:15:45 2012 From: gclayton at apple.com (Greg Clayton) Date: Fri, 20 Jan 2012 03:15:45 -0000 Subject: [Lldb-commits] [lldb] r148528 - /lldb/trunk/examples/python/crashlog.py Message-ID: <20120120031545.5A8282A6C12C@llvm.org> Author: gclayton Date: Thu Jan 19 21:15:45 2012 New Revision: 148528 URL: http://llvm.org/viewvc/llvm-project?rev=148528&view=rev Log: Modified the symbolicate-crash.py so it can be imported into python as a module (you can't import a module with a '-' in it) and also added a Symbolcate(...) top level function so it can be imported and used as an LLDB command. Then you can import the module and map a "crashlog" command (for darwin use only currently) to the python function "crashlog.Symbolicate": (lldb) script import crashlog (lldb) command script add -f crashlog.Symbolicate crashlog Then use it to symbolicate: (lldb) crashlog --crash-log /path/to/foo.crash The crash log will then get symbolicated and inline frames will be added to the crash log and the frames will be displayed. The crash log currently will only try and fetch and setup the target images requires in order to do the symbolication. This will need to be iterated upon, but it is getting close to being useful so I am going to check this in. Added: lldb/trunk/examples/python/crashlog.py (with props) Added: lldb/trunk/examples/python/crashlog.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/python/crashlog.py?rev=148528&view=auto ============================================================================== --- lldb/trunk/examples/python/crashlog.py (added) +++ lldb/trunk/examples/python/crashlog.py Thu Jan 19 21:15:45 2012 @@ -0,0 +1,622 @@ +#!/usr/bin/python + +#---------------------------------------------------------------------- +# Be sure to add the python path that points to the LLDB shared library. +# On MacOSX csh, tcsh: +# setenv PYTHONPATH /Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python +# On MacOSX sh, bash: +# export PYTHONPATH=/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python +#---------------------------------------------------------------------- + +import lldb +import commands # commands.getoutput ('/bin/ls /tmp') +import optparse +import os +import plistlib +import pprint +import re +import sys +import time + +PARSE_MODE_NORMAL = 0 +PARSE_MODE_THREAD = 1 +PARSE_MODE_IMAGES = 2 +PARSE_MODE_THREGS = 3 +PARSE_MODE_SYSTEM = 4 + +class CrashLog: + """Class that does parses darwin crash logs""" + thread_state_regex = re.compile('^Thread ([0-9]+) crashed with') + thread_regex = re.compile('^Thread ([0-9]+)([^:]*):(.*)') + frame_regex = re.compile('^([0-9]+) +([^ ]+) +\t(0x[0-9a-fA-F]+) +(.*)') + image_regex_uuid = re.compile('(0x[0-9a-fA-F]+)[- ]+(0x[0-9a-fA-F]+) +([^ ]+) +([^<]+)<([-0-9a-fA-F]+)> (.*)'); + image_regex_no_uuid = re.compile('(0x[0-9a-fA-F]+)[- ]+(0x[0-9a-fA-F]+) +([^ ]+) +([^/]+)/(.*)'); + empty_line_regex = re.compile('^$') + + class Thread: + """Class that represents a thread in a darwin crash log""" + def __init__(self, index): + self.index = index + self.frames = list() + self.registers = dict() + self.reason = None + self.queue = None + + def dump(self, prefix): + print "%sThread[%u] %s" % (prefix, self.index, self.reason) + if self.frames: + print "%s Frames:" % (prefix) + for frame in self.frames: + frame.dump(prefix + ' ') + if self.registers: + print "%s Registers:" % (prefix) + for reg in self.registers.keys(): + print "%s %-5s = %#16.16x" % (prefix, reg, self.registers[reg]) + + def did_crash(self): + return self.reason != None + + def __str__(self): + s = "Thread[%u]" % self.index + if self.reason: + s += ' %s' % self.reason + return s + + + class Frame: + """Class that represents a stack frame in a thread in a darwin crash log""" + def __init__(self, index, pc, details): + self.index = index + self.pc = pc + self.sym_ctx = None + self.details = details + + def __str__(self): + return "[%2u] %#16.16x %s" % (self.index, self.pc, self.details) + + def dump(self, prefix): + print "%s%s" % (prefix, self) + + + class Image: + """Class that represents a binary images in a darwin crash log""" + def __init__(self, text_addr_lo, text_addr_hi, ident, version, uuid, path): + self.text_addr_lo = text_addr_lo + self.text_addr_hi = text_addr_hi + self.ident = ident + self.version = version + self.uuid = uuid + self.path = path + self.target = None + self.module = None + self.plist = None + + def dump(self, prefix): + print "%s%s" % (prefix, self) + + def __str__(self): + return "%#16.16x %s %s" % (self.text_addr_lo, self.uuid, self.path) + + def basename(self): + if self.path: + return os.path.basename(self.path) + return None + + def fetch_symboled_executable_and_dsym(self): + dsym_for_uuid_command = ('~rc/bin/dsymForUUID %s' % self.uuid) + print 'Fetching %s %s...' % (self.uuid, self.path), + s = commands.getoutput(dsym_for_uuid_command) + if s: + plist_root = plistlib.readPlistFromString (s) + if plist_root: + # pp = pprint.PrettyPrinter(indent=4) + # pp.pprint(plist_root) + self.plist = plist_root[self.uuid] + if self.plist: + if 'DBGError' in self.plist: + err = self.plist['DBGError'] + if isinstance(err, unicode): + err = err.encode('utf-8') + print 'error: %s' % err + elif 'DBGSymbolRichExecutable' in self.plist: + self.path = os.path.expanduser (self.plist['DBGSymbolRichExecutable']) + #print 'success: symboled exe is "%s"' % self.path + print 'ok' + return 1 + print 'error: failed to get plist dictionary entry for UUID %s: %s' % (uuid, plist_root) + else: + print 'error: failed to extract plist from "%s"' % (s) + else: + print 'error: %s failed...' % (dsym_for_uuid_command) + return 0 + + def load_module(self): + if self.module: + text_section = self.module.FindSection ("__TEXT") + if text_section: + error = self.target.SetSectionLoadAddress (text_section, self.text_addr_lo) + if error.Success(): + print 'Success: loaded %s.__TEXT = 0x%x' % (self.basename(), self.text_addr_lo) + return None + else: + return 'error: %s' % error.GetCString() + else: + return 'error: unable to find "__TEXT" section in "%s"' % self.path + else: + return 'error: invalid module' + + def create_target(self, debugger): + if self.fetch_symboled_executable_and_dsym (): + path_spec = lldb.SBFileSpec (self.path) + arch = self.plist['DBGArchitecture'] + #print 'debugger.CreateTarget (path="%s", arch="%s") uuid=%s' % (self.path, arch, self.uuid) + #result.PutCString ('plist[%s] = %s' % (uuid, self.plist)) + error = lldb.SBError() + self.target = debugger.CreateTarget (self.path, arch, None, False, error); + if self.target: + self.module = self.target.FindModule (path_spec) + if self.module: + err = self.load_module() + if err: + print err + else: + return None + else: + return 'error: unable to get module for (%s) "%s"' % (arch, self.path) + else: + return 'error: unable to create target for (%s) "%s"' % (arch, self.path) + + def add_target_module(self, target): + if target: + self.target = target + if self.fetch_symboled_executable_and_dsym (): + path_spec = lldb.SBFileSpec (self.path) + arch = self.plist['DBGArchitecture'] + #result.PutCString ('plist[%s] = %s' % (uuid, self.plist)) + #print 'target.AddModule (path="%s", arch="%s", uuid=%s)' % (self.path, arch, self.uuid) + self.module = target.AddModule (self.path, arch, self.uuid) + if self.module: + err = self.load_module() + if err: + print err; + else: + return None + else: + return 'error: unable to get module for (%s) "%s"' % (arch, self.path) + else: + return 'error: invalid target' + + def __init__(self, path): + """CrashLog constructor that take a path to a darwin crash log file""" + self.path = path; + self.info_lines = list() + self.system_profile = list() + self.threads = list() + self.images = list() + self.idents = list() # A list of the required identifiers for doing all stack backtraces + self.crashed_thread_idx = -1 + self.version = -1 + # With possible initial component of ~ or ~user replaced by that user's home directory. + f = open(os.path.expanduser(self.path)) + self.file_lines = f.read().splitlines() + parse_mode = PARSE_MODE_NORMAL + thread = None + for line in self.file_lines: + # print line + line_len = len(line) + if line_len == 0: + if thread: + if parse_mode == PARSE_MODE_THREAD: + if thread.index == self.crashed_thread_idx: + thread.reason = '' + if self.thread_exception: + thread.reason += self.thread_exception + if self.thread_exception_data: + thread.reason += " (%s)" % self.thread_exception_data + self.threads.append(thread) + thread = None + else: + # only append an extra empty line if the previous line + # in the info_lines wasn't empty + if len(self.info_lines) > 0 and len(self.info_lines[-1]): + self.info_lines.append(line) + parse_mode = PARSE_MODE_NORMAL + # print 'PARSE_MODE_NORMAL' + elif parse_mode == PARSE_MODE_NORMAL: + if line.startswith ('Process:'): + (self.process_name, pid_with_brackets) = line[8:].strip().split() + self.process_id = pid_with_brackets.strip('[]') + elif line.startswith ('Path:'): + self.process_path = line[5:].strip() + elif line.startswith ('Identifier:'): + self.process_identifier = line[11:].strip() + elif line.startswith ('Version:'): + (self.process_version, compatability_version) = line[8:].strip().split() + self.process_compatability_version = compatability_version.strip('()') + elif line.startswith ('Parent Process:'): + (self.parent_process_name, pid_with_brackets) = line[15:].strip().split() + self.parent_process_id = pid_with_brackets.strip('[]') + elif line.startswith ('Exception Type:'): + self.thread_exception = line[15:].strip() + continue + elif line.startswith ('Exception Codes:'): + self.thread_exception_data = line[16:].strip() + continue + elif line.startswith ('Crashed Thread:'): + self.crashed_thread_idx = int(line[15:].strip().split()[0]) + continue + elif line.startswith ('Report Version:'): + self.version = int(line[15:].strip()) + continue + elif line.startswith ('System Profile:'): + parse_mode = PARSE_MODE_SYSTEM + continue + elif (line.startswith ('Interval Since Last Report:') or + line.startswith ('Crashes Since Last Report:') or + line.startswith ('Per-App Interval Since Last Report:') or + line.startswith ('Per-App Crashes Since Last Report:') or + line.startswith ('Sleep/Wake UUID:') or + line.startswith ('Anonymous UUID:')): + # ignore these + continue + elif line.startswith ('Thread'): + thread_state_match = self.thread_state_regex.search (line) + if thread_state_match: + thread_state_match = self.thread_regex.search (line) + thread_idx = int(thread_state_match.group(1)) + parse_mode = PARSE_MODE_THREGS + thread = self.threads[thread_idx] + else: + thread_match = self.thread_regex.search (line) + if thread_match: + # print 'PARSE_MODE_THREAD' + parse_mode = PARSE_MODE_THREAD + thread_idx = int(thread_match.group(1)) + thread = CrashLog.Thread(thread_idx) + continue + elif line.startswith ('Binary Images:'): + parse_mode = PARSE_MODE_IMAGES + continue + self.info_lines.append(line.strip()) + elif parse_mode == PARSE_MODE_THREAD: + frame_match = self.frame_regex.search(line) + if frame_match: + ident = frame_match.group(2) + if not ident in self.idents: + self.idents.append(ident) + thread.frames.append (CrashLog.Frame(int(frame_match.group(1)), int(frame_match.group(3), 0), frame_match.group(4))) + else: + print "error: frame regex failed" + elif parse_mode == PARSE_MODE_IMAGES: + image_match = self.image_regex_uuid.search (line) + if image_match: + image = CrashLog.Image (int(image_match.group(1),0), + int(image_match.group(2),0), + image_match.group(3).strip(), + image_match.group(4).strip(), + image_match.group(5), + image_match.group(6)) + self.images.append (image) + else: + image_match = self.image_regex_no_uuid.search (line) + if image_match: + image = CrashLog.Image (int(image_match.group(1),0), + int(image_match.group(2),0), + image_match.group(3).strip(), + image_match.group(4).strip(), + None, + image_match.group(5)) + self.images.append (image) + else: + print "error: image regex failed for: %s" % line + + elif parse_mode == PARSE_MODE_THREGS: + stripped_line = line.strip() + reg_values = stripped_line.split(' ') + for reg_value in reg_values: + (reg, value) = reg_value.split(': ') + thread.registers[reg.strip()] = int(value, 0) + elif parse_mode == PARSE_MODE_SYSTEM: + self.system_profile.append(line) + f.close() + + def dump(self): + print "Crash Log File: %s" % (self.path) + print "\nThreads:" + for thread in self.threads: + thread.dump(' ') + print "\nImages:" + for image in self.images: + image.dump(' ') + + def find_image_with_identifier(self, ident): + for image in self.images: + if image.ident == ident: + return image + return None + +def disassemble_instructions (target, instructions, pc, insts_before_pc, insts_after_pc): + lines = list() + pc_index = -1 + comment_column = 50 + for inst_idx, inst in enumerate(instructions): + inst_pc = inst.GetAddress().GetLoadAddress(target); + if pc == inst_pc: + pc_index = inst_idx + mnemonic = inst.GetMnemonic (target) + operands = inst.GetOperands (target) + comment = inst.GetComment (target) + #data = inst.GetData (target) + lines.append ("%#16.16x: %8s %s" % (inst_pc, mnemonic, operands)) + if comment: + line_len = len(lines[-1]) + if line_len < comment_column: + lines[-1] += ' ' * (comment_column - line_len) + lines[-1] += "; %s" % comment + + if pc_index >= 0: + if pc_index >= insts_before_pc: + start_idx = pc_index - insts_before_pc + else: + start_idx = 0 + end_idx = pc_index + insts_after_pc + if end_idx > inst_idx: + end_idx = inst_idx + for i in range(start_idx, end_idx+1): + if i == pc_index: + print ' -> ', lines[i] + else: + print ' ', lines[i] + +def print_module_section_data (section): + print section + section_data = section.GetSectionData() + if section_data: + ostream = lldb.SBStream() + section_data.GetDescription (ostream, section.GetFileAddress()) + print ostream.GetData() + +def print_module_section (section, depth): + print section + + if depth > 0: + num_sub_sections = section.GetNumSubSections() + for sect_idx in range(num_sub_sections): + print_module_section (section.GetSubSectionAtIndex(sect_idx), depth - 1) + +def print_module_sections (module, depth): + for sect in module.section_iter(): + print_module_section (sect, depth) + +def print_module_symbols (module): + for sym in module: + print sym + +def usage(): + print "Usage: lldb-symbolicate.py [-n name] executable-image" + sys.exit(0) + +def Symbolicate(debugger, command, result, dict): + SymbolicateCrashLog (command.split()) + +def SymbolicateCrashLog(command_args): + + parser = optparse.OptionParser(description='A script that parses skinny and universal mach-o files.') + parser.add_option('--arch', type='string', metavar='arch', dest='triple', help='specify one architecture or target triple') + parser.add_option('--platform', type='string', metavar='platform', dest='platform', help='specify one platform by name') + parser.add_option('--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) + parser.add_option('--interactive', action='store_true', dest='interactive', help='enable interactive mode', default=False) + parser.add_option('--no-images', action='store_false', dest='show_images', help='don\'t show images in stack frames', default=True) + parser.add_option('--no-dependents', action='store_false', dest='dependents', help='skip loading dependent modules', default=True) + parser.add_option('--sections', action='store_true', dest='dump_sections', help='show module sections', default=False) + parser.add_option('--symbols', action='store_true', dest='dump_symbols', help='show module symbols', default=False) + parser.add_option('--image-list', action='store_true', dest='dump_image_list', help='show image list', default=False) + parser.add_option('--debug-delay', type='int', dest='debug_delay', metavar='NSEC', help='pause for NSEC seconds for debugger', default=0) + parser.add_option('--section-depth', type='int', dest='section_depth', help='set the section depth to use when showing sections', default=0) + parser.add_option('--section-data', type='string', action='append', dest='sect_data_names', help='specify sections by name to display data for') + parser.add_option('--address', type='int', action='append', dest='addresses', help='specify addresses to lookup') + parser.add_option('--crash-log', type='string', action='append', dest='crash_log_files', help='specify crash log files to symbolicate') + parser.add_option('--crashed-only', action='store_true', dest='crashed_only', help='only show the crashed thread', default=False) + loaded_addresses = False + (options, args) = parser.parse_args(command_args) + if options.verbose: + print 'options', options + + if options.debug_delay > 0: + print "Waiting %u seconds for debugger to attach..." % options.debug_delay + time.sleep(options.debug_delay) + + # Create a new debugger instance + debugger = lldb.SBDebugger.Create() + + error = lldb.SBError() + + + if options.crash_log_files: + options.dependents = False + for crash_log_file in options.crash_log_files: + crash_log = CrashLog(crash_log_file) + crash_log.dump() + if crash_log.images: + err = crash_log.images[0].create_target (debugger) + if err: + print err + else: + target = crash_log.images[0].target + exe_module = target.GetModuleAtIndex(0) + image_paths = list() + # for i in range (1, len(crash_log.images)): + # image = crash_log.images[i] + for ident in crash_log.idents: + image = crash_log.find_image_with_identifier (ident) + if image: + if image.path in image_paths: + print "warning: skipping %s loaded at %#16.16x duplicate entry (probably commpage)" % (image.path, image.text_addr_lo) + else: + err = image.add_target_module (target) + if err: + print err + else: + image_paths.append(image.path) + else: + print 'error: can\'t find image for identifier "%s"' % ident + + for line in crash_log.info_lines: + print line + + # Reconstruct inlined frames for all threads for anything that has debug info + for thread in crash_log.threads: + if options.crashed_only and thread.did_crash() == False: + continue + # start a new frame list that we will fixup for each thread + new_thread_frames = list() + # Iterate through all concrete frames for a thread and resolve + # any parent frames of inlined functions + for frame_idx, frame in enumerate(thread.frames): + # Resolve the frame's pc into a section + offset address 'pc_addr' + pc_addr = target.ResolveLoadAddress (frame.pc) + # Check to see if we were able to resolve the address + if pc_addr: + # We were able to resolve the frame's PC into a section offset + # address. + + # Resolve the frame's PC value into a symbol context. A symbol + # context can resolve a module, compile unit, function, block, + # line table entry and/or symbol. If the frame has a block, then + # we can look for inlined frames, which are represented by blocks + # that have inlined information in them + frame.sym_ctx = target.ResolveSymbolContextForAddress (pc_addr, lldb.eSymbolContextEverything); + + # dump if the verbose option was specified + if options.verbose: + print "frame.pc = %#16.16x (file_addr = %#16.16x)" % (frame.pc, pc_addr.GetFileAddress()) + print "frame.pc_addr = ", pc_addr + print "frame.sym_ctx = " + print frame.sym_ctx + print + + # Append the frame we already had from the crash log to the new + # frames list + new_thread_frames.append(frame) + + new_frame = CrashLog.Frame (frame.index, -1, None) + + # Try and use the current frame's symbol context to calculate a + # parent frame for an inlined function. If the curent frame is + # inlined, it will return a valid symbol context for the parent + # frame of the current inlined function + parent_pc_addr = lldb.SBAddress() + new_frame.sym_ctx = frame.sym_ctx.GetParentOfInlinedScope (pc_addr, parent_pc_addr) + + # See if we were able to reconstruct anything? + while new_frame.sym_ctx: + # We have a parent frame of an inlined frame, create a new frame + # Convert the section + offset 'parent_pc_addr' to a load address + new_frame.pc = parent_pc_addr.GetLoadAddress(target) + # push the new frame onto the new frame stack + new_thread_frames.append (new_frame) + # dump if the verbose option was specified + if options.verbose: + print "new_frame.pc = %#16.16x (%s)" % (new_frame.pc, parent_pc_addr) + print "new_frame.sym_ctx = " + print new_frame.sym_ctx + print + # Create another new frame in case we have multiple inlined frames + prev_new_frame = new_frame + new_frame = CrashLog.Frame (frame.index, -1, None) + # Swap the addresses so we can try another inlined lookup + pc_addr = parent_pc_addr; + new_frame.sym_ctx = prev_new_frame.sym_ctx.GetParentOfInlinedScope (pc_addr, parent_pc_addr) + # Replace our thread frames with our new list that includes parent + # frames for inlined functions + thread.frames = new_thread_frames + # Now iterate through all threads and display our richer stack backtraces + for thread in crash_log.threads: + this_thread_crashed = thread.did_crash() + if options.crashed_only and this_thread_crashed == False: + continue + print "%s" % thread + prev_frame_index = -1 + for frame_idx, frame in enumerate(thread.frames): + details = ' %s' % frame.details + module = frame.sym_ctx.GetModule() + instructions = None + if module: + module_basename = module.GetFileSpec().GetFilename(); + function_start_load_addr = -1 + function_name = None + function = frame.sym_ctx.GetFunction() + block = frame.sym_ctx.GetBlock() + line_entry = frame.sym_ctx.GetLineEntry() + symbol = frame.sym_ctx.GetSymbol() + inlined_block = block.GetContainingInlinedBlock(); + if inlined_block: + function_name = inlined_block.GetInlinedName(); + block_range_idx = inlined_block.GetRangeIndexForBlockAddress (target.ResolveLoadAddress (frame.pc)) + if block_range_idx < lldb.UINT32_MAX: + block_range_start_addr = inlined_block.GetRangeStartAddress (block_range_idx) + function_start_load_addr = block_range_start_addr.GetLoadAddress (target) + else: + function_start_load_addr = frame.pc + if this_thread_crashed and frame_idx == 0: + instructions = function.GetInstructions(target) + elif function: + function_name = function.GetName() + function_start_load_addr = function.GetStartAddress().GetLoadAddress (target) + if this_thread_crashed and frame_idx == 0: + instructions = function.GetInstructions(target) + elif symbol: + function_name = symbol.GetName() + function_start_load_addr = symbol.GetStartAddress().GetLoadAddress (target) + if this_thread_crashed and frame_idx == 0: + instructions = symbol.GetInstructions(target) + + if function_name: + # Print the function or symbol name and annotate if it was inlined + inline_suffix = '' + if inlined_block: + inline_suffix = '[inlined] ' + else: + inline_suffix = ' ' + if options.show_images: + details = "%s%s`%s" % (inline_suffix, module_basename, function_name) + else: + details = "%s" % (function_name) + # Dump the offset from the current function or symbol if it is non zero + function_offset = frame.pc - function_start_load_addr + if function_offset > 0: + details += " + %u" % (function_offset) + elif function_offset < 0: + defaults += " %i (invalid negative offset, file a bug) " % function_offset + # Print out any line information if any is available + if line_entry.GetFileSpec(): + details += ' at %s' % line_entry.GetFileSpec().GetFilename() + details += ':%u' % line_entry.GetLine () + column = line_entry.GetColumn() + if column > 0: + details += ':%u' % column + + + # Only print out the concrete frame index if it changes. + # if prev_frame_index != frame.index: + # print "[%2u] %#16.16x %s" % (frame.index, frame.pc, details) + # else: + # print " %#16.16x %s" % (frame.pc, details) + print "[%2u] %#16.16x %s" % (frame.index, frame.pc, details) + prev_frame_index = frame.index + if instructions: + print + disassemble_instructions (target, instructions, frame.pc, 4, 4) + print + + print + + if options.dump_image_list: + print "Binary Images:" + for image in crash_log.images: + print image + + +if __name__ == '__main__': + SymbolicateCrashLog (args) + Propchange: lldb/trunk/examples/python/crashlog.py ------------------------------------------------------------------------------ svn:executable = * From gclayton at apple.com Thu Jan 19 21:32:35 2012 From: gclayton at apple.com (Greg Clayton) Date: Fri, 20 Jan 2012 03:32:35 -0000 Subject: [Lldb-commits] [lldb] r148529 - in /lldb/trunk/examples/python: crashlog.lldb crashlog.py Message-ID: <20120120033235.63E732A6C12C@llvm.org> Author: gclayton Date: Thu Jan 19 21:32:35 2012 New Revision: 148529 URL: http://llvm.org/viewvc/llvm-project?rev=148529&view=rev Log: Improved the regular expressions to handle "+" characters being at the front of the identifier name in the binary images section. Improved the regular expression for the frames. Added a new file "crashlog.lldb" which can be sourced with "command source" that will import the module and set itself up to be used as a command. Added: lldb/trunk/examples/python/crashlog.lldb Modified: lldb/trunk/examples/python/crashlog.py Added: lldb/trunk/examples/python/crashlog.lldb URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/python/crashlog.lldb?rev=148529&view=auto ============================================================================== --- lldb/trunk/examples/python/crashlog.lldb (added) +++ lldb/trunk/examples/python/crashlog.lldb Thu Jan 19 21:32:35 2012 @@ -0,0 +1,5 @@ +# source this file while being chdir'ed in the directory that contains +# this file at the LLDB command line with: +# (lldb) command source crashlog.lldb +script import crashlog +command script add -f crashlog.Symbolicate crashlog Modified: lldb/trunk/examples/python/crashlog.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/python/crashlog.py?rev=148529&r1=148528&r2=148529&view=diff ============================================================================== --- lldb/trunk/examples/python/crashlog.py (original) +++ lldb/trunk/examples/python/crashlog.py Thu Jan 19 21:32:35 2012 @@ -28,9 +28,9 @@ """Class that does parses darwin crash logs""" thread_state_regex = re.compile('^Thread ([0-9]+) crashed with') thread_regex = re.compile('^Thread ([0-9]+)([^:]*):(.*)') - frame_regex = re.compile('^([0-9]+) +([^ ]+) +\t(0x[0-9a-fA-F]+) +(.*)') - image_regex_uuid = re.compile('(0x[0-9a-fA-F]+)[- ]+(0x[0-9a-fA-F]+) +([^ ]+) +([^<]+)<([-0-9a-fA-F]+)> (.*)'); - image_regex_no_uuid = re.compile('(0x[0-9a-fA-F]+)[- ]+(0x[0-9a-fA-F]+) +([^ ]+) +([^/]+)/(.*)'); + frame_regex = re.compile('^([0-9]+) +([^ ]+) *\t(0x[0-9a-fA-F]+) +(.*)') + image_regex_uuid = re.compile('(0x[0-9a-fA-F]+)[- ]+(0x[0-9a-fA-F]+) +[+]?([^ ]+) +([^<]+)<([-0-9a-fA-F]+)> (.*)'); + image_regex_no_uuid = re.compile('(0x[0-9a-fA-F]+)[- ]+(0x[0-9a-fA-F]+) +[+]?([^ ]+) +([^/]+)/(.*)'); empty_line_regex = re.compile('^$') class Thread: @@ -80,6 +80,8 @@ class Image: """Class that represents a binary images in a darwin crash log""" + dsymForUUIDBinary = os.path.expanduser('~rc/bin/dsymForUUID') + def __init__(self, text_addr_lo, text_addr_hi, ident, version, uuid, path): self.text_addr_lo = text_addr_lo self.text_addr_hi = text_addr_hi @@ -103,32 +105,35 @@ return None def fetch_symboled_executable_and_dsym(self): - dsym_for_uuid_command = ('~rc/bin/dsymForUUID %s' % self.uuid) - print 'Fetching %s %s...' % (self.uuid, self.path), - s = commands.getoutput(dsym_for_uuid_command) - if s: - plist_root = plistlib.readPlistFromString (s) - if plist_root: - # pp = pprint.PrettyPrinter(indent=4) - # pp.pprint(plist_root) - self.plist = plist_root[self.uuid] - if self.plist: - if 'DBGError' in self.plist: - err = self.plist['DBGError'] - if isinstance(err, unicode): - err = err.encode('utf-8') - print 'error: %s' % err - elif 'DBGSymbolRichExecutable' in self.plist: - self.path = os.path.expanduser (self.plist['DBGSymbolRichExecutable']) - #print 'success: symboled exe is "%s"' % self.path - print 'ok' - return 1 - print 'error: failed to get plist dictionary entry for UUID %s: %s' % (uuid, plist_root) + if os.path.exists(self.dsymForUUIDBinary): + dsym_for_uuid_command = '%s %s' % (self.dsymForUUIDBinary, self.uuid) + print 'Fetching %s %s...' % (self.uuid, self.path), + s = commands.getoutput(dsym_for_uuid_command) + if s: + plist_root = plistlib.readPlistFromString (s) + if plist_root: + # pp = pprint.PrettyPrinter(indent=4) + # pp.pprint(plist_root) + self.plist = plist_root[self.uuid] + if self.plist: + if 'DBGError' in self.plist: + err = self.plist['DBGError'] + if isinstance(err, unicode): + err = err.encode('utf-8') + print 'error: %s' % err + elif 'DBGSymbolRichExecutable' in self.plist: + self.path = os.path.expanduser (self.plist['DBGSymbolRichExecutable']) + #print 'success: symboled exe is "%s"' % self.path + print 'ok' + return 1 + print 'error: failed to get plist dictionary entry for UUID %s: %s' % (uuid, plist_root) + else: + print 'error: failed to extract plist from "%s"' % (s) else: - print 'error: failed to extract plist from "%s"' % (s) + print 'error: %s failed...' % (dsym_for_uuid_command) + return 0 else: - print 'error: %s failed...' % (dsym_for_uuid_command) - return 0 + return 1 # no dsym locating script, just use the paths in the crash log def load_module(self): if self.module: @@ -136,7 +141,7 @@ if text_section: error = self.target.SetSectionLoadAddress (text_section, self.text_addr_lo) if error.Success(): - print 'Success: loaded %s.__TEXT = 0x%x' % (self.basename(), self.text_addr_lo) + #print 'Success: loaded %s.__TEXT = 0x%x' % (self.basename(), self.text_addr_lo) return None else: return 'error: %s' % error.GetCString() @@ -286,7 +291,7 @@ self.idents.append(ident) thread.frames.append (CrashLog.Frame(int(frame_match.group(1)), int(frame_match.group(3), 0), frame_match.group(4))) else: - print "error: frame regex failed" + print 'error: frame regex failed for line: "%s"' % line elif parse_mode == PARSE_MODE_IMAGES: image_match = self.image_regex_uuid.search (line) if image_match: @@ -436,7 +441,8 @@ options.dependents = False for crash_log_file in options.crash_log_files: crash_log = CrashLog(crash_log_file) - crash_log.dump() + if options.verbose: + crash_log.dump() if crash_log.images: err = crash_log.images[0].create_target (debugger) if err: From gclayton at apple.com Fri Jan 20 00:12:48 2012 From: gclayton at apple.com (Greg Clayton) Date: Fri, 20 Jan 2012 06:12:48 -0000 Subject: [Lldb-commits] [lldb] r148534 - /lldb/trunk/examples/python/crashlog.py Message-ID: <20120120061248.3F3E32A6C12C@llvm.org> Author: gclayton Date: Fri Jan 20 00:12:47 2012 New Revision: 148534 URL: http://llvm.org/viewvc/llvm-project?rev=148534&view=rev Log: More fixed to verify if a file in the crash log is installed in the current system and also deal with dsymForUUID being available on the network, locally, and not at all. Modified: lldb/trunk/examples/python/crashlog.py Modified: lldb/trunk/examples/python/crashlog.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/python/crashlog.py?rev=148534&r1=148533&r2=148534&view=diff ============================================================================== --- lldb/trunk/examples/python/crashlog.py (original) +++ lldb/trunk/examples/python/crashlog.py Fri Jan 20 00:12:47 2012 @@ -17,6 +17,8 @@ import re import sys import time +import uuid + PARSE_MODE_NORMAL = 0 PARSE_MODE_THREAD = 1 @@ -81,59 +83,93 @@ class Image: """Class that represents a binary images in a darwin crash log""" dsymForUUIDBinary = os.path.expanduser('~rc/bin/dsymForUUID') + if not os.path.exists(dsymForUUIDBinary): + dsymForUUIDBinary = commands.getoutput('which dsymForUUID') + + dwarfdump_uuid_regex = re.compile('UUID: ([-0-9a-fA-F]+) \(([^\(]+)\) .*') def __init__(self, text_addr_lo, text_addr_hi, ident, version, uuid, path): self.text_addr_lo = text_addr_lo self.text_addr_hi = text_addr_hi self.ident = ident self.version = version + self.arch = None self.uuid = uuid self.path = path + self.resolved_path = None + self.dsym = None self.target = None self.module = None - self.plist = None def dump(self, prefix): print "%s%s" % (prefix, self) def __str__(self): - return "%#16.16x %s %s" % (self.text_addr_lo, self.uuid, self.path) + return "%#16.16x %s %s" % (self.text_addr_lo, self.uuid, self.get_resolved_path()) - def basename(self): - if self.path: - return os.path.basename(self.path) + def get_resolved_path(self): + if self.resolved_path: + return self.resolved_path + elif self.path: + return self.path + return None + + def get_resolved_path_basename(self): + path = self.get_resolved_path() + if path: + return os.path.basename(path) + return None + + def dsym_basename(self): + if self.dsym: + return os.path.basename(self.dsym) return None def fetch_symboled_executable_and_dsym(self): + if self.resolved_path: + # Don't load a module twice... + return 0 + print 'Locating %s %s...' % (self.uuid, self.path), if os.path.exists(self.dsymForUUIDBinary): dsym_for_uuid_command = '%s %s' % (self.dsymForUUIDBinary, self.uuid) - print 'Fetching %s %s...' % (self.uuid, self.path), s = commands.getoutput(dsym_for_uuid_command) if s: plist_root = plistlib.readPlistFromString (s) if plist_root: # pp = pprint.PrettyPrinter(indent=4) # pp.pprint(plist_root) - self.plist = plist_root[self.uuid] - if self.plist: - if 'DBGError' in self.plist: - err = self.plist['DBGError'] - if isinstance(err, unicode): - err = err.encode('utf-8') - print 'error: %s' % err - elif 'DBGSymbolRichExecutable' in self.plist: - self.path = os.path.expanduser (self.plist['DBGSymbolRichExecutable']) - #print 'success: symboled exe is "%s"' % self.path - print 'ok' - return 1 - print 'error: failed to get plist dictionary entry for UUID %s: %s' % (uuid, plist_root) - else: - print 'error: failed to extract plist from "%s"' % (s) - else: - print 'error: %s failed...' % (dsym_for_uuid_command) - return 0 + plist = plist_root[self.uuid] + if plist: + if 'DBGArchitecture' in plist: + self.arch = plist['DBGArchitecture'] + if 'DBGDSYMPath' in plist: + self.dsym = os.path.realpath(plist['DBGDSYMPath']) + if 'DBGSymbolRichExecutable' in plist: + self.resolved_path = os.path.expanduser (plist['DBGSymbolRichExecutable']) + if not self.resolved_path and os.path.exists(self.path): + dwarfdump_cmd_output = commands.getoutput('dwarfdump --uuid "%s"' % self.path) + self_uuid = uuid.UUID(self.uuid) + for line in dwarfdump_cmd_output.splitlines(): + match = self.dwarfdump_uuid_regex.search (line) + if match: + dwarf_uuid_str = match.group(1) + dwarf_uuid = uuid.UUID(dwarf_uuid_str) + if self_uuid == dwarf_uuid: + self.resolved_path = self.path + self.arch = match.group(2) + break; + if not self.resolved_path: + print "error: file %s '%s' doesn't match the UUID in the installed file" % (self.uuid, self.path) + return 0 + if (self.resolved_path and os.path.exists(self.resolved_path)) or (self.path and os.path.exists(self.path)): + print 'ok' + if self.path != self.resolved_path: + print ' exe = "%s"' % self.resolved_path + if self.dsym: + print ' dsym = "%s"' % self.dsym + return 1 else: - return 1 # no dsym locating script, just use the paths in the crash log + return 0 def load_module(self): if self.module: @@ -146,18 +182,17 @@ else: return 'error: %s' % error.GetCString() else: - return 'error: unable to find "__TEXT" section in "%s"' % self.path + return 'error: unable to find "__TEXT" section in "%s"' % self.get_resolved_path() else: return 'error: invalid module' def create_target(self, debugger): if self.fetch_symboled_executable_and_dsym (): - path_spec = lldb.SBFileSpec (self.path) - arch = self.plist['DBGArchitecture'] - #print 'debugger.CreateTarget (path="%s", arch="%s") uuid=%s' % (self.path, arch, self.uuid) + resolved_path = self.get_resolved_path(); + path_spec = lldb.SBFileSpec (resolved_path) #result.PutCString ('plist[%s] = %s' % (uuid, self.plist)) error = lldb.SBError() - self.target = debugger.CreateTarget (self.path, arch, None, False, error); + self.target = debugger.CreateTarget (resolved_path, self.arch, None, False, error); if self.target: self.module = self.target.FindModule (path_spec) if self.module: @@ -167,19 +202,18 @@ else: return None else: - return 'error: unable to get module for (%s) "%s"' % (arch, self.path) + return 'error: unable to get module for (%s) "%s"' % (self.arch, resolved_path) else: - return 'error: unable to create target for (%s) "%s"' % (arch, self.path) + return 'error: unable to create target for (%s) "%s"' % (self.arch, resolved_path) def add_target_module(self, target): if target: self.target = target if self.fetch_symboled_executable_and_dsym (): - path_spec = lldb.SBFileSpec (self.path) - arch = self.plist['DBGArchitecture'] - #result.PutCString ('plist[%s] = %s' % (uuid, self.plist)) - #print 'target.AddModule (path="%s", arch="%s", uuid=%s)' % (self.path, arch, self.uuid) - self.module = target.AddModule (self.path, arch, self.uuid) + resolved_path = self.get_resolved_path(); + path_spec = lldb.SBFileSpec (resolved_path) + #print 'target.AddModule (path="%s", arch="%s", uuid=%s)' % (resolved_path, self.arch, self.uuid) + self.module = target.AddModule (resolved_path, self.arch, self.uuid) if self.module: err = self.load_module() if err: @@ -187,7 +221,7 @@ else: return None else: - return 'error: unable to get module for (%s) "%s"' % (arch, self.path) + return 'error: unable to get module for (%s) "%s"' % (self.arch, resolved_path) else: return 'error: invalid target' From gclayton at apple.com Fri Jan 20 13:25:32 2012 From: gclayton at apple.com (Greg Clayton) Date: Fri, 20 Jan 2012 19:25:32 -0000 Subject: [Lldb-commits] [lldb] r148561 - /lldb/trunk/examples/python/crashlog.py Message-ID: <20120120192532.41A122A6C12C@llvm.org> Author: gclayton Date: Fri Jan 20 13:25:32 2012 New Revision: 148561 URL: http://llvm.org/viewvc/llvm-project?rev=148561&view=rev Log: Make the script work again from the command line as long as the PYTHONPATH environment variable it set to include a path to lldb.py. Also fixed the case where the executable can't be located and doesn't match what is installed on the current system. It will still symbolicate the other frames, and will just show what was originally in the crash log file. Also removed the --crash-log option so the arguments to the "crashlog" command are one or more paths to crash logs. Fixed the script to "auto-install" itself when loaded from the embedded script interpreter. Now you only need to import the module and the command is ready for use. Modified: lldb/trunk/examples/python/crashlog.py Modified: lldb/trunk/examples/python/crashlog.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/python/crashlog.py?rev=148561&r1=148560&r2=148561&view=diff ============================================================================== --- lldb/trunk/examples/python/crashlog.py (original) +++ lldb/trunk/examples/python/crashlog.py Fri Jan 20 13:25:32 2012 @@ -98,7 +98,6 @@ self.path = path self.resolved_path = None self.dsym = None - self.target = None self.module = None def dump(self, prefix): @@ -172,10 +171,12 @@ return 0 def load_module(self): + if not lldb.target: + return 'error: no target' if self.module: text_section = self.module.FindSection ("__TEXT") if text_section: - error = self.target.SetSectionLoadAddress (text_section, self.text_addr_lo) + error = lldb.target.SetSectionLoadAddress (text_section, self.text_addr_lo) if error.Success(): #print 'Success: loaded %s.__TEXT = 0x%x' % (self.basename(), self.text_addr_lo) return None @@ -186,15 +187,15 @@ else: return 'error: invalid module' - def create_target(self, debugger): + def create_target(self): if self.fetch_symboled_executable_and_dsym (): resolved_path = self.get_resolved_path(); path_spec = lldb.SBFileSpec (resolved_path) #result.PutCString ('plist[%s] = %s' % (uuid, self.plist)) error = lldb.SBError() - self.target = debugger.CreateTarget (resolved_path, self.arch, None, False, error); - if self.target: - self.module = self.target.FindModule (path_spec) + lldb.target = lldb.debugger.CreateTarget (resolved_path, self.arch, None, False, error); + if lldb.target: + self.module = lldb.target.FindModule (path_spec) if self.module: err = self.load_module() if err: @@ -205,15 +206,16 @@ return 'error: unable to get module for (%s) "%s"' % (self.arch, resolved_path) else: return 'error: unable to create target for (%s) "%s"' % (self.arch, resolved_path) + else: + return 'error: unable to locate main executable (%s) "%s"' % (self.arch, self.path) - def add_target_module(self, target): - if target: - self.target = target + def add_target_module(self): + if lldb.target: if self.fetch_symboled_executable_and_dsym (): resolved_path = self.get_resolved_path(); path_spec = lldb.SBFileSpec (resolved_path) #print 'target.AddModule (path="%s", arch="%s", uuid=%s)' % (resolved_path, self.arch, self.uuid) - self.module = target.AddModule (resolved_path, self.arch, self.uuid) + self.module = lldb.target.AddModule (resolved_path, self.arch, self.uuid) if self.module: err = self.load_module() if err: @@ -374,18 +376,39 @@ return image return None -def disassemble_instructions (target, instructions, pc, insts_before_pc, insts_after_pc): + def create_target(self): + if not self.images: + return 'error: no images in crash log' + exe_path = self.images[0].get_resolved_path() + err = self.images[0].create_target () + if not err: + return None # success + # We weren't able to open the main executable as, but we can still symbolicate + if self.idents: + for ident in idents: + image = self.find_image_with_identifier (ident) + if image: + err = image.create_target () + if not err: + return None # success + for image in self.images: + err = image.create_target () + if not err: + return None # success + return 'error: unable to locate any executables from the crash log' + +def disassemble_instructions (instructions, pc, insts_before_pc, insts_after_pc): lines = list() pc_index = -1 comment_column = 50 for inst_idx, inst in enumerate(instructions): - inst_pc = inst.GetAddress().GetLoadAddress(target); + inst_pc = inst.GetAddress().GetLoadAddress(lldb.target); if pc == inst_pc: pc_index = inst_idx - mnemonic = inst.GetMnemonic (target) - operands = inst.GetOperands (target) - comment = inst.GetComment (target) - #data = inst.GetData (target) + mnemonic = inst.GetMnemonic (lldb.target) + operands = inst.GetOperands (lldb.target) + comment = inst.GetComment (lldb.target) + #data = inst.GetData (lldb.target) lines.append ("%#16.16x: %8s %s" % (inst_pc, mnemonic, operands)) if comment: line_len = len(lines[-1]) @@ -439,51 +462,33 @@ SymbolicateCrashLog (command.split()) def SymbolicateCrashLog(command_args): - - parser = optparse.OptionParser(description='A script that parses skinny and universal mach-o files.') - parser.add_option('--arch', type='string', metavar='arch', dest='triple', help='specify one architecture or target triple') + print 'command_args = %s' % command_args + parser = optparse.OptionParser(description='Parses darwin crash log files and symbolicates them.') parser.add_option('--platform', type='string', metavar='platform', dest='platform', help='specify one platform by name') parser.add_option('--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) - parser.add_option('--interactive', action='store_true', dest='interactive', help='enable interactive mode', default=False) parser.add_option('--no-images', action='store_false', dest='show_images', help='don\'t show images in stack frames', default=True) - parser.add_option('--no-dependents', action='store_false', dest='dependents', help='skip loading dependent modules', default=True) - parser.add_option('--sections', action='store_true', dest='dump_sections', help='show module sections', default=False) - parser.add_option('--symbols', action='store_true', dest='dump_symbols', help='show module symbols', default=False) parser.add_option('--image-list', action='store_true', dest='dump_image_list', help='show image list', default=False) parser.add_option('--debug-delay', type='int', dest='debug_delay', metavar='NSEC', help='pause for NSEC seconds for debugger', default=0) - parser.add_option('--section-depth', type='int', dest='section_depth', help='set the section depth to use when showing sections', default=0) - parser.add_option('--section-data', type='string', action='append', dest='sect_data_names', help='specify sections by name to display data for') - parser.add_option('--address', type='int', action='append', dest='addresses', help='specify addresses to lookup') - parser.add_option('--crash-log', type='string', action='append', dest='crash_log_files', help='specify crash log files to symbolicate') - parser.add_option('--crashed-only', action='store_true', dest='crashed_only', help='only show the crashed thread', default=False) + parser.add_option('--crashed-only', action='store_true', dest='crashed_only', help='only symbolicate the crashed thread', default=False) loaded_addresses = False (options, args) = parser.parse_args(command_args) if options.verbose: print 'options', options - if options.debug_delay > 0: print "Waiting %u seconds for debugger to attach..." % options.debug_delay time.sleep(options.debug_delay) - - # Create a new debugger instance - debugger = lldb.SBDebugger.Create() - error = lldb.SBError() - - - if options.crash_log_files: - options.dependents = False - for crash_log_file in options.crash_log_files: + if args: + for crash_log_file in args: crash_log = CrashLog(crash_log_file) if options.verbose: crash_log.dump() if crash_log.images: - err = crash_log.images[0].create_target (debugger) + err = crash_log.create_target () if err: print err else: - target = crash_log.images[0].target - exe_module = target.GetModuleAtIndex(0) + exe_module = lldb.target.GetModuleAtIndex(0) image_paths = list() # for i in range (1, len(crash_log.images)): # image = crash_log.images[i] @@ -493,7 +498,7 @@ if image.path in image_paths: print "warning: skipping %s loaded at %#16.16x duplicate entry (probably commpage)" % (image.path, image.text_addr_lo) else: - err = image.add_target_module (target) + err = image.add_target_module () if err: print err else: @@ -514,7 +519,7 @@ # any parent frames of inlined functions for frame_idx, frame in enumerate(thread.frames): # Resolve the frame's pc into a section + offset address 'pc_addr' - pc_addr = target.ResolveLoadAddress (frame.pc) + pc_addr = lldb.target.ResolveLoadAddress (frame.pc) # Check to see if we were able to resolve the address if pc_addr: # We were able to resolve the frame's PC into a section offset @@ -525,7 +530,7 @@ # line table entry and/or symbol. If the frame has a block, then # we can look for inlined frames, which are represented by blocks # that have inlined information in them - frame.sym_ctx = target.ResolveSymbolContextForAddress (pc_addr, lldb.eSymbolContextEverything); + frame.sym_ctx = lldb.target.ResolveSymbolContextForAddress (pc_addr, lldb.eSymbolContextEverything); # dump if the verbose option was specified if options.verbose: @@ -552,7 +557,7 @@ while new_frame.sym_ctx: # We have a parent frame of an inlined frame, create a new frame # Convert the section + offset 'parent_pc_addr' to a load address - new_frame.pc = parent_pc_addr.GetLoadAddress(target) + new_frame.pc = parent_pc_addr.GetLoadAddress(lldb.target) # push the new frame onto the new frame stack new_thread_frames.append (new_frame) # dump if the verbose option was specified @@ -592,24 +597,24 @@ inlined_block = block.GetContainingInlinedBlock(); if inlined_block: function_name = inlined_block.GetInlinedName(); - block_range_idx = inlined_block.GetRangeIndexForBlockAddress (target.ResolveLoadAddress (frame.pc)) + block_range_idx = inlined_block.GetRangeIndexForBlockAddress (lldb.target.ResolveLoadAddress (frame.pc)) if block_range_idx < lldb.UINT32_MAX: block_range_start_addr = inlined_block.GetRangeStartAddress (block_range_idx) - function_start_load_addr = block_range_start_addr.GetLoadAddress (target) + function_start_load_addr = block_range_start_addr.GetLoadAddress (lldb.target) else: function_start_load_addr = frame.pc if this_thread_crashed and frame_idx == 0: - instructions = function.GetInstructions(target) + instructions = function.GetInstructions(lldb.target) elif function: function_name = function.GetName() - function_start_load_addr = function.GetStartAddress().GetLoadAddress (target) + function_start_load_addr = function.GetStartAddress().GetLoadAddress (lldb.target) if this_thread_crashed and frame_idx == 0: - instructions = function.GetInstructions(target) + instructions = function.GetInstructions(lldb.target) elif symbol: function_name = symbol.GetName() - function_start_load_addr = symbol.GetStartAddress().GetLoadAddress (target) + function_start_load_addr = symbol.GetStartAddress().GetLoadAddress (lldb.target) if this_thread_crashed and frame_idx == 0: - instructions = symbol.GetInstructions(target) + instructions = symbol.GetInstructions(lldb.target) if function_name: # Print the function or symbol name and annotate if it was inlined @@ -646,7 +651,7 @@ prev_frame_index = frame.index if instructions: print - disassemble_instructions (target, instructions, frame.pc, 4, 4) + disassemble_instructions (instructions, frame.pc, 4, 4) print print @@ -658,5 +663,10 @@ if __name__ == '__main__': - SymbolicateCrashLog (args) + # Create a new debugger instance + lldb.debugger = lldb.SBDebugger.Create() + SymbolicateCrashLog (sys.argv) +elif lldb.debugger: + lldb.debugger.HandleCommand('command script add -f crashlog.Symbolicate crashlog') + print '"crashlog" command installed, type "crashlog --help" for detailed help' From scallanan at apple.com Fri Jan 20 13:27:48 2012 From: scallanan at apple.com (Sean Callanan) Date: Fri, 20 Jan 2012 19:27:48 -0000 Subject: [Lldb-commits] [lldb] r148562 - /lldb/trunk/examples/python/crashlog.py Message-ID: <20120120192748.BE02B2A6C12C@llvm.org> Author: spyffe Date: Fri Jan 20 13:27:48 2012 New Revision: 148562 URL: http://llvm.org/viewvc/llvm-project?rev=148562&view=rev Log: Fixed a global reference that should have been a reference to a class variable. Modified: lldb/trunk/examples/python/crashlog.py Modified: lldb/trunk/examples/python/crashlog.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/python/crashlog.py?rev=148562&r1=148561&r2=148562&view=diff ============================================================================== --- lldb/trunk/examples/python/crashlog.py (original) +++ lldb/trunk/examples/python/crashlog.py Fri Jan 20 13:27:48 2012 @@ -385,7 +385,7 @@ return None # success # We weren't able to open the main executable as, but we can still symbolicate if self.idents: - for ident in idents: + for ident in self.idents: image = self.find_image_with_identifier (ident) if image: err = image.create_target () From johnny.chen at apple.com Fri Jan 20 17:02:51 2012 From: johnny.chen at apple.com (Johnny Chen) Date: Fri, 20 Jan 2012 23:02:51 -0000 Subject: [Lldb-commits] [lldb] r148596 - in /lldb/trunk: source/Commands/CommandObjectSettings.cpp source/Core/UserSettingsController.cpp test/functionalities/completion/ test/functionalities/completion/TestCompletion.py test/lldbtest.py Message-ID: <20120120230251.EDA532A6C12C@llvm.org> Author: johnny Date: Fri Jan 20 17:02:51 2012 New Revision: 148596 URL: http://llvm.org/viewvc/llvm-project?rev=148596&view=rev Log: o CommandObjectSettingsSet.cpp: Fix a bug where "settings set -r th" wouldn't complete. o UserSettingsController.cpp: Fix a bug where "settings set target.process." wouldn't complete. o test/functionalities/completion: Add various completion test cases related to 'settings set' command. Added: lldb/trunk/test/functionalities/completion/ lldb/trunk/test/functionalities/completion/TestCompletion.py Modified: lldb/trunk/source/Commands/CommandObjectSettings.cpp lldb/trunk/source/Core/UserSettingsController.cpp lldb/trunk/test/lldbtest.py Modified: lldb/trunk/source/Commands/CommandObjectSettings.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectSettings.cpp?rev=148596&r1=148595&r2=148596&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectSettings.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectSettings.cpp Fri Jan 20 17:02:51 2012 @@ -188,7 +188,11 @@ completion_str.erase (cursor_char_position); // Attempting to complete variable name - if (cursor_index == 1) + llvm::StringRef prev_str(cursor_index == 2 ? input.GetArgumentAtIndex(1) : ""); + if (cursor_index == 1 || + (cursor_index == 2 && prev_str.startswith("-")) // "settings set -r th", followed by Tab. + ) + { CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter, CommandCompletions::eSettingsNameCompletion, completion_str.c_str(), @@ -197,6 +201,10 @@ NULL, word_complete, matches); + // If there is only 1 match which fulfills the completion request, do an early return. + if (matches.GetSize() == 1 && completion_str.compare(matches.GetStringAtIndex(0)) != 0) + return 1; + } // Attempting to complete value if ((cursor_index == 2) // Partly into the variable's value Modified: lldb/trunk/source/Core/UserSettingsController.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/UserSettingsController.cpp?rev=148596&r1=148595&r2=148596&view=diff ============================================================================== --- lldb/trunk/source/Core/UserSettingsController.cpp (original) +++ lldb/trunk/source/Core/UserSettingsController.cpp Fri Jan 20 17:02:51 2012 @@ -1714,19 +1714,21 @@ } + // The variable my_usc_sp keeps track of the user settings controller as + // we descend through the tree hierarchy. + UserSettingsControllerSP my_usc_sp = usc_sp; for (int i = 0; i < num_extra_levels; ++i) { ConstString child_level (partial_setting_name_pieces.GetArgumentAtIndex (0)); bool found = false; - int num_children = usc_sp->GetNumChildren(); - UserSettingsControllerSP child_usc_sp = usc_sp; + int num_children = my_usc_sp->GetNumChildren(); for (int j = 0; j < num_children && !found; ++j) { - if (child_usc_sp->GetChildAtIndex (j)->GetLevelName() == child_level) + if (my_usc_sp->GetChildAtIndex (j)->GetLevelName() == child_level) { found = true; - child_usc_sp = child_usc_sp->GetChildAtIndex (j); + my_usc_sp = my_usc_sp->GetChildAtIndex (j); partial_setting_name_pieces.Shift(); } } @@ -1750,15 +1752,15 @@ // 'next_name' is an instance name. The last name piece must be a non-empty partial match against an // instance_name, assuming 'next_name' is valid. - if (usc_sp->IsLiveInstance (next_name)) + if (my_usc_sp->IsLiveInstance (next_name)) { std::string complete_prefix; - usc_sp->BuildParentPrefix (complete_prefix); + my_usc_sp->BuildParentPrefix (complete_prefix); - num_matches = usc_sp->InstanceVariableMatches(partial_setting_name_pieces.GetArgumentAtIndex(0), - complete_prefix, - next_name.c_str(), - matches); + num_matches = my_usc_sp->InstanceVariableMatches(partial_setting_name_pieces.GetArgumentAtIndex(0), + complete_prefix, + next_name.c_str(), + matches); word_complete = true; if (num_matches > 1) word_complete = false; @@ -1772,14 +1774,14 @@ { // 'next_name' must be a child name. Find the correct child and pass the remaining piece to be resolved. bool found = false; - int num_children = usc_sp->GetNumChildren(); + int num_children = my_usc_sp->GetNumChildren(); ConstString child_level (next_name.c_str()); for (int i = 0; i < num_children; ++i) { - if (usc_sp->GetChildAtIndex (i)->GetLevelName() == child_level) + if (my_usc_sp->GetChildAtIndex (i)->GetLevelName() == child_level) { found = true; - return UserSettingsController::CompleteSettingsNames (usc_sp->GetChildAtIndex (i), + return UserSettingsController::CompleteSettingsNames (my_usc_sp->GetChildAtIndex (i), partial_setting_name_pieces, word_complete, matches); } Added: lldb/trunk/test/functionalities/completion/TestCompletion.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/completion/TestCompletion.py?rev=148596&view=auto ============================================================================== --- lldb/trunk/test/functionalities/completion/TestCompletion.py (added) +++ lldb/trunk/test/functionalities/completion/TestCompletion.py Fri Jan 20 17:02:51 2012 @@ -0,0 +1,116 @@ +""" +Test the lldb command line completion mechanism. +""" + +import os +import unittest2 +import lldb +import pexpect +from lldbtest import * + +class CommandLineCompletionTestCase(TestBase): + + mydir = os.path.join("functionalities", "completion") + + @classmethod + def classCleanup(cls): + """Cleanup the test byproducts.""" + system(["/bin/sh", "-c", "rm -f child_send.txt"]) + system(["/bin/sh", "-c", "rm -f child_read.txt"]) + + def test_settings_s(self): + """Test that 'settings s' completes to ['Available completions:', 'set', 'show'].""" + self.complete_from_to('settings s', ['Available completions:', 'set', 'show']) + + def test_settings_set_th(self): + """Test that 'settings set th' completes to 'settings set thread-format'.""" + self.complete_from_to('settings set th', 'settings set thread-format') + + def test_settings_s_dash(self): + """Test that 'settings set -' completes to ['Available completions:', '-n', '-r'].""" + self.complete_from_to('settings set -', ['Available completions:', '-n', '-r']) + + def test_settings_set_dash_r_th(self): + """Test that 'settings set -r th' completes to 'settings set -r thread-format'.""" + self.complete_from_to('settings set -r th', 'settings set -r thread-format') + + def test_settings_set_ta(self): + """Test that 'settings set ta' completes to 'settings set target.'.""" + self.complete_from_to('settings set ta', 'settings set target.') + + def test_settings_set_target_pr(self): + """Test that 'settings set target.pr' completes to ['Available completions:', + 'target.prefer-dynamic-value', 'target.process.'].""" + self.complete_from_to('settings set target.pr', + ['Available completions:', + 'target.prefer-dynamic-value', + 'target.process.']) + + def test_settings_set_target_process(self): + """Test that 'settings set target.process' completes to 'settings set target.process.'.""" + self.complete_from_to('settings set target.process', 'settings set target.process.') + + def test_settings_set_target_process_dot(self): + """Test that 'settings set target.process.' completes to 'settings set target.process.thread.'.""" + self.complete_from_to('settings set target.process.', 'settings set target.process.thread.') + + def test_settings_set_target_process_thread_dot(self): + """Test that 'settings set target.process.thread.' completes to ['Available completions:', + 'target.process.thread.step-avoid-regexp', 'target.process.thread.trace-thread'].""" + self.complete_from_to('settings set target.process.thread.', + ['Available completions:', + 'target.process.thread.step-avoid-regexp', + 'target.process.thread.trace-thread']) + + def complete_from_to(self, str_before, patterns): + """Test the completion mechanism completes str_before to pattern, where + patterns could be a pattern-string or a list of pattern-strings""" + prompt = "(lldb) " + add_prompt = "Enter your stop hook command(s). Type 'DONE' to end.\r\n> " + add_prompt1 = "\r\n> " + + # So that the child gets torn down after the test. + self.child = pexpect.spawn('%s %s' % (self.lldbHere, self.lldbOption)) + child = self.child + # Turn on logging for input/output to/from the child. + with open('child_send.txt', 'w') as f_send: + with open('child_read.txt', 'w') as f_read: + child.logfile_send = f_send + child.logfile_read = f_read + + # Test that str_before completes to str_after. + child.expect_exact(prompt) + child.setecho(True) + child.send("%s\t" % str_before) + #child.expect_exact("%s\t" % str_after) + child.sendline('') + child.expect_exact(prompt) + + with open('child_send.txt', 'r') as fs: + if self.TraceOn(): + print "\n\nContents of child_send.txt:" + print fs.read() + with open('child_read.txt', 'r') as fr: + from_child = fr.read() + if self.TraceOn(): + print "\n\nContents of child_read.txt:" + print from_child + + self.assertFalse(patterns is None) + if type(patterns) is not types.ListType: + patterns = [patterns] + + # If each pattern matches from_child, the completion mechanism works! + for p in patterns: + self.expect(from_child, msg=COMPLETIOND_MSG(str_before, p), exe=False, + patterns = [p]) + + child.logfile_send = None + child.logfile_read = None + + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() Modified: lldb/trunk/test/lldbtest.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lldbtest.py?rev=148596&r1=148595&r2=148596&view=diff ============================================================================== --- lldb/trunk/test/lldbtest.py (original) +++ lldb/trunk/test/lldbtest.py Fri Jan 20 17:02:51 2012 @@ -206,6 +206,10 @@ '''A generic "Command '%s' returns successfully" message generator.''' return "Command '%s' returns successfully" % str +def COMPLETIOND_MSG(str_before, str_after): + '''A generic message generator for the completion mechanism.''' + return "'%s' successfully completes to '%s'" % (str_before, str_after) + def EXP_MSG(str, exe): '''A generic "'%s' returns expected result" message generator if exe. Otherwise, it generates "'%s' matches expected result" message.''' From gclayton at apple.com Fri Jan 20 17:08:34 2012 From: gclayton at apple.com (Greg Clayton) Date: Fri, 20 Jan 2012 23:08:34 -0000 Subject: [Lldb-commits] [lldb] r148597 - /lldb/trunk/source/Target/Process.cpp Message-ID: <20120120230834.E09602A6C12C@llvm.org> Author: gclayton Date: Fri Jan 20 17:08:34 2012 New Revision: 148597 URL: http://llvm.org/viewvc/llvm-project?rev=148597&view=rev Log: Release more stuff in Process::Destroy(). Modified: lldb/trunk/source/Target/Process.cpp Modified: lldb/trunk/source/Target/Process.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=148597&r1=148596&r2=148597&view=diff ============================================================================== --- lldb/trunk/source/Target/Process.cpp (original) +++ lldb/trunk/source/Target/Process.cpp Fri Jan 20 17:08:34 2012 @@ -844,8 +844,18 @@ // We need to destroy the loader before the derived Process class gets destroyed // since it is very likely that undoing the loader will require access to the real process. - m_dyld_ap.reset(); + m_dynamic_checkers_ap.reset(); + m_abi_sp.reset(); m_os_ap.reset(); + m_dyld_ap.reset(); + m_thread_list.Clear(); + std::vector empty_notifications; + m_notifications.swap(empty_notifications); + m_image_tokens.clear(); + m_memory_cache.Clear(); + m_allocated_memory_cache.Clear(); + m_language_runtimes.clear(); + m_next_event_action_ap.reset(); } void From gclayton at apple.com Fri Jan 20 17:12:25 2012 From: gclayton at apple.com (Greg Clayton) Date: Fri, 20 Jan 2012 23:12:25 -0000 Subject: [Lldb-commits] [lldb] r148598 - /lldb/trunk/examples/python/crashlog.lldb Message-ID: <20120120231225.5C1142A6C12C@llvm.org> Author: gclayton Date: Fri Jan 20 17:12:25 2012 New Revision: 148598 URL: http://llvm.org/viewvc/llvm-project?rev=148598&view=rev Log: This file is no longer needed since the command: (lldb) script import crashlog will automatically add the "crashlog" command to the command interpreter! Removed: lldb/trunk/examples/python/crashlog.lldb Removed: lldb/trunk/examples/python/crashlog.lldb URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/python/crashlog.lldb?rev=148597&view=auto ============================================================================== --- lldb/trunk/examples/python/crashlog.lldb (original) +++ lldb/trunk/examples/python/crashlog.lldb (removed) @@ -1,5 +0,0 @@ -# source this file while being chdir'ed in the directory that contains -# this file at the LLDB command line with: -# (lldb) command source crashlog.lldb -script import crashlog -command script add -f crashlog.Symbolicate crashlog From johnny.chen at apple.com Fri Jan 20 17:34:35 2012 From: johnny.chen at apple.com (Johnny Chen) Date: Fri, 20 Jan 2012 23:34:35 -0000 Subject: [Lldb-commits] [lldb] r148600 - /lldb/trunk/test/functionalities/completion/TestCompletion.py Message-ID: <20120120233435.9BE192A6C12C@llvm.org> Author: johnny Date: Fri Jan 20 17:34:35 2012 New Revision: 148600 URL: http://llvm.org/viewvc/llvm-project?rev=148600&view=rev Log: A little bit of cleanup to make the code more understandable. Modified: lldb/trunk/test/functionalities/completion/TestCompletion.py Modified: lldb/trunk/test/functionalities/completion/TestCompletion.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/completion/TestCompletion.py?rev=148600&r1=148599&r2=148600&view=diff ============================================================================== --- lldb/trunk/test/functionalities/completion/TestCompletion.py (original) +++ lldb/trunk/test/functionalities/completion/TestCompletion.py Fri Jan 20 17:34:35 2012 @@ -62,8 +62,8 @@ 'target.process.thread.step-avoid-regexp', 'target.process.thread.trace-thread']) - def complete_from_to(self, str_before, patterns): - """Test the completion mechanism completes str_before to pattern, where + def complete_from_to(self, str_input, patterns): + """Test the completion mechanism completes str_input to pattern, where patterns could be a pattern-string or a list of pattern-strings""" prompt = "(lldb) " add_prompt = "Enter your stop hook command(s). Type 'DONE' to end.\r\n> " @@ -78,11 +78,10 @@ child.logfile_send = f_send child.logfile_read = f_read - # Test that str_before completes to str_after. child.expect_exact(prompt) child.setecho(True) - child.send("%s\t" % str_before) - #child.expect_exact("%s\t" % str_after) + # Sends str_input and a Tab to invoke the completion machinery. + child.send("%s\t" % str_input) child.sendline('') child.expect_exact(prompt) @@ -100,9 +99,10 @@ if type(patterns) is not types.ListType: patterns = [patterns] + # Test that str_input completes to our patterns. # If each pattern matches from_child, the completion mechanism works! for p in patterns: - self.expect(from_child, msg=COMPLETIOND_MSG(str_before, p), exe=False, + self.expect(from_child, msg=COMPLETIOND_MSG(str_input, p), exe=False, patterns = [p]) child.logfile_send = None From johnny.chen at apple.com Fri Jan 20 18:08:37 2012 From: johnny.chen at apple.com (Johnny Chen) Date: Sat, 21 Jan 2012 00:08:37 -0000 Subject: [Lldb-commits] [lldb] r148602 - /lldb/trunk/test/functionalities/completion/TestCompletion.py Message-ID: <20120121000837.A6B1C2A6C12C@llvm.org> Author: johnny Date: Fri Jan 20 18:08:37 2012 New Revision: 148602 URL: http://llvm.org/viewvc/llvm-project?rev=148602&view=rev Log: Add comment. Modified: lldb/trunk/test/functionalities/completion/TestCompletion.py Modified: lldb/trunk/test/functionalities/completion/TestCompletion.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/completion/TestCompletion.py?rev=148602&r1=148601&r2=148602&view=diff ============================================================================== --- lldb/trunk/test/functionalities/completion/TestCompletion.py (original) +++ lldb/trunk/test/functionalities/completion/TestCompletion.py Fri Jan 20 18:08:37 2012 @@ -85,6 +85,10 @@ child.sendline('') child.expect_exact(prompt) + # Set logfile to None to stop logging. + child.logfile_send = None + child.logfile_read = None + with open('child_send.txt', 'r') as fs: if self.TraceOn(): print "\n\nContents of child_send.txt:" @@ -105,9 +109,6 @@ self.expect(from_child, msg=COMPLETIOND_MSG(str_input, p), exe=False, patterns = [p]) - child.logfile_send = None - child.logfile_read = None - if __name__ == '__main__': import atexit From gclayton at apple.com Fri Jan 20 18:37:19 2012 From: gclayton at apple.com (Greg Clayton) Date: Sat, 21 Jan 2012 00:37:19 -0000 Subject: [Lldb-commits] [lldb] r148605 - /lldb/trunk/examples/python/crashlog.py Message-ID: <20120121003719.7E7D32A6C12C@llvm.org> Author: gclayton Date: Fri Jan 20 18:37:19 2012 New Revision: 148605 URL: http://llvm.org/viewvc/llvm-project?rev=148605&view=rev Log: Fixed it so the "--help" option works for the crashlog command. Corrected and filled out the command help and removed unused options. Updated the command to have a "--load-all" option that will cause the target that gets created to locate and load all images specified in the Binary Images section of the crash log to allow for complete program state to be matched to that of the crash log, not just the images that were in the stack frames (the default). Modified: lldb/trunk/examples/python/crashlog.py Modified: lldb/trunk/examples/python/crashlog.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/python/crashlog.py?rev=148605&r1=148604&r2=148605&view=diff ============================================================================== --- lldb/trunk/examples/python/crashlog.py (original) +++ lldb/trunk/examples/python/crashlog.py Fri Jan 20 18:37:19 2012 @@ -2,18 +2,36 @@ #---------------------------------------------------------------------- # Be sure to add the python path that points to the LLDB shared library. +# +# To use this in the embedded python interpreter using "lldb": +# +# cd /path/containing/crashlog.py +# lldb +# (lldb) script import crashlog +# "crashlog" command installed, type "crashlog --help" for detailed help +# (lldb) crashlog ~/Library/Logs/DiagnosticReports/a.crash +# +# The benefit of running the crashlog command inside lldb in the +# embedded python interpreter is when the command completes, there +# will be a target with all of the files loaded at the locations +# described in the crash log. Only the files that have stack frames +# in the backtrace will be loaded unless the "--load-all" option +# has been specified. This allows users to explore the program in the +# state it was in right at crash time. +# # On MacOSX csh, tcsh: -# setenv PYTHONPATH /Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python +# ( setenv PYTHONPATH /path/to/LLDB.framework/Resources/Python ; ./crashlog.py ~/Library/Logs/DiagnosticReports/a.crash ) +# # On MacOSX sh, bash: -# export PYTHONPATH=/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python +# PYTHONPATH=/path/to/LLDB.framework/Resources/Python ./crashlog.py ~/Library/Logs/DiagnosticReports/a.crash #---------------------------------------------------------------------- import lldb -import commands # commands.getoutput ('/bin/ls /tmp') +import commands import optparse import os import plistlib -import pprint +#import pprint # pp = pprint.PrettyPrinter(indent=4); pp.pprint(command_args) import re import sys import time @@ -135,8 +153,6 @@ if s: plist_root = plistlib.readPlistFromString (s) if plist_root: - # pp = pprint.PrettyPrinter(indent=4) - # pp.pprint(plist_root) plist = plist_root[self.uuid] if plist: if 'DBGArchitecture' in plist: @@ -463,10 +479,20 @@ def SymbolicateCrashLog(command_args): print 'command_args = %s' % command_args - parser = optparse.OptionParser(description='Parses darwin crash log files and symbolicates them.') + usage = "usage: %prog [options] [FILE ...]" + description='''Symbolicate one or more darwin crash log files to provide source file and line information, +inlined stack frames back to the concrete functions, and disassemble the location of the crash +for the first frame of the crashed thread. +If this script is imported into the LLDB command interpreter, a "crashlog" command will be added to the interpreter +for use at the LLDB command line. After a crash log has been parsed and symbolicated, a target will have been +created that has all of the shared libraries loaded at the load addresses found in the crash log file. This allows +you to explore the program as if it were stopped at the locations described in the crash log and functions can +be disassembled and lookups can be performed using the addresses found in the crash log.''' + parser = optparse.OptionParser(description=description, prog='crashlog.py',usage=usage) parser.add_option('--platform', type='string', metavar='platform', dest='platform', help='specify one platform by name') parser.add_option('--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) parser.add_option('--no-images', action='store_false', dest='show_images', help='don\'t show images in stack frames', default=True) + parser.add_option('--load-all', action='store_true', dest='load_all_images', help='load all executable images, not just the images found in the crashed stack frames', default=False) parser.add_option('--image-list', action='store_true', dest='dump_image_list', help='show image list', default=False) parser.add_option('--debug-delay', type='int', dest='debug_delay', metavar='NSEC', help='pause for NSEC seconds for debugger', default=0) parser.add_option('--crashed-only', action='store_true', dest='crashed_only', help='only symbolicate the crashed thread', default=False) @@ -483,184 +509,196 @@ crash_log = CrashLog(crash_log_file) if options.verbose: crash_log.dump() - if crash_log.images: - err = crash_log.create_target () - if err: - print err + if not crash_log.images: + print 'error: no images in crash log' + return + + err = crash_log.create_target () + if err: + print err + return + + exe_module = lldb.target.GetModuleAtIndex(0) + images_to_load = list() + loaded_image_paths = list() + if options.load_all_images: + # --load-all option was specified, load everything up + for image in crash_log.images: + images_to_load.append(image) + else: + # Only load the images found in stack frames for the crashed threads + for ident in crash_log.idents: + image = crash_log.find_image_with_identifier (ident) + if image: + images_to_load.append(image) + else: + print 'error: can\'t find image for identifier "%s"' % ident + + for image in images_to_load: + if image.path in loaded_image_paths: + print "warning: skipping %s loaded at %#16.16x duplicate entry (probably commpage)" % (image.path, image.text_addr_lo) else: - exe_module = lldb.target.GetModuleAtIndex(0) - image_paths = list() - # for i in range (1, len(crash_log.images)): - # image = crash_log.images[i] - for ident in crash_log.idents: - image = crash_log.find_image_with_identifier (ident) - if image: - if image.path in image_paths: - print "warning: skipping %s loaded at %#16.16x duplicate entry (probably commpage)" % (image.path, image.text_addr_lo) - else: - err = image.add_target_module () - if err: - print err - else: - image_paths.append(image.path) - else: - print 'error: can\'t find image for identifier "%s"' % ident - - for line in crash_log.info_lines: - print line - - # Reconstruct inlined frames for all threads for anything that has debug info - for thread in crash_log.threads: - if options.crashed_only and thread.did_crash() == False: - continue - # start a new frame list that we will fixup for each thread - new_thread_frames = list() - # Iterate through all concrete frames for a thread and resolve - # any parent frames of inlined functions - for frame_idx, frame in enumerate(thread.frames): - # Resolve the frame's pc into a section + offset address 'pc_addr' - pc_addr = lldb.target.ResolveLoadAddress (frame.pc) - # Check to see if we were able to resolve the address - if pc_addr: - # We were able to resolve the frame's PC into a section offset - # address. - - # Resolve the frame's PC value into a symbol context. A symbol - # context can resolve a module, compile unit, function, block, - # line table entry and/or symbol. If the frame has a block, then - # we can look for inlined frames, which are represented by blocks - # that have inlined information in them - frame.sym_ctx = lldb.target.ResolveSymbolContextForAddress (pc_addr, lldb.eSymbolContextEverything); - - # dump if the verbose option was specified - if options.verbose: - print "frame.pc = %#16.16x (file_addr = %#16.16x)" % (frame.pc, pc_addr.GetFileAddress()) - print "frame.pc_addr = ", pc_addr - print "frame.sym_ctx = " - print frame.sym_ctx - print - - # Append the frame we already had from the crash log to the new - # frames list - new_thread_frames.append(frame) - - new_frame = CrashLog.Frame (frame.index, -1, None) - - # Try and use the current frame's symbol context to calculate a - # parent frame for an inlined function. If the curent frame is - # inlined, it will return a valid symbol context for the parent - # frame of the current inlined function - parent_pc_addr = lldb.SBAddress() - new_frame.sym_ctx = frame.sym_ctx.GetParentOfInlinedScope (pc_addr, parent_pc_addr) - - # See if we were able to reconstruct anything? - while new_frame.sym_ctx: - # We have a parent frame of an inlined frame, create a new frame - # Convert the section + offset 'parent_pc_addr' to a load address - new_frame.pc = parent_pc_addr.GetLoadAddress(lldb.target) - # push the new frame onto the new frame stack - new_thread_frames.append (new_frame) - # dump if the verbose option was specified - if options.verbose: - print "new_frame.pc = %#16.16x (%s)" % (new_frame.pc, parent_pc_addr) - print "new_frame.sym_ctx = " - print new_frame.sym_ctx - print - # Create another new frame in case we have multiple inlined frames - prev_new_frame = new_frame - new_frame = CrashLog.Frame (frame.index, -1, None) - # Swap the addresses so we can try another inlined lookup - pc_addr = parent_pc_addr; - new_frame.sym_ctx = prev_new_frame.sym_ctx.GetParentOfInlinedScope (pc_addr, parent_pc_addr) - # Replace our thread frames with our new list that includes parent - # frames for inlined functions - thread.frames = new_thread_frames - # Now iterate through all threads and display our richer stack backtraces - for thread in crash_log.threads: - this_thread_crashed = thread.did_crash() - if options.crashed_only and this_thread_crashed == False: - continue - print "%s" % thread - prev_frame_index = -1 - for frame_idx, frame in enumerate(thread.frames): - details = ' %s' % frame.details - module = frame.sym_ctx.GetModule() - instructions = None - if module: - module_basename = module.GetFileSpec().GetFilename(); - function_start_load_addr = -1 - function_name = None - function = frame.sym_ctx.GetFunction() - block = frame.sym_ctx.GetBlock() - line_entry = frame.sym_ctx.GetLineEntry() - symbol = frame.sym_ctx.GetSymbol() - inlined_block = block.GetContainingInlinedBlock(); - if inlined_block: - function_name = inlined_block.GetInlinedName(); - block_range_idx = inlined_block.GetRangeIndexForBlockAddress (lldb.target.ResolveLoadAddress (frame.pc)) - if block_range_idx < lldb.UINT32_MAX: - block_range_start_addr = inlined_block.GetRangeStartAddress (block_range_idx) - function_start_load_addr = block_range_start_addr.GetLoadAddress (lldb.target) - else: - function_start_load_addr = frame.pc - if this_thread_crashed and frame_idx == 0: - instructions = function.GetInstructions(lldb.target) - elif function: - function_name = function.GetName() - function_start_load_addr = function.GetStartAddress().GetLoadAddress (lldb.target) - if this_thread_crashed and frame_idx == 0: - instructions = function.GetInstructions(lldb.target) - elif symbol: - function_name = symbol.GetName() - function_start_load_addr = symbol.GetStartAddress().GetLoadAddress (lldb.target) - if this_thread_crashed and frame_idx == 0: - instructions = symbol.GetInstructions(lldb.target) - - if function_name: - # Print the function or symbol name and annotate if it was inlined - inline_suffix = '' - if inlined_block: - inline_suffix = '[inlined] ' - else: - inline_suffix = ' ' - if options.show_images: - details = "%s%s`%s" % (inline_suffix, module_basename, function_name) - else: - details = "%s" % (function_name) - # Dump the offset from the current function or symbol if it is non zero - function_offset = frame.pc - function_start_load_addr - if function_offset > 0: - details += " + %u" % (function_offset) - elif function_offset < 0: - defaults += " %i (invalid negative offset, file a bug) " % function_offset - # Print out any line information if any is available - if line_entry.GetFileSpec(): - details += ' at %s' % line_entry.GetFileSpec().GetFilename() - details += ':%u' % line_entry.GetLine () - column = line_entry.GetColumn() - if column > 0: - details += ':%u' % column - - - # Only print out the concrete frame index if it changes. - # if prev_frame_index != frame.index: - # print "[%2u] %#16.16x %s" % (frame.index, frame.pc, details) - # else: - # print " %#16.16x %s" % (frame.pc, details) - print "[%2u] %#16.16x %s" % (frame.index, frame.pc, details) - prev_frame_index = frame.index - if instructions: - print - disassemble_instructions (instructions, frame.pc, 4, 4) + err = image.add_target_module () + if err: + print err + else: + loaded_image_paths.append(image.path) + + for line in crash_log.info_lines: + print line + + # Reconstruct inlined frames for all threads for anything that has debug info + for thread in crash_log.threads: + if options.crashed_only and thread.did_crash() == False: + continue + # start a new frame list that we will fixup for each thread + new_thread_frames = list() + # Iterate through all concrete frames for a thread and resolve + # any parent frames of inlined functions + for frame_idx, frame in enumerate(thread.frames): + # Resolve the frame's pc into a section + offset address 'pc_addr' + pc_addr = lldb.target.ResolveLoadAddress (frame.pc) + # Check to see if we were able to resolve the address + if pc_addr: + # We were able to resolve the frame's PC into a section offset + # address. + + # Resolve the frame's PC value into a symbol context. A symbol + # context can resolve a module, compile unit, function, block, + # line table entry and/or symbol. If the frame has a block, then + # we can look for inlined frames, which are represented by blocks + # that have inlined information in them + frame.sym_ctx = lldb.target.ResolveSymbolContextForAddress (pc_addr, lldb.eSymbolContextEverything); + + # dump if the verbose option was specified + if options.verbose: + print "frame.pc = %#16.16x (file_addr = %#16.16x)" % (frame.pc, pc_addr.GetFileAddress()) + print "frame.pc_addr = ", pc_addr + print "frame.sym_ctx = " + print frame.sym_ctx + print + + # Append the frame we already had from the crash log to the new + # frames list + new_thread_frames.append(frame) + + new_frame = CrashLog.Frame (frame.index, -1, None) + + # Try and use the current frame's symbol context to calculate a + # parent frame for an inlined function. If the curent frame is + # inlined, it will return a valid symbol context for the parent + # frame of the current inlined function + parent_pc_addr = lldb.SBAddress() + new_frame.sym_ctx = frame.sym_ctx.GetParentOfInlinedScope (pc_addr, parent_pc_addr) + + # See if we were able to reconstruct anything? + while new_frame.sym_ctx: + # We have a parent frame of an inlined frame, create a new frame + # Convert the section + offset 'parent_pc_addr' to a load address + new_frame.pc = parent_pc_addr.GetLoadAddress(lldb.target) + # push the new frame onto the new frame stack + new_thread_frames.append (new_frame) + # dump if the verbose option was specified + if options.verbose: + print "new_frame.pc = %#16.16x (%s)" % (new_frame.pc, parent_pc_addr) + print "new_frame.sym_ctx = " + print new_frame.sym_ctx print + # Create another new frame in case we have multiple inlined frames + prev_new_frame = new_frame + new_frame = CrashLog.Frame (frame.index, -1, None) + # Swap the addresses so we can try another inlined lookup + pc_addr = parent_pc_addr; + new_frame.sym_ctx = prev_new_frame.sym_ctx.GetParentOfInlinedScope (pc_addr, parent_pc_addr) + # Replace our thread frames with our new list that includes parent + # frames for inlined functions + thread.frames = new_thread_frames + # Now iterate through all threads and display our richer stack backtraces + for thread in crash_log.threads: + this_thread_crashed = thread.did_crash() + if options.crashed_only and this_thread_crashed == False: + continue + print "%s" % thread + prev_frame_index = -1 + for frame_idx, frame in enumerate(thread.frames): + details = ' %s' % frame.details + module = frame.sym_ctx.GetModule() + instructions = None + if module: + module_basename = module.GetFileSpec().GetFilename(); + function_start_load_addr = -1 + function_name = None + function = frame.sym_ctx.GetFunction() + block = frame.sym_ctx.GetBlock() + line_entry = frame.sym_ctx.GetLineEntry() + symbol = frame.sym_ctx.GetSymbol() + inlined_block = block.GetContainingInlinedBlock(); + if inlined_block: + function_name = inlined_block.GetInlinedName(); + block_range_idx = inlined_block.GetRangeIndexForBlockAddress (lldb.target.ResolveLoadAddress (frame.pc)) + if block_range_idx < lldb.UINT32_MAX: + block_range_start_addr = inlined_block.GetRangeStartAddress (block_range_idx) + function_start_load_addr = block_range_start_addr.GetLoadAddress (lldb.target) + else: + function_start_load_addr = frame.pc + if this_thread_crashed and frame_idx == 0: + instructions = function.GetInstructions(lldb.target) + elif function: + function_name = function.GetName() + function_start_load_addr = function.GetStartAddress().GetLoadAddress (lldb.target) + if this_thread_crashed and frame_idx == 0: + instructions = function.GetInstructions(lldb.target) + elif symbol: + function_name = symbol.GetName() + function_start_load_addr = symbol.GetStartAddress().GetLoadAddress (lldb.target) + if this_thread_crashed and frame_idx == 0: + instructions = symbol.GetInstructions(lldb.target) + + if function_name: + # Print the function or symbol name and annotate if it was inlined + inline_suffix = '' + if inlined_block: + inline_suffix = '[inlined] ' + else: + inline_suffix = ' ' + if options.show_images: + details = "%s%s`%s" % (inline_suffix, module_basename, function_name) + else: + details = "%s" % (function_name) + # Dump the offset from the current function or symbol if it is non zero + function_offset = frame.pc - function_start_load_addr + if function_offset > 0: + details += " + %u" % (function_offset) + elif function_offset < 0: + defaults += " %i (invalid negative offset, file a bug) " % function_offset + # Print out any line information if any is available + if line_entry.GetFileSpec(): + details += ' at %s' % line_entry.GetFileSpec().GetFilename() + details += ':%u' % line_entry.GetLine () + column = line_entry.GetColumn() + if column > 0: + details += ':%u' % column + + + # Only print out the concrete frame index if it changes. + # if prev_frame_index != frame.index: + # print "[%2u] %#16.16x %s" % (frame.index, frame.pc, details) + # else: + # print " %#16.16x %s" % (frame.pc, details) + print "[%2u] %#16.16x %s" % (frame.index, frame.pc, details) + prev_frame_index = frame.index + if instructions: + print + disassemble_instructions (instructions, frame.pc, 4, 4) + print + + print + + if options.dump_image_list: + print "Binary Images:" + for image in crash_log.images: + print image - print - - if options.dump_image_list: - print "Binary Images:" - for image in crash_log.images: - print image - if __name__ == '__main__': # Create a new debugger instance From gclayton at apple.com Fri Jan 20 19:15:06 2012 From: gclayton at apple.com (Greg Clayton) Date: Sat, 21 Jan 2012 01:15:06 -0000 Subject: [Lldb-commits] [lldb] r148613 - in /lldb/trunk: lldb.xcodeproj/project.pbxproj resources/LLDB-Info.plist tools/debugserver/debugserver.xcodeproj/project.pbxproj Message-ID: <20120121011506.E4F4A2A6C12C@llvm.org> Author: gclayton Date: Fri Jan 20 19:15:06 2012 New Revision: 148613 URL: http://llvm.org/viewvc/llvm-project?rev=148613&view=rev Log: Bumped Xcode project versions for lldb-108 and debugserver-166. Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj lldb/trunk/resources/LLDB-Info.plist lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=148613&r1=148612&r2=148613&view=diff ============================================================================== --- lldb/trunk/lldb.xcodeproj/project.pbxproj (original) +++ lldb/trunk/lldb.xcodeproj/project.pbxproj Fri Jan 20 19:15:06 2012 @@ -2984,7 +2984,7 @@ 08FB7793FE84155DC02AAC07 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0420; + LastUpgradeCheck = 0430; }; buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "lldb" */; compatibilityVersion = "Xcode 3.2"; @@ -3733,9 +3733,9 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CURRENT_PROJECT_VERSION = 107; + CURRENT_PROJECT_VERSION = 108; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 107; + DYLIB_CURRENT_VERSION = 108; EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3793,10 +3793,10 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CURRENT_PROJECT_VERSION = 107; + CURRENT_PROJECT_VERSION = 108; DEAD_CODE_STRIPPING = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 107; + DYLIB_CURRENT_VERSION = 108; EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3852,8 +3852,8 @@ 2689FFD513353D7A00698AC0 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 107; - DYLIB_CURRENT_VERSION = 107; + CURRENT_PROJECT_VERSION = 108; + DYLIB_CURRENT_VERSION = 108; EXECUTABLE_EXTENSION = a; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3881,8 +3881,8 @@ 2689FFD613353D7A00698AC0 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 107; - DYLIB_CURRENT_VERSION = 107; + CURRENT_PROJECT_VERSION = 108; + DYLIB_CURRENT_VERSION = 108; EXECUTABLE_EXTENSION = a; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3910,8 +3910,8 @@ 2689FFD713353D7A00698AC0 /* BuildAndIntegration */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 107; - DYLIB_CURRENT_VERSION = 107; + CURRENT_PROJECT_VERSION = 108; + DYLIB_CURRENT_VERSION = 108; EXECUTABLE_EXTENSION = a; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3991,7 +3991,7 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 107; + CURRENT_PROJECT_VERSION = 108; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"", @@ -4022,10 +4022,10 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 107; + CURRENT_PROJECT_VERSION = 108; DEAD_CODE_STRIPPING = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 107; + DYLIB_CURRENT_VERSION = 108; EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -4269,7 +4269,7 @@ 26F5C26C10F3D9A5009D5894 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 107; + CURRENT_PROJECT_VERSION = 108; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"", @@ -4299,7 +4299,7 @@ 26F5C26D10F3D9A5009D5894 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 107; + CURRENT_PROJECT_VERSION = 108; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"", Modified: lldb/trunk/resources/LLDB-Info.plist URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/resources/LLDB-Info.plist?rev=148613&r1=148612&r2=148613&view=diff ============================================================================== --- lldb/trunk/resources/LLDB-Info.plist (original) +++ lldb/trunk/resources/LLDB-Info.plist Fri Jan 20 19:15:06 2012 @@ -17,7 +17,7 @@ CFBundleSignature ???? CFBundleVersion - 107 + 108 CFBundleName ${EXECUTABLE_NAME} Modified: lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj?rev=148613&r1=148612&r2=148613&view=diff ============================================================================== --- lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj (original) +++ lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj Fri Jan 20 19:15:06 2012 @@ -475,7 +475,7 @@ i386, ); COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 165; + CURRENT_PROJECT_VERSION = 166; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; SDKROOT = ""; @@ -494,7 +494,7 @@ x86_64, i386, ); - CURRENT_PROJECT_VERSION = 165; + CURRENT_PROJECT_VERSION = 166; DEAD_CODE_STRIPPING = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; @@ -515,7 +515,7 @@ x86_64, i386, ); - CURRENT_PROJECT_VERSION = 165; + CURRENT_PROJECT_VERSION = 166; DEAD_CODE_STRIPPING = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; @@ -534,7 +534,7 @@ "ARCHS[sdk=iphoneos*]" = "$(ARCHS_STANDARD_32_BIT)"; "CODE_SIGN_ENTITLEMENTS[sdk=iphoneos*]" = "source/debugserver-entitlements.plist"; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 165; + CURRENT_PROJECT_VERSION = 166; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; FRAMEWORK_SEARCH_PATHS = $SDKROOT/System/Library/PrivateFrameworks; "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*][arch=*]" = ( @@ -575,7 +575,7 @@ "CODE_SIGN_ENTITLEMENTS[sdk=iphoneos*]" = "source/debugserver-entitlements.plist"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = lldb_codesign; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 165; + CURRENT_PROJECT_VERSION = 166; FRAMEWORK_SEARCH_PATHS = $SDKROOT/System/Library/PrivateFrameworks; "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*][arch=*]" = ( "$(SDKROOT)/System/Library/PrivateFrameworks", @@ -616,7 +616,7 @@ "CODE_SIGN_ENTITLEMENTS[sdk=iphoneos*]" = "source/debugserver-entitlements.plist"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = lldb_codesign; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 165; + CURRENT_PROJECT_VERSION = 166; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; FRAMEWORK_SEARCH_PATHS = $SDKROOT/System/Library/PrivateFrameworks; "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*][arch=*]" = ( From gclayton at apple.com Fri Jan 20 19:15:32 2012 From: gclayton at apple.com (Greg Clayton) Date: Sat, 21 Jan 2012 01:15:32 -0000 Subject: [Lldb-commits] [lldb] r148614 - /lldb/tags/lldb-108/ Message-ID: <20120121011532.116C02A6C12C@llvm.org> Author: gclayton Date: Fri Jan 20 19:15:31 2012 New Revision: 148614 URL: http://llvm.org/viewvc/llvm-project?rev=148614&view=rev Log: lldb-108 Added: lldb/tags/lldb-108/ - copied from r148613, lldb/trunk/ From johnny.chen at apple.com Fri Jan 20 19:45:18 2012 From: johnny.chen at apple.com (Johnny Chen) Date: Sat, 21 Jan 2012 01:45:18 -0000 Subject: [Lldb-commits] [lldb] r148615 - in /lldb/trunk: source/Commands/CommandObjectSettings.cpp source/Commands/CommandObjectSettings.h test/functionalities/completion/TestCompletion.py test/settings/TestSettings.py Message-ID: <20120121014518.4EE172A6C12C@llvm.org> Author: johnny Date: Fri Jan 20 19:45:18 2012 New Revision: 148615 URL: http://llvm.org/viewvc/llvm-project?rev=148615&view=rev Log: Followup check in for http://llvm.org/viewvc/llvm-project?rev=148491&view=rev, where we changed the CommandObjectSettingsSet object impl to require raw command string. Do the same for CommandObjectSettingsReplace class and add two test cases; one for the "settings replace" command and the other to ensure that completion for variable name still works. Modified: lldb/trunk/source/Commands/CommandObjectSettings.cpp lldb/trunk/source/Commands/CommandObjectSettings.h lldb/trunk/test/functionalities/completion/TestCompletion.py lldb/trunk/test/settings/TestSettings.py Modified: lldb/trunk/source/Commands/CommandObjectSettings.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectSettings.cpp?rev=148615&r1=148614&r2=148615&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectSettings.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectSettings.cpp Fri Jan 20 19:45:18 2012 @@ -690,11 +690,12 @@ } bool -CommandObjectSettingsReplace::Execute (Args& command, CommandReturnObject &result) +CommandObjectSettingsReplace::ExecuteRawCommandString (const char *raw_command, CommandReturnObject &result) { UserSettingsControllerSP usc_sp (Debugger::GetSettingsController ()); - const int argc = command.GetArgumentCount (); + Args cmd_args(raw_command); + const int argc = cmd_args.GetArgumentCount (); if (argc < 3) { @@ -703,7 +704,7 @@ return false; } - const char *var_name = command.GetArgumentAtIndex (0); + const char *var_name = cmd_args.GetArgumentAtIndex (0); std::string var_name_string; if ((var_name == NULL) || (var_name[0] == '\0')) { @@ -713,9 +714,9 @@ } var_name_string = var_name; - command.Shift(); + cmd_args.Shift(); - const char *index_value = command.GetArgumentAtIndex (0); + const char *index_value = cmd_args.GetArgumentAtIndex (0); std::string index_value_string; if ((index_value == NULL) || (index_value[0] == '\0')) { @@ -725,15 +726,15 @@ } index_value_string = index_value; - command.Shift(); - - const char *var_value; - std::string value_string; + cmd_args.Shift(); - command.GetQuotedCommandString (value_string); - var_value = value_string.c_str(); + // Split the raw command into var_name, index_value, and value triple. + llvm::StringRef raw_str(raw_command); + llvm::StringRef var_value_str = raw_str.split(var_name).second.split(index_value).second; + StripLeadingSpaces(var_value_str); + std::string var_value_string = var_value_str.str(); - if ((var_value == NULL) || (var_value[0] == '\0')) + if (var_value_string.empty()) { result.AppendError ("'settings replace' command requires a valid variable value; no value supplied"); result.SetStatus (eReturnStatusFailed); @@ -741,7 +742,7 @@ else { Error err = usc_sp->SetVariable (var_name_string.c_str(), - var_value, + var_value_string.c_str(), eVarSetOperationReplace, true, m_interpreter.GetDebugger().GetInstanceName().AsCString(), Modified: lldb/trunk/source/Commands/CommandObjectSettings.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectSettings.h?rev=148615&r1=148614&r2=148615&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectSettings.h (original) +++ lldb/trunk/source/Commands/CommandObjectSettings.h Fri Jan 20 19:45:18 2012 @@ -212,7 +212,19 @@ virtual bool Execute (Args& command, - CommandReturnObject &result); + CommandReturnObject &result) + { return false; } + + virtual bool + WantsRawCommandString() { return true; } + + // Overrides base class's behavior where WantsCompletion = !WantsRawCommandString. + virtual bool + WantsCompletion() { return true; } + + virtual bool + ExecuteRawCommandString (const char *raw_command, + CommandReturnObject &result); virtual int HandleArgumentCompletion (Args &input, Modified: lldb/trunk/test/functionalities/completion/TestCompletion.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/completion/TestCompletion.py?rev=148615&r1=148614&r2=148615&view=diff ============================================================================== --- lldb/trunk/test/functionalities/completion/TestCompletion.py (original) +++ lldb/trunk/test/functionalities/completion/TestCompletion.py Fri Jan 20 19:45:18 2012 @@ -18,6 +18,10 @@ system(["/bin/sh", "-c", "rm -f child_send.txt"]) system(["/bin/sh", "-c", "rm -f child_read.txt"]) + def test_settings_replace_target_ru(self): + """Test that 'settings replace target.ru' completes to 'settings replace target.run-args'.""" + self.complete_from_to('settings replace target.ru', 'settings replace target.run-args') + def test_settings_s(self): """Test that 'settings s' completes to ['Available completions:', 'set', 'show'].""" self.complete_from_to('settings s', ['Available completions:', 'set', 'show']) Modified: lldb/trunk/test/settings/TestSettings.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/settings/TestSettings.py?rev=148615&r1=148614&r2=148615&view=diff ============================================================================== --- lldb/trunk/test/settings/TestSettings.py (original) +++ lldb/trunk/test/settings/TestSettings.py Fri Jan 20 19:45:18 2012 @@ -27,6 +27,23 @@ "environment variables", "executable's environment"]) + def test_replace_target_run_args(self): + """Test that 'replace target.run-args' works.""" + # Set the run-args and then replace the index-0 element. + self.runCmd('settings set target.run-args a b c') + # And add hooks to restore the settings during tearDown(). + self.addTearDownHook( + lambda: self.runCmd("settings set -r target.run-args")) + + # Now replace the index-0 element with 'A', instead. + self.runCmd('settings replace target.run-args 0 A') + # Check it immediately! + self.expect('settings show target.run-args', + substrs = ['target.run-args (array) = ', + '[0]: "A"', + '[1]: "b"', + '[2]: "c"']) + def test_set_prompt(self): """Test that 'set prompt' actually changes the prompt.""" From jingham at apple.com Fri Jan 20 20:03:41 2012 From: jingham at apple.com (Jim Ingham) Date: Sat, 21 Jan 2012 02:03:41 -0000 Subject: [Lldb-commits] [lldb] r148616 - /lldb/trunk/source/Core/ConnectionFileDescriptor.cpp Message-ID: <20120121020341.973DE2A6C12C@llvm.org> Author: jingham Date: Fri Jan 20 20:03:41 2012 New Revision: 148616 URL: http://llvm.org/viewvc/llvm-project?rev=148616&view=rev Log: Our Read functions were taking a timeout of UINT32_MAX to mean wait forever, but then we didn't implement that in setting the socket option. Modified: lldb/trunk/source/Core/ConnectionFileDescriptor.cpp Modified: lldb/trunk/source/Core/ConnectionFileDescriptor.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ConnectionFileDescriptor.cpp?rev=148616&r1=148615&r2=148616&view=diff ============================================================================== --- lldb/trunk/source/Core/ConnectionFileDescriptor.cpp (original) +++ lldb/trunk/source/Core/ConnectionFileDescriptor.cpp Fri Jan 20 20:03:41 2012 @@ -983,8 +983,16 @@ //printf ("ConnectionFileDescriptor::SetSocketReceiveTimeout (timeout_usec = %u)\n", timeout_usec); struct timeval timeout; - timeout.tv_sec = timeout_usec / TimeValue::MicroSecPerSec; - timeout.tv_usec = timeout_usec % TimeValue::MicroSecPerSec; + if (timeout_usec == UINT32_MAX) + { + timeout.tv_sec = 0; + timeout.tv_usec = 0; + } + else + { + timeout.tv_sec = timeout_usec / TimeValue::MicroSecPerSec; + timeout.tv_usec = timeout_usec % TimeValue::MicroSecPerSec; + } if (::setsockopt (m_fd_recv, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == 0) { m_socket_timeout_usec = timeout_usec; From gclayton at apple.com Fri Jan 20 20:28:13 2012 From: gclayton at apple.com (Greg Clayton) Date: Sat, 21 Jan 2012 02:28:13 -0000 Subject: [Lldb-commits] [lldb] r148617 - /lldb/trunk/source/Core/ConnectionFileDescriptor.cpp Message-ID: <20120121022813.EC98D2A6C12C@llvm.org> Author: gclayton Date: Fri Jan 20 20:28:13 2012 New Revision: 148617 URL: http://llvm.org/viewvc/llvm-project?rev=148617&view=rev Log: A Small tweak to handle a zero timeout. Modified: lldb/trunk/source/Core/ConnectionFileDescriptor.cpp Modified: lldb/trunk/source/Core/ConnectionFileDescriptor.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ConnectionFileDescriptor.cpp?rev=148617&r1=148616&r2=148617&view=diff ============================================================================== --- lldb/trunk/source/Core/ConnectionFileDescriptor.cpp (original) +++ lldb/trunk/source/Core/ConnectionFileDescriptor.cpp Fri Jan 20 20:28:13 2012 @@ -988,6 +988,13 @@ timeout.tv_sec = 0; timeout.tv_usec = 0; } + else if (timeout_usec == 0) + { + // Sending in zero does an infinite timeout, so set this as low + // as we can go to get an effective zero timeout... + timeout.tv_sec = 0; + timeout.tv_usec = 1; + } else { timeout.tv_sec = timeout_usec / TimeValue::MicroSecPerSec; From gclayton at apple.com Fri Jan 20 20:29:36 2012 From: gclayton at apple.com (Greg Clayton) Date: Sat, 21 Jan 2012 02:29:36 -0000 Subject: [Lldb-commits] [lldb] r148618 - /lldb/tags/lldb-108/ Message-ID: <20120121022936.A94DB2A6C12C@llvm.org> Author: gclayton Date: Fri Jan 20 20:29:36 2012 New Revision: 148618 URL: http://llvm.org/viewvc/llvm-project?rev=148618&view=rev Log: Going to retag. Removed: lldb/tags/lldb-108/ From gclayton at apple.com Fri Jan 20 20:30:01 2012 From: gclayton at apple.com (Greg Clayton) Date: Sat, 21 Jan 2012 02:30:01 -0000 Subject: [Lldb-commits] [lldb] r148619 - /lldb/tags/lldb-108/ Message-ID: <20120121023001.0A2C32A6C12C@llvm.org> Author: gclayton Date: Fri Jan 20 20:30:00 2012 New Revision: 148619 URL: http://llvm.org/viewvc/llvm-project?rev=148619&view=rev Log: lldb-108 (second tag) Added: lldb/tags/lldb-108/ - copied from r148618, lldb/trunk/ From gclayton at apple.com Fri Jan 20 22:26:24 2012 From: gclayton at apple.com (Greg Clayton) Date: Sat, 21 Jan 2012 04:26:24 -0000 Subject: [Lldb-commits] [lldb] r148623 - /lldb/trunk/examples/python/crashlog.py Message-ID: <20120121042624.4B1542A6C12C@llvm.org> Author: gclayton Date: Fri Jan 20 22:26:24 2012 New Revision: 148623 URL: http://llvm.org/viewvc/llvm-project?rev=148623&view=rev Log: Use the "shlex" module to parse the command line that was passed down into python so that single and double quotes and other standard shell like argument parsing happens as expected before passing stuff along to option parsing. Also handle exceptions so that we don't accidentally exit lldb if an uncaught exception occurs. Modified: lldb/trunk/examples/python/crashlog.py Modified: lldb/trunk/examples/python/crashlog.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/python/crashlog.py?rev=148623&r1=148622&r2=148623&view=diff ============================================================================== --- lldb/trunk/examples/python/crashlog.py (original) +++ lldb/trunk/examples/python/crashlog.py Fri Jan 20 22:26:24 2012 @@ -33,6 +33,7 @@ import plistlib #import pprint # pp = pprint.PrettyPrinter(indent=4); pp.pprint(command_args) import re +import shlex import sys import time import uuid @@ -245,7 +246,7 @@ def __init__(self, path): """CrashLog constructor that take a path to a darwin crash log file""" - self.path = path; + self.path = os.path.expanduser(path); self.info_lines = list() self.system_profile = list() self.threads = list() @@ -253,8 +254,14 @@ self.idents = list() # A list of the required identifiers for doing all stack backtraces self.crashed_thread_idx = -1 self.version = -1 + self.error = None # With possible initial component of ~ or ~user replaced by that user's home directory. - f = open(os.path.expanduser(self.path)) + try: + f = open(self.path) + except IOError: + self.error = 'error: cannot open "%s"' % self.path + return + self.file_lines = f.read().splitlines() parse_mode = PARSE_MODE_NORMAL thread = None @@ -475,10 +482,12 @@ sys.exit(0) def Symbolicate(debugger, command, result, dict): - SymbolicateCrashLog (command.split()) - + try: + SymbolicateCrashLog (shlex.split(command)) + except: + result.PutCString ("error: python exception %s" % sys.exc_info()[0]) + def SymbolicateCrashLog(command_args): - print 'command_args = %s' % command_args usage = "usage: %prog [options] [FILE ...]" description='''Symbolicate one or more darwin crash log files to provide source file and line information, inlined stack frames back to the concrete functions, and disassemble the location of the crash @@ -497,9 +506,16 @@ parser.add_option('--debug-delay', type='int', dest='debug_delay', metavar='NSEC', help='pause for NSEC seconds for debugger', default=0) parser.add_option('--crashed-only', action='store_true', dest='crashed_only', help='only symbolicate the crashed thread', default=False) loaded_addresses = False - (options, args) = parser.parse_args(command_args) + try: + (options, args) = parser.parse_args(command_args) + except: + return + if options.verbose: + print 'command_args = %s' % command_args print 'options', options + print 'args', args + if options.debug_delay > 0: print "Waiting %u seconds for debugger to attach..." % options.debug_delay time.sleep(options.debug_delay) @@ -507,6 +523,9 @@ if args: for crash_log_file in args: crash_log = CrashLog(crash_log_file) + if crash_log.error: + print crash_log.error + return if options.verbose: crash_log.dump() if not crash_log.images: From gclayton at apple.com Fri Jan 20 23:10:20 2012 From: gclayton at apple.com (Greg Clayton) Date: Sat, 21 Jan 2012 05:10:20 -0000 Subject: [Lldb-commits] [lldb] r148627 - /lldb/trunk/examples/python/crashlog.py Message-ID: <20120121051020.D1B112A6C12C@llvm.org> Author: gclayton Date: Fri Jan 20 23:10:20 2012 New Revision: 148627 URL: http://llvm.org/viewvc/llvm-project?rev=148627&view=rev Log: Added options to specify how many instructions before and after the frame PC to disassemble. Users can also specify the frame depth to disassemble to and also if disassembly should happen for all threads. Modified: lldb/trunk/examples/python/crashlog.py Modified: lldb/trunk/examples/python/crashlog.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/python/crashlog.py?rev=148627&r1=148626&r2=148627&view=diff ============================================================================== --- lldb/trunk/examples/python/crashlog.py (original) +++ lldb/trunk/examples/python/crashlog.py Fri Jan 20 23:10:20 2012 @@ -420,7 +420,7 @@ return None # success return 'error: unable to locate any executables from the crash log' -def disassemble_instructions (instructions, pc, insts_before_pc, insts_after_pc): +def disassemble_instructions (instructions, pc, options, non_zeroeth_frame): lines = list() pc_index = -1 comment_column = 50 @@ -440,11 +440,19 @@ lines[-1] += "; %s" % comment if pc_index >= 0: - if pc_index >= insts_before_pc: - start_idx = pc_index - insts_before_pc + # If we are disassembling the non-zeroeth frame, we need to backup the PC by 1 + if non_zeroeth_frame and pc_index > 0: + pc_index = pc_index - 1 + if options.disassemble_before == -1: + start_idx = 0 else: + start_idx = pc_index - options.disassemble_before + if start_idx < 0: start_idx = 0 - end_idx = pc_index + insts_after_pc + if options.disassemble_before == -1: + end_idx = inst_idx + else: + end_idx = pc_index + options.disassemble_after if end_idx > inst_idx: end_idx = inst_idx for i in range(start_idx, end_idx+1): @@ -499,12 +507,16 @@ be disassembled and lookups can be performed using the addresses found in the crash log.''' parser = optparse.OptionParser(description=description, prog='crashlog.py',usage=usage) parser.add_option('--platform', type='string', metavar='platform', dest='platform', help='specify one platform by name') - parser.add_option('--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) + parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) parser.add_option('--no-images', action='store_false', dest='show_images', help='don\'t show images in stack frames', default=True) - parser.add_option('--load-all', action='store_true', dest='load_all_images', help='load all executable images, not just the images found in the crashed stack frames', default=False) + parser.add_option('-a', '--load-all', action='store_true', dest='load_all_images', help='load all executable images, not just the images found in the crashed stack frames', default=False) parser.add_option('--image-list', action='store_true', dest='dump_image_list', help='show image list', default=False) - parser.add_option('--debug-delay', type='int', dest='debug_delay', metavar='NSEC', help='pause for NSEC seconds for debugger', default=0) - parser.add_option('--crashed-only', action='store_true', dest='crashed_only', help='only symbolicate the crashed thread', default=False) + parser.add_option('-g', '--debug-delay', type='int', dest='debug_delay', metavar='NSEC', help='pause for NSEC seconds for debugger', default=0) + parser.add_option('-c', '--crashed-only', action='store_true', dest='crashed_only', help='only symbolicate the crashed thread', default=False) + parser.add_option('-d', '--disasm-depth', type='int', dest='disassemble_depth', help='set the depth in stack frames that should be disassembled (default is 1)', default=1) + parser.add_option('-D', '--disasm-all', action='store_true', dest='disassemble_all_threads', help='enabled disassembly of frames on all threads (not just the crashed thread)', default=False) + parser.add_option('-B', '--disasm-before', type='int', dest='disassemble_before', help='the number of instructions to disassemble before the frame PC', default=4) + parser.add_option('-A', '--disasm-after', type='int', dest='disassemble_after', help='the number of instructions to disassemble after the frame PC', default=4) loaded_addresses = False try: (options, args) = parser.parse_args(command_args) @@ -652,6 +664,7 @@ line_entry = frame.sym_ctx.GetLineEntry() symbol = frame.sym_ctx.GetSymbol() inlined_block = block.GetContainingInlinedBlock(); + disassemble = (this_thread_crashed or options.disassemble_all_threads) and frame_idx < options.disassemble_depth; if inlined_block: function_name = inlined_block.GetInlinedName(); block_range_idx = inlined_block.GetRangeIndexForBlockAddress (lldb.target.ResolveLoadAddress (frame.pc)) @@ -660,17 +673,17 @@ function_start_load_addr = block_range_start_addr.GetLoadAddress (lldb.target) else: function_start_load_addr = frame.pc - if this_thread_crashed and frame_idx == 0: + if disassemble: instructions = function.GetInstructions(lldb.target) elif function: function_name = function.GetName() function_start_load_addr = function.GetStartAddress().GetLoadAddress (lldb.target) - if this_thread_crashed and frame_idx == 0: + if disassemble: instructions = function.GetInstructions(lldb.target) elif symbol: function_name = symbol.GetName() function_start_load_addr = symbol.GetStartAddress().GetLoadAddress (lldb.target) - if this_thread_crashed and frame_idx == 0: + if disassemble: instructions = symbol.GetInstructions(lldb.target) if function_name: @@ -708,7 +721,7 @@ prev_frame_index = frame.index if instructions: print - disassemble_instructions (instructions, frame.pc, 4, 4) + disassemble_instructions (instructions, frame.pc, options, frame.index > 0) print print From gclayton at apple.com Sat Jan 21 20:55:09 2012 From: gclayton at apple.com (Greg Clayton) Date: Sun, 22 Jan 2012 02:55:09 -0000 Subject: [Lldb-commits] [lldb] r148650 - in /lldb/trunk: examples/python/cmdtemplate.py www/build.html www/customization.html www/download.html www/features.html www/formats.html www/python-faq.html www/sidebar.incl Message-ID: <20120122025509.36F0C2A6C12C@llvm.org> Author: gclayton Date: Sat Jan 21 20:55:08 2012 New Revision: 148650 URL: http://llvm.org/viewvc/llvm-project?rev=148650&view=rev Log: Added a python FAQ page with detailed examples of how to add python functions to breakpoints, creating new LLDB commands using python modules and also how to run scripts from the command line. Added: lldb/trunk/examples/python/cmdtemplate.py lldb/trunk/www/python-faq.html (with props) Modified: lldb/trunk/www/build.html lldb/trunk/www/customization.html lldb/trunk/www/download.html lldb/trunk/www/features.html lldb/trunk/www/formats.html lldb/trunk/www/sidebar.incl Added: lldb/trunk/examples/python/cmdtemplate.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/python/cmdtemplate.py?rev=148650&view=auto ============================================================================== --- lldb/trunk/examples/python/cmdtemplate.py (added) +++ lldb/trunk/examples/python/cmdtemplate.py Sat Jan 21 20:55:08 2012 @@ -0,0 +1,49 @@ +#!/usr/bin/python + +#---------------------------------------------------------------------- +# Be sure to add the python path that points to the LLDB shared library. +# +# To use this in the embedded python interpreter using "lldb": +# % cd /path/containing/cmdtemplate.py +# % lldb +# (lldb) script import cmdtemplate +# +# For the shells csh, tcsh: +# ( setenv PYTHONPATH /path/to/LLDB.framework/Resources/Python ; ./cmdtemplate.py ) +# +# For the shells sh, bash: +# PYTHONPATH=/path/to/LLDB.framework/Resources/Python ./cmdtemplate.py +#---------------------------------------------------------------------- + +import lldb +import commands +import optparse +import shlex + +def ls(debugger, command, result, dict): + command_args = shlex.split(command) + usage = "usage: %prog [options] [PATH ...]" + description='''This command lets you run the /bin/ls command from within lldb as a quick and easy example.''' + parser = optparse.OptionParser(description=description, prog='ls',usage=usage) + parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) + try: + (options, args) = parser.parse_args(command_args) + except: + return + + for arg in args: + if options.verbose: + print commands.getoutput('/bin/ls "%s"' % arg) + else: + print commands.getoutput('/bin/ls -lAF "%s"' % arg) + +if __name__ == '__main__': + # This script is being run from the command line, create a debugger in case we are + # going to use any debugger functions in our function. + lldb.debugger = lldb.SBDebugger.Create() + ls (sys.argv) +elif lldb.debugger: + # This script is being run from LLDB in the emabedded command interpreter + # Add any commands contained in this module to LLDB + lldb.debugger.HandleCommand('command script add -f cmdtemplate.ls ls') + print '"ls" command installed, type "ls --help" for detailed help' Modified: lldb/trunk/www/build.html URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/www/build.html?rev=148650&r1=148649&r2=148650&view=diff ============================================================================== --- lldb/trunk/www/build.html (original) +++ lldb/trunk/www/build.html Sat Jan 21 20:55:08 2012 @@ -3,7 +3,7 @@ -LLDB FAQ +Building LLDB Modified: lldb/trunk/www/customization.html URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/www/customization.html?rev=148650&r1=148649&r2=148650&view=diff ============================================================================== --- lldb/trunk/www/customization.html (original) +++ lldb/trunk/www/customization.html Sat Jan 21 20:55:08 2012 @@ -3,7 +3,7 @@ -Customization +LLDB Customization Modified: lldb/trunk/www/download.html URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/www/download.html?rev=148650&r1=148649&r2=148650&view=diff ============================================================================== --- lldb/trunk/www/download.html (original) +++ lldb/trunk/www/download.html Sat Jan 21 20:55:08 2012 @@ -3,7 +3,7 @@ -LLDB FAQ +Downloading LLDB Sources Modified: lldb/trunk/www/features.html URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/www/features.html?rev=148650&r1=148649&r2=148650&view=diff ============================================================================== --- lldb/trunk/www/features.html (original) +++ lldb/trunk/www/features.html Sat Jan 21 20:55:08 2012 @@ -3,7 +3,7 @@ -LLDB Homepage +LLDB Features Modified: lldb/trunk/www/formats.html URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/www/formats.html?rev=148650&r1=148649&r2=148650&view=diff ============================================================================== --- lldb/trunk/www/formats.html (original) +++ lldb/trunk/www/formats.html Sat Jan 21 20:55:08 2012 @@ -3,7 +3,7 @@ -LLDB Homepage +LLDB Stack and Frame Formats Added: lldb/trunk/www/python-faq.html URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/www/python-faq.html?rev=148650&view=auto ============================================================================== --- lldb/trunk/www/python-faq.html (added) +++ lldb/trunk/www/python-faq.html Sat Jan 21 20:55:08 2012 @@ -0,0 +1,421 @@ + + + + + +LLDB Python FAQ + + + +
+ LLDB Python FAQ +
+ +
+
+ +
+
+

Introduction

+
+ +

The entire LLDB API is available through a script bridging interface in Python. Python can be used + as an embedded script interpreter, or it can be used directly from python at the command line.

+ +
+ + +
+

Embedded Python Interpreter

+
+ +

The embedded python interpreter can be accessed in a variety of way from within LLDB. The + easiest way is to type script command prompt:

+
(lldb) script
+Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
+>>> 2+3
+5
+>>> hex(12345)
+'0x3039'
+>>> 
+
+ +

This drops you into the embedded python interpreter. There are a some convenience variables + that are set for you in the lldb python module that refer to the current program + and debugger state:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VariableTypeDescription
+ lldb.debugger + + lldb.SBDebugger + + A module global variable containing the current debugger object. + The type is a lldb.SBDebugger object and it contains a reference to the debegger + object that owns the command interpreter and all targets in your debug session. +
+ lldb.target + + lldb.SBTarget + + A module global variable containing the currently selected target. + The type is a lldb.SBTarget object and the object will only be valid if there is a current target. + The target select <target-index> commmand can be used to change the + currently selected target. +
+ lldb.process + + lldb.SBProcess + + A module global variable containing the current process. + The type is a lldb.SBProcess object and the object will only be + valid if there is a current target and that target has a process. +
+ lldb.thread + + lldb.SBThread + + A module global variable containing the current thread. + The type is a lldb.SBThread object and the object will only be valid if + the process has threads, and if the process has a thread selected. + A thread is always selected in the command interpreter when a target stops. + The thread select <thread-index> commmand can be used to change the + currently selected thread. +
+ lldb.frame + + lldb.SBFrame + + A module global variable containing the current stack frame. + The type is a lldb.SBFrame object and the object will only be valid if + the thread is stopped and has a frame selected. + A stack frame is always selected in the command interpreter when a target stops. + The frame select <frame-index> commmand can be used to change the + currently selected thread. +
+ +

One in the embedded interpreter, these objects can be used. Almost all of the lldb.SB objects + are able to briefly describe themselves by printing them: +

(lldb) script
+Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
+>>> print lldb.debugger
+Debugger (instance: "debugger_1", id: 1)
+>>> print lldb.target
+a.out
+>>> print lldb.process
+SBProcess: pid = 59289, state = stopped, threads = 1, executable = a.out
+>>> print lldb.thread
+SBThread: tid = 0x1f03
+>>> print lldb.frame
+frame #0: 0x0000000100000bb6 a.out main + 54 at main.c:16
+
+ +
+ + +
+
+

Running a Python script when a breakpoint gets hit

+
+ +

A python script can be run when a breakpoint gets hit. Adding python + scripts to breakpoints provides a way to create complex breakpoint + conditions and also allows for smart logging and data gathering.

+

A python function gets run when a breakpoint, and this function has + two arguments:

+

+

def breakpoint_function(frame, bp_loc):
+  # Your code goes here
+
+

+ + + + + + + + + + + + + + + + +
ArgumentTypeDescription
+ frame + + lldb.SBFrame + + The current stack frame where the breakpoint got hit. + The type is a lldb.SBFrame object and the object will always be valid. + This frame argument might not match the currently selected stack frame found in the lldb module global variable lldb.frame. +
+ bp_loc + + lldb.SBBreakpointLocation + + The breakpoint location that just got hit. Breakpoints are represented by lldb.SBBreakpoint + objects. These breakpoint objects can have one or more locations. These locations + are represented by lldb.SBBreakpointLocation objects. +
+

Now we are ready to create a python function and attach it to a breakpoint. The following example will wllow you to + create an order file for a shared library. We do this by setting a regular exprsssion breakpoint + at every function in a shared library. The regular expression we will use is '.' which will match + any function that has at least any character in the function name. + This will result in one lldb.SBBreakpoint object + that contains many lldb.SBBreakpointLocation objects. As the breakpoint continually gets + hit, we use the hit count on the main lldb.SBBreakpoint to tell us the breakpoint hit + number, and we disable the location (not the main breakpoint) on the lldb.SBBreakpointLocation + object. Then we log some info and continue the process. +

(lldb) breakpoint set --func-regex=. --shlib=libfoo.dylib
+Breakpoint created: 1: regex = '.', module = libfoo.dylib, locations = 223
+(lldb) breakpoint command add --script-type python 1
+Enter your Python command(s). Type 'DONE' to end.
+> # Get the hit count of the main breakpoint
+> hit_count = bp_loc.GetBreakpoint().GetHitCount()
+> # Get the name of the function
+> name = frame.GetFunctionName()
+> # Print the order and the function name
+> print '[%i] %s' % (hit_count, name)
+> # Disable the current breakpoint location so it doesn't get hit again
+> bp_loc.SetEnabled(False)
+> # How continue the process
+> frame.GetThread().GetProcess().Continue()
+> DONE
+
+

The breakpoint command add command above attaches a python script to breakpoint 1. + To remove the breakpoint command: +

(lldb) breakpoint command delete 1 +

+
+
+

Create a new LLDB command using a python function

+
+ +

Python functions can be used to create new commands that the LLDB command interpreter + doesn't have. This provides a very flexible and easy way to extend LLDB to meet your + debugging requirements.

+

A python function that implements a new LDB command has four arguments:

+

+ def Symbolicate(debugger, command, result, dict): + SymbolicateCrashLog (command.split()) + +

def command_function(debugger, command, result, dict):
+          # Your code goes here
+        
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentTypeDescription
+ debugger + + lldb.SBDebugger + + The current debugger object. +
+ command + + python string + + A python string containing all arguments for your command. If you need to chop up the arguments + try using the shlex module's shlex.split(command) to properly extract the + arguments. +
+ result + + lldb.SBCommandReturnObject + + A return object where you can indicate the success or failure of your command. You can also + provide information for the command result by printing data into it. You can also just print + data as you normally would in a python script and the outout will show up. +
+ dict + + python dict object + + The dictionary for the current embedded script session which contains all variables + and functions. +
+

Now we can create a module called ls.py that will implement a function that + can be used by LLDB's python command code:

+ +
#!/usr/bin/python
+
+import lldb
+import commands
+import optparse
+import shlex
+
+def ls(debugger, command, result, dict):
+    print commands.getoutput('/bin/ls %s' % command)
+
+# Any code that isn't in a function in python gets run when the module is loaded
+if lldb.debugger:
+    # This script is being run from LLDB in the emabedded command interpreter
+    # lets register the 'ls' command with the command interpreter automatically!
+    lldb.debugger.HandleCommand('command script add -f ls.ls ls')
+    print 'The "ls" python command has been installed and is ready for use.'
+
+

Now we can load the module into LLDB and use it

+
% lldb
+(lldb) script import ls
+The "ls" python command has been installed and is ready for use.
+(lldb) ls -l /tmp/
+total 365848
+-rw-r--r--@  1 someuser  wheel         6148 Jan 19 17:27 .DS_Store
+-rw-------   1 someuser  wheel         7331 Jan 19 15:37 crash.log
+
+

A template has been created in the source repository that can help you to create + lldb command quickly:

+ cmdtemplate.py +
+
+

Using the lldb.py module in python

+
+ +

LLDB has all of its core code build into a shared library which gets + used by the lldb command line application. On Mac OS X this + shared library is a framework: LLDB.framework and on other + unix variants the program is a shared library lldb.so. The + LLDB.framework contains the lldb.py module and you will + need to tell python where to look in order to find this module. This + is done by setting the PYTHONPATH environment variable contain + a path to the directory that contains the lldb.py python module: + +

For csh and tcsh:

+

% setenv PYTHONPATH /Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python

+

For sh and bash: +

% export PYTHONPATH=/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python

+ +

+ Now your python scripts are ready to import the lldb module. Below is a + python script that will launch a program from the current working directory + called "a.out", set a breakpoint at "main", and then run and hit the breakpoint, + and print the process, thread and frame objects if the process stopped: + +

+
#!/usr/bin/python
+
+import lldb
+
+# Set the path to the executable to debug
+exe = "./a.out"
+
+# Create a new debugger instance
+debugger = lldb.SBDebugger.Create()
+
+# When we step or continue, don't return from the function until the process 
+# stops. We do this by setting the async mode to false.
+debugger.SetAsync (False)
+
+# Create a target from a file and arch
+print "Creating a target for '%s'" % exe
+
+target = debugger.CreateTargetWithFileAndArch (exe, lldb.LLDB_ARCH_DEFAULT)
+
+if target:
+    # If the target is valid set a breakpoint at main
+    main_bp = target.BreakpointCreateByName ("main", target.GetExecutable().GetFilename());
+
+    print main_bp
+
+    # Launch the process. Since we specified synchronous mode, we won't return
+    # from this function until we hit the breakpoint at main
+    process = target.LaunchSimple (None, None, os.getcwd())
+    
+    # Make sure the launch went ok
+    if process:
+        # Print some simple process info
+        state = process.GetState ()
+        print process
+        if state == lldb.eStateStopped:
+        # Get the first thread
+        thread = process.GetThreadAtIndex (0)
+        if thread:
+            # Print some simple thread info
+            print thread
+            # Get the first frame
+            frame = thread.GetFrameAtIndex (0)
+            if frame:
+                # Print some simple frame info
+                print frame
+                function = frame.GetFunction()
+                # See if we have debug info (a function)
+                if function:
+                    # We do have a function, print some info for the function
+                    print function
+                    # Now get all instructions for this function and print them
+                    insts = function.GetInstructions(target)
+                    disassemble_instructions (insts)
+                else:
+                    # See if we have a symbol in the symbol table for where we stopped
+                    symbol = frame.GetSymbol();
+                    if symbol:
+                        # We do have a symbol, print some info for the symbol
+                        print symbol
+
+
+ + +
+
+
+ + Propchange: lldb/trunk/www/python-faq.html ------------------------------------------------------------------------------ svn:executable = * Modified: lldb/trunk/www/sidebar.incl URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/www/sidebar.incl?rev=148650&r1=148649&r2=148650&view=diff ============================================================================== --- lldb/trunk/www/sidebar.incl (original) +++ lldb/trunk/www/sidebar.incl Sat Jan 21 20:55:08 2012 @@ -20,8 +20,10 @@
  • FAQ
  • Frame and Thread Formatting
  • LLDB and GDB
  • +
  • Python FAQ
  • Python Scripting
  • Tutorial
  • +
  • Variable Formatting