[英]Python Linux read process memory - int too large to convert to C long
我有这个片段在Linux中读取进程内存并搜索字符串,在某些发行版上运行正常,但在其他方面只是出现此错误:
maps_file = open("/proc/%s/maps"%pid, 'r')
mem_file = open("/proc/%s/mem"%pid, 'r')
for line in maps_file.readlines(): # for each mapped region
m = re.match(r'([0-9A-Fa-f]+)', line)
if m.group(3) == 'r': # if this is a readable region
start = int(m.group(1), 16)
end = int(m.group(2), 16)
mem_file.seek(start) # seek to region start
chunk = mem_file.read(end - start) # read region contents
#print chunk, # dump contents to standard output
mem_dump = open(working_dir+"/%s.bin"%pid, "ab")
mem_dump.write(chunk,)
mem_dump.close()
maps_file.close()
mem_file.close()
错误:
scan process: 491
Traceback (most recent call last):
File "./dump.py", line 106, in <module>
MainDump(pid)
File "./dump.py", line 79, in MainDump
mem_file.seek(start) # seek to region start
OverflowError: Python int too large to convert to C long
问题是:
start = int(m.group(1), 16)
和
mem_file.seek(start)
我应该声明为float
吗? 任何想法?
尝试long()
具有相同的结果和错误。
编辑:我忘了说的是我在“x64”系统上遇到的错误。
问题是你有地址0xffffffffff600000L
。 (带符号)C long只能保存-0x8000000000000000
到0x7fffffffffffffff
值。 因此,这个地址确实“太大而无法转换为C long”。
如果您查看源代码 ,您可以看到问题很可能是由于某种原因,当在非工作发行版上配置Python时,它无法检测到fseeko
和off_t
存在。 但除非您想重建Python,否则无法帮助您。
那么,你怎么解决这个问题呢? 有几件事要尝试。
第一种可能性是从最终而不是开始寻求。
mem_len = os.fstat(mem_file.fileno()).st_size
if start >= 1<<63L:
mem_file.seek(mem_len - start, os.SEEK_END)
else:
mem_file.seek(start)
你也可以试试这个可怕的黑客:
if start >= 1<<63L:
start -= 1<<64L
这会将你的0xffffffffff600000L
转换成-0xa00000
,这很适合long
...然后希望,那个long
实际上被转换为C层内部的一些无符号64位类型,这意味着它正如你所希望的那样寻求0xffffffffff600000L
。
您也可以通过使用mmap
映射所需的页面而不是seek
和read
来解决这个问题。
如果最坏的情况发生,您可以使用ctypes
(或cffi
或任何您喜欢的)直接在文件句柄上调用fseeko
。
最后,确保您确实想要阅读此区域。 我可能错了,但我似乎记得linux保留了映射到用户空间的内核页面的上部区域。 如果我是对的,你正在寻找的琴弦不会在这里,所以你可以跳过它们......
要跳过处理区域,您可以在if中移动处理:
start = int(m.group(1), 16)
end = int(m.group(2), 16)
if start <= sys.maxint:
mem_file.seek(start) # seek to region start
chunk = mem_file.read(end - start) # read region contents
# ...
...或使用continue
语句跳到循环的下一次迭代:
start = int(m.group(1), 16)
end = int(m.group(2), 16)
if start > sys.maxint:
continue
mem_file.seek(start) # seek to region start
chunk = mem_file.read(end - start) # read region contents
# ...
如果您知道区域始终按排序顺序,则可以使用break
而不是continue
(因为其余区域也将超出范围)。
但我认为最好的解决方案是try
它,并处理错误。 此seek
和read
可能会失败的原因还有其他原因 - 例如,如果您正在查看的进程在您到达之前取消映射某个区域,或者退出 - 您宁愿跳过错误并继续操作而不是退出,正确?
所以:
if m.group(3) == 'r': # if this is a readable region
start = int(m.group(1), 16)
end = int(m.group(2), 16)
try:
mem_file.seek(start) # seek to region start
chunk = mem_file.read(end - start) # read region co
except Exception as e:
print('Skipping region {:#018x} because of error {}'.format(start, e))
continue
mem_dump = open(working_dir+"/%s.bin"%pid, "ab")
# ...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.