@@ -16,14 +16,23 @@ import (
1616 "github.com/wader/fq/pkg/scalar"
1717)
1818
19+ var x86_64Group decode.Group
20+ var arm64Group decode.Group
21+
1922func init () {
2023 interp .RegisterFormat (
2124 format .Elf ,
2225 & decode.Format {
2326 Description : "Executable and Linkable Format" ,
2427 Groups : []* decode.Group {format .Probe },
2528 DecodeFn : elfDecode ,
26- })
29+ Dependencies : []decode.Dependency {
30+ // TODO: x86 32/16?
31+ {Groups : []* decode.Group {format .X86_64 }, Out : & x86_64Group },
32+ {Groups : []* decode.Group {format .Arm64 }, Out : & arm64Group },
33+ },
34+ },
35+ )
2736}
2837
2938const (
@@ -167,6 +176,15 @@ var phTypeNames = scalar.UintRangeToScalar{
167176 {Range : [2 ]uint64 {0x70000000 , 0x7fffffff }, S : scalar.Uint {Sym : "proc" , Description : "Processor-specific" }},
168177}
169178
179+ var machineToFormatFn = map [int ]func (d * decode.D , base uint64 , symLookup func (uint64 ) (string , uint64 )){
180+ EM_X86_64 : func (d * decode.D , base uint64 , symLookup func (uint64 ) (string , uint64 )) {
181+ d .Format (& x86_64Group , format.X86_64In {Base : int64 (base ), SymLookup : symLookup })
182+ },
183+ EM_ARM64 : func (d * decode.D , base uint64 , symLookup func (uint64 ) (string , uint64 )) {
184+ d .Format (& arm64Group , format.ARM64In {Base : int64 (base ), SymLookup : symLookup })
185+ },
186+ }
187+
170188const (
171189 NT_PRSTATUS = 1
172190 NT_PRFPREG = 2
@@ -980,6 +998,8 @@ func elfDecodeDynamicTags(d *decode.D, ec elfContext, dc dynamicContext) {
980998}
981999
9821000func elfDecodeSectionHeader (d * decode.D , ec elfContext , sh sectionHeader ) {
1001+ var execInstr bool
1002+
9831003 shFlags := func (d * decode.D , archBits int ) {
9841004 d .FieldStruct ("flags" , func (d * decode.D ) {
9851005 if d .Endian == decode .LittleEndian {
@@ -988,7 +1008,7 @@ func elfDecodeSectionHeader(d *decode.D, ec elfContext, sh sectionHeader) {
9881008 d .FieldBool ("strings" )
9891009 d .FieldBool ("merge" )
9901010 d .FieldU1 ("unused0" )
991- d .FieldBool ("execinstr" )
1011+ execInstr = d .FieldBool ("execinstr" )
9921012 d .FieldBool ("alloc" )
9931013 d .FieldBool ("write" )
9941014 d .FieldBool ("tls" )
@@ -1018,13 +1038,14 @@ func elfDecodeSectionHeader(d *decode.D, ec elfContext, sh sectionHeader) {
10181038 d .FieldBool ("strings" )
10191039 d .FieldBool ("merge" )
10201040 d .FieldU1 ("unused2" )
1021- d .FieldBool ("execinstr" )
1041+ execInstr = d .FieldBool ("execinstr" )
10221042 d .FieldBool ("alloc" )
10231043 d .FieldBool ("write" )
10241044 }
10251045 })
10261046 }
10271047
1048+ var addr uint64
10281049 var offset int64
10291050 var size int64
10301051 var entSize int64
@@ -1035,7 +1056,7 @@ func elfDecodeSectionHeader(d *decode.D, ec elfContext, sh sectionHeader) {
10351056 d .FieldU32 ("name" , strTable (ec .strTabMap [STRTAB_SHSTRTAB ]))
10361057 typ = d .FieldU32 ("type" , sectionHeaderTypeMap , scalar .UintHex )
10371058 shFlags (d , ec .archBits )
1038- d .FieldU ("addr" , ec .archBits , scalar .UintHex )
1059+ addr = d .FieldU ("addr" , ec .archBits , scalar .UintHex )
10391060 offset = int64 (d .FieldU ("offset" , ec .archBits )) * 8
10401061 size = int64 (d .FieldU32 ("size" , scalar .UintHex ) * 8 )
10411062 d .FieldU32 ("link" )
@@ -1046,7 +1067,7 @@ func elfDecodeSectionHeader(d *decode.D, ec elfContext, sh sectionHeader) {
10461067 d .FieldU32 ("name" , strTable (ec .strTabMap [STRTAB_SHSTRTAB ]))
10471068 typ = d .FieldU32 ("type" , sectionHeaderTypeMap , scalar .UintHex )
10481069 shFlags (d , ec .archBits )
1049- d .FieldU ("addr" , ec .archBits , scalar .UintHex )
1070+ addr = d .FieldU ("addr" , ec .archBits , scalar .UintHex )
10501071 offset = int64 (d .FieldU ("offset" , ec .archBits , scalar .UintHex ) * 8 )
10511072 size = int64 (d .FieldU64 ("size" ) * 8 )
10521073 d .FieldU32 ("link" )
@@ -1079,9 +1100,34 @@ func elfDecodeSectionHeader(d *decode.D, ec elfContext, sh sectionHeader) {
10791100 elfDecodeSymbolTable (d , ec , int (size / entSize ), ec .strTabMap [STRTAB_DYNSTR ])
10801101 })
10811102 case SHT_PROGBITS :
1082- // TODO: name progbits?
1083- // TODO: decode opcodes
1084- d .FieldRawLen ("data" , size )
1103+ // TODO: verify this, seems to result in strange relative addresses
1104+ symLookup := func (symAddr uint64 ) (string , uint64 ) {
1105+ var best * symbol
1106+
1107+ for _ , sh := range ec .sections {
1108+ for i , s := range sh .symbols {
1109+ if symAddr >= s .value && (best == nil || symAddr - s .value < best .value - s .value ) {
1110+ best = & sh .symbols [i ]
1111+ }
1112+ }
1113+ }
1114+ if best == nil {
1115+ return "" , 0
1116+ }
1117+ return strIndexNull (int (best .name ), ec .strTabMap [STRTAB_STRTAB ]), best .value
1118+ }
1119+
1120+ // TODO: name progbits? instructions?
1121+ if fn , ok := machineToFormatFn [ec .machine ]; execInstr && ok {
1122+ d .FieldArray ("code" , func (d * decode.D ) {
1123+ d .FramedFn (size , func (d * decode.D ) {
1124+ fn (d , addr , symLookup )
1125+ })
1126+ })
1127+ } else {
1128+ d .FieldRawLen ("data" , size )
1129+ }
1130+
10851131 case SHT_GNU_HASH :
10861132 d .FieldStruct ("gnu_hash" , func (d * decode.D ) {
10871133 elfDecodeGNUHash (d , ec , size , ec .strTabMap [STRTAB_DYNSTR ])
0 commit comments