frida 16.2.1 → 16.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (386) hide show
  1. package/BSDmakefile +6 -0
  2. package/Makefile +16 -0
  3. package/README.md +14 -11
  4. package/configure +18 -0
  5. package/configure.bat +22 -0
  6. package/dist/native.js +0 -8
  7. package/lib/application.ts +98 -0
  8. package/lib/authentication.ts +3 -0
  9. package/lib/build.py +50 -0
  10. package/lib/bus.ts +30 -0
  11. package/lib/cancellable.ts +33 -0
  12. package/lib/child.ts +15 -0
  13. package/lib/crash.ts +11 -0
  14. package/lib/device.ts +329 -0
  15. package/lib/device_manager.ts +69 -0
  16. package/lib/endpoint_parameters.ts +56 -0
  17. package/lib/icon.ts +15 -0
  18. package/lib/index.ts +311 -0
  19. package/lib/iostream.ts +78 -0
  20. package/lib/meson.build +53 -0
  21. package/lib/native.ts +9 -0
  22. package/lib/portal_membership.ts +10 -0
  23. package/lib/portal_service.ts +105 -0
  24. package/lib/process.ts +57 -0
  25. package/lib/relay.ts +44 -0
  26. package/lib/script.ts +352 -0
  27. package/lib/session.ts +113 -0
  28. package/lib/signals.ts +45 -0
  29. package/lib/socket_address.ts +35 -0
  30. package/lib/spawn.ts +4 -0
  31. package/lib/system_parameters.ts +78 -0
  32. package/make.bat +23 -0
  33. package/meson.build +160 -0
  34. package/meson.options +11 -0
  35. package/package.json +27 -6
  36. package/releng/deps.py +1133 -0
  37. package/releng/deps.toml +391 -0
  38. package/releng/devkit-assets/frida-core-example-unix.c +188 -0
  39. package/releng/devkit-assets/frida-core-example-windows.c +197 -0
  40. package/releng/devkit-assets/frida-core-example.sln +28 -0
  41. package/releng/devkit-assets/frida-core-example.vcxproj +157 -0
  42. package/releng/devkit-assets/frida-core-example.vcxproj.filters +27 -0
  43. package/releng/devkit-assets/frida-gum-example-unix.c +122 -0
  44. package/releng/devkit-assets/frida-gum-example-windows.c +132 -0
  45. package/releng/devkit-assets/frida-gum-example.sln +28 -0
  46. package/releng/devkit-assets/frida-gum-example.vcxproj +157 -0
  47. package/releng/devkit-assets/frida-gum-example.vcxproj.filters +27 -0
  48. package/releng/devkit-assets/frida-gumjs-example-unix.c +84 -0
  49. package/releng/devkit-assets/frida-gumjs-example-windows.c +91 -0
  50. package/releng/devkit-assets/frida-gumjs-example.sln +28 -0
  51. package/releng/devkit-assets/frida-gumjs-example.vcxproj +157 -0
  52. package/releng/devkit-assets/frida-gumjs-example.vcxproj.filters +27 -0
  53. package/releng/devkit.py +535 -0
  54. package/releng/env.py +420 -0
  55. package/releng/env_android.py +150 -0
  56. package/releng/env_apple.py +176 -0
  57. package/releng/env_generic.py +373 -0
  58. package/releng/frida_version.py +69 -0
  59. package/releng/machine_file.py +44 -0
  60. package/releng/machine_spec.py +290 -0
  61. package/releng/meson/meson.py +27 -0
  62. package/releng/meson/mesonbuild/__init__.py +0 -0
  63. package/releng/meson/mesonbuild/_pathlib.py +63 -0
  64. package/releng/meson/mesonbuild/_typing.py +69 -0
  65. package/releng/meson/mesonbuild/arglist.py +321 -0
  66. package/releng/meson/mesonbuild/ast/__init__.py +23 -0
  67. package/releng/meson/mesonbuild/ast/interpreter.py +441 -0
  68. package/releng/meson/mesonbuild/ast/introspection.py +374 -0
  69. package/releng/meson/mesonbuild/ast/postprocess.py +109 -0
  70. package/releng/meson/mesonbuild/ast/printer.py +620 -0
  71. package/releng/meson/mesonbuild/ast/visitor.py +161 -0
  72. package/releng/meson/mesonbuild/backend/__init__.py +0 -0
  73. package/releng/meson/mesonbuild/backend/backends.py +2047 -0
  74. package/releng/meson/mesonbuild/backend/ninjabackend.py +3808 -0
  75. package/releng/meson/mesonbuild/backend/nonebackend.py +26 -0
  76. package/releng/meson/mesonbuild/backend/vs2010backend.py +2078 -0
  77. package/releng/meson/mesonbuild/backend/vs2012backend.py +35 -0
  78. package/releng/meson/mesonbuild/backend/vs2013backend.py +34 -0
  79. package/releng/meson/mesonbuild/backend/vs2015backend.py +35 -0
  80. package/releng/meson/mesonbuild/backend/vs2017backend.py +59 -0
  81. package/releng/meson/mesonbuild/backend/vs2019backend.py +54 -0
  82. package/releng/meson/mesonbuild/backend/vs2022backend.py +54 -0
  83. package/releng/meson/mesonbuild/backend/xcodebackend.py +1781 -0
  84. package/releng/meson/mesonbuild/build.py +3249 -0
  85. package/releng/meson/mesonbuild/cargo/__init__.py +5 -0
  86. package/releng/meson/mesonbuild/cargo/builder.py +238 -0
  87. package/releng/meson/mesonbuild/cargo/cfg.py +274 -0
  88. package/releng/meson/mesonbuild/cargo/interpreter.py +733 -0
  89. package/releng/meson/mesonbuild/cargo/manifest.py +227 -0
  90. package/releng/meson/mesonbuild/cargo/version.py +95 -0
  91. package/releng/meson/mesonbuild/cmake/__init__.py +28 -0
  92. package/releng/meson/mesonbuild/cmake/common.py +331 -0
  93. package/releng/meson/mesonbuild/cmake/data/__init__.py +0 -0
  94. package/releng/meson/mesonbuild/cmake/data/preload.cmake +82 -0
  95. package/releng/meson/mesonbuild/cmake/executor.py +241 -0
  96. package/releng/meson/mesonbuild/cmake/fileapi.py +324 -0
  97. package/releng/meson/mesonbuild/cmake/generator.py +186 -0
  98. package/releng/meson/mesonbuild/cmake/interpreter.py +1267 -0
  99. package/releng/meson/mesonbuild/cmake/toolchain.py +248 -0
  100. package/releng/meson/mesonbuild/cmake/traceparser.py +814 -0
  101. package/releng/meson/mesonbuild/cmake/tracetargets.py +161 -0
  102. package/releng/meson/mesonbuild/compilers/__init__.py +86 -0
  103. package/releng/meson/mesonbuild/compilers/asm.py +307 -0
  104. package/releng/meson/mesonbuild/compilers/c.py +788 -0
  105. package/releng/meson/mesonbuild/compilers/c_function_attributes.py +143 -0
  106. package/releng/meson/mesonbuild/compilers/compilers.py +1388 -0
  107. package/releng/meson/mesonbuild/compilers/cpp.py +1035 -0
  108. package/releng/meson/mesonbuild/compilers/cs.py +136 -0
  109. package/releng/meson/mesonbuild/compilers/cuda.py +806 -0
  110. package/releng/meson/mesonbuild/compilers/cython.py +91 -0
  111. package/releng/meson/mesonbuild/compilers/d.py +861 -0
  112. package/releng/meson/mesonbuild/compilers/detect.py +1396 -0
  113. package/releng/meson/mesonbuild/compilers/fortran.py +523 -0
  114. package/releng/meson/mesonbuild/compilers/java.py +113 -0
  115. package/releng/meson/mesonbuild/compilers/mixins/__init__.py +0 -0
  116. package/releng/meson/mesonbuild/compilers/mixins/arm.py +167 -0
  117. package/releng/meson/mesonbuild/compilers/mixins/ccrx.py +113 -0
  118. package/releng/meson/mesonbuild/compilers/mixins/clang.py +170 -0
  119. package/releng/meson/mesonbuild/compilers/mixins/clike.py +1330 -0
  120. package/releng/meson/mesonbuild/compilers/mixins/compcert.py +117 -0
  121. package/releng/meson/mesonbuild/compilers/mixins/elbrus.py +93 -0
  122. package/releng/meson/mesonbuild/compilers/mixins/emscripten.py +89 -0
  123. package/releng/meson/mesonbuild/compilers/mixins/gnu.py +629 -0
  124. package/releng/meson/mesonbuild/compilers/mixins/intel.py +167 -0
  125. package/releng/meson/mesonbuild/compilers/mixins/islinker.py +120 -0
  126. package/releng/meson/mesonbuild/compilers/mixins/metrowerks.py +279 -0
  127. package/releng/meson/mesonbuild/compilers/mixins/pgi.py +88 -0
  128. package/releng/meson/mesonbuild/compilers/mixins/ti.py +130 -0
  129. package/releng/meson/mesonbuild/compilers/mixins/visualstudio.py +458 -0
  130. package/releng/meson/mesonbuild/compilers/mixins/xc16.py +111 -0
  131. package/releng/meson/mesonbuild/compilers/objc.py +120 -0
  132. package/releng/meson/mesonbuild/compilers/objcpp.py +102 -0
  133. package/releng/meson/mesonbuild/compilers/rust.py +230 -0
  134. package/releng/meson/mesonbuild/compilers/swift.py +131 -0
  135. package/releng/meson/mesonbuild/compilers/vala.py +121 -0
  136. package/releng/meson/mesonbuild/coredata.py +1532 -0
  137. package/releng/meson/mesonbuild/dependencies/__init__.py +252 -0
  138. package/releng/meson/mesonbuild/dependencies/base.py +663 -0
  139. package/releng/meson/mesonbuild/dependencies/boost.py +1083 -0
  140. package/releng/meson/mesonbuild/dependencies/cmake.py +656 -0
  141. package/releng/meson/mesonbuild/dependencies/coarrays.py +80 -0
  142. package/releng/meson/mesonbuild/dependencies/configtool.py +163 -0
  143. package/releng/meson/mesonbuild/dependencies/cuda.py +295 -0
  144. package/releng/meson/mesonbuild/dependencies/data/CMakeLists.txt +102 -0
  145. package/releng/meson/mesonbuild/dependencies/data/CMakeListsLLVM.txt +204 -0
  146. package/releng/meson/mesonbuild/dependencies/data/CMakePathInfo.txt +31 -0
  147. package/releng/meson/mesonbuild/dependencies/data/__init__.py +0 -0
  148. package/releng/meson/mesonbuild/dependencies/detect.py +225 -0
  149. package/releng/meson/mesonbuild/dependencies/dev.py +707 -0
  150. package/releng/meson/mesonbuild/dependencies/dub.py +424 -0
  151. package/releng/meson/mesonbuild/dependencies/factory.py +146 -0
  152. package/releng/meson/mesonbuild/dependencies/framework.py +111 -0
  153. package/releng/meson/mesonbuild/dependencies/hdf5.py +168 -0
  154. package/releng/meson/mesonbuild/dependencies/misc.py +618 -0
  155. package/releng/meson/mesonbuild/dependencies/mpi.py +231 -0
  156. package/releng/meson/mesonbuild/dependencies/pkgconfig.py +570 -0
  157. package/releng/meson/mesonbuild/dependencies/platform.py +52 -0
  158. package/releng/meson/mesonbuild/dependencies/python.py +431 -0
  159. package/releng/meson/mesonbuild/dependencies/qt.py +484 -0
  160. package/releng/meson/mesonbuild/dependencies/scalapack.py +142 -0
  161. package/releng/meson/mesonbuild/dependencies/ui.py +281 -0
  162. package/releng/meson/mesonbuild/depfile.py +82 -0
  163. package/releng/meson/mesonbuild/envconfig.py +480 -0
  164. package/releng/meson/mesonbuild/environment.py +987 -0
  165. package/releng/meson/mesonbuild/interpreter/__init__.py +47 -0
  166. package/releng/meson/mesonbuild/interpreter/compiler.py +900 -0
  167. package/releng/meson/mesonbuild/interpreter/dependencyfallbacks.py +386 -0
  168. package/releng/meson/mesonbuild/interpreter/interpreter.py +3595 -0
  169. package/releng/meson/mesonbuild/interpreter/interpreterobjects.py +1096 -0
  170. package/releng/meson/mesonbuild/interpreter/kwargs.py +479 -0
  171. package/releng/meson/mesonbuild/interpreter/mesonmain.py +487 -0
  172. package/releng/meson/mesonbuild/interpreter/primitives/__init__.py +29 -0
  173. package/releng/meson/mesonbuild/interpreter/primitives/array.py +108 -0
  174. package/releng/meson/mesonbuild/interpreter/primitives/boolean.py +52 -0
  175. package/releng/meson/mesonbuild/interpreter/primitives/dict.py +88 -0
  176. package/releng/meson/mesonbuild/interpreter/primitives/integer.py +86 -0
  177. package/releng/meson/mesonbuild/interpreter/primitives/range.py +38 -0
  178. package/releng/meson/mesonbuild/interpreter/primitives/string.py +247 -0
  179. package/releng/meson/mesonbuild/interpreter/type_checking.py +853 -0
  180. package/releng/meson/mesonbuild/interpreterbase/__init__.py +126 -0
  181. package/releng/meson/mesonbuild/interpreterbase/_unholder.py +25 -0
  182. package/releng/meson/mesonbuild/interpreterbase/baseobjects.py +174 -0
  183. package/releng/meson/mesonbuild/interpreterbase/decorators.py +806 -0
  184. package/releng/meson/mesonbuild/interpreterbase/disabler.py +35 -0
  185. package/releng/meson/mesonbuild/interpreterbase/exceptions.py +22 -0
  186. package/releng/meson/mesonbuild/interpreterbase/helpers.py +67 -0
  187. package/releng/meson/mesonbuild/interpreterbase/interpreterbase.py +665 -0
  188. package/releng/meson/mesonbuild/interpreterbase/operator.py +32 -0
  189. package/releng/meson/mesonbuild/linkers/__init__.py +20 -0
  190. package/releng/meson/mesonbuild/linkers/base.py +39 -0
  191. package/releng/meson/mesonbuild/linkers/detect.py +229 -0
  192. package/releng/meson/mesonbuild/linkers/linkers.py +1614 -0
  193. package/releng/meson/mesonbuild/mcompile.py +380 -0
  194. package/releng/meson/mesonbuild/mconf.py +368 -0
  195. package/releng/meson/mesonbuild/mdevenv.py +234 -0
  196. package/releng/meson/mesonbuild/mdist.py +376 -0
  197. package/releng/meson/mesonbuild/mesondata.py +38 -0
  198. package/releng/meson/mesonbuild/mesonlib.py +23 -0
  199. package/releng/meson/mesonbuild/mesonmain.py +289 -0
  200. package/releng/meson/mesonbuild/minit.py +204 -0
  201. package/releng/meson/mesonbuild/minstall.py +864 -0
  202. package/releng/meson/mesonbuild/mintro.py +667 -0
  203. package/releng/meson/mesonbuild/mlog.py +542 -0
  204. package/releng/meson/mesonbuild/modules/__init__.py +270 -0
  205. package/releng/meson/mesonbuild/modules/cmake.py +442 -0
  206. package/releng/meson/mesonbuild/modules/cuda.py +377 -0
  207. package/releng/meson/mesonbuild/modules/dlang.py +117 -0
  208. package/releng/meson/mesonbuild/modules/external_project.py +306 -0
  209. package/releng/meson/mesonbuild/modules/fs.py +323 -0
  210. package/releng/meson/mesonbuild/modules/gnome.py +2215 -0
  211. package/releng/meson/mesonbuild/modules/hotdoc.py +487 -0
  212. package/releng/meson/mesonbuild/modules/i18n.py +405 -0
  213. package/releng/meson/mesonbuild/modules/icestorm.py +123 -0
  214. package/releng/meson/mesonbuild/modules/java.py +112 -0
  215. package/releng/meson/mesonbuild/modules/keyval.py +65 -0
  216. package/releng/meson/mesonbuild/modules/modtest.py +33 -0
  217. package/releng/meson/mesonbuild/modules/pkgconfig.py +744 -0
  218. package/releng/meson/mesonbuild/modules/python.py +556 -0
  219. package/releng/meson/mesonbuild/modules/python3.py +85 -0
  220. package/releng/meson/mesonbuild/modules/qt.py +621 -0
  221. package/releng/meson/mesonbuild/modules/qt4.py +23 -0
  222. package/releng/meson/mesonbuild/modules/qt5.py +23 -0
  223. package/releng/meson/mesonbuild/modules/qt6.py +22 -0
  224. package/releng/meson/mesonbuild/modules/rust.py +355 -0
  225. package/releng/meson/mesonbuild/modules/simd.py +114 -0
  226. package/releng/meson/mesonbuild/modules/sourceset.py +291 -0
  227. package/releng/meson/mesonbuild/modules/wayland.py +151 -0
  228. package/releng/meson/mesonbuild/modules/windows.py +207 -0
  229. package/releng/meson/mesonbuild/mparser.py +1114 -0
  230. package/releng/meson/mesonbuild/msetup.py +365 -0
  231. package/releng/meson/mesonbuild/msubprojects.py +764 -0
  232. package/releng/meson/mesonbuild/mtest.py +2201 -0
  233. package/releng/meson/mesonbuild/munstable_coredata.py +107 -0
  234. package/releng/meson/mesonbuild/optinterpreter.py +276 -0
  235. package/releng/meson/mesonbuild/programs.py +367 -0
  236. package/releng/meson/mesonbuild/rewriter.py +1075 -0
  237. package/releng/meson/mesonbuild/scripts/__init__.py +10 -0
  238. package/releng/meson/mesonbuild/scripts/clangformat.py +55 -0
  239. package/releng/meson/mesonbuild/scripts/clangtidy.py +30 -0
  240. package/releng/meson/mesonbuild/scripts/cleantrees.py +35 -0
  241. package/releng/meson/mesonbuild/scripts/cmake_run_ctgt.py +103 -0
  242. package/releng/meson/mesonbuild/scripts/cmd_or_ps.ps1 +17 -0
  243. package/releng/meson/mesonbuild/scripts/copy.py +19 -0
  244. package/releng/meson/mesonbuild/scripts/coverage.py +214 -0
  245. package/releng/meson/mesonbuild/scripts/delwithsuffix.py +27 -0
  246. package/releng/meson/mesonbuild/scripts/depfixer.py +495 -0
  247. package/releng/meson/mesonbuild/scripts/depscan.py +198 -0
  248. package/releng/meson/mesonbuild/scripts/dirchanger.py +20 -0
  249. package/releng/meson/mesonbuild/scripts/env2mfile.py +402 -0
  250. package/releng/meson/mesonbuild/scripts/externalproject.py +106 -0
  251. package/releng/meson/mesonbuild/scripts/gettext.py +86 -0
  252. package/releng/meson/mesonbuild/scripts/gtkdochelper.py +286 -0
  253. package/releng/meson/mesonbuild/scripts/hotdochelper.py +40 -0
  254. package/releng/meson/mesonbuild/scripts/itstool.py +77 -0
  255. package/releng/meson/mesonbuild/scripts/meson_exe.py +115 -0
  256. package/releng/meson/mesonbuild/scripts/msgfmthelper.py +29 -0
  257. package/releng/meson/mesonbuild/scripts/pycompile.py +54 -0
  258. package/releng/meson/mesonbuild/scripts/python_info.py +121 -0
  259. package/releng/meson/mesonbuild/scripts/regen_checker.py +55 -0
  260. package/releng/meson/mesonbuild/scripts/run_tool.py +58 -0
  261. package/releng/meson/mesonbuild/scripts/scanbuild.py +57 -0
  262. package/releng/meson/mesonbuild/scripts/symbolextractor.py +322 -0
  263. package/releng/meson/mesonbuild/scripts/tags.py +44 -0
  264. package/releng/meson/mesonbuild/scripts/test_loaded_modules.py +14 -0
  265. package/releng/meson/mesonbuild/scripts/uninstall.py +41 -0
  266. package/releng/meson/mesonbuild/scripts/vcstagger.py +35 -0
  267. package/releng/meson/mesonbuild/scripts/yasm.py +24 -0
  268. package/releng/meson/mesonbuild/templates/__init__.py +0 -0
  269. package/releng/meson/mesonbuild/templates/cpptemplates.py +143 -0
  270. package/releng/meson/mesonbuild/templates/cstemplates.py +90 -0
  271. package/releng/meson/mesonbuild/templates/ctemplates.py +126 -0
  272. package/releng/meson/mesonbuild/templates/cudatemplates.py +143 -0
  273. package/releng/meson/mesonbuild/templates/dlangtemplates.py +109 -0
  274. package/releng/meson/mesonbuild/templates/fortrantemplates.py +101 -0
  275. package/releng/meson/mesonbuild/templates/javatemplates.py +94 -0
  276. package/releng/meson/mesonbuild/templates/mesontemplates.py +70 -0
  277. package/releng/meson/mesonbuild/templates/objcpptemplates.py +126 -0
  278. package/releng/meson/mesonbuild/templates/objctemplates.py +126 -0
  279. package/releng/meson/mesonbuild/templates/rusttemplates.py +79 -0
  280. package/releng/meson/mesonbuild/templates/samplefactory.py +41 -0
  281. package/releng/meson/mesonbuild/templates/sampleimpl.py +160 -0
  282. package/releng/meson/mesonbuild/templates/valatemplates.py +82 -0
  283. package/releng/meson/mesonbuild/utils/__init__.py +0 -0
  284. package/releng/meson/mesonbuild/utils/core.py +166 -0
  285. package/releng/meson/mesonbuild/utils/platform.py +27 -0
  286. package/releng/meson/mesonbuild/utils/posix.py +32 -0
  287. package/releng/meson/mesonbuild/utils/universal.py +2445 -0
  288. package/releng/meson/mesonbuild/utils/vsenv.py +126 -0
  289. package/releng/meson/mesonbuild/utils/win32.py +29 -0
  290. package/releng/meson/mesonbuild/wrap/__init__.py +59 -0
  291. package/releng/meson/mesonbuild/wrap/wrap.py +846 -0
  292. package/releng/meson/mesonbuild/wrap/wraptool.py +198 -0
  293. package/releng/meson-scripts/BSDmakefile +6 -0
  294. package/releng/meson-scripts/Makefile +16 -0
  295. package/releng/meson-scripts/configure +18 -0
  296. package/releng/meson-scripts/configure.bat +22 -0
  297. package/releng/meson-scripts/make.bat +23 -0
  298. package/releng/meson_configure.py +506 -0
  299. package/releng/meson_make.py +131 -0
  300. package/releng/mkdevkit.py +107 -0
  301. package/releng/mkfatmacho.py +54 -0
  302. package/releng/post-process-oabi.py +97 -0
  303. package/releng/progress.py +14 -0
  304. package/releng/sync-from-upstream.py +185 -0
  305. package/releng/tomlkit/tomlkit/__init__.py +59 -0
  306. package/releng/tomlkit/tomlkit/_compat.py +22 -0
  307. package/releng/tomlkit/tomlkit/_types.py +83 -0
  308. package/releng/tomlkit/tomlkit/_utils.py +158 -0
  309. package/releng/tomlkit/tomlkit/api.py +308 -0
  310. package/releng/tomlkit/tomlkit/container.py +875 -0
  311. package/releng/tomlkit/tomlkit/exceptions.py +227 -0
  312. package/releng/tomlkit/tomlkit/items.py +1967 -0
  313. package/releng/tomlkit/tomlkit/parser.py +1141 -0
  314. package/releng/tomlkit/tomlkit/py.typed +0 -0
  315. package/releng/tomlkit/tomlkit/source.py +180 -0
  316. package/releng/tomlkit/tomlkit/toml_char.py +52 -0
  317. package/releng/tomlkit/tomlkit/toml_document.py +7 -0
  318. package/releng/tomlkit/tomlkit/toml_file.py +58 -0
  319. package/releng/winenv.py +140 -0
  320. package/scripts/adjust-version.py +19 -0
  321. package/scripts/detect-version.py +40 -0
  322. package/scripts/fetch-abi-bits.py +343 -0
  323. package/scripts/install.js +23 -0
  324. package/scripts/package.py +15 -0
  325. package/src/addon.cc +76 -0
  326. package/src/application.cc +148 -0
  327. package/src/application.h +31 -0
  328. package/src/authentication.cc +174 -0
  329. package/src/authentication.h +24 -0
  330. package/src/bus.cc +167 -0
  331. package/src/bus.h +33 -0
  332. package/src/cancellable.cc +117 -0
  333. package/src/cancellable.h +31 -0
  334. package/src/child.cc +150 -0
  335. package/src/child.h +32 -0
  336. package/src/crash.cc +122 -0
  337. package/src/crash.h +30 -0
  338. package/src/device.cc +1302 -0
  339. package/src/device.h +55 -0
  340. package/src/device_manager.cc +362 -0
  341. package/src/device_manager.h +35 -0
  342. package/src/endpoint_parameters.cc +171 -0
  343. package/src/endpoint_parameters.h +28 -0
  344. package/src/glib_context.cc +62 -0
  345. package/src/glib_context.h +29 -0
  346. package/src/glib_object.cc +25 -0
  347. package/src/glib_object.h +37 -0
  348. package/src/iostream.cc +247 -0
  349. package/src/iostream.h +30 -0
  350. package/src/meson.build +26 -0
  351. package/src/operation.h +94 -0
  352. package/src/portal_membership.cc +100 -0
  353. package/src/portal_membership.h +26 -0
  354. package/src/portal_service.cc +401 -0
  355. package/src/portal_service.h +40 -0
  356. package/src/process.cc +135 -0
  357. package/src/process.h +30 -0
  358. package/src/relay.cc +139 -0
  359. package/src/relay.h +31 -0
  360. package/src/runtime.cc +443 -0
  361. package/src/runtime.h +64 -0
  362. package/src/script.cc +301 -0
  363. package/src/script.h +36 -0
  364. package/src/session.cc +860 -0
  365. package/src/session.h +42 -0
  366. package/src/signals.cc +334 -0
  367. package/src/signals.h +47 -0
  368. package/src/spawn.cc +95 -0
  369. package/src/spawn.h +27 -0
  370. package/src/usage_monitor.h +117 -0
  371. package/src/uv_context.cc +118 -0
  372. package/src/uv_context.h +40 -0
  373. package/src/win_delay_load_hook.cc +63 -0
  374. package/subprojects/frida-core.wrap +8 -0
  375. package/subprojects/nan.wrap +9 -0
  376. package/subprojects/packagefiles/nan.patch +13 -0
  377. package/test/data/index.ts +13 -0
  378. package/test/data/unixvictim-linux-x86 +0 -0
  379. package/test/data/unixvictim-linux-x86_64 +0 -0
  380. package/test/data/unixvictim-macos +0 -0
  381. package/test/device.ts +27 -0
  382. package/test/device_manager.ts +16 -0
  383. package/test/labrat.ts +32 -0
  384. package/test/script.ts +176 -0
  385. package/test/session.ts +73 -0
  386. package/tsconfig.json +18 -0
