/dsym.d

https://github.com/CyberShadow/DMapTreeMap · D · 253 lines · 226 code · 19 blank · 8 comment · 62 complexity · 75dd2113825c2f14a67248608a931b7f MD5 · raw file

  1. module dsym;
  2. import core.demangle;
  3. import std.algorithm.mutation : reverse;
  4. import std.algorithm.searching;
  5. import std.array;
  6. import std.ascii;
  7. import std.conv;
  8. import std.exception;
  9. import std.string;
  10. string[] parseDSymbol(string sym, out string dem)
  11. {
  12. try
  13. {
  14. size_t p = 0;
  15. auto decoded = decodeDmdString(sym, p);
  16. if (decoded.length && p==sym.length)
  17. sym = decoded;
  18. }
  19. catch (Throwable t) {}
  20. if (sym.startsWith("__D"))
  21. sym = sym[1..$];
  22. sizediff_t p;
  23. dem = demangle(sym).idup;
  24. string[] segments;
  25. if (dem != sym)
  26. {
  27. enum SUB_SPACE = '\xFF';
  28. enum SUB_PERIOD = '\xFE';
  29. int plevel = 0;
  30. auto str = dem.dup;
  31. foreach (ref c; str)
  32. if (c=='(')
  33. plevel++;
  34. else
  35. if (c==')')
  36. plevel--;
  37. else
  38. if (c==' ' && plevel)
  39. c = SUB_SPACE;
  40. else
  41. if (c=='.' && plevel)
  42. c = SUB_PERIOD;
  43. segments = assumeUnique(str).replace("...", [SUB_PERIOD, SUB_PERIOD, SUB_PERIOD]).split(".");
  44. bool ok = true;
  45. foreach (seg; segments)
  46. if (seg.isMangledTemplateInstance())
  47. ok = false;
  48. if (ok)
  49. {
  50. foreach (ref seg; segments)
  51. {
  52. if (seg.startsWith("extern (C) "))
  53. seg = seg["extern (C) ".length..$];
  54. if (seg.lastIndexOf(' ')>=0)
  55. seg = seg[seg.lastIndexOf(' ')+1..$];
  56. if (seg.indexOf('(')>=0)
  57. seg = seg[0..seg.indexOf('(')];
  58. if (seg.indexOf('!')>=0)
  59. seg = seg[0..seg.indexOf('!')];
  60. seg = seg
  61. .replace([SUB_SPACE], " ")
  62. .replace([SUB_PERIOD], ".");
  63. }
  64. if (segments[0].startsWith("TypeInfo_"))
  65. {
  66. // _D71TypeInfo_S4core3sys7windows8setupapi11__mixin114220SP_DRVINFO_DATA_V2_W6__initZ
  67. // TypeInfo_S4core3sys7windows8setupapi11__mixin114220SP_DRVINFO_DATA_V2_W.__init
  68. auto tiDigit = segments[0].representation.countUntil!isDigit;
  69. if (tiDigit > 0)
  70. {
  71. auto tiType = segments[0][9..tiDigit];
  72. auto tiSym = "_D" ~ segments[0][tiDigit..$] ~ "Z";
  73. auto tiDem = demangle(tiSym).idup;
  74. if (tiSym != tiDem)
  75. segments = tiDem.split(".") ~ ["TypeInfo" ~ (tiType.length ? "_" : "") ~ tiType] ~ segments[1..$];
  76. }
  77. }
  78. return segments;
  79. }
  80. // core.demangle failed, use simpler algorithm
  81. }
  82. if (sym.startsWith("_D") && sym.length>=4 && isDigit(sym[2]))
  83. {
  84. segments = sym[2..$].rlSplit();
  85. dem = segments.join(".");
  86. if (segments[0].startsWith("TypeInfo_"))
  87. {
  88. auto tiSegments = segments[0][9..$].rlSplitForce();
  89. if (tiSegments.length > 1)
  90. segments = tiSegments ~ ["TypeInfo"] ~ segments[1..$];
  91. else
  92. segments = ["TypeInfo"] ~ tiSegments ~ segments[1..$];
  93. }
  94. }
  95. else
  96. if (sym.startsWith("__d_"))
  97. segments = ["D internals", sym[4..$]];
  98. else
  99. if (sym.startsWith("_d_"))
  100. segments = ["D internals", sym[3..$]];
  101. else
  102. /*if (sym in cppSymbols)
  103. dem = cppSymbols[sym];
  104. else*/
  105. if (sym.startsWith("?"))
  106. {
  107. if (sym.indexOf("@@") > 0)
  108. {
  109. while (sym.startsWith("?"))
  110. sym = sym[1..$];
  111. while (sym.length && sym[0].isDigit())
  112. sym = sym[1..$];
  113. sym = sym[0..sym.indexOf("@@")];
  114. segments = sym.split("@");
  115. segments.reverse();
  116. dem = segments.join("::");
  117. }
  118. else
  119. segments = [sym];
  120. segments = ["C++ symbols"] ~ segments;
  121. }
  122. else
  123. if (sym.startsWith("_Z"))
  124. {
  125. segments = sym[2..$].rlSplitForce()[0..$-1];
  126. dem = segments.join("::");
  127. segments = ["C++ symbols"] ~ segments;
  128. }
  129. else
  130. if (sym.startsWith("__imp__"))
  131. segments = ["Imports", sym[7..$]];
  132. else
  133. if (sym.startsWith("_TMP"))
  134. segments = ["TMP", sym[4..$]];
  135. else
  136. if (sym.startsWith("__HandlerTable"))
  137. segments = ["Exception handler tables", sym["__HandlerTable".length..$]];
  138. else
  139. if ((p = sym.indexOf(": ")) > 0)
  140. {
  141. segments = sym[0..p] ~ parseDSymbol(sym[p+2..$], dem);
  142. dem = sym[0..p+2] ~ dem;
  143. }
  144. else
  145. if (sym.startsWith("_"))
  146. {
  147. auto str = sym;
  148. while (str.startsWith("_")) str = str[1..$];
  149. p = str.indexOf("_");
  150. if (p > 0)
  151. segments = ["C symbols", str[0..p], str[p+1..$]];
  152. else
  153. segments = ["C symbols", str];
  154. }
  155. else
  156. if (sym.startsWith("gc_"))
  157. segments = ["gc", sym];
  158. else
  159. if (sym.startsWith("/"))
  160. {
  161. auto str = sym
  162. .replace(" (", "(")
  163. .replace("(", "/")
  164. .replace(")", "");
  165. segments = str.split("/");
  166. segments[0] = "/";
  167. int j = 0;
  168. while (j < segments.length-1)
  169. if (segments[j+1] == "..")
  170. segments = segments[0..j] ~ segments[j+2..$],
  171. j--;
  172. else
  173. j++;
  174. }
  175. else
  176. if (sym.endsWith(" (*fill*)"))
  177. segments = ["(*fill*)", sym];
  178. else
  179. if (sym == "internal" || sym == "anon")
  180. segments = [sym, ""];
  181. else
  182. segments = [sym];
  183. return segments;
  184. }
  185. string[] rlSplit(string str, bool force=false)
  186. {
  187. string[] segments;
  188. while (str.length)
  189. {
  190. try
  191. {
  192. if (force)
  193. while (str.length && !isDigit(str[0]))
  194. str = str[1..$];
  195. auto len = parse!uint(str);
  196. enforce(len <= str.length);
  197. segments ~= rlSubSplit(str[0..len]);
  198. str = str[len..$];
  199. //while (str.length && !isDigit(str[0]))
  200. // str = str[1..$];
  201. }
  202. catch (Exception e)
  203. {
  204. if (str != "Z")
  205. segments ~= str;
  206. str = null;
  207. }
  208. }
  209. return segments;
  210. }
  211. string[] rlSplitForce(string str)
  212. {
  213. auto s = str;
  214. try
  215. {
  216. while (s.length && !isDigit(s[0]))
  217. s = s[1..$];
  218. enforce(s.length);
  219. return rlSplit(s);
  220. }
  221. catch (Exception e)
  222. return [str];
  223. }
  224. bool isMangledTemplateInstance(string s)
  225. {
  226. return s.length > 4 && s.startsWith("__T") && isDigit(s[3]);
  227. }
  228. string[] rlSubSplit(string s)
  229. {
  230. if (s.isMangledTemplateInstance())
  231. return s[3..$].rlSplit();
  232. else
  233. return s.split("/");
  234. }