docs: def find_gadget(elf, gadget, align=1, unique=True):
      """
      Find a ROP gadget in a the executable sections of an ELF executable or
      library. The ROP gadget can be either a set of bytes for an exact match
      or a (bytes) regular expression. Once it finds gadgets, it uses the
      capstone engine to verify if the gadget consists of valid instructions
      and doesn't contain any call or jump instructions.
  
      Args:
          elf(:class:`~pwnypack.elf.ELF`): The ELF instance to find a gadget in.
          gadget(bytes or regexp): The gadget to find.
          align(int): Make sure the gadget starts at a multiple of this number
          unique(bool): If true, only unique gadgets are returned.
  
      Returns:
          dict: A dictionary containing a description of the found
              gadget. Contains the following fields:
  
              - section: The section the gadget was found in.
              - offset: The offset inside the segment the gadget was found at.
              - addr: The virtual memory address the gadget will be located at.
              - gadget: The machine code of the found gadget.
              - asm: A list of disassembled instructions.
  
      """
  
      if not HAVE_CAPSTONE:
          raise NotImplementedError('pwnypack requires capstone to find ROP gadgets')
  
      if not isinstance(elf, pwnypack.elf.ELF):
          elf = pwnypack.elf.ELF(elf)
  
      matches = []
      gadgets = []
  
      if isinstance(gadget, six.binary_type):
          gadget = re.compile(re.escape(gadget))
  
      for section in elf.section_headers:
          if section.type != section.Type.progbits:
              continue
  
          for match in gadget.finditer(section.content):
              match_index = match.start()
              if match_index % align != 0:
                  continue
  
              match_gadget = match.group()
  
              if match_gadget in gadgets:
                  continue
  
              match_addr = section.addr + match_index
  
              md = pwnypack.asm.prepare_capstone(syntax=pwnypack.asm.AsmSyntax.intel, target=elf)
              md.detail = True
              match_asm = []
  
              for insn in md.disasm(match_gadget, match_addr):
                  if insn.id == capstone.CS_OP_INVALID or set(insn.groups) & INVALID_GROUPS:
                      # Don't try to disassemble this particular gadget again.
                      gadgets.append(match_gadget)
                      break
                  match_asm.append((insn.mnemonic + ' ' + insn.op_str).strip())
              else:
                  matches.append({
                      'section': section,
                      'offset': match_index,
                      'addr': match_addr,
                      'gadget': match_gadget,
                      'asm': match_asm,
                  })
                  if unique:
                      gadgets.append(match_gadget)
  
      return matches