def _read_binary_data(fp, size, name, clip=False):
  """Read zero-padded binary data from a file.

  Attempts to read `size+1` bytes from filehandle `fp`. If 0 or more than `size`
  bytes are read, raises an IOError. Data of any other size is returned to the
  caller, followed by enough zero padding to yield `size` bytes exactly (if
  `clip` is False) or to yield the nearest larger multiple of 0x200 (if `clip`
  is True).

  Args:
    fp: file object to read from.
    size: number of bytes to read from `fp`.
    name: name for data being loaded (used for exception messages).
    clip: whether to pad binary data with 0s to the nearest larger multiple of
        0x200 (if True) or to `size` (if False).

  Returns: a 2-tuple whose members are the data loaded from `fp` (zero-padded)
      and the original size of the data in bytes prior to zero-padding.

  Raises:
    IOError: if the file is empty or contains more than size bytes.
  """
  # Read data.
  data = fp.read(size + 1)
  if len(data) == 0:
    raise IOError('failed to read any {} data'.format(name))
  if len(data) > size:
    raise IOError('{} data file was larger than {} bytes'.format(name, size))

  # Zero-pad as directed by `clip`.
  if clip:
    return data + ('\x00' * (0x200 + ~((len(data)-1) & 0x1ff))), len(data)
  else:
    return data + ('\x00' * (size - len(data))), len(data)