Go【No-10】结构体

Go语言没有类,但通过结构体实现面向对象编程。结构体是值类型,可以通过定义、实例化、初始化、添加方法等方式操作。结构体的内存布局是连续的,支持匿名字段和嵌套结构体。结构体标签提供元信息,可用于序列化。结构体的深浅拷贝取决于赋值方式:值类型深拷贝,引用类型浅拷贝。

10-结构体

Go语言中没有“类”的概念,也不支持“类”的继承等面向对象的概念。Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性。

当我们想表示一些事物时,我们可以用基本数据类型表示其各项基本属性,通过结构体将其组合起来。在 Go 中可以通过 struct 实现面向对象。

定义

注意:结构体是值类型!!!

使用 typestruct 来定义结构体。

基本语法如下:

type structT struct {
   
   
    field1 T
    field2 T
    ...
}

structT:标识只定义结构体名称,同一包内不能重复。
field:结构的基本属性的名字,结构体中的字段名不能重复
T:字段的具体类型

eg:

type person struct {
   
   
    name string
    age int8
    city string
}

同类型字段可以写在一行

type person struct {
   
   
    name, city string
    age int8
}

通过以上代码,我们就可以得到一个 person 的自定义类型,它有 nameagecity 三个字段,表示人的姓名、年龄、城市三个属性。
这样就可以通过 person 这个结构体很方便的在程序中表示和存储人的信息了。

在定义结构体时,建议各个字段按字段类型从小到大排序,有助于内存对齐
类型大小参考《数据类型》一章

Go 内置的基本数据类型用来描述一个值,而结构体用来描述一组值,本质上是一种聚合型数据类型。

一个结构体就像 Java 中的一个类,不过 Java 中的类还有构造函数、方法等,这些 Go 的结构体一样可以实现,方式有些不同

实例化

只有当结构体实例化时,才会真正地分配内存。即必须实例化后才能使用结构体的字段。

结构体本身也是一种数据类型,我们可以像声明基本数据类型一样声明结构体

// 方式1
var identifier structT
identifier.field1 = value1
identifier.field2 = value2
...

identifier:结构体实例名称
structT:结构体类型
field:结构体字段

方式1:基本实例化

type person struct {
   
   
    name string
    city string
    age int8
}

func main() {
   
   
    // 方式1
    var p1 person
    p1.city = "SWA"
    p1.name = "Boii"

    fmt.Printf("p1 = %v \n", p1)	// p1 = {Boii 0 SWA}
    fmt.Printf("p1 = %#v \n", p1)	// p1 = main.person{name:"Boii", age:0, city:"SWA"}
}

仔细观察:

  • 方式1声明以后逐一给每个字段赋值,可以结构体中定义字段时的顺序,没有赋值的字段默认为零值
  • 方式2 和 方式3在赋值的时候需要所有字段都赋值,且需要按顺序。
  • 通过.可以访问结构体中的字段,例如p1.city.

方式2:new(T) 结构体指针

通过内置函数 new() 可以对结构体实例化,得到的是结构体指针,其各个字段都为零值。

type person struct {
   
   
    name string
    city string
    age  int8
}
func main() {
   
   

	var p1 = new(person)
	fmt.Printf("%T \n", p1)      // *main.person
	fmt.Printf("p1 = %#v \n", p1) // p1 = &main.person{name:"", age:0, city:""}
	
	p1.name = "Boii"
	fmt.Printf("p1 = %#v \n", p1) // p1 = &main.person{name:"Boii", age:0, city:""}
}

注意:Go 中的结构体指针可以直接使用.来访问结构体成员。
p1.name = "Boii" 相当于 (*p1).name = "Boii",这是 Go 的语法糖。

方式3:&T{} 取结构体地址

使用 & 对结构体取地址操作相当于对该结构体类型进行了一次 new实例化操作。

type person struct {
   
   
    name string
    city string
    age  int8
}
func main() {
   
   
    var p2 = &person{
   
   "Boii", 10, "SWA"}
	fmt.Printf("%T \n", p2)       // *main.person
	fmt.Printf("p2 = %#v \n", p2) // p = &main.person{name:"Boii", age:10, city:"SWA"}

    p3 := &person{
   
   }
	p3.name = "Candy"
	p3.age = 10
	p3.city = "SWA"
	fmt.Printf("%T \n", p3)       // *main.person
	fmt.Printf("p3 = %#v \n", p3) // p = &main.person{name:"Candy", age:10, city:"SWA"}

}

所以:new(Type)&Type{} 是等价的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wlq9mjvG-1613447299933)(IMG/20201122164056342_11482.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sHqaGqDN-1613447299939)(IMG/20201122164122020_21432.png)]

匿名结构体

在定义一些临时数据结构等场景下还可以使用匿名结构体。

