MCPcopy Create free account
hub / github.com/google/pprof / openELF

Method openELF

internal/binutils/binutils.go:428–496  ·  view source on GitHub ↗
(name string, start, limit, offset uint64, relocationSymbol string)

Source from the content-addressed store, hash-verified

426}
427
428func (b *binrep) openELF(name string, start, limit, offset uint64, relocationSymbol string) (plugin.ObjFile, error) {
429 ef, err := elfOpen(name)
430 if err != nil {
431 return nil, fmt.Errorf("error parsing %s: %v", name, err)
432 }
433 defer ef.Close()
434
435 buildID := ""
436 if id, err := elfexec.GetBuildID(ef); err == nil {
437 buildID = fmt.Sprintf("%x", id)
438 }
439
440 var (
441 kernelOffset *uint64
442 pageAligned = func(addr uint64) bool { return addr%4096 == 0 }
443 )
444 if strings.Contains(name, "vmlinux") || !pageAligned(start) || !pageAligned(limit) || !pageAligned(offset) {
445 // Reading all Symbols is expensive, and we only rarely need it so
446 // we don't want to do it every time. But if _stext happens to be
447 // page-aligned but isn't the same as Vaddr, we would symbolize
448 // wrong. So if the name the addresses aren't page aligned, or if
449 // the name is "vmlinux" we read _stext. We can be wrong if: (1)
450 // someone passes a kernel path that doesn't contain "vmlinux" AND
451 // (2) _stext is page-aligned AND (3) _stext is not at Vaddr
452 symbols, err := ef.Symbols()
453 if err != nil && err != elf.ErrNoSymbols {
454 return nil, err
455 }
456
457 // The kernel relocation symbol (the mapping start address) can be either
458 // _text or _stext. When profiles are generated by `perf`, which one was used is
459 // distinguished by the mapping name for the kernel image:
460 // '[kernel.kallsyms]_text' or '[kernel.kallsyms]_stext', respectively. If we haven't
461 // been able to parse it from the mapping, we default to _stext.
462 if relocationSymbol == "" {
463 relocationSymbol = "_stext"
464 }
465 for _, s := range symbols {
466 if s.Name == relocationSymbol {
467 kernelOffset = &s.Value
468 break
469 }
470 }
471 }
472
473 // Check that we can compute a base for the binary. This may not be the
474 // correct base value, so we don't save it. We delay computing the actual base
475 // value until we have a sample address for this mapping, so that we can
476 // correctly identify the associated program segment that is needed to compute
477 // the base.
478 if _, err := elfexec.GetBase(&ef.FileHeader, elfexec.FindTextProgHeader(ef), kernelOffset, start, limit, offset); err != nil {
479 return nil, fmt.Errorf("could not identify base for %s: %v", name, err)
480 }
481
482 if b.fast || (!b.addr2lineFound && !b.llvmSymbolizerFound) {
483 return &fileNM{file: file{
484 b: b,
485 name: name,

Callers 3

TestELFObjAddrFunction · 0.95
TestELFKernelOffsetFunction · 0.95
OpenMethod · 0.80

Calls 5

GetBuildIDFunction · 0.92
GetBaseFunction · 0.92
FindTextProgHeaderFunction · 0.92
CloseMethod · 0.65
SymbolsMethod · 0.65

Tested by 2

TestELFObjAddrFunction · 0.76
TestELFKernelOffsetFunction · 0.76