elf解析需手动处理字节序与格式:先读e_ident[4]判32/64位,再依e_ident[5]选大小端,用readbytes+bitconverter解包;节头表可能缺失,须校验e_shoff/e_shnum/e_shentsize;字符串表需按\0分割;大文件应seek按需读。

ELF头部读取失败:BinaryReader直接读会错位
ELF文件头部前4字节是魔数\x7fELF,但C#默认用BinaryReader读ushort或uint时,若没设BitConverter.IsLittleEndian匹配目标平台字节序,就会把32位/64位ELF的e_ident之后字段全读反。Linux ELF一律小端,Windows x64也是小端,看似没问题——但一旦遇到交叉编译生成的ARM64 ELF(仍是小端),或你误用ReadUInt32()读64位字段(如e_entry在64位ELF中占8字节),立刻越界或解析出0。
实操建议:
- 不用
BinaryReader.ReadXXX()自动类型读取,改用ReadBytes(n)配合BitConverter.ToUInt32(bytes, 0)手动解包,显式指定偏移 - 先读
e_ident[4]判断ELFCLASS32(1)还是ELFCLASS64(2),再决定后续字段长度和偏移 -
e_ident[5]是字节序:值为1=小端,2=大端;别硬编码假设小端 - 头部固定部分长度:32位ELF是52字节,64位ELF是64字节——
e_phoff、e_shoff等关键偏移都依赖这个基准
节头表(Section Header Table)找不到:e_shoff为0或e_shnum为0
很多strip过的ELF(如发行版二进制)会删掉节头表,只留程序头表(Program Header Table)。此时e_shoff == 0或e_shnum == 0是合法状态,不是你读错了。想查.text/.data节内容?靠节头表不行,得转向程序头表+内存段映射,或者用readelf -S确认原始文件是否真有节头。
实操建议:
- 检查
e_shoff > 0 && e_shnum > 0 && e_shentsize > 0三者同时成立,才尝试读节头表 - 节头表本身不存字符串,节名存在
.shstrtab节里,而.shstrtab的索引由e_shstrndx给出——这个字段可能为SHN_UNDEF(0),意味着无节名字符串表 - 32位ELF节头单条长40字节,64位是64字节;别用同一结构体硬套两种格式
用System.IO.File.ReadAllBytes加载大ELF文件卡死
一个500MB的调试版ELF,File.ReadAllBytes会一次性分配500MB托管内存,GC压力陡增,且后续解析时还得反复Array.Copy切片——实际只需读头部几十字节和若干节数据,没必要全载入。
实操建议:
- 用
FileStream+Seek()跳转读,例如:fs.Seek(e_shoff, SeekOrigin.Begin); fs.Read(buffer, 0, e_shentsize * e_shnum) - 节内容按需读:拿到
sh_offset和sh_size后,再Seek过去读对应块,避免预分配大数组 - 如果只是校验或提取符号,优先用
objdump -h或readelf -h做验证,别在C#里重复造轮子
符号表解析失败:.symtab节存在但st_name指向乱码
st_name是符号名在字符串表(如.strtab)里的偏移,不是字符串本身。常见错误是直接把st_name当ASCII码打印,或者用Encoding.UTF8.GetString()去解整个.strtab节——但.strtab是null分隔的C字符串集合,中间有大量\x00,UTF8解码会截断或报错。
实操建议:
- 先定位
.strtab节内容(通过节头表找到其sh_offset和sh_size),再用Array.IndexOf(bytes, (byte)0, st_name)找下一个\x00位置,然后Encoding.ASCII.GetString(bytes, st_name, length) - 注意:有些ELF用
.dynsym代替.symtab(动态链接库常见),别只盯.symtab名字 -
st_info低4位是绑定属性(STB_GLOBAL等),高4位是类型(STT_FUNC等),需用st_info & 0xf和(st_info >> 4) & 0xf分别提取
ELF格式本身不复杂,但32/64位混用、大小端隐含假设、节表可选、字符串表分离这些设计,会让C#这种强类型语言容易在边界上栽跟头。最稳的方式是:每读一个字段,立刻用readelf -h或xxd -l 64核对原始字节,而不是猜结构体布局。










