docs: def marshal_load(fp, origin=None):
      """
      Unserialize data serialized with :func:`marshal.dump`. This function
      works across python versions. Marshalled code objects are returned as
      instances of :class:`~pwnypack.bytecode.CodeObject`.
  
      Arguments:
          fp(file): A file or file-like object that contains the serialized
              data.
          origin(dict): The opcode specification of the python version that
              generated the data. If you provide ``None``, the specs for the
              currently running python version will be used.
  
      Returns:
          The unserialized data.
      """
  
      origin = get_py_internals(origin)
      version = origin['version']
  
      refs = []
  
      def ref(o, flags):
          if flags & FLAG_REF:
              refs.append(o)
          return o
  
      def read_byte():
          return six.byte2int(fp.read(1))
  
      def read_short():
          return u16(fp.read(2), target=MARSHAL_TARGET)
  
      def read_long():
          return u32(fp.read(4), target=MARSHAL_TARGET)
  
      def read_int64():
          return u64(fp.read(8), target=MARSHAL_TARGET)
  
      def read_float_binary():
          return unpack('d', fp.read(8), target=MARSHAL_TARGET)[0]
  
      def read_bytes():
          return fp.read(read_long())
  
      def read_bytes_short():
          return fp.read(read_byte())
  
      def read_float_text():
          return float(read_bytes_short())
  
      def read_object():
          c = six.byte2int(fp.read(1))
          flags = c & FLAG_REF
          c = ObjectType(c & ~FLAG_REF)
  
          if c is ObjectType.null:
              return NULL
          elif c is ObjectType.none:
              return None
          elif c is ObjectType.stopiter:
              return StopIteration
          elif c is ObjectType.ellipsis:
              return Ellipsis
          elif c is ObjectType.false:
              return False
          elif c is ObjectType.true:
              return True
          elif c is ObjectType.int:
              return ref(read_long(), flags)
          elif c is ObjectType.int64:
              return ref(read_int64(), flags)
          elif c is ObjectType.long:
              n = read_long()
              r = sum(
                  read_short() << (i * PyLong_MARSHAL_SHIFT)
                  for i in range(abs(n))
              )
              return ref(-r if n < 0 else r, flags)
          elif c is ObjectType.float:
              return ref(read_float_text(), flags)
          elif c is ObjectType.binary_float:
              return ref(read_float_binary(), flags)
          elif c is ObjectType.complex:
              real = read_float_text()
              imag = read_float_text()
              return ref(complex(real, imag), flags)
          elif c is ObjectType.binary_complex:
              real = read_float_binary()
              imag = read_float_binary()
              return ref(complex(real, imag), flags)
          elif c is ObjectType.string:
              return ref(read_bytes(), flags)
          elif c is ObjectType.unicode:
              return ref(read_bytes().decode('utf-8'), flags)
          elif c is ObjectType.interned:
              if version < 30:
                  return ref(read_bytes(), FLAG_REF)
              else:
                  return ref(read_bytes().decode('utf-8'), flags)
          elif c is ObjectType.ascii:
              return ref(read_bytes().decode('ascii'), flags)
          elif c is ObjectType.ascii_interned:
              return ref(read_bytes().decode('ascii'), flags)
          elif c is ObjectType.short_ascii:
              return ref(read_bytes_short().decode('ascii'), flags)
          elif c is ObjectType.short_ascii_interned:
              return ref(read_bytes_short().decode('ascii'), flags)
          elif c in (ObjectType.tuple, ObjectType.small_tuple, ObjectType.frozenset):
              ref_index = len(refs)
              ref(NULL, flags)
              r_type = frozenset if c is ObjectType.frozenset else tuple
              n = read_byte() if c is ObjectType.small_tuple else read_long()
              r = r_type(read_object() for _ in range(n))
              if flags & FLAG_REF:
                  refs[ref_index] = r
              return r
          elif c is ObjectType.list:
              r = ref([], flags)
              for _ in range(read_long()):
                  r.append(read_object())
              return r
          elif c is ObjectType.set:
              r = ref(set(), flags)
              for _ in range(read_long()):
                  r.add(read_object())
              return r
          elif c is ObjectType.dict:
              r = ref({}, flags)
              while True:
                  k = read_object()
                  if k is NULL:
                      break
                  r[k] = read_object()
              return r
          elif c in (ObjectType.stringref, ObjectType.ref):
              return refs[read_long()]
          elif c is ObjectType.code:
              ref_index = len(refs)
              ref(NULL, flags)
  
              co_argcount = read_long()
              if version < 30:
                  co_kwonlyargcount = 0
              else:
                  co_kwonlyargcount = read_long()
              co_nlocals = read_long()
              co_stacksize = read_long()
              co_flags = read_long()
              co_code = read_object()
              co_consts = read_object()
              co_names = read_object()
              co_varnames = read_object()
              co_freevars = read_object()
              co_cellvars = read_object()
              co_filename = read_object()
              co_name = read_object()
              co_firstlineno = read_long()
              co_lnotab = read_object()
  
              r = CodeObject(
                  co_argcount,
                  co_kwonlyargcount,
                  co_nlocals,
                  co_stacksize,
                  co_flags,
                  co_code,
                  co_consts,
                  co_names,
                  co_varnames,
                  co_filename,
                  co_name,
                  co_firstlineno,
                  co_lnotab,
                  co_freevars,
                  co_cellvars,
                  origin,
              )
              if flags & FLAG_REF:
                  refs[ref_index] = r
              return r
          else:
              raise ValueError('Unexpected object type %s.' % c)
  
      return read_object()