Browse Source

Initial commit (pstack v1.2)

tags/pstack-1.3
Thomas Preud'homme 8 years ago
commit
35824dbd12
8 changed files with 1194 additions and 0 deletions
  1. 1
    0
      .cvsignore
  2. 340
    0
      COPYING
  3. 49
    0
      Makefile
  4. 38
    0
      README
  5. 3
    0
      VERSION
  6. 61
    0
      man1/pstack.1
  7. 645
    0
      pstack.c
  8. 57
    0
      pstack.spec

+ 1
- 0
.cvsignore View File

@@ -0,0 +1 @@
1
+pstack

+ 340
- 0
COPYING View File

@@ -0,0 +1,340 @@
1
+		    GNU GENERAL PUBLIC LICENSE
2
+		       Version 2, June 1991
3
+
4
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
6
+ Everyone is permitted to copy and distribute verbatim copies
7
+ of this license document, but changing it is not allowed.
8
+
9
+			    Preamble
10
+
11
+  The licenses for most software are designed to take away your
12
+freedom to share and change it.  By contrast, the GNU General Public
13
+License is intended to guarantee your freedom to share and change free
14
+software--to make sure the software is free for all its users.  This
15
+General Public License applies to most of the Free Software
16
+Foundation's software and to any other program whose authors commit to
17
+using it.  (Some other Free Software Foundation software is covered by
18
+the GNU Library General Public License instead.)  You can apply it to
19
+your programs, too.
20
+
21
+  When we speak of free software, we are referring to freedom, not
22
+price.  Our General Public Licenses are designed to make sure that you
23
+have the freedom to distribute copies of free software (and charge for
24
+this service if you wish), that you receive source code or can get it
25
+if you want it, that you can change the software or use pieces of it
26
+in new free programs; and that you know you can do these things.
27
+
28
+  To protect your rights, we need to make restrictions that forbid
29
+anyone to deny you these rights or to ask you to surrender the rights.
30
+These restrictions translate to certain responsibilities for you if you
31
+distribute copies of the software, or if you modify it.
32
+
33
+  For example, if you distribute copies of such a program, whether
34
+gratis or for a fee, you must give the recipients all the rights that
35
+you have.  You must make sure that they, too, receive or can get the
36
+source code.  And you must show them these terms so they know their
37
+rights.
38
+
39
+  We protect your rights with two steps: (1) copyright the software, and
40
+(2) offer you this license which gives you legal permission to copy,
41
+distribute and/or modify the software.
42
+
43
+  Also, for each author's protection and ours, we want to make certain
44
+that everyone understands that there is no warranty for this free
45
+software.  If the software is modified by someone else and passed on, we
46
+want its recipients to know that what they have is not the original, so
47
+that any problems introduced by others will not reflect on the original
48
+authors' reputations.
49
+
50
+  Finally, any free program is threatened constantly by software
51
+patents.  We wish to avoid the danger that redistributors of a free
52
+program will individually obtain patent licenses, in effect making the
53
+program proprietary.  To prevent this, we have made it clear that any
54
+patent must be licensed for everyone's free use or not licensed at all.
55
+
56
+  The precise terms and conditions for copying, distribution and
57
+modification follow.
58
+
59
+		    GNU GENERAL PUBLIC LICENSE
60
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
+
62
+  0. This License applies to any program or other work which contains
63
+a notice placed by the copyright holder saying it may be distributed
64
+under the terms of this General Public License.  The "Program", below,
65
+refers to any such program or work, and a "work based on the Program"
66
+means either the Program or any derivative work under copyright law:
67
+that is to say, a work containing the Program or a portion of it,
68
+either verbatim or with modifications and/or translated into another
69
+language.  (Hereinafter, translation is included without limitation in
70
+the term "modification".)  Each licensee is addressed as "you".
71
+
72
+Activities other than copying, distribution and modification are not
73
+covered by this License; they are outside its scope.  The act of
74
+running the Program is not restricted, and the output from the Program
75
+is covered only if its contents constitute a work based on the
76
+Program (independent of having been made by running the Program).
77
+Whether that is true depends on what the Program does.
78
+
79
+  1. You may copy and distribute verbatim copies of the Program's
80
+source code as you receive it, in any medium, provided that you
81
+conspicuously and appropriately publish on each copy an appropriate
82
+copyright notice and disclaimer of warranty; keep intact all the
83
+notices that refer to this License and to the absence of any warranty;
84
+and give any other recipients of the Program a copy of this License
85
+along with the Program.
86
+
87
+You may charge a fee for the physical act of transferring a copy, and
88
+you may at your option offer warranty protection in exchange for a fee.
89
+
90
+  2. You may modify your copy or copies of the Program or any portion
91
+of it, thus forming a work based on the Program, and copy and
92
+distribute such modifications or work under the terms of Section 1
93
+above, provided that you also meet all of these conditions:
94
+
95
+    a) You must cause the modified files to carry prominent notices
96
+    stating that you changed the files and the date of any change.
97
+
98
+    b) You must cause any work that you distribute or publish, that in
99
+    whole or in part contains or is derived from the Program or any
100
+    part thereof, to be licensed as a whole at no charge to all third
101
+    parties under the terms of this License.
102
+
103
+    c) If the modified program normally reads commands interactively
104
+    when run, you must cause it, when started running for such
105
+    interactive use in the most ordinary way, to print or display an
106
+    announcement including an appropriate copyright notice and a
107
+    notice that there is no warranty (or else, saying that you provide
108
+    a warranty) and that users may redistribute the program under
109
+    these conditions, and telling the user how to view a copy of this
110
+    License.  (Exception: if the Program itself is interactive but
111
+    does not normally print such an announcement, your work based on
112
+    the Program is not required to print an announcement.)
113
+
114
+These requirements apply to the modified work as a whole.  If
115
+identifiable sections of that work are not derived from the Program,
116
+and can be reasonably considered independent and separate works in
117
+themselves, then this License, and its terms, do not apply to those
118
+sections when you distribute them as separate works.  But when you
119
+distribute the same sections as part of a whole which is a work based
120
+on the Program, the distribution of the whole must be on the terms of
121
+this License, whose permissions for other licensees extend to the
122
+entire whole, and thus to each and every part regardless of who wrote it.
123
+
124
+Thus, it is not the intent of this section to claim rights or contest
125
+your rights to work written entirely by you; rather, the intent is to
126
+exercise the right to control the distribution of derivative or
127
+collective works based on the Program.
128
+
129
+In addition, mere aggregation of another work not based on the Program
130
+with the Program (or with a work based on the Program) on a volume of
131
+a storage or distribution medium does not bring the other work under
132
+the scope of this License.
133
+
134
+  3. You may copy and distribute the Program (or a work based on it,
135
+under Section 2) in object code or executable form under the terms of
136
+Sections 1 and 2 above provided that you also do one of the following:
137
+
138
+    a) Accompany it with the complete corresponding machine-readable
139
+    source code, which must be distributed under the terms of Sections
140
+    1 and 2 above on a medium customarily used for software interchange; or,
141
+
142
+    b) Accompany it with a written offer, valid for at least three
143
+    years, to give any third party, for a charge no more than your
144
+    cost of physically performing source distribution, a complete
145
+    machine-readable copy of the corresponding source code, to be
146
+    distributed under the terms of Sections 1 and 2 above on a medium
147
+    customarily used for software interchange; or,
148
+
149
+    c) Accompany it with the information you received as to the offer
150
+    to distribute corresponding source code.  (This alternative is
151
+    allowed only for noncommercial distribution and only if you
152
+    received the program in object code or executable form with such
153
+    an offer, in accord with Subsection b above.)
154
+
155
+The source code for a work means the preferred form of the work for
156
+making modifications to it.  For an executable work, complete source
157
+code means all the source code for all modules it contains, plus any
158
+associated interface definition files, plus the scripts used to
159
+control compilation and installation of the executable.  However, as a
160
+special exception, the source code distributed need not include
161
+anything that is normally distributed (in either source or binary
162
+form) with the major components (compiler, kernel, and so on) of the
163
+operating system on which the executable runs, unless that component
164
+itself accompanies the executable.
165
+
166
+If distribution of executable or object code is made by offering
167
+access to copy from a designated place, then offering equivalent
168
+access to copy the source code from the same place counts as
169
+distribution of the source code, even though third parties are not
170
+compelled to copy the source along with the object code.
171
+
172
+  4. You may not copy, modify, sublicense, or distribute the Program
173
+except as expressly provided under this License.  Any attempt
174
+otherwise to copy, modify, sublicense or distribute the Program is
175
+void, and will automatically terminate your rights under this License.
176
+However, parties who have received copies, or rights, from you under
177
+this License will not have their licenses terminated so long as such
178
+parties remain in full compliance.
179
+
180
+  5. You are not required to accept this License, since you have not
181
+signed it.  However, nothing else grants you permission to modify or
182
+distribute the Program or its derivative works.  These actions are
183
+prohibited by law if you do not accept this License.  Therefore, by
184
+modifying or distributing the Program (or any work based on the
185
+Program), you indicate your acceptance of this License to do so, and
186
+all its terms and conditions for copying, distributing or modifying
187
+the Program or works based on it.
188
+
189
+  6. Each time you redistribute the Program (or any work based on the
190
+Program), the recipient automatically receives a license from the
191
+original licensor to copy, distribute or modify the Program subject to
192
+these terms and conditions.  You may not impose any further
193
+restrictions on the recipients' exercise of the rights granted herein.
194
+You are not responsible for enforcing compliance by third parties to
195
+this License.
196
+
197
+  7. If, as a consequence of a court judgment or allegation of patent
198
+infringement or for any other reason (not limited to patent issues),
199
+conditions are imposed on you (whether by court order, agreement or
200
+otherwise) that contradict the conditions of this License, they do not
201
+excuse you from the conditions of this License.  If you cannot
202
+distribute so as to satisfy simultaneously your obligations under this
203
+License and any other pertinent obligations, then as a consequence you
204
+may not distribute the Program at all.  For example, if a patent
205
+license would not permit royalty-free redistribution of the Program by
206
+all those who receive copies directly or indirectly through you, then
207
+the only way you could satisfy both it and this License would be to
208
+refrain entirely from distribution of the Program.
209
+
210
+If any portion of this section is held invalid or unenforceable under
211
+any particular circumstance, the balance of the section is intended to
212
+apply and the section as a whole is intended to apply in other
213
+circumstances.
214
+
215
+It is not the purpose of this section to induce you to infringe any
216
+patents or other property right claims or to contest validity of any
217
+such claims; this section has the sole purpose of protecting the
218
+integrity of the free software distribution system, which is
219
+implemented by public license practices.  Many people have made
220
+generous contributions to the wide range of software distributed
221
+through that system in reliance on consistent application of that
222
+system; it is up to the author/donor to decide if he or she is willing
223
+to distribute software through any other system and a licensee cannot
224
+impose that choice.
225
+
226
+This section is intended to make thoroughly clear what is believed to
227
+be a consequence of the rest of this License.
228
+
229
+  8. If the distribution and/or use of the Program is restricted in
230
+certain countries either by patents or by copyrighted interfaces, the
231
+original copyright holder who places the Program under this License
232
+may add an explicit geographical distribution limitation excluding
233
+those countries, so that distribution is permitted only in or among
234
+countries not thus excluded.  In such case, this License incorporates
235
+the limitation as if written in the body of this License.
236
+
237
+  9. The Free Software Foundation may publish revised and/or new versions
238
+of the General Public License from time to time.  Such new versions will
239
+be similar in spirit to the present version, but may differ in detail to
240
+address new problems or concerns.
241
+
242
+Each version is given a distinguishing version number.  If the Program
243
+specifies a version number of this License which applies to it and "any
244
+later version", you have the option of following the terms and conditions
245
+either of that version or of any later version published by the Free
246
+Software Foundation.  If the Program does not specify a version number of
247
+this License, you may choose any version ever published by the Free Software
248
+Foundation.
249
+
250
+  10. If you wish to incorporate parts of the Program into other free
251
+programs whose distribution conditions are different, write to the author
252
+to ask for permission.  For software which is copyrighted by the Free
253
+Software Foundation, write to the Free Software Foundation; we sometimes
254
+make exceptions for this.  Our decision will be guided by the two goals
255
+of preserving the free status of all derivatives of our free software and
256
+of promoting the sharing and reuse of software generally.
257
+
258
+			    NO WARRANTY
259
+
260
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
262
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
266
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
267
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268
+REPAIR OR CORRECTION.
269
+
270
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278
+POSSIBILITY OF SUCH DAMAGES.
279
+
280
+		     END OF TERMS AND CONDITIONS
281
+
282
+	    How to Apply These Terms to Your New Programs
283
+
284
+  If you develop a new program, and you want it to be of the greatest
285
+possible use to the public, the best way to achieve this is to make it
286
+free software which everyone can redistribute and change under these terms.
287
+
288
+  To do so, attach the following notices to the program.  It is safest
289
+to attach them to the start of each source file to most effectively
290
+convey the exclusion of warranty; and each file should have at least
291
+the "copyright" line and a pointer to where the full notice is found.
292
+
293
+    <one line to give the program's name and a brief idea of what it does.>
294
+    Copyright (C) 19yy  <name of author>
295
+
296
+    This program is free software; you can redistribute it and/or modify
297
+    it under the terms of the GNU General Public License as published by
298
+    the Free Software Foundation; either version 2 of the License, or
299
+    (at your option) any later version.
300
+
301
+    This program is distributed in the hope that it will be useful,
302
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
303
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
304
+    GNU General Public License for more details.
305
+
306
+    You should have received a copy of the GNU General Public License
307
+    along with this program; if not, write to the Free Software
308
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
309
+
310
+
311
+Also add information on how to contact you by electronic and paper mail.
312
+
313
+If the program is interactive, make it output a short notice like this
314
+when it starts in an interactive mode:
315
+
316
+    Gnomovision version 69, Copyright (C) 19yy name of author
317
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
318
+    This is free software, and you are welcome to redistribute it
319
+    under certain conditions; type `show c' for details.
320
+
321
+The hypothetical commands `show w' and `show c' should show the appropriate
322
+parts of the General Public License.  Of course, the commands you use may
323
+be called something other than `show w' and `show c'; they could even be
324
+mouse-clicks or menu items--whatever suits your program.
325
+
326
+You should also get your employer (if you work as a programmer) or your
327
+school, if any, to sign a "copyright disclaimer" for the program, if
328
+necessary.  Here is a sample; alter the names:
329
+
330
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
331
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
332
+
333
+  <signature of Ty Coon>, 1 April 1989
334
+  Ty Coon, President of Vice
335
+
336
+This General Public License does not permit incorporating your program into
337
+proprietary programs.  If your program is a subroutine library, you may
338
+consider it more useful to permit linking proprietary applications with the
339
+library.  If this is what you want to do, use the GNU Library General
340
+Public License instead of this License.

