Instruction:
Can you create a Python 3 function that
gets a DateTime object for the current century.

Response:
def date_time_this_century(
            self,
            before_now=True,
            after_now=False,
            tzinfo=None):
        """
        Gets a DateTime object for the current century.

        :param before_now: include days in current century before today
        :param after_now: include days in current century after today
        :param tzinfo: timezone, instance of datetime.tzinfo subclass
        :example DateTime('2012-04-04 11:02:02')
        :return DateTime
        """
        now = datetime.now(tzinfo)
        this_century_start = datetime(
            now.year - (now.year % 100), 1, 1, tzinfo=tzinfo)
        next_century_start = datetime(
            min(this_century_start.year + 100, MAXYEAR), 1, 1, tzinfo=tzinfo)

        if before_now and after_now:
            return self.date_time_between_dates(
                this_century_start, next_century_start, tzinfo)
        elif not before_now and after_now:
            return self.date_time_between_dates(now, next_century_start, tzinfo)
        elif not after_now and before_now:
            return self.date_time_between_dates(this_century_start, now, tzinfo)
        else:
            return now


Instruction:
Create a Python 3 function for
getting a DateTime object for the current decade year.

Response:
def date_time_this_decade(
            self,
            before_now=True,
            after_now=False,
            tzinfo=None):
        """
        Gets a DateTime object for the decade year.

        :param before_now: include days in current decade before today
        :param after_now: include days in current decade after today
        :param tzinfo: timezone, instance of datetime.tzinfo subclass
        :example DateTime('2012-04-04 11:02:02')
        :return DateTime
        """
        now = datetime.now(tzinfo)
        this_decade_start = datetime(
            now.year - (now.year % 10), 1, 1, tzinfo=tzinfo)
        next_decade_start = datetime(
            min(this_decade_start.year + 10, MAXYEAR), 1, 1, tzinfo=tzinfo)

        if before_now and after_now:
            return self.date_time_between_dates(
                this_decade_start, next_decade_start, tzinfo)
        elif not before_now and after_now:
            return self.date_time_between_dates(now, next_decade_start, tzinfo)
        elif not after_now and before_now:
            return self.date_time_between_dates(this_decade_start, now, tzinfo)
        else:
            return now


Instruction:
Write a Python 3 function that can
get a DateTime object for the current year.

Response:
def date_time_this_year(
            self,
            before_now=True,
            after_now=False,
            tzinfo=None):
        """
        Gets a DateTime object for the current year.

        :param before_now: include days in current year before today
        :param after_now: include days in current year after today
        :param tzinfo: timezone, instance of datetime.tzinfo subclass
        :example DateTime('2012-04-04 11:02:02')
        :return DateTime
        """
        now = datetime.now(tzinfo)
        this_year_start = now.replace(
            month=1, day=1, hour=0, minute=0, second=0, microsecond=0)
        next_year_start = datetime(now.year + 1, 1, 1, tzinfo=tzinfo)

        if before_now and after_now:
            return self.date_time_between_dates(
                this_year_start, next_year_start, tzinfo)
        elif not before_now and after_now:
            return self.date_time_between_dates(now, next_year_start, tzinfo)
        elif not after_now and before_now:
            return self.date_time_between_dates(this_year_start, now, tzinfo)
        else:
            return now


Instruction:
Can you generate the documentation for the following Python 3 function
def date_time_this_month(
            self,
            before_now=True,
            after_now=False,
            tzinfo=None):
        """
        Gets a DateTime object for the current month.

        :param before_now: include days in current month before today
        :param after_now: include days in current month after today
        :param tzinfo: timezone, instance of datetime.tzinfo subclass
        :example DateTime('2012-04-04 11:02:02')
        :return DateTime
        """
        now = datetime.now(tzinfo)
        this_month_start = now.replace(
            day=1, hour=0, minute=0, second=0, microsecond=0)

        next_month_start = this_month_start + \
            relativedelta.relativedelta(months=1)
        if before_now and after_now:
            return self.date_time_between_dates(
                this_month_start, next_month_start, tzinfo)
        elif not before_now and after_now:
            return self.date_time_between_dates(now, next_month_start, tzinfo)
        elif not after_now and before_now:
            return self.date_time_between_dates(this_month_start, now, tzinfo)
        else:
            return now

Response: Gets a DateTime object for the current month.


Instruction:
Can you write a function in Python 3 where it
gets a Date object for the current century.

Response:
def date_this_century(self, before_today=True, after_today=False):
        """
        Gets a Date object for the current century.

        :param before_today: include days in current century before today
        :param after_today: include days in current century after today
        :example Date('2012-04-04')
        :return Date
        """
        today = date.today()
        this_century_start = date(today.year - (today.year % 100), 1, 1)
        next_century_start = date(this_century_start.year + 100, 1, 1)

        if before_today and after_today:
            return self.date_between_dates(
                this_century_start, next_century_start)
        elif not before_today and after_today:
            return self.date_between_dates(today, next_century_start)
        elif not after_today and before_today:
            return self.date_between_dates(this_century_start, today)
        else:
            return today


Instruction:
Given the following Python 3 function, write the documentation
def date_this_decade(self, before_today=True, after_today=False):
        today = date.today()
        this_decade_start = date(today.year - (today.year % 10), 1, 1)
        next_decade_start = date(this_decade_start.year + 10, 1, 1)

        if before_today and after_today:
            return self.date_between_dates(this_decade_start, next_decade_start)
        elif not before_today and after_today:
            return self.date_between_dates(today, next_decade_start)
        elif not after_today and before_today:
            return self.date_between_dates(this_decade_start, today)
        else:
            return today

Response: Gets a Date object for the decade year.


Instruction:
Create a Python 3 function for
getting a Date object for the current year.

Response:
def date_this_year(self, before_today=True, after_today=False):
        """
        Gets a Date object for the current year.

        :param before_today: include days in current year before today
        :param after_today: include days in current year after today
        :example Date('2012-04-04')
        :return Date
        """
        today = date.today()
        this_year_start = today.replace(month=1, day=1)
        next_year_start = date(today.year + 1, 1, 1)

        if before_today and after_today:
            return self.date_between_dates(this_year_start, next_year_start)
        elif not before_today and after_today:
            return self.date_between_dates(today, next_year_start)
        elif not after_today and before_today:
            return self.date_between_dates(this_year_start, today)
        else:
            return today


Instruction:
Here you have a function in Python 3, explain what it does
def date_this_month(self, before_today=True, after_today=False):
        today = date.today()
        this_month_start = today.replace(day=1)

        next_month_start = this_month_start + \
            relativedelta.relativedelta(months=1)
        if before_today and after_today:
            return self.date_between_dates(this_month_start, next_month_start)
        elif not before_today and after_today:
            return self.date_between_dates(today, next_month_start)
        elif not after_today and before_today:
            return self.date_between_dates(this_month_start, today)
        else:
            return today

Response: Gets a Date object for the current month.


Instruction:
Create a Python 3 function to
return a generator yielding tuples of datetime and value.

Response:
def time_series(
            self,
            start_date='-30d',
            end_date='now',
            precision=None,
            distrib=None,
            tzinfo=None):
        """
        Returns a generator yielding tuples of ``(<datetime>, <value>)``.

        The data points will start at ``start_date``, and be at every time interval specified by
        ``precision``.
        ``distrib`` is a callable that accepts ``<datetime>`` and returns ``<value>``

        """
        start_date = self._parse_date_time(start_date, tzinfo=tzinfo)
        end_date = self._parse_date_time(end_date, tzinfo=tzinfo)

        if end_date < start_date:
            raise ValueError("`end_date` must be greater than `start_date`.")

        if precision is None:
            precision = (end_date - start_date) / 30

        precision = self._parse_timedelta(precision)
        if distrib is None:
            def distrib(dt): return self.generator.random.uniform(0, precision)  # noqa

        if not callable(distrib):
            raise ValueError(
                "`distrib` must be a callable. Got {} instead.".format(distrib))

        datapoint = start_date
        while datapoint < end_date:
            dt = timestamp_to_datetime(datapoint, tzinfo)
            datapoint += precision
            yield (dt, distrib(dt))


Instruction:
Here you have a function in Python 3, explain what it does
def date_of_birth(self, tzinfo=None, minimum_age=0, maximum_age=115):

        if not isinstance(minimum_age, int):
            raise TypeError("minimum_age must be an integer.")

        if not isinstance(maximum_age, int):
            raise TypeError("maximum_age must be an integer.")

        if (maximum_age < 0):
            raise ValueError("maximum_age must be greater than or equal to zero.")

        if (minimum_age < 0):
            raise ValueError("minimum_age must be greater than or equal to zero.")

        if (minimum_age > maximum_age):
            raise ValueError("minimum_age must be less than or equal to maximum_age.")

        # In order to return the full range of possible dates of birth, add one
        # year to the potential age cap and subtract one day if we land on the
        # boundary.

        now = datetime.now(tzinfo).date()
        start_date = now.replace(year=now.year - (maximum_age+1))
        end_date = now.replace(year=now.year - minimum_age)

        dob = self.date_time_ad(tzinfo=tzinfo, start_datetime=start_date, end_datetime=end_date).date()

        return dob if dob != start_date else dob + timedelta(days=1)

Response: Generate a random date of birth.


Instruction:
Given the following Python 3 function, write the documentation
def add_dicts(*args):

    counters = [Counter(arg) for arg in args]
    return dict(reduce(operator.add, counters))

Response: Adds two or more dicts together.


Instruction:
Can you write a function in Python 3 where it
returns the provider s name of the credit card.

Response:
def credit_card_provider(self, card_type=None):
        """ Returns the provider's name of the credit card. """
        if card_type is None:
            card_type = self.random_element(self.credit_card_types.keys())
        return self._credit_card_type(card_type).name


Instruction:
Can you generate a brief explanation for the following Python 3 code
def credit_card_number(self, card_type=None):
        card = self._credit_card_type(card_type)
        prefix = self.random_element(card.prefixes)
        number = self._generate_number(self.numerify(prefix), card.length)
        return number

Response: Returns a valid credit card number.


Instruction:
Explain what the following Python 3 code does
def credit_card_security_code(self, card_type=None):
        sec_len = self._credit_card_type(card_type).security_code_length
        return self.numerify('#' * sec_len)

Response: Returns a security code string.