func main() {
   
   
    // 定义匿名结构体
    // 字段之间用 分号 隔开
    var user struct{
   
   name string; age int8
import tkinter as tk from tkinter import filedialog import os import re import sys from elftools.elf.elffile import ELFFile import subprocess import json # 确定应用程序是脚本文件还是被冻结的exe if getattr(sys, 'frozen', False): # 获取应用程序exe的路径 pathorigin = os.path.dirname(sys.executable) elif __file__: # 获取脚本程序的路径 pathorigin = os.path.dirname(__file__) #--寻找当前路径下的path_config文件 path_config_path = os.path.join(pathorigin, 'path_config.json') print(path_config_path) # config_path = config_path.replace('\\','\\\\') # 读取JSON文件并加载为字典 with open(path_config_path, 'r', encoding='utf-8') as f:# ConfigPath_dict = json.load(f) A2LUpdata_fold = ConfigPath_dict['A2LUpdata_fold'] def parseDwarfOutput(elfFileName,path11):#根据elf生成dwarf path = os.path.dirname(os.path.abspath(__file__)) #print(path) ps = subprocess.Popen(path11 + "\\objdump --dwarf=info " + elfFileName, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) dwarf = ps.communicate()[0].decode('latin-1') #print with open(os.path.join(A2LUpdata_fold, 'dwarf_info1.txt'), "w", encoding='utf-8') as dwarfFile: dwarfFile.write(dwarf) def extract_type11_10(s): # 使用 . 分割字符串 parts = s.split('.') # 检查是否正好有三部分 if len(parts) == 3: third_part = parts[2]#------这里进行a.b.c[x]形式的判断 if ('[' not in parts[0]): # 检查第三部分是否包含 [ if '[' in third_part: # 找到 [ 的位置 left_bracket_index = third_part.find('[') # 找到 ] 的位置 right_bracket_index = third_part.find(']', left_bracket_index) # 提取 [ 左边和 [] 中间的内容 if left_bracket_index != -1 and right_bracket_index != -1: content_before_bracket = third_part[:left_bracket_index] content_inside_brackets = third_part[left_bracket_index + 1:right_bracket_index] return '10',parts[0],parts[1],content_before_bracket, content_inside_brackets if(('[' not in parts[0]) and ('[' not in parts[1]) and ('[' not in parts[2])): return '11',parts[0],parts[1],parts[2],None return None,None,None,None,None def extract_components9(input_string):#A[X].B[Y].C,匹配出ABCXY # 定义正则表达式 pattern = r"^([^\[\]]+)\[([^\[\]]+)\]\.([^\[\]]+)\[([^\[\]]+)\]\.([^\[\]]+)$" flag = 0 A = 'null' B = 'null' C = 'null' X = 'null' Y = 'null' # 匹配字符串 match = re.match(pattern, input_string) if match: # 提取匹配的组 A = match.group(1) X = match.group(2) B = match.group(3) Y = match.group(4) C = match.group(5) flag = 9 return flag,A, B, C, X, Y def extract_components(s): # 统计 '.' 和 '[' 的数量 dot_count = s.count('.') bracket_count = s.count('[') a = 'null' x = 'null' b = 'null' c = 'null' y = 'null' flag = 'null' flag,a, b, c, x, y = extract_components9(s) # 如果存在两个 '.' if flag == 9: flag = 9 elif dot_count == 2: # 匹配 a[x].b.c[y] 格式 match = re.match(r'^([^\[\].]+)\[([^\[\]]+)\]\.([^\[\].]+)\.([^\[\].]+)\[([^\[\]]+)\]$', s) if match: a, x, b, c, y = match.groups() flag = '8' # 如果存在两个 '[' elif bracket_count == 2: # 匹配 a[x][y].b 格式 match = re.match(r'^([^\[\].]+)\[([^\[\]]+)\]\[([^\[\]]+)\]\.([^\[\].]+)$', s) if match: a, x, y, b = match.groups() flag = '6' # 其他情况(默认匹配 a[x].b 格式) else: # 匹配 a[x].b 格式 match = re.match(r'^([^\[\].]+)\[([^\[\]]+)\]\.([^\[\].]+)$', s) if match: a, x, b = match.groups() flag = '5' return a,x,b,c,y,flag def check_bracket_before_first_dot(s): # 找到第一个 '.' 的位置 dot_index = s.find('.') # 如果不存在 '.',直接返回标志位 0 if dot_index == -1: return 0 # 检查第一个 '.' 之前是否有 '[' if '[' in s[:dot_index]: return 1 # 标志位为 1 else: return 0 # 标志位为 0 def parse_name(name): flag = 'null' a = 'null' b = 'null' x = 'null' y = 'null' c = 'null' d = 'null' z = 'null' # 定义正则表达式匹配规则 type,result1,result2,result3,result4 = extract_type11_10(name) if type: flag = type a = result1 b = result2 x = result3 y = result4 elif(check_bracket_before_first_dot(name)): a,b,c,d,x,flag = extract_components(name) else: pattern = re.compile(r'^([^\[\].]+)(?:\.([^\[\].]+))?(?:\[([^\[\]]+)\])?(?:\[([^\[\]]+)\])?(?:\.([^\[\].]+))?(?:\.([^\[\].]+))?(?:\[([^\[\]]+)\])?$') # 匹配字符串 match = pattern.match(name) if not match: return None # 提取各部分 a = match.group(1) b = match.group(2) x = match.group(3) y = match.group(4) c = match.group(5) d = match.group(6) z = match.group(7) # 根据提取结果确定 flag if not b and not x and not y and not c and not d and not z: flag = 1 # 情况 1: a elif b and not x and not y and not c and not d and not z: flag = 2 # 情况 2: a.b elif x and not b and not y and not c and not d and not z: flag = 3 # 情况 3: a[x] elif b and x and not y and not c and not d and not z: flag = 4 # 情况 4: a.b[x] elif x and b and not y and not c and not d and not z: flag = 5 # 情况 5: a[x].b elif x and y and b and not c and not d and not z: flag = 6 # 情况 6: a[x][y].b elif b and x and c and not y and not d and not z: flag = 7 # 情况 7: a.b[x].c elif x and b and c and y and not d and not z: flag = 8 # 情况 8: a[x].b.c[y] else: flag = 0 # 未知情况 # 返回结果 return flag,a,b,x,y,c,d,z def structgetaddr(structname,vname,classes,it_dict,list11):#(结构体作为主型)a.b类型,获取a.b的地址 address = '0' currenttype = '0' skipflag = 0 for cla in classes:#找到结构体名 if skipflag == 1: break if(structname == cla.name):#找到了结构体 initaddr = cla.address#找到结构体的初始地址 for dit in it_dict.keys():#找到了键的索引 if skipflag == 1: break if(dit == cla.type):#找到了键的索引 for va in list11:#这个列表里面都是字典,字典里面都是列表,列表中还是字典list11这里有问题????? #print(va.keys()) if skipflag == 1: break for structnum,value0 in va.items(): if skipflag == 1: break if(structnum == it_dict[dit]):#如果找到的结构体编号等于索引字典的值 for list12 in value0:#这里面都是列表,列表中的内容都是字典 if skipflag == 1: break for keylist12,valuelist12 in list12.items(): if skipflag == 1: break if(vname == keylist12):#找到了这个变量 address = str(hex(int(initaddr, 16) + int(valuelist12[1], 10))) currenttype = valuelist12[0] skipflag = 1 break return address,currenttype def arraygetaddr(first_part,second_part,third_part,classes,arrayclasslist11):#(二维数组作为主型)二维数组,获取a[x][y]的地址 address0 = '' address = '0' currenttype = '0' skipflag = 0 for cla in classes:#变量的结构体都是统一的 if skipflag == 1: break if(first_part == cla.name):#到这里就是找到了变量名,找到了数组名,数组是直接,变量到数组结构 address0 = cla.address#找到初始地址 for iarray in arrayclasslist11:#对所有的数组出手 if(iarray.name == cla.type):#找到匿名地址----------- #数组类---------------这一块没有找匿名就直接找数组了,数组没有匿名哦 allnum = int(iarray.numtotal)#总数 sonmux = 1 for son in iarray.golist: sonmux = sonmux*(int(son) + 1)#得到数组的总大小 uint = allnum/sonmux layernum = (int(iarray.golist[1]) + 1)*int(uint) nowlayer = int(int(second_part))*layernum addresslayer = nowlayer + (int(third_part))*int(uint) address1 = hex(int(address0,16) + int(str(addresslayer),10)) address = str(address1) currenttype = iarray.searvh skipflag = 1 break return address,currenttype def arraygetaddr1(first_part,second_part,classes,arrayclasslist11):#(一维数组作为主型)一维数组,获取a[x]的地址 address0 = '' address = '0' currenttype = '0' skipflag = 0 for cla in classes:#变量的结构体都是统一的 if skipflag == 1: break if(first_part == cla.name):#到这里就是找到了数组名 address0 = cla.address for iarray in arrayclasslist11:#数组类 if skipflag == 1: break if(cla.type == iarray.name):#类型地址等于数组的编号 allnum = int(iarray.numtotal)#总数 sonmux = 1 for son in iarray.golist: sonmux = sonmux*(int(son) + 1)#得到数组的总大小 uint = allnum/sonmux #layernum = (int(iarray.golist[1]) + 1)*uint #nowlayer = int(second_part+1)*layernum addresslayer = (int(second_part))*int(uint) address1 = hex(int(address0,16) + int(str(addresslayer),10)) address = str(address1) currenttype = iarray.searvh skipflag = 1 break return address,currenttype def Sonstructgetaddr(searchtypename,vname,classes,it_dict,list11,arrayclasslist11,anydict):#(结构体作为子型)a.b类型,获取a.b的地址 initaddr = '0' address = '0' currenttype = '0' skipflag = 0 for dit in it_dict.keys():#找到了键的索引 if skipflag == 1: break if(dit == searchtypename):#通过数据类型找到结构体匿名 for va in list11:#这个列表里面都是字典,字典里面都是列表,列表中还是字典list11这里有问题????? #print(va.keys()) if skipflag == 1: break for structnum,value0 in va.items(): if skipflag == 1: break if(structnum == it_dict[dit]):#通过结构体匿名找到结构体 for list12 in value0:#这里面都是列表,列表中的内容都是字典 for keylist12,valuelist12 in list12.items(): if(vname == keylist12):#找到了结构体的这个成员 address = str(hex(int(initaddr, 16) + int(valuelist12[1], 10))) currenttype = valuelist12[0] skipflag = 1 break return address,currenttype#这里实际上就找到了结构体的这个成员相对于上一级的偏移 def Sonarraygetaddr(searchtype,second_part,third_part,classes,arrayclasslist11,anydict):#(二维数组作为子型)二维数组,获取a[x][y]的地址 address0 = '0' address = '0' currenttype = '0' skipflag = 0 for iarray in arrayclasslist11:#对所有的数组出手 if skipflag == 1: break if(iarray.name == searchtype):#找到匿名地址----------- #数组类---------------这一块没有找匿名就直接找数组了,数组没有匿名哦 allnum = int(iarray.numtotal)#总数 sonmux = 1 for son in iarray.golist: sonmux = sonmux*(int(son) + 1)#得到数组的总大小 uint = allnum/sonmux layernum = (int(iarray.golist[1]) + 1)*int(uint) nowlayer = int(int(second_part))*layernum addresslayer = nowlayer + (int(third_part))*int(uint) address1 = hex(int(address0,16) + int(str(addresslayer),10)) address = str(address1) currenttype = iarray.searvh skipflag = 1 break return address,currenttype#实际上的偏移 def Sonarraygetaddr1(searchtype,second_part,classes,arrayclasslist11,anydict):#(一维数组作为子型)一维数组,获取a[x]的地址 address0 = '0' address = '0' currenttype = '0' skipflag = 0 for iarray in arrayclasslist11:#数组类 if skipflag == 1: break if(searchtype == iarray.name):#类型地址等于数组的编号 allnum = int(iarray.numtotal)#总数 sonmux = 1 for son in iarray.golist: sonmux = sonmux*(int(son) + 1)#得到数组的总大小 uint = allnum/sonmux #layernum = (int(iarray.golist[1]) + 1)*uint #nowlayer = int(second_part+1)*layernum addresslayer = (int(second_part))*int(uint) address1 = hex(int(address0,16) + int(str(addresslayer),10)) address = str(address1) currenttype = iarray.searvh skipflag = 1 break return address,currenttype#实际上的偏移 #---------------------对于elf生成需要对结构体和数组进行处理的文件 def dwarfdo(dwarfaddr):#根据dwarf文件生成需要的文件 # 正则表达式 structure_pattern = re.compile(r'^\s*<\d+><([0-9a-f]+)>:.*\(DW_TAG_structure_type\)') member_pattern = re.compile(r'^\s*<\d+><([0-9a-f]+)>:.*\(DW_TAG_member\)') name_pattern = re.compile(r'^\s*<[0-9a-f]+>\s+DW_AT_name\s+.*:\s+(.*)') offset_pattern = re.compile(r'DW_OP_plus_uconst:\s*(\d+)') Stop_pattern = re.compile(r'^\s*<\d+><([0-9a-f]+)>:\sAbbrev\sNumber:\s0') #------- typedef_pattern = re.compile(r'^\s*<\d+><([0-9a-f]+)>:.*\(DW_TAG_typedef\)')#找到匿名变量 searchvalue_pattern = re.compile(r'^\s*<[0-9a-f]+>\s*DW_AT_type\s*:\s<0x([0-9a-f]+)>') #找打匿名变量的信息 # 存储结果 #----- var_pattern = re.compile(r'^\s*<\d+><([0-9a-f]+)>:.*\(DW_TAG_variable\)') varname_pattern = re.compile(r'^\s*<[0-9a-f]+>\s+DW_AT_name\s+.*:\s+(.*)') vartype_pattern = re.compile(r'^\s*<[0-9a-f]+>\s*DW_AT_type\s*:\s<0x([0-9a-f]+)>') varaddr_pattern = re.compile(r'\(DW_OP_addr:\s*([0-9a-f]+)\)') #-----存储数组 array_pattern = re.compile(r'^\s*<\d+><([0-9a-f]+)>:.*\(DW_TAG_array_type\)')#找到数组,type已经有正则表达式了 arraysearch_pattern = re.compile(r'^\s*<[0-9a-f]+>\s*DW_AT_type\s*:\s<0x([0-9a-f]+)>') #找到数组到匿名的索引 arrayinfo_pattern = re.compile(r'^\s*<\d+><([0-9a-f]+)>:.*\(DW_TAG_array_type\)')#找到数组结构信息 arrnumnum_pattern = re.compile(r'DW_AT_upper_bound\s*:\s*(\d+)')#找到数组的结构大小0-x,0-y,0-z basepattern_pattern = re.compile(r'^\s*<\d+><([0-9a-f]+)>:\sAbbrev\sNumber:\s')#找到基本数据类型这个直接用search basenumpattern_pattern = re.compile(r'DW_AT_byte_size\s*:\s*(\d+)')#找到基础数据类型的大小-这个也用search # baseupper_pattern = re.compile(r'DW_AT_upper_bound\s*:\s*(\d+)')# #-----------------------匹配任意的编号到数据类型的索引 anytypehead_pattern = re.compile(r'^\s*<\d+><([0-9a-f]+)>:\s*Abbrev\sNumber:')#search匹配任意头 anytypeend_pattern = re.compile(r'^\s*<[0-9a-f]+>\s*DW_AT_type\s*:\s<0x([0-9a-f]+)>')#match匹配整个 #-----------------------匹配任意的编号到数据类型的索引 class ALLClass: def __init__(self, name: str, type: str, address: str): self.name = name #结构体变量名称 self.type = type #结构体类型索引 self.address = address #结构体地址 class ALLClassArray: def __init__(self, name: str, numtotal: str, searvh:str,golist):#记录出来名字,总大小,深度,单位大小---- #------注意基本单位并不是真正的基本单位,这里只有找到单位大小就可以了 self.name = name #数组名称 self.numtotal = numtotal #数组总大小 self.searvh = searvh #到匿名变量的索引 self.golist = golist #结构列表 classes = [] #----- results = {} current_structure = None current_member = None StartFlag = 0 StartFlag2 = 0 stopflag = 0 searchvalue_flag = 0#寻找匿名索引值得标志位 alone_dict = {} all_dict = {} list001 = []#列表里面全都是字典,字典的键是结构体名,字典的值是列表,列表里面是变量名对应偏移量的字典 listson = []#子表 #----- listypedef = []#用于存储中间索引的列表 it_dict = {}#用于存储中间索引的字典 #----- arraystart = 0 startflag = 0 arrayclass = {}#存储数组的基本大小--这个似乎不用了 arrayclasslist11 = []#存储编号,大小,索引,数组结构 numstart = 0 namemallstart = 0 searchstart = 0 #--------匹配任意DIE的类型 anydict = {} anyheadflag = 0 #--------匹配任意DIE的类型 # 逐行处理# #1,需求,寻找编号与对应的变量、偏移已经完成 #2,需求,构建索引结构体名的索引字典已经完成 #3,需求,构建一个类,类的内容分别是编号,名字,地址,类型已经完成 with open(dwarfaddr, 'r', encoding='utf-8') as file: lines = file.readlines() # 读取所有行到列表中 for line in lines: line = line.rstrip() # 去除行尾的空白字符 #---------匹配结构体内部变量 #---------匹配结构体内部变量 structure_match = structure_pattern.match(line) member_match = member_pattern.match(line) name_match = name_pattern.match(line) offset_match = offset_pattern.search(line) stop_match = Stop_pattern.match(line) #---------匹配索引 typedef_match = typedef_pattern.match(line) searchvalue_match = searchvalue_pattern.match(line) #---------匹配结构体变量 var_match = var_pattern.match(line) varname_match = varname_pattern.match(line) vartype_match = vartype_pattern.match(line) varaddr_match = varaddr_pattern.search(line) #---------数组处理 # array_pattern = re.compile(r'^\s*<\d+><([0-9a-f]+)>:.*\(DW_TAG_array_type\)')#找到数组,type已经有正则表达式了 # arrayclass_pattern = re.compile(r'^\s*<\d+><([0-9a-f]+)>:.*\(DW_TAG_base_type\)')#找到基本数据类型 # arrnum_pattern = re.compile(r'DW_AT_byte_size\s*:\s*(\d+)')#找到基础数据类型的大小 # array_match = array_pattern.match(line) # arrayclass_match = arrayclass_pattern.match(line) # arrnum_match = arrnum_pattern.search(line) array_match = array_pattern.match(line) arraysearch_match = arraysearch_pattern.match(line) arrayinfo_match = arrayinfo_pattern.match(line) arrnumnum_match = arrnumnum_pattern.search(line) basepattern_match = basepattern_pattern.search(line) basenumpattern_match = basenumpattern_pattern.search(line) #------------------------------------匹配任意的数据类型 anytypehead_match = anytypehead_pattern.search(line) anytypeend_match = anytypeend_pattern.match(line) #------------------------------------匹配任意的数据类型 if structure_match:#当前是结构体定义处,提取编号 current_structure = structure_match.group(1) #results[current_structure] = {} StartFlag = 1 listson = [] stopflag = 1 cuttent_array = [] # 匹配成员 # elif member_match and (StartFlag == 1):#遇到成员,提取成员名与偏移 # current_member = member_match.group(1)#标记出遇到结构体的成员了 #doit #StartFlag2 = 1 #print(current_member) elif StartFlag and name_match: # print(name_match.group(1))#获取变量名 current_name = name_match.group(1) elif StartFlag and anytypeend_match: cruuenttype = anytypeend_match.group(1) cuttent_array.append(cruuenttype) elif StartFlag and offset_match: #print(offset_match.group(1))#获取上面变量名对应的偏移 current_offset = offset_match.group(1) cuttent_array.append(current_offset) alone_dict = {current_name: cuttent_array}#到这里取出一对,就建立一个字典,变量名是键偏移量是值 listson.append(alone_dict)#增加一个偏移 cuttent_array = [] elif stop_match and stopflag:#到这种时候,就代表一个结构体的内容处理完成了,接下来整理数据就好了 all_dict = {current_structure: listson} # for i in listson: # print(i) list001.append(all_dict) StartFlag = 0#处理完成标志 stopflag = 0 #这一部分是编号变量名的 #下面一部分是编号结构体名的 if typedef_match:#遇到了匿名索引 typedef_name = typedef_match.group(1)#找到匿名索引的键 searchvalue_flag = 1 elif searchvalue_flag and searchvalue_match:#找到了键,现在要找值 typedef_value = searchvalue_match.group(1) #my_dict = {typedef_name,typedef_value} it_dict[typedef_name] = typedef_value #listypedef.append(my_dict) searchvalue_flag = 0 #这一步是为了构建一个列表,列表里面有许多类,用来索引结构体的名称 if var_match: startflag = 1 elif startflag and varname_match: varname = varname_match.group(1) #print(varname) elif startflag and vartype_match: vartype = vartype_match.group(1) #print(vartype) elif startflag and varaddr_match: varaddr = varaddr_match.group(1) #print(varaddr) classes.append(ALLClass(varname,vartype,varaddr)) startflag = 0 #这里进行数组的处理找到数组中间索引-----------------找到数组变量,数组地址,数组大小,数组索引。深度, #print(line) if array_match:#找到array的DIE name = array_match.group(1)#记录数组编号 arraystart = 1#遇到数组才开始 namemallstart = 1 searchstart = 1 list004 = []#列表为空 #似乎不需要增加新的逻辑,因为每个数组与结构都是一一对应的 elif namemallstart and arraystart and basenumpattern_match:#这个大小是总大小,与数组在一起就一起记录 namemall = basenumpattern_match.group(1)#找到数组总大小并记录 namemallstart = 0 elif searchstart and arraystart and arraysearch_match:#找到找到数组到匿名变量的索引 searvh = arraysearch_match.group(1) searchstart = 0 elif arraystart and arrnumnum_match:#从这里开始记录数组结构 go = arrnumnum_match.group(1)#记录数据的结构 list004.append(go) elif arraystart and stop_match:#到停止的时候就收集信息,收集编号名称,总大小 arrayclasslist11.append(ALLClassArray(name,namemall,searvh,list004)) arraystart = 0# namemallstart = 0 searchstart = 0 #----------------到这里把数组的array块的DIE给解决了 # ---------------------------------------------这里解决数组的基础数据信息 # if basepattern_pattern:#可以索引出来大小的时候 # numhead = basepattern_pattern.group(1) # numstart = 1 # elif numstart and basenumpattern_pattern: # numend = basenumpattern_pattern.group(1) if anytypehead_match:#匹配到编号头, <2><9cb3f4>: anyhead = anytypehead_match.group(1) anyheadflag = 1 elif anyheadflag and anytypeend_match:#匹配到编号尾, <9cb3fc> DW_AT_type : <0x9cadba> anytype = anytypeend_match.group(1)# anydict[anyhead] = anytype anyheadflag = 0 return list001,it_dict,classes,arrayclasslist11,anydict def Getaddressfromelf(input_string,dict,classes):#直接从ELF里的MAP使用简单变量的,变量名与地址的对应关系更新地址-0923类型 # 提取 Name 后面的字符串 lines = input_string.split('\n') # 将字符串按行分割 result_lines = [] Address = '' for line in lines: skipflag = 0 name_pattern = r'\s+/\*\s+Name\s+\*/\s+([^\s]+)'#获取名字 address_pattern = r'\s+/\*\s*ECU\s+Address\s+\*/\s+([^\s]+)'#获取地址 address_pattern1 = r'\s+ECU_ADDRESS\s+(\S+)\s+([^\s]+)' name_match = re.search(name_pattern, line) #print(name_match.group(1)) address_match = re.search(address_pattern, line) address_match1 = re.search(address_pattern1, line) if(address_match): address_match = address_match elif(address_match1): address_match = address_match1 if name_match: #print("Name Extracted:", name_match.group(1)) # 输出: Name Extracted: ABC123 Address = name_match.group(1) result_lines.append(line) # print(line) # print(Address) # 提取 ECU Address 后面的字符串 elif(address_match and (Address != '')): #print(line) b = address_match.group(1)# + ' ' + '/*' # print(dict[Address]) # if(Address in dict.keys()): # temp = dict[Address] # # print(temp) # temp = int(temp,16) # temp = hex(temp) # new_b = str(temp)# + ' ' + '/*' # line = line.replace(b,new_b) #print(dict[Address]) for cla in classes:#变量的结构体都是统一的 if(Address == cla.name):#到这里就是找到了数组名 address0 = cla.address temp = address0 # print(temp) temp = int(temp,16) temp = hex(temp) new_b = str(temp)# + ' ' + '/*' line = line.replace(b,new_b) result_lines.append(line) #print(line) elif not line.strip(): Address = '' result_lines.append(line) else: result_lines.append(line) return '\n'.join(result_lines) def Getaddressfromelf1227(input_string,dict,classes):#直接从ELF里的MAP使用简单变量的,变量名与地址的对应关系更新地址--1127类型 # 提取 Name 后面的字符串 lines = input_string.split('\n') # 将字符串按行分割 result_lines = [] Address = '' for line in lines: # name_pattern = r'\s+/\*\s+Name\s+\*/\s+([^\s]+)'#获取名字 # address_pattern = r'\s+/\*\s*ECU\s+Address\s+\*/\s+([^\s]+)'#获取地址 # address_pattern1 = r'\s+ECU_ADDRESS\s+(\S+)\s+([^\s]+)' name_pattern = re.compile(r'\s*/begin\s(CHARACTERISTIC|MEASUREMENT)\s(\S+)\s"')#匹配约定组与预定组的名字 address_pattern = re.compile(r'0xFE([0-9A-F]+)')#匹配地址 name_match = re.search(name_pattern, line) address_match = re.search(address_pattern, line) # address_pattern11 = re.compile(r'0xFE([0-9A-F]+)') # if(name_match): # address_match = address_match # elif(address_match1): # address_match = address_match1 if name_match: #print("Name Extracted:", name_match.group(1)) # 输出: Name Extracted: ABC123 Address = name_match.group(2) # if(Address == 'ADAS_bAutDrvCtlActv_E'): # print('doit') result_lines.append(line) # print(line) # print(Address) # 提取 ECU Address 后面的字符串 elif(address_match and (Address != '')): #print(line) b = 'FE' + address_match.group(1) b1 = 'fe' + address_match.group(1) # print(dict[Address]) # if(Address in dict.keys()): # temp = dict[Address] # # print(temp) # temp = int(temp,16) # temp = hex(temp).upper()[2:] # new_b = str(temp) # line = line.replace(b,new_b) # line = line.replace(b1,new_b) for cla in classes:#变量的结构体都是统一的 if(Address == cla.name):#到这里就是找到了数组名 address0 = cla.address temp = address0 # print(temp) temp = int(temp,16) temp = hex(temp).upper()[2:] new_b = str(temp)# + ' ' + '/*' line = line.replace(b,new_b) line = line.replace(b1,new_b) #print(dict[Address]) result_lines.append(line) #print(line) elif not line.strip(): Address = '' result_lines.append(line) else: result_lines.append(line) return '\n'.join(result_lines) def Getaddressfromelfplus(input_string,list11,it_dict,classes,arrayclasslist11,dict,anydict):#从elf获取地址,处理结构体,数组0923 # 提取 Name 后面的字符串 lines = input_string.split('\n') # 将字符串按行分割 result_lines = [] Address = '' flagvar = 'null' for line in lines: name_pattern = r'\s+/\*\s+Name\s+\*/\s+([^\s]+)'#获取名字 address_pattern = r'\s+/\*\s*ECU\s+Address\s+\*/\s+([^\s]+)'#获取地址 address_pattern1 = r'\s+ECU_ADDRESS\s+(\S+)\s+([^\s]+)' name_match = re.search(name_pattern, line) address_match = re.search(address_pattern, line) address_match1 = re.search(address_pattern1, line) if(address_match): address_match = address_match elif(address_match1): address_match = address_match1 if('TeBTRCTR_e_SysBatteryMode' in line): print('test') if name_match:#在这里对不同的数据结构,采用不同的数据处理方式 #print("Name Extracted:", name_match.group(1)) # 输出: Name Extracted: ABC123 Address = name_match.group(1)#Address就是名字 flagvar = 'null' # if('TeBTRCTR_e_SysBatteryMode' in Address): # print('test') # if 'TeBTRCTR_e_SysBatteryMode' in line: # print('this') flagvar,vara,varb,varx,vary,varc,vard,varz = parse_name(Address)#提取出数据类型,与各类型数据的情况 flagvar = str(flagvar) # 1,a-----flag,a一般形式已经处理过了 # 2,a.b-----flag,a,b # 3,a[x]-----flag,a,x---这里其实是二维数组 # 4,a.b[x]----flag,a,b,x # 5,a[x].b----flag,a,b,c # 6,a[x][y].b---flag,a,b,x,c # 7,a.b[x].c---flag,a,b,x,c # 8,a[x].b.c[y]---flag,a,b,c,d,x # 9, a[x].b[y].c---flag,a,b,c,d,x # 10,a.b.c[x]--- # result_lines.append(line) # print(line) # print(Address) # 提取 ECU Address 后面的字符串 elif(address_match and (Address != '') and (flagvar != 'null') ):#正是数据处理行,并且能识别出数据类型 #print(line) address = '' if(flagvar == '2'):#最普通的结构体类型,a.b类型,对应a.b,a.b[x] structname,vname = vara,varb#= Address.split('.')#分离出来变量 address,currenttype = structgetaddr(structname,vname,classes,it_dict,list11)#结构体更新出来了 #address = int(address,16) address = str(address).upper()[2:] #print(dict[Address]) #result_lines.append(line) # elif(flagvar == 2):#这种是最普通的多维数组类型,A[X][X],最多处理二维数组,后面增加通用处理功能 # address = ''#由于在a2l里面,数组只保留到次一级,二维数组只处理a[x][y].c类型 # if(re.search(r'\._\d+_\._(\d+)', Address)):#当前是二维数组 # first_part = Address.split('._')[0]#第一部分是名字 # second_part = re.search(r'\._(\d+)', Address)#第二部分是2,1,中的2 # third_part = re.search(r'\._\d+_\._(\d+)', Address)#2,1中的1 # #address0 = ''#首地址就从map里面找了,不用dwarf # address,currenttype = arraygetaddr(first_part,second_part,third_part,classes,arrayclasslist11) # address = str(address).upper()[2:] elif(flagvar == '3'):#a[x]形式,对应a[x][y],third_part默认赋值0 first_part = vara#Address.split('._')[0]#第一部分是名字 second_part = varx#re.search(r'\._(\d+)', Address)#第二部分是2,1,中的2 #third_part = re.search(r'\._\d+\._(\d+)', Address)#2,1中的1 #address0 = ''#首地址就从map里面找了,不用dwarf third_part = '0' address,currenttype = arraygetaddr(first_part,second_part,third_part,classes,arrayclasslist11)#要用二维数组的处理方式 #address = int(address,16) address = str(address).upper()[2:] elif(flagvar == '4'):#a.b[x]形式,对应a.b[x][y],third_part默认赋值0 initaddress = '' structname = vara arrayname = varb array1dex = varx third_part = '0' address,currenttype = structgetaddr(structname,arrayname,classes,it_dict,list11)#主结构体的地址与当前成员的类型 plusaddress,currenttype = Sonarraygetaddr(currenttype,array1dex,third_part,classes,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress,16))).upper()[2:] elif(flagvar == '5'):#a[x].b,对应a[x].b和a[x],b[y] first_part = vara second_part = varb vname = varc address,searchtype = arraygetaddr1(first_part,second_part,classes,arrayclasslist11)#初始地址 plusaddress,currenttype = Sonstructgetaddr(searchtype,vname,classes,it_dict,list11,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress,16))).upper()[2:] elif(flagvar == '6'):#a[x][y].b二维主,对应a[x][y].b与a[x][y].b[z] first_part = vara second_part = varb third_part = varx vname = varc address,searchtype = arraygetaddr(first_part,second_part,third_part,classes,arrayclasslist11) plusaddress,currenttype = Sonstructgetaddr(searchtype,vname,classes,it_dict,list11,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress,16))).upper()[2:] elif(flagvar == '7'):#a.b[x].c,对应a.b[x].c与a.b[x].c[z]结构体主,数组与结构体辅a.b,b[x],t.c initaddress = '' structname = vara arrayname = varb array1dex = varx vname = varc address,currenttype = structgetaddr(structname,arrayname,classes,it_dict,list11)#主结构体的地址与当前成员的类型 plusaddress,currenttype = Sonarraygetaddr1(currenttype,array1dex,classes,arrayclasslist11,anydict) plus1address,currenttype = Sonstructgetaddr(currenttype,vname,classes,it_dict,list11,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress,16) + int(plus1address,16))).upper()[2:] elif(flagvar == '8'):#a[x].b.c[y]类型数组a[x]为主,这里其实就是a[x].b.c结构体数组,结构体里面同样有结构体 first_part = vara second_part = varb vname = varc vname1 = vard five_name = varx address,searchtype = arraygetaddr1(first_part,second_part,classes,arrayclasslist11)#初始地址 plusaddress,currenttype = Sonstructgetaddr(searchtype,vname,classes,it_dict,list11,arrayclasslist11,anydict) plusaddress1,currenttype = Sonstructgetaddr(currenttype,vname1,classes,it_dict,list11,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress,16) + int(plusaddress1,16))).upper()[2:] elif(flagvar == '9'):#a[x].b[y].c类型 first_part = vara second_part = varb vname = varc vname1 = varx five_name = vard # print(vara) # print(varb) # print(varc) # print(vard) # print(varx) address,searchtype = arraygetaddr1(first_part,second_part,classes,arrayclasslist11)#初始地址 plusaddress1,currenttype = Sonstructgetaddr(searchtype,vname,classes,it_dict,list11,arrayclasslist11,anydict) plusaddress2,currenttype = Sonarraygetaddr1(currenttype,vname1,classes,arrayclasslist11,anydict) plusaddress3,currenttype = Sonstructgetaddr(currenttype,five_name,classes,it_dict,list11,arrayclasslist11,anydict) #CurrentTypenameDict[Address] = Ftypedict[currenttype] address = str(hex(int(address,16) + int(plusaddress1,16) + int(plusaddress2,16) + int(plusaddress3,16))).upper()[2:] elif(flagvar == '10'):#a.b.c[y],实际对应a.b.c[y][z]形式 First_part = vara Second_part = varb Third_part = varx Four_part = vary third_partarray = '0' address,searchtype = structgetaddr(First_part,Second_part,classes,it_dict,list11) plusaddress1,currenttype = Sonstructgetaddr(searchtype,Third_part,classes,it_dict,list11,arrayclasslist11,anydict) plusaddress2,currenttype = Sonarraygetaddr(currenttype,Four_part,third_partarray,classes,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress1,16) + int(plusaddress2,16))).upper()[2:] elif(flagvar == '11'):#a.b.c,实际对应a.b.c First_part = vara Second_part = varb Third_part = varx address,searchtype = structgetaddr(First_part,Second_part,classes,it_dict,list11) plusaddress1,currenttype = Sonstructgetaddr(searchtype,Third_part,classes,it_dict,list11,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress1,16))).upper()[2:] if(address != ''):#确实把地址给更新掉了 b = address_match.group(1)#+ ' ' + '/*'#需要替代的 new_b = address# + ' ' + '/*'#新的 line = line.replace(b,new_b) result_lines.append(line) elif not line.strip():#空行代表进入到了下一个处理 Address = '' result_lines.append(line) else: result_lines.append(line) return '\n'.join(result_lines) def Getaddressfromelfplus1227(input_string,list11,it_dict,classes,arrayclasslist11,dict,anydict):#从elf获取地址,处理结构体与数组,1227 # 提取 Name 后面的字符串 lines = input_string.split('\n') # 将字符串按行分割 result_lines = [] Address = '' flagvar = 'null' for line in lines: # name_pattern = r'\s+/\*\s+Name\s+\*/\s+([^\s]+)'#获取名字 # address_pattern = r'\s+/\*\s*ECU\s+Address\s+\*/\s+([^\s]+)'#获取地址 # address_pattern1 = r'\s+ECU_ADDRESS\s+(\S+)\s+([^\s]+)' # name_match = re.search(name_pattern, line) # address_match = re.search(address_pattern, line) # address_match1 = re.search(address_pattern1, line) name_pattern = re.compile(r'\s*/begin\s(CHARACTERISTIC|MEASUREMENT)\s(\S+)\s"')#匹配约定组与预定组的名字 address_pattern = re.compile(r'0xFE([0-9A-F]+)')#匹配地址 name_match = re.search(name_pattern, line) address_match = re.search(address_pattern, line) # if(address_match): # address_match = address_match # elif(address_match1): # address_match = address_match1 if name_match: #print("Name Extracted:", name_match.group(1)) # 输出: Name Extracted: ABC123 Address = name_match.group(2) flagvar = 'null' if('testvar5[1].usCurrentHBStatus' in Address): print('test') flagvar,vara,varb,varx,vary,varc,vard,varz = parse_name(Address)#提取出数据类型,与各类型数据的情况 flagvar = str(flagvar) if 'STRUCTtest[1].test1111[1].ucProtectCnt' == Address: print(flagvar) print(vara) print(varb) print(varx) print(varc) print(vard) # if ('._' in Address):#结构体是1,数组是2,普通是0,0已经处理过了,这里就不再处理了 # flagtype = 2 # elif('.' in Address): # flagtype = 1 # else: # flagtype = 0 # result_lines.append(line) # # print(line) # # print(Address) # # 提取 ECU Address 后面的字符串 #print(line) result_lines.append(line) elif(address_match and (Address != '') and (flagvar != 'null') ): address = '' if(flagvar == '2'):#最普通的结构体类型,a.b structname,vname = vara,varb#= Address.split('.')#分离出来变量 address,currenttype = structgetaddr(structname,vname,classes,it_dict,list11)#结构体更新出来了 #address = int(address,16)#本身就是16进制 address = str(address).upper()[2:] #print(dict[Address]) #result_lines.append(line) # elif(flagvar == 2):#这种是最普通的多维数组类型,A[X][X],最多处理二维数组,后面增加通用处理功能 # address = ''#由于在a2l里面,数组只保留到次一级,二维数组只处理a[x][y].c类型 # if(re.search(r'\._\d+_\._(\d+)', Address)):#当前是二维数组 # first_part = Address.split('._')[0]#第一部分是名字 # second_part = re.search(r'\._(\d+)', Address)#第二部分是2,1,中的2 # third_part = re.search(r'\._\d+_\._(\d+)', Address)#2,1中的1 # #address0 = ''#首地址就从map里面找了,不用dwarf # address,currenttype = arraygetaddr(first_part,second_part,third_part,classes,arrayclasslist11) # address = str(address).upper()[2:] elif(flagvar == '3'):#当前是二维数组a[x][y] first_part = vara#Address.split('._')[0]#第一部分是名字 second_part = varx#re.search(r'\._(\d+)', Address)#第二部分是2,1,中的2 #third_part = re.search(r'\._\d+\._(\d+)', Address)#2,1中的1 #address0 = ''#首地址就从map里面找了,不用dwarf third_part = '0' address,currenttype = arraygetaddr(first_part,second_part,third_part,classes,arrayclasslist11)#实际一维数组 #address = int(address,16) address = str(address).upper()[2:] elif(flagvar == '4'):#a.b[x]主结构体与副数组 initaddress = '' structname = vara arrayname = varb array1dex = varx third_part = '0' address,currenttype = structgetaddr(structname,arrayname,classes,it_dict,list11)#主结构体的地址与当前成员的类型 plusaddress,currenttype = Sonarraygetaddr(currenttype,array1dex,third_part,classes,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress,16))).upper()[2:] elif(flagvar == '5'):#a[x].b数据类型 first_part = vara second_part = varb vname = varc address,searchtype = arraygetaddr1(first_part,second_part,classes,arrayclasslist11)#初始地址 plusaddress,currenttype = Sonstructgetaddr(searchtype,vname,classes,it_dict,list11,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress,16))).upper()[2:] elif(flagvar == '6'):#a[x][y].b二维主,结构体辅 first_part = vara second_part = varb third_part = varx vname = varc address,searchtype = arraygetaddr(first_part,second_part,third_part,classes,arrayclasslist11) plusaddress,currenttype = Sonstructgetaddr(searchtype,vname,classes,it_dict,list11,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress,16))).upper()[2:] elif(flagvar == '7'):#a.b[x].c,结构体主,数组与结构体辅a.b,b[x],t.c initaddress = '' structname = vara arrayname = varb array1dex = varx vname = varc#17b04c8是什么鬼,似乎sonarrayaddr1有问题 address,currenttype = structgetaddr(structname,arrayname,classes,it_dict,list11)#主结构体的地址与当前成员的类型 plusaddress,currenttype = Sonarraygetaddr1(currenttype,array1dex,classes,arrayclasslist11,anydict) plus1address,currenttype = Sonstructgetaddr(currenttype,vname,classes,it_dict,list11,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress,16) + int(plus1address,16))).upper()[2:] elif(flagvar == '8'):#a[x].b.c[y]类型数组a[x]为主,这里其实就是a[x].b.c结构体数组,结构体里面同样有结构体 first_part = vara second_part = varb vname = varc vname1 = vard five_name = varx address,searchtype = arraygetaddr1(first_part,second_part,classes,arrayclasslist11)#初始地址 plusaddress,currenttype81 = Sonstructgetaddr(searchtype,vname,classes,it_dict,list11,arrayclasslist11,anydict) plusaddress1,currenttype = Sonstructgetaddr(currenttype81,vname1,classes,it_dict,list11,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress,16) + int(plusaddress1,16))).upper()[2:] elif(flagvar == '9'):#a[x].b[y].c类型 first_part = vara second_part = varb vname = varc vname1 = varx five_name = vard # print(vara) # print(varb) # print(varc) # print(vard) # print(varx) address,searchtype = arraygetaddr1(first_part,second_part,classes,arrayclasslist11)#初始地址 plusaddress1,currenttype = Sonstructgetaddr(searchtype,vname,classes,it_dict,list11,arrayclasslist11,anydict) plusaddress2,currenttype = Sonarraygetaddr1(currenttype,vname1,classes,arrayclasslist11,anydict) plusaddress3,currenttype = Sonstructgetaddr(currenttype,five_name,classes,it_dict,list11,arrayclasslist11,anydict) #CurrentTypenameDict[Address] = Ftypedict[currenttype] address = str(hex(int(address,16) + int(plusaddress1,16) + int(plusaddress2,16) + int(plusaddress3,16))).upper()[2:] elif(flagvar == '10'):#a.b.c[y],实际对应a.b.c[y][z]形式 First_part = vara Second_part = varb Third_part = varx Four_part = vary third_partarray = '0' address,searchtype = structgetaddr(First_part,Second_part,classes,it_dict,list11) plusaddress1,currenttype = Sonstructgetaddr(searchtype,Third_part,classes,it_dict,list11,arrayclasslist11,anydict) plusaddress2,currenttype = Sonarraygetaddr(currenttype,Four_part,third_partarray,classes,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress1,16) + int(plusaddress2,16))).upper()[2:] elif(flagvar == '11'):#a.b.c,实际对应a.b.c First_part = vara Second_part = varb Third_part = varx address,searchtype = structgetaddr(First_part,Second_part,classes,it_dict,list11) plusaddress1,currenttype = Sonstructgetaddr(searchtype,Third_part,classes,it_dict,list11,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress1,16))).upper()[2:] if(address != ''):#确实把地址给更新掉了 b = 'FE' + address_match.group(1)# + ' ' + '/*'#需要替代的 b1 = 'fe' + address_match.group(1)# + ' ' + '/*'#需要替代的 new_b = address# + ' ' + '/*'#新的 line = line.replace(b,new_b) line = line.replace(b1,new_b) result_lines.append(line) elif not line.strip():#空行代表进入到了下一个处理 Address = '' result_lines.append(line) else: result_lines.append(line) return '\n'.join(result_lines) def get_variable_addresses(elf_file):#读取ELF文件,获取变量名与地址的字典 variable_addresses = {} with open(elf_file, 'rb') as f: elffile = ELFFile(f) # 获取符号表 symtab = elffile.get_section_by_name('.symtab') if symtab is None: print("No symbol table found.") return variable_addresses # 遍历符号表 for symbol in symtab.iter_symbols(): # 过滤出变量(通常类型为STT_OBJECT) if symbol['st_info']['type'] == 'STT_OBJECT': if(symbol.name == '_Rte_NAP_VeOUT_NAP_ICCNapTimeSetToEE_sig_VeOUT_NAP_ICCNapTimeSetToEE_sig'): print("success1111111111") variable_name = symbol.name[1:] variable_address = str(symbol['st_value']) print(variable_address) variable_addresses[variable_name] = variable_address return variable_addresses def replace_header_with_a2ml(code_str, head_str): # 查找 /begin MODULE 和 /end MODULE 之间的内容 begin_header_tag = ' /begin MODULE ModuleName' end_header_tag = ' /begin MOD_COMMON' # 找到 /begin MODULE 的起始位置 start_index = code_str.find(begin_header_tag) if start_index == -1: raise ValueError("The string 'code_str' does not contain '/begin MODULE'") # 找到 /end MODULE 的结束位置 end_index = code_str.find(end_header_tag, start_index) if end_index == -1: raise ValueError("The string 'code_str' does not contain '/end MODULE' after '/begin MODULE'") end_index += len(end_header_tag) # 查找 /begin A2ML 到最后一个 /end IF_DATA 之间的内容 begin_a2ml_tag = '/begin A2ML' end_if_data_tag = '/end IF_DATA' a2ml_start_index = head_str.find(begin_a2ml_tag) if a2ml_start_index == -1: raise ValueError("The string 'head_str' does not contain '/begin A2ML'") a2ml_end_index = head_str.rfind(end_if_data_tag, a2ml_start_index) if a2ml_end_index == -1 or a2ml_end_index < a2ml_start_index: raise ValueError("The string 'head_str' does not contain a valid '/end IF_DATA' after '/begin A2ML'") a2ml_end_index += len(end_if_data_tag) # 替换 code_str 中找到的内容为 head_str 中的相应部分 replaced_code = ( code_str[:start_index] + # code_str 中 /begin MODULE 之前的部分 begin_header_tag + '\n' + head_str[a2ml_start_index:a2ml_end_index] + # head_str 中的 A2ML 部分 end_header_tag + '\n' + code_str[end_index:] # code_str 中 /end MODULE 之后的部分 ) return replaced_code def process_string(input_string, offset_hex):#偏移函数 # 将偏移量转换为整数 offset = int(offset_hex,16) # 定义正则表达式模式 begin_pattern = re.compile(r'\s*/begin\s+CHARACTERISTIC')# address_pattern = re.compile(r'ECU\s+Address\s+[^0x]*?\s+(0x[\dA-Fa-f]+)') address_pattern11 = re.compile(r'0xFE([0-9A-F]+)') lines = input_string.split('\n') # 将字符串按行分割 result_lines = [] in_characteristic_section = False current_address = None for line in lines: # if ('VALUE 0xFEXFDD81AFBC15 Scalar_BOOLEAN 0 tvi_TqVectInf_FD_CM_boolea' in line): # print(';') stripped_line = line.rstrip() # 去除行尾的空白字符 if begin_pattern.search(stripped_line): in_characteristic_section = True result_lines.append(stripped_line) # 保留这行 continue if not stripped_line: # 遇到空行,退出特性部分处理 in_characteristic_section = False result_lines.append('') # 保留空行 continue if in_characteristic_section:#空行用于识别各块 address_match = re.search(address_pattern11, stripped_line)#行 if address_match: # 提取地址并转换为整数 current_address_hex = 'FE' + address_match.group(1) current_address = int(current_address_hex, 16) # 计算新地址并格式化为十六进制字符串 new_address = hex(current_address + offset - 0x100000000).upper()[2:] # 去除'0x'并转换为大写FEXXXX # 替换地址并构建新行 #current_address_hex = current_address_hex new_line = stripped_line.replace(current_address_hex, new_address) result_lines.append(new_line) else: # 如果不是地址行,则直接添加 result_lines.append(stripped_line) else: # 如果不在特性部分,则直接添加未处理的行 result_lines.append(stripped_line) return '\n'.join(result_lines) def select_folder():#打开窗口获取文件1 # root = tk.Tk() # root.withdraw() # 隐藏主窗口 # folder_selected = filedialog.askdirectory() folder_selected = A2LUpdata_fold print(folder_selected) if folder_selected: Code,ElfFile = process_folder(folder_selected) return Code,folder_selected,ElfFile def process_folder(folder_path,):#打开窗口获取文件2 head_content = None code_content = None for filename in os.listdir(folder_path): ElfFile = '1' if filename.endswith('.a2l') and ('master' in filename):#这个是Head with open(os.path.join(folder_path, filename), 'r', encoding='utf-8') as file: head_content = file.read() elif filename.endswith('.a2l') and 'Output_All' in filename:#这个是Code # 假设只存在两个 .a2l 文件,且其中一个包含 'head',则另一个即为 'Code' with open(os.path.join(folder_path, filename), 'r', encoding='utf-8') as file: code_content = file.read() elif filename.endswith('.elf'): ElfFile = os.path.join(folder_path, filename) if code_content:#head_content and #Head = head_content Code = code_content return Code,ElfFile #print("Head content:", Head) #print("Code content:", Code) print("success!") else: print("Failed to read all required files.") # 运行选择文件夹的函数 def resolve_dictionary(d): changed = True while changed: changed = False for key in d: value = d[key] if value in d and d[value] != value: # 检查值是否是其他键,并且不是自引用 d[key] = d[value] changed = True return d #主函数从这里开始 current_script_dir = 'F:\\' Head = '' Code = '' Code ,current_script_dir ,ElfFile = select_folder()#获取原始A2L文件,其中Head是要添加的头文件 # print(ElfFile) ElfFile = ElfFile.replace("/", "\\") ElfFile = ElfFile.replace("\\", "\\\\") ##################################################################### config_path = os.path.join(pathorigin, 'path_config.json') print(config_path) # config_path = config_path.replace('\\','\\\\') # 读取JSON文件并加载为字典 with open(config_path, 'r', encoding='utf-8') as f: pathdict = json.load(f) ElfFile = pathdict['elf_path'] ##################################################################### address_dict = get_variable_addresses(ElfFile)#从ELF里面提取出map,对于普通变量,构建变量名-地址的索引 for key,value in address_dict.items(): print(key) parseDwarfOutput(ElfFile,pathorigin)#生成编译文件dwarf list11,it_dict1,classes,arrayclasslist11,anydict = dwarfdo(os.path.join(A2LUpdata_fold, 'dwarf_info1.txt'))#找到了所有需要进行(少了一个数组) #处理dwarf生成结果 # for struct in list11:#遍历所有的结构体,这个list疑似出问题 # for structnum,value0 in struct.items(): # if('169abc4' == structnum):#结构体编号 # print('1')# # print(structnum) # for member in value0:#在这里寻找指定的成员 # # for i in i2.values(): # for key,value in member.items(): # print(key) # print(value) # 打印结果 #for var_name, address in address_dict.items(): # print(type(var_name)) # print(type(address)) # print(var_name) # print(address) # print(f"Variable: {var_name}, Address: 0x{address:x}") # print(address_dict['apa_AccrPedlArbn_FD_B']) #------------------------------------------------------------------------------------# #这里做一个操作,实现typedef正确识别 it_dict = resolve_dictionary(it_dict1) #------------------------------------------------------------------------------------# New_Code = Getaddressfromelf(Code,address_dict,classes)#普通的变量在这里更新地址 #0923类型 New_Code = Getaddressfromelf1227(New_Code,address_dict,classes)#普通的变量在这里更新地址 #1227类型 New_Code = Getaddressfromelfplus(New_Code,list11,it_dict,classes,arrayclasslist11,address_dict,anydict)#普通的结构体与普通的 #多维数组,在这里更新地址----0923类型的 New_Code = Getaddressfromelfplus1227(New_Code,list11,it_dict,classes,arrayclasslist11,address_dict,anydict) #多维数组,在这里更新地址----1227类型的 #3处,更新地址与偏移------------------------------------------------------------- offset_hex = "0x2180000"#偏移量 #New_Code = replace_header_with_a2ml(New_Code, Head)#这一步进行头文件的合并 # 调用函数并打印结果 #New_Code = process_string(New_Code, offset_hex)#更新好的地址,在这里进行偏移 #print(New_Code) # result = New_Code # ------------删除编译信息 # file_path = os.path.join(current_script_dir, 'dwarf_info1.txt') # if os.path.exists(file_path): # # 删除文件 # os.remove(file_path) # print(f"文件 {file_path} 已删除") # else: # print(f"文件 {file_path} 不存在") # ------------删除编译信息 New_Code = New_Code.replace('ECU_ADDRESS FE','ECU_ADDRESS 0xFE') # 获取当前脚本的目录 result = New_Code #current_script_dir = os.path.dirname(os.path.realpath(__file__)) # 构造目标文件的路径(与当前脚本同路径,文件名为 output.a2l) output_file_path = os.path.join(A2LUpdata_fold, 'Output_All.a2l') # 将字符串内容写入到目标文件中 with open(output_file_path, 'w', encoding='utf-8') as output_file: output_file.write(result) print(f"A2L content has been saved to {output_file_path}")
最新发布
09-18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TCP404

老板大方~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值