+ 49
- 0
Makefile View File

@@ -0,0 +1,49 @@
1
+#
2
+# This file is free software; you can redistribute it and/or modify
3
+# it under the terms of the GNU General Public License as published by
4
+# the Free Software Foundation; either version 2 of the License, or
5
+# (at your option) any later version.
6
+# 
7
+# This program is distributed in the hope that it will be useful,
8
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
+# GNU General Public License for more details.
11
+# 
12
+# You should have received a copy of the GNU General Public License
13
+# along with this program; if not, write to the Free Software
14
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15
+#
16
+
17
+VERSION = $(shell awk '/Version:/ { print $$2 }' pstack.spec)
18
+CVSTAG = r$(subst .,-,$(VERSION))
19
+
20
+CFLAGS = -Wall -DVERSION=\"$(VERSION)\" $(RPM_OPT_FLAGS)
21
+
22
+ifeq ($(RPM_OPT_FLAGS),)
23
+CFLAGS += -g
24
+LDFLAGS += -g
25
+endif
26
+
27
+pstack : pstack.c
28
+	$(CC) $(CFLAGS) -o pstack pstack.c
29
+
30
+clean:
31
+	rm pstack
32
+
33
+install : pstack
34
+	mkdir -p $(BINDIR)
35
+	install -m 755 pstack $(BINDIR)
36
+	mkdir -p $(MANDIR)/man1
37
+	install -m 644 man1/pstack.1 $(MANDIR)/man1
38
+
39
+cvstag:
40
+	cvs tag -F $(CVSTAG) .
41
+
42
+archive: cvstag
43
+	@rm -rf /tmp/pstack-$(VERSION) /tmp/pstack
44
+	@cd /tmp; cvs export -r$(CVSTAG) pstack; mv pstack pstack-$(VERSION)
45
+	@cd /tmp; tar czSpf pstack-$(VERSION).tar.gz pstack-$(VERSION)
46
+	@rm -rf /tmp/pstack-$(VERSION)
47
+	@cp /tmp/pstack-$(VERSION).tar.gz .
48
+	@echo " "
49
+	@echo "The final archive is ./pstack-$(VERSION).tar.gz."

