Include program counter on action limit notification log
[gnash.git] / utilities / dumpshm.cpp
blobd20d46e2881a958e8012d6442ccf68340eaafa45
1 //
2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
3 // Foundation, Inc
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #ifdef HAVE_CONFIG_H
20 #include "gnashconfig.h"
21 #endif
23 #include "GnashSystemIOHeaders.h" // write()
24 #include <cstdarg>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <fcntl.h>
28 #include <cerrno>
30 extern "C"{
31 #ifdef HAVE_GETOPT_H
32 #include <getopt.h>
33 #endif
34 #ifndef __GNUC__
35 extern int optind, getopt(int, char *const *, const char *);
36 extern char *optarg;
37 #endif
39 #include <dirent.h>
40 #include <sys/types.h>
41 #if !defined(HAVE_WINSOCK_H) && !defined(__riscos__) && !defined(__OS2__) && !defined(__amigaos4__)
42 #include <sys/mman.h>
43 #include <sys/shm.h>
44 #include <sys/ipc.h>
45 #elif !defined(__riscos__) && !defined(__OS2__) && !defined(__amigaos4__)
46 #include <windows.h>
47 #include <process.h>
48 #include <io.h>
49 #endif
50 #include <iostream>
51 #include <iomanip>
52 #include <fstream>
53 #include <string>
54 #include <map>
55 #if defined(__STDC_HOSTED__) || !defined(__GNUC__)
56 #include <sstream>
57 #else
58 #include <strstream>
59 #endif
60 #include <cstdio>
61 #include <cerrno>
63 #ifdef ENABLE_NLS
64 # include <clocale>
65 #endif
67 #include "log.h"
68 #include "rc.h"
69 #include "shm.h"
70 #include "amf.h"
71 #include "lcshm.h"
73 using namespace std;
74 using namespace gnash;
76 #ifdef BOOST_NO_EXCEPTIONS
77 namespace boost
80 void throw_exception(std::exception const & e)
82 std::abort();
85 #endif
87 // #error "No supported shared memory type for this platform"
89 static void usage (void);
90 void dump_ctrl(void *ptr);
91 void dump_shm(bool convert, bool out);
92 key_t list_lcs();
94 const int PIDSTART = 20000;
95 const int PIDEND = 23000;
96 const int LINELEN = 80;
97 const unsigned int LOOPCNT = 5;
98 const int DEFAULT_SHM_SIZE = 64528;
100 #ifndef SHM_STAT
101 const int SHM_STAT = 13;
102 const int SHM_INFO = 14;
103 #endif
105 namespace {
106 gnash::LogFile& dbglogfile = gnash::LogFile::getDefaultInstance();
107 gnash::RcInitFile& rcfile = gnash::RcInitFile::getDefaultInstance();
110 const char *DUMPSHM_VERSION = "0.5";
113 main(int argc, char *argv[])
115 int c;
116 bool listfiles = false;
117 bool sysv = false;
118 bool convert = false;
119 int size = 0;
120 string filespec, realname, tmpname;
121 vector<const char *> dirlist;
123 // Enable native language support, i.e. internationalization
124 #ifdef ENABLE_NLS
125 std::setlocale (LC_ALL, "");
126 bindtextdomain (PACKAGE, LOCALEDIR);
127 textdomain (PACKAGE);
128 #endif
129 // scan for the two main standard GNU options
130 for (c = 0; c < argc; c++) {
131 if (strcmp("--help", argv[c]) == 0) {
132 usage();
133 exit(EXIT_SUCCESS);
135 if (strcmp("--version", argv[c]) == 0) {
136 printf (_("Gnash dumpshm version: %s, Gnash version: %s\n"),
137 DUMPSHM_VERSION, VERSION);
138 exit(EXIT_SUCCESS);
142 while ((c = getopt (argc, argv, "hircv")) != -1) {
143 switch (c) {
144 case 'h':
145 usage ();
146 break;
148 case 'r':
149 sysv = true;
150 convert = false;
151 break;
153 case 'c':
154 sysv = true;
155 convert = true;
156 break;
158 case 'i':
159 sysv = true;
160 listfiles = true;
161 break;
163 case 'v':
164 // turn on verbosity for the libraries
165 dbglogfile.setVerbosity();
166 break;
168 default:
169 usage ();
170 break;
175 // If no command line arguments have been supplied, do nothing but
176 // print the usage message.
177 if (argc < 2) {
178 usage();
179 exit(EXIT_SUCCESS);
182 #if defined(USE_SYSV_SHM) && defined(HAVE_IPC_INFO)
183 // Just list the shared memory segments
184 if (listfiles && sysv) {
185 list_lcs();
186 exit(EXIT_SUCCESS);
188 #endif
190 if (optind <= argc - 1) {
191 if (*argv[optind] == '-') {
192 filespec = '-';
196 if (sysv) {
197 if (filespec == "-") {
198 dump_shm(convert, true);
199 } else {
200 dump_shm(convert, false);
203 exit(EXIT_SUCCESS);
206 if (size == 0) {
207 size = DEFAULT_SHM_SIZE;
210 // get the file name from the command line
211 if (optind < argc) {
212 filespec = argv[optind];
213 if (!convert) {
214 log_debug(_("Will use \"%s\" for memory segment file"), filespec);
220 // Dump the older style SYS V shared memory segments
221 void
222 dump_shm(bool convert, bool out)
224 // These are here for debugging purposes. It
225 char *shmaddr;
227 key_t key = rcfile.getLCShmKey();
229 if (key == 0) {
230 log_debug(_("No LcShmKey set in ~/.gnashrc, trying to find it ourselves"));
231 #if defined(USE_SYSV_SHM) && defined(HAVE_IPC_INFO)
232 key = list_lcs();
233 #endif
236 int size = 64528; // 1007 bytes less than unsigned
238 if (key == 0) {
239 log_debug(_("No shared memory segments found!"));
240 return;
242 if (dbglogfile.getVerbosity()) {
243 log_debug(_("Existing SHM Key is: %s, Size is: %s"),
244 boost::io::group(hex, showbase, key), size);
247 amf::LcShm lc;
248 lc.connect(key);
249 lc.dump();
251 // If the -c convert options was specified, dump the memory segment to disk.
252 // This makes it easy to store them as well as to examine them in great detail.
253 if (convert) {
254 int fd = open("segment.raw",O_WRONLY|O_CREAT, S_IRWXU);
255 if (fd == -1) {
256 perror("open");
258 log_debug(_("Writing memory segment to disk: \"segment.raw\""));
259 shmaddr = lc.getAddr();
260 write(fd, shmaddr, size);
261 if (out) {
262 #if 0
263 log_debug(_("The data is: 0x%s"), hexify((uint8_t *)shmaddr, size, false));
264 #endif
267 close(fd);
270 exit (EXIT_SUCCESS);
273 #if defined(USE_SYSV_SHM) && defined(HAVE_IPC_INFO)
274 key_t
275 list_lcs()
277 int maxid, shmid, id;
278 struct shmid_ds shmseg;
280 // #ifdef USE_POSIX_SHM
281 // if (library_dir != NULL) {
282 // for (i=0; entry>0; i++) {
283 // entry = readdir(library_dir);
284 // if (entry != NULL) {
285 // cout << "Found segment: " << entry->d_name << endl;
286 // }
287 // }
288 // } else {
289 // cout << _("Sorry, we can only list the files on systems with"
290 // " disk based shared memory") << endl;
291 // }
292 // #eendif
294 // If we're using SYSV shared memory, we can get a list of shared memory segments.
295 // By examing the size of each one, we can make a reasonable guess if it's one
296 // used for flash. As permissions apply, this will only list the segments created
297 // by the user running dumpshm.
298 // struct shm_info shm_info;
299 // maxid = shmctl(0, SHM_INFO, (struct shmid_ds *) (void *) &shm_info);
300 struct shmid_ds shm_info;
301 maxid = shmctl(0, SHM_INFO, &shm_info);
302 if (maxid < 0) {
303 log_debug(_("kernel not configured for shared memory"));
304 return 0;
307 // struct shminfo shminfo;
308 if ((shmctl(0, IPC_INFO, &shm_info)) < 0) {
309 return 0;
311 for (id = 0; id <= maxid; id++) {
312 shmid = shmctl(id, SHM_STAT, &shmseg);
313 if (shmid < 0) {
314 continue;
316 #ifdef IPC_PERM_KEY
317 if (shmseg.shm_segsz == 64528) {
318 log_debug(_("Found it! \"set LCShmKey %s\" in your ~/.gnashrc"),
319 boost::io::group(hex, showbase,
320 shmseg.shm_perm.IPC_PERM_KEY));
321 log_debug(_("Last changed on: %s"), ctime(&shmseg.shm_ctime));
322 log_debug(_("Last attached on: %s"), ctime(&shmseg.shm_atime));
323 log_debug(_("Last detached on: %s"), ctime(&shmseg.shm_dtime));
324 return shmseg.shm_perm.IPC_PERM_KEY;
326 #endif // end of IPC_PERM_KEY
328 // #else
329 // # error "No supported shared memory type for this platform"
330 //#endif // end of USE_POSIX_SHM
332 // Didn't find any segments of the right size
333 return static_cast<key_t>(0);
335 #endif // end of USE_SYSV_SHM & HAVE_IPC_INFO
337 /// \brief Display the command line arguments
338 static void
339 usage (void)
341 cerr << _("This program dumps the internal data of a shared memory segment")
342 << endl;
343 cerr << _("Usage: dumpshm [hdsanlif] filename") << endl;
344 cerr << _("-h\tHelp") << endl;
345 cerr << _("-i\tList segments") << endl;
346 cerr << _("-r\tDump SYSV segments") << endl;
347 cerr << _("-c\tDump SYSV segments to disk") << endl;
348 cerr << _("-v\tVerbose output") << endl;
349 exit (EXIT_FAILURE);
352 /// \brief Dumps the internal data of the found ShmControl
353 /// block. We do our own dumping, rather than letting
354 /// ShmControl::dump() do it, cause that's for debugging,
355 /// and this is for user display purposes.
356 void dump_ctrl(void *inmem)
358 Shm *ptr = static_cast<Shm *>(inmem);
360 cerr << _("\tBase address of this segment: ")
361 << static_cast<void *>(ptr->getAddr()) << endl;
362 cerr << _("\tFilespec: ") << ptr->getName() << endl;
363 cerr << _("\t# Bytes allocated: ") << ptr->getAllocated() << endl;
364 cerr << _("\tTotal # of bytes: ") << ptr->getSize() << endl;
367 // Local Variables:
368 // mode: C++
369 // indent-tabs-mode: t
370 // End: