Skip to content

Commit

Permalink
Merge pull request #1445 from elicn/dev-posix
Browse files Browse the repository at this point in the history
POSIX bugfixes
  • Loading branch information
xwings authored Feb 11, 2024
2 parents 7e7655e + b212bf8 commit c76fcb6
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 32 deletions.
5 changes: 3 additions & 2 deletions qiling/os/posix/structs.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,12 @@ class cmsghdr(Struct):

def make_iovec(archbits: int, endian: QL_ENDIAN):
Struct = struct.get_aligned_struct(archbits, endian)
native_type = struct.get_native_type(archbits)

class iovec(Struct):
_fields_ = (
('iov_base', ctypes.c_uint64),
('iov_len', ctypes.c_uint64)
('iov_base', native_type),
('iov_len', native_type)
)

return iovec
Expand Down
77 changes: 48 additions & 29 deletions qiling/os/posix/syscall/uio.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,61 @@
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#

from qiling import Qiling
from __future__ import annotations
from typing import TYPE_CHECKING, Iterator, Tuple

def ql_syscall_writev(ql: Qiling, fd: int, vec: int, vlen: int):
regreturn = 0
size_t_len = ql.arch.pointersize
iov = ql.mem.read(vec, vlen * size_t_len * 2)
ql.log.debug('writev() CONTENT:')
from qiling.os.posix.structs import make_iovec

for i in range(vlen):
addr = ql.unpack(iov[i * size_t_len * 2 : i * size_t_len * 2 + size_t_len])
l = ql.unpack(iov[i * size_t_len * 2 + size_t_len : i * size_t_len * 2 + size_t_len * 2])
regreturn += l

buf = ql.mem.read(addr, l)
ql.log.debug(f'{bytes(buf)}')
if TYPE_CHECKING:
from qiling import Qiling

if hasattr(ql.os.fd[fd], 'write'):
ql.os.fd[fd].write(buf)

return regreturn
def __iter_iovec_array(ql: Qiling, base: int, count: int) -> Iterator[Tuple[int, int]]:
"""Iterate over an iovec array, yielding one iovec's fields at a time.
"""

iovec = make_iovec(ql.arch.bits, ql.arch.endian)

def ql_syscall_readv(ql: Qiling, fd: int, vec: int, vlen: int):
regreturn = 0
size_t_len = ql.arch.pointersize
iov = ql.mem.read(vec, vlen * size_t_len * 2)
ql.log.debug('readv() CONTENT:')
for i in range(count):
obj = iovec.load_from(ql.mem, base + i * iovec.sizeof())

for i in range(vlen):
addr = ql.unpack(iov[i * size_t_len * 2 : i * size_t_len * 2 + size_t_len])
l = ql.unpack(iov[i * size_t_len * 2 + size_t_len : i * size_t_len * 2 + size_t_len * 2])
regreturn += l
yield (obj.iov_base, obj.iov_len)

if hasattr(ql.os.fd[fd], 'read'):
data = ql.os.fd[fd].read(l)
ql.log.debug(f'{data!r}')
ql.mem.write(addr, data)

return regreturn
def ql_syscall_writev(ql: Qiling, fd: int, iov: int, iovcnt: int):
ret = 0

if hasattr(ql.os.fd[fd], 'write'):
ql.log.debug('writev CONTENT:')

for iov_base, iov_len in __iter_iovec_array(ql, iov, iovcnt):
data = ql.mem.read(iov_base, iov_len)
ql.log.debug(f' {iov_base = :#x}, {iov_len = :#x} : {bytes(data)}')

ql.os.fd[fd].write(data)
ret += len(data)

else:
ql.log.debug('writev: destination fd is not writeable, no bytes were written')

return ret


def ql_syscall_readv(ql: Qiling, fd: int, iov: int, iovcnt: int):
ret = 0

if hasattr(ql.os.fd[fd], 'read'):
ql.log.debug('readv CONTENT:')

for iov_base, iov_len in __iter_iovec_array(ql, iov, iovcnt):
data = ql.os.fd[fd].read(iov_len)
ql.log.debug(f' {iov_base = :#x}, {iov_len = :#x} : {bytes(data)}')

ql.mem.write(iov_base, data)
ret += len(data)

else:
ql.log.debug('readv: source fd is not readable, no bytes were read')

return ret
2 changes: 1 addition & 1 deletion qiling/profiles/linux.ql
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ entry_point = 0x1000000


[OS64]
stack_address = 0x7ffffffde000
stack_address = 0x7ffffffd0000
stack_size = 0x30000
load_address = 0x555555554000
interp_address = 0x7ffff7dd5000
Expand Down

0 comments on commit c76fcb6

Please sign in to comment.