Skip to content

Commit 5d3e74e

Browse files
committed
Merge branch 'dev' of github.com:xwings/qiling into dev
2 parents 697abfb + c44dbae commit 5d3e74e

File tree

8 files changed

+179
-27
lines changed

8 files changed

+179
-27
lines changed

qiling/debugger/gdb/utils.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def initialize(self, ql, hook_address, exit_point=None, mappings=None):
3737
def entry_point_hook(self, ql, *args, **kwargs):
3838
self.ql.hook_del(self._tmp_hook)
3939
self.ql.hook_code(self.dbg_hook)
40-
self.ql.os.stop()
40+
self.ql.stop()
4141
self.ql.log.info("gdb> Stop at entry point: %#x" % self.ql.reg.arch_pc)
4242

4343
def dbg_hook(self, ql, address, size):
@@ -64,7 +64,7 @@ def dbg_hook(self, ql, address, size):
6464
self.skip_bp_count -= 1
6565
else:
6666
self.breakpoint_count += 1
67-
self.ql.os.stop()
67+
self.ql.stop()
6868
self.last_bp = address
6969
ql.log.info("gdb> Breakpoint found, stop at address: 0x%x" % address)
7070

@@ -79,7 +79,7 @@ def dbg_hook(self, ql, address, size):
7979

8080
except KeyboardInterrupt as ex:
8181
ql.log.info("gdb> Paused at 0x%x, instruction size = %u" % (address, size))
82-
self.ql.os.stop()
82+
self.ql.stop()
8383
except:
8484
raise
8585

qiling/os/linux/function_hook.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,9 @@ def _parse(self):
814814

815815
elif d.d_tag == DT_PLTREL:
816816
if d.d_un != self.plt_rel_type:
817-
raise
817+
# FIXME: I don't why it is a error
818+
# but it is triggered in riscv32
819+
pass
818820
elif d.d_tag == DT_PLTRELSZ:
819821
self.plt_rel_size = d.d_un
820822
elif d.d_tag == DT_JMPREL:

qiling/os/linux/map_syscall.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2134,7 +2134,7 @@ def map_syscall(ql, syscall_num):
21342134
219: "keyctl",
21352135
220: "clone",
21362136
221: "execve",
2137-
222: "mmap",
2137+
222: "mmap2",
21382138
223: "fadvise64_64",
21392139
224: "swapon",
21402140
225: "swapoff",

qiling/os/posix/const.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@
559559

560560
FD_CLOEXEC = 1
561561

562-
AT_FDCWD = 0xffffff9c # -100
562+
AT_FDCWD = -100
563563

564564
# error code
565565
EPERM = 1

qiling/os/posix/syscall/fcntl.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,15 @@ def ql_syscall_openat(ql: Qiling, fd: int, path: int, flags: int, mode: int):
9898
mode = 0
9999

100100
flags = ql_open_flag_mapping(ql, flags)
101-
try:
101+
fd = ql.unpacks(ql.pack(fd))
102+
103+
if 0 <= fd < NR_OPEN:
102104
dir_fd = ql.os.fd[fd].fileno()
103-
except:
105+
else:
104106
dir_fd = None
105107

106108
ql.os.fd[idx] = ql.os.fs_mapper.open_ql_file(file_path, flags, mode, dir_fd)
109+
107110
regreturn = idx
108111
except QlSyscallError as e:
109112
regreturn = -e.errno

