Open vieyahn2017 opened 8 months ago
最初来自
https://www.cnblogs.com/iclodq/p/9216763.html
@vieyahn2017 Owner Author vieyahn2017 commented on Feb 25, 2022 完整代码:https://gitee.com/iclodq/codes/e81qfpxw3dnkju594yi6b90 【已失效】】
# python basecode.py -s source.c
# python basecode.py -c ext4_extent -h "10 00 00 00 01 00 02 00 1E 86 00 00"
# python basecode.py -c ext4_inode -r hexdump
# python basecode.py -c ext4_super_block -r vi
basecode.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
基础类型参考BaseCode._type_map,实际由struct模块提供
嵌套自定义类型时,需要在子类中重新定义_type_map,并把BaseCode类的_type_map深拷贝到子类中
"""
import traceback
import inspect
import struct
import json
import re
import pprint
import getopt
import sys
import time
import copy
# main正常,需要这边import。因为存在交叉引用,因此这边打开的时候,basecode_structs本身执行会失败
from basecode_structs import *
GLOBAL_SIZE_DICT = {}
GLOBAL_SIZE_DICT["ext4_extent"] = 12
GLOBAL_SIZE_DICT["ext4_extent_idx"] = 12
GLOBAL_SIZE_DICT["ext4_extent_header"] = 12
GLOBAL_SIZE_DICT["ext4_inode"] = 160
def my_try_except_warpper(is_exit=False, err_msg=None):
def _try_except_warpper(actual_do):
def add_robust(*args, **keyargs):
try:
return actual_do(*args, **keyargs)
except:
print("Error: ", traceback.format_exc())
print('Error execute: {}'.format(actual_do.__name__))
if err_msg:
print(err_msg)
if is_exit:
exit(1)
return add_robust
return _try_except_warpper
class EncodeError(Exception):
def __init__(self, error_info='error'):
super().__init__(self)
self.error_info = error_info
def __str__(self):
return self.error_info
def debug_log(*obj):
return # 调试时打开
info = inspect.getframeinfo(inspect.currentframe().f_back, 0)
print(*obj, '| ' + info.filename, info.function, info.lineno)
## not used
def has_class_attr(name, attr):
"""
判断类中是否有类属性
:param name: 类名
:param attr: 类属性名
:return:
"""
token_list = eval('dir(' + name + ')')
if attr in token_list:
return True
return False
class FieldType(object):
# 把之前的tuple格式的field改成现在的FieldType,简直太清爽
__slots__ = ('ctype', 'name', 'raw_field', 'name', 'reverse', 'length')
def __init__(self, ctype, name, **kwargs):
self.ctype = ctype
self.name = name
self.reverse = kwargs.get("reverse", False)
self.length = int(kwargs.get("length", 1))
self.raw_field = kwargs.get("raw_field", "")
def __getitem__(self, key):
if key == 0:
return self.ctype
elif key == 1:
return self.name
elif key == 2:
return {"length": self.length, "reverse": self.reverse}
def is_addtional(self):
if self.length > 1:
return True
# if self.reverse:
# return True
return False
def get_field_length(self):
return self.length
def is_little_endian(self):
return self.reverse
def get_endian_char(self):
# !网络序(同大端序),> (big-endian) , < (little-endian)
return "<" if self.reverse else ">"
def get_raw_field(self):
# get这样调用函数,set直接赋值也可以通过kwargs传递
return self.raw_field
@staticmethod
def get_little_endian_int16(int_num):
hex_str_raw = hex(int_num)
hex_str = hex_str_raw[2:].rjust(4, '0')
hex_le = '0x' + hex_str[2:4] + hex_str[0:2]
return int(hex_le, 16)
@staticmethod
def get_little_endian_int32(int_num):
hex_str_raw = hex(int_num)
hex_str = hex_str_raw[2:].rjust(8, '0')
hex_le = '0x' + hex_str[6:8] + hex_str[4:6] + hex_str[2:4] + hex_str[0:2]
return int(hex_le, 16)
@staticmethod
def get_little_endian_int64(int_num):
hex_str_raw = hex(int_num)
hex_str = hex_str_raw[2:].rjust(16, '0')
hex_le = '0x' + hex_str[15:16] + hex_str[13:14]+ hex_str[11:12]+ hex_str[9:10] + hex_str[6:8] + hex_str[4:6] + hex_str[2:4] + hex_str[0:2]
return int(hex_le, 16)
@staticmethod
def get_little_endian_hex(hex_str):
pass
class BaseCode(object):
_type_map_index_pack_tag = 1
_type_map_index_pack_size = 2 # unused
_type_map = {
# C类型:(说明, 编码标志)
'char': ('int', 'B'),
'string': ('str', 'B'),
'uint32_t': ('int', 'I'),
'int32_t': ('int', 'i'),
'int64_t': ('int', 'q'),
'uint64_t': ('int', 'Q'),
'uint16_t': ('short', 'H'),
'int16_t': ('short', 'h'),
'float': ('float', 'f'),
'double': ('double', 'd'),
}
# 每种基础类型所占字节数
_ctype_size_map = {'I': 4, 'B': 1, 'i': 4, 'b': 1, 'Q': 8, 'q': 8, 'f': 4, 'd': 8, 'h': 2, 'H': 2}
_fields_index_ctype = 0
_fields_index_value_name = 1
_fields_index_array_length = 2 # 之前的第三个参数的数字length
_fields_index_addtion_dict = 2 # 现在我改成字典 {"length":1, "reverse":True} reverse=True,表示小端序
# 用元组,扩展性很差,改成FieldType,为了兼容性良好,__init__构造的一致,实现了__getitem__,也支持[]读取
_fields = [
# (C类型, 变量名)
FieldType('uint32_t', 'nUint'),
FieldType('string', 'szString', **{"length": 20}),
FieldType('int32_t', 'nInt3'),
FieldType('uint32_t', 'nUintArray', **{"length": 4}),
]
def __init__(self):
"""
初始都置空
"""
for one in self._fields:
setattr(self, one[self._fields_index_value_name], None)
def encode(self, nest=1):
data = b''
tmp = b''
debug_log("&" * nest, self.__class__.__name__, "encode struct start :")
for one in self._fields:
debug_log("#" * nest, "encode one element:", one)
ctype = one[self._fields_index_ctype]
value = getattr(self, one[self._fields_index_value_name])
if one.is_addtional():
# _addtions = one[self._fields_index_addtion_dict]
# if type(_addtions) != dict:
# print("param one[2] error: %s", _addtions)
# exit(1)
endian_char = one.get_endian_char()
length = one.get_field_length()
if length > 1:
tmp = self._encode_array(ctype, value, length, endian_char)
else: # 这子域的是复制外面那个else分支的代码,只是修改了endian_char
if ctype not in BaseCode._type_map:
tmp = value.encode(nest + 1)
else:
fmt = endian_char + self._type_map[ctype][self._type_map_index_pack_tag]
tmp = struct.pack(fmt, value)
else:
# 不是基础类型,即嵌套定义
if ctype not in BaseCode._type_map:
tmp = value.encode(nest + 1)
else: # !网络序(同大端序),> (big-endian) , < (little-endian)
fmt = '!' + self._type_map[ctype][self._type_map_index_pack_tag]
tmp = struct.pack(fmt, value)
# debug_log(fmt, type(value), value)
debug_log("#" * nest,"encode one element:", len(tmp), tmp)
data += tmp
debug_log("&" * nest, self.__class__.__name__, "encode end: len=", len(data), data)
return data
def _encode_array(self, ctype, value, max_length, endian_char="!"):
"""
打包数组
如果是字符串类型 需要做下特殊处理
:param ctype:
:param value:
:param max_length:
:param endian_char -- !网络序(同大端序),> (big-endian) , < (little-endian)
:return:
"""
debug_log('ctype:', ctype, type(ctype))
if ctype == 'string':
max_length -= 1 # 字符串长度需要减一
value = bytes(value, encoding='utf8')
#print(value)
if len(value) > max_length:
raise EncodeError('the length of array is too long')
# # # pack长度
# data = struct.pack(endian_char + 'H', len(value))
# debug_log("array count:", len(value), "value:", value, type(value))
data = b""
# pack数组内容
for one in value:
#debug_log("self._type_map[ctype][1]=", self._type_map[ctype][self._type_map_index_pack_tag], one)
if ctype not in BaseCode._type_map:
data += one.encode()
else:
data += struct.pack(endian_char + self._type_map[ctype][self._type_map_index_pack_tag], one)
return data
def decode(self, data, offset=0, nest=1):
"""
:param data:
:return:
"""
debug_log("&" * nest, self.__class__.__name__, "decode struct start :")
for one in self._fields:
debug_log("#" * nest, "decode one element:", one)
ctype = one[self._fields_index_ctype]
if one.is_addtional():
# _addtions = one[self._fields_index_addtion_dict]
# if type(_addtions) != dict:
# print("param one[2] error: %s", _addtions)
# exit(1)
endian_char = one.get_endian_char()
length = one.get_field_length()
if length > 1:
offset = self._decode_array(one, data, offset, nest)
else: # 这子域的是复制外面那个else分支的代码,只是修改了endian_char
ctype_attr = self._type_map[ctype]
if ctype not in BaseCode._type_map:
value = eval(ctype + '()')
offset = value.decode(data, offset, nest)
setattr(self, one[self._fields_index_value_name], value)
else:
fmt = endian_char + ctype_attr[self._type_map_index_pack_tag]
value, = struct.unpack_from(fmt, data, offset)
offset += self._ctype_size_map[ctype_attr[self._type_map_index_pack_tag]]
debug_log(one, one[self._fields_index_value_name])
setattr(self, one[self._fields_index_value_name], value)
else:
ctype_attr = self._type_map[ctype]
endian_char = one.get_endian_char()
if ctype not in BaseCode._type_map:
value = eval(ctype + '()')
offset = value.decode(data, offset, nest)
setattr(self, one[self._fields_index_value_name], value)
else:
fmt = endian_char + ctype_attr[self._type_map_index_pack_tag]
value, = struct.unpack_from(fmt, data, offset)
offset += self._ctype_size_map[ctype_attr[self._type_map_index_pack_tag]]
debug_log(one, one[self._fields_index_value_name])
setattr(self, one[self._fields_index_value_name], value)
debug_log("#" * nest, "decode one element end:", offset, one)
return offset
def _decode_array(self, field, data, offset, nest):
ctype = field[self._fields_index_ctype]
# array_num, = struct.unpack_from('!H', data, offset) # 之前该同学的代码会把长度序列化和反序列化
# offset += 2
array_num = field.get_field_length()
value = []
ctype_attr = self._type_map[ctype]
endian_char = field.get_endian_char()
debug_log("$" * nest, "decode array count", array_num, field)
while array_num > 0:
array_num -= 1
if ctype not in BaseCode._type_map:
one = eval(ctype + '()')
offset = one.decode(data, offset, nest)
value.append(one)
else:
one, = struct.unpack_from(endian_char + ctype_attr[self._type_map_index_pack_tag], data, offset)
value.append(one)
offset += self._ctype_size_map[ctype_attr[self._type_map_index_pack_tag]]
if ctype == 'string':
# 这里是因为字符串是按照单个字符解包,会解成python的int,通过chr()转化为字符型
# value = [97,98]
# list(map(chr,value)) 后等于 ['a','b']
# ''.join() 就转成'ab'
value = ''.join(list(map(chr, value)))
value = bytes(value, encoding='latin1').decode('utf8')
setattr(self, field[self._fields_index_value_name], value)
debug_log("$" * nest, "decode array ok", array_num, field)
return offset
def tprint(self, tab=0):
prefix = ' ' * tab
debug_log(prefix, self.__class__, ":")
for one in self._fields:
ctype = one[self._fields_index_ctype]
value = getattr(self, one[self._fields_index_value_name])
if ctype not in BaseCode._type_map:
debug_log(prefix, one[self._fields_index_value_name] + ' =')
if type(value) == list:
[el.tprint(tab + 1) for el in value]
else:
value.tprint(tab + 1)
else:
debug_log(prefix, one[self._fields_index_value_name] + ' =', value)
def todict(self):
"""
把字段转成字典
:param ret:
:return:
"""
ret = {}
for one in self._fields:
ctype = one[self._fields_index_ctype]
key = one[self._fields_index_value_name]
value = getattr(self, key)
# print(key + ' =', value)
if ctype not in BaseCode._type_map:
# 自定义类型
if type(value) == list:
# 数组
ret[key] = [el.todict() for el in value]
else:
ret[key] = value.todict()
else:
# 基本类型
ret[key] = value
return ret
def tojson_print1(self):
print(json.dumps(self.todict(), indent=4, separators=(', ', ': '), ensure_ascii=False))
def tojson_print2(self): # 美观度不如1
pp = pprint.PrettyPrinter(indent=2)
pp.pprint(self.todict())
@staticmethod
def parse_hex_str_2_time(hex_str):
""" '0x6215e413' to '2022-02-23 15:36:51' """
return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(hex_str, 16)))
@staticmethod
def parse_hex_str_ipv4_address(hex_str):
""" '0x33200954' to '51.32.9.84' """
ip_p3 = hex_str[-8:-6]
ip_p2 = hex_str[-6:-4]
ip_p1 = hex_str[-4:-2]
ip_p0 = hex_str[-2:]
return ".".join([str(int(x, 16)) for x in [ip_p3, ip_p2, ip_p1, ip_p0]])
@staticmethod
def print_cmp_with_hex_static(ctype, _input_data):
loc = locals()
exec("test_obj = {}();".format(ctype))
test_obj = loc["test_obj"]
test_obj.print_cmp_with_hex(_input_data)
def print_cmp_with_hex(self, _input_data):
"""
输出诸如
struct ext4_extent {
__le32 ee_block : 00 00 00 00 : 0 : 0
__le16 ee_len : 01 00 : 0x1 : 1
__le16 ee_start_hi; : 00 00 : 0 : 0
__le32 ee_start_lo; : 1e 86 00 00 : 0x861e : 34334
};
嵌套的自动解包:
先把嵌套类型的名字和原始数据打出来
再把参入放入yield_params
最后用exec调用执行转换
占位格式化
mat = "{:020}\t{:010}\t{:12}" # 冒号后面指定输出宽度,冒号后的第一个0表示用0占位
print(mat.format(1,2,3333)) # 00000000000000000001 0000000002 3333
"""
results = []
results.append("struct %s {" % self.__class__.__name__)
yield_params = []
key_width = 30
mat = " {:10}{:%s} : {:30}: {:30} : {:20} {:20}" % key_width
mat2 = " {:10}{:%s} : {:62} : {:20}" % key_width
offset = 0
for one in self._fields:
key = one[self._fields_index_value_name]
value = getattr(self, key)
raw_field = one.get_raw_field()
ctype = one[self._fields_index_ctype]
if ctype not in BaseCode._type_map:
length = one.get_field_length()
ctype_size = 12 ### 要实际计算,之前测试全是ext4_extent的三个对象,都是12的size
# 已知类型,直接返回其size
if ctype in GLOBAL_SIZE_DICT.keys():
ctype_size = GLOBAL_SIZE_DICT[ctype]
else:
# 未知类型,实时计算
# 可能还需要import类型
loc = locals()
exec("_size_by_exec = %s().calculate_size(True)" % ctype)
ctype_size = loc["_size_by_exec"]
GLOBAL_SIZE_DICT[ctype] = ctype_size
for i in range(length):
hex_data = []
for i in range(ctype_size):
hex_data.append(_input_data[offset + i])
offset += ctype_size
hex_list_str = " ".join(hex_data)
line_str = mat2.format(" ", raw_field, hex_list_str, " sizeof=%s" % ctype_size)
results.append(line_str)
yield_params.append((ctype, hex_data))
else:
ctype_size = self._ctype_size_map[self._type_map[ctype][self._type_map_index_pack_tag]]
ctype_length = 1
if type(value) == list:
ctype_length = len(value)
hex_data = []
for i in range(ctype_size * ctype_length):
hex_data.append(_input_data[offset + i])
offset += ctype_size * ctype_length
if one.is_little_endian():
hex_list_str = " ".join(hex_data)
hex_str = "0x" + "".join(hex_data[::-1])
else:
hex_list_str = " ".join(hex_data)
hex_str = "0x" + "".join(hex_data)
if not value:
value = int(hex_str, 16) # exec调用的时候,上面的value获取值似乎有问题
if type(value) == list:
if ctype == "char":
value = ''.join([chr(c) for c in value])
else:
value = str(value)
# print(raw_field, key, hex_list_str, hex_str, value, " ")
if len(hex_list_str) > 23:
hex_list_str = hex_list_str[:15] + "..." + hex_list_str[-11:]
if len(hex_str) > 23:
hex_str = hex_str[:18] + "..." + hex_str[-8:]
line_str = mat.format(raw_field, key, hex_list_str, hex_str, value, " ")
if "\r" in line_str: # 修正了一个输出格式不对的bug
line_str = line_str.replace("\r", "")
if "\n" in line_str:
line_str = line_str.replace("\n", "")
if key.endswith("time"):
try:
time_parse = BaseCode.parse_hex_str_2_time(hex_str)
line_str = mat.format(raw_field, key, hex_list_str, hex_str, value, " : " + time_parse)
except:
pass
if key.endswith("ipv4_address"):
try:
ip_parse = BaseCode.parse_hex_str_ipv4_address(hex_str)
line_str = mat.format(raw_field, key, hex_list_str, hex_str, value, " : " + ip_parse)
except:
pass
results.append(line_str)
results.append("}")
print('\n'.join(results))
if yield_params:
print(" >>> extend instances :")
# print(yield_params)
for ctype1, hex_data1 in yield_params:
BaseCode.print_cmp_with_hex_static(ctype1, hex_data1)
def calculate_size(self, is_print=False):
"""
最新:已经完成嵌套的功能,但是局限性在于:
必须在 【# 自定义类型】处,手动import嵌套的子类型,要不然会报类型找不到
而且:嵌套的子类型是通过exec来执行的,debug会出错。
(因此:最新把exec代码局限在_exec_calc_size内部函数里)
"""
result = 0
for one in self._fields:
ctype = one[self._fields_index_ctype]
key = one[self._fields_index_value_name]
if ctype in BaseCode._type_map: # 基本类型
if not one.is_addtional():
result += self._ctype_size_map[self._type_map[ctype][self._type_map_index_pack_tag]]
else:
length = one.get_field_length()
result += length * self._ctype_size_map[self._type_map[ctype][self._type_map_index_pack_tag]]
else:
# 自定义类型
# 自定义类型的size,如果动态获取,只能通过exec,局限性略大
def _exec_calc_size(ctype_name):
from basecode_structs import ext4_extent
from basecode_structs import ext4_extent_header
loc = locals()
# exec("test_obj = {}();print(test_obj)".format(ctype))
exec("test_obj = {}();".format(ctype))
test_obj = loc["test_obj"]
_ctype_size = test_obj.calculate_size()
return _ctype_size
one_ctype_size = 0
# 已知类型,直接返回其size
if ctype in GLOBAL_SIZE_DICT.keys():
one_ctype_size = GLOBAL_SIZE_DICT[ctype]
else:
one_ctype_size = _exec_calc_size(ctype)
GLOBAL_SIZE_DICT[ctype] = one_ctype_size
if not one.is_addtional():
result += one_ctype_size
else:
length = one.get_field_length()
result += length * one_ctype_size
if is_print:
print(" # [calculate_size]: class %s, size=%s" % (self.__class__.__name__, result))
return result
class FormatDecoder(object):
def __init__(self, ptype='input'):
self.ptype = ptype
self.input_raw = None
self.input_length = 0
self.input_bytes = bytes([0])
self.output_data = None
self.test_obj = None
@staticmethod
def parse_struct(ccode):
"""
struct ext4_extent_header {
__le16 eh_magic; /* probably will support different formats
(i add a new line) #define EXT4_EXT_MAGIC cpu_to_le16(0xf30a)
*/
__le16 eh_entries; /* number of valid entries */
__le16 eh_max; /* capacity of store in entries */
__le16 eh_depth; /* has tree real underlying blocks? */
// i add a new line
__le32 eh_generation; // generation of the tree
};
c代码的定义 转换成 python代码:
class ext4_extent_header(BaseCode):
_fields = [
FieldType('uint16_t', 'eh_magic', **{"raw_field": "__le16", "reverse": True}),
FieldType('uint16_t', 'eh_entries', **{"raw_field": "__le16", "reverse": True}),
FieldType('uint16_t', 'eh_max', **{"raw_field": "__le16", "reverse": True}),
FieldType('uint16_t', 'eh_depth', **{"raw_field": "__le16", "reverse": True}),
FieldType('uint32_t', 'eh_generation', **{"raw_field": "__le32", "reverse": True}),
]
"""
content1 = re.sub(r'/\*.*?\*/', '', ccode, flags=re.S) # 删除代码中的注释
content = re.sub(r'(//.*)', '', content1) # 删除代码中的注释
lines = content.split("\n")
start_line_no = 0
for i, line in enumerate(lines):
if "struct" in line:
start_line_no = i
break
new_lines = []
python_codes = []
for line in lines[start_line_no + 1:]:
line_strip = line.strip()
if line_strip == '};':
break
if line_strip == '':
continue
new_lines.append(line_strip.rstrip(";").replace("\t", " "))
# print(new_lines)
max_key_width = 18
for field_line in new_lines:
key_width1 = len(field_line) - 10
if key_width1 > max_key_width:
max_key_width = key_width1
def _get_class_name(struct_line):
arr1 = struct_line.replace("\t", " ").split(" ")
return list(filter(lambda x: x, arr1))[1]
space_regex = re.compile('\s+')
def _parse_line_field(field_line, key_width=18):
# c语言的代码__le16 ee_start_hi 转换成python代码,本文件定义的field格式 ('uint16_t', 'ee_start_hi', {"reverse": True}),
arr2 = space_regex.split(field_line)
# print(arr2)
field_name = arr2[-1] # field_name = arr2[1]
field_type = arr2[0]
field_type_mapped = "char"
field_addtional_reverse = False
if len(arr2) > 2:
field_type = " ".join(arr2[:-1])
if field_type == "u8":
field_type_mapped = "char"
elif field_type == "_u8":
field_type_mapped = "char"
elif field_type == "__u8":
field_type_mapped = "char"
elif field_type == "u16":
field_type_mapped = "uint16_t"
elif field_type == "_u16":
field_type_mapped = "uint16_t"
elif field_type == "__u16":
field_type_mapped = "uint16_t"
elif field_type == "u32":
field_type_mapped = "uint32_t"
elif field_type == "_u32":
field_type_mapped = "uint32_t"
elif field_type == "__u32":
field_type_mapped = "uint32_t"
elif field_type == "u64":
field_type_mapped = "uint64_t"
elif field_type == "_u64":
field_type_mapped = "uint64_t"
elif field_type == "__u64":
field_type_mapped = "uint64_t"
elif field_type == "__be16":
field_type_mapped = "uint16_t"
elif field_type == "__be32":
field_type_mapped = "uint32_t"
elif field_type == "__be64":
field_type_mapped = "uint64_t"
elif field_type == "__le16":
field_type_mapped = "uint16_t"
elif field_type == "__le32":
field_type_mapped = "uint32_t"
elif field_type == "__le64":
field_type_mapped = "uint64_t"
elif field_type == "unsigned short":
field_type_mapped = "uint16_t"
elif field_type == "unsigned int":
field_type_mapped = "uint32_t"
elif field_type == "unsigned long":
field_type_mapped = "uint64_t"
elif field_type == "unsigned long long":
field_type_mapped = "uint64_t"
elif field_type == "short":
field_type_mapped = "int16_t"
elif field_type == "int":
field_type_mapped = "int32_t"
elif field_type == "long":
field_type_mapped = "int64_t"
elif field_type == "long long":
field_type_mapped = "int64_t"
else:
if "struct" in field_type:
# print("[%s] not base datatype, not supported." % field_type)
# field_type_mapped = field_type # 原计划原值返回,但是会不可执行,直接return吧
field_type_mapped = field_type.split(" ")[1]
elif "union" in field_type:
# print("[%s] not base datatype, not supported." % field_type)
# field_type_mapped = field_type # 原计划原值返回,但是会不可执行,直接return吧
return
else:
return
if field_type in ["__le16", "__le32", "__le64"]:
field_addtional_reverse = True
# 占位格式化
mat = " FieldType({:12}\t{:%s}\t{:48})," % key_width
addtional_dict = {"raw_field": field_type}
if field_addtional_reverse:
addtional_dict["reverse"] = True
if field_name.endswith("]"):
field_size = field_name.split("[")[1][:-1]
addtional_dict["length"] = int(field_size)
field_name = field_name.split("[")[0]
addtional_dict_str = '**' + str(addtional_dict).replace("'", '"')
field_code = mat.format("'%s'," % field_type_mapped, "'%s'," % field_name, addtional_dict_str)
return field_code
try:
class_name = _get_class_name(lines[start_line_no])
python_codes.append("class {}(BaseCode):".format(class_name))
python_codes.append(" _fields = [")
for field_line in new_lines:
_parse_field = _parse_line_field(field_line, max_key_width)
if _parse_field:
python_codes.append(_parse_field)
python_codes.append(" ]")
ccode_result = "\n".join(python_codes)
print(ccode_result)
return ccode_result, class_name
except Exception as e:
# print("Error: ", e)
print("Error: ", traceback.format_exc())
print("struct source format error")
exit(1)
@my_try_except_warpper(is_exit=True, err_msg="Decode hex data source format error")
def parse_chr_array_2_bytes(self, chrs):
"""
10 00 00 00 01 00 02 00 1E 86 00 00
转换成<class 'bytes'>
b'\x00\x00\x00\x10\x00\x01\x00\x02\x00\x00\x86\x1e'
也支持 10000000010002001E860000
=== 严格来说,要严格校验chrs的格式
"""
raw_data = []
if " " in chrs:
raw_data = list(filter(lambda x: x, chrs.split(" ")))
else:
for i, x in enumerate(chrs):
if i % 2:
raw_data.append(chrs[i - 1] + x)
hex_2_dec_data = [int(item, 16) for item in raw_data]
result = bytes(hex_2_dec_data)
print("[parse_chr_array_2_bytes]: %s" % result)
if self.ptype == "input":
self.input_bytes = result
self.input_length = len(hex_2_dec_data)
return result, len(hex_2_dec_data)
def parse_chr_array_2_hex_list(self, chrs):
"""
输入chrs 从hexdump来的 数据样式为 ' 00 00 c8 00 00 00 20 03 00 00 28 00 f3 35 0f 03 '
输入chrs 内容没有被分割 数据样式为 '000064000000900100001400e87c8701'
hex格式化输出使用,因此在parse_chr_array_2_bytes剪了部分代码过来
输出:['00', '00', 'c8', '00', '00', '00', '20', '03', '00', '00', '28', '00', 'f3', '35', '0f', '03']
"""
raw_data = []
if " " in chrs:
raw_data = list(filter(lambda x: x, chrs.split(" ")))
else:
for i, x in enumerate(chrs):
if i % 2:
raw_data.append(chrs[i - 1] + x)
if self.ptype == "input":
self.output_data = raw_data
return raw_data
def decode_hex(self, class_type):
loc = locals()
try:
exec("test_obj = {}()".format(class_type))
except NameError:
print("NameError when decode_hex")
help(sys.argv[0])
test_obj = loc['test_obj']
test_obj_size = test_obj.calculate_size()
if self.input_length < test_obj_size:
print("input hex size [%s] less than sizeof(%s)=[%s]" % (self.input_length, class_type, test_obj_size))
exit(1)
elif self.input_length > test_obj_size:
print("input hex size [%s] more than sizeof(%s)=[%s], " % (self.input_length, class_type, test_obj_size))
self.input_bytes = self.input_bytes[:test_obj_size]
print("only use the previous required data: %s" % self.input_bytes)
test_obj.decode(self.input_bytes)
self.test_obj = test_obj
def parse_to_bytes(self, **kwargs):
if self.ptype == "input":
self.input_raw = kwargs.get("input")
return self.parse_chr_array_2_bytes(self.input_raw)
print("type is unsupported")
def parse_to_hex_list(self):
if self.ptype == "input":
return self.parse_chr_array_2_hex_list(self.input_raw)
print("type is unsupported")
def show_output(self):
if self.test_obj and self.output_data:
# self.test_obj.tojson_print1()
self.test_obj.print_cmp_with_hex(self.output_data)
def run(self):
if self.test_obj and self.output_data:
# self.test_obj.tojson_print1()
self.test_obj.print_cmp_with_hex(self.output_data)
class FormatDecoderHexdump(FormatDecoder):
def __init__(self, rst_file=''):
super().__init__(ptype="hexdump")
self.rst_file = rst_file or "hexdump.rst"
@my_try_except_warpper(is_exit=True, err_msg="Decode hexdump file hexdump.rst format error")
def parse_to_bytes(self, **kwargs):
raw_data = []
with open(self.rst_file) as file1:
rcode = file1.read()
for line in rcode.split("\n"): # line = "00000400 00 00 c8 00 00 00 20 03 00 00 28 00 f3 35 0f 03 |...... ...(..5..|"
line_parse = line.split("|")[0][9:]
raw_data.extend(self.parse_chr_array_2_hex_list(line_parse))
hex_2_dec_data = [int(item, 16) for item in raw_data]
result = bytes(hex_2_dec_data)
print("[parse_hexdump_rst]: %s" % result)
self.input_bytes = result
self.input_length = len(hex_2_dec_data)
def parse_to_hex_list(self):
"""
hex格式化输出使用,因此在parse_hexdump_rst_2_bytes剪了部分代码过来
"""
raw_data = []
with open(self.rst_file) as file1:
rcode = file1.read()
for line in rcode.split("\n"):
line_parse = line.split("|")[0][9:]
raw_data.extend(self.parse_chr_array_2_hex_list(line_parse))
self.output_data = raw_data
class FormatDecoderVib(FormatDecoder):
def __init__(self, rst_file=''):
super().__init__(ptype="vib")
self.rst_file = rst_file or "vib2xxd.rst"
@my_try_except_warpper(is_exit=True, err_msg="Decode hexdump file vib2xxd.rst format error")
def parse_to_bytes(self, **kwargs):
# FC新环境没有hexdump,用vi来操作,vi -b ttt1 二进制打开文件 :%!xxd 转换成十六进制
raw_data = []
with open(self.rst_file) as file1:
rcode = file1.read()
for line in rcode.split("\n"): # line = "00000400: 0000 6400 0000 9001 0000 1400 e87c 8701 ..d..........|.."
line_parse = "".join(line.split(":")[1][1:40].split(" "))
raw_data.extend(self.parse_chr_array_2_hex_list(line_parse))
hex_2_dec_data = [int(item, 16) for item in raw_data]
result = bytes(hex_2_dec_data)
print("[parse_vib2xxd_rst]: %s" % result)
self.input_bytes = result
self.input_length = len(hex_2_dec_data)
def parse_to_hex_list(self):
raw_data = []
with open(self.rst_file) as file1:
rcode = file1.read()
for line in rcode.split("\n"):
line_parse = "".join(line.split(":")[1][1:40].split(" "))
raw_data.extend(self.parse_chr_array_2_hex_list(line_parse))
self.output_data = raw_data
### 以下是基本功能测试片段
class ext4_extent__test(BaseCode):
_fields =[
FieldType('uint32_t', 'ee_block', **{"reverse": True}),
FieldType('uint16_t', 'ee_len', **{"reverse": True}),
FieldType('uint16_t', 'ee_start_hi', **{"reverse": True}),
FieldType('uint32_t', 'ee_start_lo', **{"reverse": True}),
]
class ext4_extent__unreverse(BaseCode):
_fields =[
FieldType('uint32_t', 'ee_block'),
FieldType('uint16_t', 'ee_len'),
FieldType('uint16_t', 'ee_start_hi'),
FieldType('uint32_t', 'ee_start_lo'),
]
#【10 00 00 00 01 00 02 00 1E 86 00 00】的ext4_extent(sizeof=12), 10是ee_len, 02 00是ee_start_hi; 1E 86 00 00 ee_start_lo; 高16位,低32位,合在一起是 0x00020000861E
def ext4_test():
extent1 = ext4_extent__unreverse() # b'\x00\x00\x00\x10\x00\x01\x00\x02\x00\x00\x86\x1e'
extent1.ee_block = 16
extent1.ee_len = 1
extent1.ee_start_hi = 2
extent1.ee_start_lo = 34334 # 0x861E
data1 = extent1.encode()
print('extent1 **final:', len(data1), type(data1), data1)
print("extent2")
extent2 = ext4_extent__unreverse()
extent2.decode(data1)
extent2.tojson_print1()
print("c1") # 因为是小端对象,不能这么赋值了
c1 = ext4_extent__test()
c1.ee_block = 16
c1.ee_len = 1
c1.ee_start_hi = 2
c1.ee_start_lo = 34334 # 0x861E
data_c1 = c1.encode()
print('c1 **final:', len(data_c1), type(data_c1), data_c1)
print("c2")
c2 = ext4_extent__test()
c2.decode(data_c1)
c2.tojson_print1()
"""
c1 **final: 12 <class 'bytes'> b'\x00\x00\x00\x10\x00\x01\x00\x02\x00\x00\x86\x1e'
c2
{
"ee_block": 268435456,
"ee_len": 256,
"ee_start_hi": 512,
"ee_start_lo": 512098304 # 是 0x1E860000
}
"""
print("c3") # 因为是小端对象,不能这么赋值了
c3 = ext4_extent__test()
c3.ee_block = FieldType.get_little_endian_int32(16) # hex(268435456) '0x10000000'
c3.ee_len = FieldType.get_little_endian_int16(1) # hex(256) '0x0100
c3.ee_start_hi = FieldType.get_little_endian_int16(2) # hex(512) '0x0200'
c3.ee_start_lo = FieldType.get_little_endian_int32(34334) # 0x861E ## hex(512098304) '0x1e860000'
data_c3 = c3.encode()
print('c3 **final:', len(data_c3), type(data_c3), data_c3)
print("c4")
c4 = ext4_extent__test()
c4.decode(data_c3)
c4.tojson_print1()
print("ttt")
ttt = ext4_extent__test()
formater = FormatDecoder()
tttbytes0 = formater.parse_chr_array_2_bytes('10000000010002001E860000')
print(tttbytes0)
tttbytes = formater.parse_chr_array_2_bytes('10 00 00 00 01 00 02 00 1E 86 00 00')
print(tttbytes)
ttt.decode(tttbytes[0])
ttt.tojson_print1()
def ext4_ccode_test1():
ccode = """
int i;
int cl;
struct ext4_extent_header_mytest {
__le16 eh_magic; /* probably will support different formats
(i add a new line) #define EXT4_EXT_MAGIC cpu_to_le16(0xf30a)
*/
__le16 eh_entries; /* number of valid entries */
__le16 eh_max; /* capacity of store in entries */
__le16 eh_depth; /* has tree real underlying blocks? */
// i add a new line
__le32 eh_generation; // generation of the tree
unsigned long long test_field;
};
"""
length = 0
ccode_result, class_name = FormatDecoder.parse_struct(ccode)
ccode_result += "\n"
ccode_result += "test_obj = {}()".format(class_name)
ccode_result += "\n"
ccode_result += "length = test_obj.calculate_size()"
ccode_result += "\n"
ccode_result += "print(length)"
# eval(ccode_result) # eval new对象 - 报错 SyntaxError: invalid syntax
# eval("test_obj = {}()".format(class_name))
# eval("length = test_obj.calculate_size()")
# 换成exec,结合locals搞定
loc = locals()
exec(ccode_result)
class_ext4_extent_header_mytest = loc['ext4_extent_header_mytest']
print(class_ext4_extent_header_mytest)
test_obj =class_ext4_extent_header_mytest()
test_obj.calculate_size()
class ext4_extent_header_mytest2(BaseCode):
_fields = [
FieldType('uint16_t', 'eh_magic', **{"reverse": True}),
FieldType('uint16_t', 'eh_entries', **{"reverse": True}),
FieldType('uint16_t', 'eh_max', **{"reverse": True}),
FieldType('uint16_t', 'eh_depth', **{"reverse": True}),
FieldType('uint32_t', 'eh_generation', **{"reverse": True}),
# FieldType('uint64_t', 'test_field'),
]
def ext4_ccode_test2():
test_obj = ext4_extent_header_mytest2()
length = test_obj.calculate_size()
print(length)
def ext4_ccode_test3():
exec("ext4_extent_header_mytest2().calculate_size()")
exec("test_obj = ext4_extent_header_mytest2(); test_obj.calculate_size()")
loc = locals()
exec("test_obj = ext4_extent_header_mytest2()") # 这里exec的对象,下文中无法使用
# 为了修正这样的错误,你需要在调用 exec() 之前使用 locals() 函数来得到一个局部变量字典。 之后你就能从局部字典中获取修改过后的变量值了。
test_obj = loc['test_obj']
print(test_obj)
length = test_obj.calculate_size()
print(length)
def ext4_inode_hexdump_test():
print("\n\n========ext4_inode_hexdump_test========")
input_bytes = b'\xa0\x81\x00\x00\x18\x1b\x00\x00\x13\xe4\x15bY\xe4\x15bY\xe4\x15b\x00\x00\x00\x00\x00\x00\x01\x00\x10\x00\x00\x00\x00\x00\x08\x00\x01\x00\x00\x00\n\xf3\x02\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x88\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x8a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x03\xac\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00g\xe3\x00\x00 \x00\xe9\xa2(\xaa\x96\xd7(\xaa\x96\xd7\xac\xda\xc4C\x13\xe4\x15b\xac\xda\xc4C\x00\x00\x00\x00\x00\x00\x00\x00'
# input_length = len(input_bytes) # 160
test_obj = ext4_inode()
test_obj.decode(input_bytes)
_input_data = ['a0', '81', '00', '00', '18', '1b', '00', '00', '13', 'e4', '15', '62', '59', 'e4', '15', '62',
'59', 'e4', '15', '62', '00', '00', '00', '00', '00', '00', '01', '00', '10', '00', '00', '00',
'00', '00', '08', '00', '01', '00', '00', '00', '0a', 'f3', '02', '00', '04', '00', '00', '00',
'00', '00', '00', '00', '00', '00', '00', '00', '01', '00', '00', '00', '00', '88', '00', '00',
'01', '00', '00', '00', '01', '00', '00', '00', '00', '8a', '00', '00', '00', '00', '00', '00',
'00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00',
'00', '00', '00', '00', '05', '03', 'ac', 'b3', '00', '00', '00', '00', '00', '00', '00', '00',
'00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '67', 'e3', '00', '00',
'20', '00', 'e9', 'a2', '28', 'aa', '96', 'd7', '28', 'aa', '96', 'd7', 'ac', 'da', 'c4', '43',
'13', 'e4', '15', '62', 'ac', 'da', 'c4', '43', '00', '00', '00', '00', '00', '00', '00', '00']
test_obj.print_cmp_with_hex(_input_data)
@my_try_except_warpper()
def ext4_sb_hexdump_test():
print("\n\n========ext4_super_block_hexdump_test========")
test_obj = ext4_super_block()
hexdump_rst="test/hexdump_ext4_super_block.rst"
formater = FormatDecoderHexdump(hexdump_rst)
formater.parse_to_bytes()
test_obj.decode(formater.input_bytes)
formater.parse_to_hex_list()
test_obj.print_cmp_with_hex(formater.output_data)
@my_try_except_warpper()
def gernel_test():
ext4_test()
ext4_ccode_test1()
ext4_ccode_test2()
ext4_ccode_test3()
ext4_inode_hexdump_test()
# ext4_sb_hexdump_test()
## 拆分到basecode_structs始终还有问题,嵌套子类型不能声明在那边,eval的时候找不到
class ext4_extent(BaseCode):
_fields = [
FieldType('uint32_t', 'ee_block', **{"raw_field": "__le32", "reverse": True}),
FieldType('uint16_t', 'ee_len', **{"raw_field": "__le16", "reverse": True}),
FieldType('uint16_t', 'ee_start_hi', **{"raw_field": "__le16", "reverse": True}),
FieldType('uint32_t', 'ee_start_lo', **{"raw_field": "__le32", "reverse": True}),
]
# [calculate_size]: class ext_extent, size=12
class ext4_extent_idx(BaseCode):
_fields = [
FieldType('uint32_t', 'ei_block', **{"raw_field": "__le32", "reverse": True}),
FieldType('uint32_t', 'ei_leaf_lo', **{"raw_field": "__le32", "reverse": True}),
FieldType('uint16_t', 'ei_leaf_hi', **{"raw_field": "__le16", "reverse": True}),
FieldType('uint16_t', 'ei_unused', **{"raw_field": "__u16"}),
]
# [calculate_size]: class ext4_extent_idx, size=12
class ext4_extent_header(BaseCode):
_fields = [
FieldType('uint16_t', 'eh_magic', **{"raw_field": "__le16", "reverse": True}),
FieldType('uint16_t', 'eh_entries', **{"raw_field": "__le16", "reverse": True}),
FieldType('uint16_t', 'eh_max', **{"raw_field": "__le16", "reverse": True}),
FieldType('uint16_t', 'eh_depth', **{"raw_field": "__le16", "reverse": True}),
FieldType('uint32_t', 'eh_generation', **{"raw_field": "__le32", "reverse": True}),
]
# [calculate_size]: class ext4_extent_header, size=12
if __name__ == '__main__1':
gernel_test()
# 不用动name了,直接在这改0和1
TEST_SWITCH = 0
def help(selfname):
print('<hex input> is missing')
print('%s -c <class> -h <hex chars input>' % selfname)
print('%s -c <class> -r <hexdump/vi>' % selfname)
exit(1)
# python basecode.py -s source.c
# python basecode.py -c ext4_extent -h "10 00 00 00 01 00 02 00 1E 86 00 00"
# python basecode.py -c ext4_inode -r hexdump
# python basecode.py -c ext4_super_block -r vi
if __name__ == '__main__':
if TEST_SWITCH:
gernel_test()
exit(0)
class_type = None
hex_input = None
hex_rst_type = None
src_code = None
try:
shortargs = 'c:h:r:s:'
longargs = ['--class', '--hex', '--resource', '--source']
opts, args = getopt.getopt(sys.argv[1:], shortargs, longargs)
for opt, arg in opts:
if opt in ("-c", "--class"):
class_type = arg
elif opt in ("-h", "--hex"):
hex_input = arg
elif opt in ("-r", "--resource_type"):
hex_rst_type = arg
elif opt in ("-s", "--source"):
src_code = arg
if src_code:
file0 = open(src_code, mode='r')
ccode = file0.read()
ccode_result, class_name = FormatDecoder.parse_struct(ccode)
exit(0)
if class_type:
formater = FormatDecoder('input')
if hex_input:
formater.parse_to_bytes(input=hex_input)
elif hex_rst_type:
if hex_rst_type in ["hexdump", "hd"]:
formater = FormatDecoderHexdump()
formater.parse_to_bytes()
elif hex_rst_type == "vi":
formater = FormatDecoderVib()
formater.parse_to_bytes()
else:
help(sys.argv[0])
else:
help(sys.argv[0])
formater.decode_hex(class_type)
formater.parse_to_hex_list()
formater.show_output()
except getopt.GetoptError:
print('%s -c <class> -h <hex chars input>' % sys.argv[0])
print('%s -s <source code>' % sys.argv[0])
exit(2)
basecode_structs.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
import copy
from basecode import BaseCode, FieldType
class ext4_extent(BaseCode):
_fields = [
FieldType('uint32_t', 'ee_block', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint16_t', 'ee_len', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint16_t', 'ee_start_hi', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint32_t', 'ee_start_lo', **{"raw_field": "__le32", "reverse": True} ),
]
# [calculate_size]: class ext_extent, size=12
class ext4_extent_idx(BaseCode):
_fields = [
FieldType('uint32_t', 'ei_block', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 'ei_leaf_lo', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint16_t', 'ei_leaf_hi', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint16_t', 'ei_unused', **{"raw_field": "__u16"} ),
]
# [calculate_size]: class ext4_extent_idx, size=12
class ext4_extent_header(BaseCode):
_fields = [
FieldType('uint16_t', 'eh_magic', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint16_t', 'eh_entries', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint16_t', 'eh_max', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint16_t', 'eh_depth', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint32_t', 'eh_generation', **{"raw_field": "__le32", "reverse": True} ),
]
# [calculate_size]: class ext4_extent_header, size=12
class ext4_inode(BaseCode):
_type_map = copy.deepcopy(BaseCode._type_map)
_type_map['ext4_extent'] = ('class', 'ext4_extent')
_type_map['ext4_extent_header'] = ('class', 'ext4_extent_header')
_type_map['ext4_extent_idx'] = ('class', 'ext4_extent_idx')
_fields = [
FieldType('uint16_t', 'i_mode', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint16_t', 'i_uid', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint32_t', 'i_size_lo', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 'i_atime', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 'i_ctime', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 'i_mtime', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 'i_dtime', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint16_t', 'i_gid', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint16_t', 'i_links_count', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint32_t', 'i_blocks_lo', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 'i_flags', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 'l_i_version', **{"raw_field": "__le32", "reverse": True} ), # union { struct {__le32 l_i_version;} linux1;} osd1;
# FieldType('uint32_t', 'h_i_translator', **{"raw_field": "__u32"} ), # union { struct {__u32 h_i_translator;} hurd1;} osd1;
# FieldType('uint32_t', 'm_i_reserved1', **{"raw_field": "__u32"} ), # union { struct {__u32 m_i_reserved1;} masix1;} osd1;
# FieldType('uint32_t', 'i_block[15]', **{"raw_field": "__le32", "reverse": True, "length": 15}),
FieldType('ext4_extent_header', 'i_block__ext4_extent_header', **{"raw_field": "struct ext4_extent_header"}),
FieldType('ext4_extent_idx', 'i_block__ext4_extent_idx', **{"raw_field": "struct ext4_extent_idx", "length": 4}),
FieldType('uint32_t', 'i_generation', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 'i_file_acl_lo', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 'i_size_high', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 'i_obso_faddr', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint16_t', 'l_i_blocks_high', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint16_t', 'l_i_file_acl_high', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint16_t', 'l_i_uid_high', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint16_t', 'l_i_gid_high', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint16_t', 'l_i_checksum_lo', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint16_t', 'l_i_reserved', **{"raw_field": "__le16", "reverse": True} ),
# FieldType('uint16_t', 'h_i_reserved1', **{"raw_field": "__le16", "reverse": True} ),
# FieldType('uint16_t', 'h_i_mode_high', **{"raw_field": "__u16"} ),
# FieldType('uint16_t', 'h_i_uid_high', **{"raw_field": "__u16"} ),
# FieldType('uint16_t', 'h_i_gid_high', **{"raw_field": "__u16"} ),
# FieldType('uint32_t', 'h_i_author', **{"raw_field": "__u32"} ),
# FieldType('uint16_t', 'h_i_reserved1', **{"raw_field": "__le16", "reverse": True} ),
# FieldType('uint16_t', 'm_i_file_acl_high', **{"raw_field": "__le16", "reverse": True} ),
# FieldType('uint32_t', 'm_i_reserved2[2]', **{"raw_field": "__u32", "length": 2} ),
FieldType('uint16_t', 'i_extra_isize', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint16_t', 'i_checksum_hi', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint32_t', 'i_ctime_extra', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 'i_mtime_extra', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 'i_atime_extra', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 'i_crtime', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 'i_crtime_extra', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 'i_version_hi', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 'i_projid', **{"raw_field": "__le32", "reverse": True} ),
]
# [calculate_size]: class ext4_inode, size=160
class ext4_super_block(BaseCode):
_fields = [
FieldType('uint32_t', 's_inodes_count', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_blocks_count_lo', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_r_blocks_count_lo', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_free_blocks_count_lo', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_free_inodes_count', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_first_data_block', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_log_block_size', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_log_cluster_size', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_blocks_per_group', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_clusters_per_group', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_inodes_per_group', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_mtime', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_wtime', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint16_t', 's_mnt_count', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint16_t', 's_max_mnt_count', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint16_t', 's_magic', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint16_t', 's_state', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint16_t', 's_errors', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint16_t', 's_minor_rev_level', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint32_t', 's_lastcheck', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_checkinterval', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_creator_os', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_rev_level', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint16_t', 's_def_resuid', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint16_t', 's_def_resgid', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint32_t', 's_first_ino', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint16_t', 's_inode_size', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint16_t', 's_block_group_nr', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint32_t', 's_feature_compat', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_feature_incompat', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_feature_ro_compat', **{"raw_field": "__le32", "reverse": True} ),
FieldType('char', 's_uuid', **{"raw_field": "__u8", "length": 16} ),
FieldType('char', 's_volume_name', **{"raw_field": "char", "length": 16} ),
FieldType('char', 's_last_mounted', **{"raw_field": "char", "length": 64} ),
FieldType('uint32_t', 's_algorithm_usage_bitmap', **{"raw_field": "__le32", "reverse": True} ),
FieldType('char', 's_prealloc_blocks', **{"raw_field": "__u8"} ),
FieldType('char', 's_prealloc_dir_blocks', **{"raw_field": "__u8"} ),
FieldType('uint16_t', 's_reserved_gdt_blocks', **{"raw_field": "__le16", "reverse": True} ),
FieldType('char', 's_journal_uuid', **{"raw_field": "__u8", "length": 16} ),
FieldType('uint32_t', 's_journal_inum', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_journal_dev', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_last_orphan', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_hash_seed', **{"raw_field": "__le32", "reverse": True, "length": 4}),
FieldType('char', 's_def_hash_version', **{"raw_field": "__u8"} ),
FieldType('char', 's_jnl_backup_type', **{"raw_field": "__u8"} ),
FieldType('uint16_t', 's_desc_size', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint32_t', 's_default_mount_opts', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_first_meta_bg', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_mkfs_time', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_jnl_blocks', **{"raw_field": "__le32", "reverse": True, "length": 17}),
FieldType('uint32_t', 's_blocks_count_hi', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_r_blocks_count_hi', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_free_blocks_count_hi', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint16_t', 's_min_extra_isize', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint16_t', 's_want_extra_isize', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint32_t', 's_flags', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint16_t', 's_raid_stride', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint16_t', 's_mmp_update_interval', **{"raw_field": "__le16", "reverse": True} ),
FieldType('uint64_t', 's_mmp_block', **{"raw_field": "__le64", "reverse": True} ),
FieldType('uint32_t', 's_raid_stripe_width', **{"raw_field": "__le32", "reverse": True} ),
FieldType('char', 's_log_groups_per_flex', **{"raw_field": "__u8"} ),
FieldType('char', 's_checksum_type', **{"raw_field": "__u8"} ),
FieldType('char', 's_encryption_level', **{"raw_field": "__u8"} ),
FieldType('char', 's_reserved_pad', **{"raw_field": "__u8"} ),
FieldType('uint64_t', 's_kbytes_written', **{"raw_field": "__le64", "reverse": True} ),
FieldType('uint32_t', 's_snapshot_inum', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_snapshot_id', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint64_t', 's_snapshot_r_blocks_count', **{"raw_field": "__le64", "reverse": True} ),
FieldType('uint32_t', 's_snapshot_list', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_error_count', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_first_error_time', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_first_error_ino', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint64_t', 's_first_error_block', **{"raw_field": "__le64", "reverse": True} ),
FieldType('char', 's_first_error_func', **{"raw_field": "__u8", "length": 32} ),
FieldType('uint32_t', 's_first_error_line', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_last_error_time', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_last_error_ino', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_last_error_line', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint64_t', 's_last_error_block', **{"raw_field": "__le64", "reverse": True} ),
FieldType('char', 's_last_error_func', **{"raw_field": "__u8", "length": 32} ),
FieldType('char', 's_mount_opts', **{"raw_field": "__u8", "length": 64} ),
FieldType('uint32_t', 's_usr_quota_inum', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_grp_quota_inum', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_overhead_clusters', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_backup_bgs', **{"raw_field": "__le32", "reverse": True, "length": 2}),
FieldType('char', 's_encrypt_algos', **{"raw_field": "__u8", "length": 4} ),
FieldType('char', 's_encrypt_pw_salt', **{"raw_field": "__u8", "length": 16} ),
FieldType('uint32_t', 's_lpf_ino', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_prj_quota_inum', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_checksum_seed', **{"raw_field": "__le32", "reverse": True} ),
FieldType('uint32_t', 's_reserved', **{"raw_field": "__le32", "reverse": True, "length": 98}),
FieldType('uint32_t', 's_checksum', **{"raw_field": "__le32", "reverse": True} ),
]
# [calculate_size]: class ext4_super_block, size=1024
def size_calc():
ext4_super_block().calculate_size(True)
if __name__ == '__main__':
size_calc()
__all__ = (
# 'ext4_extent',
# 'ext4_extent_idx',
# 'ext4_extent_header',
'ext4_inode',
'ext4_super_block',
'size_calc',
)
source.c
struct ext4_super_block {
/*00*/ __le32 s_inodes_count; /* Inodes count */
__le32 s_blocks_count_lo; /* Blocks count */
__le32 s_r_blocks_count_lo; /* Reserved blocks count */
__le32 s_free_blocks_count_lo; /* Free blocks count */
/*10*/ __le32 s_free_inodes_count; /* Free inodes count */
__le32 s_first_data_block; /* First Data Block */
__le32 s_log_block_size; /* Block size */
__le32 s_log_cluster_size; /* Allocation cluster size */
/*20*/ __le32 s_blocks_per_group; /* # Blocks per group */
__le32 s_clusters_per_group; /* # Clusters per group */
__le32 s_inodes_per_group; /* # Inodes per group */
__le32 s_mtime; /* Mount time */
/*30*/ __le32 s_wtime; /* Write time */
__le16 s_mnt_count; /* Mount count */
__le16 s_max_mnt_count; /* Maximal mount count */
__le16 s_magic; /* Magic signature */
__le16 s_state; /* File system state */
__le16 s_errors; /* Behaviour when detecting errors */
__le16 s_minor_rev_level; /* minor revision level */
/*40*/ __le32 s_lastcheck; /* time of last check */
__le32 s_checkinterval; /* max. time between checks */
__le32 s_creator_os; /* OS */
__le32 s_rev_level; /* Revision level */
/*50*/ __le16 s_def_resuid; /* Default uid for reserved blocks */
__le16 s_def_resgid; /* Default gid for reserved blocks */
/*
* These fields are for EXT4_DYNAMIC_REV superblocks only.
*
* Note: the difference between the compatible feature set and
* the incompatible feature set is that if there is a bit set
* in the incompatible feature set that the kernel doesn't
* know about, it should refuse to mount the filesystem.
*
* e2fsck's requirements are more strict; if it doesn't know
* about a feature in either the compatible or incompatible
* feature set, it must abort and not try to meddle with
* things it doesn't understand...
*/
__le32 s_first_ino; /* First non-reserved inode */
__le16 s_inode_size; /* size of inode structure */
__le16 s_block_group_nr; /* block group # of this superblock */
__le32 s_feature_compat; /* compatible feature set */
/*60*/ __le32 s_feature_incompat; /* incompatible feature set */
__le32 s_feature_ro_compat; /* readonly-compatible feature set */
/*68*/ __u8 s_uuid[16]; /* 128-bit uuid for volume */
/*78*/ char s_volume_name[16]; /* volume name */
/*88*/ char s_last_mounted[64]; /* directory where last mounted */
/*C8*/ __le32 s_algorithm_usage_bitmap; /* For compression */
/*
* Performance hints. Directory preallocation should only
* happen if the EXT4_FEATURE_COMPAT_DIR_PREALLOC flag is on.
*/
__u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
__u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
__le16 s_reserved_gdt_blocks; /* Per group desc for online growth */
/*
* Journaling support valid if EXT4_FEATURE_COMPAT_HAS_JOURNAL set.
*/
/*D0*/ __u8 s_journal_uuid[16]; /* uuid of journal superblock */
/*E0*/ __le32 s_journal_inum; /* inode number of journal file */
__le32 s_journal_dev; /* device number of journal file */
__le32 s_last_orphan; /* start of list of inodes to delete */
__le32 s_hash_seed[4]; /* HTREE hash seed */
__u8 s_def_hash_version; /* Default hash version to use */
__u8 s_jnl_backup_type;
__le16 s_desc_size; /* size of group descriptor */
/*100*/ __le32 s_default_mount_opts;
__le32 s_first_meta_bg; /* First metablock block group */
__le32 s_mkfs_time; /* When the filesystem was created */
__le32 s_jnl_blocks[17]; /* Backup of the journal inode */
/* 64bit support valid if EXT4_FEATURE_COMPAT_64BIT */
/*150*/ __le32 s_blocks_count_hi; /* Blocks count */
__le32 s_r_blocks_count_hi; /* Reserved blocks count */
__le32 s_free_blocks_count_hi; /* Free blocks count */
__le16 s_min_extra_isize; /* All inodes have at least # bytes */
__le16 s_want_extra_isize; /* New inodes should reserve # bytes */
__le32 s_flags; /* Miscellaneous flags */
__le16 s_raid_stride; /* RAID stride */
__le16 s_mmp_update_interval; /* # seconds to wait in MMP checking */
__le64 s_mmp_block; /* Block for multi-mount protection */
__le32 s_raid_stripe_width; /* blocks on all data disks (N*stride)*/
__u8 s_log_groups_per_flex; /* FLEX_BG group size */
__u8 s_checksum_type; /* metadata checksum algorithm used */
__u8 s_encryption_level; /* versioning level for encryption */
__u8 s_reserved_pad; /* Padding to next 32bits */
__le64 s_kbytes_written; /* nr of lifetime kilobytes written */
__le32 s_snapshot_inum; /* Inode number of active snapshot */
__le32 s_snapshot_id; /* sequential ID of active snapshot */
__le64 s_snapshot_r_blocks_count; /* reserved blocks for active
snapshot's future use */
__le32 s_snapshot_list; /* inode number of the head of the
on-disk snapshot list */
__le32 s_error_count; /* number of fs errors */
__le32 s_first_error_time; /* first time an error happened */
__le32 s_first_error_ino; /* inode involved in first error */
__le64 s_first_error_block; /* block involved of first error */
__u8 s_first_error_func[32]; /* function where the error happened */
__le32 s_first_error_line; /* line number where error happened */
__le32 s_last_error_time; /* most recent time of an error */
__le32 s_last_error_ino; /* inode involved in last error */
__le32 s_last_error_line; /* line number where error happened */
__le64 s_last_error_block; /* block involved of last error */
__u8 s_last_error_func[32]; /* function where the error happened */
__u8 s_mount_opts[64];
__le32 s_usr_quota_inum; /* inode for tracking user quota */
__le32 s_grp_quota_inum; /* inode for tracking group quota */
__le32 s_overhead_clusters; /* overhead blocks/clusters in fs */
__le32 s_backup_bgs[2]; /* groups with sparse_super2 SBs */
__u8 s_encrypt_algos[4]; /* Encryption algorithms in use */
__u8 s_encrypt_pw_salt[16]; /* Salt used for string2key algorithm */
__le32 s_lpf_ino; /* Location of the lost+found inode */
__le32 s_prj_quota_inum; /* inode for tracking project quota */
__le32 s_checksum_seed; /* crc32c(uuid) if csum_seed set */
__le32 s_reserved[98]; /* Padding to the end of the block */
__le32 s_checksum; /* crc32c(superblock) */
};
basecode_gen_ccode.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
from basecode import *
## 需要注释掉basecode里的 from basecode_structs import *
# python basecode.py -s source.c 单独拎出来
if __name__ == '__main__':
# gernel_test()
src_code = "source.c"
src_file = open(src_code, mode='r', encoding="utf8")
ccode = src_file.read()
ccode_result, class_name = FormatDecoder.parse_struct(ccode)
exec(ccode_result)
exec("%s().calculate_size(True)" % class_name)
# loc = locals()
# test_class = loc[class_name]
# print(test_class) # <class '__main__.ext_extent'>
# exec("%s.__init__().calculate_size()" % test_class) # 不行
hexdump.rst
00000000 a0 81 00 00 18 1b 00 00 13 e4 15 62 59 e4 15 62 |...........bY..b|
00000010 59 e4 15 62 00 00 00 00 00 00 01 00 10 00 00 00 |Y..b............|
00000020 00 00 08 00 01 00 00 00 0a f3 02 00 04 00 00 00 |................|
00000030 00 00 00 00 00 00 00 00 01 00 00 00 00 88 00 00 |................|
00000040 01 00 00 00 01 00 00 00 00 8a 00 00 00 00 00 00 |................|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000060 00 00 00 00 05 03 ac b3 00 00 00 00 00 00 00 00 |................|
00000070 00 00 00 00 00 00 00 00 00 00 00 00 67 e3 00 00 |............g...|
00000080 20 00 e9 a2 28 aa 96 d7 28 aa 96 d7 ac da c4 43 | ...(...(......C|
00000090 13 e4 15 62 ac da c4 43 00 00 00 00 00 00 00 00 |...b...C........|
测试效果
python basecode.py -c ext4_inode -r hexdump
[parse_hexdump_rst]: b'\xa0\x81\x00\x00\x18\x1b\x00\x00\x13\xe4\x15bY\xe4\x15bY\xe4\x15b\x00\x00\x00\x00\x00\x00\x01\x00\x10\x00\x00\x00\x00\x00\x08\x00\x01\x00\x00\x00\n\xf3\x02\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x88\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x8a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x03\xac\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00g\xe3\x00\x00 \x00\xe9\xa2(\xaa\x96\xd7(\xaa\x96\xd7\xac\xda\xc4C\x13\xe4\x15b\xac\xda\xc4C\x00\x00\x00\x00\x00\x00\x00\x00'
struct ext4_inode {
__le16 i_mode : a0 81 : 0x81a0 : 33184
__le16 i_uid : 00 00 : 0x0000 : 0
__le32 i_size_lo : 18 1b 00 00 : 0x00001b18 : 6936
__le32 i_atime : 13 e4 15 62 : 0x6215e413 : 1645601811 : 2022-02-23 15:36:51
__le32 i_ctime : 59 e4 15 62 : 0x6215e459 : 1645601881 : 2022-02-23 15:38:01
__le32 i_mtime : 59 e4 15 62 : 0x6215e459 : 1645601881 : 2022-02-23 15:38:01
__le32 i_dtime : 00 00 00 00 : 0x00000000 : 0 : 1970-01-01 08:00:00
__le16 i_gid : 00 00 : 0x0000 : 0
__le16 i_links_count : 01 00 : 0x0001 : 1
__le32 i_blocks_lo : 10 00 00 00 : 0x00000010 : 16
__le32 i_flags : 00 00 08 00 : 0x00080000 : 524288
__le32 l_i_version : 01 00 00 00 : 0x00000001 : 1
struct ext4_extent_header : 0a f3 02 00 04 00 00 00 00 00 00 00 : sizeof=12
struct ext4_extent_idx : 00 00 00 00 01 00 00 00 00 88 00 00 : sizeof=12
struct ext4_extent_idx : 01 00 00 00 01 00 00 00 00 8a 00 00 : sizeof=12
struct ext4_extent_idx : 00 00 00 00 00 00 00 00 00 00 00 00 : sizeof=12
struct ext4_extent_idx : 00 00 00 00 00 00 00 00 00 00 00 00 : sizeof=12
__le32 i_generation : 05 03 ac b3 : 0xb3ac0305 : 3014394629
__le32 i_file_acl_lo : 00 00 00 00 : 0x00000000 : 0
__le32 i_size_high : 00 00 00 00 : 0x00000000 : 0
__le32 i_obso_faddr : 00 00 00 00 : 0x00000000 : 0
__le16 l_i_blocks_high : 00 00 : 0x0000 : 0
__le16 l_i_file_acl_high : 00 00 : 0x0000 : 0
__le16 l_i_uid_high : 00 00 : 0x0000 : 0
__le16 l_i_gid_high : 00 00 : 0x0000 : 0
__le16 l_i_checksum_lo : 67 e3 : 0xe367 : 58215
__le16 l_i_reserved : 00 00 : 0x0000 : 0
__le16 i_extra_isize : 20 00 : 0x0020 : 32
__le16 i_checksum_hi : e9 a2 : 0xa2e9 : 41705
__le32 i_ctime_extra : 28 aa 96 d7 : 0xd796aa28 : 3616975400
__le32 i_mtime_extra : 28 aa 96 d7 : 0xd796aa28 : 3616975400
__le32 i_atime_extra : ac da c4 43 : 0x43c4daac : 1136974508
__le32 i_crtime : 13 e4 15 62 : 0x6215e413 : 1645601811 : 2022-02-23 15:36:51
__le32 i_crtime_extra : ac da c4 43 : 0x43c4daac : 1136974508
__le32 i_version_hi : 00 00 00 00 : 0x00000000 : 0
__le32 i_projid : 00 00 00 00 : 0x00000000 : 0
}
>>> extend instances :
struct ext4_extent_header {
__le16 eh_magic : 0a f3 : 0xf30a : 62218
__le16 eh_entries : 02 00 : 0x0002 : 2
__le16 eh_max : 04 00 : 0x0004 : 4
__le16 eh_depth : 00 00 : 0x0000 : 0
__le32 eh_generation : 00 00 00 00 : 0x00000000 : 0
}
struct ext4_extent_idx {
__le32 ei_block : 00 00 00 00 : 0x00000000 : 0
__le32 ei_leaf_lo : 01 00 00 00 : 0x00000001 : 1
__le16 ei_leaf_hi : 00 88 : 0x8800 : 34816
__u16 ei_unused : 00 00 : 0x0000 : 0
}
struct ext4_extent_idx {
__le32 ei_block : 01 00 00 00 : 0x00000001 : 1
__le32 ei_leaf_lo : 01 00 00 00 : 0x00000001 : 1
__le16 ei_leaf_hi : 00 8a : 0x8a00 : 35328
__u16 ei_unused : 00 00 : 0x0000 : 0
}
struct ext4_extent_idx {
__le32 ei_block : 00 00 00 00 : 0x00000000 : 0
__le32 ei_leaf_lo : 00 00 00 00 : 0x00000000 : 0
__le16 ei_leaf_hi : 00 00 : 0x0000 : 0
__u16 ei_unused : 00 00 : 0x0000 : 0
}
struct ext4_extent_idx {
__le32 ei_block : 00 00 00 00 : 0x00000000 : 0
__le32 ei_leaf_lo : 00 00 00 00 : 0x00000000 : 0
__le16 ei_leaf_hi : 00 00 : 0x0000 : 0
__u16 ei_unused : 00 00 : 0x0000 : 0
}
vi -b ttt1 然后 :%!xxd 转换成十六进制,复制其中的文本出来 hexdump -Cv ttt1
00000400: 0000 6400 0000 9001 0000 1400 e87c 8701 ..d..........|..
00000410: f5ff 6300 0000 0000 0200 0000 0200 0000 ..c.............
00000420: 0080 0000 0080 0000 0020 0000 766f b763 ......... ..vo.c
00000430: 766f b763 0100 ffff 53ef 0100 0100 0000 vo.c....S.......
00000440: 3f6f b763 0000 0000 0000 0000 0100 0000 ?o.c............
00000450: 0000 0000 0b00 0000 0001 0000 3c00 0000 ............<...
00000460: c602 0000 6b04 0000 40a8 8b44 4017 470d ....k...@..D@.G.
00000470: 8790 4978 b37c de41 0000 0000 0000 0000 ..Ix.|.A........
00000480: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000490: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000004a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000004b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000004c0: 0000 0000 0000 0000 0000 0000 0000 0004 ................
000004d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000004e0: 0800 0000 0000 0000 0000 0000 4543 2fa5 ............EC/.
000004f0: 4baf 41ee b0ea 8ae1 b57a 0f20 0101 4000 K.A......z. ..@.
00000500: 0c00 0000 0000 0000 3f6f b763 0af3 0400 ........?o.c....
00000510: 0400 0000 0000 0000 0000 0000 0080 0000 ................
00000520: 0080 c800 0080 0000 0080 0000 0000 c900 ................
00000530: 0000 0100 0080 0000 0080 c900 0080 0100 ................
00000540: 0080 0000 0000 ca00 0000 0000 0000 0020 ...............
00000550: 0000 0000 0000 0000 0000 0000 2000 2000 ............ . .
00000560: 0100 0000 0000 0000 0000 0000 0000 0000 ................
00000570: 0000 0000 0401 0000 ec10 0000 0000 0000 ................
00000580: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000590: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000005a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000005b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000005c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000005d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000005e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000005f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000600: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000610: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000620: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000630: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000640: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000650: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000660: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000670: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000680: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000690: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000006a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000006b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000006c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000006d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000006e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000006f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000700: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000710: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000720: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000730: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000740: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000750: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000760: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000770: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000780: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000790: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000007a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000007b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000007c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000007d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000007e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000007f0: 0000 0000 0000 0000 0000 0000 29b6 1249 ............)..I
结果为
[parse_vib2xxd_rst]: b'\x00\x00d\x00\x00\x00\x90\x01\x00\x00\x14\x00\xe8|\x87\x01\xf5\xffc\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00 \x00\x00vo\xb7cvo\xb7c\x01\x00\xff\xffS\xef\x01\x00\x01\x00\x00\x00?o\xb7c\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00\x00\x01\x00\x00<\x00\x00\x00\xc6\x02\x00\x00k\x04\x00\x00@\xa8\x8bD@\x17G\r\x87\x90Ix\xb3|\xdeA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00EC/\xa5K\xafA\xee\xb0\xea\x8a\xe1\xb5z\x0f \x01\x01@\x00\x0c\x00\x00\x00\x00\x00\x00\x00?o\xb7c\n\xf3\x04\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x80\xc8\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\x00\xc9\x00\x00\x00\x01\x00\x00\x80\x00\x00\x00\x80\xc9\x00\x00\x80\x01\x00\x00\x80\x00\x00\x00\x00\xca\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00 \x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x01\x00\x00\xec\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00)\xb6\x12I'
struct ext4_super_block {
__le32 s_inodes_count : 00 00 64 00 : 0x00640000 : 6553600
__le32 s_blocks_count_lo : 00 00 90 01 : 0x01900000 : 26214400
__le32 s_r_blocks_count_lo : 00 00 14 00 : 0x00140000 : 1310720
__le32 s_free_blocks_count_lo : e8 7c 87 01 : 0x01877ce8 : 25656552
__le32 s_free_inodes_count : f5 ff 63 00 : 0x0063fff5 : 6553589
__le32 s_first_data_block : 00 00 00 00 : 0x00000000 : 0
__le32 s_log_block_size : 02 00 00 00 : 0x00000002 : 2
__le32 s_log_cluster_size : 02 00 00 00 : 0x00000002 : 2
__le32 s_blocks_per_group : 00 80 00 00 : 0x00008000 : 32768
__le32 s_clusters_per_group : 00 80 00 00 : 0x00008000 : 32768
__le32 s_inodes_per_group : 00 20 00 00 : 0x00002000 : 8192
__le32 s_mtime : 76 6f b7 63 : 0x63b76f76 : 1672966006 : 2023-01-06 08:46:46
__le32 s_wtime : 76 6f b7 63 : 0x63b76f76 : 1672966006 : 2023-01-06 08:46:46
__le16 s_mnt_count : 01 00 : 0x0001 : 1
__le16 s_max_mnt_count : ff ff : 0xffff : 65535
__le16 s_magic : 53 ef : 0xef53 : 61267
__le16 s_state : 01 00 : 0x0001 : 1
__le16 s_errors : 01 00 : 0x0001 : 1
__le16 s_minor_rev_level : 00 00 : 0x0000 : 0
__le32 s_lastcheck : 3f 6f b7 63 : 0x63b76f3f : 1672965951
__le32 s_checkinterval : 00 00 00 00 : 0x00000000 : 0
__le32 s_creator_os : 00 00 00 00 : 0x00000000 : 0
__le32 s_rev_level : 01 00 00 00 : 0x00000001 : 1
__le16 s_def_resuid : 00 00 : 0x0000 : 0
__le16 s_def_resgid : 00 00 : 0x0000 : 0
__le32 s_first_ino : 0b 00 00 00 : 0x0000000b : 11
__le16 s_inode_size : 00 01 : 0x0100 : 256
__le16 s_block_group_nr : 00 00 : 0x0000 : 0
__le32 s_feature_compat : 3c 00 00 00 : 0x0000003c : 60
__le32 s_feature_incompat : c6 02 00 00 : 0x000002c6 : 710
__le32 s_feature_ro_compat : 6b 04 00 00 : 0x0000046b : 1131
__u8 s_uuid : 40 a8 8b 44 40 ...b3 7c de 41 : 0x40a88b444017470d...b37cde41 : @¨�D@�G��Ix³|ÞA
char s_volume_name : 00 00 00 00 00 ...00 00 00 00 : 0x0000000000000000...00000000 :
char s_last_mounted : 00 00 00 00 00 ...00 00 00 00 : 0x0000000000000000...00000000 :
__le32 s_algorithm_usage_bitmap : 00 00 00 00 : 0x00000000 : 0
__u8 s_prealloc_blocks : 00 : 0x00 : 0
__u8 s_prealloc_dir_blocks : 00 : 0x00 : 0
__le16 s_reserved_gdt_blocks : 00 04 : 0x0400 : 1024
__u8 s_journal_uuid : 00 00 00 00 00 ...00 00 00 00 : 0x0000000000000000...00000000 :
__le32 s_journal_inum : 08 00 00 00 : 0x00000008 : 8
__le32 s_journal_dev : 00 00 00 00 : 0x00000000 : 0
__le32 s_last_orphan : 00 00 00 00 : 0x00000000 : 0
__le32 s_hash_seed : 45 43 2f a5 4b ...b5 7a 0f 20 : 0x200f7ab5e18aeab0...a52f4345 : [2771338053, 3997282123, 3783977648, 537885365]
__u8 s_def_hash_version : 01 : 0x01 : 1
__u8 s_jnl_backup_type : 01 : 0x01 : 1
__le16 s_desc_size : 40 00 : 0x0040 : 64
__le32 s_default_mount_opts : 0c 00 00 00 : 0x0000000c : 12
__le32 s_first_meta_bg : 00 00 00 00 : 0x00000000 : 0
__le32 s_mkfs_time : 3f 6f b7 63 : 0x63b76f3f : 1672965951 : 2023-01-06 08:45:51
__le32 s_jnl_blocks : 0a f3 04 00 04 ...00 00 00 20 : 0x2000000000000000...0004f30a : [324362, 4, 0, 0, 32768, 13139968, 32768, 32768, 13172736, 65536, 32768, 13205504, 98304, 32768, 13238272, 0, 536870912]
__le32 s_blocks_count_hi : 00 00 00 00 : 0x00000000 : 0
__le32 s_r_blocks_count_hi : 00 00 00 00 : 0x00000000 : 0
__le32 s_free_blocks_count_hi : 00 00 00 00 : 0x00000000 : 0
__le16 s_min_extra_isize : 20 00 : 0x0020 : 32
__le16 s_want_extra_isize : 20 00 : 0x0020 : 32
__le32 s_flags : 01 00 00 00 : 0x00000001 : 1
__le16 s_raid_stride : 00 00 : 0x0000 : 0
__le16 s_mmp_update_interval : 00 00 : 0x0000 : 0
__le64 s_mmp_block : 00 00 00 00 00 00 00 00 : 0x0000000000000000 : 0
__le32 s_raid_stripe_width : 00 00 00 00 : 0x00000000 : 0
__u8 s_log_groups_per_flex : 04 : 0x04 : 4
__u8 s_checksum_type : 01 : 0x01 : 1
__u8 s_encryption_level : 00 : 0x00 : 0
__u8 s_reserved_pad : 00 : 0x00 : 0
__le64 s_kbytes_written : ec 10 00 00 00 00 00 00 : 0x00000000000010ec : 4332
__le32 s_snapshot_inum : 00 00 00 00 : 0x00000000 : 0
__le32 s_snapshot_id : 00 00 00 00 : 0x00000000 : 0
__le64 s_snapshot_r_blocks_count : 00 00 00 00 00 00 00 00 : 0x0000000000000000 : 0
__le32 s_snapshot_list : 00 00 00 00 : 0x00000000 : 0
__le32 s_error_count : 00 00 00 00 : 0x00000000 : 0
__le32 s_first_error_time : 00 00 00 00 : 0x00000000 : 0 : 1970-01-01 08:00:00
__le32 s_first_error_ino : 00 00 00 00 : 0x00000000 : 0
__le64 s_first_error_block : 00 00 00 00 00 00 00 00 : 0x0000000000000000 : 0
__u8 s_first_error_func : 00 00 00 00 00 ...00 00 00 00 : 0x0000000000000000...00000000 :
__le32 s_first_error_line : 00 00 00 00 : 0x00000000 : 0
__le32 s_last_error_time : 00 00 00 00 : 0x00000000 : 0 : 1970-01-01 08:00:00
__le32 s_last_error_ino : 00 00 00 00 : 0x00000000 : 0
__le32 s_last_error_line : 00 00 00 00 : 0x00000000 : 0
__le64 s_last_error_block : 00 00 00 00 00 00 00 00 : 0x0000000000000000 : 0
__u8 s_last_error_func : 00 00 00 00 00 ...00 00 00 00 : 0x0000000000000000...00000000 :
__u8 s_mount_opts : 00 00 00 00 00 ...00 00 00 00 : 0x0000000000000000...00000000 :
__le32 s_usr_quota_inum : 00 00 00 00 : 0x00000000 : 0
__le32 s_grp_quota_inum : 00 00 00 00 : 0x00000000 : 0
__le32 s_overhead_clusters : 00 00 00 00 : 0x00000000 : 0
__le32 s_backup_bgs : 00 00 00 00 00 00 00 00 : 0x0000000000000000 : [0, 0]
__u8 s_encrypt_algos : 00 00 00 00 : 0x00000000 :
__u8 s_encrypt_pw_salt : 00 00 00 00 00 ...00 00 00 00 : 0x0000000000000000...00000000 :
__le32 s_lpf_ino : 00 00 00 00 : 0x00000000 : 0
__le32 s_prj_quota_inum : 00 00 00 00 : 0x00000000 : 0
__le32 s_checksum_seed : 00 00 00 00 : 0x00000000 : 0
__le32 s_reserved : 00 00 00 00 00 ...00 00 00 00 : 0x0000000000000000...00000000 : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
__le32 s_checksum : 29 b6 12 49 : 0x4912b629 : 1225963049
}
basecode_decode_bytes.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
from basecode import *
# python basecode.py -c ext4_extent -h "10 00 00 00 01 00 02 00 1E 86 00 00" 单独拎出来
def decode_hex(class_type, hex_input):
loc = locals()
try:
exec("test_obj = {}()".format(class_type))
except NameError:
print('param <class> %s is not existed.' % class_type)
print('%s -c <class> -h <hex chars input>' % sys.argv[0])
exit(1)
test_obj = loc['test_obj']
test_obj_size = test_obj.calculate_size()
formater = FormatDecoder('input')
input_bytes, input_length = formater.parse_chr_array_2_bytes(hex_input)
if input_length < test_obj_size:
print("input hex size [%s] less than sizeof(%s)=[%s]" % (input_length, class_type, test_obj_size))
exit(1)
elif input_length > test_obj_size:
print("input hex size [%s] more than sizeof(%s)=[%s], " % (input_length, class_type, test_obj_size))
input_bytes = input_bytes[:test_obj_size]
print("only use the previous required data: %s" % input_bytes)
test_obj.decode(input_bytes)
# test_obj.tojson_print1()
test_obj.print_cmp_with_hex(formater.parse_chr_array_2_hex_list(hex_input))
def test01():
class_type = "ext4_extent"
hex_input = "10 00 00 00 01 00 02 00 1E 86 00 00"
decode_hex(class_type, hex_input)
"""
以这个inode=18为例,来研究extent_tree吧
00000120 00 00 08 00 01 00 00 00 0a f3 01 00 04 00 00 00 |................|
00000130 00 00 00 00 00 00 00 00 04 00 00 00 b0 84 00 00 |................|
00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000160 00 00 00 00
debugfs: stat <18>
EXTENTS:
(0-3):33968-33971
"""
if __name__ == '__main__':
class_type = "ext4_extent_header"
hex_input = "0a f3 01 00 04 00 00 00 00 00 00 00"
decode_hex(class_type, hex_input)
class_type = "ext4_extent_idx"
hex_input = "00 00 00 00 04 00 00 00 b0 84 00 00 "
decode_hex(class_type, hex_input)
C结构体转换为python工具