addr2line.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2018 Alexey Matveichev
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 Application
27  addr2line
28 
29 Description
30  A simple, partial emulation of addr2line utility for Mac-OS.
31 
32 \*---------------------------------------------------------------------------*/
33 
34 #include <getopt.h>
35 #include <cstdlib>
36 #include <string>
37 #include <vector>
38 #include <iostream>
39 
40 #include "regExp.H"
41 #include "SubStrings.H"
42 
43 static void usage();
44 static void version();
45 static std::string getLine(const std::string&, const std::string&);
46 static std::string pipeOpen(const std::string& cmd, const int lineNum = 0);
47 
48 
49 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
50 
51 int main(int argc, char *argv[])
52 {
53  int optHelp = 0, optFunctions = 0, optVersion = 0;
54  int ch;
55  std::string filename = "a.out";
56  std::vector<std::string> addresses;
57 
58  static struct option opts[] =
59  {
60  { "target", required_argument, nullptr, 'b' },
61  { "demangle", required_argument, nullptr, 'C' },
62  { "exe", required_argument, nullptr, 'e' },
63  { "functions", no_argument, &optFunctions, 1 },
64  { "version", no_argument, &optVersion, 1 },
65  { "basename", no_argument, nullptr, 's' },
66  { "inlines", no_argument, nullptr, 'i' },
67  { "section", required_argument, nullptr, 'j' },
68  { "help", no_argument, &optHelp, 1 },
69  { nullptr, 0, nullptr, 0 }
70  };
71 
72  while ((ch = getopt_long(argc, argv, "b:C:e:fVsij:H", opts, nullptr)) != -1)
73  {
74  switch (ch)
75  {
76  case 'e':
77  filename = std::string(optarg);
78  break;
79  case 'C':
80  // Ignoring this flag for now
81  break;
82  case 'f':
83  // Functions are demangled in printStack
84  break;
85  case 0:
86  if (optHelp) usage();
87  if (optVersion) version();
88  break;
89  default:
90  usage();
91  break;
92  }
93  }
94 
95  if (optind >= argc)
96  {
97  usage();
98  }
99 
100  argc -= optind;
101  argv += optind;
102 
103  while (argc > 0)
104  {
105  addresses.push_back(std::string(*argv));
106  ++argv;
107  --argc;
108  }
109 
110  for (const auto& addr : addresses)
111  {
112  std::cout<< '\n' << getLine(filename, addr).c_str() << '\n';
113  }
114 
115  return 0;
116 }
117 
118 
119 void usage()
120 {
121  std::cout
122  << "usage: addr2line [-e filename|--exe=filename]"
123  " address [address...]\n" << std::endl;
124  std::exit(1);
125 }
126 
127 
128 void version()
129 {
130  std::cout<< "OpenFOAM addr2line emulator\n" << std::endl;
131  std::exit(0);
132 }
133 
134 
135 // Read up to and including lineNum from the piped command
136 // Return the final line read
137 std::string pipeOpen(const std::string& cmd, int lineNum)
138 {
139  std::string str;
140 
141  FILE* handle = popen(cmd.c_str(), "r");
142  if (!handle) return str;
143 
144  char* buf = nullptr;
145  size_t len = 0;
146  ssize_t nread;
147 
148  // Read lineNum number of lines
149  for
150  (
151  int cnt = 0;
152  cnt <= lineNum && (nread = ::getline(&buf, &len, handle)) >= 0;
153  ++cnt
154  )
155  {
156  if (cnt == lineNum)
157  {
158  // Retain the last line, trimming trailing newline
159  str.assign(buf);
160 
161  if (str.size())
162  {
163  str.resize(str.size()-1);
164  }
165  }
166  }
167 
168  free(buf);
169  pclose(handle);
170 
171  return str;
172 }
173 
174 
175 std::string getLine(const std::string& filename, const std::string& addr)
176 {
177  std::string line =
178  pipeOpen
179  (
180  "echo 'image lookup -va " + addr
181  + "'"
182  + " | xcrun lldb "
183  + "-O 'target create --no-dependents -a x86_64 "
184  + filename
185  + "' -o '"
186  + "target module load -f "
187  + filename
188  + " __TEXT 0x0' 2>/dev/null"
189  + " | grep LineEntry"
190  );
191 
192 
193  Foam::regExp re(".+LineEntry: .+: (.+):([0-9]+):[0-9]+");
194 
196  if (!re.match(line, groups))
197  {
198  line = "??:0";
199  }
200  else
201  {
202  line = groups[1].str() + ":" + groups[2].str();
203  }
204 
205  return line;
206 }
207 
208 
209 // ************************************************************************* //
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
const dimensionedScalar re
Classical electron radius: default SI units: [m].
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
Sub-ranges of a string with a structure similar to std::match_results, but without the underlying reg...
Definition: CStringList.H:57
StringType str(size_t pos) const
Retrieve element at pos, converted to a string type.
Definition: SubStrings.H:96
const std::string version
OpenFOAM version (name or stringified number) as a std::string.
Wrapper around POSIX extended regular expressions with some additional prefix-handling. The prefix-handling is loosely oriented on PCRE regular expressions and provides a simple means of tuning the expressions.
Definition: regExpPosix.H:80