Instruction:
Given the following Python 3 function, write the documentation
def _credit_card_type(self, card_type=None):
        if card_type is None:
            card_type = self.random_element(self.credit_card_types.keys())
        elif isinstance(card_type, CreditCard):
            return card_type
        return self.credit_card_types[card_type]

Response: Returns a random credit card type instance.


Instruction:
Create a Python 3 function to
generate a random CC number.

Response:
def _generate_number(self, prefix, length):
        """
        'prefix' is the start of the CC number as a string, any number of digits.
        'length' is the length of the CC number to generate. Typically 13 or 16
        """
        number = prefix
        # Generate random char digits
        number += '#' * (length - len(prefix) - 1)
        number = self.numerify(number)
        reverse = number[::-1]
        # Calculate sum
        tot = 0
        pos = 0
        while pos < length - 1:
            tot += Provider.luhn_lookup[reverse[pos]]
            if pos != (length - 2):
                tot += int(reverse[pos + 1])
            pos += 2
        # Calculate check digit
        check_digit = (10 - (tot % 10)) % 10
        number += str(check_digit)
        return number


Instruction:
Can you generate the documentation for the following Python 3 function
def company_business_id(self):
        def calculate_checksum(number):
            """Calculate the checksum using mod 11,2 method"""
            factors = [7, 9, 10, 5, 8, 4, 2]
            sum_ = 0
            for x, y in zip(number, factors):
                sum_ = sum_ + int(x) * y
            if sum_ % 11 == 0:
                return '0'
            else:
                return str(11 - sum_ % 11)

        first_digit = str(self.random_digit_not_null())
        body = first_digit + self.bothify('######')
        cs = calculate_checksum(body)
        return body + '-' + str(cs)

Response: Returns a string that is used to identify the company business identity code for the current company.


Instruction:
Implement a function in Python 3 to
generate a 11 digits Belgian SSN called rjksregisternummer

Response:
def ssn(self):
        """
        Returns a 11 digits Belgian SSN called "rijksregisternummer" as a string

        The first 6 digits represent the birthdate with (in order) year, month and day.
        The second group of 3 digits is represents a sequence number (order of birth).
        It is even for women and odd for men.
        For men the range starts at 1 and ends 997, for women 2 until 998.
        The third group of 2 digits is a checksum based on the previous 9 digits (modulo 97).
        Divide those 9 digits by 97, subtract the remainder from 97 and that's the result.
        For persons born in or after 2000, the 9 digit number needs to be proceeded by a 2
        (add 2000000000) before the division by 97.

        """
        # see http://nl.wikipedia.org/wiki/Burgerservicenummer (in Dutch)
        def _checksum(digits):
            res = 97 - (digits % 97)
            return res

        # Generate a date (random)
        mydate = self.generator.date()
        # Convert it to an int
        elms = mydate.split("-")
        # Adjust for year 2000 if necessary
        if elms[0][0] == '2':
            above = True
        else:
            above = False
        # Only keep the last 2 digits of the year
        elms[0] = elms[0][2:4]
        # Simulate the gender/sequence - should be 3 digits
        seq = self.generator.random_int(1, 998)
        # Right justify sequence and append to list
        seq_str = "{:0>3}".format(seq)
        elms.append(seq_str)
        # Now convert list to an integer so the checksum can be calculated
        date_as_int = int("".join(elms))
        if above:
            date_as_int += 2000000000
        # Generate checksum
        s = _checksum(date_as_int)
        s_rjust = "{:0>2}".format(s)
        # return result as a string
        elms.append(s_rjust)
        return "".join(elms)


Instruction:
Can you tell what is the following Python 3 function doing
def road_address(self):
        pattern = self.random_element(self.road_address_formats)
        return self.generator.parse(pattern)

Response: :example 세종특별자치시 도움5로 19 (어진동)


Instruction:
Here you have a function in Python 3, explain what it does
def address_detail(self):
        pattern = self.bothify(self.random_element(
            self.address_detail_formats))
        return self.generator.parse(pattern)

Response: :example 가나아파트 가동 102호


Instruction:
Write a Python 3 function that can
calculate the checksum of a Canadian Social Insurance Number.

Response:
def checksum(sin):
    """
    Determine validity of a Canadian Social Insurance Number.
    Validation is performed using a modified Luhn Algorithm.  To check
    the Every second digit of the SIN is doubled and the result is
    summed.  If the result is a multiple of ten, the Social Insurance
    Number is considered valid.

    https://en.wikipedia.org/wiki/Social_Insurance_Number
    """

    # Remove spaces and create a list of digits.
    checksumCollection = list(sin.replace(' ', ''))
    checksumCollection = [int(i) for i in checksumCollection]

    # Discard the last digit, we will be calculating it later.
    checksumCollection[-1] = 0

    # Iterate over the provided SIN and double every second digit.
    # In the case that doubling that digit results in a two-digit
    # number, then add the two digits together and keep that sum.

    for i in range(1, len(checksumCollection), 2):
        result = checksumCollection[i] * 2
        if result < 10:
            checksumCollection[i] = result
        else:
            checksumCollection[i] = result - 10 + 1

    # The appropriate checksum digit is the value that, when summed
    # with the first eight values, results in a value divisible by 10

    check_digit = 10 - (sum(checksumCollection) % 10)
    check_digit = (0 if check_digit == 10 else check_digit)

    return check_digit


Instruction:
Can you create a Python 3 function that
produces a hostname with specified number of subdomain levels.

Response:
def hostname(self, levels=1):
        """
        Produce a hostname with specified number of subdomain levels.

        >>> hostname()
        db-01.nichols-phillips.com
        >>> hostname(0)
        laptop-56
        >>> hostname(2)
        web-12.williamson-hopkins.jackson.com
        """
        if levels < 1:
            return self.random_element(self.hostname_prefixes) + '-' + self.numerify('##')
        return self.random_element(self.hostname_prefixes) + '-' + self.numerify('##') + '.' + self.domain_name(levels)


Instruction:
Make a summary of the following Python 3 code
def domain_name(self, levels=1):
        if levels < 1:
            raise ValueError("levels must be greater than or equal to 1")
        if levels == 1:
            return self.domain_word() + '.' + self.tld()
        else:
            return self.domain_word() + '.' + self.domain_name(levels - 1)

Response: Produce an Internet domain name with the specified number of subdomain levels.


Instruction:
Can you generate the documentation for the following Python 3 function
def url(self, schemes=None):
        if schemes is None:
            schemes = ['http', 'https']

        pattern = '{}://{}'.format(
            self.random_element(schemes) if schemes else "",
            self.random_element(self.url_formats),
        )

        return self.generator.parse(pattern)

Response: Generate a random url string.


Instruction:
Explain what the following Python 3 code does
def _random_ipv4_address_from_subnet(self, subnet, network=False):
        address = str(
            subnet[self.generator.random.randint(
                0, subnet.num_addresses - 1,
            )],
        )

        if network:
            address += '/' + str(self.generator.random.randint(
                subnet.prefixlen,
                subnet.max_prefixlen,
            ))
            address = str(ip_network(address, strict=False))

        return address

Response:
Generates a random IPv4 address or network with a valid CIDR
            from within a given subnet.


Instruction:
Write a Python 3 script to
return a list of IPv4 networks from another list of networks.

Response:
def _exclude_ipv4_networks(self, networks, networks_to_exclude):
        """
        Exclude the list of networks from another list of networks
        and return a flat list of new networks.

        :param networks: List of IPv4 networks to exclude from
        :param networks_to_exclude: List of IPv4 networks to exclude
        :returns: Flat list of IPv4 networks
        """
        for network_to_exclude in networks_to_exclude:
            def _exclude_ipv4_network(network):
                """
                Exclude a single network from another single network
                and return a list of networks. Network to exclude
                comes from the outer scope.

                :param network: Network to exclude from
                :returns: Flat list of IPv4 networks after exclusion.
                          If exclude fails because networks do not
                          overlap, a single element list with the
                          orignal network is returned. If it overlaps,
                          even partially, the network is excluded.
                """
                try:
                    return list(network.address_exclude(network_to_exclude))
                except ValueError:
                    # If networks overlap partially, `address_exclude`
                    # will fail, but the network still must not be used
                    # in generation.
                    if network.overlaps(network_to_exclude):
                        return []
                    else:
                        return [network]

            networks = list(map(_exclude_ipv4_network, networks))

            # flatten list of lists
            networks = [
                item for nested in networks for item in nested
            ]

        return networks


Instruction:
Write a Python 3 script to
produce a random IPv4 address or network with a valid CIDR.

Response:
def ipv4(self, network=False, address_class=None, private=None):
        """
        Produce a random IPv4 address or network with a valid CIDR.

        :param network: Network address
        :param address_class: IPv4 address class (a, b, or c)
        :param private: Public or private
        :returns: IPv4
        """
        if private is True:
            return self.ipv4_private(address_class=address_class,
                                     network=network)
        elif private is False:
            return self.ipv4_public(address_class=address_class,
                                    network=network)

        # if neither private nor public is required explicitly,
        # generate from whole requested address space
        if address_class:
            all_networks = [_IPv4Constants._network_classes[address_class]]
        else:
            # if no address class is choosen, use whole IPv4 pool
            all_networks = [ip_network('0.0.0.0/0')]

        # exclude special networks
        all_networks = self._exclude_ipv4_networks(
            all_networks,
            _IPv4Constants._excluded_networks,
        )

        # choose random network from the list
        random_network = self.generator.random.choice(all_networks)

        return self._random_ipv4_address_from_subnet(random_network, network)


Instruction:
How would you code a function in Python 3 to
return a private IPv4.

Response:
def ipv4_private(self, network=False, address_class=None):
        """
        Returns a private IPv4.

        :param network: Network address
        :param address_class: IPv4 address class (a, b, or c)
        :returns: Private IPv4
        """
        # compute private networks from given class
        supernet = _IPv4Constants._network_classes[
            address_class or self.ipv4_network_class()
        ]

        private_networks = [
            subnet for subnet in _IPv4Constants._private_networks
            if subnet.overlaps(supernet)
        ]

        # exclude special networks
        private_networks = self._exclude_ipv4_networks(
            private_networks,
            _IPv4Constants._excluded_networks,
        )

        # choose random private network from the list
        private_network = self.generator.random.choice(private_networks)

        return self._random_ipv4_address_from_subnet(private_network, network)


