ClearBlue
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Friends
cb-extract.h
1 /*
2  * cb-extract.h
3  *
4  * Created on: Nov 29, 2016
5  * Author: Fan Gang <fangang@clearblue.com>
6  *
7  *
8  * The main part of this file is copied from file DebugInfoAnalysis.cpp, please
9  * keep sync when it is changing.
10  */
11 
12 #ifndef TOOLS_PP_EXTRACT_PP_EXTRACT_H_
13 #define TOOLS_PP_EXTRACT_PP_EXTRACT_H_
14 
15 #include "Utils/ADT/kvec.h"
16 #include "Utils/ADT/kvec_ext.h"
17 #include "Utils/StringUtils.h"
18 #include <llvm/IR/DebugInfo.h>
19 #include <llvm/Support/Allocator.h>
20 #include <unordered_map>
21 
22 using namespace llvm;
23 
24 // Use a memory allocator to manage the char array allocated on heap
25 // The memory will be automatically released
26 BumpPtrAllocator string_allocator;
27 // Reconstruct the path of the source code files in a simpler form
28 template <int initN>
29 StringRef synthesize_file_path(StringRef File, StringRef Dir,
30  kvec_str<initN> &path_result) {
31  path_result.clear();
32 
33  StringRef path_have_root_name;
34 
35  if (!sys::path::is_absolute(File)) {
36  // When the file name is not an absolute path,
37  // we should concatenate the dir and file name to obtain the full path
38  path_result.fill(Dir.data(), Dir.size());
39  path_have_root_name = Dir;
40  } else {
41  path_have_root_name = File;
42  }
43 
44  // It could be that current system is Linux but the input bitcode is generated
45  // on windows or vice versa.
46  char input_bc_path_sep = '/';
47  if (path_have_root_name.size() >= 3 && (path_have_root_name[1] == ':') &&
48  (path_have_root_name[2] == '\\')) {
49  input_bc_path_sep = '\\';
50  }
51 
52  bool first_comp = true;
53  for (sys::path::const_iterator it = sys::path::begin(File),
54  ie = sys::path::end(File);
55  it != ie; ++it, first_comp = false) {
56  StringRef component = *it;
57 
58  if (component == "..") {
59  int pos = path_result.rfind(input_bc_path_sep);
60  if (pos > 0) {
61  path_result.erase_substr(pos);
62  } else {
63  // If current path is already at root, .. has no effect
64  }
65  } else if (component != ".") {
66  // Append component to the path, including the root symbol /
67 
68  if (first_comp) {
69  // The first component is either a root name (e.g. //net) or a root
70  // directory (e.g. /) The root name has special meaning on Windows, we
71  // should keep it intact
72 
73  if (component == sys::path::root_name(File)) {
74  // On Unix system, a path starts with "//net" can be erroneously
75  // determined as a root name by sys::path::root_name. However, "//net"
76  // is actually writing the root symbol "//" twice and it is equal to
77  // "/net". Therefore, we handle the wrong root name determination
78  // here.
79 
80  size_t last_bslash = component.rfind("/");
81  if (last_bslash != StringRef::npos) {
82  component = component.substr(last_bslash);
83  } else {
84  // This is perhaps a real root name.
85  // It is either the windows driver letter (e.g. C:)
86  // or the "server_host" in the remote path "server_host:/home/xx"
87  // defined by file URI scheme specification. We just keep the
88  // component unchanged.
89  }
90  }
91  }
92 
93  // Add a backslash if the component does not start with a separator and
94  // the synthesized path is not ended with a separator
95  if (!component.startswith(StringRef(&input_bc_path_sep, 1)) &&
96  (path_result.empty() || path_result.back() != input_bc_path_sep))
97  path_result.push_back(input_bc_path_sep);
98 
99  // Add the component
100  path_result.append_str(component.data(), component.size());
101  }
102  }
103 
104  // First look up the global cache
105  // We do not set trailing zero for file name StringRef
106  StringRef file_name(path_result.c_str(), path_result.size());
107  file_name = hooked_format_str(string_allocator, "%s", path_result.c_str());
108  return file_name;
109 }
110 
111 std::unique_ptr<std::unordered_map<const Function *, StringRef>>
112 getFunctionSrcFiles(Module &M) {
113 
114  auto pFuncSrcFileCache =
115  std::unique_ptr<std::unordered_map<const Function *, StringRef>>(
116  new std::unordered_map<const Function *, StringRef>());
117 
118  // Scan the debug information placed at the end of module
119  DebugInfoFinder DbgFinder;
120  DbgFinder.processModule(M);
121  kvec_str<512> tmp_src_path;
122 
123  // Cache the function information
124  auto it_func_range = DbgFinder.subprograms();
125  for (auto it = it_func_range.begin(), ie = it_func_range.end(); it != ie;
126  ++it) {
127  const DISubprogram &f_loc = *it;
128 
129  Function *F = f_loc.getFunction();
130  StringRef File = f_loc.getFilename();
131  StringRef Dir = f_loc.getDirectory();
132  if (File.data() && Dir.data()) {
133  (*pFuncSrcFileCache)[F] = synthesize_file_path(File, Dir, tmp_src_path);
134  } else {
135  (*pFuncSrcFileCache)[F] = "";
136  }
137  }
138  return pFuncSrcFileCache;
139 }
140 
141 #endif /* TOOLS_PP_EXTRACT_PP_EXTRACT_H_ */