@@ -20,7 +20,7 @@ import (
20
20
type elfCode struct {
21
21
* elf.File
22
22
symbols []elf.Symbol
23
- symbolsPerSection map [elf.SectionIndex ]map [uint64 ]string
23
+ symbolsPerSection map [elf.SectionIndex ]map [uint64 ]elf. Symbol
24
24
license string
25
25
version uint32
26
26
}
@@ -173,20 +173,20 @@ func (ec *elfCode) loadPrograms(progSections map[elf.SectionIndex]*elf.Section,
173
173
return nil , xerrors .Errorf ("section %v: missing symbols" , prog .Name )
174
174
}
175
175
176
- funcSym := syms [0 ]
177
- if funcSym == "" {
176
+ funcSym , ok := syms [0 ]
177
+ if ! ok {
178
178
return nil , xerrors .Errorf ("section %v: no label at start" , prog .Name )
179
179
}
180
180
181
181
insns , length , err := ec .loadInstructions (prog , syms , relocations [idx ])
182
182
if err != nil {
183
- return nil , xerrors .Errorf ("program %s: can't unmarshal instructions: %w" , funcSym , err )
183
+ return nil , xerrors .Errorf ("program %s: can't unmarshal instructions: %w" , funcSym . Name , err )
184
184
}
185
185
186
186
progType , attachType := getProgType (prog .Name )
187
187
188
188
spec := & ProgramSpec {
189
- Name : funcSym ,
189
+ Name : funcSym . Name ,
190
190
Type : progType ,
191
191
AttachType : attachType ,
192
192
License : ec .license ,
@@ -223,7 +223,7 @@ func (ec *elfCode) loadPrograms(progSections map[elf.SectionIndex]*elf.Section,
223
223
return res , nil
224
224
}
225
225
226
- func (ec * elfCode ) loadInstructions (section * elf.Section , symbols map [ uint64 ] string , relocations map [uint64 ]elf.Symbol ) (asm.Instructions , uint64 , error ) {
226
+ func (ec * elfCode ) loadInstructions (section * elf.Section , symbols , relocations map [uint64 ]elf.Symbol ) (asm.Instructions , uint64 , error ) {
227
227
var (
228
228
r = section .Open ()
229
229
insns asm.Instructions
@@ -239,7 +239,7 @@ func (ec *elfCode) loadInstructions(section *elf.Section, symbols map[uint64]str
239
239
return nil , 0 , xerrors .Errorf ("offset %d: %w" , offset , err )
240
240
}
241
241
242
- ins .Symbol = symbols [offset ]
242
+ ins .Symbol = symbols [offset ]. Name
243
243
244
244
if rel , ok := relocations [offset ]; ok {
245
245
if err = ec .relocateInstruction (& ins , rel ); err != nil {
@@ -256,9 +256,20 @@ func (ec *elfCode) relocateInstruction(ins *asm.Instruction, rel elf.Symbol) err
256
256
var (
257
257
typ = elf .ST_TYPE (rel .Info )
258
258
bind = elf .ST_BIND (rel .Info )
259
- ref = rel .Name
259
+ name = rel .Name
260
260
)
261
261
262
+ if typ == elf .STT_SECTION {
263
+ // Symbols with section type do not have a name set. Get it
264
+ // from the section itself.
265
+ idx := int (rel .Section )
266
+ if idx > len (ec .Sections ) {
267
+ return xerrors .New ("out-of-bounds section index" )
268
+ }
269
+
270
+ name = ec .Sections [idx ].Name
271
+ }
272
+
262
273
outer:
263
274
switch {
264
275
case ins .OpCode == asm .LoadImmOp (asm .DWord ):
@@ -272,18 +283,10 @@ outer:
272
283
// This is a direct load since the referenced symbol is a
273
284
// section. Weirdly, the offset of the real symbol in the
274
285
// section is encoded in the instruction stream.
275
- idx := int (rel .Section )
276
- if idx > len (ec .Sections ) {
277
- return xerrors .New ("out-of-bounds section index" )
278
- }
279
-
280
286
if bind != elf .STB_LOCAL {
281
- return xerrors .Errorf ("direct load: %s: unsupported relocation %s" , ref , bind )
287
+ return xerrors .Errorf ("direct load: %s: unsupported relocation %s" , name , bind )
282
288
}
283
289
284
- // Make the instruction reference the map it's loading from.
285
- ref = ec .Sections [idx ].Name
286
-
287
290
// For some reason, clang encodes the offset of the symbol its
288
291
// section in the first basic BPF instruction, while the kernel
289
292
// expects it in the second one.
@@ -293,7 +296,7 @@ outer:
293
296
case elf .STT_NOTYPE :
294
297
if bind == elf .STB_GLOBAL && rel .Section == elf .SHN_UNDEF {
295
298
// This is a relocation generated by inline assembly.
296
- // We can't do more than assing ins.Reference.
299
+ // We can't do more than assigning ins.Reference.
297
300
break outer
298
301
}
299
302
@@ -303,10 +306,13 @@ outer:
303
306
304
307
case elf .STT_OBJECT :
305
308
if bind != elf .STB_GLOBAL {
306
- return xerrors .Errorf ("load: %s: unsupported relocation %s" , ref , bind )
309
+ return xerrors .Errorf ("load: %s: unsupported binding: %s" , name , bind )
307
310
}
308
311
309
312
ins .Src = asm .PseudoMapFD
313
+
314
+ default :
315
+ return xerrors .Errorf ("load: %s: unsupported relocation: %s" , name , typ )
310
316
}
311
317
312
318
// Mark the instruction as needing an update when creating the
@@ -316,19 +322,47 @@ outer:
316
322
}
317
323
318
324
case ins .OpCode .JumpOp () == asm .Call :
319
- if bind != elf . STB_GLOBAL {
320
- return xerrors .Errorf ("call: %s: unsupported relocation %s " , ref , bind )
325
+ if ins . Src != asm . PseudoCall {
326
+ return xerrors .Errorf ("call: %s: incorrect source register " , name )
321
327
}
322
328
323
- if typ != elf .STT_NOTYPE && typ != elf .STT_FUNC {
324
- return xerrors .Errorf ("call: %s: invalid symbol type %s" , ref , typ )
329
+ switch typ {
330
+ case elf .STT_NOTYPE , elf .STT_FUNC :
331
+ if bind != elf .STB_GLOBAL {
332
+ return xerrors .Errorf ("call: %s: unsupported binding: %s" , name , bind )
333
+ }
334
+
335
+ case elf .STT_SECTION :
336
+ if bind != elf .STB_LOCAL {
337
+ return xerrors .Errorf ("call: %s: unsupported binding: %s" , name , bind )
338
+ }
339
+
340
+ // The function we want to call is in the indicated section,
341
+ // at the offset encoded in the instruction itself. Reverse
342
+ // the calculation to find the real function we're looking for.
343
+ // A value of -1 references the first instruction in the section.
344
+ offset := int64 (int32 (ins .Constant )+ 1 ) * asm .InstructionSize
345
+ if offset < 0 {
346
+ return xerrors .Errorf ("call: %s: invalid offset %d" , offset )
347
+ }
348
+
349
+ sym , ok := ec .symbolsPerSection [rel .Section ][uint64 (offset )]
350
+ if ! ok {
351
+ return xerrors .Errorf ("call: %s: no symbol at offset %d" , name , offset )
352
+ }
353
+
354
+ ins .Constant = - 1
355
+ name = sym .Name
356
+
357
+ default :
358
+ return xerrors .Errorf ("call: %s: invalid symbol type %s" , name , typ )
325
359
}
326
360
327
361
default :
328
362
return xerrors .Errorf ("relocation for unsupported instruction: %s" , ins .OpCode )
329
363
}
330
364
331
- ins .Reference = ref
365
+ ins .Reference = name
332
366
return nil
333
367
}
334
368
@@ -348,19 +382,19 @@ func (ec *elfCode) loadMaps(maps map[string]*MapSpec, mapSections map[elf.Sectio
348
382
size = sec .Size / uint64 (len (syms ))
349
383
)
350
384
for i , offset := 0 , uint64 (0 ); i < len (syms ); i , offset = i + 1 , offset + size {
351
- mapSym := syms [offset ]
352
- if mapSym == "" {
385
+ mapSym , ok := syms [offset ]
386
+ if ! ok {
353
387
return xerrors .Errorf ("section %s: missing symbol for map at offset %d" , sec .Name , offset )
354
388
}
355
389
356
- if maps [mapSym ] != nil {
390
+ if maps [mapSym . Name ] != nil {
357
391
return xerrors .Errorf ("section %v: map %v already exists" , sec .Name , mapSym )
358
392
}
359
393
360
394
lr := io .LimitReader (r , int64 (size ))
361
395
362
396
spec := MapSpec {
363
- Name : SanitizeName (mapSym , - 1 ),
397
+ Name : SanitizeName (mapSym . Name , - 1 ),
364
398
}
365
399
switch {
366
400
case binary .Read (lr , ec .ByteOrder , & spec .Type ) != nil :
@@ -379,7 +413,7 @@ func (ec *elfCode) loadMaps(maps map[string]*MapSpec, mapSections map[elf.Sectio
379
413
return xerrors .Errorf ("map %v: unknown and non-zero fields in definition" , mapSym )
380
414
}
381
415
382
- maps [mapSym ] = & spec
416
+ maps [mapSym . Name ] = & spec
383
417
}
384
418
}
385
419
@@ -398,21 +432,22 @@ func (ec *elfCode) loadBTFMaps(maps map[string]*MapSpec, mapSections map[elf.Sec
398
432
}
399
433
400
434
for _ , sym := range syms {
401
- if maps [sym ] != nil {
435
+ name := sym .Name
436
+ if maps [name ] != nil {
402
437
return xerrors .Errorf ("section %v: map %v already exists" , sec .Name , sym )
403
438
}
404
439
405
- btfMap , btfMapMembers , err := spec .Map (sym )
440
+ btfMap , btfMapMembers , err := spec .Map (name )
406
441
if err != nil {
407
- return xerrors .Errorf ("map %v: can't get BTF: %w" , sym , err )
442
+ return xerrors .Errorf ("map %v: can't get BTF: %w" , name , err )
408
443
}
409
444
410
445
spec , err := mapSpecFromBTF (btfMap , btfMapMembers )
411
446
if err != nil {
412
- return xerrors .Errorf ("map %v: %w" , sym , err )
447
+ return xerrors .Errorf ("map %v: %w" , name , err )
413
448
}
414
449
415
- maps [sym ] = spec
450
+ maps [name ] = spec
416
451
}
417
452
}
418
453
@@ -640,9 +675,9 @@ func (ec *elfCode) loadRelocations(sections map[elf.SectionIndex]*elf.Section) (
640
675
return result , nil
641
676
}
642
677
643
- func symbolsPerSection (symbols []elf.Symbol ) map [elf.SectionIndex ]map [uint64 ]string {
644
- result := make (map [elf.SectionIndex ]map [uint64 ]string )
645
- for i , sym := range symbols {
678
+ func symbolsPerSection (symbols []elf.Symbol ) map [elf.SectionIndex ]map [uint64 ]elf. Symbol {
679
+ result := make (map [elf.SectionIndex ]map [uint64 ]elf. Symbol )
680
+ for _ , sym := range symbols {
646
681
switch elf .ST_TYPE (sym .Info ) {
647
682
case elf .STT_NOTYPE :
648
683
// Older versions of LLVM doesn't tag
@@ -666,9 +701,9 @@ func symbolsPerSection(symbols []elf.Symbol) map[elf.SectionIndex]map[uint64]str
666
701
667
702
idx := sym .Section
668
703
if _ , ok := result [idx ]; ! ok {
669
- result [idx ] = make (map [uint64 ]string )
704
+ result [idx ] = make (map [uint64 ]elf. Symbol )
670
705
}
671
- result [idx ][sym.Value ] = symbols [ i ]. Name
706
+ result [idx ][sym.Value ] = sym
672
707
}
673
708
return result
674
709
}
0 commit comments