'Reads some data from the current (or provided) position of the file.
:param dst_addr:    If specified, the data is written to that address.
:param length:      The length of the read.
:return:            The length of the read.'

def read(self, dst_addr, length):

    orig_length = length
    real_length = length
    max_length = length
    if (self.size is not None):
        max_length = (self.size - self.pos)
    if ((sim_options.CONCRETIZE_SYMBOLIC_FILE_READ_SIZES in self.state.options) and (self.state.se.symbolic(orig_length) or self.state.se.symbolic(max_length))):
        orig_max = self.state.se.max_int(orig_length)
        self.state.add_constraints((orig_length == orig_max))
        real_length = min(orig_max, self.state.se.max_int(max_length))
    if (self.size is not None):
        length_constraint = ((self.pos + real_length) <= self.size)
        if ((self.state.se.symbolic(real_length) or self.state.se.symbolic(max_length)) and self.state.se.satisfiable(extra_constraints=(length_constraint,))):
            self.state.add_constraints(length_constraint)
        elif ((not self.state.se.symbolic(real_length)) or (not self.state.se.symbolic(max_length))):
            real_length = min(self.state.se.any_int(max_length), self.state.se.any_int(real_length))
    self.content.copy_contents(dst_addr, self.pos, real_length, dst_memory=self.state.memory)
    self.read_pos += _deps_unpack(real_length)[0]
    return real_length