Instruction:
Can you generate a brief explanation for the following Python 3 code
def ipv4_public(self, network=False, address_class=None):
        # compute public networks
        public_networks = [_IPv4Constants._network_classes[
            address_class or self.ipv4_network_class()
        ]]

        # exclude private and excluded special networks
        public_networks = self._exclude_ipv4_networks(
            public_networks,
            _IPv4Constants._private_networks +
            _IPv4Constants._excluded_networks,
        )

        # choose random public network from the list
        public_network = self.generator.random.choice(public_networks)

        return self._random_ipv4_address_from_subnet(public_network, network)

Response: Returns a public IPv4 excluding private blocks.


Instruction:
Here you have a function in Python 3, explain what it does
def ipv6(self, network=False):
        address = str(ip_address(self.generator.random.randint(
            2 ** IPV4LENGTH, (2 ** IPV6LENGTH) - 1)))
        if network:
            address += '/' + str(self.generator.random.randint(0, IPV6LENGTH))
            address = str(ip_network(address, strict=False))
        return address

Response: Produce a random IPv6 address or network with a valid CIDR


Instruction:
Can you write a function in Python 3 where it
returns a random URL to the image of the given size.

Response:
def image_url(self, width=None, height=None):
        """
        Returns URL to placeholder image
        Example: http://placehold.it/640x480
        """
        width_ = width or self.random_int(max=1024)
        height_ = height or self.random_int(max=1024)
        placeholder_url = self.random_element(self.image_placeholder_services)
        return placeholder_url.format(width=width_, height=height_)


Instruction:
Here you have a function in Python 3, explain what it does
def format(self, formatter, *args, **kwargs):
        # TODO: data export?
        return self.get_formatter(formatter)(*args, **kwargs)

Response: Format a log entry using the given formatter.


Instruction:
How would you implement a function in Python 3 that
performs a forward execution and perform alias analysis.

Response:
def _alias_analysis(self, mock_sp=True, mock_bp=True):
        """
        Perform a forward execution and perform alias analysis. Note that this analysis is fast, light-weight, and by no
        means complete. For instance, most arithmetic operations are not supported.

        - Depending on user settings, stack pointer and stack base pointer will be mocked and propagated to individual
          tmps.

        :param bool mock_sp: propagate stack pointer or not
        :param bool mock_bp: propagate stack base pointer or not
        :return: None
        """

        state = SimLightState(
            regs={
                self._arch.sp_offset: self._arch.initial_sp,
                self._arch.bp_offset: self._arch.initial_sp + 0x2000, # TODO: take care of the relation between sp and bp
            },
            temps={},
            options={
            'mock_sp': mock_sp,
            'mock_bp': mock_bp,
            }
        )

        for stmt_idx, stmt in list(enumerate(self._statements)):
            self._forward_handler_stmt(stmt, state)


Instruction:
How would you explain what the following Python 3 function does
def _slice(self):

        regs = set(self._target_regs)
        tmps = set(self._target_tmps)
        stack_offsets = set(self._target_stack_offsets)

        state = SimLightState(regs=regs, temps=tmps, stack_offsets=stack_offsets)

        for stmt_idx, stmt in reversed(list(enumerate(self._statements))):
            if self._backward_handler_stmt(stmt, state):
                self.stmts.insert(0, stmt)
                self.stmt_indices.insert(0, stmt_idx)

                if self._inslice_callback:
                    self._inslice_callback(stmt_idx, stmt, self.inslice_callback_infodict)

            if not regs and not tmps and not stack_offsets:
                break

        self.final_regs = state.regs
        self.final_stack_offsets = state.stack_offsets

Response: Slice the internal state.


Instruction:
How would you explain what the following Python 3 function does
def prepare_function_symbol(self, symbol_name, basic_addr=None):
        if self.project.loader.main_object.is_ppc64_abiv1:
            if basic_addr is not None:
                pointer = self.project.loader.memory.unpack_word(basic_addr)
                return pointer, basic_addr

            pseudo_hookaddr = self.project.loader.extern_object.get_pseudo_addr(symbol_name)
            pseudo_toc = self.project.loader.extern_object.allocate(size=0x18)
            self.project.loader.extern_object.memory.pack_word(
                AT.from_mva(pseudo_toc, self.project.loader.extern_object).to_rva(), pseudo_hookaddr)
            return pseudo_hookaddr, pseudo_toc
        else:
            if basic_addr is None:
                basic_addr = self.project.loader.extern_object.get_pseudo_addr(symbol_name)
            return basic_addr, basic_addr

Response: Prepares the address space with the data necessary to perform relocations pointing to the given symbol.


Instruction:
Make a summary of the following Python 3 code
def initialize_segment_register_x64(self, state, concrete_target):
        _l.debug("Synchronizing fs segment register")
        state.regs.fs = self._read_fs_register_x64(concrete_target)

Response: Initialize the fs register in the angr to the value of the fs register in the concrete target.


Instruction:
Can you implement a function in Python 3 that
creates a GDT in the state memory and populate the segment registers.

Response:
def initialize_gdt_x86(self,state,concrete_target):
        """
        Create a GDT in the state memory and populate the segment registers.
        Rehook the vsyscall address using the real value in the concrete process memory

        :param state:               state which will be modified
        :param concrete_target:     concrete target that will be used to read the fs register
        :return:
        """
        _l.debug("Creating fake Global Descriptor Table and synchronizing gs segment register")
        gs = self._read_gs_register_x86(concrete_target)
        gdt = self.generate_gdt(0x0, gs)
        self.setup_gdt(state, gdt)

        # Synchronize the address of vsyscall in simprocedures dictionary with the concrete value
        _vsyscall_address = concrete_target.read_memory(gs + 0x10, state.project.arch.bits / 8)
        _vsyscall_address = struct.unpack(state.project.arch.struct_fmt(), _vsyscall_address)[0]
        state.project.rehook_symbol(_vsyscall_address, '_vsyscall')

        return gdt


Instruction:
How would you implement a function in Python 3 that
merges this node with the other node returning a new node that spans the both.

Response:
def merge(self, other):
        """
        Merges this node with the other, returning a new node that spans the both.
        """
        new_node = self.copy()
        new_node.size += other.size
        new_node.instruction_addrs += other.instruction_addrs
        # FIXME: byte_string should never be none, but it is sometimes
        # like, for example, patcherex test_cfg.py:test_fullcfg_properties
        if new_node.byte_string is None or other.byte_string is None:
            new_node.byte_string = None
        else:
            new_node.byte_string += other.byte_string
        return new_node


Instruction:
Explain what the following Python 3 code does
def new_array(state, element_type, size):
        size_bounded = SimSootExpr_NewArray._bound_array_size(state, size)
        # return the reference of the array base
        # => elements getting lazy initialized in the javavm memory
        return SimSootValue_ArrayBaseRef(heap_alloc_id=state.javavm_memory.get_new_uuid(),
                                         element_type=element_type,
                                         size=size_bounded)

Response: Allocates a new array in memory and returns the reference to the base.


Instruction:
Can you implement a function in Python 3 that
converts recovered reaching conditions from claripy ASTs to ailment Expressions

Response:
def _convert_claripy_bool_ast(self, cond):
        """
        Convert recovered reaching conditions from claripy ASTs to ailment Expressions

        :return: None
        """

        if isinstance(cond, ailment.Expr.Expression):
            return cond

        if cond.op == "BoolS" and claripy.is_true(cond):
            return cond
        if cond in self._condition_mapping:
            return self._condition_mapping[cond]

        _mapping = {
            'Not': lambda cond_: ailment.Expr.UnaryOp(None, 'Not', self._convert_claripy_bool_ast(cond_.args[0])),
            'And': lambda cond_: ailment.Expr.BinaryOp(None, 'LogicalAnd', (
                self._convert_claripy_bool_ast(cond_.args[0]),
                self._convert_claripy_bool_ast(cond_.args[1]),
            )),
            'Or': lambda cond_: ailment.Expr.BinaryOp(None, 'LogicalOr', (
                self._convert_claripy_bool_ast(cond_.args[0]),
                self._convert_claripy_bool_ast(cond_.args[1]),
            )),
            'ULE': lambda cond_: ailment.Expr.BinaryOp(None, 'CmpULE',
                                                          tuple(map(self._convert_claripy_bool_ast, cond_.args)),
                                                          ),
            '__le__': lambda cond_: ailment.Expr.BinaryOp(None, 'CmpLE',
                                                          tuple(map(self._convert_claripy_bool_ast, cond_.args)),
                                                          ),
            'UGT': lambda cond_: ailment.Expr.BinaryOp(None, 'CmpUGT',
                                                          tuple(map(self._convert_claripy_bool_ast, cond_.args)),
                                                          ),
            '__gt__': lambda cond_: ailment.Expr.BinaryOp(None, 'CmpGT',
                                                          tuple(map(self._convert_claripy_bool_ast, cond_.args)),
                                                          ),
            '__eq__': lambda cond_: ailment.Expr.BinaryOp(None, 'CmpEQ',
                                                          tuple(map(self._convert_claripy_bool_ast, cond_.args)),
                                                          ),
            '__ne__': lambda cond_: ailment.Expr.BinaryOp(None, 'CmpNE',
                                                          tuple(map(self._convert_claripy_bool_ast, cond_.args)),
                                                          ),
            '__xor__': lambda cond_: ailment.Expr.BinaryOp(None, 'Xor',
                                                          tuple(map(self._convert_claripy_bool_ast, cond_.args)),
                                                          ),
            'BVV': lambda cond_: ailment.Expr.Const(None, None, cond_.args[0], cond_.size()),
            'BoolV': lambda cond_: ailment.Expr.Const(None, None, True, 1) if cond_.args[0] is True
                                                                        else ailment.Expr.Const(None, None, False, 1),
        }

        if cond.op in _mapping:
            return _mapping[cond.op](cond)
        raise NotImplementedError(("Condition variable %s has an unsupported operator %s. "
                                   "Consider implementing.") % (cond, cond.op))


Instruction:
Given the following Python 3 function, write the documentation
def _extract_jump_targets(stmt):

        targets = [ ]

        # FIXME: We are assuming all jump targets are concrete targets. They may not be.

        if isinstance(stmt, ailment.Stmt.Jump):
            targets.append(stmt.target.value)
        elif isinstance(stmt, ailment.Stmt.ConditionalJump):
            targets.append(stmt.true_target.value)
            targets.append(stmt.false_target.value)

        return targets