@@ -0,0 +1,495 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Copyright 2013-2016 The Meson development team
3
+
4
+ from __future__ import annotations
5
+
6
+
7
+ import sys
8
+ import os
9
+ import stat
10
+ import struct
11
+ import shutil
12
+ import subprocess
13
+ import typing as T
14
+
15
+ from ..mesonlib import OrderedSet, generate_list, Popen_safe
16
+
17
+ SHT_STRTAB = 3
18
+ DT_NEEDED = 1
19
+ DT_RPATH = 15
20
+ DT_RUNPATH = 29
21
+ DT_STRTAB = 5
22
+ DT_SONAME = 14
23
+ DT_MIPS_RLD_MAP_REL = 1879048245
24
+
25
+ # Global cache for tools
26
+ INSTALL_NAME_TOOL = False
27
+
28
+ class DataSizes:
29
+ def __init__(self, ptrsize: int, is_le: bool) -> None:
30
+ if is_le:
31
+ p = '<'
32
+ else:
33
+ p = '>'
34
+ self.Half = p + 'h'
35
+ self.HalfSize = 2
36
+ self.Word = p + 'I'
37
+ self.WordSize = 4
38
+ self.Sword = p + 'i'
39
+ self.SwordSize = 4
40
+ if ptrsize == 64:
41
+ self.Addr = p + 'Q'
42
+ self.AddrSize = 8
43
+ self.Off = p + 'Q'
44
+ self.OffSize = 8
45
+ self.XWord = p + 'Q'
46
+ self.XWordSize = 8
47
+ self.Sxword = p + 'q'
48
+ self.SxwordSize = 8
49
+ else:
50
+ self.Addr = p + 'I'
51
+ self.AddrSize = 4
52
+ self.Off = p + 'I'
53
+ self.OffSize = 4
54
+
55
+ class DynamicEntry(DataSizes):
56
+ def __init__(self, ifile: T.BinaryIO, ptrsize: int, is_le: bool) -> None:
57
+ super().__init__(ptrsize, is_le)
58
+ self.ptrsize = ptrsize
59
+ if ptrsize == 64:
60
+ self.d_tag = struct.unpack(self.Sxword, ifile.read(self.SxwordSize))[0]
61
+ self.val = struct.unpack(self.XWord, ifile.read(self.XWordSize))[0]
62
+ else:
63
+ self.d_tag = struct.unpack(self.Sword, ifile.read(self.SwordSize))[0]
64
+ self.val = struct.unpack(self.Word, ifile.read(self.WordSize))[0]
65
+
66
+ def write(self, ofile: T.BinaryIO) -> None:
67
+ if self.ptrsize == 64:
68
+ ofile.write(struct.pack(self.Sxword, self.d_tag))
69
+ ofile.write(struct.pack(self.XWord, self.val))
70
+ else:
71
+ ofile.write(struct.pack(self.Sword, self.d_tag))
72
+ ofile.write(struct.pack(self.Word, self.val))
73
+
74
+ class SectionHeader(DataSizes):
75
+ def __init__(self, ifile: T.BinaryIO, ptrsize: int, is_le: bool) -> None:
76
+ super().__init__(ptrsize, is_le)
77
+ is_64 = ptrsize == 64
78
+
79
+ # Elf64_Word
80
+ self.sh_name = struct.unpack(self.Word, ifile.read(self.WordSize))[0]
81
+ # Elf64_Word
82
+ self.sh_type = struct.unpack(self.Word, ifile.read(self.WordSize))[0]
83
+ # Elf64_Xword
84
+ if is_64:
85
+ self.sh_flags = struct.unpack(self.XWord, ifile.read(self.XWordSize))[0]
86
+ else:
87
+ self.sh_flags = struct.unpack(self.Word, ifile.read(self.WordSize))[0]
88
+ # Elf64_Addr
89
+ self.sh_addr = struct.unpack(self.Addr, ifile.read(self.AddrSize))[0]
90
+ # Elf64_Off
91
+ self.sh_offset = struct.unpack(self.Off, ifile.read(self.OffSize))[0]
92
+ # Elf64_Xword
93
+ if is_64:
94
+ self.sh_size = struct.unpack(self.XWord, ifile.read(self.XWordSize))[0]
95
+ else:
96
+ self.sh_size = struct.unpack(self.Word, ifile.read(self.WordSize))[0]
97
+ # Elf64_Word
98
+ self.sh_link = struct.unpack(self.Word, ifile.read(self.WordSize))[0]
99
+ # Elf64_Word
100
+ self.sh_info = struct.unpack(self.Word, ifile.read(self.WordSize))[0]
101
+ # Elf64_Xword
102
+ if is_64:
103
+ self.sh_addralign = struct.unpack(self.XWord, ifile.read(self.XWordSize))[0]
104
+ else:
105
+ self.sh_addralign = struct.unpack(self.Word, ifile.read(self.WordSize))[0]
106
+ # Elf64_Xword
107
+ if is_64:
108
+ self.sh_entsize = struct.unpack(self.XWord, ifile.read(self.XWordSize))[0]
109
+ else:
110
+ self.sh_entsize = struct.unpack(self.Word, ifile.read(self.WordSize))[0]
111
+
112
+ class Elf(DataSizes):
113
+ def __init__(self, bfile: str, verbose: bool = True) -> None:
114
+ self.bfile = bfile
115
+ self.verbose = verbose
116
+ self.sections: T.List[SectionHeader] = []
117
+ self.dynamic: T.List[DynamicEntry] = []
118
+ self.open_bf(bfile)
119
+ try:
120
+ (self.ptrsize, self.is_le) = self.detect_elf_type()
121
+ super().__init__(self.ptrsize, self.is_le)
122
+ self.parse_header()
123
+ self.parse_sections()
124
+ self.parse_dynamic()
125
+ except (struct.error, RuntimeError):
126
+ self.close_bf()
127
+ raise
128
+
129
+ def open_bf(self, bfile: str) -> None:
130
+ self.bf = None
131
+ self.bf_perms = None
132
+ try:
133
+ self.bf = open(bfile, 'r+b')
134
+ except PermissionError as e:
135
+ self.bf_perms = stat.S_IMODE(os.lstat(bfile).st_mode)
136
+ os.chmod(bfile, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
137
+ try:
138
+ self.bf = open(bfile, 'r+b')
139
+ except Exception:
140
+ os.chmod(bfile, self.bf_perms)
141
+ self.bf_perms = None
142
+ raise e
143
+
144
+ def close_bf(self) -> None:
145
+ if self.bf is not None:
146
+ if self.bf_perms is not None:
147
+ os.chmod(self.bf.fileno(), self.bf_perms)
148
+ self.bf_perms = None
149
+ self.bf.close()
150
+ self.bf = None
151
+
152
+ def __enter__(self) -> 'Elf':
153
+ return self
154
+
155
+ def __del__(self) -> None:
156
+ self.close_bf()
157
+
158
+ def __exit__(self, exc_type: T.Any, exc_value: T.Any, traceback: T.Any) -> None:
159
+ self.close_bf()
160
+
161
+ def detect_elf_type(self) -> T.Tuple[int, bool]:
162
+ data = self.bf.read(6)
163
+ if data[1:4] != b'ELF':
164
+ # This script gets called to non-elf targets too
165
+ # so just ignore them.
166
+ if self.verbose:
167
+ print(f'File {self.bfile!r} is not an ELF file.')
168
+ sys.exit(0)
169
+ if data[4] == 1:
170
+ ptrsize = 32
171
+ elif data[4] == 2:
172
+ ptrsize = 64
173
+ else:
174
+ sys.exit(f'File {self.bfile!r} has unknown ELF class.')
175
+ if data[5] == 1:
176
+ is_le = True
177
+ elif data[5] == 2:
178
+ is_le = False
179
+ else:
180
+ sys.exit(f'File {self.bfile!r} has unknown ELF endianness.')
181
+ return ptrsize, is_le
182
+
183
+ def parse_header(self) -> None:
184
+ self.bf.seek(0)
185
+ self.e_ident = struct.unpack('16s', self.bf.read(16))[0]
186
+ self.e_type = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0]
187
+ self.e_machine = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0]
188
+ self.e_version = struct.unpack(self.Word, self.bf.read(self.WordSize))[0]
189
+ self.e_entry = struct.unpack(self.Addr, self.bf.read(self.AddrSize))[0]
190
+ self.e_phoff = struct.unpack(self.Off, self.bf.read(self.OffSize))[0]
191
+ self.e_shoff = struct.unpack(self.Off, self.bf.read(self.OffSize))[0]
192
+ self.e_flags = struct.unpack(self.Word, self.bf.read(self.WordSize))[0]
193
+ self.e_ehsize = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0]
194
+ self.e_phentsize = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0]
195
+ self.e_phnum = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0]
196
+ self.e_shentsize = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0]
197
+ self.e_shnum = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0]
198
+ self.e_shstrndx = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0]
199
+
200
+ def parse_sections(self) -> None:
201
+ self.bf.seek(self.e_shoff)
202
+ for _ in range(self.e_shnum):
203
+ self.sections.append(SectionHeader(self.bf, self.ptrsize, self.is_le))
204
+
205
+ def read_str(self) -> bytes:
206
+ arr = []
207
+ x = self.bf.read(1)
208
+ while x != b'\0':
209
+ arr.append(x)
210
+ x = self.bf.read(1)
211
+ if x == b'':
212
+ raise RuntimeError('Tried to read past the end of the file')
213
+ return b''.join(arr)
214
+
215
+ def find_section(self, target_name: bytes) -> T.Optional[SectionHeader]:
216
+ section_names = self.sections[self.e_shstrndx]
217
+ for i in self.sections:
218
+ self.bf.seek(section_names.sh_offset + i.sh_name)
219
+ name = self.read_str()
220
+ if name == target_name:
221
+ return i
222
+ return None
223
+
224
+ def parse_dynamic(self) -> None:
225
+ sec = self.find_section(b'.dynamic')
226
+ if sec is None:
227
+ return
228
+ self.bf.seek(sec.sh_offset)
229
+ while True:
230
+ e = DynamicEntry(self.bf, self.ptrsize, self.is_le)
231
+ self.dynamic.append(e)
232
+ if e.d_tag == 0:
233
+ break
234
+
235
+ @generate_list
236
+ def get_section_names(self) -> T.Generator[str, None, None]:
237
+ section_names = self.sections[self.e_shstrndx]
238
+ for i in self.sections:
239
+ self.bf.seek(section_names.sh_offset + i.sh_name)
240
+ yield self.read_str().decode()
241
+
242
+ def get_soname(self) -> T.Optional[str]:
243
+ soname = None
244
+ strtab = None
245
+ for i in self.dynamic:
246
+ if i.d_tag == DT_SONAME:
247
+ soname = i
248
+ if i.d_tag == DT_STRTAB:
249
+ strtab = i
250
+ if soname is None or strtab is None:
251
+ return None
252
+ self.bf.seek(strtab.val + soname.val)
253
+ return self.read_str().decode()
254
+
255
+ def get_entry_offset(self, entrynum: int) -> T.Optional[int]:
256
+ sec = self.find_section(b'.dynstr')
257
+ for i in self.dynamic:
258
+ if i.d_tag == entrynum:
259
+ res = sec.sh_offset + i.val
260
+ assert isinstance(res, int)
261
+ return res
262
+ return None
263
+
264
+ def get_rpath(self) -> T.Optional[str]:
265
+ offset = self.get_entry_offset(DT_RPATH)
266
+ if offset is None:
267
+ return None
268
+ self.bf.seek(offset)
269
+ return self.read_str().decode()
270
+
271
+ def get_runpath(self) -> T.Optional[str]:
272
+ offset = self.get_entry_offset(DT_RUNPATH)
273
+ if offset is None:
274
+ return None
275
+ self.bf.seek(offset)
276
+ return self.read_str().decode()
277
+
278
+ @generate_list
279
+ def get_deps(self) -> T.Generator[str, None, None]:
280
+ sec = self.find_section(b'.dynstr')
281
+ for i in self.dynamic:
282
+ if i.d_tag == DT_NEEDED:
283
+ offset = sec.sh_offset + i.val
284
+ self.bf.seek(offset)
285
+ yield self.read_str().decode()
286
+
287
+ def fix_deps(self, prefix: bytes) -> None:
288
+ sec = self.find_section(b'.dynstr')
289
+ deps = []
290
+ for i in self.dynamic:
291
+ if i.d_tag == DT_NEEDED:
292
+ deps.append(i)
293
+ for i in deps:
294
+ offset = sec.sh_offset + i.val
295
+ self.bf.seek(offset)
296
+ name = self.read_str()
297
+ if name.startswith(prefix):
298
+ basename = name.rsplit(b'/', maxsplit=1)[-1]
299
+ padding = b'\0' * (len(name) - len(basename))
300
+ newname = basename + padding
301
+ assert len(newname) == len(name)
302
+ self.bf.seek(offset)
303
+ self.bf.write(newname)
304
+
305
+ def fix_rpath(self, fname: str, rpath_dirs_to_remove: T.Set[bytes], new_rpath: bytes) -> None:
306
+ # The path to search for can be either rpath or runpath.
307
+ # Fix both of them to be sure.
308
+ self.fix_rpathtype_entry(fname, rpath_dirs_to_remove, new_rpath, DT_RPATH)
309
+ self.fix_rpathtype_entry(fname, rpath_dirs_to_remove, new_rpath, DT_RUNPATH)
310
+
311
+ def fix_rpathtype_entry(self, fname: str, rpath_dirs_to_remove: T.Set[bytes], new_rpath: bytes, entrynum: int) -> None:
312
+ rp_off = self.get_entry_offset(entrynum)
313
+ if rp_off is None:
314
+ if self.verbose:
315
+ print(f'File {fname!r} does not have an rpath. It should be a fully static executable.')
316
+ return
317
+ self.bf.seek(rp_off)
318
+
319
+ old_rpath = self.read_str()
320
+ # Some rpath entries may come from multiple sources.
321
+ # Only add each one once.
322
+ new_rpaths: OrderedSet[bytes] = OrderedSet()
323
+ if new_rpath:
324
+ new_rpaths.update(new_rpath.split(b':'))
325
+ if old_rpath:
326
+ # Filter out build-only rpath entries
327
+ # added by get_link_dep_subdirs() or
328
+ # specified by user with build_rpath.
329
+ for rpath_dir in old_rpath.split(b':'):
330
+ if not (rpath_dir in rpath_dirs_to_remove or
331
+ rpath_dir == (b'X' * len(rpath_dir))):
332
+ if rpath_dir:
333
+ new_rpaths.add(rpath_dir)
334
+
335
+ # Prepend user-specified new entries while preserving the ones that came from pkgconfig etc.
336
+ new_rpath = b':'.join(new_rpaths)
337
+
338
+ if len(old_rpath) < len(new_rpath):
339
+ msg = "New rpath must not be longer than the old one.\n Old: {}\n New: {}".format(old_rpath.decode('utf-8'), new_rpath.decode('utf-8'))
340
+ sys.exit(msg)
341
+ # The linker does read-only string deduplication. If there is a
342
+ # string that shares a suffix with the rpath, they might get
343
+ # deduped. This means changing the rpath string might break something
344
+ # completely unrelated. This has already happened once with X.org.
345
+ # Thus we want to keep this change as small as possible to minimize
346
+ # the chance of obliterating other strings. It might still happen
347
+ # but our behavior is identical to what chrpath does and it has
348
+ # been in use for ages so based on that this should be rare.
349
+ if not new_rpath:
350
+ self.remove_rpath_entry(entrynum)
351
+ else:
352
+ self.bf.seek(rp_off)
353
+ self.bf.write(new_rpath)
354
+ self.bf.write(b'\0')
355
+
356
+ def remove_rpath_entry(self, entrynum: int) -> None:
357
+ sec = self.find_section(b'.dynamic')
358
+ if sec is None:
359
+ return None
360
+ for (i, entry) in enumerate(self.dynamic):
361
+ if entry.d_tag == entrynum:
362
+ rpentry = self.dynamic[i]
363
+ rpentry.d_tag = 0
364
+ self.dynamic = self.dynamic[:i] + self.dynamic[i + 1:] + [rpentry]
365
+ break
366
+ # DT_MIPS_RLD_MAP_REL is relative to the offset of the tag. Adjust it consequently.
367
+ for entry in self.dynamic[i:]:
368
+ if entry.d_tag == DT_MIPS_RLD_MAP_REL:
369
+ entry.val += 2 * (self.ptrsize // 8)
370
+ break
371
+ self.bf.seek(sec.sh_offset)
372
+ for entry in self.dynamic:
373
+ entry.write(self.bf)
374
+ return None
375
+
376
+ def fix_elf(fname: str, rpath_dirs_to_remove: T.Set[bytes], new_rpath: T.Optional[bytes], verbose: bool = True) -> None:
377
+ if new_rpath is not None:
378
+ with Elf(fname, verbose) as e:
379
+ # note: e.get_rpath() and e.get_runpath() may be useful
380
+ e.fix_rpath(fname, rpath_dirs_to_remove, new_rpath)
381
+
382
+ def get_darwin_rpaths_to_remove(fname: str) -> T.List[str]:
383
+ p, out, _ = Popen_safe(['otool', '-l', fname], stderr=subprocess.DEVNULL)
384
+ if p.returncode != 0:
385
+ raise subprocess.CalledProcessError(p.returncode, p.args, out)
386
+ result = []
387
+ current_cmd = 'FOOBAR'
388
+ for line in out.split('\n'):
389
+ line = line.strip()
390
+ if ' ' not in line:
391
+ continue
392
+ key, value = line.strip().split(' ', 1)
393
+ if key == 'cmd':
394
+ current_cmd = value
395
+ if key == 'path' and current_cmd == 'LC_RPATH':
396
+ rp = value.split('(', 1)[0].strip()
397
+ result.append(rp)
398
+ return result
399
+
400
+ def fix_darwin(fname: str, new_rpath: str, final_path: str, install_name_mappings: T.Dict[str, str]) -> None:
401
+ try:
402
+ rpaths = get_darwin_rpaths_to_remove(fname)
403
+ except subprocess.CalledProcessError:
404
+ # Otool failed, which happens when invoked on a
405
+ # non-executable target. Just return.
406
+ return
407
+ try:
408
+ args = []
409
+ if rpaths:
410
+ # TODO: fix this properly, not totally clear how
411
+ #
412
+ # removing rpaths from binaries on macOS has tons of
413
+ # weird edge cases. For instance, if the user provided
414
+ # a '-Wl,-rpath' argument in LDFLAGS that happens to
415
+ # coincide with an rpath generated from a dependency,
416
+ # this would cause installation failures, as meson would
417
+ # generate install_name_tool calls with two identical
418
+ # '-delete_rpath' arguments, which install_name_tool
419
+ # fails on. Because meson itself ensures that it never
420
+ # adds duplicate rpaths, duplicate rpaths necessarily
421
+ # come from user variables. The idea of using OrderedSet
422
+ # is to remove *at most one* duplicate RPATH entry. This
423
+ # is not optimal, as it only respects the user's choice
424
+ # partially: if they provided a non-duplicate '-Wl,-rpath'
425
+ # argument, it gets removed, if they provided a duplicate
426
+ # one, it remains in the final binary. A potentially optimal
427
+ # solution would split all user '-Wl,-rpath' arguments from
428
+ # LDFLAGS, and later add them back with '-add_rpath'.
429
+ for rp in OrderedSet(rpaths):
430
+ args += ['-delete_rpath', rp]
431
+ subprocess.check_call(['install_name_tool', fname] + args,
432
+ stdout=subprocess.DEVNULL,
433
+ stderr=subprocess.DEVNULL)
434
+ args = []
435
+ if new_rpath:
436
+ args += ['-add_rpath', new_rpath]
437
+ # Rewrite -install_name @rpath/libfoo.dylib to /path/to/libfoo.dylib
438
+ if fname.endswith('dylib'):
439
+ args += ['-id', final_path]
440
+ if install_name_mappings:
441
+ for old, new in install_name_mappings.items():
442
+ args += ['-change', old, new]
443
+ if args:
444
+ subprocess.check_call(['install_name_tool', fname] + args,
445
+ stdout=subprocess.DEVNULL,
446
+ stderr=subprocess.DEVNULL)
447
+ except Exception as err:
448
+ raise SystemExit(err)
449
+
450
+ def fix_jar(fname: str) -> None:
451
+ subprocess.check_call(['jar', 'xf', fname, 'META-INF/MANIFEST.MF'])
452
+ with open('META-INF/MANIFEST.MF', 'r+', encoding='utf-8') as f:
453
+ lines = f.readlines()
454
+ f.seek(0)
455
+ for line in lines:
456
+ if not line.startswith('Class-Path:'):
457
+ f.write(line)
458
+ f.truncate()
459
+ # jar -um doesn't allow removing existing attributes. Use -uM instead,
460
+ # which a) removes the existing manifest from the jar and b) disables
461
+ # special-casing for the manifest file, so we can re-add it as a normal
462
+ # archive member. This puts the manifest at the end of the jar rather
463
+ # than the beginning, but the spec doesn't forbid that.
464
+ subprocess.check_call(['jar', 'ufM', fname, 'META-INF/MANIFEST.MF'])
465
+
466
+ def fix_rpath(fname: str, rpath_dirs_to_remove: T.Set[bytes], new_rpath: T.Union[str, bytes], final_path: str, install_name_mappings: T.Dict[str, str], verbose: bool = True) -> None:
467
+ global INSTALL_NAME_TOOL # pylint: disable=global-statement
468
+ # Static libraries, import libraries, debug information, headers, etc
469
+ # never have rpaths
470
+ # DLLs and EXE currently do not need runtime path fixing
471
+ if fname.endswith(('.a', '.lib', '.pdb', '.h', '.hpp', '.dll', '.exe')):
472
+ return
473
+ try:
474
+ if fname.endswith('.jar'):
475
+ fix_jar(fname)
476
+ return
477
+ if isinstance(new_rpath, str):
478
+ new_rpath = new_rpath.encode('utf8')
479
+ fix_elf(fname, rpath_dirs_to_remove, new_rpath, verbose)
480
+ return
481
+ except SystemExit as e:
482
+ if isinstance(e.code, int) and e.code == 0:
483
+ pass
484
+ else:
485
+ raise
486
+ # We don't look for this on import because it will do a useless PATH lookup
487
+ # on non-mac platforms. That can be expensive on some Windows machines
488
+ # (up to 30ms), which is significant with --only-changed. For details, see:
489
+ # https://github.com/mesonbuild/meson/pull/6612#discussion_r378581401
490
+ if INSTALL_NAME_TOOL is False:
491
+ INSTALL_NAME_TOOL = bool(shutil.which('install_name_tool'))
492
+ if INSTALL_NAME_TOOL:
493
+ if isinstance(new_rpath, bytes):
494
+ new_rpath = new_rpath.decode('utf8')
495
+ fix_darwin(fname, new_rpath, final_path, install_name_mappings)
@@ -0,0 +1,198 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Copyright 2020 The Meson development team
3
+
4
+ from __future__ import annotations
5
+
6
+ import json
7
+ import os
8
+ import pathlib
9
+ import pickle
10
+ import re
11
+ import sys
12
+ import typing as T
13
+
14
+ from ..backend.ninjabackend import ninja_quote
15
+ from ..compilers.compilers import lang_suffixes
16
+
17
+ if T.TYPE_CHECKING:
18
+ from ..backend.ninjabackend import TargetDependencyScannerInfo
19
+
20
+ CPP_IMPORT_RE = re.compile(r'\w*import ([a-zA-Z0-9]+);')
21
+ CPP_EXPORT_RE = re.compile(r'\w*export module ([a-zA-Z0-9]+);')
22
+
23
+ FORTRAN_INCLUDE_PAT = r"^\s*include\s*['\"](\w+\.\w+)['\"]"
24
+ FORTRAN_MODULE_PAT = r"^\s*\bmodule\b\s+(\w+)\s*(?:!+.*)*$"
25
+ FORTRAN_SUBMOD_PAT = r"^\s*\bsubmodule\b\s*\((\w+:?\w+)\)\s*(\w+)"
26
+ FORTRAN_USE_PAT = r"^\s*use,?\s*(?:non_intrinsic)?\s*(?:::)?\s*(\w+)"
27
+
28
+ FORTRAN_MODULE_RE = re.compile(FORTRAN_MODULE_PAT, re.IGNORECASE)
29
+ FORTRAN_SUBMOD_RE = re.compile(FORTRAN_SUBMOD_PAT, re.IGNORECASE)
30
+ FORTRAN_USE_RE = re.compile(FORTRAN_USE_PAT, re.IGNORECASE)
31
+
32
+ class DependencyScanner:
33
+ def __init__(self, pickle_file: str, outfile: str, sources: T.List[str]):
34
+ with open(pickle_file, 'rb') as pf:
35
+ self.target_data: TargetDependencyScannerInfo = pickle.load(pf)
36
+ self.outfile = outfile
37
+ self.sources = sources
38
+ self.provided_by: T.Dict[str, str] = {}
39
+ self.exports: T.Dict[str, str] = {}
40
+ self.needs: T.Dict[str, T.List[str]] = {}
41
+ self.sources_with_exports: T.List[str] = []
42
+
43
+ def scan_file(self, fname: str) -> None:
44
+ suffix = os.path.splitext(fname)[1][1:]
45
+ if suffix != 'C':
46
+ suffix = suffix.lower()
47
+ if suffix in lang_suffixes['fortran']:
48
+ self.scan_fortran_file(fname)
49
+ elif suffix in lang_suffixes['cpp']:
50
+ self.scan_cpp_file(fname)
51
+ else:
52
+ sys.exit(f'Can not scan files with suffix .{suffix}.')
53
+
54
+ def scan_fortran_file(self, fname: str) -> None:
55
+ fpath = pathlib.Path(fname)
56
+ modules_in_this_file = set()
57
+ for line in fpath.read_text(encoding='utf-8', errors='ignore').split('\n'):
58
+ import_match = FORTRAN_USE_RE.match(line)
59
+ export_match = FORTRAN_MODULE_RE.match(line)
60
+ submodule_export_match = FORTRAN_SUBMOD_RE.match(line)
61
+ if import_match:
62
+ needed = import_match.group(1).lower()
63
+ # In Fortran you have an using declaration also for the module
64
+ # you define in the same file. Prevent circular dependencies.
65
+ if needed not in modules_in_this_file:
66
+ if fname in self.needs:
67
+ self.needs[fname].append(needed)
68
+ else:
69
+ self.needs[fname] = [needed]
70
+ if export_match:
71
+ exported_module = export_match.group(1).lower()
72
+ assert exported_module not in modules_in_this_file
73
+ modules_in_this_file.add(exported_module)
74
+ if exported_module in self.provided_by:
75
+ raise RuntimeError(f'Multiple files provide module {exported_module}.')
76
+ self.sources_with_exports.append(fname)
77
+ self.provided_by[exported_module] = fname
78
+ self.exports[fname] = exported_module
79
+ if submodule_export_match:
80
+ # Store submodule "Foo" "Bar" as "foo:bar".
81
+ # A submodule declaration can be both an import and an export declaration:
82
+ #
83
+ # submodule (a1:a2) a3
84
+ # - requires a1@a2.smod
85
+ # - produces a1@a3.smod
86
+ parent_module_name_full = submodule_export_match.group(1).lower()
87
+ parent_module_name = parent_module_name_full.split(':')[0]
88
+ submodule_name = submodule_export_match.group(2).lower()
89
+ concat_name = f'{parent_module_name}:{submodule_name}'
90
+ self.sources_with_exports.append(fname)
91
+ self.provided_by[concat_name] = fname
92
+ self.exports[fname] = concat_name
93
+ # Fortran requires that the immediate parent module must be built
94
+ # before the current one. Thus:
95
+ #
96
+ # submodule (parent) parent <- requires parent.mod (really parent.smod, but they are created at the same time)
97
+ # submodule (a1:a2) a3 <- requires a1@a2.smod
98
+ #
99
+ # a3 does not depend on the a1 parent module directly, only transitively.
100
+ if fname in self.needs:
101
+ self.needs[fname].append(parent_module_name_full)
102
+ else:
103
+ self.needs[fname] = [parent_module_name_full]
104
+
105
+ def scan_cpp_file(self, fname: str) -> None:
106
+ fpath = pathlib.Path(fname)
107
+ for line in fpath.read_text(encoding='utf-8', errors='ignore').split('\n'):
108
+ import_match = CPP_IMPORT_RE.match(line)
109
+ export_match = CPP_EXPORT_RE.match(line)
110
+ if import_match:
111
+ needed = import_match.group(1)
112
+ if fname in self.needs:
113
+ self.needs[fname].append(needed)
114
+ else:
115
+ self.needs[fname] = [needed]
116
+ if export_match:
117
+ exported_module = export_match.group(1)
118
+ if exported_module in self.provided_by:
119
+ raise RuntimeError(f'Multiple files provide module {exported_module}.')
120
+ self.sources_with_exports.append(fname)
121
+ self.provided_by[exported_module] = fname
122
+ self.exports[fname] = exported_module
123
+
124
+ def objname_for(self, src: str) -> str:
125
+ objname = self.target_data.source2object[src]
126
+ assert isinstance(objname, str)
127
+ return objname
128
+
129
+ def module_name_for(self, src: str) -> str:
130
+ suffix = os.path.splitext(src)[1][1:].lower()
131
+ if suffix in lang_suffixes['fortran']:
132
+ exported = self.exports[src]
133
+ # Module foo:bar goes to a file name foo@bar.smod
134
+ # Module Foo goes to a file name foo.mod
135
+ namebase = exported.replace(':', '@')
136
+ if ':' in exported:
137
+ extension = 'smod'
138
+ else:
139
+ extension = 'mod'
140
+ return os.path.join(self.target_data.private_dir, f'{namebase}.{extension}')
141
+ elif suffix in lang_suffixes['cpp']:
142
+ return '{}.ifc'.format(self.exports[src])
143
+ else:
144
+ raise RuntimeError('Unreachable code.')
145
+
146
+ def scan(self) -> int:
147
+ for s in self.sources:
148
+ self.scan_file(s)
149
+ with open(self.outfile, 'w', encoding='utf-8') as ofile:
150
+ ofile.write('ninja_dyndep_version = 1\n')
151
+ for src in self.sources:
152
+ objfilename = self.objname_for(src)
153
+ mods_and_submods_needed = []
154
+ module_files_generated = []
155
+ module_files_needed = []
156
+ if src in self.sources_with_exports:
157
+ module_files_generated.append(self.module_name_for(src))
158
+ if src in self.needs:
159
+ for modname in self.needs[src]:
160
+ if modname not in self.provided_by:
161
+ # Nothing provides this module, we assume that it
162
+ # comes from a dependency library somewhere and is
163
+ # already built by the time this compilation starts.
164
+ pass
165
+ else:
166
+ mods_and_submods_needed.append(modname)
167
+
168
+ for modname in mods_and_submods_needed:
169
+ provider_src = self.provided_by[modname]
170
+ provider_modfile = self.module_name_for(provider_src)
171
+ # Prune self-dependencies
172
+ if provider_src != src:
173
+ module_files_needed.append(provider_modfile)
174
+
175
+ quoted_objfilename = ninja_quote(objfilename, True)
176
+ quoted_module_files_generated = [ninja_quote(x, True) for x in module_files_generated]
177
+ quoted_module_files_needed = [ninja_quote(x, True) for x in module_files_needed]
178
+ if quoted_module_files_generated:
179
+ mod_gen = '| ' + ' '.join(quoted_module_files_generated)
180
+ else:
181
+ mod_gen = ''
182
+ if quoted_module_files_needed:
183
+ mod_dep = '| ' + ' '.join(quoted_module_files_needed)
184
+ else:
185
+ mod_dep = ''
186
+ build_line = 'build {} {}: dyndep {}'.format(quoted_objfilename,
187
+ mod_gen,
188
+ mod_dep)
189
+ ofile.write(build_line + '\n')
190
+ return 0
191
+
192
+ def run(args: T.List[str]) -> int:
193
+ assert len(args) == 3, 'got wrong number of arguments!'
194
+ pickle_file, outfile, jsonfile = args
195
+ with open(jsonfile, encoding='utf-8') as f:
196
+ sources = json.load(f)
197
+ scanner = DependencyScanner(pickle_file, outfile, sources)
198
+ return scanner.scan()