1 Star 0 Fork 103

keep-running/UniProton

forked from openEuler/UniProton 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
bin_helper.py 6.79 KB
一键复制 编辑 原始数据 按行查看 历史
zhaohonghao 提交于 2024-03-13 13:40 . cxx: add cxx support code for hi3093
#!/usr/bin/env python3
# coding=utf-8
# 通过readelf获取elf的程序头信息并填充到指定的g_phdrs数组中
import os
import struct
import sys,getopt
PI_TYPE = 0 # Type
PI_OFFSET = 1 # Offset
PI_VIRT_ADDR = 2 # VirtAddr
PI_PHYS_ADDR = 3 # PhysAddr
PI_FILE_SIZ = 4 # FileSiz
PI_MEM_SIZ = 5 # MemSiz
PI_FLG = 6 # Flg
PI_ALIGN = 7 # Align
PT_LOAD = 1 # Loadable program segment
PT_NOTE = 4 # Auxiliary information
PT_GNU_EH_FRAME = 0x6474e550 # GCC .eh_frame_hdr segment
PT_GNU_STACK = 0x6474e551 # Indicates stack executability
PT_GNU_PROPERTY = 0x6474e553 # GNU property
PF_X = (1 << 0) # Segment is executable
PF_W = (1 << 1) # Segment is writable
PF_R = (1 << 2) # Segment is readable
class BinHelper:
p_flags_map = {'R':PF_R, 'W':PF_W, 'E':PF_X}
p_flags_str_map = {PF_R:'PF_R', PF_W:'PF_W', PF_X:'PF_X'}
pt_type_map = {
'LOAD':PT_LOAD,
'NOTE':PT_NOTE,
'GNU_EH_FRAME':PT_GNU_EH_FRAME,
'GNU_STACK':PT_GNU_STACK,
'GNU_PROPERTY':PT_GNU_PROPERTY
}
pt_type_str_map = {
PT_LOAD:'PT_LOAD',
PT_NOTE:'PT_NOTE',
PT_GNU_EH_FRAME:'PT_GNU_EH_FRAME',
PT_GNU_STACK:'PT_GNU_STACK',
PT_GNU_PROPERTY:'PT_GNU_PROPERTY'
}
def extract(self, str):
fidx = 0
fields = str.split(" ")
p_flags = 0
output = []
for i in range(len(fields)):
fval = fields[i]
if len(fval) == 0:
continue
if fidx == 0:
if (fval not in self.pt_type_map):
print("ignore segment type {0}".format(fval))
return output
output.append(self.pt_type_map[fval])
elif fidx >= 6:
if fval[0:2] == '0x':
output.append(p_flags)
output.append(int(fval, base = 16))
break
elif len(fval) <= 3:
for fch in fval:
if (fch in self.p_flags_map):
p_flags |= self.p_flags_map[fch]
else:
output.append(int(fval, base = 16))
fidx = fidx + 1
return output
def get_addr(self, symbol):
# format: 192: 0000000f02a01800 336 OBJECT LOCAL DEFAULT 3 g_phdrs
strs = os.popen("{0} -s {1} | grep {2}".format(self.readelf_path, self.path, symbol)).readlines()
if len(strs) == 0:
print("phdrs array not found")
sys.exit(-1)
if len(strs) > 1:
print("warn ")
return strs[0].strip().split(" ")[1]
def parse_phdrs(self):
lines = os.popen("{0} -Wl {1}".format(self.readelf_path, self.path)).readlines()
state = 0
phdrs = []
for l in lines:
if state == 0:
if (l.find('Entry point') >= 0):
entry_point = int(l.split(" ")[2], base = 16)
state = 1
elif state == 1:
if l.find('Type') >= 0:
state = 2
elif state == 2:
if len(l.strip()) == 0:
break
else:
info = self.extract(l)
if len(info) == 0:
continue
phdrs.append(info)
return entry_point, phdrs
def gen_file(self, offset, phdrs, nocopy):
dstpath = self.path
if not nocopy:
basename = os.path.basename(self.path)
dirname = os.path.dirname(self.path)
filename = basename.split(".")[0]
suffix = basename.split(".")[1]
dstpath = "{0}/{1}_cpp.{2}".format(dirname, filename, suffix)
ret = os.system('cp {0} {1}'.format(self.path, dstpath))
if ret != 0:
print("copy failed")
sys.exit(ret)
dstfile = open(dstpath,'rb+')
dstfile.seek(offset, 0)
for phdr in phdrs:
dstfile.write(struct.pack('2I6L',
phdr[PI_TYPE],
phdr[PI_FLG],
phdr[PI_OFFSET],
phdr[PI_VIRT_ADDR],
phdr[PI_PHYS_ADDR],
phdr[PI_FILE_SIZ],
phdr[PI_MEM_SIZ],
phdr[PI_ALIGN]))
print('update {0} finish, offset: {1}'.format(dstpath, offset))
dstfile.close()
def fill_phdrs(self, nocopy):
phdrs = self.parse_phdrs()[1]
phdrs_addr = int(self.get_addr(self.phdrsym), base = 16)
offset, vaddr = self.find_segment(phdrs_addr, phdrs)
if offset == -1:
print("invald addr/phdrs")
sys.exit(-1)
self.gen_file(phdrs_addr + offset - vaddr, phdrs, nocopy)
def find_segment(self, pc, phdrs):
for phdr in phdrs:
if (pc >= phdr[PI_VIRT_ADDR] and pc < phdr[PI_VIRT_ADDR] + phdr[PI_FILE_SIZ]):
return (phdr[PI_OFFSET], phdr[PI_VIRT_ADDR])
return -1, -1
def get_flags_str(self, flags):
list = []
for f in self.p_flags_map.values():
if f & flags:
list.append(self.p_flags_str_map[f])
if len(list) == 0:
return '0'
return '|'.join(list)
def print_phdrs(self):
phdrs = self.parse_phdrs()[1]
pattern = '''\n\t.p_type = {0},\n\t.p_flags = {1},\n\t.p_offset = 0x{2:x},\n\t.p_vaddr = 0x{3:x},
\t.p_paddr = 0x{4:x},\n\t.p_filesz = 0x{5:x},\n\t.p_memsz = 0x{6:x},\n\t.p_align = 0x{7:x}'''
for phdr in phdrs:
print('{',pattern.format(
self.pt_type_str_map[phdr[PI_TYPE]],
self.get_flags_str(phdr[PI_FLG]),
phdr[PI_OFFSET],
phdr[PI_VIRT_ADDR],
phdr[PI_PHYS_ADDR],
phdr[PI_FILE_SIZ],
phdr[PI_MEM_SIZ],
phdr[PI_ALIGN]),'\n},')
def __init__(self, path, readelf_path, phdrsym):
self.path = path
self.readelf_path = readelf_path
self.phdrsym = phdrsym
def do_cmd(argv):
inputfile = ''
debugmode = False
nocopy = False
try:
opts, args = getopt.getopt(argv, "hf:d", ["nocopy"])
except getopt.GetoptError:
print("bin_helper.py -f <inputfile>")
sys.exit(-1)
for opt, arg in opts:
if opt == "-h":
print("bin_helper.py -f <inputfile>")
sys.exit()
elif opt == "-f":
inputfile = arg
elif opt == "-d":
debugmode = True
elif opt == "--nocopy":
nocopy = True
helper = BinHelper(inputfile, 'readelf', 'g_phdrs')
if debugmode:
helper.print_phdrs()
helper.fill_phdrs(nocopy)
if __name__ == "__main__":
do_cmd(sys.argv[1:])
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/peng-langyuan/UniProton.git
[email protected]:peng-langyuan/UniProton.git
peng-langyuan
UniProton
UniProton
master

搜索帮助