Response: Extracts concrete jump targets from a Jump or ConditionalJump statement.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def malloc(self, sim_size):
        raise NotImplementedError("%s not implemented for %s" % (self.malloc.__func__.__name__,
                                                                 self.__class__.__name__))

Response: A somewhat faithful implementation of libc malloc.


Instruction:
Explain what the following Python 3 code does
def set_stack(self, stack_dump, stack_top):
        data = self._read_data(stack_dump)
        self.real_stack_top = stack_top
        addr = stack_top - len(data) # Address of the bottom of the stack
        l.info("Setting stack from 0x%x up to %#x", addr, stack_top)
        #FIXME: we should probably make we don't overwrite other stuff loaded there
        self._write(addr, data)

Response: Set the stack dump of the current session.


Instruction:
Implement a function in Python 3 to
set the heap dump to the given base address.

Response:
def set_heap(self, heap_dump, heap_base):
        """
        Heap dump is a dump of the heap from gdb, i.e. the result of the
        following gdb command:

        ``dump binary memory [stack_dump] [begin] [end]``

        :param heap_dump:   The dump file.
        :param heap_base:   The start address of the heap in the gdb session.
        """
        # We set the heap at the same addresses as the gdb session to avoid pointer corruption.
        data = self._read_data(heap_dump)
        self.state.heap.heap_location = heap_base + len(data)
        addr = heap_base
        l.info("Set heap from 0x%x to %#x", addr, addr+len(data))
        #FIXME: we should probably make we don't overwrite other stuff loaded there
        self._write(addr, data)


Instruction:
Create a Python 3 function for
setting the data of the current object to the given address.

Response:
def set_data(self, addr, data_dump):
        """
        Update any data range (most likely use is the data segments of loaded objects)
        """
        data = self._read_data(data_dump)
        l.info("Set data from 0x%x to %#x", addr, addr+len(data))
        self._write(addr, data)


Instruction:
Can you generate the documentation for the following Python 3 function
def set_regs(self, regs_dump):

        if self.real_stack_top == 0 and self.adjust_stack is True:
            raise SimStateError("You need to set the stack first, or set"
                    "adjust_stack to False. Beware that in this case, sp and bp won't be updated")

        data = self._read_data(regs_dump)
        rdata = re.split(b"\n", data)
        for r in rdata:
            if r == b"":
                continue
            reg = re.split(b" +", r)[0].decode()
            val = int(re.split(b" +", r)[1],16)
            try:
                self.state.registers.store(reg, claripy.BVV(val, self.state.arch.bits))
            # Some registers such as cs, ds, eflags etc. aren't supported in angr
            except KeyError as e:
                l.warning("Reg %s was not set", e)

        self._adjust_regs()

Response: Initialize the state registers within the state object.


Instruction:
How would you explain what the following Python 3 function does
def _adjust_regs(self):
        if not self.adjust_stack:
            return

        bp = self.state.arch.register_names[self.state.arch.bp_offset]
        sp = self.state.arch.register_names[self.state.arch.sp_offset]

        stack_shift = self.state.arch.initial_sp - self.real_stack_top
        self.state.registers.store(sp, self.state.regs.sp + stack_shift)

        if not self.omit_fp:
            self.state.registers.store(bp, self.state.regs.bp + stack_shift)

Response: Adjust sp and bp registers w. r. t. stack difference between GDB session and angr.


Instruction:
Can you write a function in Python 3 where it
parses a strongly connected graph and return a list of Loop objects.

Response:
def _parse_loop_graph(self, subg, bigg):
        """
        Create a Loop object for a strongly connected graph, and any strongly
        connected subgraphs, if possible.

        :param subg:    A strongly connected subgraph.
        :param bigg:    The graph which subg is a subgraph of.

        :return:        A list of Loop objects, some of which may be inside others,
                        but all need to be documented.
        """
        loop_body_nodes = list(subg.nodes())[:]
        entry_edges = []
        break_edges = []
        continue_edges = []
        entry_node = None
        for node in loop_body_nodes:
            for pred_node in bigg.predecessors(node):
                if pred_node not in loop_body_nodes:
                    if entry_node is not None and entry_node != node:
                        l.warning("Bad loop: more than one entry point (%s, %s)", entry_node, node)
                        return None, []
                    entry_node = node
                    entry_edges.append((pred_node, node))
                    subg.add_edge(pred_node, node)
            for succ_node in bigg.successors(node):
                if succ_node not in loop_body_nodes:
                    break_edges.append((node, succ_node))
                    subg.add_edge(node, succ_node)
        if entry_node is None:
            entry_node = min(loop_body_nodes, key=lambda n: n.addr)
            l.info("Couldn't find entry point, assuming it's the first by address (%s)", entry_node)

        acyclic_subg = subg.copy()
        for pred_node in subg.predecessors(entry_node):
            if pred_node in loop_body_nodes:
                continue_edge = (pred_node, entry_node)
                acyclic_subg.remove_edge(*continue_edge)
                continue_edges.append(continue_edge)

        removed_exits = {}
        removed_entries = {}
        tops, alls = self._parse_loops_from_graph(acyclic_subg)
        for subloop in tops:
            if subloop.entry in loop_body_nodes:
                # break existing entry edges, exit edges
                # re-link in loop object
                # the exception logic is to handle when you have two loops adjacent to each other
                # you gotta link the two loops together and remove the dangling edge
                for entry_edge in subloop.entry_edges:
                    try:
                        subg.remove_edge(*entry_edge)
                    except networkx.NetworkXError:
                        if entry_edge in removed_entries:
                            subg.add_edge(removed_entries[entry_edge], subloop)
                            try:
                                subg.remove_edge(removed_entries[entry_edge], entry_edge[1])
                            except networkx.NetworkXError:
                                pass
                        else:
                            raise
                    else:
                        subg.add_edge(entry_edge[0], subloop)
                        removed_entries[entry_edge] = subloop
                for exit_edge in subloop.break_edges:
                    try:
                        subg.remove_edge(*exit_edge)
                    except networkx.NetworkXError:
                        if exit_edge in removed_entries:
                            subg.add_edge(subloop, removed_entries[exit_edge])
                            try:
                                subg.remove_edge(exit_edge[0], removed_entries[exit_edge])
                            except networkx.NetworkXError:
                                pass
                        else:
                            raise
                    else:
                        subg.add_edge(subloop, exit_edge[1])
                        removed_exits[exit_edge] = subloop
                subg = next(filter(lambda g: entry_node in g.nodes(),
                        networkx.weakly_connected_component_subgraphs(subg)))

        me = Loop(entry_node,
             entry_edges,
             break_edges,
             continue_edges,
             loop_body_nodes,
             subg,
             tops[:])
        return me, [me] + alls


Instruction:
Create a Python 3 function for
returning a list of Loop instances that can be extracted from a graph.

Response:
def _parse_loops_from_graph(self, graph):
        """
        Return all Loop instances that can be extracted from a graph.

        :param graph:   The graph to analyze.

        :return:        A list of all the Loop instances that were found in the graph.
        """
        outtop = []
        outall = []
        for subg in networkx.strongly_connected_component_subgraphs(graph):
            if len(subg.nodes()) == 1:
                if len(list(subg.successors(list(subg.nodes())[0]))) == 0:
                    continue
            thisloop, allloops = self._parse_loop_graph(subg, graph)
            if thisloop is not None:
                outall += allloops
                outtop.append(thisloop)
        return outtop, outall


Instruction:
How would you explain what the following Python 3 function does
def get_ref(cls, state, obj_alloc_id, field_class_name, field_name, field_type):
        # resolve field
        field_class = state.javavm_classloader.get_class(field_class_name)
        field_id = resolve_field(state, field_class, field_name, field_type)
        # return field ref
        return cls.from_field_id(obj_alloc_id, field_id)

Response: Resolve the field within the given state.


Instruction:
How would you explain what the following Python 3 function does
def _euclidean_dist(vector_a, vector_b):
    dist = 0
    for (x, y) in zip(vector_a, vector_b):
        dist += (x-y)*(x-y)
    return math.sqrt(dist)

Response: Calculates the euclidean distance between two lists of numbers.


Instruction:
Given the following Python 3 function, write the documentation
def _get_closest_matches(input_attributes, target_attributes):
    closest_matches = {}

    # for each object in the first set find the objects with the closest target attributes
    for a in input_attributes:
        best_dist = float('inf')
        best_matches = []
        for b in target_attributes:
            dist = _euclidean_dist(input_attributes[a], target_attributes[b])
            if dist < best_dist:
                best_matches = [b]
                best_dist = dist
            elif dist == best_dist:
                best_matches.append(b)
        closest_matches[a] = best_matches

    return closest_matches

Response: Returns a dictionary of objects in the input_attributes to the closest objects in the target_attributes.


Instruction:
Write a Python 3 script for
returning the Levenshtein distance between two lists or strings

Response:
def _levenshtein_distance(s1, s2):
    """
    :param s1:  A list or string
    :param s2:  Another list or string
    :returns:    The levenshtein distance between the two
    """
    if len(s1) > len(s2):
        s1, s2 = s2, s1
    distances = range(len(s1) + 1)
    for index2, num2 in enumerate(s2):
        new_distances = [index2 + 1]
        for index1, num1 in enumerate(s1):
            if num1 == num2:
                new_distances.append(distances[index1])
            else:
                new_distances.append(1 + min((distances[index1],
                                             distances[index1+1],
                                             new_distances[-1])))
        distances = new_distances
    return distances[-1]


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _normalized_levenshtein_distance(s1, s2, acceptable_differences):
    if len(s1) > len(s2):
        s1, s2 = s2, s1
        acceptable_differences = set(-i for i in acceptable_differences)
    distances = range(len(s1) + 1)
    for index2, num2 in enumerate(s2):
        new_distances = [index2 + 1]
        for index1, num1 in enumerate(s1):
            if num2 - num1 in acceptable_differences:
                new_distances.append(distances[index1])
            else:
                new_distances.append(1 + min((distances[index1],
                                             distances[index1+1],
                                             new_distances[-1])))
        distances = new_distances
    return distances[-1]

Response: This function calculates the levenshtein distance between two lists.


