Introduction

Qiling Framework is always a fast-evolving project thanks to the efforts of the whole community. Since more and more developers join us, it's also a big challenge to maintain the whole project clean and thus here comes the contribution guide.

Before creating your first pull request, please read this page carefully.

Join us

  • Join our telegram group, most of our developers are active in this group.
  • Follow our twitter @qiling_io to get latest news.
  • Don't forget to give us a star on Github!

Check existing issue/PR

Before submitting your pull request, please search in issues and PRs firstly. Also remember to check our TODO and FAQ.

Reading materials

Before starting your first line, there are a bunch of reading materials for you to get start.

See here for a full list.

Based on dev and merge to dev

Once you fork our project and decide to write your awesome PR, one thing you should keep in mind is that: Always work on dev branch.

In Qiling Framework, dev branch means new features, new fixes and testing functions where new pull requests should be based on.

Coding Convention

Note

Since the refactor is going on, you may find some parts of current codebase are opposite to these conventions.

Logging

Please use ql.log, which is a logging.Logger object.

When catching an exception, besides simply raising it, ql.log.exception can be of great help.

try:
    1/0
except ZeroDivisionError as e:
    #print(e)
    ql.log.exception("Divide by zero!")

Property

Whenever you would like to add a class member, consider property instead.

class QlOsDumb:
    def __init__(self):
        #self.dumb = 1
        self._dumb = 1

    @property
    def dumb(self):
        return self._dumb

    def do_something(self):
        print(self.dumb)

Python property is more readable and helpful for code autocompletion.

Type hinting

Python type hinting is a kind of edit-time annotation which provides extra information for autocompletion.

def ql_is_multithread(ql: Qiling) -> bool:
    return ql.multithread

Note

Due to the historical design problem, you may encounter cyclic import when adding type hints. See this link for a clean solution.

Docstring

Whenever possible, add docstring for your method or property.

def ql_dumb_function():
    """
    This is a docstring
    """
    pass

Naming

See codes below for naming convention.

# Class: PascalCase
class QlOsDumb:
    pass

# Function: snake_case
def ql_dumb_function():
    pass

# Variable: snake_case
mem_ptr = 0

# Constants: UPPERCASE
# If the constant is from other place, e.g. Linux Kernel, follow their naming convention.
ERROR = 0

Tests

If your PR consists of some new features, remember to add a new test.

See test_pathutils.py for an example.

Imports

Always prefer relative imports for qiling modules.

from .mapper import QlFsMapper

Built in modules should be imported either in one line or fully seperately.

# ok
import logging, os, re
# ok
import logging
import re
import os
# no
import logging, re
import os

Note

Due to the historical design problem on project structure, you may have to use full import like from qiling.os.utils import * sometimes.

Comments

You should leave comments for your code if it matches the following cases:

  • This part of code is copied/rewritten/extracted from other location, e.g. Linux kernel, etc.
  • This implementation follows some external documents, e.g. Linux manual.
  • This code has some unexpected side effects.

Of course, the more, the better.

Changelog

Finally, before merging your PR into dev branch, one last thing you have to do is to update Changelog.