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