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 pOpen(const std::string&, int line=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 std::string pOpen(const std::string& cmd, int line)
136 {
137  std::string res;
138 
139  FILE* cmdPipe = popen(cmd.c_str(), "r");
140  if (!cmdPipe) return res;
141 
142  char* buf = nullptr;
143 
144  // Read line number of lines
145  for (int cnt = 0; cnt <= line; ++cnt)
146  {
147  size_t linecap = 0;
148  ssize_t linelen = ::getline(&buf, &linecap, cmdPipe);
149 
150  if (linelen < 0)
151  {
152  break;
153  }
154 
155  if (cnt == line)
156  {
157  res = std::string(buf);
158 
159  // Trim trailing newline
160  if (res.size())
161  {
162  res.resize(res.size()-1);
163  }
164  break;
165  }
166  }
167 
168  if (buf) free(buf);
169 
170  pclose(cmdPipe);
171 
172  return res;
173 }
174 
175 
176 std::string getLine(const std::string& filename, const std::string& addr)
177 {
178  std::string line =
179  pOpen
180  (
181  "echo 'image lookup -va " + addr
182  + "'"
183  + " | xcrun lldb "
184  + "-O 'target create --no-dependents -a x86_64 "
185  + filename
186  + "' -o '"
187  + "target module load -f "
188  + filename
189  + " __TEXT 0x0' 2>/dev/null"
190  + " | grep LineEntry"
191  );
192 
193 
194  Foam::regExp re(".+LineEntry: .+: (.+):([0-9]+):[0-9]+");
195 
197  if (!re.match(line, groups))
198  {
199  line = "??:0";
200  }
201  else
202  {
203  line = groups[1].str() + ":" + groups[2].str();
204  }
205 
206  return line;
207 }
208 
209 
210 // ************************************************************************* //
Foam::regExpPosix
Wrapper around POSIX extended regular expressions with some additional prefix-handling....
Definition: regExpPosix.H:80
Foam::endl
Ostream & endl(Ostream &os)
Definition: Ostream.H:381
Foam::SubStrings
Sub-ranges of a string with a structure similar to std::match_results, but without the underlying reg...
Definition: CStringList.H:57
Foam::constant::atomic::re
const dimensionedScalar re
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
Foam::foamVersion::version
const std::string version
SubStrings.H
Foam::pOpen
string pOpen(const string &cmd, label line=0)
Definition: printStack.C:39
Foam::SubStrings::str
StringType str(size_t pos) const
Definition: SubStrings.H:114
regExp.H