def postprocess_chain(chain, guard_solutions):
    """
    This function post-processes the chains generated by angrop to insert input to pass
    the conditions on each gadget. It takes two arguments:

        chain - the ropchain returned by angrop
        guard_solutions - the required inputs to satisfy the gadget checks
    """
    # we assemble the chain into bytes, since we will process it that way
    payload = chain.payload_str()

    # we iterate through the whole chain to fix up each gadget. The first 8
    # bytes of the remaining "payload" string always correspond to the address
    # of the next gadget in chain._gadgets
    guarded_chain = payload[:8]
    payload = payload[8:]
    for g in chain._gadgets:
        # each gadget records how it changes the stack, which is the amount of
        # input that it pops from the payload, so we add that to our result
        guarded_chain += payload[:g.stack_change - 8]
        payload = payload[g.stack_change - 8:]

        # now, we add the input to spatisfy the conditions for triggering the
        # next gadget before going on to analyze it
        guarded_chain += guard_solutions[g.addr]
        guarded_chain += payload[:8]
        payload = payload[8:]

    assert len(payload) == 0
    return guarded_chain