+ 38
- 0
README View File

@@ -0,0 +1,38 @@
1
+pstack - print stack trace of running processes
2
+
3
+pstack dumps a stack trace for a process, given the pid of that
4
+process.  If the process named is part of a thread group, then all the threads
5
+inthe group are traced.  See the man page for more information.
6
+
7
+This program was inspired by the 'pstack' program available on Solaris.
8
+
9
+SUPPORTED PLATFORMS:
10
+	This program runs on 32 bit x86 machines, using ELF binaries
11
+generated from GNU compilers.  If threads are being used, it depends
12
+on a debuggable version of the pthreads library to find the threads in
13
+the thread group.  If anyone wants to port this to other
14
+architectures, please let me know about questions you may have, or
15
+achievements you have made.  I'd like to incorporate such changes into
16
+my version of the code.
17
+
18
+FEATURES:
19
+	symbolic address dumping
20
+  thread group support
21
+
22
+BUILD:
23
+   make
24
+
25
+INSTALL:
26
+	 make install
27
+
28
+UNINSTALL:
29
+   make uninstall
30
+
31
+NOTE: you must be root to [un]install.  pstack will run fine from any
32
+directory, install just puts the binary and man page in 'normal'
33
+places (/usr/local/...)
34
+
35
+USAGE:
36
+	pstack pid [...]
37
+
38
+See the man page for more details.

