Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for multiple input lines #118

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions .github/workflows/package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
name: package
on: [push, pull_request]

jobs:
yotamN marked this conversation as resolved.
Show resolved Hide resolved
windows-wheels:
strategy:
matrix:
arch: [x86, x64]
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- uses: actions/setup-python@v4
with:
python-version: '3.10'
architecture: ${{ matrix.arch }}
- run: make
- run: python3 -m pip install wheel
- run: python3 -m pip install tree_sitter
- run: python3 setup.py bdist_wheel
- uses: actions/upload-artifact@v3
with:
name: frida-tools-windows
path: dist/frida_tools-*.whl
- name: Publish package
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_API_TOKEN }}

macos-wheels:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- uses: actions/setup-python@v4
with:
python-version: '3.10'
- run: make
- run: python3 -m pip install wheel
- run: python3 -m pip install tree_sitter
- run: python3 setup.py bdist_wheel
- uses: actions/upload-artifact@v3
with:
name: frida-tools-macos
path: dist/frida_tools-*.whl
- name: Publish package
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_API_TOKEN }}

linux-wheels:
yotamN marked this conversation as resolved.
Show resolved Hide resolved
strategy:
matrix:
arch: [x86, x86_64, armhf, arm64, mips]
runs-on: ubuntu-latest
container: ghcr.io/frida/x-tools-linux-${{ matrix.arch }}:latest
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- run: make
- run: |
case ${{ matrix.arch }} in
x86)
py_arch=i686
;;
armhf)
py_arch=armv7l
;;
arm64)
py_arch=aarch64
;;
*)
py_arch=${{ matrix.arch }}
;;
esac
export _PYTHON_HOST_PLATFORM=linux-$py_arch
export CPPFLAGS="-I/opt/x-tools/$XTOOLS_HOST/$XTOOLS_HOST/sysroot/usr/include/python3.10"
# TODO: set LIBDIR properly
sed -i "s/\/usr\/lib\/x86_64-linux-gnu/\/opt\/x-tools\/$XTOOLS_HOST\/$XTOOLS_HOST\/sysroot\/usr\/lib/" /usr/lib/python3.10/_sysconfigdata__x86_64-linux-gnu.py
sed -i "s/\/usr\/lib\/x86_64-linux-gnu/\/opt\/x-tools\/$XTOOLS_HOST\/$XTOOLS_HOST\/sysroot\/usr\/lib/" /usr/lib/python3.10/_sysconfigdata__linux_x86_64-linux-gnu.py
python3 -m pip install --verbose tree_sitter
case ${{ matrix.arch }} in
x86*)
py_platform=manylinux_2_5_${py_arch}.manylinux1_${py_arch}
;;
arm*|ppc*|s390x)
py_platform=manylinux_2_17_${py_arch}.manylinux2014_${py_arch}
;;
*)
py_platform=manylinux_2_5_${py_arch}
;;
esac
bdist_wheel_py=/usr/lib/python3/dist-packages/wheel/bdist_wheel.py
sed "s/plat_name = plat_name\\.lower()\\.replace('-', '_')\\.replace('.', '_')/plat_name = plat_name.lower().replace('-', '_')/" \
$bdist_wheel_py > $bdist_wheel_py.patched
if cmp -s $bdist_wheel_py $bdist_wheel_py.patched; then
rm -f $bdist_wheel_py.patched
echo 'Unable to patch bdist_wheel.py' > /dev/stderr
exit 1
else
mv $bdist_wheel_py.patched $bdist_wheel_py
fi
echo "plat_name = $py_platform" >> setup.cfg
pip wheel --verbose -w ./dist --no-deps .
- uses: actions/upload-artifact@v3
with:
name: frida-tools-linux-${{ matrix.arch }}
path: dist/frida_tools-*.whl
- name: Publish package
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_API_TOKEN }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
/build/
/dist/
/frida_tools/*_agent.js
/frida_tools/treesitter.so
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "vendor/tree-sitter-javascript"]
path = vendor/tree-sitter-javascript
url = https://github.com/tree-sitter/tree-sitter-javascript
18 changes: 18 additions & 0 deletions build_aux/build_treesitter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env python3

import os

from tree_sitter import Language


def build() -> None:
Language.build_library(
os.path.join("frida_tools", "treesitter.so"),
[
os.path.join("vendor", "tree-sitter-javascript"),
],
)


if __name__ == "__main__":
build()
2 changes: 2 additions & 0 deletions build_aux/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
python = find_program('python3', 'python')
run_command(python, 'build_treesitter.py')
38 changes: 38 additions & 0 deletions frida_tools/repl.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import hashlib
import json
import os
import pathlib
import platform
import re
import shlex
Expand All @@ -20,12 +21,14 @@
from prompt_toolkit import PromptSession
from prompt_toolkit.completion import CompleteEvent, Completer, Completion
from prompt_toolkit.document import Document
from prompt_toolkit.filters import Condition, Filter
from prompt_toolkit.history import FileHistory
from prompt_toolkit.lexers import PygmentsLexer
from prompt_toolkit.shortcuts import prompt
from prompt_toolkit.styles import Style as PromptToolkitStyle
from pygments.lexers.javascript import JavascriptLexer
from pygments.token import Token
from tree_sitter import Language, Parser

from frida_tools import _repl_magic
from frida_tools.application import ConsoleApplication
Expand All @@ -34,6 +37,13 @@

T = TypeVar("T")

try:
JS_LANGUAGE = Language(str(pathlib.Path(__file__).parent / "treesitter.so"), "javascript")
ERROR_QUERY = JS_LANGUAGE.query("(_ (ERROR) @error)")
except Exception:
JS_LANGUAGE = None
ERROR_QUERY = None


class REPLApplication(ConsoleApplication):
def __init__(self) -> None:
Expand All @@ -53,6 +63,12 @@ def __init__(self) -> None:

super().__init__(self._process_input, self._on_stop)

try:
self._parser = Parser()
self._parser.set_language(JS_LANGUAGE)
except Exception:
self._parser = None

if self._have_terminal and not self._plain_terminal:
style = PromptToolkitStyle(
[
Expand All @@ -69,6 +85,7 @@ def __init__(self) -> None:
complete_in_thread=True,
enable_open_in_editor=True,
tempfile_suffix=".js",
multiline=self._input_complete(),
)
self._dumb_stdin_reader = None
else:
Expand Down Expand Up @@ -339,6 +356,27 @@ def _monitor(self, path: AnyStr) -> None:
monitor.enable()
self._monitored_files[path] = monitor

def _input_complete(self) -> Filter:
"""
check if the current input is a valid javascript code
"""

@Condition
def inner() -> bool:
assert self._cli is not None
if self._parser is None or ERROR_QUERY is None:
return False

tree = self._parser.parse(self._cli.default_buffer.document.text.encode())
query_results = ERROR_QUERY.captures(tree.root_node)
# It would have been nice to be able to query a MISSING node properly but as of when this code was written
# it was just not possible. There is an open issue for it in tree-sitter/tree-sitter#606 so maybe one day we
# could fix it. I hope it doesn't break some code that contain the work MISSING or something but I checked it
# a bit and it seems to be fine.
return len(query_results) or "MISSING" in tree.root_node.sexp()

return inner

def _process_input(self, reactor: Reactor) -> None:
if not self._quiet:
self._print_startup_message()
Expand Down
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ subdir('agents')
subdir('frida_tools')
subdir('scripts')
subdir('completions')
subdir('build_aux')
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[bdist_wheel]
py_limited_api = cp37
5 changes: 4 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

agents = glob.glob(os.path.join(pkg_dir, "*_agent.*"))
assert len(agents) > 0, "Agents not compiled; run “npm install && npm run build” in agents/*/"
os.system("python ./build_aux/build_treesitter.py")
package_data = agents + ["treesitter.so"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should tie into the build system so we don't do this when just running setup.py to query for something.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is the only way that a source distribution would build correctly?


setup(
name="frida-tools",
Expand All @@ -24,6 +26,7 @@
"frida >= 16.0.0, < 17.0.0",
"prompt-toolkit >= 2.0.0, < 4.0.0",
"pygments >= 2.0.2, < 3.0.0",
"tree_sitter==0.20.1",
],
license="wxWindows Library Licence, Version 3.1",
zip_safe=True,
Expand Down Expand Up @@ -51,7 +54,7 @@
],
packages=["frida_tools"],
package_data={
"frida_tools": agents,
"frida_tools": package_data,
},
entry_points={
"console_scripts": [
Expand Down
1 change: 1 addition & 0 deletions vendor/tree-sitter-javascript
Submodule tree-sitter-javascript added at 936d97