'read(address, count) -> bytes
Read data from the specified virtual address
Arguments:
address(int): Virtual address to read
count(int): Number of bytes to read
Returns:
A :class:`str` object, or :const:`None`.
Examples:
The simplest example is just to read the ELF header.
>>> bash = ELF(which(\'bash\'))
>>> bash.read(bash.address, 4)
\'\x7fELF\'
ELF segments do not have to contain all of the data on-disk
that gets loaded into memory.
First, let\'s create an ELF file has some code in two sections.
>>> assembly = \'\'\'
... .section .A,"awx"
... .global A
... A: nop
... .section .B,"awx"
... .global B
... B: int3
>>> e = ELF.from_assembly(assembly, vma=False)
By default, these come right after eachother in memory.
>>> e.read(e.symbols.A, 2)
\'\x90\xcc\'
>>> e.symbols.B - e.symbols.A
1
Let\'s move the sections so that B is a little bit further away.
>>> objcopy = pwnlib.asm._objcopy()
>>> objcopy += [
...     \'--change-section-vma\', \'.B+5\',
...     \'--change-section-lma\', \'.B+5\',
...     e.path
>>> subprocess.check_call(objcopy)
0
Now let\'s re-load the ELF, and check again
>>> e = ELF(e.path)
>>> e.symbols.B - e.symbols.A
6
>>> e.read(e.symbols.A, 2)
\'\x90\x00\'
>>> e.read(e.symbols.A, 7)
\'\x90\x00\x00\x00\x00\x00\xcc\'
>>> e.read(e.symbols.A, 10)
\'\x90\x00\x00\x00\x00\x00\xcc\x00\x00\x00\'
Everything is relative to the user-selected base address, so moving
things around keeps everything working.
>>> e.address += 0x1000
>>> e.read(e.symbols.A, 10)
\'\x90\x00\x00\x00\x00\x00\xcc\x00\x00\x00\''

def read(self, address, count):

    retval = []
    if (count == 0):
        return ''
    start = address
    stop = (address + count)
    overlap = self.memory.search(start, stop)
    memory = intervaltree.IntervalTree(overlap)
    memory.chop(None, start)
    memory.chop(stop, None)
    if (memory.begin() != start):
        log.error(('Address    %#x    is    not    contained    in    %s' % (start, self)))
    if (memory.end() != stop):
        log.error(('Address    %#x    is    not    contained    in    %s' % (stop, self)))
    for (begin, end, data) in sorted(memory):
        length = (end - begin)
        if (data in (None, '\x00')):
            retval.append(('\x00' * length))
            continue
        begin -= self.address
        begin += self.load_addr
        offset = (begin - data.header.p_vaddr)
        offset += data.header.p_offset
        retval.append(self.mmap[offset:(offset + length)])
    return ''.join(retval)