+ 3
- 0
VERSION View File

@@ -0,0 +1,3 @@
1
+1.0 12/Oct/1999 07:20:09 PDT
2
+1.1 25/Feb/2002
3
+1.2 12/Nov/2003

+ 61
- 0
man1/pstack.1 View File

@@ -0,0 +1,61 @@
1
+.\"
2
+.\" pstack manual page.
3
+.\" Copyright (c) 1999 Ross Thompson
4
+.\" Copyright (c) 2001, 2002 Red Hat, Inc.
5
+.\"
6
+.\" Original author: Ross Thompson <ross@whatsis.com>
7
+.\"
8
+.\" This program is free software; you can redistribute it and/or modify
9
+.\" it under the terms of the GNU General Public License as published by
10
+.\" the Free Software Foundation; either version 2, or (at your option)
11
+.\" any later version.
12
+.\"
13
+.\" This program is distributed in the hope that it will be useful,
14
+.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+.\" GNU General Public License for more details.
17
+.\"
18
+.\" You should have received a copy of the GNU General Public License
19
+.\" along with this program; see the file COPYING.  If not, write to
20
+.\" the Free Software Foundation, 59 Temple Place - Suite 330,
21
+.\" Boston, MA 02111-1307, USA.
22
+.\"
23
+.TH PSTACK 1 "Feb 25 2002" "Red Hat Linux" "Linux Programmer's Manual"
24
+
25
+.SH NAME
26
+pstack \- print a stack trace of running processes
27
+
28
+.SH SYNOPSIS
29
+.B pstack
30
+pid [...]
31
+
32
+.SH DESCRIPTION
33
+
34
+\f3pstack\f1 attaches to the active processes named by the \f3pid\f1s
35
+on the command line, and prints out an execution stack trace,
36
+including a hint at what the function arguments are.  If symbols exist
37
+in the binary (usually the case unless you have run strip(1)), then
38
+symbolic addresses are printed as well.
39
+
40
+If the process is part of a thread group, then \f3pstack\f1 will print
41
+out a stack trace for each of the threads in the group.
42
+
43
+.SH RESTRICTIONS
44
+
45
+\f3pstack\f1 currently works only on Linux, only on an x86 machine
46
+running 32 bit ELF binaries (64 bit not supported).  Also, for
47
+symbolic information, you need to use a GNU compiler to generate your
48
+program, and you can't strip symbols from the binaries.  For thread
49
+information to be dumped, you have to use the debug-aware version of
50
+the LinuxThreads libpthread.so library.
51
+(To check, run nm(1) on your pthreads library, and make sure that the
52
+symbol "__pthread_threads_debug" is defined.)
53
+Threads are not supported with the newer NPTL libpthread.so library.
54
+
55
+.SH SEE ALSO
56
+nm(1), ptrace(2)
57
+
58
+.SH AUTHORS
59
+Ross Thompson <ross@whatsis.com>
60
+
61
+Red Hat, Inc. <http://bugzilla.redhat.com/bugzilla>

+ 645
- 0
pstack.c View File