Instruction:
Can you generate the documentation for the following Python 3 function
def _is_better_match(x, y, matched_a, matched_b, attributes_dict_a, attributes_dict_b):
    attributes_x = attributes_dict_a[x]
    attributes_y = attributes_dict_b[y]
    if x in matched_a:
        attributes_match = attributes_dict_b[matched_a[x]]
        if _euclidean_dist(attributes_x, attributes_y) >= _euclidean_dist(attributes_x, attributes_match):
            return False
    if y in matched_b:
        attributes_match = attributes_dict_a[matched_b[y]]
        if _euclidean_dist(attributes_x, attributes_y) >= _euclidean_dist(attributes_y, attributes_match):
            return False
    return True

Response: Returns True if the two sets have the same attributes.


Instruction:
Given the following Python 3 function, write the documentation
def differing_constants(block_a, block_b):
    statements_a = [s for s in block_a.vex.statements if s.tag != "Ist_IMark"] + [block_a.vex.next]
    statements_b = [s for s in block_b.vex.statements if s.tag != "Ist_IMark"] + [block_b.vex.next]
    if len(statements_a) != len(statements_b):
        raise UnmatchedStatementsException("Blocks have different numbers of statements")

    start_1 = min(block_a.instruction_addrs)
    start_2 = min(block_b.instruction_addrs)

    changes = []

    # check statements
    current_offset = None
    for statement, statement_2 in zip(statements_a, statements_b):
        # sanity check
        if statement.tag != statement_2.tag:
            raise UnmatchedStatementsException("Statement tag has changed")

        if statement.tag == "Ist_IMark":
            if statement.addr - start_1 != statement_2.addr - start_2:
                raise UnmatchedStatementsException("Instruction length has changed")
            current_offset = statement.addr - start_1
            continue

        differences = compare_statement_dict(statement, statement_2)
        for d in differences:
            if d.type != DIFF_VALUE:
                raise UnmatchedStatementsException("Instruction has changed")
            else:
                changes.append(ConstantChange(current_offset, d.value_a, d.value_b))

    return changes

Response: Compares two basic blocks and returns all the constants that differ from the first block to the second block.


Instruction:
Given the following Python 3 function, write the documentation
def probably_identical(self):
        if len(self._unmatched_blocks_from_a | self._unmatched_blocks_from_b) > 0:
            return False
        for (a, b) in self._block_matches:
            if not self.blocks_probably_identical(a, b):
                return False
        return True

Response: Returns True if all the two functions are identical.


Instruction:
Implement a Python 3 function for
returning a list of all the identical blocks in the cache.

Response:
def identical_blocks(self):
        """
        :returns: A list of block matches which appear to be identical
        """
        identical_blocks = []
        for (block_a, block_b) in self._block_matches:
            if self.blocks_probably_identical(block_a, block_b):
                identical_blocks.append((block_a, block_b))
        return identical_blocks


Instruction:
Implement a Python 3 function for
returning a list of all blocks which appear to differ in the same entry.

Response:
def differing_blocks(self):
        """
        :returns: A list of block matches which appear to differ
        """
        differing_blocks = []
        for (block_a, block_b) in self._block_matches:
            if not self.blocks_probably_identical(block_a, block_b):
                differing_blocks.append((block_a, block_b))
        return differing_blocks


Instruction:
Here you have a function in Python 3, explain what it does
def blocks_with_differing_constants(self):
        differing_blocks = []
        diffs = dict()
        for (block_a, block_b) in self._block_matches:
            if self.blocks_probably_identical(block_a, block_b) and \
                    not self.blocks_probably_identical(block_a, block_b, check_constants=True):
                differing_blocks.append((block_a, block_b))
        for block_a, block_b in differing_blocks:
            ba = NormalizedBlock(block_a, self._function_a)
            bb = NormalizedBlock(block_b, self._function_b)
            diffs[(block_a, block_b)] = FunctionDiff._block_diff_constants(ba, bb)
        return diffs

Response: Returns a list of blocks which appear to differ in the same function.


Instruction:
Create a Python 3 function for
computing the similarity of two basic blocks.

Response:
def block_similarity(self, block_a, block_b):
        """
        :param block_a: The first block address.
        :param block_b: The second block address.
        :returns:       The similarity of the basic blocks, normalized for the base address of the block and function
                        call addresses.
        """

        # handle sim procedure blocks
        if self._project_a.is_hooked(block_a) and self._project_b.is_hooked(block_b):
            if self._project_a._sim_procedures[block_a] == self._project_b._sim_procedures[block_b]:
                return 1.0
            else:
                return 0.0

        try:
            block_a = NormalizedBlock(block_a, self._function_a)
        except (SimMemoryError, SimEngineError):
            block_a = None

        try:
            block_b = NormalizedBlock(block_b, self._function_b)
        except (SimMemoryError, SimEngineError):
            block_b = None

        # if both were None then they are assumed to be the same, if only one was the same they are assumed to differ
        if block_a is None and block_b is None:
            return 1.0
        elif block_a is None or block_b is None:
            return 0.0

        # get all elements for computing similarity
        tags_a = [s.tag for s in block_a.statements]
        tags_b = [s.tag for s in block_b.statements]
        consts_a = [c.value for c in block_a.all_constants]
        consts_b = [c.value for c in block_b.all_constants]
        all_registers_a = [s.offset for s in block_a.statements if hasattr(s, "offset")]
        all_registers_b = [s.offset for s in block_b.statements if hasattr(s, "offset")]
        jumpkind_a = block_a.jumpkind
        jumpkind_b = block_b.jumpkind

        # compute total distance
        total_dist = 0
        total_dist += _levenshtein_distance(tags_a, tags_b)
        total_dist += _levenshtein_distance(block_a.operations, block_b.operations)
        total_dist += _levenshtein_distance(all_registers_a, all_registers_b)
        acceptable_differences = self._get_acceptable_constant_differences(block_a, block_b)
        total_dist += _normalized_levenshtein_distance(consts_a, consts_b, acceptable_differences)
        total_dist += 0 if jumpkind_a == jumpkind_b else 1

        # compute similarity
        num_values = max(len(tags_a), len(tags_b))
        num_values += max(len(consts_a), len(consts_b))
        num_values += max(len(block_a.operations), len(block_b.operations))
        num_values += 1  # jumpkind
        similarity = 1 - (float(total_dist) / num_values)

        return similarity


Instruction:
Write a Python 3 function for
checking if two blocks are identical.

Response:
def blocks_probably_identical(self, block_a, block_b, check_constants=False):
        """
        :param block_a:         The first block address.
        :param block_b:         The second block address.
        :param check_constants: Whether or not to require matching constants in blocks.
        :returns:               Whether or not the blocks appear to be identical.
        """
        # handle sim procedure blocks
        if self._project_a.is_hooked(block_a) and self._project_b.is_hooked(block_b):
            return self._project_a._sim_procedures[block_a] == self._project_b._sim_procedures[block_b]

        try:
            block_a = NormalizedBlock(block_a, self._function_a)
        except (SimMemoryError, SimEngineError):
            block_a = None

        try:
            block_b = NormalizedBlock(block_b, self._function_b)
        except (SimMemoryError, SimEngineError):
            block_b = None

        # if both were None then they are assumed to be the same, if only one was None they are assumed to differ
        if block_a is None and block_b is None:
            return True
        elif block_a is None or block_b is None:
            return False

        # if they represent a different number of blocks they are not the same
        if len(block_a.blocks) != len(block_b.blocks):
            return False

        # check differing constants
        try:
            diff_constants = FunctionDiff._block_diff_constants(block_a, block_b)
        except UnmatchedStatementsException:
            return False

        if not check_constants:
            return True

        # get values of differences that probably indicate no change
        acceptable_differences = self._get_acceptable_constant_differences(block_a, block_b)

        # todo match globals
        for c in diff_constants:
            if (c.value_a, c.value_b) in self._block_matches:
                # constants point to matched basic blocks
                continue
            if self._bindiff is not None and (c.value_a and c.value_b) in self._bindiff.function_matches:
                # constants point to matched functions
                continue
            # if both are in the binary we'll assume it's okay, although we should really match globals
            # TODO use global matches
            if self._project_a.loader.main_object.contains_addr(c.value_a) and \
                    self._project_b.loader.main_object.contains_addr(c.value_b):
                continue
            # if the difference is equal to the difference in block addr's or successor addr's we'll say it's also okay
            if c.value_b - c.value_a in acceptable_differences:
                continue
            # otherwise they probably are different
            return False

        # the blocks appear to be identical
        return True


Instruction:
Can you implement a function in Python 3 that
computes the basic block attributes for a given function.

Response:
def _compute_block_attributes(function):
        """
        :param function:    A normalized function object.
        :returns:           A dictionary of basic block addresses to tuples of attributes.
        """
        # The attributes we use are the distance form function start, distance from function exit and whether
        # or not it has a subfunction call
        distances_from_start = FunctionDiff._distances_from_function_start(function)
        distances_from_exit = FunctionDiff._distances_from_function_exit(function)
        call_sites = function.call_sites

        attributes = {}
        for block in function.graph.nodes():
            if block in call_sites:
                number_of_subfunction_calls = len(call_sites[block])
            else:
                number_of_subfunction_calls = 0
            # there really shouldn't be blocks that can't be reached from the start, but there are for now
            dist_start = distances_from_start[block] if block in distances_from_start else 10000
            dist_exit = distances_from_exit[block] if block in distances_from_exit else 10000

            attributes[block] = (dist_start, dist_exit, number_of_subfunction_calls)

        return attributes


Instruction:
Can you write a function in Python 3 where it
returns a dictionary of basic block addresses and their distance to the exit of the function.

Response:
def _distances_from_function_exit(function):
        """
        :param function:    A normalized Function object.
        :returns:           A dictionary of basic block addresses and their distance to the exit of the function.
        """
        reverse_graph = function.graph.reverse()
        # we aren't guaranteed to have an exit from the function so explicitly add the node
        reverse_graph.add_node("start")
        found_exits = False
        for n in function.graph.nodes():
            if len(list(function.graph.successors(n))) == 0:
                reverse_graph.add_edge("start", n)
                found_exits = True

        # if there were no exits (a function with a while 1) let's consider the block with the highest address to
        # be the exit. This isn't the most scientific way, but since this case is pretty rare it should be okay
        if not found_exits:
            last = max(function.graph.nodes(), key=lambda x:x.addr)
            reverse_graph.add_edge("start", last)

        dists = networkx.single_source_shortest_path_length(reverse_graph, "start")

        # remove temp node
        del dists["start"]

        # correct for the added node
        for n in dists:
            dists[n] -= 1

        return dists