qiling/os/posix/syscall/mman.py

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,7 @@ def syscall_mmap_impl(ql: Qiling, addr: int, mlen: int, prot: int, flags: int, f
8282

8383
mmap_base = addr
8484
need_mmap = True
85-
eff_mmap_size = ((mlen + 0x1000 - 1) // 0x1000) * 0x1000
86-
87-
# align eff_mmap_size to page boundary
88-
aligned_address = (addr >> 12) << 12
89-
eff_mmap_size -= mmap_base - aligned_address
85+
eff_mmap_size = mlen
9086

9187
# initial ql.loader.mmap_address
9288
if addr != 0 and ql.mem.is_mapped(addr, mlen):
@@ -98,21 +94,24 @@ def syscall_mmap_impl(ql: Qiling, addr: int, mlen: int, prot: int, flags: int, f
9894
ql.log.debug(e)
9995
raise QlMemoryMappedError("Error: change protection at: 0x%x - 0x%x" % (addr, addr + mlen - 1))
10096
need_mmap = False
97+
else:
98+
addr = 0
10199

102100
# initialized mapping
103101
if need_mmap:
104-
if (flags & MAP_FIXED) > 0:
105-
mmap_base = addr
106-
else:
102+
eff_mmap_size = ((mlen + 0x1000 - 1) // 0x1000) * 0x1000
103+
if addr == 0:
107104
mmap_base = ql.loader.mmap_address
108-
ql.loader.mmap_address = mmap_base + eff_mmap_size
109-
ql.log.debug("%s - mapping needed for 0x%x" % (api_name, addr))
105+
ql.loader.mmap_address = mmap_base + eff_mmap_size
106+
# align eff_mmap_size to page boundary
107+
aligned_address = (mmap_base >> 12) << 12
108+
eff_mmap_size -= mmap_base - aligned_address
109+
ql.log.debug("%s - mapping needed for 0x%x" % (api_name, mmap_base))
110110
try:
111111
ql.mem.map(mmap_base, eff_mmap_size, info=("[syscall_%s]" % api_name))
112112
except Exception as e:
113113
raise QlMemoryMappedError("Error: mapping needed but failed")
114-
115-
ql.log.debug("%s - addr range 0x%x - 0x%x: " % (api_name, mmap_base, mmap_base + eff_mmap_size - 1))
114+
ql.log.debug("%s - addr range 0x%x - 0x%x: " % (api_name, mmap_base, mmap_base + eff_mmap_size - 1))
116115

117116
# FIXME: MIPS32 Big Endian
118117
try:
@@ -192,4 +191,4 @@ def ql_syscall_shmat(ql: Qiling, shmid: int, shmaddr: int, shmflg: int):
192191
else:
193192
addr = ql.mem.map(shmaddr, size, info="[shm]")
194193

195-
return addr
194+
return addr

qiling/os/posix/syscall/stat.py

Lines changed: 144 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import os
77
import ctypes
8+
import struct
89
from typing import Callable
910

1011
from qiling import Qiling
@@ -1044,15 +1045,17 @@ def transform_path(ql: Qiling, dirfd: int, path: int):
10441045
then the target file is the one referred to by the file descriptor dirfd.
10451046
"""
10461047

1048+
dirfd = ql.unpacks(ql.pack(dirfd))
10471049
path = ql.os.utils.read_cstring(path)
1048-
1050+
10491051
if path.startswith('/'):
1050-
return None, ql.os.path.transform_to_relative_path(path)
1052+
return None, os.path.join(ql.rootfs, path)
10511053

10521054
if dirfd == AT_FDCWD:
1053-
return -100, ql.os.path.transform_to_relative_path(os.path.join(ql.os.path.cwd, path))
1055+
return None, ql.os.path.transform_to_real_path(path)
10541056

1055-
return dirfd, path
1057+
if 0 < dirfd < NR_OPEN:
1058+
return ql.os.fd[dirfd].fileno(), path
10561059

10571060

10581061
def ql_syscall_chmod(ql: Qiling, filename: int, mode: int):
@@ -1143,10 +1146,145 @@ def ql_syscall_stat(ql: Qiling, path: int, buf_ptr: int):
11431146
def ql_syscall_stat64(ql: Qiling, path: int, buf_ptr: int):
11441147
return statFamily(ql, path, buf_ptr, "stat64", Stat, pack_stat64_struct)
11451148

1149+
class StatxTimestamp32(ctypes.Structure):
1150+
_fields_ = [
1151+
('tv_sec', ctypes.c_int32),
1152+
('tv_nsec', ctypes.c_uint32),
1153+
('__statx_timestamp_pad1', ctypes.c_int32)
1154+
]
1155+
1156+
class Statx32(ctypes.Structure):
1157+
"""
1158+
Reference:
1159+
- https://man7.org/linux/man-pages/man2/statx.2.html
1160+
- https://code.woboq.org/userspace/glibc/sysdeps/unix/sysv/linux/statx.c.html
1161+
1162+
"""
1163+
_fields_ = [
1164+
('stx_mask', ctypes.c_uint32),
1165+
('stx_blksize', ctypes.c_uint32),
1166+
('stx_attributes', ctypes.c_uint32),
1167+
('stx_nlink', ctypes.c_uint32),
1168+
('stx_uid', ctypes.c_uint32),
1169+
('stx_gid', ctypes.c_uint32),
1170+
('stx_mode', ctypes.c_uint16),
1171+
('__statx_pad1', ctypes.c_uint16),
1172+
('stx_ino', ctypes.c_uint32),
1173+
('stx_size', ctypes.c_uint32),
1174+
('stx_blocks', ctypes.c_uint32),
1175+
('stx_attributes_mask', ctypes.c_uint32),
1176+
('stx_atime', StatxTimestamp32),
1177+
('stx_btime', StatxTimestamp32),
1178+
('stx_ctime', StatxTimestamp32),
1179+
('stx_mtime', StatxTimestamp32),
1180+
('stx_rdev_major', ctypes.c_uint32),
1181+
('stx_rdev_minor', ctypes.c_uint32),
1182+
('stx_dev_major', ctypes.c_uint32),
1183+
('stx_dev_minor', ctypes.c_uint32),
1184+
('__statx_pad2', ctypes.c_uint32 * 14),
1185+
]
1186+
1187+
_pack_ = 8
1188+
1189+
class StatxTimestamp64(ctypes.Structure):
1190+
_fields_ = [
1191+
('tv_sec', ctypes.c_int64),
1192+
('tv_nsec', ctypes.c_uint32),
1193+
('__statx_timestamp_pad1', ctypes.c_int32)
1194+
]
1195+
1196+
class Statx64(ctypes.Structure):
1197+
"""
1198+
Reference:
1199+
- https://man7.org/linux/man-pages/man2/statx.2.html
1200+
- https://code.woboq.org/userspace/glibc/sysdeps/unix/sysv/linux/statx.c.html
1201+
1202+
"""
1203+
_fields_ = [
1204+
('stx_mask', ctypes.c_uint32),
1205+
('stx_blksize', ctypes.c_uint32),
1206+
('stx_attributes', ctypes.c_uint64),
1207+
('stx_nlink', ctypes.c_uint32),
1208+
('stx_uid', ctypes.c_uint32),
1209+
('stx_gid', ctypes.c_uint32),
1210+
('stx_mode', ctypes.c_uint16),
1211+
('__statx_pad1', ctypes.c_uint16),
1212+
('stx_ino', ctypes.c_uint64),
1213+
('stx_size', ctypes.c_uint64),
1214+
('stx_blocks', ctypes.c_uint64),
1215+
('stx_attributes_mask', ctypes.c_uint64),
1216+
('stx_atime', StatxTimestamp64),
1217+
('stx_btime', StatxTimestamp64),
1218+
('stx_ctime', StatxTimestamp64),
1219+
('stx_mtime', StatxTimestamp64),
1220+
('stx_rdev_major', ctypes.c_uint32),
1221+
('stx_rdev_minor', ctypes.c_uint32),
1222+
('stx_dev_major', ctypes.c_uint32),
1223+
('stx_dev_minor', ctypes.c_uint32),
1224+
('__statx_pad2', ctypes.c_uint64 * 14),
1225+
]
1226+
1227+
_pack_ = 4
1228+
11461229
# int statx(int dirfd, const char *restrict pathname, int flags,
11471230
# unsigned int mask, struct statx *restrict statxbuf);
1148-
def ql_syscall_statx(ql: Qiling, dirfd: int, path: int, flags: int, mask: int, statxbuf: int):
1149-
return 0
1231+
def ql_syscall_statx(ql: Qiling, dirfd: int, path: int, flags: int, mask: int, buf_ptr: int):
1232+
def statx_convert_timestamp(tv_sec, tv_nsec):
1233+
tv_sec = struct.unpack('i', struct.pack('f', tv_sec))[0]
1234+
tv_nsec = struct.unpack('i', struct.pack('f', tv_nsec))[0]
1235+
1236+
if ql.archbit == 32:
1237+
return StatxTimestamp32(tv_sec=tv_sec, tv_nsec=tv_nsec)
1238+
else:
1239+
return StatxTimestamp64(tv_sec=tv_sec, tv_nsec=tv_nsec)
1240+
1241+
1242+
def major(dev):
1243+
return ((dev >> 8) & 0xfff) | ((dev >> 32) & ~0xfff)
1244+
1245+
def minor(dev):
1246+
return (dev & 0xff) | ((dev >> 12) & ~0xff)
1247+
1248+
fd, real_path = transform_path(ql, dirfd, path)
1249+
1250+
try:
1251+
if len(real_path) == 0:
1252+
st = ql.os.fd[dirfd].fstat()
1253+
else:
1254+
st = Stat(real_path, fd)
1255+
1256+
if ql.archbit == 32:
1257+
Statx = Statx32
1258+
else:
1259+
Statx = Statx64
1260+
1261+
stx = Statx(
1262+
stx_mask = 0x07ff, # STATX_BASIC_STATS
1263+
stx_blksize = st.st_blksize,
1264+
stx_nlink = st.st_nlink,
1265+
stx_uid = st.st_uid,
1266+
stx_gid = st.st_gid,
1267+
stx_mode = st.st_mode,
1268+
stx_ino = st.st_ino,
1269+
stx_size = st.st_size,
1270+
stx_blocks = st.st_blocks,
1271+
stx_atime = statx_convert_timestamp(st.st_atime, st.st_atime_ns),
1272+
stx_ctime = statx_convert_timestamp(st.st_ctime, st.st_ctime_ns),
1273+
stx_mtime = statx_convert_timestamp(st.st_mtime, st.st_mtime_ns),
1274+
stx_rdev_major = major(st.st_rdev),
1275+
stx_rdev_minor = minor(st.st_rdev),
1276+
stx_dev_major = major(st.st_dev),
1277+
stx_dev_minor = minor(st.st_dev),
1278+
)
1279+
1280+
ql.mem.write(buf_ptr, bytes(stx))
1281+
1282+
regreturn = 0
1283+
1284+
except Exception as e:
1285+
regreturn = -1
1286+
1287+
return regreturn
11501288

11511289
def ql_syscall_lstat(ql: Qiling, path: int, buf_ptr: int):
11521290
return statFamily(ql, path, buf_ptr, "lstat", Lstat, pack_stat64_struct)

tests/test_riscv.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,15 @@ def test_riscv64_hello_dyn_linux(self):
4747

4848
del ql
4949

50+
def test_riscv32_hello_dyn_linux(self):
51+
stdout = SimpleOutStream(1)
52+
ql = Qiling(['../examples/rootfs/riscv32_linux/bin/hello-linux'], '../examples/rootfs/riscv32_linux/',
53+
verbose=QL_VERBOSE.DEFAULT, stdout=stdout)
54+
55+
ql.run()
56+
self.assertTrue(stdout.read() == b'Hello, World!\n')
57+
58+
del ql
59+
5060
if __name__ == "__main__":
5161
unittest.main()

0 commit comments

Comments
 (0)