@@ -0,0 +1,645 @@
1
+/*
2
+ pstack.c -- asynchronous stack trace of a running process
3
+ Copyright (c) 1999 Ross Thompson
4
+ Copyright (c) 2001, 2003 Red Hat, Inc.
5
+
6
+ Original Author: Ross Thompson <ross@whatsis.com>
7
+ Critical bug fix: Tim Waugh
8
+
9
+*/
10
+
11
+/*
12
+ This file is free software; you can redistribute it and/or modify
13
+ it under the terms of the GNU General Public License as published by
14
+ the Free Software Foundation; either version 2 of the License, or
15
+ (at your option) any later version.
16
+
17
+ This program is distributed in the hope that it will be useful,
18
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
+ GNU General Public License for more details.
21
+
22
+ You should have received a copy of the GNU General Public License
23
+ along with this program; if not, write to the Free Software
24
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25
+*/
26
+
27
+/* RESTRICTIONS:
28
+
29
+   pstack currently works only on Linux, only on an x86 machine running
30
+   32 bit ELF binaries (64 bit not supported).  Also, for symbolic
31
+   information, you need to use a GNU compiler to generate your
32
+   program, and you can't strip symbols from the binaries.  For thread
33
+   information to be dumped, you have to use the debug-aware version
34
+   of libpthread.so.  (To check, run 'nm' on your libpthread.so, and
35
+   make sure that the symbol "__pthread_threads_debug" is defined.)
36
+*/
37
+
38
+#include <sys/ptrace.h>
39
+#include <asm/ptrace.h>
40
+#include <sys/types.h>
41
+#include <sys/stat.h>
42
+#include <sys/wait.h>
43
+
44
+#include <fcntl.h>
45
+#include <link.h>
46
+#include <malloc.h>
47
+#include <string.h>
48
+#include <unistd.h>
49
+#include <stdlib.h>
50
+#include <stdio.h>
51
+#include <errno.h>
52
+
53
+static int thePid; /* pid requested by caller. */
54
+static struct {
55
+  int found;
56
+  int *pids; /* pid[0] is dad, pid[1] is manager */
57
+  int *attached; /* pid[i] is attached? 1 = yes, 0 = no */
58
+  int npids;
59
+} threads;
60
+
61
+/* ------------------------------ */
62
+
63
+static int attach(int pid)
64
+{
65
+  int status;
66
+
67
+  errno = 0;
68
+  ptrace(PTRACE_ATTACH, pid, 0, 0);
69
+
70
+  if (errno)
71
+    return errno;
72
+
73
+  waitpid (pid, &status, WUNTRACED);
74
+
75
+  /* If we failed due to an ECHILD, then retry with the __WCLONE
76
+     flag.  Note we loop as the the PID we get back may not be
77
+     one we care about.  */
78
+  if (errno == ECHILD) {
79
+    int x;
80
+
81
+    errno = 0;
82
+    while (1) {
83
+      x = waitpid (-1, &status, (__WCLONE));
84
+
85
+      if (x == pid || x < 0 || errno != 0) break;
86
+    }
87
+  }
88
+
89
+  return errno;
90
+}
91
+
92
+static int detachall(void)
93
+{
94
+  int i;
95
+
96
+  /* First detach from all the threads, except the one we initially
97
+     attached to.  Note that the PTRACE_DETACH will continue the
98
+     thread, so there is no need to issue a separate PTRACE_CONTINUE
99
+     call.  */
100
+  if (threads.found) {
101
+    for (i = 0; i < threads.npids; i++) {
102
+      if (threads.pids[i] != thePid && threads.attached[i]) {
103
+        errno = 0;
104
+        ptrace(PTRACE_DETACH, threads.pids[i], 0, 0);
105
+        if (errno) perror("detach");
106
+      }
107
+    }
108
+  }
109
+
110
+  /* Now attach from the thread we initially attached to.  Note that
111
+     the PTRACE_DETACH will continue the thread, so there is no need
112
+     is issue a separate PTRACE_CONTINUE call.  */
113
+  ptrace(PTRACE_DETACH, thePid, 0, 0);
114
+
115
+  return errno;
116
+}
117
+
118
+static void handle_signal (int signum)
119
+{
120
+  signal (signum, SIG_DFL);
121
+  psignal (signum, "pstack signal received");
122
+  if (thePid) detachall();
123
+  exit (1);
124
+}
125
+
126
+static void quit(char *msg)
127
+{
128
+  fputs(msg, stderr);
129
+  fputc('\n', stderr);
130
+  if (thePid) detachall();
131
+  exit(1);
132
+}
133
+
134
+/* ------------------------------ */
135
+
136
+static Elf32_Addr DebugInfo;
137
+
138
+typedef struct _t_Symbols {
139
+  struct _t_Symbols *next;
140
+  char *name;
141
+  Elf32_Sym *symbols;
142
+  int nsyms;
143
+  char *strings;
144
+  int strslen, noffsets;
145
+  Elf32_Addr baseAddr;
146
+  Elf32_Dyn *dynamic;
147
+  int ndyns;
148
+} *Symbols;
149
+
150
+static Symbols allSyms;
151
+
152
+static Symbols newSyms(const char *name)
153
+{
154
+  Symbols syms = (Symbols) calloc(sizeof(struct _t_Symbols), 1);
155
+
156
+  if (!syms) quit("Out of memory");
157
+  syms->next = allSyms;
158
+  allSyms = syms;
159
+  syms->name = strdup(name);
160
+
161
+  return syms;
162
+}
163
+
164
+static void deleteSyms(Symbols syms)
165
+{
166
+  Symbols s2;
167
+
168
+  if (syms == allSyms) allSyms = syms->next;
169
+  else {
170
+    for (s2 = allSyms; s2 && s2->next != syms; s2 = s2->next);
171
+    if (s2) s2->next = syms->next;
172
+  }
173
+  if (syms->symbols) free(syms->symbols);
174
+  if (syms->strings) free(syms->strings);
175
+  if (syms->dynamic) free(syms->dynamic);
176
+  if (syms->name)    free(syms->name);
177
+  free(syms);
178
+}
179
+
180
+static const Elf32_Sym *lookupSymInTable(const char *name, Symbols syms)
181
+{
182
+  Elf32_Sym *sym;
183
+  int i;
184
+
185
+  for (i = 0, sym = syms->symbols; i < syms->nsyms; i++, sym++) {
186
+    if (!strcmp(name, &syms->strings[sym->st_name]))
187
+      return sym;
188
+  }
189
+
190
+  return 0;
191
+}
192
+
193
+static void findCodeAddress(Elf32_Addr addr, Elf32_Sym **ans,
194
+                            Symbols *symtab)
195
+{
196
+  Elf32_Sym *sym;
197
+  Symbols tab;
198
+  int i;
199
+
200
+  for (tab = allSyms, *ans = 0, *symtab = 0; tab; tab = tab->next) {
201
+    if (addr < tab->baseAddr) continue;
202
+    for (sym = tab->symbols, i = 0; i < tab->nsyms; i++, sym++) {
203
+      if (sym->st_value <= addr && sym->st_shndx != SHN_UNDEF &&
204
+          sym->st_shndx < tab->noffsets &&
205
+          ELF32_ST_TYPE(sym->st_info) == STT_FUNC &&
206
+          (!*ans || (*ans)->st_value < sym->st_value))
207
+        *ans = sym, *symtab = tab;
208
+    }
209
+  }
210
+}
211
+
212
+/* ------------------------------ */
213
+
214
+static void resetData(void)
215
+{
216
+  Symbols syms, ns;
217
+
218
+  if (threads.pids) free(threads.pids);
219
+  if (threads.attached) free(threads.attached);
220
+  threads.pids = 0;
221
+  threads.attached = 0;
222
+  threads.found = 0;
223
+
224
+  for (syms = allSyms; syms; syms = ns) {
225
+    ns = syms->next;
226
+    deleteSyms(syms);
227
+  }
228
+}
229
+
230
+/* ------------------------------ */
231
+
232
+static const Elf32_Sym *findLocalSym(const char *name, Symbols syms)
233
+{
234
+  const Elf32_Sym *sym = lookupSymInTable(name, syms);
235
+
236
+  return (!sym || sym->st_shndx == SHN_UNDEF ||
237
+          sym->st_shndx >= syms->noffsets) ? 0 : sym;
238
+}
239
+
240
+static int readSym(Symbols syms, int pid, const char *name, int *val)
241
+{
242
+  const Elf32_Sym *sym;
243
+
244
+  if (!(sym = findLocalSym(name, syms))) return 0;
245
+  errno = 0;
246
+  *val = ptrace(PTRACE_PEEKDATA, pid, sym->st_value, 0);
247
+  if (errno) {
248
+    perror("ptrace");
249
+    quit("Could not read thread debug info.");
250
+  }
251
+  return 1;
252
+}
253
+
254
+static void checkForThreads(Symbols syms, int pid)
255
+{
256
+  const Elf32_Sym *handles;
257
+  int i, tpid, hsize, descOff, pidOff, numPids, *pptr;
258
+  Elf32_Addr descr;
259
+
260
+  if (!findLocalSym("__pthread_threads_debug", syms) ||
261
+      !(handles = findLocalSym("__pthread_handles", syms)) ||
262
+      !readSym(syms, pid, "__pthread_sizeof_handle", &hsize) ||
263
+      !readSym(syms, pid, "__pthread_offsetof_descr", &descOff) ||
264
+      !readSym(syms, pid, "__pthread_offsetof_pid", &pidOff) ||
265
+      !readSym(syms, pid, "__pthread_handles_num", &numPids) ||
266
+      numPids == 1 ||
267
+      !(threads.pids = (int *) calloc(numPids + 2, sizeof(int))) ||
268
+      !(threads.attached = (int *) calloc(numPids + 2, sizeof(int)))) {
269
+    if (threads.pids) {
270
+      free(threads.pids);
271
+      threads.pids = 0;
272
+    }
273
+    if (threads.attached) {
274
+      free(threads.attached);
275
+      threads.attached = 0;
276
+    }
277
+    return;
278
+  }
279
+  errno = 0;
280
+
281
+  for (pptr = &threads.pids[0], i = 0; i < numPids && !errno; i++) {
282
+    descr = ptrace(PTRACE_PEEKDATA, pid,
283
+                   handles->st_value + (i * hsize) + descOff, 0);
284
+    if (!descr && i == 0)
285
+      /* The initial thread's descriptor was not initialized yet.  */
286
+      *pptr++ = pid;
287
+    else if (descr && !errno) {
288
+      tpid = ptrace(PTRACE_PEEKDATA, pid, descr + pidOff, 0);
289
+      if (!errno)
290
+        *pptr++ = tpid;
291
+    }
292
+  }
293
+  threads.npids = pptr - threads.pids;
294
+
295
+  if (errno) {
296
+    perror("ptrace");
297
+    quit("Could not read thread debug info.");
298
+  }
299
+
300
+  threads.found = 1;
301
+
302
+  for (i = 0; i < threads.npids; i++) {
303
+    if (threads.pids[i] && threads.pids[i] != pid) {
304
+      if (attach(threads.pids[i]) != 0)
305
+        printf("Could not attach to thread %d.\n", threads.pids[i]);
306
+      else threads.attached[i] = 1;
307
+    } else if (threads.pids[i] == pid) {
308
+      threads.attached[i] = 1;
309
+    }
310
+
311
+  }
312
+}
313
+
314
+/* ------------------------------ */
315
+
316
+static void verify_ident(Elf32_Ehdr *hdr)
317
+{
318
+  if (memcmp(&hdr->e_ident[EI_MAG0], ELFMAG, SELFMAG))
319
+    quit("Bad magic number.");
320
+  if (hdr->e_ident[EI_CLASS] != ELFCLASS32)
321
+    quit("only 32 bit objects supported.");
322
+  if (hdr->e_ident[EI_DATA] != ELFDATA2LSB)
323
+    quit("big endian object files not supported.");
324
+  if (hdr->e_ident[EI_VERSION] != EV_CURRENT ||
325
+      hdr->e_version != EV_CURRENT)
326
+    quit("Unsupported ELF format version.");
327
+  if (hdr->e_machine != EM_386)
328
+    quit("Not an IA32 executable.");
329
+}
330
+
331
+static int find_stables(Elf32_Ehdr *hdr, int fd, Symbols syms)
332
+{
333
+  int i, idx, spot;
334
+  Elf32_Shdr shdr;
335
+
336
+  spot = hdr->e_shoff;
337
+  if (lseek(fd, spot, SEEK_SET) != spot) quit("seek failed.");
338
+
339
+  memset(&shdr, 0, sizeof(shdr));
340
+
341
+  syms->noffsets = hdr->e_shnum;
342
+
343
+  for (idx = 0; idx < hdr->e_shnum; idx++) {
344
+    if (read(fd, &shdr, hdr->e_shentsize) != hdr->e_shentsize)
345
+      quit("premature eof.");
346
+    spot += hdr->e_shentsize;
347
+    switch (shdr.sh_type) {
348
+     case SHT_SYMTAB:
349
+      syms->nsyms = shdr.sh_size / sizeof(Elf32_Sym);
350
+
351
+      if (!(syms->symbols = (Elf32_Sym *) malloc(shdr.sh_size)))
352
+        quit("Could not allocate symbol table.");
353
+
354
+      if (lseek(fd, shdr.sh_offset, SEEK_SET) != shdr.sh_offset ||
355
+          read(fd, syms->symbols, shdr.sh_size) != shdr.sh_size)
356
+        quit("Could not read symbol table.");
357
+
358
+      i = hdr->e_shoff + shdr.sh_link * hdr->e_shentsize;
359
+      if (lseek(fd, i, SEEK_SET) != i)
360
+        quit("Could not seek and find.");
361
+      if (read(fd, &shdr, hdr->e_shentsize) != hdr->e_shentsize)
362
+        quit("Could not read string table section header.");
363
+      if (!(syms->strings = malloc(shdr.sh_size)))
364
+        quit("Could not allocate string table.");
365
+      if (lseek(fd, shdr.sh_offset, SEEK_SET) != shdr.sh_offset ||
366
+          read(fd, syms->strings, shdr.sh_size) != shdr.sh_size)
367
+        quit("Could not read string table.");
368
+      lseek(fd, spot, SEEK_SET);
369
+      break;
370
+     case SHT_DYNAMIC:
371
+      syms->ndyns = shdr.sh_size / sizeof(Elf32_Dyn);
372
+      if (!(syms->dynamic = (Elf32_Dyn *) malloc(shdr.sh_size)))
373
+        quit("Out of memory.");
374
+      if (lseek(fd, shdr.sh_offset, SEEK_SET) != shdr.sh_offset ||
375
+          read(fd, syms->dynamic, shdr.sh_size) != shdr.sh_size)
376
+        quit("Could not read dynamic table.");
377
+      lseek(fd, spot, SEEK_SET);
378
+      break;
379
+    }
380
+  }
381
+
382
+  return (syms->nsyms > 0);
383
+}
384
+
385
+static Symbols loadSyms(const char *fname)
386
+{
387
+  Elf32_Ehdr hdr;
388
+  int fd;
389
+  Symbols syms;
390
+
391
+  syms = newSyms(fname);
392
+  if ((fd = open(fname, O_RDONLY)) < 0)
393
+    quit("Could not open object file.");
394
+  read(fd, &hdr, sizeof(hdr));
395
+  verify_ident(&hdr);
396
+  if (!find_stables(&hdr, fd, syms)) {
397
+    deleteSyms(syms);
398
+    syms = 0;
399
+  }
400
+  close(fd);
401
+
402
+  return syms;
403
+}
404
+
405
+static void readDynoData(Symbols syms, int pid)
406
+{
407
+  int val, done;
408
+  Elf32_Addr addr;
409
+  const Elf32_Sym *dyn = lookupSymInTable("_DYNAMIC", syms);
410
+
411
+  for (errno = done = 0, addr = dyn->st_value; !done && !errno; addr += 8) {
412
+    val = ptrace(PTRACE_PEEKDATA, pid, addr, 0);
413
+    if (errno) break;
414
+    switch (val) {
415
+     case DT_NULL: done = 1; break;
416
+     case DT_DEBUG:
417
+      // point to the r_debug struct -- see link.h
418
+      DebugInfo = (Elf32_Addr) ptrace(PTRACE_PEEKDATA, pid, addr + 4, 0);
419
+      // point to the head of the link_map chain.
420
+      DebugInfo = (Elf32_Addr) ptrace(PTRACE_PEEKDATA, pid, DebugInfo + 4, 0);
421
+      break;
422
+    }
423
+  }
424
+  if (errno) {
425
+    perror("pstack");
426
+    quit("failed to read target.");
427
+  }
428
+}
429
+
430
+static void resolveSymbols(Symbols syms, int offset)
431
+{
432
+  Elf32_Sym *sym;
433
+  int i;
434
+
435
+  syms->baseAddr = offset;
436
+
437
+  for (i = 0, sym = syms->symbols; i < syms->nsyms; i++, sym++) {
438
+    if (sym->st_shndx && sym->st_shndx < syms->noffsets) {
439
+      sym->st_value += offset;
440
+    }
441
+  }
442
+}
443
+
444
+static void loadString(int pid, int addr, char *dp, int bytes)
445
+{
446
+  long *lp = (long *) dp, nr;
447
+
448
+  memset(dp, 0, bytes);
449
+  errno = 0;
450
+
451
+  addr = ptrace(PTRACE_PEEKDATA, pid, addr, 0);
452
+
453
+  for (nr = 0, errno = 0; !errno && bytes > 4 && strlen(dp) == nr;
454
+       addr += 4, bytes -= 4, nr += 4) {
455
+    *lp++ = ptrace(PTRACE_PEEKDATA, pid, addr, 0);
456
+  }
457
+
458
+  if (errno) {
459
+    perror("ptrace");
460
+    quit("loadString failed.");
461
+  }
462
+}
463
+
464
+#define OFFSET(f, s) ((int) ((char *) &(s).f - (char *) &(s)))
465
+static void readLinkMap(int pid, Elf32_Addr base,
466
+                        struct link_map *lm, char *name, int namelen)
467
+{
468
+  errno = 0;
469
+
470
+  /* base address */
471
+  lm->l_addr = (Elf32_Addr) ptrace(PTRACE_PEEKDATA, pid,
472
+                                   base + OFFSET(l_addr, *lm), 0);
473
+  /* next element of link map chain */
474
+  if (!errno)
475
+    lm->l_next = (struct link_map *) ptrace(PTRACE_PEEKDATA, pid,
476
+                                            base + OFFSET(l_next, *lm), 0);
477
+  if (errno) {
478
+    perror("ptrace");
479
+    quit("can't read target.");
480
+  }
481
+
482
+  loadString(pid, base + OFFSET(l_name, *lm), name, namelen);
483
+}
484
+
485
+static void loadSymbols(int pid)
486
+{
487
+  char buf[256];
488
+  Symbols syms;
489
+  struct link_map lm;
490
+
491
+  sprintf(buf, "/proc/%d/exe", pid);
492
+  if (!(syms = loadSyms(buf))) {
493
+    fputs("(No symbols found)\n", stdout);
494
+    return;
495
+  }
496
+
497
+  readDynoData(syms, pid);
498
+  readLinkMap(pid, DebugInfo, &lm, buf, sizeof(buf));
499
+
500
+  for ( ; lm.l_next; ) {
501
+    readLinkMap(pid, (Elf32_Addr) lm.l_next, &lm, buf, sizeof(buf));
502
+    if (!(syms = loadSyms(buf))) {
503
+	printf("(No symbols found in %s)\n", buf);
504
+	continue;
505
+    }
506
+    resolveSymbols(syms, lm.l_addr);
507
+    if (!threads.found) checkForThreads(syms, pid);
508
+  }
509
+}
510
+
511
+/* ------------------------------ */
512
+
513
+static void print_pc(Elf32_Addr addr)
514
+{
515
+  Elf32_Sym *sym;
516
+  Symbols syms;
517
+
518
+  findCodeAddress(addr, &sym, &syms);
519
+
520
+  if (!sym)
521
+    printf("0x%08lx: ????", (unsigned long) addr);
522
+  else if (sym->st_value < addr)
523
+    printf("0x%08lx: %s + 0x%x", (unsigned long) addr,
524
+	   &syms->strings[sym->st_name], addr - sym->st_value);
525
+  else
526
+    printf("0x%08lx: %s", (unsigned long) addr, &syms->strings[sym->st_name]);
527
+}
528
+
529
+/* ------------------------------ */
530
+
531
+#define MAXARGS 6
532
+
533
+static int crawl(int pid)
534
+{
535
+  unsigned long pc, fp, nextfp, nargs, i, arg;
536
+
537
+  errno = 0;
538
+  fp = -1;
539
+
540
+  pc = ptrace(PTRACE_PEEKUSER, pid, EIP * 4, 0);
541
+  if (!errno)
542
+    fp = ptrace(PTRACE_PEEKUSER, pid, EBP * 4, 0);
543
+
544
+  if (!errno) {
545
+    print_pc(pc);
546
+    for ( ; !errno && fp; ) {
547
+      nextfp = ptrace(PTRACE_PEEKDATA, pid, fp, 0);
548
+      if (errno) break;
549
+
550
+      nargs = (nextfp - fp - 8) / 4;
551
+      if (nargs > MAXARGS) nargs = MAXARGS;
552
+      if (nargs > 0) {
553
+        fputs(" (", stdout);
554
+        for (i = 1; i <= nargs; i++) {
555
+          arg = ptrace(PTRACE_PEEKDATA, pid, fp + 4 * (i + 1), 0);
556
+          if (errno) break;
557
+          printf("%lx", arg);
558
+          if (i < nargs) fputs(", ", stdout);
559
+        }
560
+        fputc(')', stdout);
561
+        nargs = nextfp - fp - 8 - (4 * nargs);
562
+        if (!errno && nargs > 0) printf(" + %lx\n", nargs);
563
+        else fputc('\n', stdout);
564
+      } else fputc('\n', stdout);
565
+
566
+      if (errno || !nextfp) break;
567
+      pc = ptrace(PTRACE_PEEKDATA, pid, fp + 4, 0);
568
+      fp = nextfp;
569
+      if (errno) break;
570
+      print_pc(pc);
571
+    }
572
+  }
573
+
574
+  if (errno) perror("crawl");
575
+  return errno;
576
+}
577
+
578
+/* ------------------------------ */
579
+
580
+static char cmd[128];
581
+
582
+static char *cmdLine(int pid)
583
+{
584
+  int fd, len, i;
585
+
586
+  fd = -1;
587
+  sprintf(cmd, "/proc/%d/cmdline", pid);
588
+  if ((fd = open(cmd, O_RDONLY)) >= 0 &&
589
+      (len = read(fd, cmd, sizeof(cmd))) > 0) {
590
+    for (i = 0; i < len; i++) if (!cmd[i]) cmd[i] = ' ';
591
+    for ( ; len > 0 && cmd[len - 1] <= ' '; len--);
592
+    cmd[len] = 0;
593
+    if (len >= sizeof(cmd) - 4)
594
+      strcpy(&cmd[sizeof(cmd) - 4], "...");
595
+  }
596
+  if (fd < 0 || len <= 0) strcpy(cmd, "(command line?)");
597
+  if (fd >= 0) close(fd);
598
+
599
+  return cmd;
600
+}
601
+
602
+int main(int argc, char **argv)
603
+{
604
+  int i;
605
+
606
+  /* Arrange to detach if we get an unexpected signal.  This prevents
607
+     threads from being left in a suspended state if (for example) we
608
+     try to get a stack trace from a threaded process which has
609
+     been stripped.  */
610
+  for (i = 0; i < NSIG; i++)
611
+    if (i != SIGCHLD)
612
+      signal (i, handle_signal);
613
+
614
+  for (argc--, argv++; argc > 0; argc--, argv++) {
615
+    thePid = atoi(*argv);
616
+    if (!thePid || thePid == getpid()) {
617
+      fprintf(stderr, "Invalid PID %d\n", thePid);
618
+      continue;
619
+    }
620
+
621
+    if (attach(thePid) != 0) {
622
+      thePid = 0;
623
+      fprintf(stderr, "Could not attach to target.\n");
624
+    } else {
625
+      printf("\n%d: %s\n", thePid, cmdLine(thePid));
626
+      loadSymbols(thePid);
627
+      if (threads.found) {
628
+        for (i = 0; i < threads.npids; i++) {
629
+          if (threads.attached[i]) {
630
+            printf("----- Thread %d -----\n", threads.pids[i]);
631
+            if (crawl(threads.pids[i]) != 0)
632
+              fprintf(stderr, "Error tracing through thread %d\n",
633
+                      threads.pids[i]);
634
+          }
635
+        }
636
+      } else if (crawl(thePid) != 0)
637
+        fprintf(stderr, "Error tracing through process %d\n", thePid);
638
+    }
639
+
640
+    detachall();
641
+    resetData();
642
+  }
643
+
644
+  exit(0);
645
+}