Instruction:
Here you have a function in Python 3, explain what it does
def _compute_diff(self):
        # get the attributes for all blocks
        l.debug("Computing diff of functions: %s, %s",
                ("%#x" % self._function_a.startpoint.addr) if self._function_a.startpoint is not None else "None",
                ("%#x" % self._function_b.startpoint.addr) if self._function_b.startpoint is not None else "None"
                )
        self.attributes_a = self._compute_block_attributes(self._function_a)
        self.attributes_b = self._compute_block_attributes(self._function_b)

        # get the initial matches
        initial_matches = self._get_block_matches(self.attributes_a, self.attributes_b,
                                                  tiebreak_with_block_similarity=False)

        # Use a queue so we process matches in the order that they are found
        to_process = deque(initial_matches)

        # Keep track of which matches we've already added to the queue
        processed_matches = set((x, y) for (x, y) in initial_matches)

        # Keep a dict of current matches, which will be updated if better matches are found
        matched_a = dict()
        matched_b = dict()
        for (x, y) in processed_matches:
            matched_a[x] = y
            matched_b[y] = x

        # while queue is not empty
        while to_process:
            (block_a, block_b) = to_process.pop()
            l.debug("FunctionDiff: Processing (%#x, %#x)", block_a.addr, block_b.addr)

            # we could find new matches in the successors or predecessors of functions
            block_a_succ = list(self._function_a.graph.successors(block_a))
            block_b_succ = list(self._function_b.graph.successors(block_b))
            block_a_pred = list(self._function_a.graph.predecessors(block_a))
            block_b_pred = list(self._function_b.graph.predecessors(block_b))

            # propagate the difference in blocks as delta
            delta = tuple((i-j) for i, j in zip(self.attributes_b[block_b], self.attributes_a[block_a]))

            # get possible new matches
            new_matches = []

            # if the blocks are identical then the successors should most likely be matched in the same order
            if self.blocks_probably_identical(block_a, block_b) and len(block_a_succ) == len(block_b_succ):
                ordered_succ_a = self._get_ordered_successors(self._project_a, block_a, block_a_succ)
                ordered_succ_b = self._get_ordered_successors(self._project_b, block_b, block_b_succ)
                new_matches.extend(zip(ordered_succ_a, ordered_succ_b))

            new_matches += self._get_block_matches(self.attributes_a, self.attributes_b, block_a_succ, block_b_succ,
                                                   delta, tiebreak_with_block_similarity=True)
            new_matches += self._get_block_matches(self.attributes_a, self.attributes_b, block_a_pred, block_b_pred,
                                                   delta, tiebreak_with_block_similarity=True)

            # for each of the possible new matches add it if it improves the matching
            for (x, y) in new_matches:
                if (x, y) not in processed_matches:
                    processed_matches.add((x, y))
                    l.debug("FunctionDiff: checking if (%#x, %#x) is better", x.addr, y.addr)
                    # if it's a better match than what we already have use it
                    if _is_better_match(x, y, matched_a, matched_b, self.attributes_a, self.attributes_b):
                        l.debug("FunctionDiff: adding possible match (%#x, %#x)", x.addr, y.addr)
                        if x in matched_a:
                            old_match = matched_a[x]
                            del matched_b[old_match]
                        if y in matched_b:
                            old_match = matched_b[y]
                            del matched_a[old_match]
                        matched_a[x] = y
                        matched_b[y] = x
                        to_process.appendleft((x, y))

        # reformat matches into a set of pairs
        self._block_matches = set((x, y) for (x, y) in matched_a.items())

        # get the unmatched blocks
        self._unmatched_blocks_from_a = set(x for x in self._function_a.graph.nodes() if x not in matched_a)
        self._unmatched_blocks_from_b = set(x for x in self._function_b.graph.nodes() if x not in matched_b)

Response: Compute the diff between the functions and saves the result.


Instruction:
Make a summary of the following Python 3 code
def _get_block_matches(self, attributes_a, attributes_b, filter_set_a=None, filter_set_b=None, delta=(0, 0, 0),
                           tiebreak_with_block_similarity=False):
        """
        :param attributes_a:    A dict of blocks to their attributes
        :param attributes_b:    A dict of blocks to their attributes

        The following parameters are optional.

        :param filter_set_a:    A set to limit attributes_a to the blocks in this set.
        :param filter_set_b:    A set to limit attributes_b to the blocks in this set.
        :param delta:           An offset to add to each vector in attributes_a.
        :returns:               A list of tuples of matching objects.
        """
        # get the attributes that are in the sets
        if filter_set_a is None:
            filtered_attributes_a = {k: v for k, v in attributes_a.items()}
        else:
            filtered_attributes_a = {k: v for k, v in attributes_a.items() if k in filter_set_a}

        if filter_set_b is None:
            filtered_attributes_b = {k: v for k, v in attributes_b.items()}
        else:
            filtered_attributes_b = {k: v for k, v in attributes_b.items() if k in filter_set_b}

        # add delta
        for k in filtered_attributes_a:
            filtered_attributes_a[k] = tuple((i+j) for i, j in zip(filtered_attributes_a[k], delta))
        for k in filtered_attributes_b:
            filtered_attributes_b[k] = tuple((i+j) for i, j in zip(filtered_attributes_b[k], delta))

        # get closest
        closest_a = _get_closest_matches(filtered_attributes_a, filtered_attributes_b)
        closest_b = _get_closest_matches(filtered_attributes_b, filtered_attributes_a)

        if tiebreak_with_block_similarity:
            # use block similarity to break ties in the first set
            for a in closest_a:
                if len(closest_a[a]) > 1:
                    best_similarity = 0
                    best = []
                    for x in closest_a[a]:
                        similarity = self.block_similarity(a, x)
                        if similarity > best_similarity:
                            best_similarity = similarity
                            best = [x]
                        elif similarity == best_similarity:
                            best.append(x)
                    closest_a[a] = best

            # use block similarity to break ties in the second set
            for b in closest_b:
                if len(closest_b[b]) > 1:
                    best_similarity = 0
                    best = []
                    for x in closest_b[b]:
                        similarity = self.block_similarity(x, b)
                        if similarity > best_similarity:
                            best_similarity = similarity
                            best = [x]
                        elif similarity == best_similarity:
                            best.append(x)
                    closest_b[b] = best

        # a match (x,y) is good if x is the closest to y and y is the closest to x
        matches = []
        for a in closest_a:
            if len(closest_a[a]) == 1:
                match = closest_a[a][0]
                if len(closest_b[match]) == 1 and closest_b[match][0] == a:
                    matches.append((a, match))

        return matches

Response: Get the set of attributes that are in the set and the closest matches.


Instruction:
Can you tell what is the following Python 3 function doing
def functions_probably_identical(self, func_a_addr, func_b_addr, check_consts=False):
        if self.cfg_a.project.is_hooked(func_a_addr) and self.cfg_b.project.is_hooked(func_b_addr):
            return self.cfg_a.project._sim_procedures[func_a_addr] == self.cfg_b.project._sim_procedures[func_b_addr]

        func_diff = self.get_function_diff(func_a_addr, func_b_addr)
        if check_consts:
            return func_diff.probably_identical_with_consts

        return func_diff.probably_identical

Response: Compare two functions and return True if they appear identical.


Instruction:
Given the following Python 3 function, write the documentation
def identical_functions(self):
        identical_funcs = []
        for (func_a, func_b) in self.function_matches:
            if self.functions_probably_identical(func_a, func_b):
                identical_funcs.append((func_a, func_b))
        return identical_funcs

Response: Returns a list of function matches that appear to be identical to the entry point.


Instruction:
Given the following Python 3 function, write the documentation
def differing_functions(self):
        different_funcs = []
        for (func_a, func_b) in self.function_matches:
            if not self.functions_probably_identical(func_a, func_b):
                different_funcs.append((func_a, func_b))
        return different_funcs

Response: Returns a list of functions that appear to differ in the same resource.


Instruction:
Can you tell what is the following Python 3 function doing
def differing_functions_with_consts(self):
        different_funcs = []
        for (func_a, func_b) in self.function_matches:
            if not self.functions_probably_identical(func_a, func_b, check_consts=True):
                different_funcs.append((func_a, func_b))
        return different_funcs

Response: Returns a list of functions that appear to differ including just by constants.


Instruction:
Write a Python 3 function for
returning a list of all the blocks that appear to differ in the same entry.

Response:
def differing_blocks(self):
        """
        :returns: A list of block matches that appear to differ
        """
        differing_blocks = []
        for (func_a, func_b) in self.function_matches:
            differing_blocks.extend(self.get_function_diff(func_a, func_b).differing_blocks)
        return differing_blocks


Instruction:
Here you have a function in Python 3, explain what it does
def identical_blocks(self):
        identical_blocks = []
        for (func_a, func_b) in self.function_matches:
            identical_blocks.extend(self.get_function_diff(func_a, func_b).identical_blocks)
        return identical_blocks

Response: A list of all block matches that appear to be identical


Instruction:
Can you generate a brief explanation for the following Python 3 code
def blocks_with_differing_constants(self):
        diffs = dict()
        for (func_a, func_b) in self.function_matches:
            diffs.update(self.get_function_diff(func_a, func_b).blocks_with_differing_constants)
        return diffs

Response: A dict of block matches with differing constants to the tuple of constants


Instruction:
Given the following Python 3 function, write the documentation
def get_function_diff(self, function_addr_a, function_addr_b):
        pair = (function_addr_a, function_addr_b)
        if pair not in self._function_diffs:
            function_a = self.cfg_a.kb.functions.function(function_addr_a)
            function_b = self.cfg_b.kb.functions.function(function_addr_b)
            self._function_diffs[pair] = FunctionDiff(function_a, function_b, self)
        return self._function_diffs[pair]

Response: Returns the FunctionDiff object for the two functions in the binary.


Instruction:
How would you implement a function in Python 3 that
computes the attributes of the functions in the object store.

