Compare commits
1 Commits
clang-arm-
...
lldb-2
| Author | SHA1 | Date | |
|---|---|---|---|
| 41f05bd8d7 |
17
README.md
17
README.md
@@ -1,17 +0,0 @@
|
||||
# Build MINIX/arm with clang
|
||||
|
||||
It is now possible to build a full minix distribution for BeaglBone White/Black and BeagleBoardxM using clang instead of GCC.
|
||||
|
||||
This also add support to run the Kuya tests on ARM, which was not possible when GCC was used, because of problems in the C++ exception handling.
|
||||
|
||||
## Known Bugs
|
||||
|
||||
The following tests still fails:
|
||||
1. 53: Division by zero does not trigger exceptions
|
||||
2. 75: ru.tv_secs can't be zero (and is zero)
|
||||
3. 85: hangs
|
||||
4. isofs: Fails because of an out of memory condition
|
||||
5. vnd: crash
|
||||
6. Running two times the kyua tests in a row, without rebooting in between will lead to a mostly failed second run because of copy-on-write errors.
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $NetBSD: cat.c,v 1.57 2016/06/16 00:52:37 sevan Exp $ */
|
||||
/* $NetBSD: cat.c,v 1.55 2015/07/25 16:17:01 sevan Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
@@ -44,7 +44,7 @@ __COPYRIGHT(
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)cat.c 8.2 (Berkeley) 4/27/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: cat.c,v 1.57 2016/06/16 00:52:37 sevan Exp $");
|
||||
__RCSID("$NetBSD: cat.c,v 1.55 2015/07/25 16:17:01 sevan Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@@ -113,7 +113,6 @@ main(int argc, char *argv[])
|
||||
vflag = 1;
|
||||
break;
|
||||
default:
|
||||
case '?':
|
||||
(void)fprintf(stderr,
|
||||
"Usage: %s [-beflnstuv] [-B bsize] [-] "
|
||||
"[file ...]\n", getprogname());
|
||||
@@ -175,16 +174,18 @@ cook_buf(FILE *fp)
|
||||
line = gobble = 0;
|
||||
for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
|
||||
if (prev == '\n') {
|
||||
if (sflag) {
|
||||
if (ch == '\n') {
|
||||
if (gobble)
|
||||
continue;
|
||||
if (ch == '\n') {
|
||||
if (sflag) {
|
||||
if (!gobble && nflag && !bflag)
|
||||
(void)fprintf(stdout,
|
||||
"%6d\t\n", ++line);
|
||||
else if (!gobble && putchar(ch) == EOF)
|
||||
break;
|
||||
gobble = 1;
|
||||
} else
|
||||
gobble = 0;
|
||||
continue;
|
||||
}
|
||||
if (nflag) {
|
||||
if (!bflag || ch != '\n') {
|
||||
if (!bflag) {
|
||||
(void)fprintf(stdout,
|
||||
"%6d\t", ++line);
|
||||
if (ferror(stdout))
|
||||
@@ -196,7 +197,13 @@ cook_buf(FILE *fp)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (nflag) {
|
||||
(void)fprintf(stdout, "%6d\t", ++line);
|
||||
if (ferror(stdout))
|
||||
break;
|
||||
}
|
||||
}
|
||||
gobble = 0;
|
||||
if (ch == '\n') {
|
||||
if (eflag)
|
||||
if (putchar('$') == EOF)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: chmod.1,v 1.26 2016/08/11 00:10:42 sevan Exp $
|
||||
.\" $NetBSD: chmod.1,v 1.25 2013/12/17 09:54:08 apb Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1989, 1990, 1993, 1994
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
@@ -32,7 +32,7 @@
|
||||
.\"
|
||||
.\" @(#)chmod.1 8.4 (Berkeley) 3/31/94
|
||||
.\"
|
||||
.Dd August 11, 2016
|
||||
.Dd October 22, 2012
|
||||
.Dt CHMOD 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -304,11 +304,6 @@ compatible with the exception of the
|
||||
symbol
|
||||
.Dq t
|
||||
which is not included in that standard.
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
utility appeared in
|
||||
.At v1 .
|
||||
.Sh BUGS
|
||||
There's no
|
||||
.Ar perm
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: cp.1,v 1.45 2016/08/11 00:17:23 sevan Exp $
|
||||
.\" $NetBSD: cp.1,v 1.44 2015/06/28 16:22:54 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1989, 1990, 1993, 1994
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
@@ -32,7 +32,7 @@
|
||||
.\"
|
||||
.\" @(#)cp.1 8.3 (Berkeley) 4/18/94
|
||||
.\"
|
||||
.Dd August 11, 2016
|
||||
.Dd March 25, 2012
|
||||
.Dt CP 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -255,8 +255,3 @@ The
|
||||
.Fl v
|
||||
option is an extension to
|
||||
.St -p1003.2 .
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
utility appeared in
|
||||
.At v1 .
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: csh.1,v 1.53 2016/08/10 17:16:47 sevan Exp $
|
||||
.\" $NetBSD: csh.1,v 1.52 2013/01/22 21:20:26 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1980, 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
@@ -29,7 +29,7 @@
|
||||
.\"
|
||||
.\" @(#)csh.1 8.2 (Berkeley) 1/21/94
|
||||
.\"
|
||||
.Dd August 8, 2016
|
||||
.Dd January 22, 2013
|
||||
.Dt CSH 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -2233,7 +2233,7 @@ substitutions on a single line to 20.
|
||||
.Sh HISTORY
|
||||
.Nm
|
||||
appeared in
|
||||
.Bx 2 .
|
||||
.Bx 3 .
|
||||
It was a first implementation of a command language interpreter
|
||||
incorporating a history mechanism (see
|
||||
.Sx History substitutions ) ,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: date.1,v 1.44 2017/01/03 16:01:05 abhinav Exp $
|
||||
.\" $NetBSD: date.1,v 1.42 2012/04/06 11:36:56 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1980, 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
@@ -32,7 +32,7 @@
|
||||
.\"
|
||||
.\" @(#)date.1 8.3 (Berkeley) 4/28/95
|
||||
.\"
|
||||
.Dd August 11, 2016
|
||||
.Dd November 15, 2006
|
||||
.Dt DATE 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -148,7 +148,7 @@ The hour of the day, from 00 to 23.
|
||||
.It Ar MM
|
||||
The minute of the hour, from 00 to 59.
|
||||
.It Ar SS
|
||||
The second of the minute, from 00 to 60.
|
||||
The second of the minute, from 00 to 61.
|
||||
.El
|
||||
.Pp
|
||||
Everything but the minutes is optional.
|
||||
@@ -244,8 +244,3 @@ The
|
||||
.Nm
|
||||
utility is expected to be compatible with
|
||||
.St -p1003.2 .
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
utility appeared in
|
||||
.At v1 .
|
||||
|
||||
12
bin/dd/dd.1
12
bin/dd/dd.1
@@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: dd.1,v 1.32 2016/08/18 22:43:49 sevan Exp $
|
||||
.\" $NetBSD: dd.1,v 1.27 2015/03/18 13:30:13 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
@@ -32,7 +32,7 @@
|
||||
.\"
|
||||
.\" @(#)dd.1 8.2 (Berkeley) 1/13/94
|
||||
.\"
|
||||
.Dd August 18, 2016
|
||||
.Dd March 18, 2015
|
||||
.Dt DD 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -209,7 +209,7 @@ in order to output to a nonexistent file.
|
||||
The default or specified value is or'ed with
|
||||
.Va rdwr
|
||||
for a first
|
||||
.Xr open 2
|
||||
.Xt open 2
|
||||
attempt, then on failure with
|
||||
.Va wronly
|
||||
on a second attempt.
|
||||
@@ -486,6 +486,7 @@ To print summary information in human-readable form:
|
||||
.Pp
|
||||
To customize the information summary output and print it through
|
||||
.Xr unvis 3 :
|
||||
.Pp
|
||||
.Bd -literal -offset indent
|
||||
dd if=/dev/zero of=/dev/null count=1 \e
|
||||
msgfmt='speed:%E, in %s seconds\en' 2\*[Gt]\*[Am]1 | unvis
|
||||
@@ -515,8 +516,3 @@ and
|
||||
values are extensions to the
|
||||
.Tn POSIX
|
||||
standard.
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
utility appeared in
|
||||
.At v5 .
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: df.1,v 1.46 2016/08/10 23:48:14 sevan Exp $
|
||||
.\" $NetBSD: df.1,v 1.44 2010/04/05 21:17:28 joerg Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1989, 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
@@ -29,7 +29,7 @@
|
||||
.\"
|
||||
.\" @(#)df.1 8.2 (Berkeley) 1/13/92
|
||||
.\"
|
||||
.Dd August 10, 2016
|
||||
.Dd March 4, 2008
|
||||
.Dt DF 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -203,4 +203,4 @@ size block.
|
||||
A
|
||||
.Nm
|
||||
utility appeared in
|
||||
.At v1 .
|
||||
.At v6 .
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: echo.1,v 1.15 2016/08/14 22:59:22 sevan Exp $
|
||||
.\" $NetBSD: echo.1,v 1.13 2003/08/07 09:05:12 agc Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
@@ -32,7 +32,7 @@
|
||||
.\"
|
||||
.\" @(#)echo.1 8.1 (Berkeley) 7/22/93
|
||||
.\"
|
||||
.Dd August 14, 2016
|
||||
.Dd July 22, 1993
|
||||
.Dt ECHO 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -66,8 +66,3 @@ The
|
||||
utility is expected to be
|
||||
.St -p1003.2
|
||||
compatible.
|
||||
.Sh HISTORY
|
||||
An
|
||||
.Nm
|
||||
utility appeared in
|
||||
.At v2 .
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: expr.1,v 1.36 2016/08/23 20:34:23 sevan Exp $
|
||||
.\" $NetBSD: expr.1,v 1.33 2012/08/12 17:27:04 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2000,2003 The NetBSD Foundation, Inc.
|
||||
.\" All rights reserved.
|
||||
@@ -27,7 +27,7 @@
|
||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd August 23, 2016
|
||||
.Dd April 20, 2004
|
||||
.Dt EXPR 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -214,7 +214,7 @@ treat it as a delimiter to mark the end of command
|
||||
line options, and ignore it.
|
||||
Some
|
||||
.Nm
|
||||
implementations do not recognize it at all; others
|
||||
implementations don't recognize it at all; others
|
||||
might ignore it even in cases where doing so results in syntax
|
||||
error.
|
||||
There should be same result for both following examples,
|
||||
@@ -242,28 +242,15 @@ The
|
||||
.Ar length
|
||||
keyword is an extension for compatibility with GNU
|
||||
.Nm .
|
||||
.Sh HISTORY
|
||||
An
|
||||
.Nm
|
||||
utility first appeared in the Programmer's Workbench (PWB/UNIX).
|
||||
A public domain version of
|
||||
.Nm
|
||||
written by
|
||||
.An Pace Willisson
|
||||
.Aq pace@blitz.com
|
||||
appeared in
|
||||
.Bx 386 0.1 .
|
||||
.Sh AUTHORS
|
||||
Initial implementation by
|
||||
.An Pace Willisson Aq Mt pace@blitz.com
|
||||
was largely rewritten by
|
||||
.An -nosplit
|
||||
.An J.T. Conklin Aq Mt jtc@NetBSD.org .
|
||||
It was rewritten again for
|
||||
Original implementation was written by
|
||||
.An J.T. Conklin
|
||||
.Aq jtc@NetBSD.org .
|
||||
It was rewritten for
|
||||
.Nx 1.6
|
||||
by
|
||||
.An -nosplit
|
||||
.An Jaromir Dolecek Aq Mt jdolecek@NetBSD.org .
|
||||
.An Jaromir Dolecek
|
||||
.Aq jdolecek@NetBSD.org .
|
||||
.Sh NOTES
|
||||
The empty string
|
||||
.Do Dc
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: kill.1,v 1.28 2017/04/22 23:01:36 christos Exp $
|
||||
.\" $NetBSD: kill.1,v 1.22 2012/03/22 07:58:17 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1980, 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
@@ -32,7 +32,7 @@
|
||||
.\"
|
||||
.\" @(#)kill.1 8.2 (Berkeley) 4/28/95
|
||||
.\"
|
||||
.Dd April 22, 2017
|
||||
.Dd April 28, 1995
|
||||
.Dt KILL 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -63,6 +63,7 @@ by the pid operand(s).
|
||||
Only the super-user may send signals to other users' processes.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Pp
|
||||
.Bl -tag -width Ds
|
||||
.It Fl s Ar signal_name
|
||||
A symbolic signal name specifying the signal to be sent instead of the
|
||||
@@ -103,9 +104,6 @@ belonging to the user.
|
||||
.Pp
|
||||
Some of the more commonly used signals:
|
||||
.Bl -tag -width Ds -compact
|
||||
.It 0
|
||||
0 (does not affect the process; can be used to test whether the
|
||||
process exists)
|
||||
.It 1
|
||||
HUP (hang up)
|
||||
.It 2
|
||||
@@ -132,8 +130,6 @@ arguments.
|
||||
See
|
||||
.Xr csh 1
|
||||
for details.
|
||||
.Sh DIAGNOSTICS
|
||||
.Ex -std
|
||||
.Sh SEE ALSO
|
||||
.Xr csh 1 ,
|
||||
.Xr pgrep 1 ,
|
||||
@@ -145,12 +141,11 @@ for details.
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
utility is expected to be
|
||||
function is expected to be
|
||||
.St -p1003.2
|
||||
compatible.
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
command appeared in
|
||||
.At v3
|
||||
in section 8 of the manual.
|
||||
.At v6 .
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: ls.1,v 1.79 2016/08/10 17:45:12 sevan Exp $
|
||||
.\" $NetBSD: ls.1,v 1.78 2014/10/18 01:49:01 jschauma Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1980, 1990, 1991, 1993, 1994
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
@@ -32,7 +32,7 @@
|
||||
.\"
|
||||
.\" @(#)ls.1 8.7 (Berkeley) 7/29/94
|
||||
.\"
|
||||
.Dd August 10, 2016
|
||||
.Dd October 17, 2014
|
||||
.Dt LS 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -513,4 +513,4 @@ specification.
|
||||
An
|
||||
.Nm
|
||||
utility appeared in
|
||||
.At v1 .
|
||||
.At v5 .
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: mkdir.1,v 1.19 2016/08/10 18:42:00 sevan Exp $
|
||||
.\" $NetBSD: mkdir.1,v 1.17 2012/03/22 07:58:17 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1989, 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
@@ -32,7 +32,7 @@
|
||||
.\"
|
||||
.\" @(#)mkdir.1 8.2 (Berkeley) 1/25/94
|
||||
.\"
|
||||
.Dd August 10, 2016
|
||||
.Dd January 25, 1994
|
||||
.Dt MKDIR 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -92,8 +92,3 @@ The
|
||||
utility is expected to be
|
||||
.St -p1003.2
|
||||
compatible.
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
utility appeared in
|
||||
.At v1 .
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: mv.1,v 1.28 2016/08/10 18:08:14 sevan Exp $
|
||||
.\" $NetBSD: mv.1,v 1.26 2012/03/22 07:58:17 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1989, 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
@@ -32,7 +32,7 @@
|
||||
.\"
|
||||
.\" @(#)mv.1 8.1 (Berkeley) 5/31/93
|
||||
.\"
|
||||
.Dd August 10, 2016
|
||||
.Dd December 26, 2002
|
||||
.Dt MV 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -144,8 +144,3 @@ The
|
||||
.Fl v
|
||||
option is an extension to
|
||||
.St -p1003.2 .
|
||||
.Sh HISTORY
|
||||
An
|
||||
.Nm
|
||||
utility appeared in
|
||||
.At v1 .
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: cpio.1,v 1.14 2015/12/19 18:48:33 wiz Exp $
|
||||
.\" $NetBSD: cpio.1,v 1.13 2011/06/19 07:34:24 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1997 SigmaSoft, Th. Lockert
|
||||
.\" All rights reserved.
|
||||
@@ -297,8 +297,7 @@ specific archive format specification.
|
||||
.Xr pax 1 ,
|
||||
.Xr tar 1
|
||||
.Sh AUTHORS
|
||||
.An Keith Muller
|
||||
at the University of California, San Diego.
|
||||
Keith Muller at the University of California, San Diego.
|
||||
.Sh BUGS
|
||||
The
|
||||
.Fl s
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: pwd.1,v 1.25 2016/08/12 02:03:26 sevan Exp $
|
||||
.\" $NetBSD: pwd.1,v 1.24 2003/10/30 14:58:23 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
@@ -32,7 +32,7 @@
|
||||
.\"
|
||||
.\" @(#)pwd.1 8.2 (Berkeley) 4/28/95
|
||||
.\"
|
||||
.Dd August 12, 2016
|
||||
.Dd October 30, 2003
|
||||
.Dt PWD 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -87,11 +87,6 @@ except that the default is
|
||||
.Fl P
|
||||
not
|
||||
.Fl L .
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
utility appeared in
|
||||
.At v5 .
|
||||
.Sh BUGS
|
||||
In
|
||||
.Xr csh 1
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: rm.1,v 1.28 2016/08/12 02:26:42 sevan Exp $
|
||||
.\" $NetBSD: rm.1,v 1.27 2013/04/26 19:34:34 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1990, 1993, 1994, 2003
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
@@ -32,7 +32,7 @@
|
||||
.\"
|
||||
.\" @(#)rm.1 8.5 (Berkeley) 12/5/94
|
||||
.\"
|
||||
.Dd August 12, 2016
|
||||
.Dd April 26, 2013
|
||||
.Dt RM 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -190,11 +190,6 @@ magnetic disk.
|
||||
.Em Because these requirements are not met, the
|
||||
.Fl P
|
||||
.Em option does not conform to the standard .
|
||||
.Sh HISTORY
|
||||
An
|
||||
.Nm
|
||||
utility appeared in
|
||||
.At v1 .
|
||||
.Sh BUGS
|
||||
The
|
||||
.Fl P
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: rmdir.1,v 1.16 2016/08/12 02:30:37 sevan Exp $
|
||||
.\" $NetBSD: rmdir.1,v 1.15 2003/08/07 09:05:29 agc Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
@@ -32,7 +32,7 @@
|
||||
.\"
|
||||
.\" @(#)rmdir.1 8.1 (Berkeley) 5/31/93
|
||||
.\"
|
||||
.Dd August 12, 2016
|
||||
.Dd May 31, 1993
|
||||
.Dt RMDIR 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -88,8 +88,3 @@ The
|
||||
utility is expected to be
|
||||
.St -p1003.2
|
||||
compatible.
|
||||
.Sh HISTORY
|
||||
An
|
||||
.Nm
|
||||
utility appeared in
|
||||
.At v1 .
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: sleep.1,v 1.23 2016/08/12 02:36:38 sevan Exp $
|
||||
.\" $NetBSD: sleep.1,v 1.22 2011/08/15 14:45:36 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1990, 1993, 1994
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
@@ -32,7 +32,7 @@
|
||||
.\"
|
||||
.\" @(#)sleep.1 8.3 (Berkeley) 4/18/94
|
||||
.\"
|
||||
.Dd August 12, 2016
|
||||
.Dd August 13, 2011
|
||||
.Dt SLEEP 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -121,8 +121,3 @@ The
|
||||
command is expected to be
|
||||
.St -p1003.2
|
||||
compatible.
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
utility appeared in
|
||||
.At v4 .
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: stty.1,v 1.43 2016/08/14 23:29:43 sevan Exp $
|
||||
.\" $NetBSD: stty.1,v 1.41 2012/06/20 14:19:39 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1990, 1993, 1994
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
@@ -32,7 +32,7 @@
|
||||
.\"
|
||||
.\" @(#)stty.1 8.5 (Berkeley) 6/1/94
|
||||
.\"
|
||||
.Dd August 15, 2016
|
||||
.Dd June 16, 2012
|
||||
.Dt STTY 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -633,8 +633,3 @@ and
|
||||
flags are
|
||||
extensions to the standard, as are the operands mentioned in the control
|
||||
operations section.
|
||||
.Sh HISTORY
|
||||
An
|
||||
.Nm
|
||||
utility appeared in
|
||||
.At v2 .
|
||||
|
||||
@@ -81,9 +81,6 @@
|
||||
./usr/include/arm/vm.h minix-comp
|
||||
./usr/include/arm/vmparam.h minix-comp
|
||||
./usr/include/arm/wchar_limits.h minix-comp
|
||||
./usr/include/clang-3.6/arm_acle.h minix-comp llvm,llvmcmds
|
||||
./usr/include/clang-3.6/arm_neon.h minix-comp llvm,llvmcmds
|
||||
./usr/include/clang-3.6/stdatomic.h minix-comp llvm,llvmcmds
|
||||
./usr/include/evbarm minix-comp
|
||||
./usr/include/evbarm/disklabel.h minix-comp
|
||||
./usr/include/evbarm/intr.h minix-comp
|
||||
|
||||
4
external/bsd/bind/bin/named/Makefile
vendored
4
external/bsd/bind/bin/named/Makefile
vendored
@@ -7,10 +7,6 @@ MAN= named.8 lwresd.8 named.conf.5
|
||||
BINDIR= /usr/sbin
|
||||
LINKS= ${BINDIR}/named ${BINDIR}/lwresd
|
||||
|
||||
.if defined(__MINIX)
|
||||
CWARNFLAGS.gcc+= -Wno-maybe-uninitialized
|
||||
.endif # defined(__MINIX)
|
||||
|
||||
.include "${.CURDIR}/../Makefile.inc"
|
||||
|
||||
DIST=${IDIST}/bin/named
|
||||
|
||||
6
external/bsd/bind/dist/lib/lwres/lwconfig.c
vendored
6
external/bsd/bind/dist/lib/lwres/lwconfig.c
vendored
@@ -606,21 +606,15 @@ lwres_conf_parse(lwres_context_t *ctx, const char *filename) {
|
||||
FILE *fp = NULL;
|
||||
char word[256];
|
||||
lwres_result_t rval, ret;
|
||||
#if !defined(NDEBUG) && defined(__minix)
|
||||
lwres_conf_t *confdata;
|
||||
#endif /* !defined(NDEBUG) && defined(__minix) */
|
||||
int stopchar;
|
||||
|
||||
REQUIRE(ctx != NULL);
|
||||
#if !defined(NDEBUG) && defined(__minix)
|
||||
confdata = &ctx->confdata;
|
||||
#endif /* !defined(NDEBUG) && defined(__minix) */
|
||||
|
||||
REQUIRE(filename != NULL);
|
||||
REQUIRE(strlen(filename) > 0U);
|
||||
#if !defined(NDEBUG) && defined(__minix)
|
||||
REQUIRE(confdata != NULL);
|
||||
#endif /* !defined(NDEBUG) && defined(__minix) */
|
||||
|
||||
errno = 0;
|
||||
if ((fp = fopen(filename, "r")) == NULL)
|
||||
|
||||
5
external/bsd/bind/lib/libdns/Makefile
vendored
5
external/bsd/bind/lib/libdns/Makefile
vendored
@@ -7,11 +7,6 @@ LIB=dns
|
||||
|
||||
.include "${.CURDIR}/../Makefile.inc"
|
||||
|
||||
.if defined(__MINIX)
|
||||
#LSC: -Wno-maybe-uninitialized while compiling with -DNDEBUG -Os
|
||||
CWARNFLAGS.gcc+= -Wno-maybe-uninitialized
|
||||
.endif # defined(__MINIX)
|
||||
|
||||
DIST= ${IDIST}/lib/dns
|
||||
.include "${DIST}/api"
|
||||
.include "${DIST}/mapapi"
|
||||
|
||||
5
external/bsd/bind/lib/libisc/Makefile
vendored
5
external/bsd/bind/lib/libisc/Makefile
vendored
@@ -5,11 +5,6 @@ LIB=isc
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
.if defined(__MINIX)
|
||||
#LSC: -Wno-maybe-uninitialized while compiling with -DNDEBUG -Os
|
||||
CWARNFLAGS.gcc+= -Wno-maybe-uninitialized
|
||||
.endif # defined(__MINIX)
|
||||
|
||||
.include "${.CURDIR}/../Makefile.inc"
|
||||
|
||||
DIST= ${IDIST}/lib/isc
|
||||
|
||||
8
external/bsd/dhcp/lib/common/Makefile
vendored
8
external/bsd/dhcp/lib/common/Makefile
vendored
@@ -12,11 +12,3 @@ MAN = dhcp-options.5 dhcp-eval.5
|
||||
DHCPSRCDIR= common
|
||||
|
||||
.include <bsd.lib.mk>
|
||||
|
||||
.if defined(__MINIX)
|
||||
.if !empty(DBG:M-Og) || !empty(CFLAGS:M-Og) || \
|
||||
!empty(DBG:M-g) || !empty(CFLAGS:M-g)
|
||||
#LSC: -Wno-maybe-uninitialized while compiling with -DNDEBUG -Og
|
||||
CWARNFLAGS.gcc+= -Wno-maybe-uninitialized
|
||||
.endif
|
||||
.endif # defined(__MINIX)
|
||||
|
||||
4
external/bsd/dhcpcd/sbin/dhcpcd/Makefile
vendored
4
external/bsd/dhcpcd/sbin/dhcpcd/Makefile
vendored
@@ -14,10 +14,6 @@ CPPFLAGS+= -DHAVE_CONFIG_H
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
.if defined(__MINIX)
|
||||
CWARNFLAGS.gcc+= -Wno-maybe-uninitialized
|
||||
.endif # defined(__MINIX)
|
||||
|
||||
SRCS+= auth.c hmac_md5.c
|
||||
|
||||
USE_INET?= yes
|
||||
|
||||
@@ -3816,7 +3816,6 @@ class ARMTargetInfo : public TargetInfo {
|
||||
SizeType = UnsignedInt;
|
||||
|
||||
switch (T.getOS()) {
|
||||
case llvm::Triple::Minix:
|
||||
case llvm::Triple::NetBSD:
|
||||
WCharType = SignedInt;
|
||||
break;
|
||||
|
||||
@@ -275,7 +275,7 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
|
||||
// FIXME: Thumb should just be another -target-feaure, not in the triple.
|
||||
#if defined(__minix) || 1
|
||||
// Minix/ARM-specific force to ARMv7 and EABI.
|
||||
StringRef Suffix = "v7a";
|
||||
StringRef Suffix = "v7";
|
||||
Triple.setEnvironment(llvm::Triple::EABI);
|
||||
#else
|
||||
StringRef Suffix = Triple.isOSBinFormatMachO()
|
||||
|
||||
@@ -665,10 +665,6 @@ StringRef tools::arm::getARMFloatABI(const Driver &D, const ArgList &Args,
|
||||
}
|
||||
break;
|
||||
|
||||
case llvm::Triple::Minix:
|
||||
FloatABI = "softfp";
|
||||
break;
|
||||
|
||||
default:
|
||||
switch(Triple.getEnvironment()) {
|
||||
case llvm::Triple::GNUEABIHF:
|
||||
@@ -800,9 +796,6 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
|
||||
ABIName = "aapcs";
|
||||
break;
|
||||
default:
|
||||
if (Triple.getOS() == llvm::Triple::Minix)
|
||||
ABIName = "apcs-gnu";
|
||||
|
||||
if (Triple.getOS() == llvm::Triple::NetBSD)
|
||||
ABIName = "apcs-gnu";
|
||||
else
|
||||
@@ -7740,11 +7733,6 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
// Many NetBSD architectures support more than one ABI.
|
||||
// Determine the correct emulation for ld.
|
||||
switch (getToolChain().getArch()) {
|
||||
case llvm::Triple::arm:
|
||||
case llvm::Triple::thumb:
|
||||
CmdArgs.push_back("-m");
|
||||
CmdArgs.push_back("armelf_minix");
|
||||
break;
|
||||
case llvm::Triple::x86:
|
||||
CmdArgs.push_back("-m");
|
||||
CmdArgs.push_back("elf_i386_minix");
|
||||
|
||||
@@ -638,8 +638,6 @@ llvm::Optional<ProgramStateRef> MallocChecker::performKernelMalloc(
|
||||
if (!KernelZeroFlagVal.hasValue()) {
|
||||
if (OS == llvm::Triple::FreeBSD)
|
||||
KernelZeroFlagVal = 0x0100;
|
||||
else if (OS == llvm::Triple::Minix)
|
||||
KernelZeroFlagVal = 0x0002;
|
||||
else if (OS == llvm::Triple::NetBSD)
|
||||
KernelZeroFlagVal = 0x0002;
|
||||
else if (OS == llvm::Triple::OpenBSD)
|
||||
|
||||
4
external/bsd/llvm/dist/lldb/.arcconfig
vendored
Normal file
4
external/bsd/llvm/dist/lldb/.arcconfig
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"project_id" : "lldb",
|
||||
"conduit_uri" : "http://llvm-reviews.chandlerc.com/"
|
||||
}
|
||||
275
external/bsd/llvm/dist/lldb/CMakeLists.txt
vendored
Normal file
275
external/bsd/llvm/dist/lldb/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,275 @@
|
||||
if ( CMAKE_SYSTEM_NAME MATCHES "Windows" )
|
||||
set(LLDB_DEFAULT_DISABLE_PYTHON 1)
|
||||
else()
|
||||
set(LLDB_DEFAULT_DISABLE_PYTHON 0)
|
||||
endif()
|
||||
set(LLDB_DISABLE_PYTHON ${LLDB_DEFAULT_DISABLE_PYTHON} CACHE BOOL
|
||||
"Disables the Python scripting integration.")
|
||||
|
||||
# If we are not building as a part of LLVM, build LLDB as an
|
||||
# standalone project, using LLVM as an external library:
|
||||
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||
project(lldb)
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set(LLDB_PATH_TO_LLVM_SOURCE "" CACHE PATH
|
||||
"Path to LLVM source code. Not necessary if using an installed LLVM.")
|
||||
set(LLDB_PATH_TO_LLVM_BUILD "" CACHE PATH
|
||||
"Path to the directory where LLVM was built or installed.")
|
||||
|
||||
set(LLDB_PATH_TO_CLANG_SOURCE "" CACHE PATH
|
||||
"Path to Clang source code. Not necessary if using an installed Clang.")
|
||||
set(LLDB_PATH_TO_CLANG_BUILD "" CACHE PATH
|
||||
"Path to the directory where Clang was built or installed.")
|
||||
|
||||
if (LLDB_PATH_TO_LLVM_SOURCE)
|
||||
if (NOT EXISTS "${LLDB_PATH_TO_LLVM_SOURCE}/cmake/config-ix.cmake")
|
||||
message(FATAL_ERROR "Please set LLDB_PATH_TO_LLVM_SOURCE to the root "
|
||||
"directory of LLVM source code.")
|
||||
else()
|
||||
get_filename_component(LLVM_MAIN_SRC_DIR ${LLDB_PATH_TO_LLVM_SOURCE}
|
||||
ABSOLUTE)
|
||||
list(APPEND CMAKE_MODULE_PATH "${LLVM_MAIN_SRC_DIR}/cmake/modules")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (LLDB_PATH_TO_CLANG_SOURCE)
|
||||
get_filename_component(CLANG_MAIN_SRC_DIR ${LLDB_PATH_TO_CLANG_SOURCE}
|
||||
ABSOLUTE)
|
||||
endif()
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${LLDB_PATH_TO_LLVM_BUILD}/share/llvm/cmake")
|
||||
|
||||
get_filename_component(PATH_TO_LLVM_BUILD ${LLDB_PATH_TO_LLVM_BUILD}
|
||||
ABSOLUTE)
|
||||
|
||||
get_filename_component(PATH_TO_CLANG_BUILD ${LLDB_PATH_TO_CLANG_BUILD}
|
||||
ABSOLUTE)
|
||||
|
||||
include(AddLLVM)
|
||||
include("${LLDB_PATH_TO_LLVM_BUILD}/share/llvm/cmake/LLVMConfig.cmake")
|
||||
include(HandleLLVMOptions)
|
||||
|
||||
set(PACKAGE_VERSION "${LLVM_PACKAGE_VERSION}")
|
||||
|
||||
set(LLVM_MAIN_INCLUDE_DIR "${LLVM_MAIN_SRC_DIR}/include")
|
||||
set(LLVM_BINARY_DIR ${CMAKE_BINARY_DIR})
|
||||
|
||||
set(CLANG_MAIN_INCLUDE_DIR "${CLANG_MAIN_SRC_DIR}/include")
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
include_directories("${PATH_TO_LLVM_BUILD}/include"
|
||||
"${LLVM_MAIN_INCLUDE_DIR}"
|
||||
"${PATH_TO_CLANG_BUILD}/include"
|
||||
"${CLANG_MAIN_INCLUDE_DIR}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/source")
|
||||
link_directories("${PATH_TO_LLVM_BUILD}/lib"
|
||||
"${PATH_TO_CLANG_BUILD}/lib")
|
||||
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||
|
||||
set(LLDB_BUILT_STANDALONE 1)
|
||||
endif()
|
||||
|
||||
if (LLDB_DISABLE_PYTHON)
|
||||
add_definitions( -DLLDB_DISABLE_PYTHON )
|
||||
endif()
|
||||
|
||||
macro(add_lldb_definitions)
|
||||
# We don't want no semicolons on LLDB_DEFINITIONS:
|
||||
foreach(arg ${ARGN})
|
||||
set(LLDB_DEFINITIONS "${LLVM_DEFINITIONS} ${arg}")
|
||||
endforeach(arg)
|
||||
add_definitions( ${ARGN} )
|
||||
endmacro(add_lldb_definitions)
|
||||
|
||||
if (NOT LLDB_DISABLE_PYTHON)
|
||||
find_package(PythonLibs REQUIRED)
|
||||
include_directories(${PYTHON_INCLUDE_DIRS})
|
||||
endif()
|
||||
include_directories(../clang/include)
|
||||
include_directories("${CMAKE_CURRENT_BINARY_DIR}/../clang/include")
|
||||
|
||||
# lldb requires c++11 to build. Make sure that we have a compiler and standard
|
||||
# library combination that can do that.
|
||||
if (NOT MSVC)
|
||||
# gcc and clang require the -std=c++0x or -std=c++11 flag.
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU" OR
|
||||
"${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||
if (NOT ("${CMAKE_CXX_FLAGS}" MATCHES "-std=c\\+\\+0x" OR
|
||||
"${CMAKE_CXX_FLAGS}" MATCHES "-std=gnu\\+\\+0x" OR
|
||||
"${CMAKE_CXX_FLAGS}" MATCHES "-std=c\\+\\+11" OR
|
||||
"${CMAKE_CXX_FLAGS}" MATCHES "-std=gnu\\+\\+11"))
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.7")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
endif()
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
elseif (MSVC_VERSION LESS 1700)
|
||||
message(FATAL_ERROR "The selected compiler does not support c++11 which is "
|
||||
"required to build lldb.")
|
||||
endif()
|
||||
|
||||
# Disable Clang warnings
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
add_lldb_definitions(
|
||||
-Wno-deprecated-declarations # Suppress "deprecated auto_ptr" warnings
|
||||
)
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang"
|
||||
AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "3.3")
|
||||
add_lldb_definitions(
|
||||
-Wno-deprecated-register # Suppress "deprecated register keyword" warnings
|
||||
)
|
||||
endif()
|
||||
|
||||
# Disable MSVC warnings
|
||||
if( MSVC )
|
||||
add_lldb_definitions(
|
||||
-wd4018 # Suppress 'warning C4018: '>=' : signed/unsigned mismatch'
|
||||
-wd4068 # Suppress 'warning C4068: unknown pragma'
|
||||
-wd4150 # Suppress 'warning C4150: deletion of pointer to incomplete type'
|
||||
-wd4521 # Suppress 'warning C4521: 'type' : multiple copy constructors specified'
|
||||
)
|
||||
endif()
|
||||
|
||||
# If building on a 32-bit system, make sure off_t can store offsets > 2GB
|
||||
if( CMAKE_SIZEOF_VOID_P EQUAL 4 )
|
||||
add_lldb_definitions(
|
||||
-D_LARGEFILE_SOURCE
|
||||
-D_FILE_OFFSET_BITS=64
|
||||
)
|
||||
endif()
|
||||
|
||||
set(LLDB_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(LLDB_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
|
||||
message(FATAL_ERROR "In-source builds are not allowed. CMake would overwrite "
|
||||
"the makefiles distributed with LLDB. Please create a directory and run cmake "
|
||||
"from there, passing the path to this source directory as the last argument. "
|
||||
"This process created the file `CMakeCache.txt' and the directory "
|
||||
"`CMakeFiles'. Please delete them.")
|
||||
endif()
|
||||
|
||||
# Compute the LLDB version from the LLVM version.
|
||||
string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" LLDB_VERSION
|
||||
${PACKAGE_VERSION})
|
||||
message(STATUS "LLDB version: ${LLDB_VERSION}")
|
||||
|
||||
macro(add_lldb_library name)
|
||||
llvm_process_sources(srcs ${ARGN})
|
||||
if (MSVC_IDE OR XCODE)
|
||||
string(REGEX MATCHALL "/[^/]+" split_path ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
list(GET split_path -1 dir)
|
||||
file(GLOB_RECURSE headers
|
||||
../../include/lldb${dir}/*.h)
|
||||
set(srcs ${srcs} ${headers})
|
||||
endif()
|
||||
if (MODULE)
|
||||
set(libkind MODULE)
|
||||
elseif (SHARED_LIBRARY)
|
||||
set(libkind SHARED)
|
||||
else()
|
||||
set(libkind STATIC)
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
|
||||
add_library(${name} ${libkind} ${srcs})
|
||||
#if (LLVM_COMMON_DEPENDS)
|
||||
##add_dependencies(${name} ${LLVM_COMMON_DEPENDS})
|
||||
#endif()
|
||||
|
||||
if(LLDB_USED_LIBS)
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Linux" OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD" OR CMAKE_SYSTEM_NAME MATCHES "Windows")
|
||||
target_link_libraries(${name} -Wl,--start-group ${LLDB_USED_LIBS} -Wl,--end-group)
|
||||
else()
|
||||
target_link_libraries(${name} ${LLDB_USED_LIBS})
|
||||
endif()
|
||||
endif()
|
||||
target_link_libraries(${name} ${CLANG_USED_LIBS})
|
||||
target_link_libraries(${name} ${LLVM_USED_LIBS})
|
||||
llvm_config(${name} ${LLVM_LINK_COMPONENTS})
|
||||
target_link_libraries(${name} ${LLVM_COMMON_LIBS})
|
||||
link_system_libs(${name})
|
||||
if (LLVM_COMMON_DEPENDS)
|
||||
add_dependencies(${name} ${LLVM_COMMON_DEPENDS})
|
||||
endif()
|
||||
|
||||
# Hack: only some LLDB libraries depend on the clang autogenerated headers,
|
||||
# but it is simple enough to make all of LLDB depend on some of those
|
||||
# headers without negatively impacting much of anything.
|
||||
set (LLDB_DEPENDENCIES
|
||||
libclang
|
||||
)
|
||||
add_dependencies(${name} ${LLDB_DEPENDENCIES})
|
||||
|
||||
install(TARGETS ${name}
|
||||
LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX}
|
||||
ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX})
|
||||
set_target_properties(${name} PROPERTIES FOLDER "lldb libraries")
|
||||
endmacro(add_lldb_library)
|
||||
|
||||
macro(add_lldb_executable name)
|
||||
#add_llvm_executable(${name} ${ARGN})
|
||||
llvm_process_sources( ALL_FILES ${ARGN} )
|
||||
add_executable(${name} ${ALL_FILES})
|
||||
#target_link_libraries(${name} ${CLANG_USED_LIBS})
|
||||
#llvm_config( ${name} ${LLVM_LINK_COMPONENTS} )
|
||||
#link_system_libs( ${name} )
|
||||
#if (LLVM_COMMON_DEPENDS)
|
||||
#add_dependencies(${name} ${LLVM_COMMON_DEPENDS})
|
||||
#endif()
|
||||
set_target_properties(${name} PROPERTIES FOLDER "lldb executables")
|
||||
endmacro(add_lldb_executable)
|
||||
|
||||
include_directories(BEFORE
|
||||
${CMAKE_CURRENT_BINARY_DIR}/include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
)
|
||||
|
||||
install(DIRECTORY include/
|
||||
DESTINATION include
|
||||
FILES_MATCHING
|
||||
PATTERN "*.h"
|
||||
PATTERN ".svn" EXCLUDE
|
||||
)
|
||||
|
||||
|
||||
# Find libraries or frameworks that may be needed
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
find_library(CARBON_LIBRARY Carbon)
|
||||
find_library(FOUNDATION_LIBRARY Foundation)
|
||||
find_library(CORE_FOUNDATION_LIBRARY CoreFoundation)
|
||||
find_library(CORE_SERVICES_LIBRARY CoreServices)
|
||||
find_library(SECURITY_LIBRARY Security)
|
||||
find_library(DEBUG_SYMBOLS_LIBRARY DebugSymbols PATHS "/System/Library/PrivateFrameworks")
|
||||
|
||||
set(LIBXML2_INCLUDE_DIR "/usr/include/libxml2")
|
||||
list(APPEND system_libs xml2)
|
||||
list(APPEND system_libs ${CARBON_LIBRARY} ${FOUNDATION_LIBRARY}
|
||||
${CORE_FOUNDATION_LIBRARY} ${CORE_SERVICES_LIBRARY} ${SECURITY_LIBRARY}
|
||||
${DEBUG_SYMBOLS_LIBRARY})
|
||||
endif()
|
||||
|
||||
# On FreeBSD, link libexecinfo because libc is missing backtrace()
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
|
||||
list(APPEND system_libs execinfo)
|
||||
endif()
|
||||
|
||||
#add_subdirectory(include)
|
||||
add_subdirectory(docs)
|
||||
if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows")
|
||||
add_subdirectory(scripts)
|
||||
endif()
|
||||
add_subdirectory(source)
|
||||
add_subdirectory(test)
|
||||
add_subdirectory(tools)
|
||||
13
external/bsd/llvm/dist/lldb/INSTALL.txt
vendored
Normal file
13
external/bsd/llvm/dist/lldb/INSTALL.txt
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
LLDB Installation Instructions
|
||||
==============================
|
||||
|
||||
LLDB builds on Mac OS X (with Xcode) and Linux (with GCC or Clang).
|
||||
|
||||
On Mac OS X, in addition to using Xcode you'll need to enable code signing
|
||||
on your system to either build lldb or debug using lldb. Please see the code
|
||||
signing documentation in docs/code-signing.txt for more detailed directions.
|
||||
|
||||
For instructions to build LLDB on Linux, or more details about supported
|
||||
compiler versions, other dependencies, and build flags, see:
|
||||
|
||||
http://lldb.llvm.org/build.html
|
||||
38
external/bsd/llvm/dist/lldb/LICENSE.TXT
vendored
Normal file
38
external/bsd/llvm/dist/lldb/LICENSE.TXT
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
University of Illinois/NCSA
|
||||
Open Source License
|
||||
|
||||
Copyright (c) 2010 Apple Inc.
|
||||
All rights reserved.
|
||||
|
||||
Developed by:
|
||||
|
||||
LLDB Team
|
||||
|
||||
http://lldb.llvm.org/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal with
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimers.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimers in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the names of the LLDB Team, copyright holders, nor the names of
|
||||
its contributors may be used to endorse or promote products derived from
|
||||
this Software without specific prior written permission.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
|
||||
SOFTWARE.
|
||||
|
||||
117
external/bsd/llvm/dist/lldb/Makefile
vendored
Normal file
117
external/bsd/llvm/dist/lldb/Makefile
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
##===- Makefile --------------------------------------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
# If LLDB_LEVEL is not set, then we are the top-level Makefile. Otherwise, we
|
||||
# are being included from a subdirectory makefile.
|
||||
|
||||
ifndef LLDB_LEVEL
|
||||
|
||||
IS_TOP_LEVEL := 1
|
||||
LLDB_LEVEL := .
|
||||
DIRS := include source lib tools
|
||||
|
||||
PARALLEL_DIRS :=
|
||||
endif
|
||||
|
||||
###
|
||||
# Common Makefile code, shared by all LLDB Makefiles.
|
||||
|
||||
# Set LLVM source root level.
|
||||
LEVEL := $(LLDB_LEVEL)/../..
|
||||
|
||||
# Include LLVM common makefile.
|
||||
include $(LEVEL)/Makefile.common
|
||||
|
||||
# Set common LLDB build flags.
|
||||
CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/include
|
||||
CPP.Flags += -I$(PROJ_OBJ_DIR)/$(LLDB_LEVEL)/include
|
||||
CPP.Flags += -I$(LLVM_SRC_ROOT)/tools/clang/include
|
||||
CPP.Flags += -I$(LLVM_OBJ_ROOT)/tools/clang/include
|
||||
CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source
|
||||
CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Utility
|
||||
CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/Utility
|
||||
CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/POSIX
|
||||
|
||||
ifeq (,$(findstring -DLLDB_DISABLE_PYTHON,$(CXXFLAGS)))
|
||||
# Set Python include directory
|
||||
PYTHON_INC_DIR = $(shell python-config --includes)
|
||||
CPP.Flags += $(PYTHON_INC_DIR)
|
||||
endif
|
||||
|
||||
ifeq ($(HOST_OS),Darwin)
|
||||
CPP.Flags += $(subst -I,-I$(SDKROOT),$(PYTHON_INC_DIR))
|
||||
CPP.Flags += -F$(SDKROOT)/System/Library/Frameworks
|
||||
CPP.Flags += -F$(SDKROOT)/System/Library/PrivateFrameworks
|
||||
CPP.Flags += -I$(SDKROOT)/usr/include/libxml2
|
||||
endif
|
||||
ifdef LLDB_VENDOR
|
||||
CPP.Flags += -DLLDB_VENDOR='"$(LLDB_VENDOR) "'
|
||||
endif
|
||||
|
||||
# If building on a 32-bit system, make sure off_t can store offsets > 2GB
|
||||
ifneq "$(HOST_ARCH)" "x86_64"
|
||||
CPP.Flags += -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
|
||||
endif
|
||||
|
||||
# Disable -fstrict-aliasing. Darwin disables it by default (and LLVM doesn't
|
||||
# work with it enabled with GCC), Clang/llvm-gc don't support it yet, and newer
|
||||
# GCC's have false positive warnings with it on Linux (which prove a pain to
|
||||
# fix). For example:
|
||||
# http://gcc.gnu.org/PR41874
|
||||
# http://gcc.gnu.org/PR41838
|
||||
#
|
||||
# We can revisit this when LLVM/Clang support it.
|
||||
CXX.Flags += -fno-strict-aliasing
|
||||
|
||||
# Do not warn about pragmas. In particular, we are looking to ignore the
|
||||
# "#pragma mark" construct which GCC warns about on platforms other than Darwin.
|
||||
EXTRA_OPTIONS += -Wno-unknown-pragmas
|
||||
|
||||
# Drop -Wsign-compare, which we are not currently clean with.
|
||||
EXTRA_OPTIONS += -Wno-sign-compare
|
||||
|
||||
# Drop -Wunused-function and -Wunneeded-internal-declaration, which we are not
|
||||
# currently clean with.
|
||||
EXTRA_OPTIONS += -Wno-sign-compare -Wno-unused-function
|
||||
|
||||
###
|
||||
# LLDB Top Level specific stuff.
|
||||
|
||||
ifeq ($(IS_TOP_LEVEL),1)
|
||||
|
||||
ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT))
|
||||
$(RecursiveTargets)::
|
||||
$(Verb) if [ ! -f test/Makefile ]; then \
|
||||
$(MKDIR) test; \
|
||||
$(CP) $(PROJ_SRC_DIR)/test/Makefile test/Makefile; \
|
||||
fi
|
||||
endif
|
||||
|
||||
test::
|
||||
@ $(MAKE) -C test
|
||||
|
||||
#report::
|
||||
# @ $(MAKE) -C test report
|
||||
|
||||
#clean::
|
||||
# @ $(MAKE) -C test clean
|
||||
|
||||
tags::
|
||||
$(Verb) etags `find . -type f -name '*.h' -or -name '*.cpp' | \
|
||||
grep -v /lib/Headers | grep -v /test/`
|
||||
|
||||
cscope.files:
|
||||
find tools lib include -name '*.cpp' \
|
||||
-or -name '*.def' \
|
||||
-or -name '*.td' \
|
||||
-or -name '*.h' > cscope.files
|
||||
|
||||
.PHONY: test report clean cscope.files
|
||||
|
||||
endif
|
||||
41
external/bsd/llvm/dist/lldb/docs/CMakeLists.txt
vendored
Normal file
41
external/bsd/llvm/dist/lldb/docs/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
include(FindDoxygen)
|
||||
|
||||
if(DOXYGEN_FOUND)
|
||||
set(abs_top_srcdir ${CMAKE_CURRENT_SOURCE_DIR}/..)
|
||||
set(DOT dot)
|
||||
set(PACKAGE_VERSION mainline)
|
||||
set(abs_top_builddir ..)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doxygen.cfg.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/doxygen.cfg @ONLY)
|
||||
|
||||
add_custom_target(lldb-cpp-doc
|
||||
${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxygen.cfg
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMENT "Generating LLDB C++ API reference with Doxygen" VERBATIM
|
||||
)
|
||||
endif(DOXYGEN_FOUND)
|
||||
|
||||
find_package(PythonInterp REQUIRED)
|
||||
find_program(EPYDOC_EXECUTABLE NAMES epydoc epydoc.py)
|
||||
if(EPYDOC_EXECUTABLE)
|
||||
find_program(DOT_EXECUTABLE dot)
|
||||
if(DOT_EXECUTABLE)
|
||||
set(EPYDOC_OPTIONS ${EPYDOC_OPTIONS} --graph all --dotpath ${DOT_EXECUTABLE})
|
||||
endif()
|
||||
set(DOC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/doc")
|
||||
file(MAKE_DIRECTORY "${DOC_DIR}")
|
||||
#set(ENV{PYTHONPATH} ${CMAKE_CURRENT_BINARY_DIR}/../../../lib/python2.7/site-packages)
|
||||
add_custom_target(lldb-python-doc
|
||||
${EPYDOC_EXECUTABLE}
|
||||
--html
|
||||
lldb
|
||||
-o ${CMAKE_CURRENT_BINARY_DIR}/python_reference
|
||||
--name "LLDB python API"
|
||||
--url "http://lldb.llvm.org"
|
||||
${EPYDOC_OPTIONS}
|
||||
DEPENDS swig_wrapper liblldb
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../lib/python2.7/site-packages
|
||||
COMMENT "Generating LLDB Python API reference with epydoc" VERBATIM
|
||||
)
|
||||
endif(EPYDOC_EXECUTABLE)
|
||||
50
external/bsd/llvm/dist/lldb/docs/building-with-debug-llvm.txt
vendored
Normal file
50
external/bsd/llvm/dist/lldb/docs/building-with-debug-llvm.txt
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
This document describes how to build a debug version of LLVM for use with
|
||||
LLDB, and how to make LLDB use it.
|
||||
|
||||
It assumes that you are using the Xcode 3 series (I used 3.2.4) to build
|
||||
LLDB. It also assumes that your shell is /bin/bash, and that you are
|
||||
currently at a shell prompt in a checked-out LLDB repository.
|
||||
|
||||
1. Check out LLVM and Clang from their repositories. To determine
|
||||
the revision to use, consult scripts/build-llvm.pl (this is done
|
||||
in the first command line below). !!! WARNING Do not use the
|
||||
name "llvm" for your checkout, for reasons described in part 3
|
||||
below.
|
||||
|
||||
$ export CLANG_REVISION=`cat scripts/build-llvm.pl | grep ^our.*llvm_revision | cut -d \' -f 2,2`
|
||||
$ svn co -r $CLANG_REVISION http://llvm.org/svn/llvm-project/llvm/trunk llvm.checkout
|
||||
$ svn co -r $CLANG_REVISION http://llvm.org/svn/llvm-project/cfe/trunk llvm.checkout/tools/clang
|
||||
|
||||
2. Configure LLVM/Clang with the proper options and compilers. I use:
|
||||
|
||||
$ cd llvm.checkout
|
||||
$ CC="cc -g -O0" CXX="c++ -g -O0" ./configure --disable-optimized --enable-assertions --enable-targets=x86_64,arm
|
||||
$ CC="cc -g -O0" CXX="c++ -g -O0" make -j 2
|
||||
$ cd ..
|
||||
|
||||
3. Create a link to the built LLVM. !!! WARNING: Do not rename the
|
||||
directory! The LLVM builder script that runs as part of the Xcode
|
||||
build keys off the fact that llvm/ is a symlink to recognize that
|
||||
we are building with a custom debug build.
|
||||
|
||||
$ ln -sf llvm.checkout llvm
|
||||
|
||||
4. Make sure that your Xcode project is set up correctly. Open
|
||||
lldb.xcodeproj and do the following:
|
||||
|
||||
Under "Targets" in the Groups & Files navigator, double-click
|
||||
lldb-tool. In the resulting window, select "Debug" from the
|
||||
"Configuration:" drop-down. Then, make sure that the setting
|
||||
"Build Active Architecture Only" is enabled. Close the window.
|
||||
|
||||
Under "Targets" in the Groups & Files navigator, double-click
|
||||
LLDB. In the resulting window, select "Debug" from the
|
||||
"Configuration:" drop-down. Then, make sure that the setting
|
||||
"Build Active Architecture Only" is enabled. Close the window.
|
||||
|
||||
5. Ensure that Xcode is building the lldb-tool target in Debug
|
||||
configuration for your architecture (typically x86_64). You
|
||||
can usually pick these options from the Overview drop-down at
|
||||
the top left of the Xcode window.
|
||||
|
||||
6. Build lldb.xcodeproj.
|
||||
61
external/bsd/llvm/dist/lldb/docs/code-signing.txt
vendored
Normal file
61
external/bsd/llvm/dist/lldb/docs/code-signing.txt
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
On MacOSX lldb needs to be code signed. The Debug, DebugClang and Release
|
||||
builds are set to code sign using a code signing certificate named
|
||||
"lldb_codesign".
|
||||
|
||||
If you have re-installed a new OS, please delete all old lldb_codesign items
|
||||
from your keychain. There will be 3: a code signing certification and a public
|
||||
and private key. Reboot after deleting them. You will also need to delete and
|
||||
build folders that contained old signed items. The darwin kernel will cache
|
||||
code sigining using the executable's file system node, so you will need to
|
||||
delete the file so the kernel clears its cache.
|
||||
|
||||
If you don't have one yet you will need to:
|
||||
- Launch /Applications/Utilities/Keychain Access.app
|
||||
|
||||
- In Keychain Access select the "login" keychain in the "Keychains"
|
||||
list in the upper left hand corner of the window.
|
||||
|
||||
- Select the following menu item:
|
||||
|
||||
Keychain Access->Certificate Assistant->Create a Certificate...
|
||||
|
||||
- Set the following settings
|
||||
|
||||
Name = lldb_codesign
|
||||
Identity Type = Self Signed Root
|
||||
Certificate Type = Code Signing
|
||||
|
||||
- Click Create
|
||||
- Click Continue
|
||||
- Click Done
|
||||
- Click on the "My Certificates"
|
||||
- Double click on your new lldb_codesign certificate
|
||||
- Turn down the "Trust" disclosure triangle, scroll to the "Code Signing" trust
|
||||
pulldown menu and select "Always Trust" and authenticate as needed using your
|
||||
username and password.
|
||||
- Drag the new "lldb_codesign" code signing certificate (not the public or private
|
||||
keys of the same name) from the "login" keychain to the "System" keychain in the
|
||||
Keychains pane on the left hand side of the main Keychain Access window. This will
|
||||
move this certificate to the "System" keychain. You'll have to authorize a few
|
||||
more times, set it to be "Always trusted" when asked.
|
||||
- Remove "~/Desktop/lldb_codesign.cer" file on your desktop if there is one.
|
||||
- In the Keychain Access GUI, click and drag "lldb_codesign" in the "System" keychain
|
||||
onto the desktop. The drag will create a "~/Desktop/lldb_codesign.cer" file used in
|
||||
the next step.
|
||||
- Switch to Terminal, and run the following:
|
||||
|
||||
sudo security add-trust -d -r trustRoot -p basic -p codeSign -k /Library/Keychains/System.keychain ~/Desktop/lldb_codesign.cer
|
||||
rm -f ~/Desktop/lldb_codesign.cer
|
||||
|
||||
- Drag the "lldb_codesign" certificate from the "System" keychain back into the
|
||||
"login" keychain
|
||||
- Quit Keychain Access
|
||||
- Reboot
|
||||
- Clean by removing all previously creating code signed binaries and rebuild
|
||||
lldb and you should be able to debug.
|
||||
|
||||
When you build your LLDB for the first time, the Xcode GUI will prompt you for permission
|
||||
to use the "lldb_codesign" keychain. Be sure to click "Always Allow" on your first
|
||||
build. From here on out, the "lldb_codesign" will be trusted and you can build from the
|
||||
command line without having to authorize. Also the first time you debug using a LLDB that
|
||||
was built with this code signing certificate, you will need to authenticate once.
|
||||
1631
external/bsd/llvm/dist/lldb/docs/doxygen.cfg.in
vendored
Normal file
1631
external/bsd/llvm/dist/lldb/docs/doxygen.cfg.in
vendored
Normal file
File diff suppressed because it is too large
Load Diff
13
external/bsd/llvm/dist/lldb/docs/doxygen.footer
vendored
Normal file
13
external/bsd/llvm/dist/lldb/docs/doxygen.footer
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<hr>
|
||||
<p class="footer">
|
||||
Generated on $datetime for <a href="http://lldb.llvm.org/">$projectname</a> by
|
||||
<a href="http://www.doxygen.org"><img src="doxygen.png" alt="Doxygen"
|
||||
align="middle" border="0"/>$doxygenversion</a><br>
|
||||
Copyright © 2003-2013 University of Illinois at Urbana-Champaign.
|
||||
All Rights Reserved.</p>
|
||||
|
||||
<hr>
|
||||
<!--#include virtual="/attrib.incl" -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
9
external/bsd/llvm/dist/lldb/docs/doxygen.header
vendored
Normal file
9
external/bsd/llvm/dist/lldb/docs/doxygen.header
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"/>
|
||||
<meta name="keywords" content="LLDB,C++,doxygen,API,documentation"/>
|
||||
<meta name="description" content="C++ source code API documentation for LLDB."/>
|
||||
<title>LLVM: $title</title>
|
||||
<link href="doxygen.css" rel="stylesheet" type="text/css"/>
|
||||
</head><body>
|
||||
<p class="title">LLDB API Documentation</p>
|
||||
19
external/bsd/llvm/dist/lldb/docs/doxygen.intro
vendored
Normal file
19
external/bsd/llvm/dist/lldb/docs/doxygen.intro
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
/// @mainpage LLDB
|
||||
///
|
||||
/// @section main_intro Introduction
|
||||
/// Welcome to LLDB.
|
||||
///
|
||||
/// This documentation describes the @b interface that can drive LLDB.
|
||||
/// There are no instructions here on how to use LLDB, only the APIs
|
||||
/// that make up the software. For usage instructions, please see
|
||||
/// the help command.
|
||||
///
|
||||
/// @section main_caveat Caveat
|
||||
/// This documentation is generated directly from the source code with doxygen.
|
||||
/// Since LLDB is constantly under active development, what you're about to
|
||||
/// read is out of date! However, it may still be useful since certain portions
|
||||
/// of LLDB are very stable.
|
||||
///
|
||||
/// @section main_changelog Change Log
|
||||
/// - Adapted for LLDB 05/25/2013 by Daniel Malea
|
||||
/// - Original content written 12/30/2003 by Reid Spencer
|
||||
488
external/bsd/llvm/dist/lldb/docs/lldb-for-gdb-users.txt
vendored
Normal file
488
external/bsd/llvm/dist/lldb/docs/lldb-for-gdb-users.txt
vendored
Normal file
@@ -0,0 +1,488 @@
|
||||
Here's a short precis of how to run lldb if you are familiar with the
|
||||
gdb command set:
|
||||
|
||||
|
||||
1) LLDB Command Structure:
|
||||
|
||||
First some details on lldb command structure to help orient you...
|
||||
|
||||
Unlike gdb's command set, which is rather free-form, we tried to make
|
||||
the lldb command syntax fairly structured. The commands are all of the
|
||||
form
|
||||
|
||||
<noun> <verb> [-options [option-value]] [argument [argument...]]
|
||||
|
||||
The command line parsing is done before command execution, so it is
|
||||
uniform across all the commands. The command syntax is very simple,
|
||||
basically arguments, options and option values are all white-space
|
||||
separated. If you need to put a backslash or double-quote character
|
||||
in an argument you back-slash it in the argument. That makes the
|
||||
command syntax more regular, but it also means you may have to
|
||||
quote some arguments in lldb that you wouldn't in gdb.
|
||||
|
||||
Options can be placed anywhere on the command line, but if the arguments
|
||||
begin with a "-" then you have to tell lldb that you're done with options
|
||||
using the "--" option. So for instance, the "process launch" command takes
|
||||
the "-s" option to mean "stop the process at the first instruction". It's
|
||||
arguments are the arguments you are passing to the program. So if you wanted
|
||||
to pass an argument that contained a "-" you would have to do:
|
||||
|
||||
(lldb) process launch -- -program_arg value
|
||||
|
||||
We also tried to reduce the number of special purpose argument
|
||||
parsers, which sometimes forces the user to be a little more explicit
|
||||
about stating their intentions. The first instance you'll note of
|
||||
this is the breakpoint command. In gdb, to set a breakpoint, you
|
||||
would just say:
|
||||
|
||||
(gdb) break foo.c:12
|
||||
|
||||
or
|
||||
|
||||
(gdb) break foo
|
||||
|
||||
if foo is a function. As time went on, the parser that tells foo.c:12
|
||||
from foo from foo.c::foo (which means the function foo in the file
|
||||
foo.c) got more and more complex and bizarre, and especially in C++
|
||||
there are times where there's really no way to specify the function
|
||||
you want to break on. The lldb commands are more verbose but also precise.
|
||||
So you say:
|
||||
|
||||
(lldb) breakpoint set -f foo.c -l 12
|
||||
|
||||
to set a file & line breakpoint. To set a breakpoint on a function
|
||||
by name, you do:
|
||||
|
||||
(lldb) breakpoint set -n foo
|
||||
|
||||
This can allow us to be more expressive, so you can say:
|
||||
|
||||
(lldb) breakpoint set -M foo
|
||||
|
||||
to break on all C++ methods named foo, or:
|
||||
|
||||
(lldb) breakpoint set -S alignLeftEdges:
|
||||
|
||||
to set a breakpoint on all ObjC selectors called alignLeftEdges:. It
|
||||
also makes it easy to compose specifications, like:
|
||||
|
||||
(lldb) breakpoint set -s foo.dylib -n foo
|
||||
|
||||
for all functions called foo in the shared library foo.dylib. Suggestions
|
||||
on more interesting primitives of this sort are also very welcome.
|
||||
|
||||
So for instance:
|
||||
|
||||
(lldb) breakpoint set -n "-[SKTGraphicView alignLeftEdges:]"
|
||||
|
||||
Just like gdb, the lldb command interpreter does a shortest unique
|
||||
string match on command names, so the previous command can also be
|
||||
typed:
|
||||
|
||||
(lldb) b s -n "-[SKTGraphicView alignLeftEdges:]"
|
||||
|
||||
lldb also supports command completion for source file names, symbol
|
||||
names, file names, etc. Completion is initiated by a hitting a <TAB>.
|
||||
Individual options in a command can have different completers, so for
|
||||
instance the -f option in "breakpoint" completes to source files, the
|
||||
-s option to currently loaded shared libraries, etc... We can even do
|
||||
things like if you specify -s, and are completing on -f, we will only
|
||||
list source files in the shared library specified by -s...
|
||||
|
||||
The individual commands are pretty extensively documented, using
|
||||
the "help" command. And there is an "apropos" command that will
|
||||
search the help for a particular word and dump a summary help string
|
||||
for each matching command.
|
||||
|
||||
Finally, there is a mechanism to construct aliases for commonly used
|
||||
commands. So for instance if you get annoyed typing
|
||||
|
||||
(lldb) b s -f foo.c -l 12
|
||||
|
||||
you can do:
|
||||
|
||||
(lldb) command alias bfl breakpoint set -f %1 -l %2
|
||||
(lldb) bfl foo.c 12
|
||||
|
||||
We have added a few aliases for commonly used commands (e.g. "step",
|
||||
"next" and "continue") but we haven't tried to be exhaustive because
|
||||
in our experience it is more convenient to make the basic commands
|
||||
unique down to a letter or two, and then learn these sequences than
|
||||
fill the namespace with lots of aliases, and then have to type them
|
||||
all the way out.
|
||||
|
||||
However, users are free to customize lldb's command set however they
|
||||
like, and since lldb reads the file ~/.lldbinit at startup, you can
|
||||
store all your aliases there and they will be generally available to
|
||||
you. Your aliases are also documented in the help command so you can
|
||||
remind yourself of what you've set up.
|
||||
|
||||
lldb also has a built-in Python interpreter, which is accessible by
|
||||
the "script" command. All the functionality of the debugger is
|
||||
available as classes in the Python interpreter, so the more complex
|
||||
commands that in gdb you would introduce with the "define" command can
|
||||
be done by writing Python functions using the lldb-Python library,
|
||||
then loading the scripts into your running session and accessing them
|
||||
with the "script" command.
|
||||
|
||||
|
||||
|
||||
2) A typical session:
|
||||
|
||||
|
||||
a) Setting the program to debug:
|
||||
|
||||
|
||||
As with gdb, you can start lldb and specify the file you wish to debug
|
||||
on the command line:
|
||||
|
||||
$ lldb /Projects/Sketch/build/Debug/Sketch.app
|
||||
Current executable set to '/Projects/Sketch/build/Debug/Sketch.app' (x86_64).
|
||||
|
||||
or you can specify it after the fact with the "file" command:
|
||||
|
||||
(lldb) file /Projects/Sketch/build/Debug/Sketch.app
|
||||
Current executable set to '/Projects/Sketch/build/Debug/Sketch.app' (x86_64).
|
||||
|
||||
|
||||
b) Setting breakpoints:
|
||||
|
||||
|
||||
We've discussed how to set breakpoints above. You can use "help break set"
|
||||
to see all the options for breakpoint setting. For instance, we might do:
|
||||
|
||||
(lldb) b s -S alignLeftEdges:
|
||||
Breakpoint created: 1: name = 'alignLeftEdges:', locations = 1, resolved = 1
|
||||
|
||||
You can find out about the breakpoints you've set with:
|
||||
|
||||
(lldb) break list
|
||||
Current breakpoints:
|
||||
1: name = 'alignLeftEdges:', locations = 1, resolved = 1
|
||||
1.1: where = Sketch`-[SKTGraphicView alignLeftEdges:] + 33 at /Projects/Sketch/SKTGraphicView.m:1405, address = 0x0000000100010d5b, resolved, hit count = 0
|
||||
|
||||
Note that each "logical" breakpoint can have multiple "locations".
|
||||
The logical breakpoint has an integer id, and it's locations have an
|
||||
id within their parent breakpoint (the two are joined by a ".",
|
||||
e.g. 1.1 in the example above.)
|
||||
|
||||
Also the breakpoints remain "live" so that if another shared library
|
||||
were to be loaded that had another implementation of the
|
||||
"alignLeftEdges:" selector, the new location would be added to
|
||||
breakpoint 1 (e.g. a "1.2" breakpoint would be set on the newly loaded
|
||||
selector).
|
||||
|
||||
The other piece of information in the breakpoint listing is whether the
|
||||
breakpoint location was "resolved" or not. A location gets resolved when
|
||||
the file address it corresponds to gets loaded into the program you are
|
||||
debugging. For instance if you set a breakpoint in a shared library that
|
||||
then gets unloaded, that breakpoint location will remain, but it will no
|
||||
longer be "resolved".
|
||||
|
||||
One other thing to note for gdb users is that lldb acts like gdb with:
|
||||
|
||||
(gdb) set breakpoint pending on
|
||||
|
||||
That is, lldb should always make a breakpoint from your specification, even
|
||||
if it couldn't find any locations that match the specification. You can tell
|
||||
whether the expression was resolved or not by checking the locations field
|
||||
in "breakpoint list", and we report the breakpoint as "pending" when you
|
||||
set it so you can tell you've made a typo more easily, if that was indeed
|
||||
the reason no locations were found:
|
||||
|
||||
(lldb) b s -f no_such_file.c -l 10000000
|
||||
Breakpoint created: 1: file ='no_such_file.c', line = 10000000, locations = 0 (pending)
|
||||
|
||||
You can delete, disable, set conditions and ignore counts either on all the
|
||||
locations generated by your logical breakpoint, or on particular locations
|
||||
your specification resolved to. For instance if we wanted to add a command
|
||||
to print a backtrace when we hit this breakpoint we could do:
|
||||
|
||||
(lldb) b command add -c 1.1
|
||||
Enter your debugger command(s). Type 'DONE' to end.
|
||||
> bt
|
||||
> DONE
|
||||
|
||||
The "-c" option specifies that the breakpoint command is a set of lldb
|
||||
command interpreter commands. Use "-s" if you want to implement your
|
||||
breakpoint command using the Python interface instead.
|
||||
|
||||
|
||||
c) Running the program:
|
||||
|
||||
Then you can either launch the process with the command:
|
||||
|
||||
(lldb) process launch
|
||||
|
||||
or its alias:
|
||||
|
||||
(lldb) r
|
||||
|
||||
Or you can attach to a process by name with:
|
||||
|
||||
(lldb) process attach -n Sketch
|
||||
|
||||
the "attach by name" also supports the "-w" option which waits for the
|
||||
next process of that name to show up, and attaches to that. You can also
|
||||
attach by PID:
|
||||
|
||||
(lldb) process attach -p 12345
|
||||
Process 46915 Attaching
|
||||
(lldb) Process 46915 Stopped
|
||||
1 of 3 threads stopped with reasons:
|
||||
* thread #1: tid = 0x2c03, 0x00007fff85cac76a, where = libSystem.B.dylib`__getdirentries64 + 10, stop reason = signal = SIGSTOP, queue = com.apple.main-thread
|
||||
|
||||
Note that we tell you that "1 of 3 threads stopped with reasons" and
|
||||
then list those threads. In a multi-threaded environment it is very
|
||||
common for more than one thread to hit your breakpoint(s) before the
|
||||
kernel actually returns control to the debugger. In that case, you
|
||||
will see all the threads that stopped for some interesting reason
|
||||
listed in the stop message.
|
||||
|
||||
|
||||
d) Controlling execution:
|
||||
|
||||
|
||||
After launching, we can continue until we hit our breakpoint. The primitive
|
||||
commands for process control all exist under the "thread" command:
|
||||
|
||||
(lldb) thread continue
|
||||
Resuming thread 0x2c03 in process 46915
|
||||
Resuming process 46915
|
||||
(lldb)
|
||||
|
||||
At present you can only operate on one thread at a time, but the
|
||||
design will ultimately support saying "step over the function in
|
||||
Thread 1, and step into the function in Thread 2, and continue Thread
|
||||
3" etc. When we eventually support keeping some threads running while
|
||||
others are stopped this will be particularly important. For
|
||||
convenience, however, all the stepping commands have easy aliases.
|
||||
So "thread continue" is just "c", etc.
|
||||
|
||||
The other program stepping commands are pretty much the same as in gdb.
|
||||
You've got:
|
||||
|
||||
1. (lldb) thread step-in
|
||||
The same as gdb's "step" -- there is also the alias "s" in lldb
|
||||
|
||||
2. (lldb) thread step-over
|
||||
The same as gdb's "next" -- there is also the alias "n" in lldb
|
||||
|
||||
3. (lldb) thread step-out
|
||||
The same as gdb's "finish" -- there is also the alias "f" in lldb
|
||||
|
||||
And the "by instruction" versions:
|
||||
|
||||
(lldb) thread step-inst
|
||||
(lldb) thread step-over-inst
|
||||
|
||||
Finally, there's:
|
||||
|
||||
(lldb) thread until 100
|
||||
|
||||
which runs the thread in the current frame till it reaches line 100 in
|
||||
this frame or stops if it leaves the current frame. This is a pretty
|
||||
close equivalent to gdb's "until" command.
|
||||
|
||||
|
||||
One thing here that might be a little disconcerting to gdb users here is that
|
||||
when you resume process execution, you immediately get a prompt back. That's
|
||||
because the lldb interpreter remains live when you are running the target.
|
||||
This allows you to set a breakpoint, etc without having to explicitly interrupt
|
||||
the program you are debugging. We're still working out all the operations
|
||||
that it is safe to do while running. But this way of operation will set us
|
||||
up for "no stop" debugging when we get to implementing that.
|
||||
|
||||
If you want to interrupt a running program do:
|
||||
|
||||
(lldb) process interrupt
|
||||
|
||||
To find out the state of the program, use:
|
||||
|
||||
(lldb) process status
|
||||
Process 47958 is running.
|
||||
|
||||
This is very convenient, but it does have the down-side that debugging
|
||||
programs that use stdin is no longer as straightforward. For now, you
|
||||
have to specify another tty to use as the program stdout & stdin using
|
||||
the appropriate options to "process launch", or start your program in
|
||||
another terminal and catch it with "process attach -w". We will come
|
||||
up with some more convenient way to juggle the terminal back & forth
|
||||
over time.
|
||||
|
||||
|
||||
e) Examining program state:
|
||||
|
||||
Once you've stopped, lldb will choose a current thread, usually the
|
||||
one that stopped "for a reason", and a current frame in that thread.
|
||||
Many the commands for inspecting state work on this current
|
||||
thread/frame.
|
||||
|
||||
To inspect the current state of your process, you can start with the
|
||||
threads:
|
||||
|
||||
(lldb) thread list
|
||||
Process 46915 state is Stopped
|
||||
* thread #1: tid = 0x2c03, 0x00007fff85cac76a, where = libSystem.B.dylib`__getdirentries64 + 10, stop reason = signal = SIGSTOP, queue = com.apple.main-thread
|
||||
thread #2: tid = 0x2e03, 0x00007fff85cbb08a, where = libSystem.B.dylib`kevent + 10, queue = com.apple.libdispatch-manager
|
||||
thread #3: tid = 0x2f03, 0x00007fff85cbbeaa, where = libSystem.B.dylib`__workq_kernreturn + 10
|
||||
|
||||
The * indicates that Thread 1 is the current thread. To get a
|
||||
backtrace for that thread, do:
|
||||
|
||||
(lldb) thread backtrace
|
||||
thread #1: tid = 0x2c03, stop reason = breakpoint 1.1, queue = com.apple.main-thread
|
||||
frame #0: 0x0000000100010d5b, where = Sketch`-[SKTGraphicView alignLeftEdges:] + 33 at /Projects/Sketch/SKTGraphicView.m:1405
|
||||
frame #1: 0x00007fff8602d152, where = AppKit`-[NSApplication sendAction:to:from:] + 95
|
||||
frame #2: 0x00007fff860516be, where = AppKit`-[NSMenuItem _corePerformAction] + 365
|
||||
frame #3: 0x00007fff86051428, where = AppKit`-[NSCarbonMenuImpl performActionWithHighlightingForItemAtIndex:] + 121
|
||||
frame #4: 0x00007fff860370c1, where = AppKit`-[NSMenu performKeyEquivalent:] + 272
|
||||
frame #5: 0x00007fff86035e69, where = AppKit`-[NSApplication _handleKeyEquivalent:] + 559
|
||||
frame #6: 0x00007fff85f06aa1, where = AppKit`-[NSApplication sendEvent:] + 3630
|
||||
frame #7: 0x00007fff85e9d922, where = AppKit`-[NSApplication run] + 474
|
||||
frame #8: 0x00007fff85e965f8, where = AppKit`NSApplicationMain + 364
|
||||
frame #9: 0x0000000100015ae3, where = Sketch`main + 33 at /Projects/Sketch/SKTMain.m:11
|
||||
frame #10: 0x0000000100000f20, where = Sketch`start + 52
|
||||
|
||||
You can also provide a list of threads to backtrace, or the keyword
|
||||
"all" to see all threads:
|
||||
|
||||
(lldb) thread backtrace all
|
||||
|
||||
Next task is inspecting data:
|
||||
|
||||
The most convenient way to inspect a frame's arguments and local variables is:
|
||||
|
||||
(lldb) frame variable
|
||||
self = (SKTGraphicView *) 0x0000000100208b40
|
||||
_cmd = (struct objc_selector *) 0x000000010001bae1
|
||||
sender = (id) 0x00000001001264e0
|
||||
selection = (NSArray *) 0x00000001001264e0
|
||||
i = (NSUInteger) 0x00000001001264e0
|
||||
c = (NSUInteger) 0x00000001001253b0
|
||||
|
||||
You can also choose particular variables to view:
|
||||
|
||||
(lldb) frame variable self
|
||||
(SKTGraphicView *) self = 0x0000000100208b40
|
||||
|
||||
The frame variable command is not a full expression parser but it
|
||||
does support some common operations like dereferencing:
|
||||
|
||||
(lldb) fr v *self
|
||||
(SKTGraphicView *) self = 0x0000000100208b40
|
||||
(NSView) NSView = {
|
||||
(NSResponder) NSResponder = {
|
||||
...
|
||||
|
||||
and structure element references:
|
||||
|
||||
(lldb) frame variable self.isa
|
||||
(struct objc_class *) self.isa = 0x0000000100023730
|
||||
|
||||
The frame variable command will also perform "object printing" operations on
|
||||
variables (currently we only support NSPrintForDebugger) with:
|
||||
|
||||
(lldb) fr v -o self
|
||||
(SKTGraphicView *) self = 0x0000000100208b40
|
||||
<SKTGraphicView: 0x100208b40>
|
||||
|
||||
You can select another frame to view with:
|
||||
|
||||
(lldb) frame select 9
|
||||
frame #9: 0x0000000100015ae3, where = Sketch`main + 33 at /Projects/Sketch/SKTMain.m:11
|
||||
8
|
||||
9
|
||||
10 int main(int argc, const char *argv[]) {
|
||||
11 -> return NSApplicationMain(argc, argv);
|
||||
12 }
|
||||
13
|
||||
14
|
||||
|
||||
Another neat trick that the variable list does is array references, so:
|
||||
|
||||
(lldb) fr v argv[0]
|
||||
(char const *) argv[0] = 0x00007fff5fbffaf8 "/Projects/Sketch/build/Debug/Sketch.app/Contents/MacOS/Sketch"
|
||||
|
||||
If you need to view more complex data or change program data, you can
|
||||
use the general "expression" command. It takes an expression and
|
||||
evaluates it in the scope of the currently selected frame. For instance:
|
||||
|
||||
(lldb) expr self
|
||||
$0 = (SKTGraphicView *) 0x0000000100135430
|
||||
(lldb) expr self = 0x00
|
||||
$1 = (SKTGraphicView *) 0x0000000000000000
|
||||
(lldb) frame var self
|
||||
(SKTGraphicView *) self = 0x0000000000000000
|
||||
|
||||
You can also call functions:
|
||||
|
||||
(lldb) expr (int) printf ("I have a pointer 0x%llx.\n", self)
|
||||
$2 = (int) 22
|
||||
I have a pointer 0x0.
|
||||
|
||||
One thing to note from this example is that lldb commands can be defined to
|
||||
take "raw" input. "expression" is one of these. So in the expression command,
|
||||
you don't have to quote your whole expression, nor backslash protect quotes,
|
||||
etc...
|
||||
|
||||
Finally, the results of the expressions are stored in persistent variables
|
||||
(of the form $[0-9]+) that you can use in further expressions, like:
|
||||
|
||||
(lldb) expr self = $0
|
||||
$4 = (SKTGraphicView *) 0x0000000100135430
|
||||
|
||||
f) Customization:
|
||||
|
||||
You can use the embedded Python interpreter to add the following 'pwd' and 'cd' commands
|
||||
for your lldb session:
|
||||
|
||||
(lldb) script import os
|
||||
(lldb) command alias pwd script print os.getcwd()
|
||||
(lldb) command regex cd "s/^(.*)$/script os.chdir(os.path.expanduser('%1'))/"
|
||||
|
||||
...
|
||||
|
||||
(lldb) cd /tmp
|
||||
script os.chdir(os.path.expanduser('/tmp'))
|
||||
(lldb) pwd
|
||||
/private/tmp
|
||||
(lldb)
|
||||
|
||||
Or for a more capable 'cd' command, create ~/utils.py like this:
|
||||
|
||||
import os
|
||||
|
||||
def chdir(debugger, args, result, dict):
|
||||
"""Change the working directory, or cd to ${HOME}."""
|
||||
dir = args.strip()
|
||||
if dir:
|
||||
os.chdir(args)
|
||||
else:
|
||||
os.chdir(os.path.expanduser('~'))
|
||||
print "Current working directory: %s" % os.getcwd()
|
||||
|
||||
and, have the following in your ~/.lldbinit file:
|
||||
|
||||
script import os, sys
|
||||
script sys.path.append(os.path.expanduser('~'))
|
||||
script import utils
|
||||
command alias pwd script print os.getcwd()
|
||||
command script add -f utils.chdir cd
|
||||
|
||||
and, then in your lldb session, you can have:
|
||||
|
||||
(lldb) help cd
|
||||
|
||||
Change the working directory, or cd to ${HOME}.
|
||||
Syntax: cd
|
||||
(lldb) cd
|
||||
Current working directory: /Volumes/data/Users/johnny
|
||||
(lldb) cd /tmp
|
||||
Current working directory: /private/tmp
|
||||
(lldb) pwd
|
||||
/private/tmp
|
||||
(lldb)
|
||||
|
||||
For more examples of customization, look under the ToT/examples/customization
|
||||
directory.
|
||||
1162
external/bsd/llvm/dist/lldb/docs/lldb-gdb-remote.txt
vendored
Normal file
1162
external/bsd/llvm/dist/lldb/docs/lldb-gdb-remote.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
119
external/bsd/llvm/dist/lldb/docs/lldb.1
vendored
Normal file
119
external/bsd/llvm/dist/lldb/docs/lldb.1
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
.Dd 7 June, 2012 \" DATE
|
||||
.Dt LLDB 1 \" Program name and manual section number
|
||||
.Os Darwin \" Operating System
|
||||
.Sh NAME \" Section Header - required - don't modify
|
||||
.Nm lldb
|
||||
.Nd The debugger
|
||||
.Sh SYNOPSIS \" Section Header - required - don't modify
|
||||
.Nm lldb
|
||||
.Op Fl hvdexw
|
||||
.Op Fl a Ar arch
|
||||
.Op Fl l Ar script-language
|
||||
.Op Fl s Ar lldb-commands
|
||||
.Op Fl n Ar process-name
|
||||
.Op Fl p Ar pid
|
||||
.Ar [[--] <PROGRAM-ARG1> <PROGRAM-ARG2> ...]
|
||||
.Sh DESCRIPTION \" Section Header - required - don't modify
|
||||
.Nm
|
||||
is the command line interface for the LLDB debugger library.
|
||||
.Nm
|
||||
can debug C, C++, Objective-C, and Objective-C++ programs.
|
||||
.Pp
|
||||
The following options are available:
|
||||
.Bl -tag -width indent
|
||||
.It Fl h, -help
|
||||
Prints out the usage information for the
|
||||
.Nm
|
||||
debugger. The \fB\-\-help\fR text may be more up-to-date and
|
||||
authoritative than the command line options described in this man
|
||||
page.
|
||||
.It Fl v, -version
|
||||
Prints out the version number of the
|
||||
.Nm
|
||||
debugger.
|
||||
.It Fl a, -arch Ar arch
|
||||
Specifies which architecture
|
||||
.Nm
|
||||
will use when launching the specified program (assuming the provided
|
||||
executable is built for multiple architectures.)
|
||||
.It Fl f, -file Ar filename
|
||||
Specifies the executable file that
|
||||
.nm
|
||||
will be launching / attaching to.
|
||||
.It Fl n, -attach-name Ar process-name
|
||||
Specifies the name of a currently-running process to attach to.
|
||||
(or the name of a process to wait for if \fB\-w\fR is used.)
|
||||
.It Fl w, -wait-for
|
||||
When used in concert with \&\fB\-n process-name\-E\fR, indicates that
|
||||
.Nm
|
||||
should wait for a new process of that name to be started -- and attach
|
||||
to it as early in the process-launch as possible.
|
||||
.It Fl p, -attach-pid Ar pid
|
||||
Specifies a currently running process that
|
||||
.Nm
|
||||
should attach to.
|
||||
.It Fl l, -script-language Ar language
|
||||
Tells the debugger to use the specified scripting language for
|
||||
user-defined scripts, rather than the default. Valid scripting
|
||||
languages that can be specified include Python, Perl, Ruby and Tcl.
|
||||
Currently only the Python extensions have been implemented.
|
||||
.It Fl d, -debug
|
||||
Tells the debugger to print out extra information for debugging itself.
|
||||
.It Fl s, -source Ar filename
|
||||
Tells
|
||||
.Nm
|
||||
to read in and execute the file "\fBfilename\fR", which
|
||||
should contain
|
||||
.Nm
|
||||
commands.
|
||||
.It Fl e, -editor
|
||||
Instructs
|
||||
.Nm
|
||||
to open source files using the host's "external editor" mechanism.
|
||||
.It Fl x, -no-lldbinit
|
||||
Do not automatically parse any '.lldbinit' files.
|
||||
.Pp
|
||||
(If you don't provide -f then the first argument will be the file to be debugged
|
||||
so 'lldb -- <filename> [<ARG1> [<ARG2>]]' also works.
|
||||
Remember to end the options with "--" if any of your arguments have a "-" in them.)
|
||||
.El
|
||||
.Sh USING LLDB
|
||||
In
|
||||
.Nm
|
||||
there is a \fBhelp\fR command which can be used to find descriptions and examples of
|
||||
all
|
||||
.Nm
|
||||
commands. To get help on "\fBbreakpoint set\fR" you would type "\fBhelp breakpoint set\fR".
|
||||
.Pp
|
||||
There is also an \fBapropos\fR command which will search the help text of all commands
|
||||
for a given term -- this is useful for locating a command by topic. For instance, "\fBapropos breakpoint\fR"
|
||||
will list any command that has the word \fBbreakpoint\fR in its help text.
|
||||
.Sh FILES
|
||||
.Nm
|
||||
will read settings/aliases/commands from three files at startup, if they exist.
|
||||
.Pp
|
||||
First, it will read a \fB~/.lldbinit-\fIdebugger\fR command file. If you are using the
|
||||
.Nm
|
||||
command line interface, this is \fB~/.lldbinit-lldb\fR. If you are using
|
||||
.Nm
|
||||
inside a GUI debugger like
|
||||
.Nm Xcode
|
||||
this will be \fB~/.lldbinit-Xcode\fR. This is a useful place to put settings that you
|
||||
want to apply only when a given
|
||||
.Nm
|
||||
command interpreter is used.
|
||||
.Pp
|
||||
Second, \fB~/.lldbinit\fR is read.
|
||||
.Pp
|
||||
Third, an \fR.lldbinit\fR file in the current working directory (where
|
||||
.Nm
|
||||
is started) will be read.
|
||||
.Sh SEE ALSO
|
||||
The LLDB project page http://lldb.llvm.org/ has many different resources for
|
||||
.Nm
|
||||
users -- the gdb/lldb command equivalence page http://lldb.llvm.org/lldb-gdb.html can
|
||||
be especially helpful for users coming from gdb.
|
||||
.Sh BUGS
|
||||
To report bugs, please visit http://llvm.org/bugs/
|
||||
.Sh AUTHOR
|
||||
Maintained by the LLDB Team, http://lldb.llvm.org/
|
||||
@@ -0,0 +1,43 @@
|
||||
|
||||
os command: [['/bin/sh', '-c', 'make clean; make']]
|
||||
stdout: rm -rf "a.out" "a.out.dSYM" main.o main.d
|
||||
g++ -arch x86_64 -gdwarf-2 -O0 -c -o main.o main.cpp
|
||||
g++ -arch x86_64 -gdwarf-2 -O0 main.o -o "a.out"
|
||||
/usr/bin/dsymutil -o "a.out.dSYM" "a.out"
|
||||
|
||||
stderr: None
|
||||
retcode: 0
|
||||
|
||||
|
||||
runCmd: file /Volumes/data/lldb/svn/trunk/test/settings/a.out
|
||||
output: Current executable set to '/Volumes/data/lldb/svn/trunk/test/settings/a.out' (x86_64).
|
||||
|
||||
|
||||
runCmd: settings set target.process.output-path 'stdout.txt'
|
||||
output:
|
||||
|
||||
runCmd: settings show target.process.output-path
|
||||
output: target.process.output-path (string) = 'stdout.txt'
|
||||
|
||||
|
||||
Expecting start string: target.process.output-path (string) = 'stdout.txt'
|
||||
Matched
|
||||
|
||||
runCmd: run
|
||||
output: Process 43533 launched: '/Volumes/data/lldb/svn/trunk/test/settings/a.out' (x86_64)
|
||||
|
||||
|
||||
FAIL
|
||||
|
||||
runCmd: process kill
|
||||
check of return status not required
|
||||
runCmd failed!
|
||||
error: Process must be launched.
|
||||
|
||||
|
||||
Traceback (most recent call last):
|
||||
File "/Volumes/data/lldb/svn/trunk/test/settings/TestSettings.py", line 125, in test_set_output_path
|
||||
"'stdout.txt' exists due to target.process.output-path.")
|
||||
AssertionError: False is not True : 'stdout.txt' exists due to target.process.output-path.
|
||||
|
||||
|
||||
309
external/bsd/llvm/dist/lldb/docs/testsuite/a-detailed-walkthrough.txt
vendored
Normal file
309
external/bsd/llvm/dist/lldb/docs/testsuite/a-detailed-walkthrough.txt
vendored
Normal file
@@ -0,0 +1,309 @@
|
||||
Let's pick test/settings/TestSettings.py as our example. First, notice the file
|
||||
name "TestSettings.py", the Test*.py pattern is the default mechanism that the
|
||||
test driver uses for discovery of tests. As to TestSettings.py, it defines a
|
||||
class:
|
||||
|
||||
class SettingsCommandTestCase(TestBase):
|
||||
|
||||
derived from TestBase, which is defined in test/lldbtest.py and is itself
|
||||
derived from Python's unittest framework's TestCase class. See also
|
||||
http://docs.python.org/library/unittest.html for more details.
|
||||
|
||||
To just run the TestSettings.py test, chdir to the lldb test directory, and then
|
||||
type the following command:
|
||||
|
||||
/Volumes/data/lldb/svn/trunk/test $ ./dotest.py settings
|
||||
----------------------------------------------------------------------
|
||||
Collected 6 tests
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 6 tests in 8.699s
|
||||
|
||||
OK (expected failures=1)
|
||||
/Volumes/data/lldb/svn/trunk/test $
|
||||
|
||||
Pass '-v' option to the test driver to also output verbose descriptions of the
|
||||
individual test cases and their test status:
|
||||
|
||||
/Volumes/data/lldb/svn/trunk/test $ ./dotest.py -v settings
|
||||
----------------------------------------------------------------------
|
||||
Collected 6 tests
|
||||
|
||||
test_set_auto_confirm (TestSettings.SettingsCommandTestCase)
|
||||
Test that after 'set auto-confirm true', manual confirmation should not kick in. ... ok
|
||||
test_set_output_path (TestSettings.SettingsCommandTestCase)
|
||||
Test that setting target.process.output-path for the launched process works. ... expected failure
|
||||
test_set_prompt (TestSettings.SettingsCommandTestCase)
|
||||
Test that 'set prompt' actually changes the prompt. ... ok
|
||||
test_set_term_width (TestSettings.SettingsCommandTestCase)
|
||||
Test that 'set term-width' actually changes the term-width. ... ok
|
||||
test_with_dsym (TestSettings.SettingsCommandTestCase)
|
||||
Test that run-args and env-vars are passed to the launched process. ... ok
|
||||
test_with_dwarf (TestSettings.SettingsCommandTestCase)
|
||||
Test that run-args and env-vars are passed to the launched process. ... ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 6 tests in 5.735s
|
||||
|
||||
OK (expected failures=1)
|
||||
/Volumes/data/lldb/svn/trunk/test $
|
||||
|
||||
Underneath, the '-v' option passes keyword argument verbosity=2 to the
|
||||
Python's unittest.TextTestRunner (see also
|
||||
http://docs.python.org/library/unittest.html#unittest.TextTestRunner). For very
|
||||
detailed descriptions about what's going on during the test, pass '-t' to the
|
||||
test driver, which asks the test driver to trace the commands executed and to
|
||||
display their output. For brevity, the '-t' output is not included here.
|
||||
|
||||
Notice the 'expected failures=1' message at the end of the run. This is because
|
||||
of a bug currently in lldb such that setting target.process.output-path to
|
||||
'stdout.txt' does not have any effect on the redirection of the standard output
|
||||
of the subsequent launched process. We are using unittest2 (a backport of new
|
||||
unittest features for Python 2.4-2.6) to decorate (mark) the particular test
|
||||
method as such:
|
||||
|
||||
@unittest2.expectedFailure
|
||||
# rdar://problem/8435794
|
||||
# settings set target.process.output-path does not seem to work
|
||||
def test_set_output_path(self):
|
||||
|
||||
See http://pypi.python.org/pypi/unittest2 for more details.
|
||||
|
||||
Now let's look inside the test method:
|
||||
|
||||
def test_set_output_path(self):
|
||||
"""Test that setting target.process.output-path for the launched process works."""
|
||||
self.buildDefault()
|
||||
|
||||
exe = os.path.join(os.getcwd(), "a.out")
|
||||
self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
|
||||
|
||||
# Set the output-path and verify it is set.
|
||||
self.runCmd("settings set target.process.output-path 'stdout.txt'")
|
||||
self.expect("settings show target.process.output-path",
|
||||
startstr = "target.process.output-path (string) = 'stdout.txt'")
|
||||
|
||||
self.runCmd("run", RUN_SUCCEEDED)
|
||||
|
||||
# The 'stdout.txt' file should now exist.
|
||||
self.assertTrue(os.path.isfile("stdout.txt"),
|
||||
"'stdout.txt' exists due to target.process.output-path.")
|
||||
|
||||
# Read the output file produced by running the program.
|
||||
with open('stdout.txt', 'r') as f:
|
||||
output = f.read()
|
||||
|
||||
self.expect(output, exe=False,
|
||||
startstr = "This message should go to standard out.")
|
||||
|
||||
The self.buildDefault() statement is used to build a default binary for this
|
||||
test instance. For this particular test case, since we don't really care what
|
||||
debugging format is used, we instruct the build subsystem to build the default
|
||||
binary for us. The base class TestBase has defined three instance methods:
|
||||
|
||||
def buildDefault(self, architecture=None, compiler=None, dictionary=None):
|
||||
"""Platform specific way to build the default binaries."""
|
||||
module = __import__(sys.platform)
|
||||
if not module.buildDefault(self, architecture, compiler, dictionary):
|
||||
raise Exception("Don't know how to build default binary")
|
||||
|
||||
def buildDsym(self, architecture=None, compiler=None, dictionary=None):
|
||||
"""Platform specific way to build binaries with dsym info."""
|
||||
module = __import__(sys.platform)
|
||||
if not module.buildDsym(self, architecture, compiler, dictionary):
|
||||
raise Exception("Don't know how to build binary with dsym")
|
||||
|
||||
def buildDwarf(self, architecture=None, compiler=None, dictionary=None):
|
||||
"""Platform specific way to build binaries with dwarf maps."""
|
||||
module = __import__(sys.platform)
|
||||
if not module.buildDwarf(self, architecture, compiler, dictionary):
|
||||
raise Exception("Don't know how to build binary with dwarf")
|
||||
|
||||
And the test/plugins/darwin.py provides the implementation for all three build
|
||||
methods using the makefile mechanism. We envision that linux plugin can use a
|
||||
similar approach to accomplish the task of building the binaries.
|
||||
|
||||
Mac OS X provides an additional way to manipulate archived DWARF debug symbol
|
||||
files and produces dSYM files. The buildDsym() instance method is used by the
|
||||
test method to build the binary with dsym info. For an example of this,
|
||||
see test/array_types/TestArrayTypes.py:
|
||||
|
||||
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
|
||||
def test_with_dsym_and_run_command(self):
|
||||
"""Test 'frame variable var_name' on some variables with array types."""
|
||||
self.buildDsym()
|
||||
self.array_types()
|
||||
|
||||
This method is decorated with a skipUnless decorator so that it will only gets
|
||||
included into the test suite if the platform it is running on is 'darwin', aka
|
||||
Mac OS X.
|
||||
|
||||
Type 'man dsymutil' for more details.
|
||||
|
||||
After the binary is built, it is time to specify the file to be used as the main
|
||||
executable by lldb:
|
||||
|
||||
exe = os.path.join(os.getcwd(), "a.out")
|
||||
self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
|
||||
|
||||
This is where the attribute assignment:
|
||||
|
||||
class SettingsCommandTestCase(TestBase):
|
||||
|
||||
mydir = "settings"
|
||||
|
||||
which happens right after the SettingsCommandTestCase class declaration comes
|
||||
into place. It specifies the relative directory to the top level 'test' so that
|
||||
the test harness can change its working directory in order to find the
|
||||
executable as well as the source code files. The runCmd() method is defined in
|
||||
the TestBase base class (within test/lldbtest.py) and its purpose is to pass the
|
||||
specified command to the lldb command interpreter. It's like you're typing the
|
||||
command within an interactive lldb session.
|
||||
|
||||
The CURRENT_EXECUTABLE_SET is an assert message defined in the lldbtest module
|
||||
so that it can be reused from other test modules.
|
||||
|
||||
By default, the runCmd() is going to check the return status of the command
|
||||
execution and fails the test if it is not a success. The assert message, in our
|
||||
case CURRENT_EXECUTABLE_SET, is used in the exception printout if this happens.
|
||||
|
||||
There are cases when we don't care about the return status from the command
|
||||
execution. This can be accomplished by passing the keyword argument pair
|
||||
'check=False' to the method.
|
||||
|
||||
After the current executable is set, we'll then execute two more commands:
|
||||
|
||||
# Set the output-path and verify it is set.
|
||||
self.runCmd("settings set target.process.output-path 'stdout.txt'")
|
||||
self.expect("settings show target.process.output-path",
|
||||
SETTING_MSG("target.process.output-path"),
|
||||
startstr = "target.process.output-path (string) = 'stdout.txt'")
|
||||
|
||||
The first uses the 'settings set' command to set the static setting
|
||||
target.process.output-path to be 'stdout.txt', instead of the default
|
||||
'/dev/stdout'. We then immediately issue a 'settings show' command to check
|
||||
that, indeed, the setting did take place. Notice that we use a new method
|
||||
expect() to accomplish the task, which in effect issues a runCmd() behind the
|
||||
door and grabs the output from the command execution and expects to match the
|
||||
start string of the output against what we pass in as the value of the keyword
|
||||
argument pair:
|
||||
|
||||
startstr = "target.process.output-path (string) = 'stdout.txt'"
|
||||
|
||||
Take a look at TestBase.expect() within lldbtest.py for more details. Among
|
||||
other things, it can also match against a list of regexp patterns as well as a
|
||||
list of sub strings. And it can also perform negative matching, i.e., instead
|
||||
of expecting something from the output of command execution, it can perform the
|
||||
action of 'not expecting' something.
|
||||
|
||||
This will launch/run the program:
|
||||
|
||||
self.runCmd("run", RUN_SUCCEEDED)
|
||||
|
||||
And this asserts that the file 'stdout.txt' should be present after running the
|
||||
program.
|
||||
|
||||
# The 'stdout.txt' file should now exist.
|
||||
self.assertTrue(os.path.isfile("stdout.txt"),
|
||||
"'stdout.txt' exists due to target.process.output-path.")
|
||||
|
||||
Also take a look at main.cpp which emits some message to the stdout. Now, if we
|
||||
pass this assertion, it's time to examine the contents of the file to make sure
|
||||
it contains the same message as programmed in main.cpp:
|
||||
|
||||
# Read the output file produced by running the program.
|
||||
with open('stdout.txt', 'r') as f:
|
||||
output = f.read()
|
||||
|
||||
self.expect(output, exe=False,
|
||||
startstr = "This message should go to standard out.")
|
||||
|
||||
We open the file and read its contents into output, then issue an expect()
|
||||
method. The 'exe=False' keyword argument pair tells expect() that don't try to
|
||||
execute the first arg as a command at all. Instead, treat it as a string to
|
||||
match against whatever is thrown in as keyword argument pairs!
|
||||
|
||||
There are also other test methods present in the TestSettings.py mode:
|
||||
test_set_prompt(), test_set_term_width(), test_set_auto_confirm(),
|
||||
test_with_dsym(), and test_with_dwarf(). We are using the default test loader
|
||||
from unittest framework, which uses the 'test' method name prefix to identify
|
||||
test methods automatically.
|
||||
|
||||
This finishes the walkthrough of the test method test_set_output_path(self).
|
||||
Before we say goodbye, notice the little method definition at the top of the
|
||||
file:
|
||||
|
||||
@classmethod
|
||||
def classCleanup(cls):
|
||||
system(["/bin/sh", "-c", "rm -f output.txt"])
|
||||
system(["/bin/sh", "-c", "rm -f stdout.txt"])
|
||||
|
||||
This is a classmethod (as shown by the @classmethod decorator) which allows the
|
||||
individual test class to perform cleanup actions after the test harness finishes
|
||||
with the particular test class. This is part of the so-called test fixture in
|
||||
the unittest framework. From http://docs.python.org/library/unittest.html:
|
||||
|
||||
A test fixture represents the preparation needed to perform one or more tests,
|
||||
and any associate cleanup actions. This may involve, for example, creating
|
||||
temporary or proxy databases, directories, or starting a server process.
|
||||
|
||||
The TestBase class uses such fixture with setUp(self), tearDown(self),
|
||||
setUpClass(cls), and tearDownClass(cls). And within teraDownClass(cls), it
|
||||
checks whether the current class has an attribute named 'classCleanup', and
|
||||
executes as a method if present. In this particular case, the classCleanup()
|
||||
calls a utility function system() defined in lldbtest.py in order to remove the
|
||||
files created by running the program as the tests are executed.
|
||||
|
||||
This system() function uses the Python subprocess module to spawn the process
|
||||
and to retrieve its results. If the test instance passes the keyword argument
|
||||
pair 'sender=self', the detailed command execution through the operating system
|
||||
also gets recorded in a session object. If the test instance fails or errors,
|
||||
the session info automatically gets dumped to a file grouped under a directory
|
||||
named after the timestamp of the particular test suite run.
|
||||
|
||||
For simple cases, look for the timestamp directory in the same directory of the
|
||||
test driver program dotest.py. For example, if we comment out the
|
||||
@expectedFailure decorator for TestSettings.py, and then run the test module:
|
||||
|
||||
/Volumes/data/lldb/svn/trunk/test $ ./dotest.py -v settings
|
||||
----------------------------------------------------------------------
|
||||
Collected 6 tests
|
||||
|
||||
test_set_auto_confirm (TestSettings.SettingsCommandTestCase)
|
||||
Test that after 'set auto-confirm true', manual confirmation should not kick in. ... ok
|
||||
test_set_output_path (TestSettings.SettingsCommandTestCase)
|
||||
Test that setting target.process.output-path for the launched process works. ... FAIL
|
||||
test_set_prompt (TestSettings.SettingsCommandTestCase)
|
||||
Test that 'set prompt' actually changes the prompt. ... ok
|
||||
test_set_term_width (TestSettings.SettingsCommandTestCase)
|
||||
Test that 'set term-width' actually changes the term-width. ... ok
|
||||
test_with_dsym (TestSettings.SettingsCommandTestCase)
|
||||
Test that run-args and env-vars are passed to the launched process. ... ok
|
||||
test_with_dwarf (TestSettings.SettingsCommandTestCase)
|
||||
Test that run-args and env-vars are passed to the launched process. ... ok
|
||||
|
||||
======================================================================
|
||||
FAIL: test_set_output_path (TestSettings.SettingsCommandTestCase)
|
||||
Test that setting target.process.output-path for the launched process works.
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "/Volumes/data/lldb/svn/trunk/test/settings/TestSettings.py", line 125, in test_set_output_path
|
||||
"'stdout.txt' exists due to target.process.output-path.")
|
||||
AssertionError: False is not True : 'stdout.txt' exists due to target.process.output-path.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 6 tests in 8.219s
|
||||
|
||||
FAILED (failures=1)
|
||||
/Volumes/data/lldb/svn/trunk/test $ ls 2010-10-19-14:10:49.059609
|
||||
|
||||
NOTE: This directory name has been changed to not contain the ':' character
|
||||
which is not allowed in windows platforms. We'll change the ':' to '_'
|
||||
and get rid of the microsecond resolution by modifying the test driver.
|
||||
|
||||
TestSettings.SettingsCommandTestCase.test_set_output_path.log
|
||||
/Volumes/data/lldb/svn/trunk/test $
|
||||
|
||||
We get one failure and a timestamp directory 2010-10-19-14:10:49.059609.
|
||||
For education purposes, the directory and its contents are reproduced here in
|
||||
the same directory as the current file.
|
||||
93
external/bsd/llvm/dist/lldb/docs/testsuite/best-practices.txt
vendored
Normal file
93
external/bsd/llvm/dist/lldb/docs/testsuite/best-practices.txt
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
This document attempts to point out some best practices that prove to be helpful
|
||||
when building new test cases in the tot/test directory. Everyone is welcomed to
|
||||
add/modify contents into this file.
|
||||
|
||||
o Do not use hard-coded line numbers in your test case. Instead, try to tag the
|
||||
line with some distinguishing pattern, and use the function line_number()
|
||||
defined in lldbtest.py which takes filename and string_to_match as arguments
|
||||
and returns the line number.
|
||||
|
||||
As an example, take a look at test/breakpoint_conditions/main.c which has these
|
||||
two lines:
|
||||
|
||||
return c(val); // Find the line number of c's parent call here.
|
||||
|
||||
and
|
||||
|
||||
return val + 3; // Find the line number of function "c" here.
|
||||
|
||||
The Python test case TestBreakpointConditions.py uses the comment strings to
|
||||
find the line numbers during setUp(self) and use them later on to verify that
|
||||
the correct breakpoint is being stopped on and that its parent frame also has
|
||||
the correct line number as intended through the breakpoint condition.
|
||||
|
||||
o Take advantage of the unittest framework's decorator features to properly
|
||||
mark your test class or method for platform-specific tests.
|
||||
|
||||
As an example, take a look at test/forward/TestForwardDeclaration.py which has
|
||||
these lines:
|
||||
|
||||
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
|
||||
def test_with_dsym_and_run_command(self):
|
||||
"""Display *bar_ptr when stopped on a function with forward declaration of struct bar."""
|
||||
self.buildDsym()
|
||||
self.forward_declaration()
|
||||
|
||||
This tells the test harness that unless we are running "darwin", the test should
|
||||
be skipped. This is because we are asking to build the binaries with dsym debug
|
||||
info, which is only available on the darwin platforms.
|
||||
|
||||
o Cleanup after yourself. A classic example of this can be found in test/types/
|
||||
TestFloatTypes.py:
|
||||
|
||||
def test_float_types_with_dsym(self):
|
||||
"""Test that float-type variables are displayed correctly."""
|
||||
d = {'CXX_SOURCES': 'float.cpp'}
|
||||
self.buildDsym(dictionary=d)
|
||||
self.setTearDownCleanup(dictionary=d)
|
||||
self.float_type()
|
||||
|
||||
...
|
||||
|
||||
def test_double_type_with_dsym(self):
|
||||
"""Test that double-type variables are displayed correctly."""
|
||||
d = {'CXX_SOURCES': 'double.cpp'}
|
||||
self.buildDsym(dictionary=d)
|
||||
self.setTearDownCleanup(dictionary=d)
|
||||
self.double_type()
|
||||
|
||||
This tests different data structures composed of float types to verify that what
|
||||
the debugger prints out matches what the compiler does for different variables
|
||||
of these types. We're using a dictionary to pass the build parameters to the
|
||||
build system. After a particular test instance is done, it is a good idea to
|
||||
clean up the files built. This eliminates the chance that some leftover files
|
||||
can interfere with the build phase for the next test instance and render it
|
||||
invalid.
|
||||
|
||||
TestBase.setTearDownCleanup(self, dictionary) defined in lldbtest.py is created
|
||||
to cope with this use case by taking the same build parameters in order to do
|
||||
the cleanup when we are finished with a test instance, during
|
||||
TestBase.tearDown(self).
|
||||
|
||||
o Class-wise cleanup after yourself.
|
||||
|
||||
TestBase.tearDownClass(cls) provides a mechanism to invoke the platform-specific
|
||||
cleanup after finishing with a test class. A test class can have more than one
|
||||
test methods, so the tearDownClass(cls) method gets run after all the test
|
||||
methods have been executed by the test harness.
|
||||
|
||||
The default cleanup action performed by the plugins/darwin.py module invokes the
|
||||
"make clean" os command.
|
||||
|
||||
If this default cleanup is not enough, individual class can provide an extra
|
||||
cleanup hook with a class method named classCleanup , for example,
|
||||
in test/breakpoint_command/TestBreakpointCommand.py:
|
||||
|
||||
@classmethod
|
||||
def classCleanup(cls):
|
||||
system(["/bin/sh", "-c", "rm -f output.txt"])
|
||||
|
||||
The 'output.txt' file gets generated during the test run, so it makes sense to
|
||||
explicitly spell out the action in the same TestBreakpointCommand.py file to do
|
||||
the cleanup instead of artificially adding it as part of the default cleanup
|
||||
action which serves to cleanup those intermediate and a.out files.
|
||||
5
external/bsd/llvm/dist/lldb/examples/customization/bin-utils/.lldbinit
vendored
Normal file
5
external/bsd/llvm/dist/lldb/examples/customization/bin-utils/.lldbinit
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
# So that ~/binutils.py takes precedence.
|
||||
script sys.path[:0] = [os.path.expanduser('~')]
|
||||
script import binutils
|
||||
command script add -f binutils.itob itob
|
||||
command script add -f binutils.utob utob
|
||||
36
external/bsd/llvm/dist/lldb/examples/customization/bin-utils/README
vendored
Normal file
36
external/bsd/llvm/dist/lldb/examples/customization/bin-utils/README
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
Files in this directory:
|
||||
|
||||
o .lldbinit:
|
||||
|
||||
An example lldb init file that imports the binutils.py module and adds the
|
||||
following commands: 'itob' and 'utob'.
|
||||
|
||||
o binutils.py:
|
||||
|
||||
Python module which provides implementation for the 'itob' and 'utob' commands.
|
||||
|
||||
o README:
|
||||
|
||||
The file you are reading now.
|
||||
|
||||
================================================================================
|
||||
The following terminal output shows an interaction with lldb using the .lldbinit
|
||||
and the binutils.py files which are located in my HOME directory. The lldb init
|
||||
file imports the utils Python module and adds the 'itob' and 'utob' commands.
|
||||
|
||||
$ /Volumes/data/lldb/svn/trunk/build/Debug/lldb
|
||||
(lldb) help itob
|
||||
Convert the integer to print its two's complement representation.
|
||||
args[0] (mandatory) is the integer to be converted
|
||||
args[1] (mandatory) is the bit width of the two's complement representation
|
||||
args[2] (optional) if specified, turns on verbose printing
|
||||
Syntax: itob
|
||||
(lldb) itob -5 4
|
||||
[1, 0, 1, 1]
|
||||
(lldb) itob -5 32 v
|
||||
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1]
|
||||
(lldb) utob 0xABCD 32 v
|
||||
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1]
|
||||
(lldb)
|
||||
122
external/bsd/llvm/dist/lldb/examples/customization/bin-utils/binutils.py
vendored
Normal file
122
external/bsd/llvm/dist/lldb/examples/customization/bin-utils/binutils.py
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
"Collection of tools for displaying bit representation of numbers."""
|
||||
|
||||
import StringIO
|
||||
|
||||
def binary(n, width=None):
|
||||
"""
|
||||
Return a list of (0|1)'s for the binary representation of n where n >= 0.
|
||||
If you specify a width, it must be > 0, otherwise it is ignored. The list
|
||||
could be padded with 0 bits if width is specified.
|
||||
"""
|
||||
l = []
|
||||
if width and width <= 0:
|
||||
width = None
|
||||
while n > 0:
|
||||
l.append(1 if n&1 else 0)
|
||||
n = n >> 1
|
||||
|
||||
if width:
|
||||
for i in range(width - len(l)):
|
||||
l.append(0)
|
||||
|
||||
l.reverse()
|
||||
return l
|
||||
|
||||
def twos_complement(n, width):
|
||||
"""
|
||||
Return a list of (0|1)'s for the binary representation of a width-bit two's
|
||||
complement numeral system of an integer n which may be negative.
|
||||
"""
|
||||
val = 2**(width-1)
|
||||
if n >= 0:
|
||||
if n > (val-1):
|
||||
return None
|
||||
# It is safe to represent n with width-bits.
|
||||
return binary(n, width)
|
||||
|
||||
if n < 0:
|
||||
if abs(n) > val:
|
||||
return None
|
||||
# It is safe to represent n (a negative int) with width-bits.
|
||||
return binary(val*2 - abs(n))
|
||||
|
||||
# print binary(0xABCD)
|
||||
# [1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1]
|
||||
# print binary(0x1F, 8)
|
||||
# [0, 0, 0, 1, 1, 1, 1, 1]
|
||||
# print twos_complement(-5, 4)
|
||||
# [1, 0, 1, 1]
|
||||
# print twos_complement(7, 4)
|
||||
# [0, 1, 1, 1]
|
||||
# print binary(7)
|
||||
# [1, 1, 1]
|
||||
# print twos_complement(-5, 64)
|
||||
# [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1]
|
||||
|
||||
def positions(width):
|
||||
"""Helper function returning a list describing the bit positions.
|
||||
Bit positions greater than 99 are truncated to 2 digits, for example,
|
||||
100 -> 00 and 127 -> 27."""
|
||||
return ['{0:2}'.format(i)[-2:] for i in reversed(range(width))]
|
||||
|
||||
|
||||
def utob(debugger, command_line, result, dict):
|
||||
"""Convert the unsigned integer to print its binary representation.
|
||||
args[0] (mandatory) is the unsigned integer to be converted
|
||||
args[1] (optional) is the bit width of the binary representation
|
||||
args[2] (optional) if specified, turns on verbose printing"""
|
||||
args = command_line.split()
|
||||
try:
|
||||
n = int(args[0], 0)
|
||||
width = None
|
||||
if len(args) > 1:
|
||||
width = int(args[1], 0)
|
||||
if width < 0:
|
||||
width = 0
|
||||
except:
|
||||
print utob.__doc__
|
||||
return
|
||||
|
||||
if len(args) > 2:
|
||||
verbose = True
|
||||
else:
|
||||
verbose = False
|
||||
|
||||
bits = binary(n, width)
|
||||
if not bits:
|
||||
print "insufficient width value: %d" % width
|
||||
return
|
||||
if verbose and width > 0:
|
||||
pos = positions(width)
|
||||
print ' '+' '.join(pos)
|
||||
print ' %s' % str(bits)
|
||||
|
||||
def itob(debugger, command_line, result, dict):
|
||||
"""Convert the integer to print its two's complement representation.
|
||||
args[0] (mandatory) is the integer to be converted
|
||||
args[1] (mandatory) is the bit width of the two's complement representation
|
||||
args[2] (optional) if specified, turns on verbose printing"""
|
||||
args = command_line.split()
|
||||
try:
|
||||
n = int(args[0], 0)
|
||||
width = int(args[1], 0)
|
||||
if width < 0:
|
||||
width = 0
|
||||
except:
|
||||
print itob.__doc__
|
||||
return
|
||||
|
||||
if len(args) > 2:
|
||||
verbose = True
|
||||
else:
|
||||
verbose = False
|
||||
|
||||
bits = twos_complement(n, width)
|
||||
if not bits:
|
||||
print "insufficient width value: %d" % width
|
||||
return
|
||||
if verbose and width > 0:
|
||||
pos = positions(width)
|
||||
print ' '+' '.join(pos)
|
||||
print ' %s' % str(bits)
|
||||
|
||||
40
external/bsd/llvm/dist/lldb/examples/customization/import-python/README
vendored
Normal file
40
external/bsd/llvm/dist/lldb/examples/customization/import-python/README
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
Files in this directory:
|
||||
|
||||
o importcmd.py:
|
||||
|
||||
Python module which provides implementation for the 'import' command.
|
||||
|
||||
o README:
|
||||
|
||||
The file you are reading now.
|
||||
|
||||
================================================================================
|
||||
The import command defined by importcmd.py can be used in LLDB to load a Python
|
||||
module given its full pathname.
|
||||
The command works by extending Python's sys.path lookup to include the path to
|
||||
the module to be imported when required, and then going through the language
|
||||
ordinary 'import' mechanism. In this respect, modules imported from LLDB command
|
||||
line should not be distinguishable from those imported using the script interpreter.
|
||||
The following terminal output shows an interaction with lldb using this new command.
|
||||
|
||||
Enrico-Granatas-MacBook-Pro:Debug enricogranata$ ./lldb
|
||||
(lldb) script import importcmd
|
||||
(lldb) command script add import -f importcmd.pyimport_cmd
|
||||
(lldb) import ../demo.py
|
||||
(lldb) script demo.test_function('hello world')
|
||||
I am a Python function that says hello world
|
||||
(lldb) quit
|
||||
Enrico-Granatas-MacBook-Pro:Debug enricogranata$
|
||||
|
||||
Of course, the commands to import the importcmd.py module and to define the import
|
||||
command, can be included in the .lldbinit file to make this feature available at
|
||||
debugger startup
|
||||
|
||||
WARNING: The import command defined by importcmd.py is now obsolete
|
||||
In TOT LLDB, you can say:
|
||||
(lldb) command script import ../demo.py
|
||||
(lldb) script demo.test_function('hello world')
|
||||
I am a Python function that says hello world
|
||||
(lldb) quit
|
||||
|
||||
using the native "command script import" command, which offers a superset of what the import command provided by importcmd.py does
|
||||
31
external/bsd/llvm/dist/lldb/examples/customization/import-python/importcmd.py
vendored
Normal file
31
external/bsd/llvm/dist/lldb/examples/customization/import-python/importcmd.py
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
import sys,os,lldb
|
||||
def check_has_dir_in_path(dirname):
|
||||
return sys.path.__contains__(dirname);
|
||||
|
||||
def ensure_has_dir_in_path(dirname):
|
||||
dirname = os.path.abspath(dirname)
|
||||
if not (check_has_dir_in_path(dirname)):
|
||||
sys.path.append(dirname);
|
||||
|
||||
def do_import(debugger,modname):
|
||||
if (len(modname) > 4 and modname[-4:] == '.pyc'):
|
||||
modname = modname[:-4]
|
||||
if (len(modname) > 3 and modname[-3:] == '.py'):
|
||||
modname = modname[:-3]
|
||||
debugger.HandleCommand("script import " + modname)
|
||||
|
||||
def pyimport_cmd(debugger, args, result, dict):
|
||||
"""Import a Python module given its full path"""
|
||||
print 'WARNING: obsolete feature - use native command "command script import"'
|
||||
if args == "":
|
||||
return "no module path given";
|
||||
if not (os.sep in args):
|
||||
modname = args
|
||||
ensure_has_dir_in_path('.')
|
||||
else:
|
||||
endofdir = args.rfind(os.sep)
|
||||
modname = args[endofdir+1:]
|
||||
args = args[0:endofdir]
|
||||
ensure_has_dir_in_path(args)
|
||||
do_import(debugger,modname)
|
||||
return None
|
||||
7
external/bsd/llvm/dist/lldb/examples/customization/pwd-cd-and-system/.lldbinit
vendored
Normal file
7
external/bsd/llvm/dist/lldb/examples/customization/pwd-cd-and-system/.lldbinit
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
script import os, sys
|
||||
# So that ~/utils.py takes precedence.
|
||||
script sys.path[:0] = [os.path.expanduser('~')]
|
||||
script import utils
|
||||
command alias pwd script print os.getcwd()
|
||||
command script add -f utils.chdir cd
|
||||
command script add -f utils.system system
|
||||
41
external/bsd/llvm/dist/lldb/examples/customization/pwd-cd-and-system/README
vendored
Normal file
41
external/bsd/llvm/dist/lldb/examples/customization/pwd-cd-and-system/README
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
Files in this directory:
|
||||
|
||||
o .lldbinit:
|
||||
|
||||
An example lldb init file that imports the utils.py module and adds the
|
||||
following commands: 'pwd', 'cd', and 'system'.
|
||||
|
||||
o utils.py:
|
||||
|
||||
Python module which provides implementation for the 'cd' and 'system' commands.
|
||||
|
||||
o README:
|
||||
|
||||
The file you are reading now.
|
||||
|
||||
================================================================================
|
||||
The following terminal output shows an interaction with lldb using the .lldbinit
|
||||
and the utils.py files which are located in my HOME directory. The lldb init
|
||||
file imports the utils Python module and adds the 'pwd', 'cd', and 'system'
|
||||
commands.
|
||||
|
||||
Johnnys-MacBook-Pro:multiple_threads johnny$ pwd
|
||||
/Volumes/data/lldb/svn/trunk/test/functionalities/watchpoint/multiple_threads
|
||||
Johnnys-MacBook-Pro:multiple_threads johnny$ lldb
|
||||
(lldb) pwd
|
||||
/Volumes/data/lldb/svn/trunk/test/functionalities/watchpoint/multiple_threads
|
||||
(lldb) cd ..
|
||||
Current working directory: /Volumes/data/lldb/svn/trunk/test/functionalities/watchpoint
|
||||
(lldb) help system
|
||||
|
||||
Execute the command (a string) in a subshell.
|
||||
Syntax: system
|
||||
(lldb) system ls -l
|
||||
total 0
|
||||
drwxr-xr-x 7 johnny admin 238 Oct 11 17:24 hello_watchlocation
|
||||
drwxr-xr-x 7 johnny admin 238 Oct 11 17:24 hello_watchpoint
|
||||
drwxr-xr-x 7 johnny admin 238 Oct 11 17:24 multiple_threads
|
||||
drwxr-xr-x 7 johnny admin 238 Oct 11 17:24 watchpoint_commands
|
||||
|
||||
retcode: 0
|
||||
(lldb)
|
||||
49
external/bsd/llvm/dist/lldb/examples/customization/pwd-cd-and-system/utils.py
vendored
Normal file
49
external/bsd/llvm/dist/lldb/examples/customization/pwd-cd-and-system/utils.py
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
"""Utility for changing directories and execution of commands in a subshell."""
|
||||
|
||||
import os, shlex, subprocess
|
||||
|
||||
# Store the previous working directory for the 'cd -' command.
|
||||
class Holder:
|
||||
"""Holds the _prev_dir_ class attribute for chdir() function."""
|
||||
_prev_dir_ = None
|
||||
|
||||
@classmethod
|
||||
def prev_dir(cls):
|
||||
return cls._prev_dir_
|
||||
|
||||
@classmethod
|
||||
def swap(cls, dir):
|
||||
cls._prev_dir_ = dir
|
||||
|
||||
def chdir(debugger, args, result, dict):
|
||||
"""Change the working directory, or cd to ${HOME}.
|
||||
You can also issue 'cd -' to change to the previous working directory."""
|
||||
new_dir = args.strip()
|
||||
if not new_dir:
|
||||
new_dir = os.path.expanduser('~')
|
||||
elif new_dir == '-':
|
||||
if not Holder.prev_dir():
|
||||
# Bad directory, not changing.
|
||||
print "bad directory, not changing"
|
||||
return
|
||||
else:
|
||||
new_dir = Holder.prev_dir()
|
||||
|
||||
Holder.swap(os.getcwd())
|
||||
os.chdir(new_dir)
|
||||
print "Current working directory: %s" % os.getcwd()
|
||||
|
||||
def system(debugger, command_line, result, dict):
|
||||
"""Execute the command (a string) in a subshell."""
|
||||
args = shlex.split(command_line)
|
||||
process = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
output, error = process.communicate()
|
||||
retcode = process.poll()
|
||||
if output and error:
|
||||
print "stdout=>\n", output
|
||||
print "stderr=>\n", error
|
||||
elif output:
|
||||
print output
|
||||
elif error:
|
||||
print error
|
||||
print "retcode:", retcode
|
||||
1135
external/bsd/llvm/dist/lldb/examples/darwin/heap_find/heap.py
vendored
Normal file
1135
external/bsd/llvm/dist/lldb/examples/darwin/heap_find/heap.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
33
external/bsd/llvm/dist/lldb/examples/darwin/heap_find/heap/Makefile
vendored
Normal file
33
external/bsd/llvm/dist/lldb/examples/darwin/heap_find/heap/Makefile
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
#----------------------------------------------------------------------
|
||||
# Fill in the source files to build
|
||||
#----------------------------------------------------------------------
|
||||
# Uncomment line below for debugging shell commands
|
||||
# SHELL = /bin/sh -x
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Change any build/tool options needed
|
||||
#----------------------------------------------------------------------
|
||||
ARCH ?= x86_64
|
||||
CFLAGS ?=-arch $(ARCH) -gdwarf-2 -O0
|
||||
CXX ?= $(shell xcrun -find clang++)
|
||||
EXE ?= libheap.dylib
|
||||
DSYM ?= $(EXE).dSYM
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Compile the executable from all the objects (default rule) with no
|
||||
# dsym file.
|
||||
#----------------------------------------------------------------------
|
||||
$(EXE) : heap_find.cpp
|
||||
$(CXX) $(CFLAGS) -install_name "@executable_path/libheap.dylib" -dynamiclib -lobjc heap_find.cpp -o "$(EXE)"
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Include all of the makefiles for each source file so we don't have
|
||||
# to manually track all of the prerequisites for each source file.
|
||||
#----------------------------------------------------------------------
|
||||
.PHONY: clean
|
||||
all: $(EXE)
|
||||
clean:
|
||||
rm -rf "$(EXE)" "$(DSYM)"
|
||||
|
||||
|
||||
|
||||
1071
external/bsd/llvm/dist/lldb/examples/darwin/heap_find/heap/heap_find.cpp
vendored
Normal file
1071
external/bsd/llvm/dist/lldb/examples/darwin/heap_find/heap/heap_find.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
18
external/bsd/llvm/dist/lldb/examples/functions/Makefile
vendored
Normal file
18
external/bsd/llvm/dist/lldb/examples/functions/Makefile
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
LEVEL = ../../test/make
|
||||
|
||||
CXX_SOURCES := main.cpp
|
||||
|
||||
EXE := lldb-functions
|
||||
USE_LIBCPP := 1
|
||||
|
||||
MY_OS = $(shell uname -s)
|
||||
|
||||
ifeq "$(MY_OS)" "Darwin"
|
||||
LLDB_BUILD_DIR ?= /Applications/Xcode.app/Contents/SharedFrameworks
|
||||
LD_EXTRAS ?= -framework LLDB -Wl,-rpath,"$(LLDB_BUILD_DIR)"
|
||||
FRAMEWORK_INCLUDES=-F"$(LLDB_BUILD_DIR)"
|
||||
else
|
||||
LD_EXTRAS ?= $(LLDB_BUILD_DIR)/_lldb.so
|
||||
endif
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
||||
364
external/bsd/llvm/dist/lldb/examples/functions/main.cpp
vendored
Normal file
364
external/bsd/llvm/dist/lldb/examples/functions/main.cpp
vendored
Normal file
@@ -0,0 +1,364 @@
|
||||
//===-- main.cpp ------------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <LLDB/LLDB.h>
|
||||
#else
|
||||
#include "LLDB/SBBlock.h"
|
||||
#include "LLDB/SBCompileUnit.h"
|
||||
#include "LLDB/SBDebugger.h"
|
||||
#include "LLDB/SBFunction.h"
|
||||
#include "LLDB/SBModule.h"
|
||||
#include "LLDB/SBStream.h"
|
||||
#include "LLDB/SBSymbol.h"
|
||||
#include "LLDB/SBTarget.h"
|
||||
#include "LLDB/SBThread.h"
|
||||
#include "LLDB/SBProcess.h"
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace lldb;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// This quick sample code shows how to create a debugger instance and
|
||||
// create an executable target without adding dependent shared
|
||||
// libraries. It will then set a regular expression breakpoint to get
|
||||
// breakpoint locations for all functions in the module, and use the
|
||||
// locations to extract the symbol context for each location. Then it
|
||||
// dumps all // information about the function: its name, file address
|
||||
// range, the return type (if any), and all argument types.
|
||||
//
|
||||
// To build the program, type (while in this directory):
|
||||
//
|
||||
// $ make
|
||||
//
|
||||
// then to run this on MacOSX, specify the path to your LLDB.framework
|
||||
// library using the DYLD_FRAMEWORK_PATH option and run the executable
|
||||
//
|
||||
// $ DYLD_FRAMEWORK_PATH=/Volumes/data/lldb/tot/build/Debug ./a.out executable_path1 [executable_path2 ...]
|
||||
//----------------------------------------------------------------------
|
||||
class LLDBSentry
|
||||
{
|
||||
public:
|
||||
LLDBSentry() {
|
||||
// Initialize LLDB
|
||||
SBDebugger::Initialize();
|
||||
}
|
||||
~LLDBSentry() {
|
||||
// Terminate LLDB
|
||||
SBDebugger::Terminate();
|
||||
}
|
||||
};
|
||||
|
||||
static struct option g_long_options[] =
|
||||
{
|
||||
{ "arch", required_argument, NULL, 'a' },
|
||||
{ "canonical", no_argument, NULL, 'c' },
|
||||
{ "extern", no_argument, NULL, 'x' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "platform", required_argument, NULL, 'p' },
|
||||
{ "verbose", no_argument, NULL, 'v' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
#define PROGRAM_NAME "lldb-functions"
|
||||
void
|
||||
usage ()
|
||||
{
|
||||
puts (
|
||||
"NAME\n"
|
||||
" " PROGRAM_NAME " -- extract all function signatures from one or more binaries.\n"
|
||||
"\n"
|
||||
"SYNOPSIS\n"
|
||||
" " PROGRAM_NAME " [[--arch=<ARCH>] [--platform=<PLATFORM>] [--verbose] [--help] [--canonical] --] <PATH> [<PATH>....]\n"
|
||||
"\n"
|
||||
"DESCRIPTION\n"
|
||||
" Loads the executable pointed to by <PATH> and dumps complete signatures for all functions that have debug information.\n"
|
||||
"\n"
|
||||
"EXAMPLE\n"
|
||||
" " PROGRAM_NAME " --arch=x86_64 /usr/lib/dyld\n"
|
||||
);
|
||||
exit(0);
|
||||
}
|
||||
int
|
||||
main (int argc, char const *argv[])
|
||||
{
|
||||
// Use a sentry object to properly initialize/terminate LLDB.
|
||||
LLDBSentry sentry;
|
||||
|
||||
SBDebugger debugger (SBDebugger::Create());
|
||||
|
||||
// Create a debugger instance so we can create a target
|
||||
if (!debugger.IsValid())
|
||||
fprintf (stderr, "error: failed to create a debugger object\n");
|
||||
|
||||
bool show_usage = false;
|
||||
bool verbose = false;
|
||||
bool canonical = false;
|
||||
bool external_only = false;
|
||||
const char *arch = NULL;
|
||||
const char *platform = NULL;
|
||||
std::string short_options("h?");
|
||||
for (const struct option *opt = g_long_options; opt->name; ++opt)
|
||||
{
|
||||
if (isprint(opt->val))
|
||||
{
|
||||
short_options.append(1, (char)opt->val);
|
||||
switch (opt->has_arg)
|
||||
{
|
||||
case no_argument:
|
||||
break;
|
||||
case required_argument:
|
||||
short_options.append(1, ':');
|
||||
break;
|
||||
case optional_argument:
|
||||
short_options.append(2, ':');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef __GLIBC__
|
||||
optind = 0;
|
||||
#else
|
||||
optreset = 1;
|
||||
optind = 1;
|
||||
#endif
|
||||
char ch;
|
||||
while ((ch = getopt_long_only(argc, (char * const *)argv, short_options.c_str(), g_long_options, 0)) != -1)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
if (arch != NULL)
|
||||
{
|
||||
fprintf (stderr, "error: the --arch option can only be specified once\n");
|
||||
exit(1);
|
||||
}
|
||||
arch = optarg;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
canonical = true;
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
external_only = true;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
platform = optarg;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
verbose = true;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
case '?':
|
||||
default:
|
||||
show_usage = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
const bool add_dependent_libs = false;
|
||||
SBError error;
|
||||
for (int arg_idx = 0; arg_idx < argc; ++arg_idx)
|
||||
{
|
||||
// The first argument is the file path we want to look something up in
|
||||
const char *exe_file_path = argv[arg_idx];
|
||||
|
||||
// Create a target using the executable.
|
||||
SBTarget target = debugger.CreateTarget (exe_file_path,
|
||||
arch,
|
||||
platform,
|
||||
add_dependent_libs,
|
||||
error);
|
||||
|
||||
if (error.Success())
|
||||
{
|
||||
if (target.IsValid())
|
||||
{
|
||||
SBFileSpec exe_file_spec (exe_file_path, true);
|
||||
SBModule module (target.FindModule (exe_file_spec));
|
||||
SBFileSpecList comp_unit_list;
|
||||
|
||||
if (module.IsValid())
|
||||
{
|
||||
char command[1024];
|
||||
lldb::SBCommandReturnObject command_result;
|
||||
snprintf (command, sizeof(command), "add-dsym --uuid %s", module.GetUUIDString());
|
||||
debugger.GetCommandInterpreter().HandleCommand (command, command_result);
|
||||
if (!command_result.Succeeded())
|
||||
{
|
||||
fprintf (stderr, "error: couldn't locate debug symbols for '%s'\n", exe_file_path);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
SBFileSpecList module_list;
|
||||
module_list.Append(exe_file_spec);
|
||||
SBBreakpoint bp = target.BreakpointCreateByRegex (".", module_list, comp_unit_list);
|
||||
|
||||
const size_t num_locations = bp.GetNumLocations();
|
||||
for (uint32_t bp_loc_idx=0; bp_loc_idx<num_locations; ++bp_loc_idx)
|
||||
{
|
||||
SBBreakpointLocation bp_loc = bp.GetLocationAtIndex(bp_loc_idx);
|
||||
SBSymbolContext sc (bp_loc.GetAddress().GetSymbolContext(eSymbolContextEverything));
|
||||
if (sc.IsValid())
|
||||
{
|
||||
if (sc.GetBlock().GetContainingInlinedBlock().IsValid())
|
||||
{
|
||||
// Skip inlined functions
|
||||
continue;
|
||||
}
|
||||
SBFunction function (sc.GetFunction());
|
||||
if (function.IsValid())
|
||||
{
|
||||
addr_t lo_pc = function.GetStartAddress().GetFileAddress();
|
||||
if (lo_pc == LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
// Skip functions that don't have concrete instances in the binary
|
||||
continue;
|
||||
}
|
||||
addr_t hi_pc = function.GetEndAddress().GetFileAddress();
|
||||
const char *func_demangled_name = function.GetName();
|
||||
const char *func_mangled_name = function.GetMangledName();
|
||||
|
||||
bool dump = true;
|
||||
const bool is_objc_method = ((func_demangled_name[0] == '-') || (func_demangled_name[0] == '+')) && (func_demangled_name[1] == '[');
|
||||
if (external_only)
|
||||
{
|
||||
// Dump all objective C methods, or external symbols
|
||||
dump = is_objc_method;
|
||||
if (!dump)
|
||||
dump = sc.GetSymbol().IsExternal();
|
||||
}
|
||||
|
||||
if (dump)
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
printf ("\n name: %s\n", func_demangled_name);
|
||||
if (func_mangled_name)
|
||||
printf ("mangled: %s\n", func_mangled_name);
|
||||
printf (" range: [0x%16.16llx - 0x%16.16llx)\n type: ", lo_pc, hi_pc);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("[0x%16.16llx - 0x%16.16llx) ", lo_pc, hi_pc);
|
||||
}
|
||||
SBType function_type = function.GetType();
|
||||
SBType return_type = function_type.GetFunctionReturnType();
|
||||
|
||||
if (canonical)
|
||||
return_type = return_type.GetCanonicalType();
|
||||
|
||||
if (func_mangled_name &&
|
||||
func_mangled_name[0] == '_' &&
|
||||
func_mangled_name[1] == 'Z')
|
||||
{
|
||||
printf ("%s %s\n", return_type.GetName(), func_demangled_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
SBTypeList function_args = function_type.GetFunctionArgumentTypes();
|
||||
const size_t num_function_args = function_args.GetSize();
|
||||
|
||||
if (is_objc_method)
|
||||
{
|
||||
const char *class_name_start = func_demangled_name + 2;
|
||||
|
||||
if (num_function_args == 0)
|
||||
{
|
||||
printf("%c(%s)[%s\n", func_demangled_name[0], return_type.GetName(), class_name_start);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *class_name_end = strchr(class_name_start,' ');
|
||||
const int class_name_len = class_name_end - class_name_start;
|
||||
printf ("%c(%s)[%*.*s", func_demangled_name[0], return_type.GetName(), class_name_len, class_name_len, class_name_start);
|
||||
|
||||
const char *selector_pos = class_name_end + 1;
|
||||
for (uint32_t function_arg_idx = 0; function_arg_idx < num_function_args; ++function_arg_idx)
|
||||
{
|
||||
const char *selector_end = strchr(selector_pos, ':') + 1;
|
||||
const int selector_len = selector_end - selector_pos;
|
||||
SBType function_arg_type = function_args.GetTypeAtIndex(function_arg_idx);
|
||||
|
||||
if (canonical)
|
||||
function_arg_type = function_arg_type.GetCanonicalType();
|
||||
|
||||
printf (" %*.*s", selector_len, selector_len, selector_pos);
|
||||
if (function_arg_type.IsValid())
|
||||
{
|
||||
printf ("(%s)", function_arg_type.GetName());
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("(?)");
|
||||
}
|
||||
selector_pos = selector_end;
|
||||
}
|
||||
printf ("]\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("%s ", return_type.GetName());
|
||||
if (strchr (func_demangled_name, '('))
|
||||
printf ("(*)(");
|
||||
else
|
||||
printf ("%s(", func_demangled_name);
|
||||
|
||||
for (uint32_t function_arg_idx = 0; function_arg_idx < num_function_args; ++function_arg_idx)
|
||||
{
|
||||
SBType function_arg_type = function_args.GetTypeAtIndex(function_arg_idx);
|
||||
|
||||
if (canonical)
|
||||
function_arg_type = function_arg_type.GetCanonicalType();
|
||||
|
||||
if (function_arg_type.IsValid())
|
||||
{
|
||||
printf ("%s%s", function_arg_idx > 0 ? ", " : "", function_arg_type.GetName());
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("%s???", function_arg_idx > 0 ? ", " : "");
|
||||
}
|
||||
}
|
||||
printf (")\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "error: %s\n", error.GetCString());
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
1152
external/bsd/llvm/dist/lldb/examples/interposing/darwin/fd_interposing/FDInterposing.cpp
vendored
Normal file
1152
external/bsd/llvm/dist/lldb/examples/interposing/darwin/fd_interposing/FDInterposing.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7
external/bsd/llvm/dist/lldb/examples/interposing/darwin/fd_interposing/Makefile
vendored
Normal file
7
external/bsd/llvm/dist/lldb/examples/interposing/darwin/fd_interposing/Makefile
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
LEVEL = ../../../../test/make
|
||||
|
||||
DYLIB_NAME := FDInterposing
|
||||
DYLIB_ONLY := YES
|
||||
DYLIB_CXX_SOURCES := FDInterposing.cpp
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
||||
17
external/bsd/llvm/dist/lldb/examples/lookup/Makefile
vendored
Normal file
17
external/bsd/llvm/dist/lldb/examples/lookup/Makefile
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
LEVEL = ../../test/make
|
||||
|
||||
CXX_SOURCES := main.cpp
|
||||
EXE := lldb-lookup
|
||||
USE_LIBCPP := 1
|
||||
|
||||
MY_OS = $(shell uname -s)
|
||||
|
||||
ifeq "$(MY_OS)" "Darwin"
|
||||
LLDB_BUILD_DIR ?= /Applications/Xcode.app/Contents/SharedFrameworks
|
||||
LD_EXTRAS ?= -framework LLDB -Wl,-rpath,"$(LLDB_BUILD_DIR)"
|
||||
FRAMEWORK_INCLUDES=-F"$(LLDB_BUILD_DIR)"
|
||||
else
|
||||
LD_EXTRAS ?= $(LLDB_BUILD_DIR)/_lldb.so
|
||||
endif
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
||||
235
external/bsd/llvm/dist/lldb/examples/lookup/main.cpp
vendored
Normal file
235
external/bsd/llvm/dist/lldb/examples/lookup/main.cpp
vendored
Normal file
@@ -0,0 +1,235 @@
|
||||
//===-- main.cpp ------------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <LLDB/LLDB.h>
|
||||
#else
|
||||
#include "LLDB/SBBlock.h"
|
||||
#include "LLDB/SBCompileUnit.h"
|
||||
#include "LLDB/SBDebugger.h"
|
||||
#include "LLDB/SBFunction.h"
|
||||
#include "LLDB/SBModule.h"
|
||||
#include "LLDB/SBStream.h"
|
||||
#include "LLDB/SBSymbol.h"
|
||||
#include "LLDB/SBTarget.h"
|
||||
#include "LLDB/SBThread.h"
|
||||
#include "LLDB/SBProcess.h"
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace lldb;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// This quick sample code shows how to create a debugger instance and
|
||||
// create an "i386" executable target. Then we can lookup the executable
|
||||
// module and resolve a file address into a section offset address,
|
||||
// and find all symbol context objects (if any) for that address:
|
||||
// compile unit, function, deepest block, line table entry and the
|
||||
// symbol.
|
||||
//
|
||||
// To build the program, type (while in this directory):
|
||||
//
|
||||
// $ make
|
||||
//
|
||||
// then (for example):
|
||||
//
|
||||
// $ DYLD_FRAMEWORK_PATH=/Volumes/data/lldb/svn/ToT/build/Debug ./a.out executable_path file_address
|
||||
//----------------------------------------------------------------------
|
||||
class LLDBSentry
|
||||
{
|
||||
public:
|
||||
LLDBSentry() {
|
||||
// Initialize LLDB
|
||||
SBDebugger::Initialize();
|
||||
}
|
||||
~LLDBSentry() {
|
||||
// Terminate LLDB
|
||||
SBDebugger::Terminate();
|
||||
}
|
||||
};
|
||||
|
||||
static struct option g_long_options[] =
|
||||
{
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "verbose", no_argument, NULL, 'v' },
|
||||
{ "arch", required_argument, NULL, 'a' },
|
||||
{ "platform", required_argument, NULL, 'p' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
#define PROGRAM_NAME "lldb-lookup"
|
||||
void
|
||||
usage ()
|
||||
{
|
||||
puts (
|
||||
"NAME\n"
|
||||
" " PROGRAM_NAME " -- symbolicate addresses using lldb.\n"
|
||||
"\n"
|
||||
"SYNOPSIS\n"
|
||||
" " PROGRAM_NAME " [[--arch=<ARCH>] [--platform=<PLATFORM>] [--verbose] [--help] --] <PATH> <ADDRESS> [<ADDRESS>....]\n"
|
||||
"\n"
|
||||
"DESCRIPTION\n"
|
||||
" Loads the executable pointed to by <PATH> and looks up and <ADDRESS>\n"
|
||||
" arguments\n"
|
||||
"\n"
|
||||
"EXAMPLE\n"
|
||||
" " PROGRAM_NAME " --arch=x86_64 -- /usr/lib/dyld 0x100000000\n"
|
||||
);
|
||||
exit(0);
|
||||
}
|
||||
int
|
||||
main (int argc, char const *argv[])
|
||||
{
|
||||
// Use a sentry object to properly initialize/terminate LLDB.
|
||||
LLDBSentry sentry;
|
||||
|
||||
SBDebugger debugger (SBDebugger::Create());
|
||||
|
||||
// Create a debugger instance so we can create a target
|
||||
if (!debugger.IsValid())
|
||||
fprintf (stderr, "error: failed to create a debugger object\n");
|
||||
|
||||
bool show_usage = false;
|
||||
bool verbose = false;
|
||||
const char *arch = NULL;
|
||||
const char *platform = NULL;
|
||||
std::string short_options("h?");
|
||||
for (const struct option *opt = g_long_options; opt->name; ++opt)
|
||||
{
|
||||
if (isprint(opt->val))
|
||||
{
|
||||
short_options.append(1, (char)opt->val);
|
||||
switch (opt->has_arg)
|
||||
{
|
||||
case no_argument:
|
||||
break;
|
||||
case required_argument:
|
||||
short_options.append(1, ':');
|
||||
break;
|
||||
case optional_argument:
|
||||
short_options.append(2, ':');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef __GLIBC__
|
||||
optind = 0;
|
||||
#else
|
||||
optreset = 1;
|
||||
optind = 1;
|
||||
#endif
|
||||
char ch;
|
||||
while ((ch = getopt_long_only(argc, (char * const *)argv, short_options.c_str(), g_long_options, 0)) != -1)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
if (arch != NULL)
|
||||
{
|
||||
fprintf (stderr, "error: the --arch option can only be specified once\n");
|
||||
exit(1);
|
||||
}
|
||||
arch = optarg;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
platform = optarg;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
verbose = true;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
case '?':
|
||||
default:
|
||||
show_usage = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (show_usage || argc < 2)
|
||||
usage();
|
||||
|
||||
int arg_idx = 0;
|
||||
// The first argument is the file path we want to look something up in
|
||||
const char *exe_file_path = argv[arg_idx];
|
||||
const char *addr_cstr;
|
||||
const bool add_dependent_libs = false;
|
||||
SBError error;
|
||||
SBStream strm;
|
||||
strm.RedirectToFileHandle (stdout, false);
|
||||
|
||||
while ((addr_cstr = argv[++arg_idx]) != NULL)
|
||||
{
|
||||
// The second argument in the address that we want to lookup
|
||||
lldb::addr_t file_addr = strtoull (addr_cstr, NULL, 0);
|
||||
|
||||
// Create a target using the executable.
|
||||
SBTarget target = debugger.CreateTarget (exe_file_path,
|
||||
arch,
|
||||
platform,
|
||||
add_dependent_libs,
|
||||
error);
|
||||
if (!error.Success())
|
||||
{
|
||||
fprintf (stderr, "error: %s\n", error.GetCString());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf ("%sLooking up 0x%llx in '%s':\n", (arg_idx > 1) ? "\n" : "", file_addr, exe_file_path);
|
||||
|
||||
if (target.IsValid())
|
||||
{
|
||||
// Find the executable module so we can do a lookup inside it
|
||||
SBFileSpec exe_file_spec (exe_file_path, true);
|
||||
SBModule module (target.FindModule (exe_file_spec));
|
||||
|
||||
// Take a file virtual address and resolve it to a section offset
|
||||
// address that can be used to do a symbol lookup by address
|
||||
SBAddress addr = module.ResolveFileAddress (file_addr);
|
||||
bool success = addr.IsValid() && addr.GetSection().IsValid();
|
||||
if (success)
|
||||
{
|
||||
// We can resolve a section offset address in the module
|
||||
// and only ask for what we need. You can logical or together
|
||||
// bits from the SymbolContextItem enumeration found in
|
||||
// lldb-enumeration.h to request only what you want. Here we
|
||||
// are asking for everything.
|
||||
//
|
||||
// NOTE: the less you ask for, the less LLDB will parse as
|
||||
// LLDB does partial parsing on just about everything.
|
||||
SBSymbolContext sc (module.ResolveSymbolContextForAddress (addr, eSymbolContextEverything));
|
||||
|
||||
strm.Printf (" Address: %s + 0x%llx\n Summary: ", addr.GetSection().GetName (), addr.GetOffset());
|
||||
addr.GetDescription (strm);
|
||||
strm.Printf ("\n");
|
||||
if (verbose)
|
||||
sc.GetDescription (strm);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("error: 0x%llx does not resolve to a valid file address in '%s'\n", file_addr, exe_file_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
56
external/bsd/llvm/dist/lldb/examples/plugins/commands/fooplugin.cpp
vendored
Normal file
56
external/bsd/llvm/dist/lldb/examples/plugins/commands/fooplugin.cpp
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
//===-- fooplugin.cpp -------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/*
|
||||
An example plugin for LLDB that provides a new foo command with a child subcommand
|
||||
Compile this into a dylib foo.dylib and load by placing in appropriate locations on disk or
|
||||
by typing plugin load foo.dylib at the LLDB command line
|
||||
*/
|
||||
|
||||
#include <LLDB/SBCommandInterpreter.h>
|
||||
#include <LLDB/SBCommandReturnObject.h>
|
||||
#include <LLDB/SBDebugger.h>
|
||||
|
||||
namespace lldb {
|
||||
bool
|
||||
PluginInitialize (lldb::SBDebugger debugger);
|
||||
}
|
||||
|
||||
class ChildCommand : public lldb::SBCommandPluginInterface
|
||||
{
|
||||
public:
|
||||
virtual bool
|
||||
DoExecute (lldb::SBDebugger debugger,
|
||||
char** command,
|
||||
lldb::SBCommandReturnObject &result)
|
||||
{
|
||||
if (command)
|
||||
{
|
||||
const char* arg = *command;
|
||||
while (arg)
|
||||
{
|
||||
result.Printf("%s\n",arg);
|
||||
arg = *(++command);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
bool
|
||||
lldb::PluginInitialize (lldb::SBDebugger debugger)
|
||||
{
|
||||
lldb::SBCommandInterpreter interpreter = debugger.GetCommandInterpreter();
|
||||
lldb::SBCommand foo = interpreter.AddMultiwordCommand("foo",NULL);
|
||||
foo.AddCommand("child",new ChildCommand(),"a child of foo");
|
||||
return true;
|
||||
}
|
||||
|
||||
76
external/bsd/llvm/dist/lldb/examples/python/cmdtemplate.py
vendored
Normal file
76
external/bsd/llvm/dist/lldb/examples/python/cmdtemplate.py
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
#!/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" just
|
||||
# import it with the full path using the "command script import"
|
||||
# command
|
||||
# (lldb) command script import /path/to/cmdtemplate.py
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
import lldb
|
||||
import commands
|
||||
import optparse
|
||||
import shlex
|
||||
|
||||
def create_framestats_options():
|
||||
usage = "usage: %prog [options]"
|
||||
description='''This command is meant to be an example of how to make an LLDB command that
|
||||
does something useful, follows best practices, and exploits the SB API.
|
||||
Specifically, this command computes the aggregate and average size of the variables in the current frame
|
||||
and allows you to tweak exactly which variables are to be accounted in the computation.
|
||||
'''
|
||||
parser = optparse.OptionParser(description=description, prog='framestats',usage=usage)
|
||||
parser.add_option('-i', '--in-scope', action='store_true', dest='inscope', help='in_scope_only = True', default=False)
|
||||
parser.add_option('-a', '--arguments', action='store_true', dest='arguments', help='arguments = True', default=False)
|
||||
parser.add_option('-l', '--locals', action='store_true', dest='locals', help='locals = True', default=False)
|
||||
parser.add_option('-s', '--statics', action='store_true', dest='statics', help='statics = True', default=False)
|
||||
return parser
|
||||
|
||||
def the_framestats_command(debugger, command, result, dict):
|
||||
# Use the Shell Lexer to properly parse up command options just like a
|
||||
# shell would
|
||||
command_args = shlex.split(command)
|
||||
parser = create_framestats_options()
|
||||
try:
|
||||
(options, args) = parser.parse_args(command_args)
|
||||
except:
|
||||
# if you don't handle exceptions, passing an incorrect argument to the OptionParser will cause LLDB to exit
|
||||
# (courtesy of OptParse dealing with argument errors by throwing SystemExit)
|
||||
result.SetError ("option parsing failed")
|
||||
return
|
||||
|
||||
# in a command - the lldb.* convenience variables are not to be used
|
||||
# and their values (if any) are undefined
|
||||
# this is the best practice to access those objects from within a command
|
||||
target = debugger.GetSelectedTarget()
|
||||
process = target.GetProcess()
|
||||
thread = process.GetSelectedThread()
|
||||
frame = thread.GetSelectedFrame()
|
||||
if not frame.IsValid():
|
||||
return "no frame here"
|
||||
# from now on, replace lldb.<thing>.whatever with <thing>.whatever
|
||||
variables_list = frame.GetVariables(options.arguments, options.locals, options.statics, options.inscope)
|
||||
variables_count = variables_list.GetSize()
|
||||
if variables_count == 0:
|
||||
print >> result, "no variables here"
|
||||
return
|
||||
total_size = 0
|
||||
for i in range(0,variables_count):
|
||||
variable = variables_list.GetValueAtIndex(i)
|
||||
variable_type = variable.GetType()
|
||||
total_size = total_size + variable_type.GetByteSize()
|
||||
average_size = float(total_size) / variables_count
|
||||
print >>result, "Your frame has %d variables. Their total size is %d bytes. The average size is %f bytes" % (variables_count,total_size,average_size)
|
||||
# not returning anything is akin to returning success
|
||||
|
||||
def __lldb_init_module (debugger, dict):
|
||||
# This initializer is being run from LLDB in the embedded command interpreter
|
||||
# Make the options so we can generate the help text for the new LLDB
|
||||
# command line command prior to registering it with LLDB below
|
||||
parser = create_framestats_options()
|
||||
the_framestats_command.__doc__ = parser.format_help()
|
||||
# Add any commands contained in this module to LLDB
|
||||
debugger.HandleCommand('command script add -f cmdtemplate.the_framestats_command framestats')
|
||||
print 'The "framestats" command has been installed, type "help framestats" or "framestats --help" for detailed help.'
|
||||
782
external/bsd/llvm/dist/lldb/examples/python/crashlog.py
vendored
Executable file
782
external/bsd/llvm/dist/lldb/examples/python/crashlog.py
vendored
Executable file
@@ -0,0 +1,782 @@
|
||||
#!/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/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 /path/to/LLDB.framework/Resources/Python ; ./crashlog.py ~/Library/Logs/DiagnosticReports/a.crash )
|
||||
#
|
||||
# On MacOSX sh, bash:
|
||||
# PYTHONPATH=/path/to/LLDB.framework/Resources/Python ./crashlog.py ~/Library/Logs/DiagnosticReports/a.crash
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
import commands
|
||||
import cmd
|
||||
import datetime
|
||||
import glob
|
||||
import optparse
|
||||
import os
|
||||
import platform
|
||||
import plistlib
|
||||
import pprint # pp = pprint.PrettyPrinter(indent=4); pp.pprint(command_args)
|
||||
import re
|
||||
import shlex
|
||||
import string
|
||||
import sys
|
||||
import time
|
||||
import uuid
|
||||
|
||||
try:
|
||||
# Just try for LLDB in case PYTHONPATH is already correctly setup
|
||||
import lldb
|
||||
except ImportError:
|
||||
lldb_python_dirs = list()
|
||||
# lldb is not in the PYTHONPATH, try some defaults for the current platform
|
||||
platform_system = platform.system()
|
||||
if platform_system == 'Darwin':
|
||||
# On Darwin, try the currently selected Xcode directory
|
||||
xcode_dir = commands.getoutput("xcode-select --print-path")
|
||||
if xcode_dir:
|
||||
lldb_python_dirs.append(os.path.realpath(xcode_dir + '/../SharedFrameworks/LLDB.framework/Resources/Python'))
|
||||
lldb_python_dirs.append(xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
|
||||
lldb_python_dirs.append('/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
|
||||
success = False
|
||||
for lldb_python_dir in lldb_python_dirs:
|
||||
if os.path.exists(lldb_python_dir):
|
||||
if not (sys.path.__contains__(lldb_python_dir)):
|
||||
sys.path.append(lldb_python_dir)
|
||||
try:
|
||||
import lldb
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
print 'imported lldb from: "%s"' % (lldb_python_dir)
|
||||
success = True
|
||||
break
|
||||
if not success:
|
||||
print "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly"
|
||||
sys.exit(1)
|
||||
|
||||
from lldb.utils import symbolication
|
||||
|
||||
PARSE_MODE_NORMAL = 0
|
||||
PARSE_MODE_THREAD = 1
|
||||
PARSE_MODE_IMAGES = 2
|
||||
PARSE_MODE_THREGS = 3
|
||||
PARSE_MODE_SYSTEM = 4
|
||||
|
||||
class CrashLog(symbolication.Symbolicator):
|
||||
"""Class that does parses darwin crash logs"""
|
||||
parent_process_regex = re.compile('^Parent Process:\s*(.*)\[(\d+)\]');
|
||||
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.idents = 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 add_ident(self, ident):
|
||||
if not ident in self.idents:
|
||||
self.idents.append(ident)
|
||||
|
||||
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, description):
|
||||
self.pc = pc
|
||||
self.description = description
|
||||
self.index = index
|
||||
|
||||
def __str__(self):
|
||||
if self.description:
|
||||
return "[%3u] 0x%16.16x %s" % (self.index, self.pc, self.description)
|
||||
else:
|
||||
return "[%3u] 0x%16.16x" % (self.index, self.pc)
|
||||
|
||||
def dump(self, prefix):
|
||||
print "%s%s" % (prefix, str(self))
|
||||
|
||||
class DarwinImage(symbolication.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, identifier, version, uuid, path):
|
||||
symbolication.Image.__init__(self, path, uuid);
|
||||
self.add_section (symbolication.Section(text_addr_lo, text_addr_hi, "__TEXT"))
|
||||
self.identifier = identifier
|
||||
self.version = version
|
||||
|
||||
def locate_module_and_debug_symbols(self):
|
||||
# Don't load a module twice...
|
||||
if self.resolved:
|
||||
return True
|
||||
# Mark this as resolved so we don't keep trying
|
||||
self.resolved = True
|
||||
uuid_str = self.get_normalized_uuid_string()
|
||||
print 'Getting symbols for %s %s...' % (uuid_str, self.path),
|
||||
if os.path.exists(self.dsymForUUIDBinary):
|
||||
dsym_for_uuid_command = '%s %s' % (self.dsymForUUIDBinary, uuid_str)
|
||||
s = commands.getoutput(dsym_for_uuid_command)
|
||||
if s:
|
||||
plist_root = plistlib.readPlistFromString (s)
|
||||
if plist_root:
|
||||
plist = plist_root[uuid_str]
|
||||
if plist:
|
||||
if 'DBGArchitecture' in plist:
|
||||
self.arch = plist['DBGArchitecture']
|
||||
if 'DBGDSYMPath' in plist:
|
||||
self.symfile = 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 = self.get_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:
|
||||
self.unavailable = True
|
||||
print "error\n error: unable to locate '%s' with UUID %s" % (self.path, uuid_str)
|
||||
return False
|
||||
if (self.resolved_path and os.path.exists(self.resolved_path)) or (self.path and os.path.exists(self.path)):
|
||||
print 'ok'
|
||||
# if self.resolved_path:
|
||||
# print ' exe = "%s"' % self.resolved_path
|
||||
# if self.symfile:
|
||||
# print ' dsym = "%s"' % self.symfile
|
||||
return True
|
||||
else:
|
||||
self.unavailable = True
|
||||
return False
|
||||
|
||||
|
||||
|
||||
def __init__(self, path):
|
||||
"""CrashLog constructor that take a path to a darwin crash log file"""
|
||||
symbolication.Symbolicator.__init__(self);
|
||||
self.path = os.path.expanduser(path);
|
||||
self.info_lines = list()
|
||||
self.system_profile = list()
|
||||
self.threads = list()
|
||||
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.
|
||||
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
|
||||
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:'):
|
||||
version_string = line[8:].strip()
|
||||
matched_pair = re.search("(.+)\((.+)\)", version_string)
|
||||
if matched_pair:
|
||||
self.process_version = matched_pair.group(1)
|
||||
self.process_compatability_version = matched_pair.group(2)
|
||||
else:
|
||||
self.process = version_string
|
||||
self.process_compatability_version = version_string
|
||||
elif self.parent_process_regex.search(line):
|
||||
parent_process_match = self.parent_process_regex.search(line)
|
||||
self.parent_process_name = parent_process_match.group(1)
|
||||
self.parent_process_id = parent_process_match.group(2)
|
||||
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:
|
||||
if line.startswith ('Thread'):
|
||||
continue
|
||||
frame_match = self.frame_regex.search(line)
|
||||
if frame_match:
|
||||
ident = frame_match.group(2)
|
||||
thread.add_ident(ident)
|
||||
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 for line: "%s"' % line
|
||||
elif parse_mode == PARSE_MODE_IMAGES:
|
||||
image_match = self.image_regex_uuid.search (line)
|
||||
if image_match:
|
||||
image = CrashLog.DarwinImage (int(image_match.group(1),0),
|
||||
int(image_match.group(2),0),
|
||||
image_match.group(3).strip(),
|
||||
image_match.group(4).strip(),
|
||||
uuid.UUID(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.DarwinImage (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()
|
||||
# "r12: 0x00007fff6b5939c8 r13: 0x0000000007000006 r14: 0x0000000000002a03 r15: 0x0000000000000c00"
|
||||
reg_values = re.findall ('([a-zA-Z0-9]+: 0[Xx][0-9a-fA-F]+) *', stripped_line);
|
||||
for reg_value in reg_values:
|
||||
#print 'reg_value = "%s"' % reg_value
|
||||
(reg, value) = reg_value.split(': ')
|
||||
#print 'reg = "%s"' % reg
|
||||
#print 'value = "%s"' % value
|
||||
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, identifier):
|
||||
for image in self.images:
|
||||
if image.identifier == identifier:
|
||||
return image
|
||||
return None
|
||||
|
||||
def create_target(self):
|
||||
#print 'crashlog.create_target()...'
|
||||
target = symbolication.Symbolicator.create_target(self)
|
||||
if target:
|
||||
return target
|
||||
# We weren't able to open the main executable as, but we can still symbolicate
|
||||
print 'crashlog.create_target()...2'
|
||||
if self.idents:
|
||||
for ident in self.idents:
|
||||
image = self.find_image_with_identifier (ident)
|
||||
if image:
|
||||
target = image.create_target ()
|
||||
if target:
|
||||
return target # success
|
||||
print 'crashlog.create_target()...3'
|
||||
for image in self.images:
|
||||
target = image.create_target ()
|
||||
if target:
|
||||
return target # success
|
||||
print 'crashlog.create_target()...4'
|
||||
print 'error: unable to locate any executables from the crash log'
|
||||
return None
|
||||
|
||||
|
||||
def usage():
|
||||
print "Usage: lldb-symbolicate.py [-n name] executable-image"
|
||||
sys.exit(0)
|
||||
|
||||
class Interactive(cmd.Cmd):
|
||||
'''Interactive prompt for analyzing one or more Darwin crash logs, type "help" to see a list of supported commands.'''
|
||||
image_option_parser = None
|
||||
|
||||
def __init__(self, crash_logs):
|
||||
cmd.Cmd.__init__(self)
|
||||
self.use_rawinput = False
|
||||
self.intro = 'Interactive crashlogs prompt, type "help" to see a list of supported commands.'
|
||||
self.crash_logs = crash_logs
|
||||
self.prompt = '% '
|
||||
|
||||
def default(self, line):
|
||||
'''Catch all for unknown command, which will exit the interpreter.'''
|
||||
print "uknown command: %s" % line
|
||||
return True
|
||||
|
||||
def do_q(self, line):
|
||||
'''Quit command'''
|
||||
return True
|
||||
|
||||
def do_quit(self, line):
|
||||
'''Quit command'''
|
||||
return True
|
||||
|
||||
def do_symbolicate(self, line):
|
||||
description='''Symbolicate one or more darwin crash log files by index 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.'''
|
||||
option_parser = CreateSymbolicateCrashLogOptions ('symbolicate', description, False)
|
||||
command_args = shlex.split(line)
|
||||
try:
|
||||
(options, args) = option_parser.parse_args(command_args)
|
||||
except:
|
||||
return
|
||||
|
||||
if args:
|
||||
# We have arguments, they must valid be crash log file indexes
|
||||
for idx_str in args:
|
||||
idx = int(idx_str)
|
||||
if idx < len(self.crash_logs):
|
||||
SymbolicateCrashLog (self.crash_logs[idx], options)
|
||||
else:
|
||||
print 'error: crash log index %u is out of range' % (idx)
|
||||
else:
|
||||
# No arguments, symbolicate all crash logs using the options provided
|
||||
for idx in range(len(self.crash_logs)):
|
||||
SymbolicateCrashLog (self.crash_logs[idx], options)
|
||||
|
||||
def do_list(self, line=None):
|
||||
'''Dump a list of all crash logs that are currently loaded.
|
||||
|
||||
USAGE: list'''
|
||||
print '%u crash logs are loaded:' % len(self.crash_logs)
|
||||
for (crash_log_idx, crash_log) in enumerate(self.crash_logs):
|
||||
print '[%u] = %s' % (crash_log_idx, crash_log.path)
|
||||
|
||||
def do_image(self, line):
|
||||
'''Dump information about one or more binary images in the crash log given an image basename, or all images if no arguments are provided.'''
|
||||
usage = "usage: %prog [options] <PATH> [PATH ...]"
|
||||
description='''Dump information about one or more images in all crash logs. The <PATH> can be a full path, image basename, or partial path. Searches are done in this order.'''
|
||||
command_args = shlex.split(line)
|
||||
if not self.image_option_parser:
|
||||
self.image_option_parser = optparse.OptionParser(description=description, prog='image',usage=usage)
|
||||
self.image_option_parser.add_option('-a', '--all', action='store_true', help='show all images', default=False)
|
||||
try:
|
||||
(options, args) = self.image_option_parser.parse_args(command_args)
|
||||
except:
|
||||
return
|
||||
|
||||
if args:
|
||||
for image_path in args:
|
||||
fullpath_search = image_path[0] == '/'
|
||||
for (crash_log_idx, crash_log) in enumerate(self.crash_logs):
|
||||
matches_found = 0
|
||||
for (image_idx, image) in enumerate(crash_log.images):
|
||||
if fullpath_search:
|
||||
if image.get_resolved_path() == image_path:
|
||||
matches_found += 1
|
||||
print '[%u] ' % (crash_log_idx), image
|
||||
else:
|
||||
image_basename = image.get_resolved_path_basename()
|
||||
if image_basename == image_path:
|
||||
matches_found += 1
|
||||
print '[%u] ' % (crash_log_idx), image
|
||||
if matches_found == 0:
|
||||
for (image_idx, image) in enumerate(crash_log.images):
|
||||
resolved_image_path = image.get_resolved_path()
|
||||
if resolved_image_path and string.find(image.get_resolved_path(), image_path) >= 0:
|
||||
print '[%u] ' % (crash_log_idx), image
|
||||
else:
|
||||
for crash_log in self.crash_logs:
|
||||
for (image_idx, image) in enumerate(crash_log.images):
|
||||
print '[%u] %s' % (image_idx, image)
|
||||
return False
|
||||
|
||||
|
||||
def interactive_crashlogs(options, args):
|
||||
crash_log_files = list()
|
||||
for arg in args:
|
||||
for resolved_path in glob.glob(arg):
|
||||
crash_log_files.append(resolved_path)
|
||||
|
||||
crash_logs = list();
|
||||
for crash_log_file in crash_log_files:
|
||||
#print 'crash_log_file = "%s"' % crash_log_file
|
||||
crash_log = CrashLog(crash_log_file)
|
||||
if crash_log.error:
|
||||
print crash_log.error
|
||||
continue
|
||||
if options.debug:
|
||||
crash_log.dump()
|
||||
if not crash_log.images:
|
||||
print 'error: no images in crash log "%s"' % (crash_log)
|
||||
continue
|
||||
else:
|
||||
crash_logs.append(crash_log)
|
||||
|
||||
interpreter = Interactive(crash_logs)
|
||||
# List all crash logs that were imported
|
||||
interpreter.do_list()
|
||||
interpreter.cmdloop()
|
||||
|
||||
|
||||
def save_crashlog(debugger, command, result, dict):
|
||||
usage = "usage: %prog [options] <output-path>"
|
||||
description='''Export the state of current target into a crashlog file'''
|
||||
parser = optparse.OptionParser(description=description, prog='save_crashlog',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(shlex.split(command))
|
||||
except:
|
||||
result.PutCString ("error: invalid options");
|
||||
return
|
||||
if len(args) != 1:
|
||||
result.PutCString ("error: invalid arguments, a single output file is the only valid argument")
|
||||
return
|
||||
out_file = open(args[0], 'w')
|
||||
if not out_file:
|
||||
result.PutCString ("error: failed to open file '%s' for writing...", args[0]);
|
||||
return
|
||||
if lldb.target:
|
||||
identifier = lldb.target.executable.basename
|
||||
if lldb.process:
|
||||
pid = lldb.process.id
|
||||
if pid != lldb.LLDB_INVALID_PROCESS_ID:
|
||||
out_file.write('Process: %s [%u]\n' % (identifier, pid))
|
||||
out_file.write('Path: %s\n' % (lldb.target.executable.fullpath))
|
||||
out_file.write('Identifier: %s\n' % (identifier))
|
||||
out_file.write('\nDate/Time: %s\n' % (datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
|
||||
out_file.write('OS Version: Mac OS X %s (%s)\n' % (platform.mac_ver()[0], commands.getoutput('sysctl -n kern.osversion')));
|
||||
out_file.write('Report Version: 9\n')
|
||||
for thread_idx in range(lldb.process.num_threads):
|
||||
thread = lldb.process.thread[thread_idx]
|
||||
out_file.write('\nThread %u:\n' % (thread_idx))
|
||||
for (frame_idx, frame) in enumerate(thread.frames):
|
||||
frame_pc = frame.pc
|
||||
frame_offset = 0
|
||||
if frame.function:
|
||||
block = frame.GetFrameBlock()
|
||||
block_range = block.range[frame.addr]
|
||||
if block_range:
|
||||
block_start_addr = block_range[0]
|
||||
frame_offset = frame_pc - block_start_addr.load_addr
|
||||
else:
|
||||
frame_offset = frame_pc - frame.function.addr.load_addr
|
||||
elif frame.symbol:
|
||||
frame_offset = frame_pc - frame.symbol.addr.load_addr
|
||||
out_file.write('%-3u %-32s 0x%16.16x %s' % (frame_idx, frame.module.file.basename, frame_pc, frame.name))
|
||||
if frame_offset > 0:
|
||||
out_file.write(' + %u' % (frame_offset))
|
||||
line_entry = frame.line_entry
|
||||
if line_entry:
|
||||
if options.verbose:
|
||||
# This will output the fullpath + line + column
|
||||
out_file.write(' %s' % (line_entry))
|
||||
else:
|
||||
out_file.write(' %s:%u' % (line_entry.file.basename, line_entry.line))
|
||||
column = line_entry.column
|
||||
if column:
|
||||
out_file.write(':%u' % (column))
|
||||
out_file.write('\n')
|
||||
|
||||
out_file.write('\nBinary Images:\n')
|
||||
for module in lldb.target.modules:
|
||||
text_segment = module.section['__TEXT']
|
||||
if text_segment:
|
||||
text_segment_load_addr = text_segment.GetLoadAddress(lldb.target)
|
||||
if text_segment_load_addr != lldb.LLDB_INVALID_ADDRESS:
|
||||
text_segment_end_load_addr = text_segment_load_addr + text_segment.size
|
||||
identifier = module.file.basename
|
||||
module_version = '???'
|
||||
module_version_array = module.GetVersion()
|
||||
if module_version_array:
|
||||
module_version = '.'.join(map(str,module_version_array))
|
||||
out_file.write (' 0x%16.16x - 0x%16.16x %s (%s - ???) <%s> %s\n' % (text_segment_load_addr, text_segment_end_load_addr, identifier, module_version, module.GetUUIDString(), module.file.fullpath))
|
||||
out_file.close()
|
||||
else:
|
||||
result.PutCString ("error: invalid target");
|
||||
|
||||
|
||||
def Symbolicate(debugger, command, result, dict):
|
||||
try:
|
||||
SymbolicateCrashLogs (shlex.split(command))
|
||||
except:
|
||||
result.PutCString ("error: python exception %s" % sys.exc_info()[0])
|
||||
|
||||
def SymbolicateCrashLog(crash_log, options):
|
||||
if crash_log.error:
|
||||
print crash_log.error
|
||||
return
|
||||
if options.debug:
|
||||
crash_log.dump()
|
||||
if not crash_log.images:
|
||||
print 'error: no images in crash log'
|
||||
return
|
||||
|
||||
if options.dump_image_list:
|
||||
print "Binary Images:"
|
||||
for image in crash_log.images:
|
||||
if options.verbose:
|
||||
print image.debug_dump()
|
||||
else:
|
||||
print image
|
||||
|
||||
target = crash_log.create_target ()
|
||||
if not target:
|
||||
return
|
||||
exe_module = target.GetModuleAtIndex(0)
|
||||
images_to_load = list()
|
||||
loaded_images = 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
|
||||
if options.crashed_only:
|
||||
for thread in crash_log.threads:
|
||||
if thread.did_crash():
|
||||
for ident in thread.idents:
|
||||
images = crash_log.find_images_with_identifier (ident)
|
||||
if images:
|
||||
for image in images:
|
||||
images_to_load.append(image)
|
||||
else:
|
||||
print 'error: can\'t find image for identifier "%s"' % ident
|
||||
else:
|
||||
for ident in crash_log.idents:
|
||||
images = crash_log.find_images_with_identifier (ident)
|
||||
if images:
|
||||
for image in images:
|
||||
images_to_load.append(image)
|
||||
else:
|
||||
print 'error: can\'t find image for identifier "%s"' % ident
|
||||
|
||||
for image in images_to_load:
|
||||
if image in loaded_images:
|
||||
print "warning: skipping %s loaded at %#16.16x duplicate entry (probably commpage)" % (image.path, image.text_addr_lo)
|
||||
else:
|
||||
err = image.add_module (target)
|
||||
if err:
|
||||
print err
|
||||
else:
|
||||
#print 'loaded %s' % image
|
||||
loaded_images.append(image)
|
||||
|
||||
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
|
||||
display_frame_idx = -1
|
||||
for frame_idx, frame in enumerate(thread.frames):
|
||||
disassemble = (this_thread_crashed or options.disassemble_all_threads) and frame_idx < options.disassemble_depth;
|
||||
if frame_idx == 0:
|
||||
symbolicated_frame_addresses = crash_log.symbolicate (frame.pc & crash_log.addr_mask, options.verbose)
|
||||
else:
|
||||
# Any frame above frame zero and we have to subtract one to get the previous line entry
|
||||
symbolicated_frame_addresses = crash_log.symbolicate ((frame.pc & crash_log.addr_mask) - 1, options.verbose)
|
||||
|
||||
if symbolicated_frame_addresses:
|
||||
symbolicated_frame_address_idx = 0
|
||||
for symbolicated_frame_address in symbolicated_frame_addresses:
|
||||
display_frame_idx += 1
|
||||
print '[%3u] %s' % (frame_idx, symbolicated_frame_address)
|
||||
if (options.source_all or thread.did_crash()) and display_frame_idx < options.source_frames and options.source_context:
|
||||
source_context = options.source_context
|
||||
line_entry = symbolicated_frame_address.get_symbol_context().line_entry
|
||||
if line_entry.IsValid():
|
||||
strm = lldb.SBStream()
|
||||
if line_entry:
|
||||
lldb.debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers(line_entry.file, line_entry.line, source_context, source_context, "->", strm)
|
||||
source_text = strm.GetData()
|
||||
if source_text:
|
||||
# Indent the source a bit
|
||||
indent_str = ' '
|
||||
join_str = '\n' + indent_str
|
||||
print '%s%s' % (indent_str, join_str.join(source_text.split('\n')))
|
||||
if symbolicated_frame_address_idx == 0:
|
||||
if disassemble:
|
||||
instructions = symbolicated_frame_address.get_instructions()
|
||||
if instructions:
|
||||
print
|
||||
symbolication.disassemble_instructions (target,
|
||||
instructions,
|
||||
frame.pc,
|
||||
options.disassemble_before,
|
||||
options.disassemble_after, frame.index > 0)
|
||||
print
|
||||
symbolicated_frame_address_idx += 1
|
||||
else:
|
||||
print frame
|
||||
print
|
||||
|
||||
def CreateSymbolicateCrashLogOptions(command_name, description, add_interactive_options):
|
||||
usage = "usage: %prog [options] <FILE> [FILE ...]"
|
||||
option_parser = optparse.OptionParser(description=description, prog='crashlog',usage=usage)
|
||||
option_parser.add_option('--verbose' , '-v', action='store_true', dest='verbose', help='display verbose debug info', default=False)
|
||||
option_parser.add_option('--debug' , '-g', action='store_true', dest='debug', help='display verbose debug logging', default=False)
|
||||
option_parser.add_option('--load-all' , '-a', action='store_true', dest='load_all_images', help='load all executable images, not just the images found in the crashed stack frames', default=False)
|
||||
option_parser.add_option('--images' , action='store_true', dest='dump_image_list', help='show image list', default=False)
|
||||
option_parser.add_option('--debug-delay' , type='int', dest='debug_delay', metavar='NSEC', help='pause for NSEC seconds for debugger', default=0)
|
||||
option_parser.add_option('--crashed-only' , '-c', action='store_true', dest='crashed_only', help='only symbolicate the crashed thread', default=False)
|
||||
option_parser.add_option('--disasm-depth' , '-d', type='int', dest='disassemble_depth', help='set the depth in stack frames that should be disassembled (default is 1)', default=1)
|
||||
option_parser.add_option('--disasm-all' , '-D', action='store_true', dest='disassemble_all_threads', help='enabled disassembly of frames on all threads (not just the crashed thread)', default=False)
|
||||
option_parser.add_option('--disasm-before' , '-B', type='int', dest='disassemble_before', help='the number of instructions to disassemble before the frame PC', default=4)
|
||||
option_parser.add_option('--disasm-after' , '-A', type='int', dest='disassemble_after', help='the number of instructions to disassemble after the frame PC', default=4)
|
||||
option_parser.add_option('--source-context', '-C', type='int', metavar='NLINES', dest='source_context', help='show NLINES source lines of source context (default = 4)', default=4)
|
||||
option_parser.add_option('--source-frames' , type='int', metavar='NFRAMES', dest='source_frames', help='show source for NFRAMES (default = 4)', default=4)
|
||||
option_parser.add_option('--source-all' , action='store_true', dest='source_all', help='show source for all threads, not just the crashed thread', default=False)
|
||||
if add_interactive_options:
|
||||
option_parser.add_option('-i', '--interactive', action='store_true', help='parse all crash logs and enter interactive mode', default=False)
|
||||
return option_parser
|
||||
|
||||
def SymbolicateCrashLogs(command_args):
|
||||
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.'''
|
||||
option_parser = CreateSymbolicateCrashLogOptions ('crashlog', description, True)
|
||||
try:
|
||||
(options, args) = option_parser.parse_args(command_args)
|
||||
except:
|
||||
return
|
||||
|
||||
if options.debug:
|
||||
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)
|
||||
error = lldb.SBError()
|
||||
|
||||
if args:
|
||||
if options.interactive:
|
||||
interactive_crashlogs(options, args)
|
||||
else:
|
||||
for crash_log_file in args:
|
||||
crash_log = CrashLog(crash_log_file)
|
||||
SymbolicateCrashLog (crash_log, options)
|
||||
if __name__ == '__main__':
|
||||
# Create a new debugger instance
|
||||
lldb.debugger = lldb.SBDebugger.Create()
|
||||
SymbolicateCrashLogs (sys.argv[1:])
|
||||
elif getattr(lldb, 'debugger', None):
|
||||
lldb.debugger.HandleCommand('command script add -f lldb.macosx.crashlog.Symbolicate crashlog')
|
||||
lldb.debugger.HandleCommand('command script add -f lldb.macosx.crashlog.save_crashlog save_crashlog')
|
||||
print '"crashlog" and "save_crashlog" command installed, use the "--help" option for detailed help'
|
||||
|
||||
115
external/bsd/llvm/dist/lldb/examples/python/delta.py
vendored
Executable file
115
external/bsd/llvm/dist/lldb/examples/python/delta.py
vendored
Executable file
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# This module will enable GDB remote packet logging when the
|
||||
# 'start_gdb_log' command is called with a filename to log to. When the
|
||||
# 'stop_gdb_log' command is called, it will disable the logging and
|
||||
# print out statistics about how long commands took to execute and also
|
||||
# will primnt ou
|
||||
# Be sure to add the python path that points to the LLDB shared library.
|
||||
#
|
||||
# To use this in the embedded python interpreter using "lldb" just
|
||||
# import it with the full path using the "command script import"
|
||||
# command. This can be done from the LLDB command line:
|
||||
# (lldb) command script import /path/to/gdbremote.py
|
||||
# Or it can be added to your ~/.lldbinit file so this module is always
|
||||
# available.
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
import commands
|
||||
import optparse
|
||||
import os
|
||||
import shlex
|
||||
import re
|
||||
import tempfile
|
||||
|
||||
def start_gdb_log(debugger, command, result, dict):
|
||||
'''Start logging GDB remote packets by enabling logging with timestamps and
|
||||
thread safe logging. Follow a call to this function with a call to "stop_gdb_log"
|
||||
in order to dump out the commands.'''
|
||||
global log_file
|
||||
if log_file:
|
||||
result.PutCString ('error: logging is already in progress with file "%s"', log_file)
|
||||
else:
|
||||
args_len = len(args)
|
||||
if args_len == 0:
|
||||
log_file = tempfile.mktemp()
|
||||
elif len(args) == 1:
|
||||
log_file = args[0]
|
||||
|
||||
if log_file:
|
||||
debugger.HandleCommand('log enable --threadsafe --timestamp --file "%s" gdb-remote packets' % log_file);
|
||||
result.PutCString ("GDB packet logging enable with log file '%s'\nUse the 'stop_gdb_log' command to stop logging and show packet statistics." % log_file)
|
||||
return
|
||||
|
||||
result.PutCString ('error: invalid log file path')
|
||||
result.PutCString (usage)
|
||||
|
||||
def parse_time_log(debugger, command, result, dict):
|
||||
# Any commands whose names might be followed by more valid C identifier
|
||||
# characters must be listed here
|
||||
command_args = shlex.split(command)
|
||||
parse_time_log_args (command_args)
|
||||
|
||||
def parse_time_log_args(command_args):
|
||||
usage = "usage: parse_time_log [options] [<LOGFILEPATH>]"
|
||||
description='''Parse a log file that contains timestamps and convert the timestamps to delta times between log lines.'''
|
||||
parser = optparse.OptionParser(description=description, prog='parse_time_log',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 log_file in args:
|
||||
parse_log_file (log_file, options)
|
||||
|
||||
def parse_log_file(file, options):
|
||||
'''Parse a log file that was contains timestamps. These logs are typically
|
||||
generated using:
|
||||
(lldb) log enable --threadsafe --timestamp --file <FILE> ....
|
||||
|
||||
This log file will contain timestamps and this fucntion will then normalize
|
||||
those packets to be relative to the first value timestamp that is found and
|
||||
show delta times between log lines and also keep track of how long it takes
|
||||
for GDB remote commands to make a send/receive round trip. This can be
|
||||
handy when trying to figure out why some operation in the debugger is taking
|
||||
a long time during a preset set of debugger commands.'''
|
||||
|
||||
print '#----------------------------------------------------------------------'
|
||||
print "# Log file: '%s'" % file
|
||||
print '#----------------------------------------------------------------------'
|
||||
|
||||
timestamp_regex = re.compile('(\s*)([1-9][0-9]+\.[0-9]+)([^0-9].*)$')
|
||||
|
||||
base_time = 0.0
|
||||
last_time = 0.0
|
||||
file = open(file)
|
||||
lines = file.read().splitlines()
|
||||
for line in lines:
|
||||
match = timestamp_regex.match (line)
|
||||
if match:
|
||||
curr_time = float (match.group(2))
|
||||
delta = 0.0
|
||||
if base_time:
|
||||
delta = curr_time - last_time
|
||||
else:
|
||||
base_time = curr_time
|
||||
|
||||
print '%s%.6f %+.6f%s' % (match.group(1), curr_time - base_time, delta, match.group(3))
|
||||
last_time = curr_time
|
||||
else:
|
||||
print line
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
parse_time_log_args (sys.argv[1:])
|
||||
|
||||
else:
|
||||
import lldb
|
||||
if lldb.debugger:
|
||||
# This initializer is being run from LLDB in the embedded command interpreter
|
||||
# Add any commands contained in this module to LLDB
|
||||
lldb.debugger.HandleCommand('command script add -f delta.parse_time_log parse_time_log')
|
||||
print 'The "parse_time_log" command is now installed and ready for use, type "parse_time_log --help" for more information'
|
||||
171
external/bsd/llvm/dist/lldb/examples/python/diagnose_nsstring.py
vendored
Normal file
171
external/bsd/llvm/dist/lldb/examples/python/diagnose_nsstring.py
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
# This implements the "diagnose-nsstring" command, usually installed in the debug session like
|
||||
# command script import lldb.diagnose
|
||||
# it is used when NSString summary formatter fails to replicate the logic that went into LLDB making the
|
||||
# decisions it did and providing some useful context information that can be used for improving the formatter
|
||||
|
||||
import lldb
|
||||
|
||||
def read_memory(process,location,size):
|
||||
data = ""
|
||||
error = lldb.SBError()
|
||||
for x in range(0,size-1):
|
||||
byte = process.ReadUnsignedFromMemory(x+location,1,error)
|
||||
if error.fail:
|
||||
data = data + "err%s" % "" if x == size-2 else ":"
|
||||
else:
|
||||
try:
|
||||
data = data + "0x%x" % byte
|
||||
if byte == 0:
|
||||
data = data + "(\\0)"
|
||||
elif byte == 0xa:
|
||||
data = data + "(\\a)"
|
||||
elif byte == 0xb:
|
||||
data = data + "(\\b)"
|
||||
elif byte == 0xc:
|
||||
data = data + "(\\c)"
|
||||
elif byte == '\n':
|
||||
data = data + "(\\n)"
|
||||
else:
|
||||
data = data + "(%s)" % chr(byte)
|
||||
if x < size-2:
|
||||
data = data + ":"
|
||||
except Exception as e:
|
||||
print e
|
||||
return data
|
||||
|
||||
def diagnose_nsstring_Command_Impl(debugger,command,result,internal_dict):
|
||||
"""
|
||||
A command to diagnose the LLDB NSString data formatter
|
||||
invoke as
|
||||
(lldb) diagnose-nsstring <expr returning NSString>
|
||||
e.g.
|
||||
(lldb) diagnose-nsstring @"Hello world"
|
||||
"""
|
||||
target = debugger.GetSelectedTarget()
|
||||
process = target.GetProcess()
|
||||
thread = process.GetSelectedThread()
|
||||
frame = thread.GetSelectedFrame()
|
||||
if not target.IsValid() or not process.IsValid():
|
||||
return "unable to get target/process - cannot proceed"
|
||||
options = lldb.SBExpressionOptions()
|
||||
options.SetFetchDynamicValue()
|
||||
error = lldb.SBError()
|
||||
if frame.IsValid():
|
||||
nsstring = frame.EvaluateExpression(command,options)
|
||||
else:
|
||||
nsstring = target.EvaluateExpression(command,options)
|
||||
print >>result,str(nsstring)
|
||||
nsstring_address = nsstring.GetValueAsUnsigned(0)
|
||||
if nsstring_address == 0:
|
||||
return "unable to obtain the string - cannot proceed"
|
||||
expression = "\
|
||||
struct $__lldb__notInlineMutable {\
|
||||
char* buffer;\
|
||||
signed long length;\
|
||||
signed long capacity;\
|
||||
unsigned int hasGap:1;\
|
||||
unsigned int isFixedCapacity:1;\
|
||||
unsigned int isExternalMutable:1;\
|
||||
unsigned int capacityProvidedExternally:1;\n\
|
||||
#if __LP64__\n\
|
||||
unsigned long desiredCapacity:60;\n\
|
||||
#else\n\
|
||||
unsigned long desiredCapacity:28;\n\
|
||||
#endif\n\
|
||||
void* contentsAllocator;\
|
||||
};\
|
||||
\
|
||||
struct $__lldb__CFString {\
|
||||
void* _cfisa;\
|
||||
uint8_t _cfinfo[4];\
|
||||
uint32_t _rc;\
|
||||
union {\
|
||||
struct __inline1 {\
|
||||
signed long length;\
|
||||
} inline1;\
|
||||
struct __notInlineImmutable1 {\
|
||||
char* buffer;\
|
||||
signed long length;\
|
||||
void* contentsDeallocator;\
|
||||
} notInlineImmutable1;\
|
||||
struct __notInlineImmutable2 {\
|
||||
char* buffer;\
|
||||
void* contentsDeallocator;\
|
||||
} notInlineImmutable2;\
|
||||
struct $__lldb__notInlineMutable notInlineMutable;\
|
||||
} variants;\
|
||||
};\
|
||||
"
|
||||
|
||||
expression = expression + "*(($__lldb__CFString*) %d)" % nsstring_address
|
||||
# print expression
|
||||
dumped = target.EvaluateExpression(expression,options)
|
||||
print >>result, str(dumped)
|
||||
|
||||
little_endian = (target.byte_order == lldb.eByteOrderLittle)
|
||||
ptr_size = target.addr_size
|
||||
|
||||
info_bits = dumped.GetChildMemberWithName("_cfinfo").GetChildAtIndex(0 if little_endian else 3).GetValueAsUnsigned(0)
|
||||
is_mutable = (info_bits & 1) == 1
|
||||
is_inline = (info_bits & 0x60) == 0
|
||||
has_explicit_length = (info_bits & (1 | 4)) != 4
|
||||
is_unicode = (info_bits & 0x10) == 0x10
|
||||
is_special = (nsstring.GetDynamicValue(lldb.eDynamicCanRunTarget).GetTypeName() == "NSPathStore2")
|
||||
has_null = (info_bits & 8) == 8
|
||||
|
||||
print >>result,"\nInfo=%d\nMutable=%s\nInline=%s\nExplicit=%s\nUnicode=%s\nSpecial=%s\nNull=%s\n" % \
|
||||
(info_bits, "yes" if is_mutable else "no","yes" if is_inline else "no","yes" if has_explicit_length else "no","yes" if is_unicode else "no","yes" if is_special else "no","yes" if has_null else "no")
|
||||
|
||||
|
||||
explicit_length_offset = 0
|
||||
if not has_null and has_explicit_length and not is_special:
|
||||
explicit_length_offset = 2*ptr_size
|
||||
if is_mutable and not is_inline:
|
||||
explicit_length_offset = explicit_length_offset + ptr_size
|
||||
elif is_inline:
|
||||
pass
|
||||
elif not is_inline and not is_mutable:
|
||||
explicit_length_offset = explicit_length_offset + ptr_size
|
||||
else:
|
||||
explicit_length_offset = 0
|
||||
|
||||
if explicit_length_offset == 0:
|
||||
print >>result,"There is no explicit length marker - skipping this step\n"
|
||||
else:
|
||||
explicit_length_offset = nsstring_address + explicit_length_offset
|
||||
explicit_length = process.ReadUnsignedFromMemory(explicit_length_offset, 4, error)
|
||||
print >>result,"Explicit length location is at 0x%x - read value is %d\n" % (explicit_length_offset,explicit_length)
|
||||
|
||||
if is_mutable:
|
||||
location = 2 * ptr_size + nsstring_address
|
||||
location = process.ReadPointerFromMemory(location,error)
|
||||
elif is_inline and has_explicit_length and not is_unicode and not is_special and not is_mutable:
|
||||
location = 3 * ptr_size + nsstring_address
|
||||
elif is_unicode:
|
||||
location = 2 * ptr_size + nsstring_address
|
||||
if is_inline:
|
||||
if not has_explicit_length:
|
||||
print >>result,"Unicode & Inline & !Explicit is a new combo - no formula for it"
|
||||
else:
|
||||
location += ptr_size
|
||||
else:
|
||||
location = process.ReadPointerFromMemory(location,error)
|
||||
elif is_special:
|
||||
location = nsstring_address + ptr_size + 4
|
||||
elif is_inline:
|
||||
location = 2 * ptr_size + nsstring_address
|
||||
if not has_explicit_length:
|
||||
location += 1
|
||||
else:
|
||||
location = 2 * ptr_size + nsstring_address
|
||||
location = process.ReadPointerFromMemory(location,error)
|
||||
print >>result,"Expected data location: 0x%x\n" % (location)
|
||||
print >>result,"1K of data around location: %s\n" % read_memory(process,location,1024)
|
||||
print >>result,"5K of data around string pointer: %s\n" % read_memory(process,nsstring_address,1024*5)
|
||||
|
||||
def __lldb_init_module(debugger, internal_dict):
|
||||
debugger.HandleCommand("command script add -f %s.diagnose_nsstring_Command_Impl diagnose-nsstring" % __name__)
|
||||
print 'The "diagnose-nsstring" command has been installed, type "help diagnose-nsstring" for detailed help.'
|
||||
|
||||
__lldb_init_module(lldb.debugger,None)
|
||||
__lldb_init_module = None
|
||||
270
external/bsd/llvm/dist/lldb/examples/python/diagnose_unwind.py
vendored
Normal file
270
external/bsd/llvm/dist/lldb/examples/python/diagnose_unwind.py
vendored
Normal file
@@ -0,0 +1,270 @@
|
||||
# This implements the "diagnose-unwind" command, usually installed
|
||||
# in the debug session like
|
||||
# command script import lldb.diagnose
|
||||
# it is used when lldb's backtrace fails -- it collects and prints
|
||||
# information about the stack frames, and tries an alternate unwind
|
||||
# algorithm, that will help to understand why lldb's unwind algorithm
|
||||
# did not succeed.
|
||||
|
||||
import optparse
|
||||
import lldb
|
||||
import re
|
||||
import shlex
|
||||
|
||||
# Print the frame number, pc, frame pointer, module UUID and function name
|
||||
# Returns the SBModule that contains the PC, if it could be found
|
||||
def backtrace_print_frame (target, frame_num, addr, fp):
|
||||
process = target.GetProcess()
|
||||
addr_for_printing = addr
|
||||
addr_width = process.GetAddressByteSize() * 2
|
||||
if frame_num > 0:
|
||||
addr = addr - 1
|
||||
|
||||
sbaddr = lldb.SBAddress()
|
||||
try:
|
||||
sbaddr.SetLoadAddress(addr, target)
|
||||
module_description = ""
|
||||
if sbaddr.GetModule():
|
||||
module_filename = ""
|
||||
module_uuid_str = sbaddr.GetModule().GetUUIDString()
|
||||
if module_uuid_str == None:
|
||||
module_uuid_str = ""
|
||||
if sbaddr.GetModule().GetFileSpec():
|
||||
module_filename = sbaddr.GetModule().GetFileSpec().GetFilename()
|
||||
if module_filename == None:
|
||||
module_filename = ""
|
||||
if module_uuid_str != "" or module_filename != "":
|
||||
module_description = '%s %s' % (module_filename, module_uuid_str)
|
||||
except Exception:
|
||||
print '%2d: pc==0x%-*x fp==0x%-*x' % (frame_num, addr_width, addr_for_printing, addr_width, fp)
|
||||
return
|
||||
|
||||
sym_ctx = target.ResolveSymbolContextForAddress(sbaddr, lldb.eSymbolContextEverything)
|
||||
if sym_ctx.IsValid() and sym_ctx.GetSymbol().IsValid():
|
||||
function_start = sym_ctx.GetSymbol().GetStartAddress().GetLoadAddress(target)
|
||||
offset = addr - function_start
|
||||
print '%2d: pc==0x%-*x fp==0x%-*x %s %s + %d' % (frame_num, addr_width, addr_for_printing, addr_width, fp, module_description, sym_ctx.GetSymbol().GetName(), offset)
|
||||
else:
|
||||
print '%2d: pc==0x%-*x fp==0x%-*x %s' % (frame_num, addr_width, addr_for_printing, addr_width, fp, module_description)
|
||||
return sbaddr.GetModule()
|
||||
|
||||
# A simple stack walk algorithm that follows the frame chain.
|
||||
# Returns a two-element list; the first element is a list of modules
|
||||
# seen and the second element is a list of addresses seen during the backtrace.
|
||||
def simple_backtrace(debugger):
|
||||
target = debugger.GetSelectedTarget()
|
||||
process = target.GetProcess()
|
||||
cur_thread = process.GetSelectedThread()
|
||||
|
||||
initial_fp = cur_thread.GetFrameAtIndex(0).GetFP()
|
||||
|
||||
# If the pseudoreg "fp" isn't recognized, on arm hardcode to r7 which is correct for Darwin programs.
|
||||
if initial_fp == lldb.LLDB_INVALID_ADDRESS and target.triple[0:3] == "arm":
|
||||
for reggroup in cur_thread.GetFrameAtIndex(1).registers:
|
||||
if reggroup.GetName() == "General Purpose Registers":
|
||||
for reg in reggroup:
|
||||
if reg.GetName() == "r7":
|
||||
initial_fp = int (reg.GetValue(), 16)
|
||||
|
||||
module_list = []
|
||||
address_list = [cur_thread.GetFrameAtIndex(0).GetPC()]
|
||||
this_module = backtrace_print_frame (target, 0, cur_thread.GetFrameAtIndex(0).GetPC(), initial_fp)
|
||||
print_stack_frame (process, initial_fp)
|
||||
print ""
|
||||
if this_module != None:
|
||||
module_list.append (this_module)
|
||||
if cur_thread.GetNumFrames() < 2:
|
||||
return [module_list, address_list]
|
||||
|
||||
cur_fp = process.ReadPointerFromMemory (initial_fp, lldb.SBError())
|
||||
cur_pc = process.ReadPointerFromMemory (initial_fp + process.GetAddressByteSize(), lldb.SBError())
|
||||
|
||||
frame_num = 1
|
||||
|
||||
while cur_pc != 0 and cur_fp != 0 and cur_pc != lldb.LLDB_INVALID_ADDRESS and cur_fp != lldb.LLDB_INVALID_ADDRESS:
|
||||
address_list.append (cur_pc)
|
||||
this_module = backtrace_print_frame (target, frame_num, cur_pc, cur_fp)
|
||||
print_stack_frame (process, cur_fp)
|
||||
print ""
|
||||
if this_module != None:
|
||||
module_list.append (this_module)
|
||||
frame_num = frame_num + 1
|
||||
next_pc = 0
|
||||
next_fp = 0
|
||||
if target.triple[0:6] == "x86_64" or target.triple[0:4] == "i386" or target.triple[0:3] == "arm":
|
||||
error = lldb.SBError()
|
||||
next_pc = process.ReadPointerFromMemory(cur_fp + process.GetAddressByteSize(), error)
|
||||
if not error.Success():
|
||||
next_pc = 0
|
||||
next_fp = process.ReadPointerFromMemory(cur_fp, error)
|
||||
if not error.Success():
|
||||
next_fp = 0
|
||||
# Clear the 0th bit for arm frames - this indicates it is a thumb frame
|
||||
if target.triple[0:3] == "arm" and (next_pc & 1) == 1:
|
||||
next_pc = next_pc & ~1
|
||||
cur_pc = next_pc
|
||||
cur_fp = next_fp
|
||||
this_module = backtrace_print_frame (target, frame_num, cur_pc, cur_fp)
|
||||
print_stack_frame (process, cur_fp)
|
||||
print ""
|
||||
if this_module != None:
|
||||
module_list.append (this_module)
|
||||
return [module_list, address_list]
|
||||
|
||||
def print_stack_frame(process, fp):
|
||||
if fp == 0 or fp == lldb.LLDB_INVALID_ADDRESS or fp == 1:
|
||||
return
|
||||
addr_size = process.GetAddressByteSize()
|
||||
addr = fp - (2 * addr_size)
|
||||
i = 0
|
||||
outline = "Stack frame from $fp-%d: " % (2 * addr_size)
|
||||
error = lldb.SBError()
|
||||
try:
|
||||
while i < 5 and error.Success():
|
||||
address = process.ReadPointerFromMemory(addr + (i * addr_size), error)
|
||||
outline += " 0x%x" % address
|
||||
i += 1
|
||||
print outline
|
||||
except Exception:
|
||||
return
|
||||
|
||||
def diagnose_unwind(debugger, command, result, dict):
|
||||
"""
|
||||
Gather diagnostic information to help debug incorrect unwind (backtrace)
|
||||
behavior in lldb. When there is a backtrace that doesn't look
|
||||
correct, run this command with the correct thread selected and a
|
||||
large amount of diagnostic information will be printed, it is likely
|
||||
to be helpful when reporting the problem.
|
||||
"""
|
||||
|
||||
command_args = shlex.split(command)
|
||||
parser = create_diagnose_unwind_options()
|
||||
try:
|
||||
(options, args) = parser.parse_args(command_args)
|
||||
except:
|
||||
return
|
||||
target = debugger.GetSelectedTarget()
|
||||
if target:
|
||||
process = target.GetProcess()
|
||||
if process:
|
||||
thread = process.GetSelectedThread()
|
||||
if thread:
|
||||
lldb_versions_match = re.search(r'[lL][lL][dD][bB]-(\d+)([.](\d+))?([.](\d+))?', debugger.GetVersionString())
|
||||
lldb_version = 0
|
||||
lldb_minor = 0
|
||||
if len(lldb_versions_match.groups()) >= 1 and lldb_versions_match.groups()[0]:
|
||||
lldb_major = int(lldb_versions_match.groups()[0])
|
||||
if len(lldb_versions_match.groups()) >= 5 and lldb_versions_match.groups()[4]:
|
||||
lldb_minor = int(lldb_versions_match.groups()[4])
|
||||
|
||||
modules_seen = []
|
||||
addresses_seen = []
|
||||
|
||||
print 'LLDB version %s' % debugger.GetVersionString()
|
||||
print 'Unwind diagnostics for thread %d' % thread.GetIndexID()
|
||||
print ""
|
||||
print "============================================================================================="
|
||||
print ""
|
||||
print "OS plugin setting:"
|
||||
debugger.HandleCommand("settings show target.process.python-os-plugin-path")
|
||||
print ""
|
||||
print "Live register context:"
|
||||
thread.SetSelectedFrame(0)
|
||||
debugger.HandleCommand("register read")
|
||||
print ""
|
||||
print "============================================================================================="
|
||||
print ""
|
||||
print "lldb's unwind algorithm:"
|
||||
print ""
|
||||
frame_num = 0
|
||||
for frame in thread.frames:
|
||||
if not frame.IsInlined():
|
||||
this_module = backtrace_print_frame (target, frame_num, frame.GetPC(), frame.GetFP())
|
||||
print_stack_frame (process, frame.GetFP())
|
||||
print ""
|
||||
if this_module != None:
|
||||
modules_seen.append (this_module)
|
||||
addresses_seen.append (frame.GetPC())
|
||||
frame_num = frame_num + 1
|
||||
print ""
|
||||
print "============================================================================================="
|
||||
print ""
|
||||
print "Simple stack walk algorithm:"
|
||||
print ""
|
||||
(module_list, address_list) = simple_backtrace(debugger)
|
||||
if module_list and module_list != None:
|
||||
modules_seen += module_list
|
||||
if address_list and address_list != None:
|
||||
addresses_seen = set(addresses_seen)
|
||||
addresses_seen.update(set(address_list))
|
||||
|
||||
print ""
|
||||
print "============================================================================================="
|
||||
print ""
|
||||
print "Modules seen in stack walks:"
|
||||
print ""
|
||||
modules_already_seen = set()
|
||||
for module in modules_seen:
|
||||
if module != None and module.GetFileSpec().GetFilename() != None:
|
||||
if not module.GetFileSpec().GetFilename() in modules_already_seen:
|
||||
debugger.HandleCommand('image list %s' % module.GetFileSpec().GetFilename())
|
||||
modules_already_seen.add(module.GetFileSpec().GetFilename())
|
||||
|
||||
print ""
|
||||
print "============================================================================================="
|
||||
print ""
|
||||
print "Disassembly ofaddresses seen in stack walks:"
|
||||
print ""
|
||||
additional_addresses_to_disassemble = addresses_seen
|
||||
for frame in thread.frames:
|
||||
if not frame.IsInlined():
|
||||
print "--------------------------------------------------------------------------------------"
|
||||
print ""
|
||||
print "Disassembly of %s, frame %d, address 0x%x" % (frame.GetFunctionName(), frame.GetFrameID(), frame.GetPC())
|
||||
print ""
|
||||
if target.triple[0:6] == "x86_64" or target.triple[0:4] == "i386":
|
||||
debugger.HandleCommand('disassemble -F att -a 0x%x' % frame.GetPC())
|
||||
else:
|
||||
debugger.HandleCommand('disassemble -a 0x%x' % frame.GetPC())
|
||||
if frame.GetPC() in additional_addresses_to_disassemble:
|
||||
additional_addresses_to_disassemble.remove (frame.GetPC())
|
||||
|
||||
for address in list(additional_addresses_to_disassemble):
|
||||
print "--------------------------------------------------------------------------------------"
|
||||
print ""
|
||||
print "Disassembly of 0x%x" % address
|
||||
print ""
|
||||
if target.triple[0:6] == "x86_64" or target.triple[0:4] == "i386":
|
||||
debugger.HandleCommand('disassemble -F att -a 0x%x' % address)
|
||||
else:
|
||||
debugger.HandleCommand('disassemble -a 0x%x' % address)
|
||||
|
||||
print ""
|
||||
print "============================================================================================="
|
||||
print ""
|
||||
additional_addresses_to_show_unwind = addresses_seen
|
||||
for frame in thread.frames:
|
||||
if not frame.IsInlined():
|
||||
print "--------------------------------------------------------------------------------------"
|
||||
print ""
|
||||
print "Unwind instructions for %s, frame %d" % (frame.GetFunctionName(), frame.GetFrameID())
|
||||
print ""
|
||||
debugger.HandleCommand('image show-unwind -a "0x%x"' % frame.GetPC())
|
||||
if frame.GetPC() in additional_addresses_to_show_unwind:
|
||||
additional_addresses_to_show_unwind.remove (frame.GetPC())
|
||||
|
||||
for address in list(additional_addresses_to_show_unwind):
|
||||
print "--------------------------------------------------------------------------------------"
|
||||
print ""
|
||||
print "Unwind instructions for 0x%x" % address
|
||||
print ""
|
||||
debugger.HandleCommand('image show-unwind -a "0x%x"' % address)
|
||||
|
||||
def create_diagnose_unwind_options():
|
||||
usage = "usage: %prog"
|
||||
description='''Print diagnostic information about a thread backtrace which will help to debug unwind problems'''
|
||||
parser = optparse.OptionParser(description=description, prog='diagnose_unwind',usage=usage)
|
||||
return parser
|
||||
|
||||
lldb.debugger.HandleCommand('command script add -f %s.diagnose_unwind diagnose-unwind' % __name__)
|
||||
print 'The "diagnose-unwind" command has been installed, type "help diagnose-unwind" for detailed help.'
|
||||
61
external/bsd/llvm/dist/lldb/examples/python/dict_utils.py
vendored
Executable file
61
external/bsd/llvm/dist/lldb/examples/python/dict_utils.py
vendored
Executable file
@@ -0,0 +1,61 @@
|
||||
|
||||
class LookupDictionary(dict):
|
||||
"""
|
||||
a dictionary which can lookup value by key, or keys by value
|
||||
"""
|
||||
def __init__(self, items=[]):
|
||||
"""items can be a list of pair_lists or a dictionary"""
|
||||
dict.__init__(self, items)
|
||||
|
||||
def get_keys_for_value(self, value, fail_value = None):
|
||||
"""find the key(s) as a list given a value"""
|
||||
list_result = [item[0] for item in self.items() if item[1] == value]
|
||||
if len(list_result) > 0:
|
||||
return list_result
|
||||
return fail_value
|
||||
|
||||
def get_first_key_for_value(self, value, fail_value = None):
|
||||
"""return the first key of this dictionary given the value"""
|
||||
list_result = [item[0] for item in self.items() if item[1] == value]
|
||||
if len(list_result) > 0:
|
||||
return list_result[0]
|
||||
return fail_value
|
||||
|
||||
def get_value(self, key, fail_value = None):
|
||||
"""find the value given a key"""
|
||||
if key in self:
|
||||
return self[key]
|
||||
return fail_value
|
||||
|
||||
|
||||
class Enum(LookupDictionary):
|
||||
|
||||
def __init__(self, initial_value=0, items=[]):
|
||||
"""items can be a list of pair_lists or a dictionary"""
|
||||
LookupDictionary.__init__(self, items)
|
||||
self.value = initial_value
|
||||
|
||||
def set_value(self, v):
|
||||
v_typename = typeof(v).__name__
|
||||
if v_typename == 'str':
|
||||
if str in self:
|
||||
v = self[v]
|
||||
else:
|
||||
v = 0
|
||||
else:
|
||||
self.value = v
|
||||
|
||||
def get_enum_value(self):
|
||||
return self.value
|
||||
|
||||
def get_enum_name(self):
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
s = self.get_first_key_for_value (self.value, None)
|
||||
if s == None:
|
||||
s = "%#8.8x" % self.value
|
||||
return s
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
168
external/bsd/llvm/dist/lldb/examples/python/disasm-stress-test.py
vendored
Executable file
168
external/bsd/llvm/dist/lldb/examples/python/disasm-stress-test.py
vendored
Executable file
@@ -0,0 +1,168 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import argparse, datetime, re, subprocess, sys, time
|
||||
|
||||
parser = argparse.ArgumentParser(description="Run an exhaustive test of the LLDB disassembler for a specific architecture.")
|
||||
|
||||
parser.add_argument('--arch', required=True, action='store', help='The architecture whose disassembler is to be tested')
|
||||
parser.add_argument('--bytes', required=True, action='store', type=int, help='The byte width of instructions for that architecture')
|
||||
parser.add_argument('--random', required=False, action='store_true', help='Enables non-sequential testing')
|
||||
parser.add_argument('--start', required=False, action='store', type=int, help='The first instruction value to test')
|
||||
parser.add_argument('--skip', required=False, action='store', type=int, help='The interval between instructions to test')
|
||||
parser.add_argument('--log', required=False, action='store', help='A log file to write the most recent instruction being tested')
|
||||
parser.add_argument('--time', required=False, action='store_true', help='Every 100,000 instructions, print an ETA to standard out')
|
||||
parser.add_argument('--lldb', required=False, action='store', help='The path to LLDB.framework, if LLDB should be overridden')
|
||||
|
||||
arguments = sys.argv[1:]
|
||||
|
||||
arg_ns = parser.parse_args(arguments)
|
||||
|
||||
def AddLLDBToSysPathOnMacOSX():
|
||||
def GetLLDBFrameworkPath():
|
||||
lldb_path = subprocess.check_output(["xcrun", "-find", "lldb"])
|
||||
re_result = re.match("(.*)/Developer/usr/bin/lldb", lldb_path)
|
||||
if re_result == None:
|
||||
return None
|
||||
xcode_contents_path = re_result.group(1)
|
||||
return xcode_contents_path + "/SharedFrameworks/LLDB.framework"
|
||||
|
||||
lldb_framework_path = GetLLDBFrameworkPath()
|
||||
|
||||
if lldb_framework_path == None:
|
||||
print "Couldn't find LLDB.framework"
|
||||
sys.exit(-1)
|
||||
|
||||
sys.path.append(lldb_framework_path + "/Resources/Python")
|
||||
|
||||
if arg_ns.lldb == None:
|
||||
AddLLDBToSysPathOnMacOSX()
|
||||
else:
|
||||
sys.path.append(arg_ns.lldb + "/Resources/Python")
|
||||
|
||||
import lldb
|
||||
|
||||
debugger = lldb.SBDebugger.Create()
|
||||
|
||||
if debugger.IsValid() == False:
|
||||
print "Couldn't create an SBDebugger"
|
||||
sys.exit(-1)
|
||||
|
||||
target = debugger.CreateTargetWithFileAndArch(None, arg_ns.arch)
|
||||
|
||||
if target.IsValid() == False:
|
||||
print "Couldn't create an SBTarget for architecture " + arg_ns.arch
|
||||
sys.exit(-1)
|
||||
|
||||
def ResetLogFile(log_file):
|
||||
if log_file != sys.stdout:
|
||||
log_file.seek(0)
|
||||
|
||||
def PrintByteArray(log_file, byte_array):
|
||||
for byte in byte_array:
|
||||
print >>log_file, hex(byte) + " ",
|
||||
print >>log_file
|
||||
|
||||
class SequentialInstructionProvider:
|
||||
def __init__(self, byte_width, log_file, start=0, skip=1):
|
||||
self.m_byte_width = byte_width
|
||||
self.m_log_file = log_file
|
||||
self.m_start = start
|
||||
self.m_skip = skip
|
||||
self.m_value = start
|
||||
self.m_last = (1 << (byte_width * 8)) - 1
|
||||
def PrintCurrentState(self, ret):
|
||||
ResetLogFile(self.m_log_file)
|
||||
print >>self.m_log_file, self.m_value
|
||||
PrintByteArray(self.m_log_file, ret)
|
||||
def GetNextInstruction(self):
|
||||
if self.m_value > self.m_last:
|
||||
return None
|
||||
ret = bytearray(self.m_byte_width)
|
||||
for i in range(self.m_byte_width):
|
||||
ret[self.m_byte_width - (i + 1)] = (self.m_value >> (i * 8)) & 255
|
||||
self.PrintCurrentState(ret)
|
||||
self.m_value += self.m_skip
|
||||
return ret
|
||||
def GetNumInstructions(self):
|
||||
return (self.m_last - self.m_start) / self.m_skip
|
||||
def __iter__(self):
|
||||
return self
|
||||
def next(self):
|
||||
ret = self.GetNextInstruction()
|
||||
if ret == None:
|
||||
raise StopIteration
|
||||
return ret
|
||||
|
||||
class RandomInstructionProvider:
|
||||
def __init__(self, byte_width, log_file):
|
||||
self.m_byte_width = byte_width
|
||||
self.m_log_file = log_file
|
||||
self.m_random_file = open("/dev/random", 'r')
|
||||
def PrintCurrentState(self, ret):
|
||||
ResetLogFile(self.m_log_file)
|
||||
PrintByteArray(self.m_log_file, ret)
|
||||
def GetNextInstruction(self):
|
||||
ret = bytearray(self.m_byte_width)
|
||||
for i in range(self.m_byte_width):
|
||||
ret[i] = self.m_random_file.read(1)
|
||||
self.PrintCurrentState(ret)
|
||||
return ret
|
||||
def __iter__(self):
|
||||
return self
|
||||
def next(self):
|
||||
ret = self.GetNextInstruction()
|
||||
if ret == None:
|
||||
raise StopIteration
|
||||
return ret
|
||||
|
||||
log_file = None
|
||||
|
||||
def GetProviderWithArguments(args):
|
||||
global log_file
|
||||
if args.log != None:
|
||||
log_file = open(args.log, 'w')
|
||||
else:
|
||||
log_file = sys.stdout
|
||||
instruction_provider = None
|
||||
if args.random == True:
|
||||
instruction_provider = RandomInstructionProvider(args.bytes, log_file)
|
||||
else:
|
||||
start = 0
|
||||
skip = 1
|
||||
if args.start != None:
|
||||
start = args.start
|
||||
if args.skip != None:
|
||||
skip = args.skip
|
||||
instruction_provider = SequentialInstructionProvider(args.bytes, log_file, start, skip)
|
||||
return instruction_provider
|
||||
|
||||
instruction_provider = GetProviderWithArguments(arg_ns)
|
||||
|
||||
fake_address = lldb.SBAddress()
|
||||
|
||||
actually_time = arg_ns.time and not arg_ns.random
|
||||
|
||||
if actually_time:
|
||||
num_instructions_logged = 0
|
||||
total_num_instructions = instruction_provider.GetNumInstructions()
|
||||
start_time = time.time()
|
||||
|
||||
for inst_bytes in instruction_provider:
|
||||
if actually_time:
|
||||
if (num_instructions_logged != 0) and (num_instructions_logged % 100000 == 0):
|
||||
curr_time = time.time()
|
||||
elapsed_time = curr_time - start_time
|
||||
remaining_time = float(total_num_instructions - num_instructions_logged) * (float(elapsed_time) / float(num_instructions_logged))
|
||||
print str(datetime.timedelta(seconds=remaining_time))
|
||||
num_instructions_logged = num_instructions_logged + 1
|
||||
inst_list = target.GetInstructions(fake_address, inst_bytes)
|
||||
if not inst_list.IsValid():
|
||||
print >>log_file, "Invalid instruction list"
|
||||
continue
|
||||
inst = inst_list.GetInstructionAtIndex(0)
|
||||
if not inst.IsValid():
|
||||
print >>log_file, "Invalid instruction"
|
||||
continue
|
||||
instr_output_stream = lldb.SBStream()
|
||||
inst.GetDescription(instr_output_stream)
|
||||
print >>log_file, instr_output_stream.GetData()
|
||||
119
external/bsd/llvm/dist/lldb/examples/python/disasm.py
vendored
Executable file
119
external/bsd/llvm/dist/lldb/examples/python/disasm.py
vendored
Executable file
@@ -0,0 +1,119 @@
|
||||
#!/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 os
|
||||
import sys
|
||||
|
||||
def disassemble_instructions (insts):
|
||||
for i in insts:
|
||||
print i
|
||||
|
||||
def usage():
|
||||
print "Usage: disasm.py [-n name] executable-image"
|
||||
print " By default, it breaks at and disassembles the 'main' function."
|
||||
sys.exit(0)
|
||||
|
||||
if len(sys.argv) == 2:
|
||||
fname = 'main'
|
||||
exe = sys.argv[1]
|
||||
elif len(sys.argv) == 4:
|
||||
if sys.argv[1] != '-n':
|
||||
usage()
|
||||
else:
|
||||
fname = sys.argv[2]
|
||||
exe = sys.argv[3]
|
||||
else:
|
||||
usage()
|
||||
|
||||
# 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 (fname, 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
|
||||
# Now get all instructions for this symbol and print them
|
||||
insts = symbol.GetInstructions(target)
|
||||
disassemble_instructions (insts)
|
||||
|
||||
registerList = frame.GetRegisters()
|
||||
print "Frame registers (size of register set = %d):" % registerList.GetSize()
|
||||
for value in registerList:
|
||||
#print value
|
||||
print "%s (number of children = %d):" % (value.GetName(), value.GetNumChildren())
|
||||
for child in value:
|
||||
print "Name: ", child.GetName(), " Value: ", child.GetValue()
|
||||
|
||||
print "Hit the breakpoint at main, enter to continue and wait for program to exit or 'Ctrl-D'/'quit' to terminate the program"
|
||||
next = sys.stdin.readline()
|
||||
if not next or next.rstrip('\n') == 'quit':
|
||||
print "Terminating the inferior process..."
|
||||
process.Kill()
|
||||
else:
|
||||
# Now continue to the program exit
|
||||
process.Continue()
|
||||
# When we return from the above function we will hopefully be at the
|
||||
# program exit. Print out some process info
|
||||
print process
|
||||
elif state == lldb.eStateExited:
|
||||
print "Didn't hit the breakpoint at main, program has exited..."
|
||||
else:
|
||||
print "Unexpected process state: %s, killing process..." % debugger.StateAsCString (state)
|
||||
process.Kill()
|
||||
|
||||
|
||||
|
||||
lldb.SBDebugger.Terminate()
|
||||
221
external/bsd/llvm/dist/lldb/examples/python/file_extract.py
vendored
Executable file
221
external/bsd/llvm/dist/lldb/examples/python/file_extract.py
vendored
Executable file
@@ -0,0 +1,221 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
import string
|
||||
import struct
|
||||
import sys
|
||||
|
||||
class FileExtract:
|
||||
'''Decode binary data from a file'''
|
||||
|
||||
def __init__(self, f, b = '='):
|
||||
'''Initialize with an open binary file and optional byte order'''
|
||||
|
||||
self.file = f
|
||||
self.byte_order = b
|
||||
self.offsets = list()
|
||||
|
||||
def set_byte_order(self, b):
|
||||
'''Set the byte order, valid values are "big", "little", "swap", "native", "<", ">", "@", "="'''
|
||||
if b == 'big':
|
||||
self.byte_order = '>'
|
||||
elif b == 'little':
|
||||
self.byte_order = '<'
|
||||
elif b == 'swap':
|
||||
# swap what ever the current byte order is
|
||||
self.byte_order = swap_unpack_char()
|
||||
elif b == 'native':
|
||||
self.byte_order = '='
|
||||
elif b == '<' or b == '>' or b == '@' or b == '=':
|
||||
self.byte_order = b
|
||||
else:
|
||||
print "error: invalid byte order specified: '%s'" % b
|
||||
|
||||
def is_in_memory(self):
|
||||
return False
|
||||
|
||||
def seek(self, offset, whence = 0):
|
||||
if self.file:
|
||||
return self.file.seek(offset, whence)
|
||||
raise ValueError
|
||||
|
||||
def tell(self):
|
||||
if self.file:
|
||||
return self.file.tell()
|
||||
raise ValueError
|
||||
|
||||
def read_size (self, byte_size):
|
||||
s = self.file.read(byte_size)
|
||||
if len(s) != byte_size:
|
||||
return None
|
||||
return s
|
||||
|
||||
def push_offset_and_seek(self, offset):
|
||||
'''Push the current file offset and seek to "offset"'''
|
||||
self.offsets.append(self.file.tell())
|
||||
self.file.seek(offset, 0)
|
||||
|
||||
def pop_offset_and_seek(self):
|
||||
'''Pop a previously pushed file offset, or do nothing if there were no previously pushed offsets'''
|
||||
if len(self.offsets) > 0:
|
||||
self.file.seek(self.offsets.pop())
|
||||
|
||||
def get_sint8(self, fail_value=0):
|
||||
'''Extract a single int8_t from the binary file at the current file position, returns a single integer'''
|
||||
s = self.read_size(1)
|
||||
if s:
|
||||
v, = struct.unpack(self.byte_order + 'b', s)
|
||||
return v
|
||||
else:
|
||||
return fail_value
|
||||
|
||||
def get_uint8(self, fail_value=0):
|
||||
'''Extract a single uint8_t from the binary file at the current file position, returns a single integer'''
|
||||
s = self.read_size(1)
|
||||
if s:
|
||||
v, = struct.unpack(self.byte_order + 'B', s)
|
||||
return v
|
||||
else:
|
||||
return fail_value
|
||||
|
||||
def get_sint16(self, fail_value=0):
|
||||
'''Extract a single int16_t from the binary file at the current file position, returns a single integer'''
|
||||
s = self.read_size(2)
|
||||
if s:
|
||||
v, = struct.unpack(self.byte_order + 'h', s)
|
||||
return v
|
||||
else:
|
||||
return fail_value
|
||||
|
||||
def get_uint16(self, fail_value=0):
|
||||
'''Extract a single uint16_t from the binary file at the current file position, returns a single integer'''
|
||||
s = self.read_size(2)
|
||||
if s:
|
||||
v, = struct.unpack(self.byte_order + 'H', s)
|
||||
return v
|
||||
else:
|
||||
return fail_value
|
||||
|
||||
def get_sint32(self, fail_value=0):
|
||||
'''Extract a single int32_t from the binary file at the current file position, returns a single integer'''
|
||||
s = self.read_size(4)
|
||||
if s:
|
||||
v, = struct.unpack(self.byte_order + 'i', s)
|
||||
return v
|
||||
else:
|
||||
return fail_value
|
||||
|
||||
def get_uint32(self, fail_value=0):
|
||||
'''Extract a single uint32_t from the binary file at the current file position, returns a single integer'''
|
||||
s = self.read_size(4)
|
||||
if s:
|
||||
v, = struct.unpack(self.byte_order + 'I', s)
|
||||
return v
|
||||
else:
|
||||
return fail_value
|
||||
|
||||
def get_sint64(self, fail_value=0):
|
||||
'''Extract a single int64_t from the binary file at the current file position, returns a single integer'''
|
||||
s = self.read_size(8)
|
||||
if s:
|
||||
v, = struct.unpack(self.byte_order + 'q', s)
|
||||
return v
|
||||
else:
|
||||
return fail_value
|
||||
|
||||
def get_uint64(self, fail_value=0):
|
||||
'''Extract a single uint64_t from the binary file at the current file position, returns a single integer'''
|
||||
s = self.read_size(8)
|
||||
if s:
|
||||
v, = struct.unpack(self.byte_order + 'Q', s)
|
||||
return v
|
||||
else:
|
||||
return fail_value
|
||||
|
||||
def get_fixed_length_c_string(self, n, fail_value='', isprint_only_with_space_padding=False):
|
||||
'''Extract a single fixed length C string from the binary file at the current file position, returns a single C string'''
|
||||
s = self.read_size(n)
|
||||
if s:
|
||||
cstr, = struct.unpack(self.byte_order + ("%i" % n) + 's', s)
|
||||
# Strip trialing NULLs
|
||||
cstr = string.strip(cstr, "\0")
|
||||
if isprint_only_with_space_padding:
|
||||
for c in cstr:
|
||||
if c in string.printable or ord(c) == 0:
|
||||
continue
|
||||
return fail_value
|
||||
return cstr
|
||||
else:
|
||||
return fail_value
|
||||
|
||||
def get_c_string(self):
|
||||
'''Extract a single NULL terminated C string from the binary file at the current file position, returns a single C string'''
|
||||
cstr = ''
|
||||
byte = self.get_uint8()
|
||||
while byte != 0:
|
||||
cstr += "%c" % byte
|
||||
byte = self.get_uint8()
|
||||
return cstr
|
||||
|
||||
def get_n_sint8(self, n, fail_value=0):
|
||||
'''Extract "n" int8_t integers from the binary file at the current file position, returns a list of integers'''
|
||||
s = self.read_size(n)
|
||||
if s:
|
||||
return struct.unpack(self.byte_order + ("%u" % n) + 'b', s)
|
||||
else:
|
||||
return (fail_value,) * n
|
||||
|
||||
def get_n_uint8(self, n, fail_value=0):
|
||||
'''Extract "n" uint8_t integers from the binary file at the current file position, returns a list of integers'''
|
||||
s = self.read_size(n)
|
||||
if s:
|
||||
return struct.unpack(self.byte_order + ("%u" % n) + 'B', s)
|
||||
else:
|
||||
return (fail_value,) * n
|
||||
|
||||
def get_n_sint16(self, n, fail_value=0):
|
||||
'''Extract "n" int16_t integers from the binary file at the current file position, returns a list of integers'''
|
||||
s = self.read_size(2*n)
|
||||
if s:
|
||||
return struct.unpack(self.byte_order + ("%u" % n) + 'h', s)
|
||||
else:
|
||||
return (fail_value,) * n
|
||||
|
||||
def get_n_uint16(self, n, fail_value=0):
|
||||
'''Extract "n" uint16_t integers from the binary file at the current file position, returns a list of integers'''
|
||||
s = self.read_size(2*n)
|
||||
if s:
|
||||
return struct.unpack(self.byte_order + ("%u" % n) + 'H', s)
|
||||
else:
|
||||
return (fail_value,) * n
|
||||
|
||||
def get_n_sint32(self, n, fail_value=0):
|
||||
'''Extract "n" int32_t integers from the binary file at the current file position, returns a list of integers'''
|
||||
s = self.read_size(4*n)
|
||||
if s:
|
||||
return struct.unpack(self.byte_order + ("%u" % n) + 'i', s)
|
||||
else:
|
||||
return (fail_value,) * n
|
||||
|
||||
def get_n_uint32(self, n, fail_value=0):
|
||||
'''Extract "n" uint32_t integers from the binary file at the current file position, returns a list of integers'''
|
||||
s = self.read_size(4*n)
|
||||
if s:
|
||||
return struct.unpack(self.byte_order + ("%u" % n) + 'I', s)
|
||||
else:
|
||||
return (fail_value,) * n
|
||||
|
||||
def get_n_sint64(self, n, fail_value=0):
|
||||
'''Extract "n" int64_t integers from the binary file at the current file position, returns a list of integers'''
|
||||
s = self.read_size(8*n)
|
||||
if s:
|
||||
return struct.unpack(self.byte_order + ("%u" % n) + 'q', s)
|
||||
else:
|
||||
return (fail_value,) * n
|
||||
|
||||
def get_n_uint64(self, n, fail_value=0):
|
||||
'''Extract "n" uint64_t integers from the binary file at the current file position, returns a list of integers'''
|
||||
s = self.read_size(8*n)
|
||||
if s:
|
||||
return struct.unpack(self.byte_order + ("%u" % n) + 'Q', s)
|
||||
else:
|
||||
return (fail_value,) * n
|
||||
24
external/bsd/llvm/dist/lldb/examples/python/gdb_disassemble.py
vendored
Executable file
24
external/bsd/llvm/dist/lldb/examples/python/gdb_disassemble.py
vendored
Executable file
@@ -0,0 +1,24 @@
|
||||
import lldb
|
||||
|
||||
def disassemble(debugger, command, result, dict):
|
||||
if lldb.frame.function:
|
||||
instructions = lldb.frame.function.instructions
|
||||
start_addr = lldb.frame.function.addr.load_addr
|
||||
name = lldb.frame.function.name
|
||||
elif lldb.frame.symbol:
|
||||
instructions = lldb.frame.symbol.instructions
|
||||
start_addr = lldb.frame.symbol.addr.load_addr
|
||||
name = lldb.frame.symbol.name
|
||||
|
||||
for inst in instructions:
|
||||
inst_addr = inst.addr.load_addr
|
||||
inst_offset = inst_addr - start_addr
|
||||
comment = inst.comment
|
||||
if comment:
|
||||
print "<%s + %-4u> 0x%x %8s %s ; %s" % (name, inst_offset, inst_addr, inst.mnemonic, inst.operands, comment)
|
||||
else:
|
||||
print "<%s + %-4u> 0x%x %8s %s" % (name, inst_offset, inst_addr, inst.mnemonic, inst.operands)
|
||||
|
||||
# Install the command when the module gets imported
|
||||
lldb.debugger.HandleCommand('command script add -f gdb_disassemble.disassemble gdb-disassemble')
|
||||
print 'Installed "gdb-disassemble" command for disassembly'
|
||||
1042
external/bsd/llvm/dist/lldb/examples/python/gdbremote.py
vendored
Executable file
1042
external/bsd/llvm/dist/lldb/examples/python/gdbremote.py
vendored
Executable file
File diff suppressed because it is too large
Load Diff
72
external/bsd/llvm/dist/lldb/examples/python/globals.py
vendored
Executable file
72
external/bsd/llvm/dist/lldb/examples/python/globals.py
vendored
Executable file
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# For the shells csh, tcsh:
|
||||
# ( setenv PYTHONPATH /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python ; ./globals.py <path> [<path> ...])
|
||||
#
|
||||
# For the shells sh, bash:
|
||||
# PYTHONPATH=/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python ./globals.py <path> [<path> ...]
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
import lldb
|
||||
import commands
|
||||
import optparse
|
||||
import os
|
||||
import shlex
|
||||
import sys
|
||||
|
||||
def get_globals(raw_path, options):
|
||||
error = lldb.SBError()
|
||||
# Resolve the path if needed
|
||||
path = os.path.expanduser(raw_path)
|
||||
# Create a target using path + options
|
||||
target = lldb.debugger.CreateTarget(path, options.arch, options.platform, False, error)
|
||||
if target:
|
||||
# Get the executable module
|
||||
module = target.module[target.executable.basename]
|
||||
if module:
|
||||
# Keep track of which variables we have already looked up
|
||||
global_names = list()
|
||||
# Iterate through all symbols in the symbol table and watch for any DATA symbols
|
||||
for symbol in module.symbols:
|
||||
if symbol.type == lldb.eSymbolTypeData:
|
||||
# The symbol is a DATA symbol, lets try and find all global variables
|
||||
# that match this name and print them
|
||||
global_name = symbol.name
|
||||
# Make sure we don't lookup the same variable twice
|
||||
if global_name not in global_names:
|
||||
global_names.append(global_name)
|
||||
# Find all global variables by name
|
||||
global_variable_list = module.FindGlobalVariables (target, global_name, lldb.UINT32_MAX)
|
||||
if global_variable_list:
|
||||
# Print results for anything that matched
|
||||
for global_variable in global_variable_list:
|
||||
print 'name = %s' % global_variable.name # returns the global variable name as a string
|
||||
print 'value = %s' % global_variable.value # Returns the variable value as a string
|
||||
print 'type = %s' % global_variable.type # Returns an lldb.SBType object
|
||||
print 'addr = %s' % global_variable.addr # Returns an lldb.SBAddress (section offset address) for this global
|
||||
print 'file_addr = 0x%x' % global_variable.addr.file_addr # Returns the file virtual address for this global
|
||||
print 'location = %s' % global_variable.location # returns the global variable value as a string
|
||||
print 'size = %s' % global_variable.size # Returns the size in bytes of this global variable
|
||||
print
|
||||
|
||||
def globals(command_args):
|
||||
'''Extract all globals from any arguments which must be paths to object files.'''
|
||||
usage = "usage: %prog [options] <PATH> [PATH ...]"
|
||||
description='''This command will find all globals in the specified object file and return an list() of lldb.SBValue objects (which might be empty).'''
|
||||
parser = optparse.OptionParser(description=description, prog='globals',usage=usage)
|
||||
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
|
||||
parser.add_option('-a', '--arch', type='string', metavar='arch', dest='arch', help='Specify an architecture (or triple) to use when extracting from a file.')
|
||||
parser.add_option('-p', '--platform', type='string', metavar='platform', dest='platform', help='Specify the platform to use when creating the debug target. Valid values include "localhost", "darwin-kernel", "ios-simulator", "remote-freebsd", "remote-macosx", "remote-ios", "remote-linux".')
|
||||
try:
|
||||
(options, args) = parser.parse_args(command_args)
|
||||
except:
|
||||
return
|
||||
|
||||
for path in args:
|
||||
get_globals (path, options)
|
||||
|
||||
if __name__ == '__main__':
|
||||
lldb.debugger = lldb.SBDebugger.Create()
|
||||
globals (sys.argv[1:])
|
||||
|
||||
173
external/bsd/llvm/dist/lldb/examples/python/jump.py
vendored
Normal file
173
external/bsd/llvm/dist/lldb/examples/python/jump.py
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
import lldb, re
|
||||
|
||||
def parse_linespec (linespec, frame, result):
|
||||
"""Handles a subset of GDB-style linespecs. Specifically:
|
||||
|
||||
number - A line in the current file
|
||||
+offset - The line /offset/ lines after this line
|
||||
-offset - The line /offset/ lines before this line
|
||||
filename:number - Line /number/ in file /filename/
|
||||
function - The start of /function/
|
||||
*address - The pointer target of /address/, which must be a literal (but see `` in LLDB)
|
||||
|
||||
We explicitly do not handle filename:function because it is ambiguous in Objective-C.
|
||||
|
||||
This function returns a list of addresses."""
|
||||
|
||||
breakpoint = None
|
||||
target = frame.GetThread().GetProcess().GetTarget()
|
||||
|
||||
matched = False
|
||||
|
||||
if (not matched):
|
||||
mo = re.match("^([0-9]+)$", linespec)
|
||||
if (mo != None):
|
||||
matched = True
|
||||
#print "Matched <linenum>"
|
||||
line_number = int(mo.group(1))
|
||||
line_entry = frame.GetLineEntry()
|
||||
if not line_entry.IsValid():
|
||||
result.AppendMessage("Specified a line in the current file, but the current frame doesn't have line table information.")
|
||||
return
|
||||
breakpoint = target.BreakpointCreateByLocation (line_entry.GetFileSpec(), line_number)
|
||||
|
||||
if (not matched):
|
||||
mo = re.match("^\+([0-9]+)$", linespec)
|
||||
if (mo != None):
|
||||
matched = True
|
||||
#print "Matched +<count>"
|
||||
line_number = int(mo.group(1))
|
||||
line_entry = frame.GetLineEntry()
|
||||
if not line_entry.IsValid():
|
||||
result.AppendMessage("Specified a line in the current file, but the current frame doesn't have line table information.")
|
||||
return
|
||||
breakpoint = target.BreakpointCreateByLocation(line_entry.GetFileSpec(), (line_entry.GetLine() + line_number))
|
||||
|
||||
if (not matched):
|
||||
mo = re.match("^\-([0-9]+)$", linespec)
|
||||
if (mo != None):
|
||||
matched = True
|
||||
#print "Matched -<count>"
|
||||
line_number = int(mo.group(1))
|
||||
line_entry = frame.GetLineEntry()
|
||||
if not line_entry.IsValid():
|
||||
result.AppendMessage("Specified a line in the current file, but the current frame doesn't have line table information.")
|
||||
return
|
||||
breakpoint = target.BreakpointCreateByLocation(line_entry.GetFileSpec(), (line_entry.GetLine() - line_number))
|
||||
|
||||
if (not matched):
|
||||
mo = re.match("^(.*):([0-9]+)$", linespec)
|
||||
if (mo != None):
|
||||
matched = True
|
||||
#print "Matched <filename>:<linenum>"
|
||||
file_name = mo.group(1)
|
||||
line_number = int(mo.group(2))
|
||||
breakpoint = target.BreakpointCreateByLocation(file_name, line_number)
|
||||
|
||||
if (not matched):
|
||||
mo = re.match("\*((0x)?([0-9a-f]+))$", linespec)
|
||||
if (mo != None):
|
||||
matched = True
|
||||
#print "Matched <address-expression>"
|
||||
address = long(mo.group(1), base=0)
|
||||
breakpoint = target.BreakpointCreateByAddress(address)
|
||||
|
||||
if (not matched):
|
||||
#print "Trying <function-name>"
|
||||
breakpoint = target.BreakpointCreateByName(linespec)
|
||||
|
||||
num_locations = breakpoint.GetNumLocations()
|
||||
|
||||
if (num_locations == 0):
|
||||
result.AppendMessage("The line specification provided doesn't resolve to any addresses.")
|
||||
|
||||
addr_list = []
|
||||
|
||||
for location_index in range(num_locations):
|
||||
location = breakpoint.GetLocationAtIndex(location_index)
|
||||
addr_list.append(location.GetAddress())
|
||||
|
||||
target.BreakpointDelete(breakpoint.GetID())
|
||||
|
||||
return addr_list
|
||||
|
||||
def usage_string():
|
||||
return """ Sets the program counter to a specific address.
|
||||
|
||||
Syntax: jump <linespec> [<location-id>]
|
||||
|
||||
Command Options Usage:
|
||||
jump <linenum>
|
||||
jump +<count>
|
||||
jump -<count>
|
||||
jump <filename>:<linenum>
|
||||
jump <function-name>
|
||||
jump *<address-expression>
|
||||
|
||||
<location-id> serves to disambiguate when multiple locations could be meant."""
|
||||
|
||||
def jump (debugger, command, result, internal_dict):
|
||||
if (command == ""):
|
||||
result.AppendMessage(usage_string())
|
||||
|
||||
args = command.split()
|
||||
|
||||
if not debugger.IsValid():
|
||||
result.AppendMessage("Invalid debugger!")
|
||||
return
|
||||
|
||||
target = debugger.GetSelectedTarget()
|
||||
if not target.IsValid():
|
||||
result.AppendMessage("jump requires a valid target.")
|
||||
return
|
||||
|
||||
process = target.GetProcess()
|
||||
if not process.IsValid():
|
||||
result.AppendMessage("jump requires a valid process.")
|
||||
return
|
||||
|
||||
thread = process.GetSelectedThread()
|
||||
if not thread.IsValid():
|
||||
result.AppendMessage("jump requires a valid thread.")
|
||||
return
|
||||
|
||||
frame = thread.GetSelectedFrame()
|
||||
if not frame.IsValid():
|
||||
result.AppendMessage("jump requires a valid frame.")
|
||||
return
|
||||
|
||||
addresses = parse_linespec(args[0], frame, result)
|
||||
|
||||
stream = lldb.SBStream()
|
||||
|
||||
if len(addresses) == 0:
|
||||
return
|
||||
|
||||
desired_address = addresses[0]
|
||||
|
||||
if len(addresses) > 1:
|
||||
if len(args) == 2:
|
||||
desired_index = int(args[1])
|
||||
if (desired_index >= 0) and (desired_index < len(addresses)):
|
||||
desired_address = addresses[desired_index]
|
||||
else:
|
||||
result.AppendMessage("Desired index " + args[1] + " is not one of the options.")
|
||||
return
|
||||
else:
|
||||
index = 0
|
||||
result.AppendMessage("The specified location resolves to multiple targets.");
|
||||
for address in addresses:
|
||||
stream.Clear()
|
||||
address.GetDescription(stream)
|
||||
result.AppendMessage(" Location ID " + str(index) + ": " + stream.GetData())
|
||||
index = index + 1
|
||||
result.AppendMessage("Please type 'jump " + command + " <location-id>' to choose one.")
|
||||
return
|
||||
|
||||
frame.SetPC(desired_address.GetLoadAddress(target))
|
||||
|
||||
if lldb.debugger:
|
||||
# Module is being run inside the LLDB interpreter
|
||||
jump.__doc__ = usage_string()
|
||||
lldb.debugger.HandleCommand('command script add -f jump.jump jump')
|
||||
print 'The "jump" command has been installed, type "help jump" or "jump <ENTER>" for detailed help.'
|
||||
59
external/bsd/llvm/dist/lldb/examples/python/lldb_module_utils.py
vendored
Normal file
59
external/bsd/llvm/dist/lldb/examples/python/lldb_module_utils.py
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import lldb
|
||||
import optparse
|
||||
import shlex
|
||||
import string
|
||||
import sys
|
||||
|
||||
def create_dump_module_line_tables_options ():
|
||||
usage = "usage: dump_module_line_tables [options] MODULE1 [MODULE2 ...]"
|
||||
description='''Dumps all line tables from all compile units for any modules specified as arguments. Specifying the --verbose flag will output address ranges for each line entry.'''
|
||||
parser = optparse.OptionParser(description=description, prog='start_gdb_log',usage=usage)
|
||||
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='Display verbose output.', default=False)
|
||||
return parser
|
||||
|
||||
def dump_module_line_tables(debugger, command, result, dict):
|
||||
'''Dumps all line tables from all compile units for any modules specified as arguments.'''
|
||||
command_args = shlex.split(command)
|
||||
|
||||
parser = create_dump_module_line_tables_options ()
|
||||
try:
|
||||
(options, args) = parser.parse_args(command_args)
|
||||
except:
|
||||
return
|
||||
if command_args:
|
||||
target = debugger.GetSelectedTarget()
|
||||
lldb.target = target
|
||||
for module_name in command_args:
|
||||
result.PutCString('Searching for module "%s"' % (module_name,))
|
||||
module_fspec = lldb.SBFileSpec (module_name, False)
|
||||
module = target.FindModule (module_fspec);
|
||||
if module:
|
||||
for cu_idx in range (module.GetNumCompileUnits()):
|
||||
cu = module.GetCompileUnitAtIndex(cu_idx)
|
||||
result.PutCString("\n%s:" % (cu.file))
|
||||
for line_idx in range(cu.GetNumLineEntries()):
|
||||
line_entry = cu.GetLineEntryAtIndex(line_idx)
|
||||
start_file_addr = line_entry.addr.file_addr
|
||||
end_file_addr = line_entry.end_addr.file_addr
|
||||
# If the two addresses are equal, this line table entry is a termination entry
|
||||
if options.verbose:
|
||||
if start_file_addr != end_file_addr:
|
||||
result.PutCString('[%#x - %#x): %s' % (start_file_addr, end_file_addr, line_entry))
|
||||
else:
|
||||
if start_file_addr == end_file_addr:
|
||||
result.PutCString('%#x: END' % (start_file_addr))
|
||||
else:
|
||||
result.PutCString('%#x: %s' % (start_file_addr, line_entry))
|
||||
if start_file_addr == end_file_addr:
|
||||
result.Printf("\n")
|
||||
else:
|
||||
result.PutCString ("no module for '%s'" % module)
|
||||
else:
|
||||
result.PutCString ("error: invalid target")
|
||||
|
||||
parser = create_dump_module_line_tables_options ()
|
||||
dump_module_line_tables.__doc__ = parser.format_help()
|
||||
lldb.debugger.HandleCommand('command script add -f %s.dump_module_line_tables dump_module_line_tables' % __name__)
|
||||
print 'Installed "dump_module_line_tables" command'
|
||||
1687
external/bsd/llvm/dist/lldb/examples/python/mach_o.py
vendored
Executable file
1687
external/bsd/llvm/dist/lldb/examples/python/mach_o.py
vendored
Executable file
File diff suppressed because it is too large
Load Diff
181
external/bsd/llvm/dist/lldb/examples/python/memory.py
vendored
Executable file
181
external/bsd/llvm/dist/lldb/examples/python/memory.py
vendored
Executable file
@@ -0,0 +1,181 @@
|
||||
#!/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" just
|
||||
# import it with the full path using the "command script import"
|
||||
# command
|
||||
# (lldb) command script import /path/to/cmdtemplate.py
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
import commands
|
||||
import platform
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
try:
|
||||
# Just try for LLDB in case PYTHONPATH is already correctly setup
|
||||
import lldb
|
||||
except ImportError:
|
||||
lldb_python_dirs = list()
|
||||
# lldb is not in the PYTHONPATH, try some defaults for the current platform
|
||||
platform_system = platform.system()
|
||||
if platform_system == 'Darwin':
|
||||
# On Darwin, try the currently selected Xcode directory
|
||||
xcode_dir = commands.getoutput("xcode-select --print-path")
|
||||
if xcode_dir:
|
||||
lldb_python_dirs.append(os.path.realpath(xcode_dir + '/../SharedFrameworks/LLDB.framework/Resources/Python'))
|
||||
lldb_python_dirs.append(xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
|
||||
lldb_python_dirs.append('/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
|
||||
success = False
|
||||
for lldb_python_dir in lldb_python_dirs:
|
||||
if os.path.exists(lldb_python_dir):
|
||||
if not (sys.path.__contains__(lldb_python_dir)):
|
||||
sys.path.append(lldb_python_dir)
|
||||
try:
|
||||
import lldb
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
print 'imported lldb from: "%s"' % (lldb_python_dir)
|
||||
success = True
|
||||
break
|
||||
if not success:
|
||||
print "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly"
|
||||
sys.exit(1)
|
||||
|
||||
import commands
|
||||
import optparse
|
||||
import shlex
|
||||
import string
|
||||
import struct
|
||||
import time
|
||||
|
||||
def append_data_callback(option, opt_str, value, parser):
|
||||
if opt_str == "--uint8":
|
||||
int8 = int(value, 0)
|
||||
parser.values.data += struct.pack('1B',int8)
|
||||
if opt_str == "--uint16":
|
||||
int16 = int(value, 0)
|
||||
parser.values.data += struct.pack('1H',int16)
|
||||
if opt_str == "--uint32":
|
||||
int32 = int(value, 0)
|
||||
parser.values.data += struct.pack('1I',int32)
|
||||
if opt_str == "--uint64":
|
||||
int64 = int(value, 0)
|
||||
parser.values.data += struct.pack('1Q',int64)
|
||||
if opt_str == "--int8":
|
||||
int8 = int(value, 0)
|
||||
parser.values.data += struct.pack('1b',int8)
|
||||
if opt_str == "--int16":
|
||||
int16 = int(value, 0)
|
||||
parser.values.data += struct.pack('1h',int16)
|
||||
if opt_str == "--int32":
|
||||
int32 = int(value, 0)
|
||||
parser.values.data += struct.pack('1i',int32)
|
||||
if opt_str == "--int64":
|
||||
int64 = int(value, 0)
|
||||
parser.values.data += struct.pack('1q',int64)
|
||||
|
||||
def create_memfind_options():
|
||||
usage = "usage: %prog [options] STARTADDR [ENDADDR]"
|
||||
description='''This command can find data in a specified address range.
|
||||
Options are used to specify the data that is to be looked for and the options
|
||||
can be specified multiple times to look for longer streams of data.
|
||||
'''
|
||||
parser = optparse.OptionParser(description=description, prog='memfind',usage=usage)
|
||||
parser.add_option('-s', '--size', type='int', metavar='BYTESIZE', dest='size', help='Specify the byte size to search.', default=0)
|
||||
parser.add_option('--int8', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 8 bit signed integer value to search for in memory.', default='')
|
||||
parser.add_option('--int16', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 16 bit signed integer value to search for in memory.', default='')
|
||||
parser.add_option('--int32', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 32 bit signed integer value to search for in memory.', default='')
|
||||
parser.add_option('--int64', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 64 bit signed integer value to search for in memory.', default='')
|
||||
parser.add_option('--uint8', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 8 bit unsigned integer value to search for in memory.', default='')
|
||||
parser.add_option('--uint16', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 16 bit unsigned integer value to search for in memory.', default='')
|
||||
parser.add_option('--uint32', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 32 bit unsigned integer value to search for in memory.', default='')
|
||||
parser.add_option('--uint64', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 64 bit unsigned integer value to search for in memory.', default='')
|
||||
return parser
|
||||
|
||||
def memfind_command (debugger, command, result, dict):
|
||||
# Use the Shell Lexer to properly parse up command options just like a
|
||||
# shell would
|
||||
command_args = shlex.split(command)
|
||||
parser = create_memfind_options()
|
||||
(options, args) = parser.parse_args(command_args)
|
||||
# try:
|
||||
# (options, args) = parser.parse_args(command_args)
|
||||
# except:
|
||||
# # if you don't handle exceptions, passing an incorrect argument to the OptionParser will cause LLDB to exit
|
||||
# # (courtesy of OptParse dealing with argument errors by throwing SystemExit)
|
||||
# result.SetStatus (lldb.eReturnStatusFailed)
|
||||
# print >>result, "error: option parsing failed" # returning a string is the same as returning an error whose description is the string
|
||||
# return
|
||||
memfind (debugger.GetSelectedTarget(), options, args, result)
|
||||
|
||||
def print_error(str, show_usage, result):
|
||||
print >>result, str
|
||||
if show_usage:
|
||||
print >>result, create_memfind_options().format_help()
|
||||
|
||||
def memfind (target, options, args, result):
|
||||
num_args = len(args)
|
||||
start_addr = 0
|
||||
if num_args == 1:
|
||||
if options.size > 0:
|
||||
print_error ("error: --size must be specified if there is no ENDADDR argument", True, result)
|
||||
return
|
||||
start_addr = int(args[0], 0)
|
||||
elif num_args == 2:
|
||||
if options.size != 0:
|
||||
print_error ("error: --size can't be specified with an ENDADDR argument", True, result)
|
||||
return
|
||||
start_addr = int(args[0], 0)
|
||||
end_addr = int(args[1], 0)
|
||||
if start_addr >= end_addr:
|
||||
print_error ("error: inavlid memory range [%#x - %#x)" % (start_addr, end_addr), True, result)
|
||||
return
|
||||
options.size = end_addr - start_addr
|
||||
else:
|
||||
print_error ("error: memfind takes 1 or 2 arguments", True, result)
|
||||
return
|
||||
|
||||
if not options.data:
|
||||
print >>result, 'error: no data specified to search for'
|
||||
return
|
||||
|
||||
if not target:
|
||||
print >>result, 'error: invalid target'
|
||||
return
|
||||
process = target.process
|
||||
if not process:
|
||||
print >>result, 'error: invalid process'
|
||||
return
|
||||
|
||||
error = lldb.SBError()
|
||||
bytes = process.ReadMemory (start_addr, options.size, error)
|
||||
if error.Success():
|
||||
num_matches = 0
|
||||
print >>result, "Searching memory range [%#x - %#x) for" % (start_addr, end_addr),
|
||||
for byte in options.data:
|
||||
print >>result, '%2.2x' % ord(byte),
|
||||
print >>result
|
||||
|
||||
match_index = string.find(bytes, options.data)
|
||||
while match_index != -1:
|
||||
num_matches = num_matches + 1
|
||||
print >>result, '%#x: %#x + %u' % (start_addr + match_index, start_addr, match_index)
|
||||
match_index = string.find(bytes, options.data, match_index + 1)
|
||||
|
||||
if num_matches == 0:
|
||||
print >>result, "error: no matches found"
|
||||
else:
|
||||
print >>result, 'error: %s' % (error.GetCString())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print 'error: this script is designed to be used within the embedded script interpreter in LLDB'
|
||||
elif getattr(lldb, 'debugger', None):
|
||||
memfind_command.__doc__ = create_memfind_options().format_help()
|
||||
lldb.debugger.HandleCommand('command script add -f memory.memfind_command memfind')
|
||||
print '"memfind" command installed, use the "--help" option for detailed help'
|
||||
104
external/bsd/llvm/dist/lldb/examples/python/operating_system.py
vendored
Normal file
104
external/bsd/llvm/dist/lldb/examples/python/operating_system.py
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import lldb
|
||||
import struct
|
||||
|
||||
class OperatingSystemPlugIn(object):
|
||||
"""Class that provides data for an instance of a LLDB 'OperatingSystemPython' plug-in class"""
|
||||
|
||||
def __init__(self, process):
|
||||
'''Initialization needs a valid.SBProcess object.
|
||||
|
||||
This plug-in will get created after a live process is valid and has stopped for the
|
||||
first time.'''
|
||||
self.process = None
|
||||
self.registers = None
|
||||
self.threads = None
|
||||
if type(process) is lldb.SBProcess and process.IsValid():
|
||||
self.process = process
|
||||
self.threads = None # Will be an dictionary containing info for each thread
|
||||
|
||||
def get_target(self):
|
||||
# NOTE: Don't use "lldb.target" when trying to get your target as the "lldb.target"
|
||||
# tracks the current target in the LLDB command interpreter which isn't the
|
||||
# correct thing to use for this plug-in.
|
||||
return self.process.target
|
||||
|
||||
def create_thread(self, tid, context):
|
||||
if tid == 0x444444444:
|
||||
thread_info = { 'tid' : tid, 'name' : 'four' , 'queue' : 'queue4', 'state' : 'stopped', 'stop_reason' : 'none' }
|
||||
self.threads.append(thread_info)
|
||||
return thread_info
|
||||
return None
|
||||
|
||||
def get_thread_info(self):
|
||||
if not self.threads:
|
||||
# The sample dictionary below shows the values that can be returned for a thread
|
||||
# tid => thread ID (mandatory)
|
||||
# name => thread name (optional key/value pair)
|
||||
# queue => thread dispatch queue name (optional key/value pair)
|
||||
# state => thred state (mandatory, set to 'stopped' for now)
|
||||
# stop_reason => thread stop reason. (mandatory, usually set to 'none')
|
||||
# Possible values include:
|
||||
# 'breakpoint' if the thread is stopped at a breakpoint
|
||||
# 'none' thread is just stopped because the process is stopped
|
||||
# 'trace' the thread just single stepped
|
||||
# The usual value for this while threads are in memory is 'none'
|
||||
# register_data_addr => the address of the register data in memory (optional key/value pair)
|
||||
# Specifying this key/value pair for a thread will avoid a call to get_register_data()
|
||||
# and can be used when your registers are in a thread context structure that is contiguous
|
||||
# in memory. Don't specify this if your register layout in memory doesn't match the layout
|
||||
# described by the dictionary returned from a call to the get_register_info() method.
|
||||
self.threads = [
|
||||
{ 'tid' : 0x111111111, 'name' : 'one' , 'queue' : 'queue1', 'state' : 'stopped', 'stop_reason' : 'breakpoint'},
|
||||
{ 'tid' : 0x222222222, 'name' : 'two' , 'queue' : 'queue2', 'state' : 'stopped', 'stop_reason' : 'none' },
|
||||
{ 'tid' : 0x333333333, 'name' : 'three', 'queue' : 'queue3', 'state' : 'stopped', 'stop_reason' : 'trace' , 'register_data_addr' : 0x100000000 }
|
||||
]
|
||||
return self.threads
|
||||
|
||||
def get_register_info(self):
|
||||
if self.registers == None:
|
||||
self.registers = dict()
|
||||
triple = self.process.target.triple
|
||||
if triple:
|
||||
arch = triple.split('-')[0]
|
||||
if arch == 'x86_64':
|
||||
self.registers['sets'] = ['GPR', 'FPU', 'EXC']
|
||||
self.registers['registers'] = [
|
||||
{ 'name':'rax' , 'bitsize' : 64, 'offset' : 0, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 0, 'dwarf' : 0},
|
||||
{ 'name':'rbx' , 'bitsize' : 64, 'offset' : 8, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 3, 'dwarf' : 3},
|
||||
{ 'name':'rcx' , 'bitsize' : 64, 'offset' : 16, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 2, 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', },
|
||||
{ 'name':'rdx' , 'bitsize' : 64, 'offset' : 24, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 1, 'dwarf' : 1, 'generic':'arg3', 'alt-name':'arg3', },
|
||||
{ 'name':'rdi' , 'bitsize' : 64, 'offset' : 32, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 5, 'dwarf' : 5, 'generic':'arg1', 'alt-name':'arg1', },
|
||||
{ 'name':'rsi' , 'bitsize' : 64, 'offset' : 40, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 4, 'dwarf' : 4, 'generic':'arg2', 'alt-name':'arg2', },
|
||||
{ 'name':'rbp' , 'bitsize' : 64, 'offset' : 48, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 6, 'dwarf' : 6, 'generic':'fp' , 'alt-name':'fp', },
|
||||
{ 'name':'rsp' , 'bitsize' : 64, 'offset' : 56, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 7, 'dwarf' : 7, 'generic':'sp' , 'alt-name':'sp', },
|
||||
{ 'name':'r8' , 'bitsize' : 64, 'offset' : 64, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 8, 'dwarf' : 8, 'generic':'arg5', 'alt-name':'arg5', },
|
||||
{ 'name':'r9' , 'bitsize' : 64, 'offset' : 72, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 9, 'dwarf' : 9, 'generic':'arg6', 'alt-name':'arg6', },
|
||||
{ 'name':'r10' , 'bitsize' : 64, 'offset' : 80, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 10, 'dwarf' : 10},
|
||||
{ 'name':'r11' , 'bitsize' : 64, 'offset' : 88, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 11, 'dwarf' : 11},
|
||||
{ 'name':'r12' , 'bitsize' : 64, 'offset' : 96, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 12, 'dwarf' : 12},
|
||||
{ 'name':'r13' , 'bitsize' : 64, 'offset' : 104, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 13, 'dwarf' : 13},
|
||||
{ 'name':'r14' , 'bitsize' : 64, 'offset' : 112, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 14, 'dwarf' : 14},
|
||||
{ 'name':'r15' , 'bitsize' : 64, 'offset' : 120, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 15, 'dwarf' : 15},
|
||||
{ 'name':'rip' , 'bitsize' : 64, 'offset' : 128, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 16, 'dwarf' : 16, 'generic':'pc', 'alt-name':'pc' },
|
||||
{ 'name':'rflags' , 'bitsize' : 64, 'offset' : 136, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'generic':'flags', 'alt-name':'flags' },
|
||||
{ 'name':'cs' , 'bitsize' : 64, 'offset' : 144, 'encoding':'uint' , 'format':'hex' , 'set': 0 },
|
||||
{ 'name':'fs' , 'bitsize' : 64, 'offset' : 152, 'encoding':'uint' , 'format':'hex' , 'set': 0 },
|
||||
{ 'name':'gs' , 'bitsize' : 64, 'offset' : 160, 'encoding':'uint' , 'format':'hex' , 'set': 0 },
|
||||
]
|
||||
return self.registers
|
||||
|
||||
def get_register_data(self, tid):
|
||||
if tid == 0x111111111:
|
||||
return struct.pack('21Q',1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21);
|
||||
elif tid == 0x222222222:
|
||||
return struct.pack('21Q',11,12,13,14,15,16,17,18,19,110,111,112,113,114,115,116,117,118,119,120,121);
|
||||
elif tid == 0x333333333:
|
||||
return struct.pack('21Q',21,22,23,24,25,26,27,28,29,210,211,212,213,214,215,216,217,218,219,220,221);
|
||||
elif tid == 0x444444444:
|
||||
return struct.pack('21Q',31,32,33,34,35,36,37,38,39,310,311,312,313,314,315,316,317,318,319,320,321);
|
||||
else:
|
||||
return struct.pack('21Q',41,42,43,44,45,46,47,48,49,410,411,412,413,414,415,416,417,418,419,420,421);
|
||||
return None
|
||||
|
||||
335
external/bsd/llvm/dist/lldb/examples/python/performance.py
vendored
Executable file
335
external/bsd/llvm/dist/lldb/examples/python/performance.py
vendored
Executable file
@@ -0,0 +1,335 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Be sure to add the python path that points to the LLDB shared library.
|
||||
# On MacOSX csh, tcsh:
|
||||
# setenv PYTHONPATH /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python
|
||||
# On MacOSX sh, bash:
|
||||
# export PYTHONPATH=/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
import commands
|
||||
import optparse
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import resource
|
||||
import sys
|
||||
import time
|
||||
import types
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Code that auto imports LLDB
|
||||
#----------------------------------------------------------------------
|
||||
try:
|
||||
# Just try for LLDB in case PYTHONPATH is already correctly setup
|
||||
import lldb
|
||||
except ImportError:
|
||||
lldb_python_dirs = list()
|
||||
# lldb is not in the PYTHONPATH, try some defaults for the current platform
|
||||
platform_system = platform.system()
|
||||
if platform_system == 'Darwin':
|
||||
# On Darwin, try the currently selected Xcode directory
|
||||
xcode_dir = commands.getoutput("xcode-select --print-path")
|
||||
if xcode_dir:
|
||||
lldb_python_dirs.append(os.path.realpath(xcode_dir + '/../SharedFrameworks/LLDB.framework/Resources/Python'))
|
||||
lldb_python_dirs.append(xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
|
||||
lldb_python_dirs.append('/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
|
||||
success = False
|
||||
for lldb_python_dir in lldb_python_dirs:
|
||||
if os.path.exists(lldb_python_dir):
|
||||
if not (sys.path.__contains__(lldb_python_dir)):
|
||||
sys.path.append(lldb_python_dir)
|
||||
try:
|
||||
import lldb
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
print 'imported lldb from: "%s"' % (lldb_python_dir)
|
||||
success = True
|
||||
break
|
||||
if not success:
|
||||
print "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly"
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
class Timer:
|
||||
def __enter__(self):
|
||||
self.start = time.clock()
|
||||
return self
|
||||
|
||||
def __exit__(self, *args):
|
||||
self.end = time.clock()
|
||||
self.interval = self.end - self.start
|
||||
|
||||
class Action(object):
|
||||
"""Class that encapsulates actions to take when a thread stops for a reason."""
|
||||
def __init__(self, callback = None, callback_owner = None):
|
||||
self.callback = callback
|
||||
self.callback_owner = callback_owner
|
||||
def ThreadStopped (self, thread):
|
||||
assert False, "performance.Action.ThreadStopped(self, thread) must be overridden in a subclass"
|
||||
|
||||
class PlanCompleteAction (Action):
|
||||
def __init__(self, callback = None, callback_owner = None):
|
||||
Action.__init__(self, callback, callback_owner)
|
||||
def ThreadStopped (self, thread):
|
||||
if thread.GetStopReason() == lldb.eStopReasonPlanComplete:
|
||||
if self.callback:
|
||||
if self.callback_owner:
|
||||
self.callback (self.callback_owner, thread)
|
||||
else:
|
||||
self.callback (thread)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class BreakpointAction (Action):
|
||||
def __init__(self, callback = None, callback_owner = None, name = None, module = None, file = None, line = None, breakpoint = None):
|
||||
Action.__init__(self, callback, callback_owner)
|
||||
self.modules = lldb.SBFileSpecList()
|
||||
self.files = lldb.SBFileSpecList()
|
||||
self.breakpoints = list()
|
||||
# "module" can be a list or a string
|
||||
if breakpoint:
|
||||
self.breakpoints.append(breakpoint)
|
||||
else:
|
||||
if module:
|
||||
if isinstance(module, types.ListType):
|
||||
for module_path in module:
|
||||
self.modules.Append(lldb.SBFileSpec(module_path, False))
|
||||
elif isinstance(module, types.StringTypes):
|
||||
self.modules.Append(lldb.SBFileSpec(module, False))
|
||||
if name:
|
||||
# "file" can be a list or a string
|
||||
if file:
|
||||
if isinstance(file, types.ListType):
|
||||
self.files = lldb.SBFileSpecList()
|
||||
for f in file:
|
||||
self.files.Append(lldb.SBFileSpec(f, False))
|
||||
elif isinstance(file, types.StringTypes):
|
||||
self.files.Append(lldb.SBFileSpec(file, False))
|
||||
self.breakpoints.append (self.target.BreakpointCreateByName(name, self.modules, self.files))
|
||||
elif file and line:
|
||||
self.breakpoints.append (self.target.BreakpointCreateByLocation(file, line))
|
||||
def ThreadStopped (self, thread):
|
||||
if thread.GetStopReason() == lldb.eStopReasonBreakpoint:
|
||||
for bp in self.breakpoints:
|
||||
if bp.GetID() == thread.GetStopReasonDataAtIndex(0):
|
||||
if self.callback:
|
||||
if self.callback_owner:
|
||||
self.callback (self.callback_owner, thread)
|
||||
else:
|
||||
self.callback (thread)
|
||||
return True
|
||||
return False
|
||||
class TestCase:
|
||||
"""Class that aids in running performance tests."""
|
||||
def __init__(self):
|
||||
self.verbose = False
|
||||
self.debugger = lldb.SBDebugger.Create()
|
||||
self.target = None
|
||||
self.process = None
|
||||
self.thread = None
|
||||
self.launch_info = None
|
||||
self.done = False
|
||||
self.listener = self.debugger.GetListener()
|
||||
self.user_actions = list()
|
||||
self.builtin_actions = list()
|
||||
self.bp_id_to_dict = dict()
|
||||
|
||||
def Setup(self, args):
|
||||
self.launch_info = lldb.SBLaunchInfo(args)
|
||||
|
||||
def Run (self, args):
|
||||
assert False, "performance.TestCase.Run(self, args) must be subclassed"
|
||||
|
||||
def Launch(self):
|
||||
if self.target:
|
||||
error = lldb.SBError()
|
||||
self.process = self.target.Launch (self.launch_info, error)
|
||||
if not error.Success():
|
||||
print "error: %s" % error.GetCString()
|
||||
if self.process:
|
||||
self.process.GetBroadcaster().AddListener(self.listener, lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitInterrupt)
|
||||
return True
|
||||
return False
|
||||
|
||||
def WaitForNextProcessEvent (self):
|
||||
event = None
|
||||
if self.process:
|
||||
while event is None:
|
||||
process_event = lldb.SBEvent()
|
||||
if self.listener.WaitForEvent (lldb.UINT32_MAX, process_event):
|
||||
state = lldb.SBProcess.GetStateFromEvent (process_event)
|
||||
if self.verbose:
|
||||
print "event = %s" % (lldb.SBDebugger.StateAsCString(state))
|
||||
if lldb.SBProcess.GetRestartedFromEvent(process_event):
|
||||
continue
|
||||
if state == lldb.eStateInvalid or state == lldb.eStateDetached or state == lldb.eStateCrashed or state == lldb.eStateUnloaded or state == lldb.eStateExited:
|
||||
event = process_event
|
||||
self.done = True
|
||||
elif state == lldb.eStateConnected or state == lldb.eStateAttaching or state == lldb.eStateLaunching or state == lldb.eStateRunning or state == lldb.eStateStepping or state == lldb.eStateSuspended:
|
||||
continue
|
||||
elif state == lldb.eStateStopped:
|
||||
event = process_event
|
||||
call_test_step = True
|
||||
fatal = False
|
||||
selected_thread = False
|
||||
for thread in self.process:
|
||||
frame = thread.GetFrameAtIndex(0)
|
||||
select_thread = False
|
||||
|
||||
stop_reason = thread.GetStopReason()
|
||||
if self.verbose:
|
||||
print "tid = %#x pc = %#x " % (thread.GetThreadID(),frame.GetPC()),
|
||||
if stop_reason == lldb.eStopReasonNone:
|
||||
if self.verbose:
|
||||
print "none"
|
||||
elif stop_reason == lldb.eStopReasonTrace:
|
||||
select_thread = True
|
||||
if self.verbose:
|
||||
print "trace"
|
||||
elif stop_reason == lldb.eStopReasonPlanComplete:
|
||||
select_thread = True
|
||||
if self.verbose:
|
||||
print "plan complete"
|
||||
elif stop_reason == lldb.eStopReasonThreadExiting:
|
||||
if self.verbose:
|
||||
print "thread exiting"
|
||||
elif stop_reason == lldb.eStopReasonExec:
|
||||
if self.verbose:
|
||||
print "exec"
|
||||
elif stop_reason == lldb.eStopReasonInvalid:
|
||||
if self.verbose:
|
||||
print "invalid"
|
||||
elif stop_reason == lldb.eStopReasonException:
|
||||
select_thread = True
|
||||
if self.verbose:
|
||||
print "exception"
|
||||
fatal = True
|
||||
elif stop_reason == lldb.eStopReasonBreakpoint:
|
||||
select_thread = True
|
||||
bp_id = thread.GetStopReasonDataAtIndex(0)
|
||||
bp_loc_id = thread.GetStopReasonDataAtIndex(1)
|
||||
if self.verbose:
|
||||
print "breakpoint id = %d.%d" % (bp_id, bp_loc_id)
|
||||
elif stop_reason == lldb.eStopReasonWatchpoint:
|
||||
select_thread = True
|
||||
if self.verbose:
|
||||
print "watchpoint id = %d" % (thread.GetStopReasonDataAtIndex(0))
|
||||
elif stop_reason == lldb.eStopReasonSignal:
|
||||
select_thread = True
|
||||
if self.verbose:
|
||||
print "signal %d" % (thread.GetStopReasonDataAtIndex(0))
|
||||
|
||||
if select_thread and not selected_thread:
|
||||
self.thread = thread
|
||||
selected_thread = self.process.SetSelectedThread(thread)
|
||||
|
||||
for action in self.user_actions:
|
||||
action.ThreadStopped (thread)
|
||||
|
||||
|
||||
if fatal:
|
||||
# if self.verbose:
|
||||
# Xcode.RunCommand(self.debugger,"bt all",true)
|
||||
sys.exit(1)
|
||||
return event
|
||||
|
||||
class Measurement:
|
||||
'''A class that encapsulates a measurement'''
|
||||
def __init__(self):
|
||||
object.__init__(self)
|
||||
def Measure(self):
|
||||
assert False, "performance.Measurement.Measure() must be subclassed"
|
||||
|
||||
class MemoryMeasurement(Measurement):
|
||||
'''A class that can measure memory statistics for a process.'''
|
||||
def __init__(self, pid):
|
||||
Measurement.__init__(self)
|
||||
self.pid = pid
|
||||
self.stats = ["rprvt","rshrd","rsize","vsize","vprvt","kprvt","kshrd","faults","cow","pageins"]
|
||||
self.command = "top -l 1 -pid %u -stats %s" % (self.pid, ",".join(self.stats))
|
||||
self.value = dict()
|
||||
|
||||
def Measure(self):
|
||||
output = commands.getoutput(self.command).split("\n")[-1]
|
||||
values = re.split('[-+\s]+', output)
|
||||
for (idx, stat) in enumerate(values):
|
||||
multiplier = 1
|
||||
if stat:
|
||||
if stat[-1] == 'K':
|
||||
multiplier = 1024
|
||||
stat = stat[:-1]
|
||||
elif stat[-1] == 'M':
|
||||
multiplier = 1024*1024
|
||||
stat = stat[:-1]
|
||||
elif stat[-1] == 'G':
|
||||
multiplier = 1024*1024*1024
|
||||
elif stat[-1] == 'T':
|
||||
multiplier = 1024*1024*1024*1024
|
||||
stat = stat[:-1]
|
||||
self.value[self.stats[idx]] = int (stat) * multiplier
|
||||
|
||||
def __str__(self):
|
||||
'''Dump the MemoryMeasurement current value'''
|
||||
s = ''
|
||||
for key in self.value.keys():
|
||||
if s:
|
||||
s += "\n"
|
||||
s += "%8s = %s" % (key, self.value[key])
|
||||
return s
|
||||
|
||||
|
||||
class TesterTestCase(TestCase):
|
||||
def __init__(self):
|
||||
TestCase.__init__(self)
|
||||
self.verbose = True
|
||||
self.num_steps = 5
|
||||
|
||||
def BreakpointHit (self, thread):
|
||||
bp_id = thread.GetStopReasonDataAtIndex(0)
|
||||
loc_id = thread.GetStopReasonDataAtIndex(1)
|
||||
print "Breakpoint %i.%i hit: %s" % (bp_id, loc_id, thread.process.target.FindBreakpointByID(bp_id))
|
||||
thread.StepOver()
|
||||
|
||||
def PlanComplete (self, thread):
|
||||
if self.num_steps > 0:
|
||||
thread.StepOver()
|
||||
self.num_steps = self.num_steps - 1
|
||||
else:
|
||||
thread.process.Kill()
|
||||
|
||||
def Run (self, args):
|
||||
self.Setup(args)
|
||||
with Timer() as total_time:
|
||||
self.target = self.debugger.CreateTarget(args[0])
|
||||
if self.target:
|
||||
with Timer() as breakpoint_timer:
|
||||
bp = self.target.BreakpointCreateByName("main")
|
||||
print('Breakpoint time = %.03f sec.' % breakpoint_timer.interval)
|
||||
|
||||
self.user_actions.append (BreakpointAction(breakpoint=bp, callback=TesterTestCase.BreakpointHit, callback_owner=self))
|
||||
self.user_actions.append (PlanCompleteAction(callback=TesterTestCase.PlanComplete, callback_owner=self))
|
||||
|
||||
if self.Launch():
|
||||
while not self.done:
|
||||
self.WaitForNextProcessEvent()
|
||||
else:
|
||||
print "error: failed to launch process"
|
||||
else:
|
||||
print "error: failed to create target with '%s'" % (args[0])
|
||||
print('Total time = %.03f sec.' % total_time.interval)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
lldb.SBDebugger.Initialize()
|
||||
test = TesterTestCase()
|
||||
test.Run (sys.argv[1:])
|
||||
mem = MemoryMeasurement(os.getpid())
|
||||
mem.Measure()
|
||||
print str(mem)
|
||||
lldb.SBDebugger.Terminate()
|
||||
# print "sleeeping for 100 seconds"
|
||||
# time.sleep(100)
|
||||
272
external/bsd/llvm/dist/lldb/examples/python/process_events.py
vendored
Executable file
272
external/bsd/llvm/dist/lldb/examples/python/process_events.py
vendored
Executable file
@@ -0,0 +1,272 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Be sure to add the python path that points to the LLDB shared library.
|
||||
# On MacOSX csh, tcsh:
|
||||
# setenv PYTHONPATH /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python
|
||||
# On MacOSX sh, bash:
|
||||
# export PYTHONPATH=/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
import commands
|
||||
import optparse
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Code that auto imports LLDB
|
||||
#----------------------------------------------------------------------
|
||||
try:
|
||||
# Just try for LLDB in case PYTHONPATH is already correctly setup
|
||||
import lldb
|
||||
except ImportError:
|
||||
lldb_python_dirs = list()
|
||||
# lldb is not in the PYTHONPATH, try some defaults for the current platform
|
||||
platform_system = platform.system()
|
||||
if platform_system == 'Darwin':
|
||||
# On Darwin, try the currently selected Xcode directory
|
||||
xcode_dir = commands.getoutput("xcode-select --print-path")
|
||||
if xcode_dir:
|
||||
lldb_python_dirs.append(os.path.realpath(xcode_dir + '/../SharedFrameworks/LLDB.framework/Resources/Python'))
|
||||
lldb_python_dirs.append(xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
|
||||
lldb_python_dirs.append('/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
|
||||
success = False
|
||||
for lldb_python_dir in lldb_python_dirs:
|
||||
if os.path.exists(lldb_python_dir):
|
||||
if not (sys.path.__contains__(lldb_python_dir)):
|
||||
sys.path.append(lldb_python_dir)
|
||||
try:
|
||||
import lldb
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
print 'imported lldb from: "%s"' % (lldb_python_dir)
|
||||
success = True
|
||||
break
|
||||
if not success:
|
||||
print "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly"
|
||||
sys.exit(1)
|
||||
|
||||
def print_threads(process, options):
|
||||
if options.show_threads:
|
||||
for thread in process:
|
||||
print '%s %s' % (thread, thread.GetFrameAtIndex(0))
|
||||
|
||||
def run_commands(command_interpreter, commands):
|
||||
return_obj = lldb.SBCommandReturnObject()
|
||||
for command in commands:
|
||||
command_interpreter.HandleCommand( command, return_obj )
|
||||
if return_obj.Succeeded():
|
||||
print return_obj.GetOutput()
|
||||
else:
|
||||
print return_obj
|
||||
if options.stop_on_error:
|
||||
break
|
||||
|
||||
def main(argv):
|
||||
description='''Debugs a program using the LLDB python API and uses asynchronous broadcast events to watch for process state changes.'''
|
||||
epilog='''Examples:
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Run "/bin/ls" with the arguments "-lAF /tmp/", and set a breakpoint
|
||||
# at "malloc" and backtrace and read all registers each time we stop
|
||||
#----------------------------------------------------------------------
|
||||
% ./process_events.py --breakpoint malloc --stop-command bt --stop-command 'register read' -- /bin/ls -lAF /tmp/
|
||||
|
||||
'''
|
||||
optparse.OptionParser.format_epilog = lambda self, formatter: self.epilog
|
||||
parser = optparse.OptionParser(description=description, prog='process_events',usage='usage: process_events [options] program [arg1 arg2]', epilog=epilog)
|
||||
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help="Enable verbose logging.", default=False)
|
||||
parser.add_option('-b', '--breakpoint', action='append', type='string', metavar='BPEXPR', dest='breakpoints', help='Breakpoint commands to create after the target has been created, the values will be sent to the "_regexp-break" command which supports breakpoints by name, file:line, and address.')
|
||||
parser.add_option('-a', '--arch', type='string', dest='arch', help='The architecture to use when creating the debug target.', default=None)
|
||||
parser.add_option('--platform', type='string', metavar='platform', dest='platform', help='Specify the platform to use when creating the debug target. Valid values include "localhost", "darwin-kernel", "ios-simulator", "remote-freebsd", "remote-macosx", "remote-ios", "remote-linux".', default=None)
|
||||
parser.add_option('-l', '--launch-command', action='append', type='string', metavar='CMD', dest='launch_commands', help='LLDB command interpreter commands to run once after the process has launched. This option can be specified more than once.', default=[])
|
||||
parser.add_option('-s', '--stop-command', action='append', type='string', metavar='CMD', dest='stop_commands', help='LLDB command interpreter commands to run each time the process stops. This option can be specified more than once.', default=[])
|
||||
parser.add_option('-c', '--crash-command', action='append', type='string', metavar='CMD', dest='crash_commands', help='LLDB command interpreter commands to run in case the process crashes. This option can be specified more than once.', default=[])
|
||||
parser.add_option('-x', '--exit-command', action='append', type='string', metavar='CMD', dest='exit_commands', help='LLDB command interpreter commands to run once after the process has exited. This option can be specified more than once.', default=[])
|
||||
parser.add_option('-T', '--no-threads', action='store_false', dest='show_threads', help="Don't show threads when process stops.", default=True)
|
||||
parser.add_option('--ignore-errors', action='store_false', dest='stop_on_error', help="Don't stop executing LLDB commands if the command returns an error. This applies to all of the LLDB command interpreter commands that get run for launch, stop, crash and exit.", default=True)
|
||||
parser.add_option('-n', '--run-count', type='int', dest='run_count', metavar='N', help='How many times to run the process in case the process exits.', default=1)
|
||||
parser.add_option('-t', '--event-timeout', type='int', dest='event_timeout', metavar='SEC', help='Specify the timeout in seconds to wait for process state change events.', default=lldb.UINT32_MAX)
|
||||
parser.add_option('-e', '--environment', action='append', type='string', metavar='ENV', dest='env_vars', help='Environment variables to set in the inferior process when launching a process.')
|
||||
parser.add_option('-d', '--working-dir', type='string', metavar='DIR', dest='working_dir', help='The the current working directory when launching a process.', default=None)
|
||||
parser.add_option('-p', '--attach-pid', type='int', dest='attach_pid', metavar='PID', help='Specify a process to attach to by process ID.', default=-1)
|
||||
parser.add_option('-P', '--attach-name', type='string', dest='attach_name', metavar='PROCESSNAME', help='Specify a process to attach to by name.', default=None)
|
||||
parser.add_option('-w', '--attach-wait', action='store_true', dest='attach_wait', help='Wait for the next process to launch when attaching to a process by name.', default=False)
|
||||
try:
|
||||
(options, args) = parser.parse_args(argv)
|
||||
except:
|
||||
return
|
||||
|
||||
attach_info = None
|
||||
launch_info = None
|
||||
exe = None
|
||||
if args:
|
||||
exe = args.pop(0)
|
||||
launch_info = lldb.SBLaunchInfo (args)
|
||||
if options.env_vars:
|
||||
launch_info.SetEnvironmentEntries(options.env_vars, True)
|
||||
if options.working_dir:
|
||||
launch_info.SetWorkingDirectory(options.working_dir)
|
||||
elif options.attach_pid != -1:
|
||||
if options.run_count == 1:
|
||||
attach_info = lldb.SBAttachInfo (options.attach_pid)
|
||||
else:
|
||||
print "error: --run-count can't be used with the --attach-pid option"
|
||||
sys.exit(1)
|
||||
elif not options.attach_name is None:
|
||||
if options.run_count == 1:
|
||||
attach_info = lldb.SBAttachInfo (options.attach_name, options.attach_wait)
|
||||
else:
|
||||
print "error: --run-count can't be used with the --attach-name option"
|
||||
sys.exit(1)
|
||||
else:
|
||||
print 'error: a program path for a program to debug and its arguments are required'
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
|
||||
# Create a new debugger instance
|
||||
debugger = lldb.SBDebugger.Create()
|
||||
debugger.SetAsync (True)
|
||||
command_interpreter = debugger.GetCommandInterpreter()
|
||||
# Create a target from a file and arch
|
||||
|
||||
if exe:
|
||||
print "Creating a target for '%s'" % exe
|
||||
error = lldb.SBError()
|
||||
target = debugger.CreateTarget (exe, options.arch, options.platform, True, error)
|
||||
|
||||
if target:
|
||||
|
||||
# Set any breakpoints that were specified in the args if we are launching. We use the
|
||||
# command line command to take advantage of the shorthand breakpoint creation
|
||||
if launch_info and options.breakpoints:
|
||||
for bp in options.breakpoints:
|
||||
debugger.HandleCommand( "_regexp-break %s" % (bp))
|
||||
run_commands(command_interpreter, ['breakpoint list'])
|
||||
|
||||
for run_idx in range(options.run_count):
|
||||
# Launch the process. Since we specified synchronous mode, we won't return
|
||||
# from this function until we hit the breakpoint at main
|
||||
error = lldb.SBError()
|
||||
|
||||
if launch_info:
|
||||
if options.run_count == 1:
|
||||
print 'Launching "%s"...' % (exe)
|
||||
else:
|
||||
print 'Launching "%s"... (launch %u of %u)' % (exe, run_idx + 1, options.run_count)
|
||||
|
||||
process = target.Launch (launch_info, error)
|
||||
else:
|
||||
if options.attach_pid != -1:
|
||||
print 'Attaching to process %i...' % (options.attach_pid)
|
||||
else:
|
||||
if options.attach_wait:
|
||||
print 'Waiting for next to process named "%s" to launch...' % (options.attach_name)
|
||||
else:
|
||||
print 'Attaching to existing process named "%s"...' % (options.attach_name)
|
||||
process = target.Attach (attach_info, error)
|
||||
|
||||
# Make sure the launch went ok
|
||||
if process and process.GetProcessID() != lldb.LLDB_INVALID_PROCESS_ID:
|
||||
pid = process.GetProcessID()
|
||||
listener = debugger.GetListener()
|
||||
# sign up for process state change events
|
||||
stop_idx = 0
|
||||
done = False
|
||||
while not done:
|
||||
event = lldb.SBEvent()
|
||||
if listener.WaitForEvent (options.event_timeout, event):
|
||||
if lldb.SBProcess.EventIsProcessEvent(event):
|
||||
state = lldb.SBProcess.GetStateFromEvent (event)
|
||||
if state == lldb.eStateInvalid:
|
||||
# Not a state event
|
||||
print 'process event = %s' % (event)
|
||||
else:
|
||||
print "process state changed event: %s" % (lldb.SBDebugger.StateAsCString(state))
|
||||
if state == lldb.eStateStopped:
|
||||
if stop_idx == 0:
|
||||
if launch_info:
|
||||
print "process %u launched" % (pid)
|
||||
run_commands(command_interpreter, ['breakpoint list'])
|
||||
else:
|
||||
print "attached to process %u" % (pid)
|
||||
for m in target.modules:
|
||||
print m
|
||||
if options.breakpoints:
|
||||
for bp in options.breakpoints:
|
||||
debugger.HandleCommand( "_regexp-break %s" % (bp))
|
||||
run_commands(command_interpreter, ['breakpoint list'])
|
||||
run_commands (command_interpreter, options.launch_commands)
|
||||
else:
|
||||
if options.verbose:
|
||||
print "process %u stopped" % (pid)
|
||||
run_commands (command_interpreter, options.stop_commands)
|
||||
stop_idx += 1
|
||||
print_threads (process, options)
|
||||
print "continuing process %u" % (pid)
|
||||
process.Continue()
|
||||
elif state == lldb.eStateExited:
|
||||
exit_desc = process.GetExitDescription()
|
||||
if exit_desc:
|
||||
print "process %u exited with status %u: %s" % (pid, process.GetExitStatus (), exit_desc)
|
||||
else:
|
||||
print "process %u exited with status %u" % (pid, process.GetExitStatus ())
|
||||
run_commands (command_interpreter, options.exit_commands)
|
||||
done = True
|
||||
elif state == lldb.eStateCrashed:
|
||||
print "process %u crashed" % (pid)
|
||||
print_threads (process, options)
|
||||
run_commands (command_interpreter, options.crash_commands)
|
||||
done = True
|
||||
elif state == lldb.eStateDetached:
|
||||
print "process %u detached" % (pid)
|
||||
done = True
|
||||
elif state == lldb.eStateRunning:
|
||||
# process is running, don't say anything, we will always get one of these after resuming
|
||||
if options.verbose:
|
||||
print "process %u resumed" % (pid)
|
||||
elif state == lldb.eStateUnloaded:
|
||||
print "process %u unloaded, this shouldn't happen" % (pid)
|
||||
done = True
|
||||
elif state == lldb.eStateConnected:
|
||||
print "process connected"
|
||||
elif state == lldb.eStateAttaching:
|
||||
print "process attaching"
|
||||
elif state == lldb.eStateLaunching:
|
||||
print "process launching"
|
||||
else:
|
||||
print 'event = %s' % (event)
|
||||
else:
|
||||
# timeout waiting for an event
|
||||
print "no process event for %u seconds, killing the process..." % (options.event_timeout)
|
||||
done = True
|
||||
# Now that we are done dump the stdout and stderr
|
||||
process_stdout = process.GetSTDOUT(1024)
|
||||
if process_stdout:
|
||||
print "Process STDOUT:\n%s" % (process_stdout)
|
||||
while process_stdout:
|
||||
process_stdout = process.GetSTDOUT(1024)
|
||||
print process_stdout
|
||||
process_stderr = process.GetSTDERR(1024)
|
||||
if process_stderr:
|
||||
print "Process STDERR:\n%s" % (process_stderr)
|
||||
while process_stderr:
|
||||
process_stderr = process.GetSTDERR(1024)
|
||||
print process_stderr
|
||||
process.Kill() # kill the process
|
||||
else:
|
||||
if error:
|
||||
print error
|
||||
else:
|
||||
if launch_info:
|
||||
print 'error: launch failed'
|
||||
else:
|
||||
print 'error: attach failed'
|
||||
|
||||
lldb.SBDebugger.Terminate()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv[1:])
|
||||
328
external/bsd/llvm/dist/lldb/examples/python/pytracer.py
vendored
Normal file
328
external/bsd/llvm/dist/lldb/examples/python/pytracer.py
vendored
Normal file
@@ -0,0 +1,328 @@
|
||||
import sys
|
||||
import inspect
|
||||
from collections import OrderedDict
|
||||
|
||||
class TracebackFancy:
|
||||
def __init__(self,traceback):
|
||||
self.t = traceback
|
||||
|
||||
def getFrame(self):
|
||||
return FrameFancy(self.t.tb_frame)
|
||||
|
||||
def getLineNumber(self):
|
||||
return self.t.tb_lineno if self.t != None else None
|
||||
|
||||
def getNext(self):
|
||||
return TracebackFancy(self.t.tb_next)
|
||||
|
||||
def __str__(self):
|
||||
if self.t == None:
|
||||
return ""
|
||||
str_self = "%s @ %s" % (self.getFrame().getName(), self.getLineNumber())
|
||||
return str_self + "\n" + self.getNext().__str__()
|
||||
|
||||
class ExceptionFancy:
|
||||
def __init__(self,frame):
|
||||
self.etraceback = frame.f_exc_traceback
|
||||
self.etype = frame.exc_type
|
||||
self.evalue = frame.f_exc_value
|
||||
|
||||
def __init__(self,tb,ty,va):
|
||||
self.etraceback = tb
|
||||
self.etype = ty
|
||||
self.evalue = va
|
||||
|
||||
def getTraceback(self):
|
||||
return TracebackFancy(self.etraceback)
|
||||
|
||||
def __nonzero__(self):
|
||||
return self.etraceback != None or self.etype != None or self.evalue != None
|
||||
|
||||
def getType(self):
|
||||
return str(self.etype)
|
||||
|
||||
def getValue(self):
|
||||
return self.evalue
|
||||
|
||||
class CodeFancy:
|
||||
def __init__(self,code):
|
||||
self.c = code
|
||||
|
||||
def getArgCount(self):
|
||||
return self.c.co_argcount if self.c != None else 0
|
||||
|
||||
def getFilename(self):
|
||||
return self.c.co_filename if self.c != None else ""
|
||||
|
||||
def getVariables(self):
|
||||
return self.c.co_varnames if self.c != None else []
|
||||
|
||||
def getName(self):
|
||||
return self.c.co_name if self.c != None else ""
|
||||
|
||||
def getFileName(self):
|
||||
return self.c.co_filename if self.c != None else ""
|
||||
|
||||
class ArgsFancy:
|
||||
def __init__(self,frame,arginfo):
|
||||
self.f = frame
|
||||
self.a = arginfo
|
||||
|
||||
def __str__(self):
|
||||
args, varargs, kwargs = self.getArgs(), self.getVarArgs(), self.getKWArgs()
|
||||
ret = ""
|
||||
count = 0
|
||||
size = len(args)
|
||||
for arg in args:
|
||||
ret = ret + ("%s = %s" % (arg, args[arg]))
|
||||
count = count + 1
|
||||
if count < size:
|
||||
ret = ret + ", "
|
||||
if varargs:
|
||||
if size > 0:
|
||||
ret = ret + " "
|
||||
ret = ret + "varargs are " + str(varargs)
|
||||
if kwargs:
|
||||
if size > 0:
|
||||
ret = ret + " "
|
||||
ret = ret + "kwargs are " + str(kwargs)
|
||||
return ret
|
||||
|
||||
def getNumArgs(wantVarargs = False, wantKWArgs=False):
|
||||
args, varargs, keywords, values = self.a
|
||||
size = len(args)
|
||||
if varargs and wantVarargs:
|
||||
size = size+len(self.getVarArgs())
|
||||
if keywords and wantKWArgs:
|
||||
size = size+len(self.getKWArgs())
|
||||
return size
|
||||
|
||||
def getArgs(self):
|
||||
args, _, _, values = self.a
|
||||
argWValues = OrderedDict()
|
||||
for arg in args:
|
||||
argWValues[arg] = values[arg]
|
||||
return argWValues
|
||||
|
||||
def getVarArgs(self):
|
||||
_, vargs, _, _ = self.a
|
||||
if vargs:
|
||||
return self.f.f_locals[vargs]
|
||||
return ()
|
||||
|
||||
def getKWArgs(self):
|
||||
_, _, kwargs, _ = self.a
|
||||
if kwargs:
|
||||
return self.f.f_locals[kwargs]
|
||||
return {}
|
||||
|
||||
class FrameFancy:
|
||||
def __init__(self,frame):
|
||||
self.f = frame
|
||||
|
||||
def getCaller(self):
|
||||
return FrameFancy(self.f.f_back)
|
||||
|
||||
def getLineNumber(self):
|
||||
return self.f.f_lineno if self.f != None else 0
|
||||
|
||||
def getCodeInformation(self):
|
||||
return CodeFancy(self.f.f_code) if self.f != None else None
|
||||
|
||||
def getExceptionInfo(self):
|
||||
return ExceptionFancy(self.f) if self.f != None else None
|
||||
|
||||
def getName(self):
|
||||
return self.getCodeInformation().getName() if self.f != None else ""
|
||||
|
||||
def getFileName(self):
|
||||
return self.getCodeInformation().getFileName() if self.f != None else ""
|
||||
|
||||
def getLocals(self):
|
||||
return self.f.f_locals if self.f != None else {}
|
||||
|
||||
def getArgumentInfo(self):
|
||||
return ArgsFancy(self.f,inspect.getargvalues(self.f)) if self.f != None else None
|
||||
|
||||
class TracerClass:
|
||||
def callEvent(self,frame):
|
||||
pass
|
||||
|
||||
def lineEvent(self,frame):
|
||||
pass
|
||||
|
||||
def returnEvent(self,frame,retval):
|
||||
pass
|
||||
|
||||
def exceptionEvent(self,frame,exception,value,traceback):
|
||||
pass
|
||||
|
||||
def cCallEvent(self,frame,cfunct):
|
||||
pass
|
||||
|
||||
def cReturnEvent(self,frame,cfunct):
|
||||
pass
|
||||
|
||||
def cExceptionEvent(self,frame,cfunct):
|
||||
pass
|
||||
|
||||
tracer_impl = TracerClass()
|
||||
|
||||
|
||||
def the_tracer_entrypoint(frame,event,args):
|
||||
if tracer_impl == None:
|
||||
return None
|
||||
if event == "call":
|
||||
call_retval = tracer_impl.callEvent(FrameFancy(frame))
|
||||
if call_retval == False:
|
||||
return None
|
||||
return the_tracer_entrypoint
|
||||
elif event == "line":
|
||||
line_retval = tracer_impl.lineEvent(FrameFancy(frame))
|
||||
if line_retval == False:
|
||||
return None
|
||||
return the_tracer_entrypoint
|
||||
elif event == "return":
|
||||
tracer_impl.returnEvent(FrameFancy(frame),args)
|
||||
elif event == "exception":
|
||||
exty,exva,extb = args
|
||||
exception_retval = tracer_impl.exceptionEvent(FrameFancy(frame),ExceptionFancy(extb,exty,exva))
|
||||
if exception_retval == False:
|
||||
return None
|
||||
return the_tracer_entrypoint
|
||||
elif event == "c_call":
|
||||
tracer_impl.cCallEvent(FrameFancy(frame),args)
|
||||
elif event == "c_return":
|
||||
tracer_impl.cReturnEvent(FrameFancy(frame),args)
|
||||
elif event == "c_exception":
|
||||
tracer_impl.cExceptionEvent(FrameFancy(frame),args)
|
||||
return None
|
||||
|
||||
def enable(t=None):
|
||||
global tracer_impl
|
||||
if t:
|
||||
tracer_impl = t
|
||||
sys.settrace(the_tracer_entrypoint)
|
||||
|
||||
def disable():
|
||||
sys.settrace(None)
|
||||
|
||||
class LoggingTracer:
|
||||
def callEvent(self,frame):
|
||||
print "call " + frame.getName() + " from " + frame.getCaller().getName() + " @ " + str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo())
|
||||
|
||||
def lineEvent(self,frame):
|
||||
print "running " + frame.getName() + " @ " + str(frame.getLineNumber()) + " locals are " + str(frame.getLocals()) + " in " + frame.getFileName()
|
||||
|
||||
def returnEvent(self,frame,retval):
|
||||
print "return from " + frame.getName() + " value is " + str(retval) + " locals are " + str(frame.getLocals())
|
||||
|
||||
def exceptionEvent(self,frame,exception):
|
||||
print "exception %s %s raised from %s @ %s" % (exception.getType(), str(exception.getValue()), frame.getName(), frame.getLineNumber())
|
||||
print "tb: " + str(exception.getTraceback())
|
||||
|
||||
# the same functionality as LoggingTracer, but with a little more lldb-specific smarts
|
||||
class LLDBAwareTracer:
|
||||
def callEvent(self,frame):
|
||||
if frame.getName() == "<module>":
|
||||
return
|
||||
if frame.getName() == "run_one_line":
|
||||
print "call run_one_line(%s)" % (frame.getArgumentInfo().getArgs()["input_string"])
|
||||
return
|
||||
if "Python.framework" in frame.getFileName():
|
||||
print "call into Python at " + frame.getName()
|
||||
return
|
||||
if frame.getName() == "__init__" and frame.getCaller().getName() == "run_one_line" and frame.getCaller().getLineNumber() == 101:
|
||||
return False
|
||||
strout = "call " + frame.getName()
|
||||
if (frame.getCaller().getFileName() == ""):
|
||||
strout += " from LLDB - args are "
|
||||
args = frame.getArgumentInfo().getArgs()
|
||||
for arg in args:
|
||||
if arg == "dict" or arg == "internal_dict":
|
||||
continue
|
||||
strout = strout + ("%s = %s " % (arg,args[arg]))
|
||||
else:
|
||||
strout += " from " + frame.getCaller().getName() + " @ " + str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo())
|
||||
print strout
|
||||
|
||||
def lineEvent(self,frame):
|
||||
if frame.getName() == "<module>":
|
||||
return
|
||||
if frame.getName() == "run_one_line":
|
||||
print "running run_one_line(%s) @ %s" % (frame.getArgumentInfo().getArgs()["input_string"],frame.getLineNumber())
|
||||
return
|
||||
if "Python.framework" in frame.getFileName():
|
||||
print "running into Python at " + frame.getName() + " @ " + str(frame.getLineNumber())
|
||||
return
|
||||
strout = "running " + frame.getName() + " @ " + str(frame.getLineNumber()) + " locals are "
|
||||
if (frame.getCaller().getFileName() == ""):
|
||||
locals = frame.getLocals()
|
||||
for local in locals:
|
||||
if local == "dict" or local == "internal_dict":
|
||||
continue
|
||||
strout = strout + ("%s = %s " % (local,locals[local]))
|
||||
else:
|
||||
strout = strout + str(frame.getLocals())
|
||||
strout = strout + " in " + frame.getFileName()
|
||||
print strout
|
||||
|
||||
def returnEvent(self,frame,retval):
|
||||
if frame.getName() == "<module>":
|
||||
return
|
||||
if frame.getName() == "run_one_line":
|
||||
print "return from run_one_line(%s) return value is %s" % (frame.getArgumentInfo().getArgs()["input_string"],retval)
|
||||
return
|
||||
if "Python.framework" in frame.getFileName():
|
||||
print "return from Python at " + frame.getName() + " return value is " + str(retval)
|
||||
return
|
||||
strout = "return from " + frame.getName() + " return value is " + str(retval) + " locals are "
|
||||
if (frame.getCaller().getFileName() == ""):
|
||||
locals = frame.getLocals()
|
||||
for local in locals:
|
||||
if local == "dict" or local == "internal_dict":
|
||||
continue
|
||||
strout = strout + ("%s = %s " % (local,locals[local]))
|
||||
else:
|
||||
strout = strout + str(frame.getLocals())
|
||||
strout = strout + " in " + frame.getFileName()
|
||||
print strout
|
||||
|
||||
def exceptionEvent(self,frame,exception):
|
||||
if frame.getName() == "<module>":
|
||||
return
|
||||
print "exception %s %s raised from %s @ %s" % (exception.getType(), str(exception.getValue()), frame.getName(), frame.getLineNumber())
|
||||
print "tb: " + str(exception.getTraceback())
|
||||
|
||||
def f(x,y=None):
|
||||
if x > 0:
|
||||
return 2 + f(x-2)
|
||||
return 35
|
||||
|
||||
def g(x):
|
||||
return 1.134 / x
|
||||
|
||||
def print_keyword_args(**kwargs):
|
||||
# kwargs is a dict of the keyword args passed to the function
|
||||
for key, value in kwargs.iteritems():
|
||||
print "%s = %s" % (key, value)
|
||||
|
||||
def total(initial=5, *numbers, **keywords):
|
||||
count = initial
|
||||
for number in numbers:
|
||||
count += number
|
||||
for key in keywords:
|
||||
count += keywords[key]
|
||||
return count
|
||||
|
||||
if __name__ == "__main__":
|
||||
enable(LoggingTracer())
|
||||
f(5)
|
||||
f(5,1)
|
||||
print_keyword_args(first_name="John", last_name="Doe")
|
||||
total(10, 1, 2, 3, vegetables=50, fruits=100)
|
||||
try:
|
||||
g(0)
|
||||
except:
|
||||
pass
|
||||
disable()
|
||||
255
external/bsd/llvm/dist/lldb/examples/python/sbvalue.py
vendored
Executable file
255
external/bsd/llvm/dist/lldb/examples/python/sbvalue.py
vendored
Executable file
@@ -0,0 +1,255 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import lldb
|
||||
|
||||
class value(object):
|
||||
'''A class that wraps an lldb.SBValue object and returns an object that
|
||||
can be used as an object with attribytes:\n
|
||||
argv = a.value(lldb.frame.FindVariable('argv'))\n
|
||||
argv.name - return the name of the value that this object contains\n
|
||||
argv.type - return the lldb.SBType for this value
|
||||
argv.type_name - return the name of the type
|
||||
argv.size - return the byte size of this value
|
||||
argv.is_in_scope - return true if this value is currently in scope
|
||||
argv.is_pointer - return true if this value is a pointer
|
||||
argv.format - return the current format for this value
|
||||
argv.value - return the value's value as a string
|
||||
argv.summary - return a summary of this value's value
|
||||
argv.description - return the runtime description for this value
|
||||
argv.location - return a string that represents the values location (address, register, etc)
|
||||
argv.target - return the lldb.SBTarget for this value
|
||||
argv.process - return the lldb.SBProcess for this value
|
||||
argv.thread - return the lldb.SBThread for this value
|
||||
argv.frame - return the lldb.SBFrame for this value
|
||||
argv.num_children - return the number of children this value has
|
||||
argv.children - return a list of sbvalue objects that represents all of the children of this value
|
||||
'''
|
||||
def __init__(self, sbvalue):
|
||||
self.sbvalue = sbvalue
|
||||
|
||||
def __nonzero__(self):
|
||||
return self.sbvalue.__nonzero__()
|
||||
|
||||
def __repr__(self):
|
||||
return self.sbvalue.__repr__()
|
||||
|
||||
def __str__(self):
|
||||
return self.sbvalue.__str__()
|
||||
|
||||
def __getitem__(self, key):
|
||||
if type(key) is int:
|
||||
return value(self.sbvalue.GetChildAtIndex(key, lldb.eNoDynamicValues, True))
|
||||
raise TypeError
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name == 'name':
|
||||
return self.sbvalue.GetName()
|
||||
if name == 'type':
|
||||
return self.sbvalue.GetType()
|
||||
if name == 'type_name':
|
||||
return self.sbvalue.GetTypeName()
|
||||
if name == 'size':
|
||||
return self.sbvalue.GetByteSize()
|
||||
if name == 'is_in_scope':
|
||||
return self.sbvalue.IsInScope()
|
||||
if name == 'is_pointer':
|
||||
return self.sbvalue.TypeIsPointerType()
|
||||
if name == 'format':
|
||||
return self.sbvalue.GetFormat ()
|
||||
if name == 'value':
|
||||
return self.sbvalue.GetValue ()
|
||||
if name == 'summary':
|
||||
return self.sbvalue.GetSummary ()
|
||||
if name == 'description':
|
||||
return self.sbvalue.GetObjectDescription ()
|
||||
if name == 'location':
|
||||
return self.sbvalue.GetLocation ()
|
||||
if name == 'target':
|
||||
return self.sbvalue.GetTarget()
|
||||
if name == 'process':
|
||||
return self.sbvalue.GetProcess()
|
||||
if name == 'thread':
|
||||
return self.sbvalue.GetThread()
|
||||
if name == 'frame':
|
||||
return self.sbvalue.GetFrame()
|
||||
if name == 'num_children':
|
||||
return self.sbvalue.GetNumChildren()
|
||||
if name == 'children':
|
||||
# Returns an array of sbvalue objects, one for each child of
|
||||
# the value for the lldb.SBValue
|
||||
children = []
|
||||
for i in range (self.sbvalue.GetNumChildren()):
|
||||
children.append(value(self.sbvalue.GetChildAtIndex(i, lldb.eNoDynamicValues, True)))
|
||||
return children
|
||||
raise AttributeError
|
||||
|
||||
class variable(object):
|
||||
'''A class that treats a lldb.SBValue and allows it to be used just as
|
||||
a variable would be in code. So if you have a Point structure variable
|
||||
in your code, you would be able to do: "pt.x + pt.y"'''
|
||||
def __init__(self, sbvalue):
|
||||
self.sbvalue = sbvalue
|
||||
|
||||
def __nonzero__(self):
|
||||
return self.sbvalue.__nonzero__()
|
||||
|
||||
def __repr__(self):
|
||||
return self.sbvalue.__repr__()
|
||||
|
||||
def __str__(self):
|
||||
return self.sbvalue.__str__()
|
||||
|
||||
def __getitem__(self, key):
|
||||
# Allow array access if this value has children...
|
||||
if type(key) is int:
|
||||
return variable(self.sbvalue.GetValueForExpressionPath("[%i]" % key))
|
||||
raise TypeError
|
||||
|
||||
def __getattr__(self, name):
|
||||
child_sbvalue = self.sbvalue.GetChildMemberWithName (name)
|
||||
if child_sbvalue:
|
||||
return variable(child_sbvalue)
|
||||
raise AttributeError
|
||||
|
||||
def __add__(self, other):
|
||||
return int(self) + int(other)
|
||||
|
||||
def __sub__(self, other):
|
||||
return int(self) - int(other)
|
||||
|
||||
def __mul__(self, other):
|
||||
return int(self) * int(other)
|
||||
|
||||
def __floordiv__(self, other):
|
||||
return int(self) // int(other)
|
||||
|
||||
def __mod__(self, other):
|
||||
return int(self) % int(other)
|
||||
|
||||
def __divmod__(self, other):
|
||||
return int(self) % int(other)
|
||||
|
||||
def __pow__(self, other):
|
||||
return int(self) ** int(other)
|
||||
|
||||
def __lshift__(self, other):
|
||||
return int(self) << int(other)
|
||||
|
||||
def __rshift__(self, other):
|
||||
return int(self) >> int(other)
|
||||
|
||||
def __and__(self, other):
|
||||
return int(self) & int(other)
|
||||
|
||||
def __xor__(self, other):
|
||||
return int(self) ^ int(other)
|
||||
|
||||
def __or__(self, other):
|
||||
return int(self) | int(other)
|
||||
|
||||
def __div__(self, other):
|
||||
return int(self) / int(other)
|
||||
|
||||
def __truediv__(self, other):
|
||||
return int(self) / int(other)
|
||||
|
||||
def __iadd__(self, other):
|
||||
result = self.__add__(other)
|
||||
self.sbvalue.SetValueFromCString (str(result))
|
||||
return result
|
||||
|
||||
def __isub__(self, other):
|
||||
result = self.__sub__(other)
|
||||
self.sbvalue.SetValueFromCString (str(result))
|
||||
return result
|
||||
|
||||
def __imul__(self, other):
|
||||
result = self.__mul__(other)
|
||||
self.sbvalue.SetValueFromCString (str(result))
|
||||
return result
|
||||
|
||||
def __idiv__(self, other):
|
||||
result = self.__div__(other)
|
||||
self.sbvalue.SetValueFromCString (str(result))
|
||||
return result
|
||||
|
||||
def __itruediv__(self, other):
|
||||
result = self.__truediv__(other)
|
||||
self.sbvalue.SetValueFromCString (str(result))
|
||||
return result
|
||||
|
||||
def __ifloordiv__(self, other):
|
||||
result = self.__floordiv__(self, other)
|
||||
self.sbvalue.SetValueFromCString (str(result))
|
||||
return result
|
||||
|
||||
def __imod__(self, other):
|
||||
result = self.__and__(self, other)
|
||||
self.sbvalue.SetValueFromCString (str(result))
|
||||
return result
|
||||
|
||||
def __ipow__(self, other):
|
||||
result = self.__pow__(self, other)
|
||||
self.sbvalue.SetValueFromCString (str(result))
|
||||
return result
|
||||
|
||||
def __ipow__(self, other, modulo):
|
||||
result = self.__pow__(self, other, modulo)
|
||||
self.sbvalue.SetValueFromCString (str(result))
|
||||
return result
|
||||
|
||||
def __ilshift__(self, other):
|
||||
result = self.__lshift__(self, other)
|
||||
self.sbvalue.SetValueFromCString (str(result))
|
||||
return result
|
||||
|
||||
def __irshift__(self, other):
|
||||
result = self.__rshift__(self, other)
|
||||
self.sbvalue.SetValueFromCString (str(result))
|
||||
return result
|
||||
|
||||
def __iand__(self, other):
|
||||
result = self.__and__(self, other)
|
||||
self.sbvalue.SetValueFromCString (str(result))
|
||||
return result
|
||||
|
||||
def __ixor__(self, other):
|
||||
result = self.__xor__(self, other)
|
||||
self.sbvalue.SetValueFromCString (str(result))
|
||||
return result
|
||||
|
||||
def __ior__(self, other):
|
||||
result = self.__ior__(self, other)
|
||||
self.sbvalue.SetValueFromCString (str(result))
|
||||
return result
|
||||
|
||||
def __neg__(self):
|
||||
return -int(self)
|
||||
|
||||
def __pos__(self):
|
||||
return +int(self)
|
||||
|
||||
def __abs__(self):
|
||||
return abs(int(self))
|
||||
|
||||
def __invert__(self):
|
||||
return ~int(self)
|
||||
|
||||
def __complex__(self):
|
||||
return complex (int(self))
|
||||
|
||||
def __int__(self):
|
||||
return self.sbvalue.GetValueAsSigned()
|
||||
|
||||
def __long__(self):
|
||||
return self.sbvalue.GetValueAsSigned()
|
||||
|
||||
def __float__(self):
|
||||
return float (self.sbvalue.GetValueAsSigned())
|
||||
|
||||
def __oct__(self):
|
||||
return '0%o' % self.sbvalue.GetValueAsSigned()
|
||||
|
||||
def __hex__(self):
|
||||
return '0x%x' % self.sbvalue.GetValueAsSigned()
|
||||
|
||||
28
external/bsd/llvm/dist/lldb/examples/python/sources.py
vendored
Normal file
28
external/bsd/llvm/dist/lldb/examples/python/sources.py
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import lldb
|
||||
import shlex
|
||||
|
||||
def dump_module_sources(module, result):
|
||||
if module:
|
||||
print >> result, "Module: %s" % (module.file)
|
||||
for compile_unit in module.compile_units:
|
||||
if compile_unit.file:
|
||||
print >> result, " %s" % (compile_unit.file)
|
||||
|
||||
def info_sources(debugger, command, result, dict):
|
||||
description='''This command will dump all compile units in any modules that are listed as arguments, or for all modules if no arguments are supplied.'''
|
||||
module_names = shlex.split(command)
|
||||
target = debugger.GetSelectedTarget()
|
||||
if module_names:
|
||||
for module_name in module_names:
|
||||
dump_module_sources(target.module[module_name], result)
|
||||
else:
|
||||
for module in target.modules:
|
||||
dump_module_sources(module, result)
|
||||
|
||||
|
||||
def __lldb_init_module (debugger, dict):
|
||||
# Add any commands contained in this module to LLDB
|
||||
debugger.HandleCommand('command script add -f sources.info_sources info_sources')
|
||||
print 'The "info_sources" command has been installed, type "help info_sources" or "info_sources --help" for detailed help.'
|
||||
56
external/bsd/llvm/dist/lldb/examples/python/stacks.py
vendored
Executable file
56
external/bsd/llvm/dist/lldb/examples/python/stacks.py
vendored
Executable file
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import lldb
|
||||
import commands
|
||||
import optparse
|
||||
import shlex
|
||||
|
||||
def stack_frames(debugger, command, result, dict):
|
||||
command_args = shlex.split(command)
|
||||
usage = "usage: %prog [options] <PATH> [PATH ...]"
|
||||
description='''This command will enumerate all stack frames, print the stack size for each, and print an aggregation of which functions have the largest stack frame sizes at the end.'''
|
||||
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
|
||||
|
||||
frame_info = {}
|
||||
for thread in lldb.process:
|
||||
last_frame = None
|
||||
print "thread %u" % (thread.id)
|
||||
for frame in thread.frames:
|
||||
if last_frame:
|
||||
frame_size = 0
|
||||
if frame.idx == 1:
|
||||
if frame.fp == last_frame.fp:
|
||||
# No frame one the first frame (might be right at the entry point)
|
||||
first_frame_size = 0
|
||||
frame_size = frame.fp - frame.sp
|
||||
else:
|
||||
# First frame that has a valid size
|
||||
first_frame_size = last_frame.fp - last_frame.sp
|
||||
print "<%#7x> %s" % (first_frame_size, last_frame)
|
||||
if first_frame_size:
|
||||
name = last_frame.name
|
||||
if name not in frame_info:
|
||||
frame_info[name] = first_frame_size
|
||||
else:
|
||||
frame_info[name] += first_frame_size
|
||||
else:
|
||||
# Second or higher frame
|
||||
frame_size = frame.fp - last_frame.fp
|
||||
print "<%#7x> %s" % (frame_size, frame)
|
||||
if frame_size > 0:
|
||||
name = frame.name
|
||||
if name not in frame_info:
|
||||
frame_info[name] = frame_size
|
||||
else:
|
||||
frame_info[name] += frame_size
|
||||
last_frame = frame
|
||||
print frame_info
|
||||
|
||||
|
||||
lldb.debugger.HandleCommand("command script add -f stacks.stack_frames stack_frames")
|
||||
print "A new command called 'stack_frames' was added, type 'stack_frames --help' for more information."
|
||||
583
external/bsd/llvm/dist/lldb/examples/python/symbolication.py
vendored
Executable file
583
external/bsd/llvm/dist/lldb/examples/python/symbolication.py
vendored
Executable file
@@ -0,0 +1,583 @@
|
||||
#!/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/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 /path/to/LLDB.framework/Resources/Python ; ./crashlog.py ~/Library/Logs/DiagnosticReports/a.crash )
|
||||
#
|
||||
# On MacOSX sh, bash:
|
||||
# PYTHONPATH=/path/to/LLDB.framework/Resources/Python ./crashlog.py ~/Library/Logs/DiagnosticReports/a.crash
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
import lldb
|
||||
import commands
|
||||
import optparse
|
||||
import os
|
||||
import plistlib
|
||||
import re
|
||||
import shlex
|
||||
import sys
|
||||
import time
|
||||
import uuid
|
||||
|
||||
class Address:
|
||||
"""Class that represents an address that will be symbolicated"""
|
||||
def __init__(self, target, load_addr):
|
||||
self.target = target
|
||||
self.load_addr = load_addr # The load address that this object represents
|
||||
self.so_addr = None # the resolved lldb.SBAddress (if any), named so_addr for section/offset address
|
||||
self.sym_ctx = None # The cached symbol context for this address
|
||||
self.description = None # Any original textual description of this address to be used as a backup in case symbolication fails
|
||||
self.symbolication = None # The cached symbolicated string that describes this address
|
||||
self.inlined = False
|
||||
def __str__(self):
|
||||
s = "%#16.16x" % (self.load_addr)
|
||||
if self.symbolication:
|
||||
s += " %s" % (self.symbolication)
|
||||
elif self.description:
|
||||
s += " %s" % (self.description)
|
||||
elif self.so_addr:
|
||||
s += " %s" % (self.so_addr)
|
||||
return s
|
||||
|
||||
def resolve_addr(self):
|
||||
if self.so_addr == None:
|
||||
self.so_addr = self.target.ResolveLoadAddress (self.load_addr)
|
||||
return self.so_addr
|
||||
|
||||
def is_inlined(self):
|
||||
return self.inlined
|
||||
|
||||
def get_symbol_context(self):
|
||||
if self.sym_ctx == None:
|
||||
sb_addr = self.resolve_addr()
|
||||
if sb_addr:
|
||||
self.sym_ctx = self.target.ResolveSymbolContextForAddress (sb_addr, lldb.eSymbolContextEverything)
|
||||
else:
|
||||
self.sym_ctx = lldb.SBSymbolContext()
|
||||
return self.sym_ctx
|
||||
|
||||
def get_instructions(self):
|
||||
sym_ctx = self.get_symbol_context()
|
||||
if sym_ctx:
|
||||
function = sym_ctx.GetFunction()
|
||||
if function:
|
||||
return function.GetInstructions(self.target)
|
||||
return sym_ctx.GetSymbol().GetInstructions(self.target)
|
||||
return None
|
||||
|
||||
def symbolicate(self, verbose = False):
|
||||
if self.symbolication == None:
|
||||
self.symbolication = ''
|
||||
self.inlined = False
|
||||
sym_ctx = self.get_symbol_context()
|
||||
if sym_ctx:
|
||||
module = sym_ctx.GetModule()
|
||||
if module:
|
||||
# Print full source file path in verbose mode
|
||||
if verbose:
|
||||
self.symbolication += str(module.GetFileSpec()) + '`'
|
||||
else:
|
||||
self.symbolication += module.GetFileSpec().GetFilename() + '`'
|
||||
function_start_load_addr = -1
|
||||
function = sym_ctx.GetFunction()
|
||||
block = sym_ctx.GetBlock()
|
||||
line_entry = sym_ctx.GetLineEntry()
|
||||
symbol = sym_ctx.GetSymbol()
|
||||
inlined_block = block.GetContainingInlinedBlock();
|
||||
if function:
|
||||
self.symbolication += function.GetName()
|
||||
|
||||
if inlined_block:
|
||||
self.inlined = True
|
||||
self.symbolication += ' [inlined] ' + inlined_block.GetInlinedName();
|
||||
block_range_idx = inlined_block.GetRangeIndexForBlockAddress (self.so_addr)
|
||||
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 (self.target)
|
||||
if function_start_load_addr == -1:
|
||||
function_start_load_addr = function.GetStartAddress().GetLoadAddress (self.target)
|
||||
elif symbol:
|
||||
self.symbolication += symbol.GetName()
|
||||
function_start_load_addr = symbol.GetStartAddress().GetLoadAddress (self.target)
|
||||
else:
|
||||
self.symbolication = ''
|
||||
return False
|
||||
|
||||
# Dump the offset from the current function or symbol if it is non zero
|
||||
function_offset = self.load_addr - function_start_load_addr
|
||||
if function_offset > 0:
|
||||
self.symbolication += " + %u" % (function_offset)
|
||||
elif function_offset < 0:
|
||||
self.symbolication += " %i (invalid negative offset, file a bug) " % function_offset
|
||||
|
||||
# Print out any line information if any is available
|
||||
if line_entry.GetFileSpec():
|
||||
# Print full source file path in verbose mode
|
||||
if verbose:
|
||||
self.symbolication += ' at %s' % line_entry.GetFileSpec()
|
||||
else:
|
||||
self.symbolication += ' at %s' % line_entry.GetFileSpec().GetFilename()
|
||||
self.symbolication += ':%u' % line_entry.GetLine ()
|
||||
column = line_entry.GetColumn()
|
||||
if column > 0:
|
||||
self.symbolication += ':%u' % column
|
||||
return True
|
||||
return False
|
||||
|
||||
class Section:
|
||||
"""Class that represents an load address range"""
|
||||
sect_info_regex = re.compile('(?P<name>[^=]+)=(?P<range>.*)')
|
||||
addr_regex = re.compile('^\s*(?P<start>0x[0-9A-Fa-f]+)\s*$')
|
||||
range_regex = re.compile('^\s*(?P<start>0x[0-9A-Fa-f]+)\s*(?P<op>[-+])\s*(?P<end>0x[0-9A-Fa-f]+)\s*$')
|
||||
|
||||
def __init__(self, start_addr = None, end_addr = None, name = None):
|
||||
self.start_addr = start_addr
|
||||
self.end_addr = end_addr
|
||||
self.name = name
|
||||
|
||||
def contains(self, addr):
|
||||
return self.start_addr <= addr and addr < self.end_addr;
|
||||
|
||||
def set_from_string(self, s):
|
||||
match = self.sect_info_regex.match (s)
|
||||
if match:
|
||||
self.name = match.group('name')
|
||||
range_str = match.group('range')
|
||||
addr_match = self.addr_regex.match(range_str)
|
||||
if addr_match:
|
||||
self.start_addr = int(addr_match.group('start'), 16)
|
||||
self.end_addr = None
|
||||
return True
|
||||
|
||||
range_match = self.range_regex.match(range_str)
|
||||
if range_match:
|
||||
self.start_addr = int(range_match.group('start'), 16)
|
||||
self.end_addr = int(range_match.group('end'), 16)
|
||||
op = range_match.group('op')
|
||||
if op == '+':
|
||||
self.end_addr += self.start_addr
|
||||
return True
|
||||
print 'error: invalid section info string "%s"' % s
|
||||
print 'Valid section info formats are:'
|
||||
print 'Format Example Description'
|
||||
print '--------------------- -----------------------------------------------'
|
||||
print '<name>=<base> __TEXT=0x123000 Section from base address only'
|
||||
print '<name>=<base>-<end> __TEXT=0x123000-0x124000 Section from base address and end address'
|
||||
print '<name>=<base>+<size> __TEXT=0x123000+0x1000 Section from base address and size'
|
||||
return False
|
||||
|
||||
def __str__(self):
|
||||
if self.name:
|
||||
if self.end_addr != None:
|
||||
if self.start_addr != None:
|
||||
return "%s=[0x%16.16x - 0x%16.16x)" % (self.name, self.start_addr, self.end_addr)
|
||||
else:
|
||||
if self.start_addr != None:
|
||||
return "%s=0x%16.16x" % (self.name, self.start_addr)
|
||||
return self.name
|
||||
return "<invalid>"
|
||||
|
||||
class Image:
|
||||
"""A class that represents an executable image and any associated data"""
|
||||
|
||||
def __init__(self, path, uuid = None):
|
||||
self.path = path
|
||||
self.resolved_path = None
|
||||
self.resolved = False
|
||||
self.unavailable = False
|
||||
self.uuid = uuid
|
||||
self.section_infos = list()
|
||||
self.identifier = None
|
||||
self.version = None
|
||||
self.arch = None
|
||||
self.module = None
|
||||
self.symfile = None
|
||||
self.slide = None
|
||||
|
||||
|
||||
def dump(self, prefix):
|
||||
print "%s%s" % (prefix, self)
|
||||
|
||||
def debug_dump(self):
|
||||
print 'path = "%s"' % (self.path)
|
||||
print 'resolved_path = "%s"' % (self.resolved_path)
|
||||
print 'resolved = %i' % (self.resolved)
|
||||
print 'unavailable = %i' % (self.unavailable)
|
||||
print 'uuid = %s' % (self.uuid)
|
||||
print 'section_infos = %s' % (self.section_infos)
|
||||
print 'identifier = "%s"' % (self.identifier)
|
||||
print 'version = %s' % (self.version)
|
||||
print 'arch = %s' % (self.arch)
|
||||
print 'module = %s' % (self.module)
|
||||
print 'symfile = "%s"' % (self.symfile)
|
||||
print 'slide = %i (0x%x)' % (self.slide, self.slide)
|
||||
|
||||
def __str__(self):
|
||||
s = "%s %s %s" % (self.get_uuid(), self.version, self.get_resolved_path())
|
||||
for section_info in self.section_infos:
|
||||
s += ", %s" % (section_info)
|
||||
if self.slide != None:
|
||||
s += ', slide = 0x%16.16x' % self.slide
|
||||
return s
|
||||
|
||||
def add_section(self, section):
|
||||
#print "added '%s' to '%s'" % (section, self.path)
|
||||
self.section_infos.append (section)
|
||||
|
||||
def get_section_containing_load_addr (self, load_addr):
|
||||
for section_info in self.section_infos:
|
||||
if section_info.contains(load_addr):
|
||||
return section_info
|
||||
return None
|
||||
|
||||
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 symfile_basename(self):
|
||||
if self.symfile:
|
||||
return os.path.basename(self.symfile)
|
||||
return None
|
||||
|
||||
def has_section_load_info(self):
|
||||
return self.section_infos or self.slide != None
|
||||
|
||||
def load_module(self, target):
|
||||
if self.unavailable:
|
||||
return None # We already warned that we couldn't find this module, so don't return an error string
|
||||
# Load this module into "target" using the section infos to
|
||||
# set the section load addresses
|
||||
if self.has_section_load_info():
|
||||
if target:
|
||||
if self.module:
|
||||
if self.section_infos:
|
||||
num_sections_loaded = 0
|
||||
for section_info in self.section_infos:
|
||||
if section_info.name:
|
||||
section = self.module.FindSection (section_info.name)
|
||||
if section:
|
||||
error = target.SetSectionLoadAddress (section, section_info.start_addr)
|
||||
if error.Success():
|
||||
num_sections_loaded += 1
|
||||
else:
|
||||
return 'error: %s' % error.GetCString()
|
||||
else:
|
||||
return 'error: unable to find the section named "%s"' % section_info.name
|
||||
else:
|
||||
return 'error: unable to find "%s" section in "%s"' % (range.name, self.get_resolved_path())
|
||||
if num_sections_loaded == 0:
|
||||
return 'error: no sections were successfully loaded'
|
||||
else:
|
||||
err = target.SetModuleLoadAddress(self.module, self.slide)
|
||||
if err.Fail():
|
||||
return err.GetCString()
|
||||
return None
|
||||
else:
|
||||
return 'error: invalid module'
|
||||
else:
|
||||
return 'error: invalid target'
|
||||
else:
|
||||
return 'error: no section infos'
|
||||
|
||||
def add_module(self, target):
|
||||
'''Add the Image described in this object to "target" and load the sections if "load" is True.'''
|
||||
if target:
|
||||
# Try and find using UUID only first so that paths need not match up
|
||||
uuid_str = self.get_normalized_uuid_string()
|
||||
if uuid_str:
|
||||
self.module = target.AddModule (None, None, uuid_str)
|
||||
if not self.module:
|
||||
self.locate_module_and_debug_symbols ()
|
||||
if self.unavailable:
|
||||
return None
|
||||
resolved_path = self.get_resolved_path()
|
||||
self.module = target.AddModule (resolved_path, self.arch, uuid_str, self.symfile)
|
||||
if not self.module:
|
||||
return 'error: unable to get module for (%s) "%s"' % (self.arch, self.get_resolved_path())
|
||||
if self.has_section_load_info():
|
||||
return self.load_module(target)
|
||||
else:
|
||||
return None # No sections, the module was added to the target, so success
|
||||
else:
|
||||
return 'error: invalid target'
|
||||
|
||||
def locate_module_and_debug_symbols (self):
|
||||
# By default, just use the paths that were supplied in:
|
||||
# self.path
|
||||
# self.resolved_path
|
||||
# self.module
|
||||
# self.symfile
|
||||
# Subclasses can inherit from this class and override this function
|
||||
self.resolved = True
|
||||
return True
|
||||
|
||||
def get_uuid(self):
|
||||
if not self.uuid and self.module:
|
||||
self.uuid = uuid.UUID(self.module.GetUUIDString())
|
||||
return self.uuid
|
||||
|
||||
def get_normalized_uuid_string(self):
|
||||
if self.uuid:
|
||||
return str(self.uuid).upper()
|
||||
return None
|
||||
|
||||
def create_target(self):
|
||||
'''Create a target using the information in this Image object.'''
|
||||
if self.unavailable:
|
||||
return None
|
||||
|
||||
if self.locate_module_and_debug_symbols ():
|
||||
resolved_path = self.get_resolved_path();
|
||||
path_spec = lldb.SBFileSpec (resolved_path)
|
||||
#result.PutCString ('plist[%s] = %s' % (uuid, self.plist))
|
||||
error = lldb.SBError()
|
||||
target = lldb.debugger.CreateTarget (resolved_path, self.arch, None, False, error);
|
||||
if target:
|
||||
self.module = target.FindModule(path_spec)
|
||||
if self.has_section_load_info():
|
||||
err = self.load_module(target)
|
||||
if err:
|
||||
print 'ERROR: ', err
|
||||
return target
|
||||
else:
|
||||
print 'error: unable to create a valid target for (%s) "%s"' % (self.arch, self.path)
|
||||
else:
|
||||
print 'error: unable to locate main executable (%s) "%s"' % (self.arch, self.path)
|
||||
return None
|
||||
|
||||
class Symbolicator:
|
||||
|
||||
def __init__(self):
|
||||
"""A class the represents the information needed to symbolicate addresses in a program"""
|
||||
self.target = None
|
||||
self.images = list() # a list of images to be used when symbolicating
|
||||
self.addr_mask = 0xffffffffffffffff
|
||||
|
||||
def __str__(self):
|
||||
s = "Symbolicator:\n"
|
||||
if self.target:
|
||||
s += "Target = '%s'\n" % (self.target)
|
||||
s += "Target modules:'\n"
|
||||
for m in self.target.modules:
|
||||
print m
|
||||
s += "Images:\n"
|
||||
for image in self.images:
|
||||
s += ' %s\n' % (image)
|
||||
return s
|
||||
|
||||
def find_images_with_identifier(self, identifier):
|
||||
images = list()
|
||||
for image in self.images:
|
||||
if image.identifier == identifier:
|
||||
images.append(image)
|
||||
return images
|
||||
|
||||
def find_image_containing_load_addr(self, load_addr):
|
||||
for image in self.images:
|
||||
if image.get_section_containing_load_addr (load_addr):
|
||||
return image
|
||||
return None
|
||||
|
||||
def create_target(self):
|
||||
if self.target:
|
||||
return self.target
|
||||
|
||||
if self.images:
|
||||
for image in self.images:
|
||||
self.target = image.create_target ()
|
||||
if self.target:
|
||||
if self.target.GetAddressByteSize() == 4:
|
||||
triple = self.target.triple
|
||||
if triple:
|
||||
arch = triple.split('-')[0]
|
||||
if "arm" in arch:
|
||||
self.addr_mask = 0xfffffffffffffffe
|
||||
return self.target
|
||||
return None
|
||||
|
||||
def symbolicate(self, load_addr, verbose = False):
|
||||
if not self.target:
|
||||
self.create_target()
|
||||
if self.target:
|
||||
live_process = False
|
||||
process = self.target.process
|
||||
if process:
|
||||
state = process.state
|
||||
if state > lldb.eStateUnloaded and state < lldb.eStateDetached:
|
||||
live_process = True
|
||||
# If we don't have a live process, we can attempt to find the image
|
||||
# that a load address belongs to and lazily load its module in the
|
||||
# target, but we shouldn't do any of this if we have a live process
|
||||
if not live_process:
|
||||
image = self.find_image_containing_load_addr (load_addr)
|
||||
if image:
|
||||
image.add_module (self.target)
|
||||
symbolicated_address = Address(self.target, load_addr)
|
||||
if symbolicated_address.symbolicate (verbose):
|
||||
if symbolicated_address.so_addr:
|
||||
symbolicated_addresses = list()
|
||||
symbolicated_addresses.append(symbolicated_address)
|
||||
# See if we were able to reconstruct anything?
|
||||
while 1:
|
||||
inlined_parent_so_addr = lldb.SBAddress()
|
||||
inlined_parent_sym_ctx = symbolicated_address.sym_ctx.GetParentOfInlinedScope (symbolicated_address.so_addr, inlined_parent_so_addr)
|
||||
if not inlined_parent_sym_ctx:
|
||||
break
|
||||
if not inlined_parent_so_addr:
|
||||
break
|
||||
|
||||
symbolicated_address = Address(self.target, inlined_parent_so_addr.GetLoadAddress(self.target))
|
||||
symbolicated_address.sym_ctx = inlined_parent_sym_ctx
|
||||
symbolicated_address.so_addr = inlined_parent_so_addr
|
||||
symbolicated_address.symbolicate (verbose)
|
||||
|
||||
# push the new frame onto the new frame stack
|
||||
symbolicated_addresses.append (symbolicated_address)
|
||||
|
||||
if symbolicated_addresses:
|
||||
return symbolicated_addresses
|
||||
else:
|
||||
print 'error: no target in Symbolicator'
|
||||
return None
|
||||
|
||||
|
||||
def disassemble_instructions (target, instructions, pc, insts_before_pc, insts_after_pc, non_zeroeth_frame):
|
||||
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 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 insts_before_pc == -1:
|
||||
start_idx = 0
|
||||
else:
|
||||
start_idx = pc_index - insts_before_pc
|
||||
if start_idx < 0:
|
||||
start_idx = 0
|
||||
if insts_before_pc == -1:
|
||||
end_idx = inst_idx
|
||||
else:
|
||||
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 Symbolicate(command_args):
|
||||
|
||||
usage = "usage: %prog [options] <addr1> [addr2 ...]"
|
||||
description='''Symbolicate one or more addresses using LLDB's python scripting API..'''
|
||||
parser = optparse.OptionParser(description=description, prog='crashlog.py',usage=usage)
|
||||
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
|
||||
parser.add_option('-p', '--platform', type='string', metavar='platform', dest='platform', help='Specify the platform to use when creating the debug target. Valid values include "localhost", "darwin-kernel", "ios-simulator", "remote-freebsd", "remote-macosx", "remote-ios", "remote-linux".')
|
||||
parser.add_option('-f', '--file', type='string', metavar='file', dest='file', help='Specify a file to use when symbolicating')
|
||||
parser.add_option('-a', '--arch', type='string', metavar='arch', dest='arch', help='Specify a architecture to use when symbolicating')
|
||||
parser.add_option('-s', '--slide', type='int', metavar='slide', dest='slide', help='Specify the slide to use on the file specified with the --file option', default=None)
|
||||
parser.add_option('--section', type='string', action='append', dest='section_strings', help='specify <sect-name>=<start-addr> or <sect-name>=<start-addr>-<end-addr>')
|
||||
try:
|
||||
(options, args) = parser.parse_args(command_args)
|
||||
except:
|
||||
return
|
||||
symbolicator = Symbolicator()
|
||||
images = list();
|
||||
if options.file:
|
||||
image = Image(options.file);
|
||||
image.arch = options.arch
|
||||
# Add any sections that were specified with one or more --section options
|
||||
if options.section_strings:
|
||||
for section_str in options.section_strings:
|
||||
section = Section()
|
||||
if section.set_from_string (section_str):
|
||||
image.add_section (section)
|
||||
else:
|
||||
sys.exit(1)
|
||||
if options.slide != None:
|
||||
image.slide = options.slide
|
||||
symbolicator.images.append(image)
|
||||
|
||||
target = symbolicator.create_target()
|
||||
if options.verbose:
|
||||
print symbolicator
|
||||
if target:
|
||||
for addr_str in args:
|
||||
addr = int(addr_str, 0)
|
||||
symbolicated_addrs = symbolicator.symbolicate(addr, options.verbose)
|
||||
for symbolicated_addr in symbolicated_addrs:
|
||||
print symbolicated_addr
|
||||
print
|
||||
else:
|
||||
print 'error: no target for %s' % (symbolicator)
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Create a new debugger instance
|
||||
lldb.debugger = lldb.SBDebugger.Create()
|
||||
Symbolicate (sys.argv[1:])
|
||||
252
external/bsd/llvm/dist/lldb/examples/python/types.py
vendored
Executable file
252
external/bsd/llvm/dist/lldb/examples/python/types.py
vendored
Executable file
@@ -0,0 +1,252 @@
|
||||
#!/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" just
|
||||
# import it with the full path using the "command script import"
|
||||
# command
|
||||
# (lldb) command script import /path/to/cmdtemplate.py
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
import commands
|
||||
import platform
|
||||
import os
|
||||
import re
|
||||
import signal
|
||||
import sys
|
||||
|
||||
try:
|
||||
# Just try for LLDB in case PYTHONPATH is already correctly setup
|
||||
import lldb
|
||||
except ImportError:
|
||||
lldb_python_dirs = list()
|
||||
# lldb is not in the PYTHONPATH, try some defaults for the current platform
|
||||
platform_system = platform.system()
|
||||
if platform_system == 'Darwin':
|
||||
# On Darwin, try the currently selected Xcode directory
|
||||
xcode_dir = commands.getoutput("xcode-select --print-path")
|
||||
if xcode_dir:
|
||||
lldb_python_dirs.append(os.path.realpath(xcode_dir + '/../SharedFrameworks/LLDB.framework/Resources/Python'))
|
||||
lldb_python_dirs.append(xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
|
||||
lldb_python_dirs.append('/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
|
||||
success = False
|
||||
for lldb_python_dir in lldb_python_dirs:
|
||||
if os.path.exists(lldb_python_dir):
|
||||
if not (sys.path.__contains__(lldb_python_dir)):
|
||||
sys.path.append(lldb_python_dir)
|
||||
try:
|
||||
import lldb
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
print 'imported lldb from: "%s"' % (lldb_python_dir)
|
||||
success = True
|
||||
break
|
||||
if not success:
|
||||
print "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly"
|
||||
sys.exit(1)
|
||||
|
||||
import commands
|
||||
import optparse
|
||||
import shlex
|
||||
import time
|
||||
|
||||
def regex_option_callback(option, opt_str, value, parser):
|
||||
if opt_str == "--std":
|
||||
value = '^std::'
|
||||
regex = re.compile(value)
|
||||
parser.values.skip_type_regexes.append (regex)
|
||||
|
||||
def create_types_options(for_lldb_command):
|
||||
if for_lldb_command:
|
||||
usage = "usage: %prog [options]"
|
||||
description='''This command will help check for padding in between
|
||||
base classes and members in structs and classes. It will summarize the types
|
||||
and how much padding was found. If no types are specified with the --types TYPENAME
|
||||
option, all structure and class types will be verified. If no modules are
|
||||
specified with the --module option, only the target's main executable will be
|
||||
searched.
|
||||
'''
|
||||
else:
|
||||
usage = "usage: %prog [options] EXEPATH [EXEPATH ...]"
|
||||
description='''This command will help check for padding in between
|
||||
base classes and members in structures and classes. It will summarize the types
|
||||
and how much padding was found. One or more paths to executable files must be
|
||||
specified and targets will be created with these modules. If no types are
|
||||
specified with the --types TYPENAME option, all structure and class types will
|
||||
be verified in all specified modules.
|
||||
'''
|
||||
parser = optparse.OptionParser(description=description, prog='framestats',usage=usage)
|
||||
if not for_lldb_command:
|
||||
parser.add_option('-a', '--arch', type='string', dest='arch', help='The architecture to use when creating the debug target.', default=None)
|
||||
parser.add_option('-p', '--platform', type='string', metavar='platform', dest='platform', help='Specify the platform to use when creating the debug target. Valid values include "localhost", "darwin-kernel", "ios-simulator", "remote-freebsd", "remote-macosx", "remote-ios", "remote-linux".')
|
||||
parser.add_option('-m', '--module', action='append', type='string', metavar='MODULE', dest='modules', help='Specify one or more modules which will be used to verify the types.', default=[])
|
||||
parser.add_option('-d', '--debug', action='store_true', dest='debug', help='Pause 10 seconds to wait for a debugger to attach.', default=False)
|
||||
parser.add_option('-t', '--type', action='append', type='string', metavar='TYPENAME', dest='typenames', help='Specify one or more type names which should be verified. If no type names are specified, all class and struct types will be verified.', default=[])
|
||||
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='Enable verbose logging and information.', default=False)
|
||||
parser.add_option('-s', '--skip-type-regex', action="callback", callback=regex_option_callback, type='string', metavar='REGEX', dest='skip_type_regexes', help='Regular expressions that, if they match the current member typename, will cause the type to no be recursively displayed.', default=[])
|
||||
parser.add_option('--std', action="callback", callback=regex_option_callback, metavar='REGEX', dest='skip_type_regexes', help="Don't' recurse into types in the std namespace.", default=[])
|
||||
return parser
|
||||
|
||||
def verify_type (target, options, type):
|
||||
print type
|
||||
typename = type.GetName()
|
||||
# print 'type: %s' % (typename)
|
||||
(end_offset, padding) = verify_type_recursive (target, options, type, None, 0, 0, 0)
|
||||
byte_size = type.GetByteSize()
|
||||
# if end_offset < byte_size:
|
||||
# last_member_padding = byte_size - end_offset
|
||||
# print '%+4u <%u> padding' % (end_offset, last_member_padding)
|
||||
# padding += last_member_padding
|
||||
print 'Total byte size: %u' % (byte_size)
|
||||
print 'Total pad bytes: %u' % (padding)
|
||||
if padding > 0:
|
||||
print 'Padding percentage: %2.2f %%' % ((float(padding) / float(byte_size)) * 100.0)
|
||||
print
|
||||
|
||||
def verify_type_recursive (target, options, type, member_name, depth, base_offset, padding):
|
||||
prev_end_offset = base_offset
|
||||
typename = type.GetName()
|
||||
byte_size = type.GetByteSize()
|
||||
if member_name and member_name != typename:
|
||||
print '%+4u <%3u> %s%s %s;' % (base_offset, byte_size, ' ' * depth, typename, member_name)
|
||||
else:
|
||||
print '%+4u {%3u} %s%s' % (base_offset, byte_size, ' ' * depth, typename)
|
||||
|
||||
for type_regex in options.skip_type_regexes:
|
||||
match = type_regex.match (typename)
|
||||
if match:
|
||||
return (base_offset + byte_size, padding)
|
||||
|
||||
members = type.members
|
||||
if members:
|
||||
for member_idx, member in enumerate(members):
|
||||
member_type = member.GetType()
|
||||
member_canonical_type = member_type.GetCanonicalType()
|
||||
member_type_class = member_canonical_type.GetTypeClass()
|
||||
member_name = member.GetName()
|
||||
member_offset = member.GetOffsetInBytes()
|
||||
member_total_offset = member_offset + base_offset
|
||||
member_byte_size = member_type.GetByteSize()
|
||||
member_is_class_or_struct = False
|
||||
if member_type_class == lldb.eTypeClassStruct or member_type_class == lldb.eTypeClassClass:
|
||||
member_is_class_or_struct = True
|
||||
if member_idx == 0 and member_offset == target.GetAddressByteSize() and type.IsPolymorphicClass():
|
||||
ptr_size = target.GetAddressByteSize()
|
||||
print '%+4u <%3u> %s__vtbl_ptr_type * _vptr;' % (prev_end_offset, ptr_size, ' ' * (depth + 1))
|
||||
prev_end_offset = ptr_size
|
||||
else:
|
||||
if prev_end_offset < member_total_offset:
|
||||
member_padding = member_total_offset - prev_end_offset
|
||||
padding = padding + member_padding
|
||||
print '%+4u <%3u> %s<PADDING>' % (prev_end_offset, member_padding, ' ' * (depth + 1))
|
||||
|
||||
if member_is_class_or_struct:
|
||||
(prev_end_offset, padding) = verify_type_recursive (target, options, member_canonical_type, member_name, depth + 1, member_total_offset, padding)
|
||||
else:
|
||||
prev_end_offset = member_total_offset + member_byte_size
|
||||
member_typename = member_type.GetName()
|
||||
if member.IsBitfield():
|
||||
print '%+4u <%3u> %s%s:%u %s;' % (member_total_offset, member_byte_size, ' ' * (depth + 1), member_typename, member.GetBitfieldSizeInBits(), member_name)
|
||||
else:
|
||||
print '%+4u <%3u> %s%s %s;' % (member_total_offset, member_byte_size, ' ' * (depth + 1), member_typename, member_name)
|
||||
|
||||
if prev_end_offset < byte_size:
|
||||
last_member_padding = byte_size - prev_end_offset
|
||||
print '%+4u <%3u> %s<PADDING>' % (prev_end_offset, last_member_padding, ' ' * (depth + 1))
|
||||
padding += last_member_padding
|
||||
else:
|
||||
if type.IsPolymorphicClass():
|
||||
ptr_size = target.GetAddressByteSize()
|
||||
print '%+4u <%3u> %s__vtbl_ptr_type * _vptr;' % (prev_end_offset, ptr_size, ' ' * (depth + 1))
|
||||
prev_end_offset = ptr_size
|
||||
prev_end_offset = base_offset + byte_size
|
||||
|
||||
return (prev_end_offset, padding)
|
||||
|
||||
def check_padding_command (debugger, command, result, dict):
|
||||
# Use the Shell Lexer to properly parse up command options just like a
|
||||
# shell would
|
||||
command_args = shlex.split(command)
|
||||
parser = create_types_options(True)
|
||||
try:
|
||||
(options, args) = parser.parse_args(command_args)
|
||||
except:
|
||||
# if you don't handle exceptions, passing an incorrect argument to the OptionParser will cause LLDB to exit
|
||||
# (courtesy of OptParse dealing with argument errors by throwing SystemExit)
|
||||
result.SetStatus (lldb.eReturnStatusFailed)
|
||||
return "option parsing failed" # returning a string is the same as returning an error whose description is the string
|
||||
verify_types(options, debugger.GetSelectedTarget(), command_args)
|
||||
|
||||
|
||||
def verify_types (target, options):
|
||||
|
||||
if not target:
|
||||
print 'error: invalid target'
|
||||
return
|
||||
|
||||
modules = list()
|
||||
if len(options.modules) == 0:
|
||||
# Append just the main executable if nothing was specified
|
||||
module = target.modules[0]
|
||||
if module:
|
||||
modules.append(module)
|
||||
else:
|
||||
for module_name in options.modules:
|
||||
module = lldb.target.module[module_name]
|
||||
if module:
|
||||
modules.append(module)
|
||||
|
||||
if modules:
|
||||
for module in modules:
|
||||
print 'module: %s' % (module.file)
|
||||
if options.typenames:
|
||||
for typename in options.typenames:
|
||||
types = module.FindTypes(typename)
|
||||
if types.GetSize():
|
||||
print 'Found %u types matching "%s" in "%s"' % (len(types), typename, module.file)
|
||||
for type in types:
|
||||
verify_type (target, options, type)
|
||||
else:
|
||||
print 'error: no type matches "%s" in "%s"' % (typename, module.file)
|
||||
else:
|
||||
types = module.GetTypes(lldb.eTypeClassClass | lldb.eTypeClassStruct)
|
||||
print 'Found %u types in "%s"' % (len(types), module.file)
|
||||
for type in types:
|
||||
verify_type (target, options, type)
|
||||
else:
|
||||
print 'error: no modules'
|
||||
|
||||
if __name__ == '__main__':
|
||||
debugger = lldb.SBDebugger.Create()
|
||||
parser = create_types_options(False)
|
||||
|
||||
# try:
|
||||
(options, args) = parser.parse_args(sys.argv[1:])
|
||||
# except:
|
||||
# print "error: option parsing failed"
|
||||
# sys.exit(1)
|
||||
|
||||
if options.debug:
|
||||
print "Waiting for debugger to attach to process %d" % os.getpid()
|
||||
os.kill(os.getpid(), signal.SIGSTOP)
|
||||
|
||||
for path in args:
|
||||
# in a command - the lldb.* convenience variables are not to be used
|
||||
# and their values (if any) are undefined
|
||||
# this is the best practice to access those objects from within a command
|
||||
error = lldb.SBError()
|
||||
target = debugger.CreateTarget (path,
|
||||
options.arch,
|
||||
options.platform,
|
||||
True,
|
||||
error)
|
||||
if error.Fail():
|
||||
print error.GetCString()
|
||||
continue
|
||||
verify_types (target, options)
|
||||
|
||||
elif getattr(lldb, 'debugger', None):
|
||||
lldb.debugger.HandleCommand('command script add -f types.check_padding_command check_padding')
|
||||
print '"check_padding" command installed, use the "--help" option for detailed help'
|
||||
353
external/bsd/llvm/dist/lldb/examples/python/x86_64_linux_target_definition.py
vendored
Normal file
353
external/bsd/llvm/dist/lldb/examples/python/x86_64_linux_target_definition.py
vendored
Normal file
@@ -0,0 +1,353 @@
|
||||
#!/usr/bin/python
|
||||
#===-- x86_64_linux_target_definition.py -----------------------------*- C++ -*-===//
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
#===----------------------------------------------------------------------===//
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This file can be used with the following setting:
|
||||
# plugin.process.gdb-remote.target-definition-file
|
||||
# This setting should be used when you are trying to connect to a
|
||||
# remote GDB server that doesn't support any of the register discovery
|
||||
# packets that LLDB normally uses.
|
||||
#
|
||||
# Why is this necessary? LLDB doesn't require a new build of LLDB that
|
||||
# targets each new architecture you will debug with. Instead, all
|
||||
# architectures are supported and LLDB relies on extra GDB server
|
||||
# packets to discover the target we are connecting to so that is can
|
||||
# show the right registers for each target. This allows the GDB server
|
||||
# to change and add new registers without requiring a new LLDB build
|
||||
# just so we can see new registers.
|
||||
#
|
||||
# This file implements the x86_64 registers for the darwin version of
|
||||
# GDB and allows you to connect to servers that use this register set.
|
||||
#
|
||||
# USAGE
|
||||
#
|
||||
# (lldb) settings set plugin.process.gdb-remote.target-definition-file /path/to/x86_64_linux_target_definition.py
|
||||
# (lldb) gdb-remote other.baz.com:1234
|
||||
#
|
||||
# The target definition file will get used if and only if the
|
||||
# qRegisterInfo packets are not supported when connecting to a remote
|
||||
# GDB server.
|
||||
#----------------------------------------------------------------------
|
||||
from lldb import *
|
||||
|
||||
# Compiler and DWARF register numbers
|
||||
name_to_gcc_dwarf_regnum = {
|
||||
'rax' : 0 ,
|
||||
'rdx' : 1 ,
|
||||
'rcx' : 2 ,
|
||||
'rbx' : 3 ,
|
||||
'rsi' : 4 ,
|
||||
'rdi' : 5 ,
|
||||
'rbp' : 6 ,
|
||||
'rsp' : 7 ,
|
||||
'r8' : 8 ,
|
||||
'r9' : 9 ,
|
||||
'r10' : 10,
|
||||
'r11' : 11,
|
||||
'r12' : 12,
|
||||
'r13' : 13,
|
||||
'r14' : 14,
|
||||
'r15' : 15,
|
||||
'rip' : 16,
|
||||
'xmm0' : 17,
|
||||
'xmm1' : 18,
|
||||
'xmm2' : 19,
|
||||
'xmm3' : 20,
|
||||
'xmm4' : 21,
|
||||
'xmm5' : 22,
|
||||
'xmm6' : 23,
|
||||
'xmm7' : 24,
|
||||
'xmm8' : 25,
|
||||
'xmm9' : 26,
|
||||
'xmm10' : 27,
|
||||
'xmm11' : 28,
|
||||
'xmm12' : 29,
|
||||
'xmm13' : 30,
|
||||
'xmm14' : 31,
|
||||
'xmm15' : 32,
|
||||
'stmm0' : 33,
|
||||
'stmm1' : 34,
|
||||
'stmm2' : 35,
|
||||
'stmm3' : 36,
|
||||
'stmm4' : 37,
|
||||
'stmm5' : 38,
|
||||
'stmm6' : 39,
|
||||
'stmm7' : 30,
|
||||
'ymm0' : 41,
|
||||
'ymm1' : 42,
|
||||
'ymm2' : 43,
|
||||
'ymm3' : 44,
|
||||
'ymm4' : 45,
|
||||
'ymm5' : 46,
|
||||
'ymm6' : 47,
|
||||
'ymm7' : 48,
|
||||
'ymm8' : 49,
|
||||
'ymm9' : 40,
|
||||
'ymm10' : 41,
|
||||
'ymm11' : 42,
|
||||
'ymm12' : 43,
|
||||
'ymm13' : 44,
|
||||
'ymm14' : 45,
|
||||
'ymm15' : 46
|
||||
};
|
||||
|
||||
name_to_gdb_regnum = {
|
||||
'rax' : 0,
|
||||
'rbx' : 1,
|
||||
'rcx' : 2,
|
||||
'rdx' : 3,
|
||||
'rsi' : 4,
|
||||
'rdi' : 5,
|
||||
'rbp' : 6,
|
||||
'rsp' : 7,
|
||||
'r8' : 8,
|
||||
'r9' : 9,
|
||||
'r10' : 10,
|
||||
'r11' : 11,
|
||||
'r12' : 12,
|
||||
'r13' : 13,
|
||||
'r14' : 14,
|
||||
'r15' : 15,
|
||||
'rip' : 16,
|
||||
'rflags': 17,
|
||||
'cs' : 18,
|
||||
'ss' : 19,
|
||||
'ds' : 20,
|
||||
'es' : 21,
|
||||
'fs' : 22,
|
||||
'gs' : 23,
|
||||
'stmm0' : 24,
|
||||
'stmm1' : 25,
|
||||
'stmm2' : 26,
|
||||
'stmm3' : 27,
|
||||
'stmm4' : 28,
|
||||
'stmm5' : 29,
|
||||
'stmm6' : 30,
|
||||
'stmm7' : 31,
|
||||
'fctrl' : 32,
|
||||
'fstat' : 33,
|
||||
'ftag' : 34,
|
||||
'fiseg' : 35,
|
||||
'fioff' : 36,
|
||||
'foseg' : 37,
|
||||
'fooff' : 38,
|
||||
'fop' : 39,
|
||||
'xmm0' : 40,
|
||||
'xmm1' : 41,
|
||||
'xmm2' : 42,
|
||||
'xmm3' : 43,
|
||||
'xmm4' : 44,
|
||||
'xmm5' : 45,
|
||||
'xmm6' : 46,
|
||||
'xmm7' : 47,
|
||||
'xmm8' : 48,
|
||||
'xmm9' : 49,
|
||||
'xmm10' : 50,
|
||||
'xmm11' : 51,
|
||||
'xmm12' : 52,
|
||||
'xmm13' : 53,
|
||||
'xmm14' : 54,
|
||||
'xmm15' : 55,
|
||||
'mxcsr' : 56,
|
||||
'ymm0' : 57,
|
||||
'ymm1' : 58,
|
||||
'ymm2' : 59,
|
||||
'ymm3' : 60,
|
||||
'ymm4' : 61,
|
||||
'ymm5' : 62,
|
||||
'ymm6' : 63,
|
||||
'ymm7' : 64,
|
||||
'ymm8' : 65,
|
||||
'ymm9' : 66,
|
||||
'ymm10' : 67,
|
||||
'ymm11' : 68,
|
||||
'ymm12' : 69,
|
||||
'ymm13' : 70,
|
||||
'ymm14' : 71,
|
||||
'ymm15' : 72
|
||||
};
|
||||
|
||||
name_to_generic_regnum = {
|
||||
'rip' : LLDB_REGNUM_GENERIC_PC,
|
||||
'rsp' : LLDB_REGNUM_GENERIC_SP,
|
||||
'rbp' : LLDB_REGNUM_GENERIC_FP,
|
||||
'rdi' : LLDB_REGNUM_GENERIC_ARG1,
|
||||
'rsi' : LLDB_REGNUM_GENERIC_ARG2,
|
||||
'rdx' : LLDB_REGNUM_GENERIC_ARG3,
|
||||
'rcx' : LLDB_REGNUM_GENERIC_ARG4,
|
||||
'r8' : LLDB_REGNUM_GENERIC_ARG5,
|
||||
'r9' : LLDB_REGNUM_GENERIC_ARG6
|
||||
};
|
||||
|
||||
def get_reg_num (reg_num_dict, reg_name):
|
||||
if reg_name in reg_num_dict:
|
||||
return reg_num_dict[reg_name]
|
||||
return LLDB_INVALID_REGNUM
|
||||
|
||||
x86_64_register_infos = [
|
||||
{ 'name':'rax' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
|
||||
{ 'name':'rbx' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
|
||||
{ 'name':'rcx' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg4' },
|
||||
{ 'name':'rdx' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg3' },
|
||||
{ 'name':'rsi' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg2' },
|
||||
{ 'name':'rdi' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg1' },
|
||||
{ 'name':'rbp' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'fp' },
|
||||
{ 'name':'rsp' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'sp' },
|
||||
{ 'name':'r8' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg5' },
|
||||
{ 'name':'r9' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg6' },
|
||||
{ 'name':'r10' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
|
||||
{ 'name':'r11' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
|
||||
{ 'name':'r12' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
|
||||
{ 'name':'r13' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
|
||||
{ 'name':'r14' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
|
||||
{ 'name':'r15' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
|
||||
{ 'name':'rip' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'pc' },
|
||||
{ 'name':'rflags', 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'cs' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'ss' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'ds' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'es' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'fs' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'gs' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'stmm0' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'stmm1' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'stmm2' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'stmm3' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'stmm4' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'stmm5' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'stmm6' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'stmm7' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'fctrl' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'fstat' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'ftag' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'fiseg' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'fioff' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'foseg' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'fooff' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'fop' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'xmm0' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm1' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm2' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm3' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm4' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm5' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm6' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm7' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm8' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm9' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm10' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm11' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm12' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm13' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm14' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm15' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'mxcsr' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'orig_rax' , 'set':1, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
# Registers that are contained in or composed of one of more other registers
|
||||
{ 'name':'eax' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rax[31:0]' },
|
||||
{ 'name':'ebx' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[31:0]' },
|
||||
{ 'name':'ecx' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[31:0]' },
|
||||
{ 'name':'edx' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[31:0]' },
|
||||
{ 'name':'edi' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdi[31:0]' },
|
||||
{ 'name':'esi' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsi[31:0]' },
|
||||
{ 'name':'ebp' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbp[31:0]' },
|
||||
{ 'name':'esp' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsp[31:0]' },
|
||||
{ 'name':'r8d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r8[31:0]' },
|
||||
{ 'name':'r9d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r9[31:0]' },
|
||||
{ 'name':'r10d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r10[31:0]' },
|
||||
{ 'name':'r11d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r11[31:0]' },
|
||||
{ 'name':'r12d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r12[31:0]' },
|
||||
{ 'name':'r13d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r13[31:0]' },
|
||||
{ 'name':'r14d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r14[31:0]' },
|
||||
{ 'name':'r15d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r15[31:0]' },
|
||||
|
||||
{ 'name':'ax' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rax[15:0]' },
|
||||
{ 'name':'bx' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[15:0]' },
|
||||
{ 'name':'cx' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[15:0]' },
|
||||
{ 'name':'dx' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[15:0]' },
|
||||
{ 'name':'di' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdi[15:0]' },
|
||||
{ 'name':'si' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsi[15:0]' },
|
||||
{ 'name':'bp' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbp[15:0]' },
|
||||
{ 'name':'sp' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsp[15:0]' },
|
||||
{ 'name':'r8w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r8[15:0]' },
|
||||
{ 'name':'r9w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r9[15:0]' },
|
||||
{ 'name':'r10w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r10[15:0]' },
|
||||
{ 'name':'r11w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r11[15:0]' },
|
||||
{ 'name':'r12w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r12[15:0]' },
|
||||
{ 'name':'r13w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r13[15:0]' },
|
||||
{ 'name':'r14w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r14[15:0]' },
|
||||
{ 'name':'r15w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r15[15:0]' },
|
||||
|
||||
{ 'name':'ah' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rax[15:8]' },
|
||||
{ 'name':'bh' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[15:8]' },
|
||||
{ 'name':'ch' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[15:8]' },
|
||||
{ 'name':'dh' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[15:8]' },
|
||||
|
||||
{ 'name':'al' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rax[7:0]' },
|
||||
{ 'name':'bl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[7:0]' },
|
||||
{ 'name':'cl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[7:0]' },
|
||||
{ 'name':'dl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[7:0]' },
|
||||
{ 'name':'dil' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdi[7:0]' },
|
||||
{ 'name':'sil' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsi[7:0]' },
|
||||
{ 'name':'bpl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbp[7:0]' },
|
||||
{ 'name':'spl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsp[7:0]' },
|
||||
{ 'name':'r8l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r8[7:0]' },
|
||||
{ 'name':'r9l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r9[7:0]' },
|
||||
{ 'name':'r10l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r10[7:0]' },
|
||||
{ 'name':'r11l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r11[7:0]' },
|
||||
{ 'name':'r12l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r12[7:0]' },
|
||||
{ 'name':'r13l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r13[7:0]' },
|
||||
{ 'name':'r14l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r14[7:0]' },
|
||||
{ 'name':'r15l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r15[7:0]' },
|
||||
];
|
||||
|
||||
g_target_definition = None
|
||||
|
||||
def get_target_definition ():
|
||||
global g_target_definition
|
||||
if g_target_definition == None:
|
||||
g_target_definition = {}
|
||||
offset = 0
|
||||
for reg_info in x86_64_register_infos:
|
||||
reg_name = reg_info['name']
|
||||
|
||||
# Only fill in the offset if there is no 'slice' in the register info
|
||||
if 'slice' not in reg_info and 'composite' not in reg_info:
|
||||
reg_info['offset'] = offset
|
||||
offset += reg_info['bitsize']/8
|
||||
|
||||
# Set the GCC/DWARF register number for this register if it has one
|
||||
reg_num = get_reg_num(name_to_gcc_dwarf_regnum, reg_name)
|
||||
if reg_num != LLDB_INVALID_REGNUM:
|
||||
reg_info['gcc'] = reg_num
|
||||
reg_info['dwarf'] = reg_num
|
||||
|
||||
# Set the generic register number for this register if it has one
|
||||
reg_num = get_reg_num(name_to_generic_regnum, reg_name)
|
||||
if reg_num != LLDB_INVALID_REGNUM:
|
||||
reg_info['generic'] = reg_num
|
||||
|
||||
# Set the GDB register number for this register if it has one
|
||||
reg_num = get_reg_num(name_to_gdb_regnum, reg_name)
|
||||
if reg_num != LLDB_INVALID_REGNUM:
|
||||
reg_info['gdb'] = reg_num
|
||||
|
||||
g_target_definition['sets'] = ['General Purpose Registers', 'Floating Point Registers']
|
||||
g_target_definition['registers'] = x86_64_register_infos
|
||||
g_target_definition['host-info'] = { 'triple' : 'x86_64-*-linux', 'endian': eByteOrderLittle }
|
||||
g_target_definition['g-packet-size'] = offset
|
||||
g_target_definition['breakpoint-pc-offset'] = -1
|
||||
return g_target_definition
|
||||
|
||||
def get_dynamic_setting(target, setting_name):
|
||||
if setting_name == 'gdb-server-target-definition':
|
||||
return get_target_definition()
|
||||
357
external/bsd/llvm/dist/lldb/examples/python/x86_64_target_definition.py
vendored
Normal file
357
external/bsd/llvm/dist/lldb/examples/python/x86_64_target_definition.py
vendored
Normal file
@@ -0,0 +1,357 @@
|
||||
#!/usr/bin/python
|
||||
#===-- x86_64_target_definition.py -----------------------------*- C++ -*-===//
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
#===----------------------------------------------------------------------===//
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This file can be used with the following setting:
|
||||
# plugin.process.gdb-remote.target-definition-file
|
||||
# This setting should be used when you are trying to connect to a
|
||||
# remote GDB server that doesn't support any of the register discovery
|
||||
# packets that LLDB normally uses.
|
||||
#
|
||||
# Why is this necessary? LLDB doesn't require a new build of LLDB that
|
||||
# targets each new architecture you will debug with. Instead, all
|
||||
# architectures are supported and LLDB relies on extra GDB server
|
||||
# packets to discover the target we are connecting to so that is can
|
||||
# show the right registers for each target. This allows the GDB server
|
||||
# to change and add new registers without requiring a new LLDB build
|
||||
# just so we can see new registers.
|
||||
#
|
||||
# This file implements the x86_64 registers for the darwin version of
|
||||
# GDB and allows you to connect to servers that use this register set.
|
||||
#
|
||||
# USAGE
|
||||
#
|
||||
# (lldb) settings set plugin.process.gdb-remote.target-definition-file /path/to/x86_64_target_definition.py
|
||||
# (lldb) gdb-remote other.baz.com:1234
|
||||
#
|
||||
# The target definition file will get used if and only if the
|
||||
# qRegisterInfo packets are not supported when connecting to a remote
|
||||
# GDB server.
|
||||
#----------------------------------------------------------------------
|
||||
from lldb import *
|
||||
|
||||
# Compiler and DWARF register numbers
|
||||
name_to_gcc_dwarf_regnum = {
|
||||
'rax' : 0 ,
|
||||
'rdx' : 1 ,
|
||||
'rcx' : 2 ,
|
||||
'rbx' : 3 ,
|
||||
'rsi' : 4 ,
|
||||
'rdi' : 5 ,
|
||||
'rbp' : 6 ,
|
||||
'rsp' : 7 ,
|
||||
'r8' : 8 ,
|
||||
'r9' : 9 ,
|
||||
'r10' : 10,
|
||||
'r11' : 11,
|
||||
'r12' : 12,
|
||||
'r13' : 13,
|
||||
'r14' : 14,
|
||||
'r15' : 15,
|
||||
'rip' : 16,
|
||||
'xmm0' : 17,
|
||||
'xmm1' : 18,
|
||||
'xmm2' : 19,
|
||||
'xmm3' : 20,
|
||||
'xmm4' : 21,
|
||||
'xmm5' : 22,
|
||||
'xmm6' : 23,
|
||||
'xmm7' : 24,
|
||||
'xmm8' : 25,
|
||||
'xmm9' : 26,
|
||||
'xmm10' : 27,
|
||||
'xmm11' : 28,
|
||||
'xmm12' : 29,
|
||||
'xmm13' : 30,
|
||||
'xmm14' : 31,
|
||||
'xmm15' : 32,
|
||||
'stmm0' : 33,
|
||||
'stmm1' : 34,
|
||||
'stmm2' : 35,
|
||||
'stmm3' : 36,
|
||||
'stmm4' : 37,
|
||||
'stmm5' : 38,
|
||||
'stmm6' : 39,
|
||||
'stmm7' : 30,
|
||||
'ymm0' : 41,
|
||||
'ymm1' : 42,
|
||||
'ymm2' : 43,
|
||||
'ymm3' : 44,
|
||||
'ymm4' : 45,
|
||||
'ymm5' : 46,
|
||||
'ymm6' : 47,
|
||||
'ymm7' : 48,
|
||||
'ymm8' : 49,
|
||||
'ymm9' : 40,
|
||||
'ymm10' : 41,
|
||||
'ymm11' : 42,
|
||||
'ymm12' : 43,
|
||||
'ymm13' : 44,
|
||||
'ymm14' : 45,
|
||||
'ymm15' : 46
|
||||
};
|
||||
|
||||
name_to_gdb_regnum = {
|
||||
'rax' : 0,
|
||||
'rbx' : 1,
|
||||
'rcx' : 2,
|
||||
'rdx' : 3,
|
||||
'rsi' : 4,
|
||||
'rdi' : 5,
|
||||
'rbp' : 6,
|
||||
'rsp' : 7,
|
||||
'r8' : 8,
|
||||
'r9' : 9,
|
||||
'r10' : 10,
|
||||
'r11' : 11,
|
||||
'r12' : 12,
|
||||
'r13' : 13,
|
||||
'r14' : 14,
|
||||
'r15' : 15,
|
||||
'rip' : 16,
|
||||
'rflags': 17,
|
||||
'cs' : 18,
|
||||
'ss' : 19,
|
||||
'ds' : 20,
|
||||
'es' : 21,
|
||||
'fs' : 22,
|
||||
'gs' : 23,
|
||||
'stmm0' : 24,
|
||||
'stmm1' : 25,
|
||||
'stmm2' : 26,
|
||||
'stmm3' : 27,
|
||||
'stmm4' : 28,
|
||||
'stmm5' : 29,
|
||||
'stmm6' : 30,
|
||||
'stmm7' : 31,
|
||||
'fctrl' : 32,
|
||||
'fstat' : 33,
|
||||
'ftag' : 34,
|
||||
'fiseg' : 35,
|
||||
'fioff' : 36,
|
||||
'foseg' : 37,
|
||||
'fooff' : 38,
|
||||
'fop' : 39,
|
||||
'xmm0' : 40,
|
||||
'xmm1' : 41,
|
||||
'xmm2' : 42,
|
||||
'xmm3' : 43,
|
||||
'xmm4' : 44,
|
||||
'xmm5' : 45,
|
||||
'xmm6' : 46,
|
||||
'xmm7' : 47,
|
||||
'xmm8' : 48,
|
||||
'xmm9' : 49,
|
||||
'xmm10' : 50,
|
||||
'xmm11' : 51,
|
||||
'xmm12' : 52,
|
||||
'xmm13' : 53,
|
||||
'xmm14' : 54,
|
||||
'xmm15' : 55,
|
||||
'mxcsr' : 56,
|
||||
'ymm0' : 57,
|
||||
'ymm1' : 58,
|
||||
'ymm2' : 59,
|
||||
'ymm3' : 60,
|
||||
'ymm4' : 61,
|
||||
'ymm5' : 62,
|
||||
'ymm6' : 63,
|
||||
'ymm7' : 64,
|
||||
'ymm8' : 65,
|
||||
'ymm9' : 66,
|
||||
'ymm10' : 67,
|
||||
'ymm11' : 68,
|
||||
'ymm12' : 69,
|
||||
'ymm13' : 70,
|
||||
'ymm14' : 71,
|
||||
'ymm15' : 72
|
||||
};
|
||||
|
||||
name_to_generic_regnum = {
|
||||
'rip' : LLDB_REGNUM_GENERIC_PC,
|
||||
'rsp' : LLDB_REGNUM_GENERIC_SP,
|
||||
'rbp' : LLDB_REGNUM_GENERIC_FP,
|
||||
'rdi' : LLDB_REGNUM_GENERIC_ARG1,
|
||||
'rsi' : LLDB_REGNUM_GENERIC_ARG2,
|
||||
'rdx' : LLDB_REGNUM_GENERIC_ARG3,
|
||||
'rcx' : LLDB_REGNUM_GENERIC_ARG4,
|
||||
'r8' : LLDB_REGNUM_GENERIC_ARG5,
|
||||
'r9' : LLDB_REGNUM_GENERIC_ARG6
|
||||
};
|
||||
|
||||
|
||||
def get_reg_num (reg_num_dict, reg_name):
|
||||
if reg_name in reg_num_dict:
|
||||
return reg_num_dict[reg_name]
|
||||
return LLDB_INVALID_REGNUM
|
||||
|
||||
def get_reg_num (reg_num_dict, reg_name):
|
||||
if reg_name in reg_num_dict:
|
||||
return reg_num_dict[reg_name]
|
||||
return LLDB_INVALID_REGNUM
|
||||
|
||||
x86_64_register_infos = [
|
||||
{ 'name':'rax' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
|
||||
{ 'name':'rbx' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
|
||||
{ 'name':'rcx' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg4' },
|
||||
{ 'name':'rdx' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg3' },
|
||||
{ 'name':'rsi' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg2' },
|
||||
{ 'name':'rdi' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg1' },
|
||||
{ 'name':'rbp' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'fp' },
|
||||
{ 'name':'rsp' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'sp' },
|
||||
{ 'name':'r8' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg5' },
|
||||
{ 'name':'r9' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg6' },
|
||||
{ 'name':'r10' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
|
||||
{ 'name':'r11' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
|
||||
{ 'name':'r12' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
|
||||
{ 'name':'r13' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
|
||||
{ 'name':'r14' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
|
||||
{ 'name':'r15' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
|
||||
{ 'name':'rip' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'pc' },
|
||||
{ 'name':'rflags', 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'cs' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'ss' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'ds' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'es' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'fs' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'gs' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'stmm0' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'stmm1' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'stmm2' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'stmm3' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'stmm4' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'stmm5' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'stmm6' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'stmm7' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'fctrl' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'fstat' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'ftag' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'fiseg' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'fioff' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'foseg' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'fooff' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'fop' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
{ 'name':'xmm0' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm1' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm2' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm3' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm4' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm5' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm6' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm7' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm8' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm9' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm10' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm11' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm12' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm13' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm14' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'xmm15' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
|
||||
{ 'name':'mxcsr' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
|
||||
# Registers that are contained in or composed of one of more other registers
|
||||
{ 'name':'eax' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rax[31:0]' },
|
||||
{ 'name':'ebx' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[31:0]' },
|
||||
{ 'name':'ecx' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[31:0]' },
|
||||
{ 'name':'edx' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[31:0]' },
|
||||
{ 'name':'edi' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdi[31:0]' },
|
||||
{ 'name':'esi' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsi[31:0]' },
|
||||
{ 'name':'ebp' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbp[31:0]' },
|
||||
{ 'name':'esp' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsp[31:0]' },
|
||||
{ 'name':'r8d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r8[31:0]' },
|
||||
{ 'name':'r9d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r9[31:0]' },
|
||||
{ 'name':'r10d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r10[31:0]' },
|
||||
{ 'name':'r11d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r11[31:0]' },
|
||||
{ 'name':'r12d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r12[31:0]' },
|
||||
{ 'name':'r13d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r13[31:0]' },
|
||||
{ 'name':'r14d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r14[31:0]' },
|
||||
{ 'name':'r15d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r15[31:0]' },
|
||||
|
||||
{ 'name':'ax' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rax[15:0]' },
|
||||
{ 'name':'bx' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[15:0]' },
|
||||
{ 'name':'cx' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[15:0]' },
|
||||
{ 'name':'dx' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[15:0]' },
|
||||
{ 'name':'di' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdi[15:0]' },
|
||||
{ 'name':'si' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsi[15:0]' },
|
||||
{ 'name':'bp' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbp[15:0]' },
|
||||
{ 'name':'sp' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsp[15:0]' },
|
||||
{ 'name':'r8w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r8[15:0]' },
|
||||
{ 'name':'r9w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r9[15:0]' },
|
||||
{ 'name':'r10w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r10[15:0]' },
|
||||
{ 'name':'r11w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r11[15:0]' },
|
||||
{ 'name':'r12w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r12[15:0]' },
|
||||
{ 'name':'r13w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r13[15:0]' },
|
||||
{ 'name':'r14w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r14[15:0]' },
|
||||
{ 'name':'r15w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r15[15:0]' },
|
||||
|
||||
{ 'name':'ah' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rax[15:8]' },
|
||||
{ 'name':'bh' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[15:8]' },
|
||||
{ 'name':'ch' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[15:8]' },
|
||||
{ 'name':'dh' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[15:8]' },
|
||||
|
||||
{ 'name':'al' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rax[7:0]' },
|
||||
{ 'name':'bl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[7:0]' },
|
||||
{ 'name':'cl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[7:0]' },
|
||||
{ 'name':'dl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[7:0]' },
|
||||
{ 'name':'dil' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdi[7:0]' },
|
||||
{ 'name':'sil' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsi[7:0]' },
|
||||
{ 'name':'bpl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbp[7:0]' },
|
||||
{ 'name':'spl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsp[7:0]' },
|
||||
{ 'name':'r8l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r8[7:0]' },
|
||||
{ 'name':'r9l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r9[7:0]' },
|
||||
{ 'name':'r10l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r10[7:0]' },
|
||||
{ 'name':'r11l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r11[7:0]' },
|
||||
{ 'name':'r12l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r12[7:0]' },
|
||||
{ 'name':'r13l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r13[7:0]' },
|
||||
{ 'name':'r14l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r14[7:0]' },
|
||||
{ 'name':'r15l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r15[7:0]' },
|
||||
];
|
||||
|
||||
g_target_definition = None
|
||||
|
||||
def get_target_definition ():
|
||||
global g_target_definition
|
||||
if g_target_definition == None:
|
||||
g_target_definition = {}
|
||||
offset = 0
|
||||
for reg_info in x86_64_register_infos:
|
||||
reg_name = reg_info['name']
|
||||
|
||||
# Only fill in the offset if there is no 'slice' in the register info
|
||||
if 'slice' not in reg_info and 'composite' not in reg_info:
|
||||
reg_info['offset'] = offset
|
||||
|
||||
# Set the GCC/DWARF register number for this register if it has one
|
||||
reg_num = get_reg_num(name_to_gcc_dwarf_regnum, reg_name)
|
||||
if reg_num != LLDB_INVALID_REGNUM:
|
||||
reg_info['gcc'] = reg_num
|
||||
reg_info['dwarf'] = reg_num
|
||||
|
||||
# Set the generic register number for this register if it has one
|
||||
reg_num = get_reg_num(name_to_generic_regnum, reg_name)
|
||||
if reg_num != LLDB_INVALID_REGNUM:
|
||||
reg_info['generic'] = reg_num
|
||||
|
||||
# Set the GDB register number for this register if it has one
|
||||
reg_num = get_reg_num(name_to_gdb_regnum, reg_name)
|
||||
if reg_num != LLDB_INVALID_REGNUM:
|
||||
reg_info['gdb'] = reg_num
|
||||
|
||||
offset += reg_info['bitsize']/8
|
||||
g_target_definition['sets'] = ['General Purpose Registers', 'Floating Point Registers']
|
||||
g_target_definition['registers'] = x86_64_register_infos
|
||||
g_target_definition['host-info'] = { 'triple' : 'x86_64-apple-macosx', 'endian': eByteOrderLittle }
|
||||
g_target_definition['g-packet-size'] = offset
|
||||
return g_target_definition
|
||||
|
||||
def get_dynamic_setting(target, setting_name):
|
||||
if setting_name == 'gdb-server-target-definition':
|
||||
return get_target_definition()
|
||||
200
external/bsd/llvm/dist/lldb/examples/scripting/dictionary.c
vendored
Normal file
200
external/bsd/llvm/dist/lldb/examples/scripting/dictionary.c
vendored
Normal file
@@ -0,0 +1,200 @@
|
||||
//===-- dictionary.c ---------------------------------------------*- C -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct tree_node
|
||||
{
|
||||
const char *word;
|
||||
struct tree_node *left;
|
||||
struct tree_node *right;
|
||||
} tree_node;
|
||||
|
||||
/* Given a char*, returns a substring that starts at the first
|
||||
alphabet character and ends at the last alphabet character, i.e. it
|
||||
strips off beginning or ending quotes, punctuation, etc. */
|
||||
|
||||
char *
|
||||
strip (char **word)
|
||||
{
|
||||
char *start = *word;
|
||||
int len = strlen (start);
|
||||
char *end = start + len - 1;
|
||||
|
||||
while ((start < end) && (!isalpha (start[0])))
|
||||
start++;
|
||||
|
||||
while ((end > start) && (!isalpha (end[0])))
|
||||
end--;
|
||||
|
||||
if (start > end)
|
||||
return NULL;
|
||||
|
||||
end[1] = '\0';
|
||||
*word = start;
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
/* Given a binary search tree (sorted alphabetically by the word at
|
||||
each node), and a new word, inserts the word at the appropriate
|
||||
place in the tree. */
|
||||
|
||||
void
|
||||
insert (tree_node *root, char *word)
|
||||
{
|
||||
if (root == NULL)
|
||||
return;
|
||||
|
||||
int compare_value = strcmp (word, root->word);
|
||||
|
||||
if (compare_value == 0)
|
||||
return;
|
||||
|
||||
if (compare_value < 0)
|
||||
{
|
||||
if (root->left != NULL)
|
||||
insert (root->left, word);
|
||||
else
|
||||
{
|
||||
tree_node *new_node = (tree_node *) malloc (sizeof (tree_node));
|
||||
new_node->word = strdup (word);
|
||||
new_node->left = NULL;
|
||||
new_node->right = NULL;
|
||||
root->left = new_node;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (root->right != NULL)
|
||||
insert (root->right, word);
|
||||
else
|
||||
{
|
||||
tree_node *new_node = (tree_node *) malloc (sizeof (tree_node));
|
||||
new_node->word = strdup (word);
|
||||
new_node->left = NULL;
|
||||
new_node->right = NULL;
|
||||
root->right = new_node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Read in a text file and storea all the words from the file in a
|
||||
binary search tree. */
|
||||
|
||||
void
|
||||
populate_dictionary (tree_node **dictionary, char *filename)
|
||||
{
|
||||
FILE *in_file;
|
||||
char word[1024];
|
||||
|
||||
in_file = fopen (filename, "r");
|
||||
if (in_file)
|
||||
{
|
||||
while (fscanf (in_file, "%s", word) == 1)
|
||||
{
|
||||
char *new_word = (strdup (word));
|
||||
new_word = strip (&new_word);
|
||||
if (*dictionary == NULL)
|
||||
{
|
||||
tree_node *new_node = (tree_node *) malloc (sizeof (tree_node));
|
||||
new_node->word = new_word;
|
||||
new_node->left = NULL;
|
||||
new_node->right = NULL;
|
||||
*dictionary = new_node;
|
||||
}
|
||||
else
|
||||
insert (*dictionary, new_word);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Given a binary search tree and a word, search for the word
|
||||
in the binary search tree. */
|
||||
|
||||
int
|
||||
find_word (tree_node *dictionary, char *word)
|
||||
{
|
||||
if (!word || !dictionary)
|
||||
return 0;
|
||||
|
||||
int compare_value = strcmp (word, dictionary->word);
|
||||
|
||||
if (compare_value == 0)
|
||||
return 1;
|
||||
else if (compare_value < 0)
|
||||
return find_word (dictionary->left, word);
|
||||
else
|
||||
return find_word (dictionary->right, word);
|
||||
}
|
||||
|
||||
/* Print out the words in the binary search tree, in sorted order. */
|
||||
|
||||
void
|
||||
print_tree (tree_node *dictionary)
|
||||
{
|
||||
if (!dictionary)
|
||||
return;
|
||||
|
||||
if (dictionary->left)
|
||||
print_tree (dictionary->left);
|
||||
|
||||
printf ("%s\n", dictionary->word);
|
||||
|
||||
|
||||
if (dictionary->right)
|
||||
print_tree (dictionary->right);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
tree_node *dictionary = NULL;
|
||||
char buffer[1024];
|
||||
char *filename;
|
||||
int done = 0;
|
||||
|
||||
if (argc == 2)
|
||||
filename = argv[1];
|
||||
|
||||
if (!filename)
|
||||
return -1;
|
||||
|
||||
populate_dictionary (&dictionary, filename);
|
||||
fprintf (stdout, "Dictionary loaded.\nEnter search word: ");
|
||||
while (!done && fgets (buffer, sizeof(buffer), stdin))
|
||||
{
|
||||
char *word = buffer;
|
||||
int len = strlen (word);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; ++i)
|
||||
word[i] = tolower (word[i]);
|
||||
|
||||
if ((len > 0) && (word[len-1] == '\n'))
|
||||
{
|
||||
word[len-1] = '\0';
|
||||
len = len - 1;
|
||||
}
|
||||
|
||||
if (find_word (dictionary, word))
|
||||
fprintf (stdout, "Yes!\n");
|
||||
else
|
||||
fprintf (stdout, "No!\n");
|
||||
|
||||
fprintf (stdout, "Enter search word: ");
|
||||
}
|
||||
|
||||
fprintf (stdout, "\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
118
external/bsd/llvm/dist/lldb/examples/scripting/tree_utils.py
vendored
Executable file
118
external/bsd/llvm/dist/lldb/examples/scripting/tree_utils.py
vendored
Executable file
@@ -0,0 +1,118 @@
|
||||
"""
|
||||
# ===-- tree_utils.py ---------------------------------------*- Python -*-===//
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
# ===---------------------------------------------------------------------===//
|
||||
|
||||
tree_utils.py - A set of functions for examining binary
|
||||
search trees, based on the example search tree defined in
|
||||
dictionary.c. These functions contain calls to LLDB API
|
||||
functions, and assume that the LLDB Python module has been
|
||||
imported.
|
||||
|
||||
For a thorough explanation of how the DFS function works, and
|
||||
for more information about dictionary.c go to
|
||||
http://lldb.llvm.org/scripting.html
|
||||
"""
|
||||
|
||||
|
||||
def DFS (root, word, cur_path):
|
||||
"""
|
||||
Recursively traverse a binary search tree containing
|
||||
words sorted alphabetically, searching for a particular
|
||||
word in the tree. Also maintains a string representing
|
||||
the path from the root of the tree to the current node.
|
||||
If the word is found in the tree, return the path string.
|
||||
Otherwise return an empty string.
|
||||
|
||||
This function assumes the binary search tree is
|
||||
the one defined in dictionary.c It uses LLDB API
|
||||
functions to examine and traverse the tree nodes.
|
||||
"""
|
||||
|
||||
# Get pointer field values out of node 'root'
|
||||
|
||||
root_word_ptr = root.GetChildMemberWithName ("word")
|
||||
left_child_ptr = root.GetChildMemberWithName ("left")
|
||||
right_child_ptr = root.GetChildMemberWithName ("right")
|
||||
|
||||
# Get the word out of the word pointer and strip off
|
||||
# surrounding quotes (added by call to GetSummary).
|
||||
|
||||
root_word = root_word_ptr.GetSummary()
|
||||
end = len (root_word) - 1
|
||||
if root_word[0] == '"' and root_word[end] == '"':
|
||||
root_word = root_word[1:end]
|
||||
end = len (root_word) - 1
|
||||
if root_word[0] == '\'' and root_word[end] == '\'':
|
||||
root_word = root_word[1:end]
|
||||
|
||||
# Main depth first search
|
||||
|
||||
if root_word == word:
|
||||
return cur_path
|
||||
elif word < root_word:
|
||||
|
||||
# Check to see if left child is NULL
|
||||
|
||||
if left_child_ptr.GetValue() == None:
|
||||
return ""
|
||||
else:
|
||||
cur_path = cur_path + "L"
|
||||
return DFS (left_child_ptr, word, cur_path)
|
||||
else:
|
||||
|
||||
# Check to see if right child is NULL
|
||||
|
||||
if right_child_ptr.GetValue() == None:
|
||||
return ""
|
||||
else:
|
||||
cur_path = cur_path + "R"
|
||||
return DFS (right_child_ptr, word, cur_path)
|
||||
|
||||
|
||||
def tree_size (root):
|
||||
"""
|
||||
Recursively traverse a binary search tree, counting
|
||||
the nodes in the tree. Returns the final count.
|
||||
|
||||
This function assumes the binary search tree is
|
||||
the one defined in dictionary.c It uses LLDB API
|
||||
functions to examine and traverse the tree nodes.
|
||||
"""
|
||||
if (root.GetValue == None):
|
||||
return 0
|
||||
|
||||
if (int (root.GetValue(), 16) == 0):
|
||||
return 0
|
||||
|
||||
left_size = tree_size (root.GetChildAtIndex(1));
|
||||
right_size = tree_size (root.GetChildAtIndex(2));
|
||||
|
||||
total_size = left_size + right_size + 1
|
||||
return total_size
|
||||
|
||||
|
||||
def print_tree (root):
|
||||
"""
|
||||
Recursively traverse a binary search tree, printing out
|
||||
the words at the nodes in alphabetical order (the
|
||||
search order for the binary tree).
|
||||
|
||||
This function assumes the binary search tree is
|
||||
the one defined in dictionary.c It uses LLDB API
|
||||
functions to examine and traverse the tree nodes.
|
||||
"""
|
||||
if (root.GetChildAtIndex(1).GetValue() != None) and (int (root.GetChildAtIndex(1).GetValue(), 16) != 0):
|
||||
print_tree (root.GetChildAtIndex(1))
|
||||
|
||||
print root.GetChildAtIndex(0).GetSummary()
|
||||
|
||||
if (root.GetChildAtIndex(2).GetValue() != None) and (int (root.GetChildAtIndex(2).GetValue(), 16) != 0):
|
||||
print_tree (root.GetChildAtIndex(2))
|
||||
|
||||
|
||||
204
external/bsd/llvm/dist/lldb/examples/summaries/cocoa/CFArray.py
vendored
Normal file
204
external/bsd/llvm/dist/lldb/examples/summaries/cocoa/CFArray.py
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
"""
|
||||
LLDB AppKit formatters
|
||||
|
||||
part of The LLVM Compiler Infrastructure
|
||||
This file is distributed under the University of Illinois Open Source
|
||||
License. See LICENSE.TXT for details.
|
||||
"""
|
||||
# example summary provider for NSArray
|
||||
# the real summary is now C++ code built into LLDB
|
||||
import lldb
|
||||
import ctypes
|
||||
import lldb.runtime.objc.objc_runtime
|
||||
import lldb.formatters.metrics
|
||||
import lldb.formatters.Logger
|
||||
|
||||
statistics = lldb.formatters.metrics.Metrics()
|
||||
statistics.add_metric('invalid_isa')
|
||||
statistics.add_metric('invalid_pointer')
|
||||
statistics.add_metric('unknown_class')
|
||||
statistics.add_metric('code_notrun')
|
||||
|
||||
# much less functional than the other two cases below
|
||||
# just runs code to get to the count and then returns
|
||||
# no children
|
||||
class NSArrayKVC_SynthProvider:
|
||||
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def __init__(self, valobj, dict, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj;
|
||||
self.update()
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
|
||||
def num_children(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
stream = lldb.SBStream()
|
||||
self.valobj.GetExpressionPath(stream)
|
||||
num_children_vo = self.valobj.CreateValueFromExpression("count","(int)[" + stream.GetData() + " count]");
|
||||
if num_children_vo.IsValid():
|
||||
return num_children_vo.GetValueAsUnsigned(0)
|
||||
return "<variable is not NSArray>"
|
||||
|
||||
# much less functional than the other two cases below
|
||||
# just runs code to get to the count and then returns
|
||||
# no children
|
||||
class NSArrayCF_SynthProvider:
|
||||
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def __init__(self, valobj, dict, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj;
|
||||
self.sys_params = params
|
||||
if not (self.sys_params.types_cache.ulong):
|
||||
self.sys_params.types_cache.ulong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
|
||||
self.update()
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
|
||||
def num_children(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
num_children_vo = self.valobj.CreateChildAtOffset("count",
|
||||
self.sys_params.cfruntime_size,
|
||||
self.sys_params.types_cache.ulong)
|
||||
return num_children_vo.GetValueAsUnsigned(0)
|
||||
|
||||
class NSArrayI_SynthProvider:
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def __init__(self, valobj, dict, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj;
|
||||
self.sys_params = params
|
||||
if not(self.sys_params.types_cache.long):
|
||||
self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
|
||||
self.update()
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
|
||||
# skip the isa pointer and get at the size
|
||||
def num_children(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
count = self.valobj.CreateChildAtOffset("count",
|
||||
self.sys_params.pointer_size,
|
||||
self.sys_params.types_cache.long);
|
||||
return count.GetValueAsUnsigned(0)
|
||||
|
||||
class NSArrayM_SynthProvider:
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def __init__(self, valobj, dict, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj;
|
||||
self.sys_params = params
|
||||
if not(self.sys_params.types_cache.long):
|
||||
self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
|
||||
self.update()
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
|
||||
# skip the isa pointer and get at the size
|
||||
def num_children(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
count = self.valobj.CreateChildAtOffset("count",
|
||||
self.sys_params.pointer_size,
|
||||
self.sys_params.types_cache.long);
|
||||
return count.GetValueAsUnsigned(0)
|
||||
|
||||
# this is the actual synth provider, but is just a wrapper that checks
|
||||
# whether valobj is an instance of __NSArrayI or __NSArrayM and sets up an
|
||||
# appropriate backend layer to do the computations
|
||||
class NSArray_SynthProvider:
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def __init__(self, valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj;
|
||||
self.adjust_for_architecture()
|
||||
self.error = False
|
||||
self.wrapper = self.make_wrapper()
|
||||
self.invalid = (self.wrapper == None)
|
||||
|
||||
def num_children(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if self.wrapper == None:
|
||||
return 0;
|
||||
return self.wrapper.num_children()
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if self.wrapper == None:
|
||||
return
|
||||
self.wrapper.update()
|
||||
|
||||
# this code acts as our defense against NULL and unitialized
|
||||
# NSArray pointers, which makes it much longer than it would be otherwise
|
||||
def make_wrapper(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if self.valobj.GetValueAsUnsigned() == 0:
|
||||
self.error = True
|
||||
return lldb.runtime.objc.objc_runtime.InvalidPointer_Description(True)
|
||||
else:
|
||||
global statistics
|
||||
class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(self.valobj,statistics)
|
||||
if wrapper:
|
||||
self.error = True
|
||||
return wrapper
|
||||
|
||||
name_string = class_data.class_name()
|
||||
|
||||
logger >> "Class name is " + str(name_string)
|
||||
|
||||
if name_string == '__NSArrayI':
|
||||
wrapper = NSArrayI_SynthProvider(self.valobj, dict, class_data.sys_params)
|
||||
statistics.metric_hit('code_notrun',self.valobj.GetName())
|
||||
elif name_string == '__NSArrayM':
|
||||
wrapper = NSArrayM_SynthProvider(self.valobj, dict, class_data.sys_params)
|
||||
statistics.metric_hit('code_notrun',self.valobj.GetName())
|
||||
elif name_string == '__NSCFArray':
|
||||
wrapper = NSArrayCF_SynthProvider(self.valobj, dict, class_data.sys_params)
|
||||
statistics.metric_hit('code_notrun',self.valobj.GetName())
|
||||
else:
|
||||
wrapper = NSArrayKVC_SynthProvider(self.valobj, dict, class_data.sys_params)
|
||||
statistics.metric_hit('unknown_class',str(self.valobj.GetName()) + " seen as " + name_string)
|
||||
return wrapper;
|
||||
|
||||
def CFArray_SummaryProvider (valobj,dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
provider = NSArray_SynthProvider(valobj,dict);
|
||||
if provider.invalid == False:
|
||||
if provider.error == True:
|
||||
return provider.wrapper.message()
|
||||
try:
|
||||
summary = int(provider.num_children());
|
||||
except:
|
||||
summary = None
|
||||
logger >> "provider gave me " + str(summary)
|
||||
if summary == None:
|
||||
summary = '<variable is not NSArray>'
|
||||
elif isinstance(summary,basestring):
|
||||
pass
|
||||
else:
|
||||
# we format it like it were a CFString to make it look the same as the summary from Xcode
|
||||
summary = '@"' + str(summary) + (" objects" if summary != 1 else " object") + '"'
|
||||
return summary
|
||||
return 'Summary Unavailable'
|
||||
|
||||
def __lldb_init_module(debugger,dict):
|
||||
debugger.HandleCommand("type summary add -F CFArray.CFArray_SummaryProvider NSArray CFArrayRef CFMutableArrayRef")
|
||||
146
external/bsd/llvm/dist/lldb/examples/summaries/cocoa/CFBag.py
vendored
Normal file
146
external/bsd/llvm/dist/lldb/examples/summaries/cocoa/CFBag.py
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
"""
|
||||
LLDB AppKit formatters
|
||||
|
||||
part of The LLVM Compiler Infrastructure
|
||||
This file is distributed under the University of Illinois Open Source
|
||||
License. See LICENSE.TXT for details.
|
||||
"""
|
||||
# example summary provider for CFBag
|
||||
# the real summary is now C++ code built into LLDB
|
||||
import lldb
|
||||
import ctypes
|
||||
import lldb.runtime.objc.objc_runtime
|
||||
import lldb.formatters.metrics
|
||||
import lldb.formatters.Logger
|
||||
|
||||
statistics = lldb.formatters.metrics.Metrics()
|
||||
statistics.add_metric('invalid_isa')
|
||||
statistics.add_metric('invalid_pointer')
|
||||
statistics.add_metric('unknown_class')
|
||||
statistics.add_metric('code_notrun')
|
||||
|
||||
# despite the similary to synthetic children providers, these classes are not
|
||||
# trying to provide anything but the length for an CFBag, so they need not
|
||||
# obey the interface specification for synthetic children providers
|
||||
class CFBagRef_SummaryProvider:
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj;
|
||||
self.sys_params = params
|
||||
if not(self.sys_params.types_cache.NSUInteger):
|
||||
if self.sys_params.is_64_bit:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
|
||||
else:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
|
||||
self.update();
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
|
||||
# 12 bytes on i386
|
||||
# 20 bytes on x64
|
||||
# most probably 2 pointers and 4 bytes of data
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if self.sys_params.is_64_bit:
|
||||
return 20
|
||||
else:
|
||||
return 12
|
||||
|
||||
def length(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
size = self.valobj.CreateChildAtOffset("count",
|
||||
self.offset(),
|
||||
self.sys_params.types_cache.NSUInteger)
|
||||
return size.GetValueAsUnsigned(0)
|
||||
|
||||
|
||||
class CFBagUnknown_SummaryProvider:
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj;
|
||||
self.sys_params = params
|
||||
self.update();
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
|
||||
def length(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
stream = lldb.SBStream()
|
||||
self.valobj.GetExpressionPath(stream)
|
||||
num_children_vo = self.valobj.CreateValueFromExpression("count","(int)CFBagGetCount(" + stream.GetData() + " )")
|
||||
if num_children_vo.IsValid():
|
||||
return num_children_vo.GetValueAsUnsigned(0)
|
||||
return "<variable is not CFBag>"
|
||||
|
||||
|
||||
def GetSummary_Impl(valobj):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
global statistics
|
||||
class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
|
||||
if wrapper:
|
||||
return wrapper
|
||||
|
||||
name_string = class_data.class_name()
|
||||
actual_name = name_string
|
||||
|
||||
logger >> "name string got was " + str(name_string) + " but actual name is " + str(actual_name)
|
||||
|
||||
if class_data.is_cftype():
|
||||
# CFBag does not expose an actual NSWrapper type, so we have to check that this is
|
||||
# an NSCFType and then check we are a pointer-to __CFBag
|
||||
valobj_type = valobj.GetType()
|
||||
if valobj_type.IsValid() and valobj_type.IsPointerType():
|
||||
valobj_type = valobj_type.GetPointeeType()
|
||||
if valobj_type.IsValid():
|
||||
actual_name = valobj_type.GetName()
|
||||
if actual_name == '__CFBag' or \
|
||||
actual_name == 'const struct __CFBag':
|
||||
wrapper = CFBagRef_SummaryProvider(valobj, class_data.sys_params)
|
||||
statistics.metric_hit('code_notrun',valobj)
|
||||
return wrapper
|
||||
wrapper = CFBagUnknown_SummaryProvider(valobj, class_data.sys_params)
|
||||
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + actual_name)
|
||||
return wrapper;
|
||||
|
||||
def CFBag_SummaryProvider (valobj,dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
provider = GetSummary_Impl(valobj);
|
||||
if provider != None:
|
||||
if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
|
||||
return provider.message()
|
||||
try:
|
||||
summary = provider.length();
|
||||
except:
|
||||
summary = None
|
||||
logger >> "summary got from provider: " + str(summary)
|
||||
# for some reason, one needs to clear some bits for the count
|
||||
# to be correct when using CF(Mutable)BagRef on x64
|
||||
# the bit mask was derived through experimentation
|
||||
# (if counts start looking weird, then most probably
|
||||
# the mask needs to be changed)
|
||||
if summary == None:
|
||||
summary = '<variable is not CFBag>'
|
||||
elif isinstance(summary,basestring):
|
||||
pass
|
||||
else:
|
||||
if provider.sys_params.is_64_bit:
|
||||
summary = summary & ~0x1fff000000000000
|
||||
if summary == 1:
|
||||
summary = '@"1 value"'
|
||||
else:
|
||||
summary = '@"' + str(summary) + ' values"'
|
||||
return summary
|
||||
return 'Summary Unavailable'
|
||||
|
||||
def __lldb_init_module(debugger,dict):
|
||||
debugger.HandleCommand("type summary add -F CFBag.CFBag_SummaryProvider CFBagRef CFMutableBagRef")
|
||||
142
external/bsd/llvm/dist/lldb/examples/summaries/cocoa/CFBinaryHeap.py
vendored
Normal file
142
external/bsd/llvm/dist/lldb/examples/summaries/cocoa/CFBinaryHeap.py
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
"""
|
||||
LLDB AppKit formatters
|
||||
|
||||
part of The LLVM Compiler Infrastructure
|
||||
This file is distributed under the University of Illinois Open Source
|
||||
License. See LICENSE.TXT for details.
|
||||
"""
|
||||
# example summary provider for CFBinaryHeap
|
||||
# the real summary is now C++ code built into LLDB
|
||||
import lldb
|
||||
import ctypes
|
||||
import lldb.runtime.objc.objc_runtime
|
||||
import lldb.formatters.metrics
|
||||
import lldb.formatters.Logger
|
||||
|
||||
statistics = lldb.formatters.metrics.Metrics()
|
||||
statistics.add_metric('invalid_isa')
|
||||
statistics.add_metric('invalid_pointer')
|
||||
statistics.add_metric('unknown_class')
|
||||
statistics.add_metric('code_notrun')
|
||||
|
||||
# despite the similary to synthetic children providers, these classes are not
|
||||
# trying to provide anything but the length for an CFBinaryHeap, so they need not
|
||||
# obey the interface specification for synthetic children providers
|
||||
class CFBinaryHeapRef_SummaryProvider:
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj;
|
||||
self.sys_params = params
|
||||
if not(self.sys_params.types_cache.NSUInteger):
|
||||
if self.sys_params.is_64_bit:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
|
||||
else:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
|
||||
self.update();
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
|
||||
# 8 bytes on i386
|
||||
# 16 bytes on x64
|
||||
# most probably 2 pointers
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return 2 * self.sys_params.pointer_size
|
||||
|
||||
def length(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
size = self.valobj.CreateChildAtOffset("count",
|
||||
self.offset(),
|
||||
self.sys_params.types_cache.NSUInteger)
|
||||
return size.GetValueAsUnsigned(0)
|
||||
|
||||
|
||||
class CFBinaryHeapUnknown_SummaryProvider:
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj;
|
||||
self.sys_params = params
|
||||
self.update();
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
|
||||
def length(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
stream = lldb.SBStream()
|
||||
self.valobj.GetExpressionPath(stream)
|
||||
num_children_vo = self.valobj.CreateValueFromExpression("count","(int)CFBinaryHeapGetCount(" + stream.GetData() + " )");
|
||||
if num_children_vo.IsValid():
|
||||
return num_children_vo.GetValueAsUnsigned(0)
|
||||
return '<variable is not CFBinaryHeap>'
|
||||
|
||||
|
||||
def GetSummary_Impl(valobj):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
global statistics
|
||||
class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
|
||||
if wrapper:
|
||||
return wrapper
|
||||
|
||||
name_string = class_data.class_name()
|
||||
actual_name = class_data.class_name()
|
||||
|
||||
logger >> "name string got was " + str(name_string) + " but actual name is " + str(actual_name)
|
||||
|
||||
if class_data.is_cftype():
|
||||
# CFBinaryHeap does not expose an actual NSWrapper type, so we have to check that this is
|
||||
# an NSCFType and then check we are a pointer-to CFBinaryHeap
|
||||
valobj_type = valobj.GetType()
|
||||
if valobj_type.IsValid() and valobj_type.IsPointerType():
|
||||
valobj_type = valobj_type.GetPointeeType()
|
||||
if valobj_type.IsValid():
|
||||
actual_name = valobj_type.GetName()
|
||||
if actual_name == '__CFBinaryHeap':
|
||||
wrapper = CFBinaryHeapRef_SummaryProvider(valobj, class_data.sys_params)
|
||||
statistics.metric_hit('code_notrun',valobj)
|
||||
return wrapper
|
||||
wrapper = CFBinaryHeapUnknown_SummaryProvider(valobj, class_data.sys_params)
|
||||
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
|
||||
return wrapper;
|
||||
|
||||
def CFBinaryHeap_SummaryProvider (valobj,dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
provider = GetSummary_Impl(valobj);
|
||||
if provider != None:
|
||||
if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
|
||||
return provider.message()
|
||||
try:
|
||||
summary = provider.length();
|
||||
except:
|
||||
summary = None
|
||||
logger >> "summary got from provider: " + str(summary)
|
||||
# for some reason, one needs to clear some bits for the count
|
||||
# to be correct when using CF(Mutable)BagRef on x64
|
||||
# the bit mask was derived through experimentation
|
||||
# (if counts start looking weird, then most probably
|
||||
# the mask needs to be changed)
|
||||
if summary == None:
|
||||
summary = '<variable is not CFBinaryHeap>'
|
||||
elif isinstance(summary,basestring):
|
||||
pass
|
||||
else:
|
||||
if provider.sys_params.is_64_bit:
|
||||
summary = summary & ~0x1fff000000000000
|
||||
if summary == 1:
|
||||
return '@"1 item"'
|
||||
else:
|
||||
summary = '@"' + str(summary) + ' items"'
|
||||
return summary
|
||||
return 'Summary Unavailable'
|
||||
|
||||
def __lldb_init_module(debugger,dict):
|
||||
debugger.HandleCommand("type summary add -F CFBinaryHeap.CFBinaryHeap_SummaryProvider CFBinaryHeapRef")
|
||||
175
external/bsd/llvm/dist/lldb/examples/summaries/cocoa/CFBitVector.py
vendored
Normal file
175
external/bsd/llvm/dist/lldb/examples/summaries/cocoa/CFBitVector.py
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
"""
|
||||
LLDB AppKit formatters
|
||||
|
||||
part of The LLVM Compiler Infrastructure
|
||||
This file is distributed under the University of Illinois Open Source
|
||||
License. See LICENSE.TXT for details.
|
||||
"""
|
||||
# summary provider for CF(Mutable)BitVector
|
||||
import lldb
|
||||
import ctypes
|
||||
import lldb.runtime.objc.objc_runtime
|
||||
import lldb.formatters.metrics
|
||||
import lldb.formatters.Logger
|
||||
|
||||
# first define some utility functions
|
||||
def byte_index(abs_pos):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return abs_pos/8
|
||||
|
||||
def bit_index(abs_pos):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return abs_pos & 7
|
||||
|
||||
def get_bit(byte,index):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if index < 0 or index > 7:
|
||||
return None
|
||||
return (byte >> (7-index)) & 1
|
||||
|
||||
def grab_array_item_data(pointer,index):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return pointer.GetPointeeData(index,1)
|
||||
|
||||
statistics = lldb.formatters.metrics.Metrics()
|
||||
statistics.add_metric('invalid_isa')
|
||||
statistics.add_metric('invalid_pointer')
|
||||
statistics.add_metric('unknown_class')
|
||||
statistics.add_metric('code_notrun')
|
||||
|
||||
# despite the similary to synthetic children providers, these classes are not
|
||||
# trying to provide anything but a summary for a CF*BitVector, so they need not
|
||||
# obey the interface specification for synthetic children providers
|
||||
class CFBitVectorKnown_SummaryProvider:
|
||||
def adjust_for_architecture(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.uiint_size = self.sys_params.types_cache.NSUInteger.GetByteSize()
|
||||
pass
|
||||
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj;
|
||||
self.sys_params = params
|
||||
if not(self.sys_params.types_cache.NSUInteger):
|
||||
if self.sys_params.is_64_bit:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
|
||||
else:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
|
||||
if not(self.sys_params.types_cache.charptr):
|
||||
self.sys_params.types_cache.charptr = self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType()
|
||||
self.update();
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
|
||||
# we skip the CFRuntimeBase
|
||||
# then the next CFIndex is the count
|
||||
# then we skip another CFIndex and then we get at a byte array
|
||||
# that wraps the individual bits
|
||||
|
||||
def contents(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
count_vo = self.valobj.CreateChildAtOffset("count",self.sys_params.cfruntime_size,
|
||||
self.sys_params.types_cache.NSUInteger)
|
||||
count = count_vo.GetValueAsUnsigned(0)
|
||||
if count == 0:
|
||||
return '(empty)'
|
||||
|
||||
array_vo = self.valobj.CreateChildAtOffset("data",
|
||||
self.sys_params.cfruntime_size+2*self.uiint_size,
|
||||
self.sys_params.types_cache.charptr)
|
||||
|
||||
data_list = []
|
||||
cur_byte_pos = None
|
||||
for i in range(0,count):
|
||||
if cur_byte_pos == None:
|
||||
cur_byte_pos = byte_index(i)
|
||||
cur_byte = grab_array_item_data(array_vo,cur_byte_pos)
|
||||
cur_byte_val = cur_byte.uint8[0]
|
||||
else:
|
||||
byte_pos = byte_index(i)
|
||||
# do not fetch the pointee data every single time through
|
||||
if byte_pos != cur_byte_pos:
|
||||
cur_byte_pos = byte_pos
|
||||
cur_byte = grab_array_item_data(array_vo,cur_byte_pos)
|
||||
cur_byte_val = cur_byte.uint8[0]
|
||||
bit = get_bit(cur_byte_val,bit_index(i))
|
||||
if (i % 4) == 0:
|
||||
data_list.append(' ')
|
||||
if bit == 1:
|
||||
data_list.append('1')
|
||||
else:
|
||||
data_list.append('0')
|
||||
return ''.join(data_list)
|
||||
|
||||
|
||||
class CFBitVectorUnknown_SummaryProvider:
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj;
|
||||
self.sys_params = params
|
||||
self.update();
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
|
||||
def contents(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return '<unable to summarize this CFBitVector>'
|
||||
|
||||
|
||||
def GetSummary_Impl(valobj):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
global statistics
|
||||
class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
|
||||
if wrapper:
|
||||
return wrapper
|
||||
|
||||
name_string = class_data.class_name()
|
||||
actual_name = name_string
|
||||
|
||||
logger >> "name string got was " + str(name_string) + " but actual name is " + str(actual_name)
|
||||
|
||||
if class_data.is_cftype():
|
||||
# CFBitVectorRef does not expose an actual NSWrapper type, so we have to check that this is
|
||||
# an NSCFType and then check we are a pointer-to CFBitVectorRef
|
||||
valobj_type = valobj.GetType()
|
||||
if valobj_type.IsValid() and valobj_type.IsPointerType():
|
||||
valobj_type = valobj_type.GetPointeeType()
|
||||
if valobj_type.IsValid():
|
||||
actual_name = valobj_type.GetName()
|
||||
if actual_name == '__CFBitVector' or actual_name == '__CFMutableBitVector':
|
||||
wrapper = CFBitVectorKnown_SummaryProvider(valobj, class_data.sys_params)
|
||||
statistics.metric_hit('code_notrun',valobj)
|
||||
else:
|
||||
wrapper = CFBitVectorUnknown_SummaryProvider(valobj, class_data.sys_params)
|
||||
print actual_name
|
||||
else:
|
||||
wrapper = CFBitVectorUnknown_SummaryProvider(valobj, class_data.sys_params)
|
||||
print name_string
|
||||
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
|
||||
return wrapper;
|
||||
|
||||
def CFBitVector_SummaryProvider (valobj,dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
provider = GetSummary_Impl(valobj);
|
||||
if provider != None:
|
||||
if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
|
||||
return provider.message()
|
||||
try:
|
||||
summary = provider.contents();
|
||||
except:
|
||||
summary = None
|
||||
logger >> "summary got from provider: " + str(summary)
|
||||
if summary == None or summary == '':
|
||||
summary = '<variable is not CFBitVector>'
|
||||
return summary
|
||||
return 'Summary Unavailable'
|
||||
|
||||
def __lldb_init_module(debugger,dict):
|
||||
debugger.HandleCommand("type summary add -F CFBitVector.CFBitVector_SummaryProvider CFBitVectorRef CFMutableBitVectorRef")
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user