Orfeo Toolbox  3.16
itkSmapsFileParser.cxx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkSmapsFileParser.cxx,v $
5  Language: C++
6  Date: $Date: 2009-11-24 02:27:28 $
7  Version: $Revision: 1.4 $
8 
9  Copyright (c) Insight Software Consortium. All rights reserved.
10  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11 
12  This software is distributed WITHOUT ANY WARRANTY; without even
13  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14  PURPOSE. See the above copyright notices for more information.
15 
16 =========================================================================*/
17 
18 #include "itkSmapsFileParser.h"
19 #include <stdlib.h>
20 
21 namespace itk
22 {
23 
24 bool ITKCommon_EXPORT ci_equal(char a, char b)
25 {
26  return tolower(static_cast<int>(a)) == tolower(static_cast<int>(b));
27 }
28 
30 {
31 }
32 
33 void MapRecord::Reset(void)
34 {
35  m_Tokens.clear();
36  m_RecordName = "";
37 }
38 
39 /* SmapsRecord implementation */
40 
41 ITKCommon_EXPORT std::istream& operator>>(std::istream &in, SmapsRecord &record)
42 {
43  record.Reset();
44 
45  try
46  {
47  // Get Header line
48  std::string headerline;
49  std::getline( in, headerline);
50 
51  if (headerline.empty())
52  {
53  return in;
54  }
55 
56  // Get name
57  std::istringstream stream(headerline);
58  std::string address, perms, offset, device;
59  int inode=-1;
60  // the header is defined with the following expression: "address permissions offset device inode [name]"
61  stream>>address;
62  if (!stream.good()) itkGenericExceptionMacro( << "bad address: " << address );
63  stream>>perms;
64  if (!stream.good()) itkGenericExceptionMacro( << "bad perms: " << perms );
65  stream>>offset;
66  if (!stream.good()) itkGenericExceptionMacro( << "bad offset: " << offset );
67  stream>>device;
68  if (!stream.good()) itkGenericExceptionMacro( << "bad device: " << device );
69  stream>>inode;
70  // name can be empty
71  if (!stream.eof())
72  {
73  std::getline(stream, record.m_RecordName);
74  }
75 
76  std::string token;
77  std::streampos lastPos = in.tellg();
78  // a token is defined with the following expression: "token: N kB"
79  while ( std::getline(in,token,':').good() )
80  {
81  //make sure it is a token and not a new record. A token doesn't contains space character
82  if ( token.find(' ') != std::string::npos )
83  {
84  in.seekg (lastPos, std::ios::beg);
85  break;
86  }
87  //fill the token with the memory usage N in kB
88  in>>record.m_Tokens[token];
89  std::getline(in,token);
90  if ( token != " kB" || !in.good()) itkGenericExceptionMacro( << "bad size: " << record.m_Tokens[token] );
91  lastPos = in.tellg();
92  }
93  }
94  catch (ExceptionObject excp)
95  {
96  record.Reset();
97  // propagate the exception
98  itkGenericExceptionMacro( << "The smaps header is corrupted" );
99  }
100  return in;
101 }
102 
103 
104 ITKCommon_EXPORT std::istream& operator>>(std::istream &in, VMMapSummaryRecord &record)
105 {
106  record.Reset();
107 
108  try
109  {
110  // the record name can have spaces.
111  in >> record.m_RecordName;
112 
113  if (in.eof() && record.m_RecordName.empty())
114  {
115  return in;
116  }
117 
118  if (!in.good())
119  {
120  itkGenericExceptionMacro( << "Bad record name: " << record.m_RecordName );
121  }
122 
123  std::string bracket;
124 
125  while ( (in>>bracket).good() && bracket.find("[",0) == std::string::npos )
126  {
127  record.m_RecordName += std::string(" ") + bracket;
128  }
129 
130  if (!in.good() || bracket.find("[",0) == std::string::npos )
131  {
132  itkGenericExceptionMacro( << "For record: " << record.m_RecordName
133  << ", bad left bracket: " << bracket );
134  }
135 
136  in >> record.m_Tokens["Size"];
137 
138  if( !in.good() )
139  {
140  itkGenericExceptionMacro( << "For record: " << record.m_RecordName
141  << ", bad size: " << record.m_Tokens["Size"] );
142  }
143 
144  in >> bracket;
145 
146  if( !in.good() )
147  {
148  itkGenericExceptionMacro( << "For record: " << record.m_RecordName
149  << ", bad right bracket: " << bracket );
150  }
151  }
152  catch (ExceptionObject excp)
153  {
154  record.Reset();
155  // propagate the exception
156  itkGenericExceptionMacro( << "The smaps header is corrupted" );
157  }
158  return in;
159 }
160 
161 /* typical output:
162  * __DATA c000 [ 4K] rw-/rwx SM=ZER ...l/bin/cronwake
163  * VALLOC_USED(DefaultMallocZone_ 25000 [ 4K] rw-/rwx SM=COW
164  * MALLOC_USED(DefaultMallocZone_ 26000 [ 44K] rw-/rwx SM=ZER
165  * 31000 [ 4K] rw-/rwx SM=COW 34300000 00000...
166  * 32000 [ 76K] rw-/rwx SM=COW 00001eaa 01001...
167  * 45000 [ 4K] rw-/rwx SM=COW 34300000 00000...
168  * 46000 [ 344K] rw-/rwx SM=COW 00000000 00000...
169  * Memory tag=7 100000 [1044K] rw-/rwx SM=COW
170  * MALLOC_USED(DefaultMallocZone_ 300000 [ 4K] rw-/rwx SM=PRV
171  * Submap 90000000-9fffffff r--/r-- machine-wide submap
172  * __DATA a0000000 [ 4K] rw-/rw- SM=COW ...System.B.dylib
173  * __DATA a0001000 [ 4K] rw-/rw- SM=ZER ...System.B.dylib
174  * __DATA a0002000 [ 4K] rw-/rw- SM=COW ...System.B.dylib
175  * __DATA a0003000 [ 20K] rw-/rw- SM=COW ...System.B.dylib
176 */
177 
178 ITKCommon_EXPORT std::istream& operator>>(std::istream &in, VMMapRecord &record)
179 {
180  record.Reset();
181  bool submapFound = false;
182  bool recordHasNoName = false;
183  char line[256];
184  try
185  {
186  std::string address;
187  do
188  {
189  // the record name can have spaces.
190  in >> record.m_RecordName;
191  if( in.eof() || record.m_RecordName.empty() )
192  {
193  return in;
194  }
195 
196  if (!in.good())
197  {
198  itkGenericExceptionMacro( << "Bad record name: " << record.m_RecordName );
199  }
200 
201  //skip Submap entries
202  if ( record.m_RecordName == "Submap" )
203  {
204  in.getline(line,256);
205  submapFound = true;
206  }
207 
208  // all the records have been parsed, this is a new section
209  else if ( record.m_RecordName == "====" )
210  {
211  record.Reset();
212  return in;
213  }
214  else
215  {
216  // the name is folowed by an address
217  in >> address;
218 
219  if( !in.good() )
220  {
221  itkGenericExceptionMacro( << "For record: " << record.m_RecordName
222  << ", bad address: " << address );
223  }
224  // If address is "[" then recordName was the address and there is name for
225  // the record, skip it.
226  if ( address.find("[",0) != std::string::npos )
227  {
228  in.getline(line,256);
229  recordHasNoName = true;
230  }
231  else
232  {
233  recordHasNoName = false;
234  }
235  submapFound = false;
236  }
237  } while(submapFound || recordHasNoName);
238 
239  std::string bracket;
240 
241  while ( (in>>bracket).good() && bracket.find("[",0) == std::string::npos )
242  {
243  // the string is not a bracket yet, but probably the address. So the previous
244  // address was just the name
245  record.m_RecordName += std::string(" ") + address;
246  address = bracket;
247  }
248  if (!in.good() || bracket.find("[",0) == std::string::npos )
249  {
250  itkGenericExceptionMacro( << "For record: " << record.m_RecordName
251  << ", bad left bracket: " << bracket );
252  }
253  if ( bracket.length() > 1 )
254  {//bracket contains the size, ie "[1024K]"
255  record.m_Tokens["Size"] = atoi(bracket.substr(1,bracket.length()-3).c_str());
256  }
257  else
258  {
259  in>>record.m_Tokens["Size"];
260  }
261  if (!in.good())
262  {
263  itkGenericExceptionMacro( << "For record: " << record.m_RecordName
264  << ", bad size: " << record.m_Tokens["Size"] );
265  }
266  in.getline(line,256);
267  if (!in.good())
268  {
269  itkGenericExceptionMacro( << "For record: " << record.m_RecordName
270  << ", bad end of line: " << line );
271  }
272  }
273  catch (ExceptionObject excp)
274  {
275  record.Reset();
276  // propagate the exception
277  itkGenericExceptionMacro( << "The smaps header is corrupted" );
278  }
279  return in;
280 }
281 
282 
283 //bool ITKCommon_EXPORT ci_equal(char a, char b); // located in itkSmapsFileParser.cxx
284 
287 template<class TFirstType>
289  MapRecordPlusor<TFirstType>(const char * token = "Size")
290  :m_Token(token)
291  {
292  }
293 
294  TFirstType operator()(TFirstType first, const MapRecord* const & second)
295  {
296  std::map<std::string,unsigned int>::const_iterator it = second->m_Tokens.find(m_Token);
297  return first + ((it!=second->m_Tokens.end())?it->second:0);
298  }
299  const char * m_Token;
300 };
301 
305 template<class TFirstType>
307  MapRecordConditionalPlusor<TFirstType>(const char * filter, const char * token = "Size")
308  :m_Filter(filter), m_Token(token)
309  {
310  }
311  TFirstType operator()(TFirstType first, const MapRecord* const &second)
312  {
313  if ( std::search(second->m_RecordName.begin(),second->m_RecordName.end(),
314  m_Filter.begin(),m_Filter.end(),ci_equal) != second->m_RecordName.end())
315  {
316  return MapRecordPlusor<TFirstType>(m_Token)(first,second);
317  }
318  return first;
319  }
320  std::string m_Filter;
321  const char * m_Token;
322 };
323 
328 {
329  this->Reset();
330 }
331 
334 {
335  return std::accumulate(this->m_Records.begin(), this->m_Records.end(), 0, MapRecordPlusor<MemoryLoadType>());
336 }
337 
339 MapData::GetMemoryUsage( const char * filter , const char * token)
340 {
341  return std::accumulate(this->m_Records.begin(), this->m_Records.end(), 0, MapRecordConditionalPlusor<MemoryLoadType>(filter,token));
342 }
343 
346 {
347  return m_Records.empty();
348 }
349 
350 void DeleteMapRecord(MapRecord* const &record)
351 {
352  delete record;
353 }
354 
356 {
357  std::for_each(m_Records.begin(),m_Records.end(),DeleteMapRecord);
358  m_Records.clear();
359 }
360 
364 {
365 }
366 
367 ITK_EXPORT std::istream& operator>>( std::istream & smapsStream, SmapsData_2_6 & data)
368 {
369  SmapsRecord* record = NULL;
370  // reset the records from a previous parsing
371  data.Reset();
372  try
373  {
374  record = new SmapsRecord;
375  // parse each line of the Smaps file and fill the record vector.
376  while( smapsStream >> *record )
377  {
378  data.m_Records.push_back( record );
379  record = new SmapsRecord;
380  }
381  }
382  catch( ExceptionObject excp )
383  {
384  // in case of error, erase the records.
385  data.Reset();
386  // propagate the exception
387  itkGenericExceptionMacro( << "The Smaps stream contains errors, can't read the memory records." );
388  }
389  delete record;
390  return smapsStream;
391 }
392 
395 {
396  MemoryLoadType heapUsage = this->GetMemoryUsage("heap","Size");
397  // in some machines, there is no [heap] record;
398  if ( heapUsage == 0 )
399  {
400  //use the unnamed segments instead
401  heapUsage = this->GetMemoryUsage("","Size");
402  }
403  return heapUsage;
404 }
405 
408 {
409  return this->GetMemoryUsage("stack","Size");
410 }
411 
416  :m_UsingSummary(false)
417 {
418 }
419 
422 {
423 }
424 
425 
426 ITK_EXPORT std::istream& operator>>( std::istream & stream, VMMapData_10_2 & data)
427 {
428  MapRecord* record = NULL;
429  // reset the records from a previous parsing
430  data.Reset();
431  try
432  {
433  std::string line;
434  std::streampos startPos = stream.tellg();
435  // get to the Summary subsection
436  while( std::getline(stream,line).good() )
437  {
438  if ( line.find("==== Summary for process",0) != std::string::npos )
439  break;
440  }
441  // get to the first record
442  while( std::getline(stream,line).good() )
443  {
444  if ( line.find("REGION TYPE",0) != std::string::npos )
445  break;
446  }
447  // burn the line "=========== [ =======]"
448  if ( !std::getline(stream,line).good() )
449  {
450  //sometimes, vmmap doesn't have any Region Type summary sections,
451  //parse "Writable regions" instead
452  //go back to the beginning of the file
453  stream.clear();
454  stream.seekg(0,std::ios_base::beg);
455  // get to the Summary subsection
456  while( std::getline(stream,line).good() )
457  {
458  if ( line.find("==== Writable regions for process",0) != std::string::npos )
459  break;
460  }
461  if ( stream.fail() )
462  {
463  itkGenericExceptionMacro( << "Can't find the \"Writable regions\" section, can't read the memory records." );
464  }
465  data.m_UsingSummary = false;
466  }
467  else
468  {
469  data.m_UsingSummary = true;
470  }
471  if( data.m_UsingSummary )
472  {
473  record = new VMMapSummaryRecord;
474  // parse each line of the Smaps file and fill the record vector.
475  while( stream >> *dynamic_cast<VMMapSummaryRecord *>(record) )
476  {
477  if( record->m_RecordName.empty() )
478  {
479  break;
480  }
481  data.m_Records.push_back( record );
482  record = new VMMapSummaryRecord;
483  }
484  }
485  else
486  {
487  record = new VMMapRecord;
488  // parse each line of the Smaps file and fill the record vector.
489  while( stream >> *dynamic_cast<VMMapRecord* >(record) )
490  {
491  if( record->m_RecordName.empty() )
492  {
493  break;
494  }
495  data.m_Records.push_back( record );
496  record = new VMMapRecord;
497  }
498  }
499  }
500  catch( ExceptionObject excp )
501  {
502  // in case of error, erase the records.
503  data.Reset();
504  // propagate the exception
505  itkGenericExceptionMacro( << "The VMMap stream contains errors, can't read the memory records." );
506  }
507  //last record failed, it hasn't be added into data, delete it.
508  delete record;
509  return stream;
510 }
511 
514 {
515  return this->GetMemoryUsage("malloc","Size");
516 }
517 
520 {
521  return this->GetMemoryUsage("stack","Size");
522 }
523 
524 
525 } // end namespace itk

Generated at Sun May 19 2013 00:08:10 for Orfeo Toolbox with doxygen 1.8.3.1