Response:
def _compute_function_attributes(cfg):
        """
        :param cfg: An angr CFG object
        :returns:    a dictionary of function addresses to tuples of attributes
        """
        # the attributes we use are the number of basic blocks, number of edges, and number of subfunction calls
        attributes = dict()
        all_funcs = set(cfg.kb.callgraph.nodes())
        for function_addr in cfg.kb.functions:
            # skip syscalls and functions which are None in the cfg
            if cfg.kb.functions.function(function_addr) is None or cfg.kb.functions.function(function_addr).is_syscall:
                continue
            if cfg.kb.functions.function(function_addr) is not None:
                normalized_funtion = NormalizedFunction(cfg.kb.functions.function(function_addr))
                number_of_basic_blocks = len(normalized_funtion.graph.nodes())
                number_of_edges = len(normalized_funtion.graph.edges())
            else:
                number_of_basic_blocks = 0
                number_of_edges = 0
            if function_addr in all_funcs:
                number_of_subfunction_calls = len(list(cfg.kb.callgraph.successors(function_addr)))
            else:
                number_of_subfunction_calls = 0
            attributes[function_addr] = (number_of_basic_blocks, number_of_edges, number_of_subfunction_calls)

        return attributes


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _get_function_matches(attributes_a, attributes_b, filter_set_a=None, filter_set_b=None):
        # get the attributes that are in the sets
        if filter_set_a is None:
            filtered_attributes_a = {k: v for k, v in attributes_a.items()}
        else:
            filtered_attributes_a = {k: v for k, v in attributes_a.items() if k in filter_set_a}

        if filter_set_b is None:
            filtered_attributes_b = {k: v for k, v in attributes_b.items()}
        else:
            filtered_attributes_b = {k: v for k, v in attributes_b.items() if k in filter_set_b}

        # get closest
        closest_a = _get_closest_matches(filtered_attributes_a, filtered_attributes_b)
        closest_b = _get_closest_matches(filtered_attributes_b, filtered_attributes_a)

        # a match (x,y) is good if x is the closest to y and y is the closest to x
        matches = []
        for a in closest_a:
            if len(closest_a[a]) == 1:
                match = closest_a[a][0]
                if len(closest_b[match]) == 1 and closest_b[match][0] == a:
                    matches.append((a, match))

        return matches

Response: Returns a list of tuples of matching functions.


Instruction:
How would you explain what the following Python 3 function does
def load_shellcode(shellcode, arch, start_offset=0, load_address=0):
    return Project(
            BytesIO(shellcode),
            main_opts={
                'backend': 'blob',
                'arch': arch,
                'entry_point': start_offset,
                'base_addr': load_address,
            }
        )

Response: Load a new project based on a string of raw bytecode.


Instruction:
Explain what the following Python 3 code does
def _register_object(self, obj, sim_proc_arch):

        # Step 1: get the set of libraries we are allowed to use to resolve unresolved symbols
        missing_libs = []
        for lib_name in self.loader.missing_dependencies:
            try:
                missing_libs.append(SIM_LIBRARIES[lib_name])
            except KeyError:
                l.info("There are no simprocedures for missing library %s :(", lib_name)
        # additionally provide libraries we _have_ loaded as a fallback fallback
        # this helps in the case that e.g. CLE picked up a linux arm libc to satisfy an android arm binary
        for lib in self.loader.all_objects:
            if lib.provides in SIM_LIBRARIES:
                simlib = SIM_LIBRARIES[lib.provides]
                if simlib not in missing_libs:
                    missing_libs.append(simlib)

        # Step 2: Categorize every "import" symbol in each object.
        # If it's IGNORED, mark it for stubbing
        # If it's blacklisted, don't process it
        # If it matches a simprocedure we have, replace it
        for reloc in obj.imports.values():
            # Step 2.1: Quick filter on symbols we really don't care about
            func = reloc.symbol
            if func is None:
                continue
            if not func.is_function and func.type != cle.backends.symbol.Symbol.TYPE_NONE:
                continue
            if not reloc.resolved:
                # This is a hack, effectively to support Binary Ninja, which doesn't provide access to dependency
                # library names. The backend creates the Relocation objects, but leaves them unresolved so that
                # we can try to guess them here. Once the Binary Ninja API starts supplying the dependencies,
                # The if/else, along with Project._guess_simprocedure() can be removed if it has no other utility,
                # just leave behind the 'unresolved' debug statement from the else clause.
                if reloc.owner.guess_simprocs:
                    l.debug("Looking for matching SimProcedure for unresolved %s from %s with hint %s",
                            func.name, reloc.owner, reloc.owner.guess_simprocs_hint)
                    self._guess_simprocedure(func, reloc.owner.guess_simprocs_hint)
                else:
                    l.debug("Ignoring unresolved import '%s' from %s ...?", func.name, reloc.owner)
                continue
            export = reloc.resolvedby
            if self.is_hooked(export.rebased_addr):
                l.debug("Already hooked %s (%s)", export.name, export.owner)
                continue

            # Step 2.2: If this function has been resolved by a static dependency,
            # check if we actually can and want to replace it with a SimProcedure.
            # We opt out of this step if it is blacklisted by ignore_functions, which
            # will cause it to be replaced by ReturnUnconstrained later.
            if export.owner is not self.loader._extern_object and \
                    export.name not in self._ignore_functions:
                if self._check_user_blacklists(export.name):
                    continue
                owner_name = export.owner.provides
                if isinstance(self.loader.main_object, cle.backends.pe.PE):
                    owner_name = owner_name.lower()
                if owner_name not in SIM_LIBRARIES:
                    continue
                sim_lib = SIM_LIBRARIES[owner_name]
                if not sim_lib.has_implementation(export.name):
                    continue
                l.info("Using builtin SimProcedure for %s from %s", export.name, sim_lib.name)
                self.hook_symbol(export.rebased_addr, sim_lib.get(export.name, sim_proc_arch))

            # Step 2.3: If 2.2 didn't work, check if the symbol wants to be resolved
            # by a library we already know something about. Resolve it appropriately.
            # Note that _check_user_blacklists also includes _ignore_functions.
            # An important consideration is that even if we're stubbing a function out,
            # we still want to try as hard as we can to figure out where it comes from
            # so we can get the calling convention as close to right as possible.
            elif reloc.resolvewith is not None and reloc.resolvewith in SIM_LIBRARIES:
                sim_lib = SIM_LIBRARIES[reloc.resolvewith]
                if self._check_user_blacklists(export.name):
                    if not func.is_weak:
                        l.info("Using stub SimProcedure for unresolved %s from %s", func.name, sim_lib.name)
                        self.hook_symbol(export.rebased_addr, sim_lib.get_stub(export.name, sim_proc_arch))
                else:
                    l.info("Using builtin SimProcedure for unresolved %s from %s", export.name, sim_lib.name)
                    self.hook_symbol(export.rebased_addr, sim_lib.get(export.name, sim_proc_arch))

            # Step 2.4: If 2.3 didn't work (the symbol didn't request a provider we know of), try
            # looking through each of the SimLibraries we're using to resolve unresolved
            # functions. If any of them know anything specifically about this function,
            # resolve it with that. As a final fallback, just ask any old SimLibrary
            # to resolve it.
            elif missing_libs:
                for sim_lib in missing_libs:
                    if sim_lib.has_metadata(export.name):
                        if self._check_user_blacklists(export.name):
                            if not func.is_weak:
                                l.info("Using stub SimProcedure for unresolved %s from %s", export.name, sim_lib.name)
                                self.hook_symbol(export.rebased_addr, sim_lib.get_stub(export.name, sim_proc_arch))
                        else:
                            l.info("Using builtin SimProcedure for unresolved %s from %s", export.name, sim_lib.name)
                            self.hook_symbol(export.rebased_addr, sim_lib.get(export.name, sim_proc_arch))
                        break
                else:
                    if not func.is_weak:
                        l.info("Using stub SimProcedure for unresolved %s", export.name)
                        self.hook_symbol(export.rebased_addr, missing_libs[0].get(export.name, sim_proc_arch))

            # Step 2.5: If 2.4 didn't work (we have NO SimLibraries to work with), just
            # use the vanilla ReturnUnconstrained, assuming that this isn't a weak func
            elif not func.is_weak:
                l.info("Using stub SimProcedure for unresolved %s", export.name)
                self.hook_symbol(export.rebased_addr, SIM_PROCEDURES['stubs']['ReturnUnconstrained'](display_name=export.name, is_stub=True))

Response: This function scans through an object imports and hooks them with simprocedures from our library and adds the needed libraries to the object if they don t have any.


Instruction:
Can you implement a function in Python 3 that
guesses the SimProcedure for a symbol name f.

Response:
def _guess_simprocedure(self, f, hint):
        """
        Does symbol name `f` exist as a SIM_PROCEDURE? If so, return it, else return None.
        Narrows down the set of libraries to search based on hint.
        Part of the hack to enable Binary Ninja support. Remove if _register_objects() stops using it.
        """
        # First, filter the SIM_LIBRARIES to a reasonable subset based on the hint
        hinted_libs = []
        if hint == "win":
            hinted_libs = filter(lambda lib: lib if lib.endswith(".dll") else None, SIM_LIBRARIES)
        else:
            hinted_libs = filter(lambda lib: lib if ".so" in lib else None, SIM_LIBRARIES)

        for lib in hinted_libs:
            if SIM_LIBRARIES[lib].has_implementation(f.name):
                l.debug("Found implementation for %s in %s", f, lib)
                self.hook_symbol(f.relative_addr, (SIM_LIBRARIES[lib].get(f.name, self.arch)))
                break
        else:
            l.debug("Could not find matching SimProcedure for %s, ignoring.", f.name)


Instruction:
How would you implement a function in Python 3 that
checks if the user has blacklisted the given symbol name f.

Response:
def _check_user_blacklists(self, f):
        """
        Has symbol name `f` been marked for exclusion by any of the user
        parameters?
        """
        return not self._should_use_sim_procedures or \
            f in self._exclude_sim_procedures_list or \
            f in self._ignore_functions or \
            (self._exclude_sim_procedures_func is not None and self._exclude_sim_procedures_func(f))