+ 57
- 0
pstack.spec View File

@@ -0,0 +1,57 @@
1
+Summary: Display stack trace of a running process
2
+Name: pstack
3
+Version: 1.2
4
+Release: 3
5
+Copyright: GPL
6
+Group: Development/Debuggers
7
+Source: %{name}-%{version}.tar.gz
8
+BuildRoot: %{_tmppath}/%{name}-root
9
+ExclusiveArch: %{ix86}
10
+
11
+%description
12
+pstack dumps a stack trace for a process, given the pid of that
13
+process.  If the process named is part of a thread group, then all the threads
14
+in the group are traced.
15
+
16
+%prep
17
+%setup -q
18
+
19
+%build
20
+make
21
+
22
+%install
23
+rm -rf $RPM_BUILD_ROOT
24
+make install BINDIR=%{buildroot}%{_bindir} MANDIR=%{buildroot}%{_mandir}
25
+
26
+%clean
27
+rm -rf $RPM_BUILD_ROOT
28
+
29
+%files
30
+%defattr(-,root,root)
31
+%doc COPYING README VERSION
32
+%{_bindir}/pstack
33
+%{_mandir}/man1/*
34
+
35
+%changelog
36
+* Wed Nov 12 2003 Roland McGrath <roland@redhat.com> 1.2-3
37
+- updated linuxthreads support for newer linuxthreads internals (#107305)
38
+- avoid buffer overflow in symbol printing (#109642)
39
+
40
+* Thu Sep 18 2003 Jakub Jelinek <jakub@redhat.com> 1.1-7
41
+- don't crash if one of shared libraries has stripped .symtab/.strtab
42
+  (#98162)
43
+
44
+* Mon Feb 24 2003 Elliot Lee <sopwith@redhat.com>
45
+- rebuilt
46
+
47
+* Sat Feb 22 2003 Jakub Jelinek <jakub@redhat.com>
48
+- rebuilt
49
+
50
+* Fri Jun 21 2002 Tim Powers <timp@redhat.com>
51
+- automated rebuild
52
+
53
+* Tue May 28 2002 Jakub Jelinek <jakub@redhat.com>
54
+- build on x86 only
55
+
56
+* Mon Feb 25 2002 Preston Brown <pbrown@redhat.com>
57
+- initial packaging

Loading…
Cancel
Save