compile/remote-compile/lbc/tool/parsePahole.py (166 lines of code) (raw):
import re
import sys
import os
import shlex
from subprocess import PIPE, Popen
class CexecCmd(object):
def __init__(self):
super(CexecCmd, self).__init__()
pass
@staticmethod
def cmd(cmds):
p = Popen(shlex.split(cmds), stdout=PIPE)
return p.stdout.read().decode('utf-8').strip()
@staticmethod
def system(cmds):
cmds = cmds.replace('\0', '').strip()
return os.system(cmds)
class CparsePahole(CexecCmd):
def __init__(self, objs):
super(CparsePahole, self).__init__()
if not os.path.exists(objs):
raise Exception("obj file %s not exist." % objs)
self._reIndex = re.compile(r"(?<=\[)[^\[\]]+(?=])")
# self.__reStruct = re.compile(r"(?<={)[^{}]+(?=})")
self._struct_mapping = {'char': 'c',
'signed char': 'b',
'unsigned char': 'B',
'__s8': 'b',
'__u8': 'b',
's8': 'b',
'u8': 'b',
'char *': 's',
'short': 'h',
'unsigned short': 'H',
'__s16': 'h',
'__u16': 'H',
's16': 'h',
'u16': 'H',
'int': 'i',
'enum': 'i',
'unsigned int': 'I',
'__s32': 'i',
'__u32': 'I',
's32': 'i',
'u32': 'I',
'long long': 'q',
'long': 'l',
'long int': 'l',
'unsigned long': 'L',
'unsigned long long': 'Q',
'long long unsigned int': 'Q',
'__s64': 'q',
'__u64': 'Q',
's64': 'q',
'u64': 'Q',
'char []': 's',
'void *': 'P'}
self._typeSize = {'c': 1, 'b': 1, 'B': 1,
'h': 2, 'H': 2,
'i': 4, 'I': 4,
'l': 8, 'L': 8, 'Q': 8, 'q': 8,
's': 8, 'P': 8,
}
self._objs = objs
self._retStr = None
def _getFormat(self, dMems):
if dMems['type'] in self._struct_mapping:
if dMems['array']:
dMems['format'] = self._struct_mapping[dMems['type']] * dMems['array']
else:
dMems['format'] = self._struct_mapping[dMems['type']]
else:
raise Exception("unknown type: %s" % dMems['type'])
def _getTopSize(self, dMems):
dMems['size'] = self._typeSize[dMems['format'][0]]
def _parseHead(self, tStr, dRet):
if tStr[-1] == ']':
t, _ = tStr.split('[', 1)
dRet['type'] = t.strip()
size = self._reIndex.findall(tStr)[0]
dRet['array'] = int(size)
else:
dRet['type'] = tStr
dRet['array'] = 0
def _getTop(self, realType):
dMems = {'member': 'value'}
self._parseHead(realType, dMems)
self._getFormat(dMems)
self._getTopSize(dMems)
return dMems
def _getStructStr(self, sStruct):
if self._retStr is None:
self._retStr = self.cmd("pahole %s" % self._objs)
find = "%s {" % sStruct
start = self._retStr.index(find) + len(find)
end = start + 1
count = 1
while count:
c = self._retStr[end]
if c == "{":
count += 1
elif c == '\0':
raise Exception("bad pahole result.")
elif c == '}':
count -= 1
end += 1
return self._retStr[start:end - 1]
# /* size: 44, cachelines: 1, members: 5 */
def _getStrcutSize(self, ano):
# print(ano)
title, _ = ano.strip()[2:].split(',', 1)
_, value = title.split(':')
return int(value.strip())
def _parseMember(self, desc):
desc = re.sub(r" +", r" ", desc)
# char c_comm[16]; /* 8 16 */
var, annotate = desc.split(';', 1)
tStr, member = var.strip().split(" ", 1)
if ":" in member:
raise ValueError("pylcc not support bit segment")
if tStr.startswith('struct'):
return self._getStruct(member)
else:
dMems = {'type': tStr}
if member[-1] == ']':
m, _ = member.split('[', 1)
dMems['member'] = m.strip()
size = self._reIndex.findall(member)[0]
dMems['array'] = int(size)
else:
dMems['member'] = member
dMems['array'] = 0
self._getFormat(dMems)
beg = annotate.index("/*") + 2
end = annotate.index("*/")
offs = annotate[beg:end].strip()
offset, size = offs.split(' ')
dMems['offset'] = int(offset)
dMems['size'] = int(size)
if dMems['array']:
dMems['size'] = int(dMems['size'] / dMems['array'])
return dMems
def _getStruct(self, sStruct):
#
# u32 c_pid; /* 0 4 */
# u32 p_pid; /* 4 4 */
# char c_comm[16]; /* 8 16 */
# char p_comm[16]; /* 24 16 */
# u32 stack_id; /* 40 4 */
#
# /* size: 44, cachelines: 1, members: 5 */
# /* last cacheline: 44 bytes */
# }
dStruct = {}
self._parseHead(sStruct, dStruct)
sDesc = self._getStructStr(dStruct['type'])
descs = sDesc.split("\n")
lMem = []
sSize = "None"
for desc in descs:
s = desc.strip()
if s == "":
continue
if s.startswith("/*"):
if s.startswith('/* size'):
sSize = s
continue
lMem.append(self._parseMember(desc))
dStruct['cells'] = lMem
dStruct['offset'] = 0
# /* size: 44, cachelines: 1, members: 5 */
dStruct['size'] = self._getStrcutSize(sSize.strip())
return dStruct
def parseType(self, t):
if t.startswith('struct '):
return self._getStruct(t)
else:
return self._getTop(t)
if __name__ == "__main__":
p = CparsePahole("../.output/lbc.bpf.o")
print(p.parseType('struct data_t'))