Instruction:
How would you implement a function in Python 3 that
hooks a section of code with a custom function. This is used internally to provide symbolic summaries of library functions, and can be used to instrument execution or to modify control flow. When hook is not specified, it returns a function decorator that allows easy hooking. Usage:: # Assuming proj is an instance of angr.Project, we will add a custom hook at the entry # point of the project. @proj.hook(proj.entry) def my_hook(state): print("Welcome to execution!") :param addr: The address to hook. :param hook: A :class:`angr.project.Hook` describing a procedure to run at the given address. You may also pass in a SimProcedure class or a function directly and it will be wrapped in a Hook object for you. :param length: If you provide a function for the hook, this is the number of bytes that will be skipped by executing the hook by default. :param kwargs: If you provide a SimProcedure for the hook, these are the keyword arguments that will be passed to the procedure's `run` method eventually. :param replace: Control the behavior on finding that the address is already hooked. If true, silently replace the hook. If false (default), warn and do not replace the hook. If none, warn and replace the hook.

Response:
def hook(self, addr, hook=None, length=0, kwargs=None, replace=False):
        """
        Hook a section of code with a custom function. This is used internally to provide symbolic
        summaries of library functions, and can be used to instrument execution or to modify
        control flow.

        When hook is not specified, it returns a function decorator that allows easy hooking.
        Usage::

            # Assuming proj is an instance of angr.Project, we will add a custom hook at the entry
            # point of the project.
            @proj.hook(proj.entry)
            def my_hook(state):
                print("Welcome to execution!")

        :param addr:        The address to hook.
        :param hook:        A :class:`angr.project.Hook` describing a procedure to run at the
                            given address. You may also pass in a SimProcedure class or a function
                            directly and it will be wrapped in a Hook object for you.
        :param length:      If you provide a function for the hook, this is the number of bytes
                            that will be skipped by executing the hook by default.
        :param kwargs:      If you provide a SimProcedure for the hook, these are the keyword
                            arguments that will be passed to the procedure's `run` method
                            eventually.
        :param replace:     Control the behavior on finding that the address is already hooked. If
                            true, silently replace the hook. If false (default), warn and do not
                            replace the hook. If none, warn and replace the hook.
        """
        if hook is None:
            # if we haven't been passed a thing to hook with, assume we're being used as a decorator
            return self._hook_decorator(addr, length=length, kwargs=kwargs)

        if kwargs is None: kwargs = {}

        l.debug('hooking %s with %s', self._addr_to_str(addr), str(hook))

        if self.is_hooked(addr):
            if replace is True:
                pass
            elif replace is False:
                l.warning("Address is already hooked, during hook(%s, %s). Not re-hooking.", self._addr_to_str(addr), hook)
                return
            else:
                l.warning("Address is already hooked, during hook(%s, %s). Re-hooking.", self._addr_to_str(addr), hook)

        if isinstance(hook, type):
            raise TypeError("Please instanciate your SimProcedure before hooking with it")

        if callable(hook):
            hook = SIM_PROCEDURES['stubs']['UserHook'](user_func=hook, length=length, **kwargs)

        self._sim_procedures[addr] = hook


Instruction:
Given the following Python 3 function, write the documentation
def hooked_by(self, addr):

        if not self.is_hooked(addr):
            l.warning("Address %s is not hooked", self._addr_to_str(addr))
            return None

        return self._sim_procedures[addr]

Response: Returns the current hook for addr.


Instruction:
Can you tell what is the following Python 3 function doing
def unhook(self, addr):
        if not self.is_hooked(addr):
            l.warning("Address %s not hooked", self._addr_to_str(addr))
            return

        del self._sim_procedures[addr]

Response: Removes a hook from the list of functions that are hooked at the given address.


Instruction:
Write a Python 3 script for
resolving a dependency in a binary and hook it with the actual version of the module.

Response:
def hook_symbol(self, symbol_name, simproc, kwargs=None, replace=None):
        """
        Resolve a dependency in a binary. Looks up the address of the given symbol, and then hooks that
        address. If the symbol was not available in the loaded libraries, this address may be provided
        by the CLE externs object.

        Additionally, if instead of a symbol name you provide an address, some secret functionality will
        kick in and you will probably just hook that address, UNLESS you're on powerpc64 ABIv1 or some
        yet-unknown scary ABI that has its function pointers point to something other than the actual
        functions, in which case it'll do the right thing.

        :param symbol_name: The name of the dependency to resolve.
        :param simproc:     The SimProcedure instance (or function) with which to hook the symbol
        :param kwargs:      If you provide a SimProcedure for the hook, these are the keyword
                            arguments that will be passed to the procedure's `run` method
                            eventually.
        :param replace:     Control the behavior on finding that the address is already hooked. If
                            true, silently replace the hook. If false, warn and do not replace the
                            hook. If none (default), warn and replace the hook.
        :returns:           The address of the new symbol.
        :rtype:             int
        """
        if type(symbol_name) is not int:
            sym = self.loader.find_symbol(symbol_name)
            if sym is None:
                # it could be a previously unresolved weak symbol..?
                new_sym = None
                for reloc in self.loader.find_relevant_relocations(symbol_name):
                    if not reloc.symbol.is_weak:
                        raise Exception("Symbol is strong but we couldn't find its resolution? Report to @rhelmot.")
                    if new_sym is None:
                        new_sym = self.loader.extern_object.make_extern(symbol_name)
                    reloc.resolve(new_sym)
                    reloc.relocate([])

                if new_sym is None:
                    l.error("Could not find symbol %s", symbol_name)
                    return None
                sym = new_sym

            basic_addr = sym.rebased_addr
        else:
            basic_addr = symbol_name
            symbol_name = None

        hook_addr, _ = self.simos.prepare_function_symbol(symbol_name, basic_addr=basic_addr)

        self.hook(hook_addr, simproc, kwargs=kwargs, replace=replace)
        return hook_addr


Instruction:
Can you generate the documentation for the following Python 3 function
def is_symbol_hooked(self, symbol_name):
        sym = self.loader.find_symbol(symbol_name)
        if sym is None:
            l.warning("Could not find symbol %s", symbol_name)
            return False
        hook_addr, _ = self.simos.prepare_function_symbol(symbol_name, basic_addr=sym.rebased_addr)
        return self.is_hooked(hook_addr)

Response: Check if a symbol is already hooked.


Instruction:
How would you explain what the following Python 3 function does
def unhook_symbol(self, symbol_name):
        sym = self.loader.find_symbol(symbol_name)
        if sym is None:
            l.warning("Could not find symbol %s", symbol_name)
            return False
        if sym.owner is self.loader._extern_object:
            l.warning("Refusing to unhook external symbol %s, replace it with another hook if you want to change it",
                      symbol_name)
            return False

        hook_addr, _ = self.simos.prepare_function_symbol(symbol_name, basic_addr=sym.rebased_addr)
        self.unhook(hook_addr)
        return True

Response: Unhook a hook on a symbol.


Instruction:
Create a Python 3 function to
move the hook for a specific symbol to a specific address

Response:
def rehook_symbol(self, new_address, symbol_name):
        """
        Move the hook for a symbol to a specific address
        :param new_address: the new address that will trigger the SimProc execution
        :param symbol_name: the name of the symbol (f.i. strcmp )
        :return: None
        """
        new_sim_procedures = {}
        for key_address, simproc_obj in self._sim_procedures.items():
            if simproc_obj.display_name == symbol_name:
                new_sim_procedures[new_address] = simproc_obj
            else:
                new_sim_procedures[key_address] = simproc_obj

        self._sim_procedures = new_sim_procedures


Instruction:
Explain what the following Python 3 code does
def execute(self, *args, **kwargs):

        if args:
            state = args[0]
        else:
            state = self.factory.full_init_state(**kwargs)

        pg = self.factory.simulation_manager(state)
        self._executing = True
        return pg.run(until=lambda lpg: not self._executing)

Response: This function is a simple style symbolic execution helper that returns a simulation manager that is ready to be used to execute the entry point.


Instruction:
Given the following Python 3 function, write the documentation
def _hook_decorator(self, addr, length=0, kwargs=None):

        def hook_decorator(func):
            self.hook(addr, func, length=length, kwargs=kwargs)
            return func

        return hook_decorator

Response: A decorator that allows easy hooking of the current object.


Instruction:
How would you explain what the following Python 3 function does
def is_java_project(self):
        if self._is_java_project is None:
            self._is_java_project = isinstance(self.arch, ArchSoot)
        return self._is_java_project

Response: Indicates if the project s main binary is a Java Archive.


Instruction:
How would you code a function in Python 3 to
indicate if the project s main binary is a Java Archive which contains native libraries.

Response:
def is_java_jni_project(self):
        """
        Indicates if the project's main binary is a Java Archive, which
        interacts during its execution with native libraries (via JNI).
        """
        if self._is_java_jni_project is None:
            self._is_java_jni_project = isinstance(self.arch, ArchSoot) and self.simos.is_javavm_with_jni_support
        return self._is_java_jni_project


Instruction:
Here you have a function in Python 3, explain what it does
def register_preset(cls, name, preset):
        if cls._presets is None:
            cls._presets = {}
        cls._presets[name] = preset

Response: Register a preset instance with the class of the hub.


Instruction:
Write a Python 3 script to
apply a preset to the hub.

Response:
def use_plugin_preset(self, preset):
        """
        Apply a preset to the hub. If there was a previously active preset, discard it.

        Preset can be either the string name of a preset or a PluginPreset instance.
        """
        if isinstance(preset, str):
            try:
                preset = self._presets[preset]
            except (AttributeError, KeyError):
                raise AngrNoPluginError("There is no preset named %s" % preset)

        elif not isinstance(preset, PluginPreset):
            raise ValueError("Argument must be an instance of PluginPreset: %s" % preset)

        if self._active_preset:
            l.warning("Overriding active preset %s with %s", self._active_preset, preset)
            self.discard_plugin_preset()

        preset.activate(self)
        self._active_preset = preset


Instruction:
Write a Python 3 function for
discarding the current active preset. Will release any plugins that were previously provided by the old preset. Will release any plugins that were previously provided by the old preset. Will release any plugins that were previously provided by the old preset.

Response:
def discard_plugin_preset(self):
        """
        Discard the current active preset. Will release any active plugins that could have come from the old preset.
        """
        if self.has_plugin_preset:
            for name, plugin in list(self._active_plugins.items()):
                if id(plugin) in self._provided_by_preset:
                    self.release_plugin(name)
            self._active_preset.deactivate(self)
        self._active_preset = None