Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 41 additions & 41 deletions process/coredump.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,30 +23,30 @@ import (
)

const (
// maxNotesSection the maximum section size for notes
// maxNotesSection is the maximum section size for notes.
maxNotesSection = 16 * 1024 * 1024
)

// CoredumpProcess implements Process interface to ELF coredumps
// CoredumpProcess implements Process interface to ELF coredumps.
type CoredumpProcess struct {
*pfelf.File

// files contains coredump's files by name
// files contains coredump's files by name.
files map[string]*CoredumpFile

// pid the original PID of the coredump
// pid is the original PID from which the coredump was generated.
pid libpf.PID

// machineData contains the parsed machine data
// machineData contains the parsed machine data.
machineData MachineData

// mappings contains the parsed mappings
// mappings contains the parsed mappings.
mappings []Mapping

// threadInfo contains the parsed thread info
// threadInfo contains the parsed thread info.
threadInfo []ThreadInfo

// execPhdrPtr points to the main executable's program headers
// execPhdrPtr points to the main executable's program headers.
execPhdrPtr libpf.Address

// hasMusl is set if musl c-library is detected in this coredump. This
Expand All @@ -57,27 +57,27 @@ type CoredumpProcess struct {

var _ Process = &CoredumpProcess{}

// CoredumpMapping describes a file backed mapping in a coredump
// CoredumpMapping describes a file backed mapping in a coredump.
type CoredumpMapping struct {
// Corresponding PT_LOAD segment
// Prog points to the corresponding PT_LOAD segment.
Prog *pfelf.Prog
// File is the backing file for this mapping
// File is the backing file for this mapping.
File *CoredumpFile
// FileOffset is the offset in the original backing file
// FileOffset is the offset in the original backing file.
FileOffset uint64
}

// CoredumpFile contains information about a file mapped into a coredump
// CoredumpFile contains information about a file mapped into a coredump.
type CoredumpFile struct {
// parent is the Coredump inside which this file is
// parent is the Coredump inside which this file is.
parent *CoredumpProcess
// inode is the synthesized inode for this file
// inode is the synthesized inode for this file.
inode uint64
// Name is the mapped file's name
// Name is the mapped file's name.
Name string
// Mappings contains mappings regarding this file
// Mappings contains mappings regarding this file.
Mappings []CoredumpMapping
// Base is the virtual address where this file is loaded
// Base is the virtual address where this file is loaded.
Base uint64
}

Expand Down Expand Up @@ -127,10 +127,10 @@ func OpenCoredump(name string) (*CoredumpProcess, error) {
// It's the value of a map indexed with mapping virtual address, and contains the data
// needed to associate data from different coredump data structures to proper internals.
type vaddrMappings struct {
// prog is the ELF PT_LOAD Program header for this virtual address
// prog is the ELF PT_LOAD Program header for this virtual address.
prog *pfelf.Prog

// mappingIndex is the mapping's index in processState.Mappings
// mappingIndex is the mapping's index in processState.Mappings.
mappingIndex int
}

Expand Down Expand Up @@ -194,7 +194,7 @@ func OpenCoredumpFile(f *pfelf.File) (*CoredumpProcess, error) {
break
}

// Parse the note if we are interested in it (skip others)
// Parse the note if we are interested in it (skip others).
name := string(nameBytes)
ty := elf.NType(note.Type)
if name == NAMESPACE_CORE {
Expand Down Expand Up @@ -247,38 +247,38 @@ func (cd *CoredumpProcess) MainExecutable() string {
return ""
}

// PID implements the Process interface
// PID implements the Process interface.
func (cd *CoredumpProcess) PID() libpf.PID {
return cd.pid
}

// GetMachineData implements the Process interface
// GetMachineData implements the Process interface.
func (cd *CoredumpProcess) GetMachineData() MachineData {
return cd.machineData
}

// GetMappings implements the Process interface
// GetMappings implements the Process interface.
func (cd *CoredumpProcess) GetMappings() ([]Mapping, uint32, error) {
return cd.mappings, 0, nil
}

// GetThreadInfo implements the Process interface
// GetThreadInfo implements the Process interface.
func (cd *CoredumpProcess) GetThreads() ([]ThreadInfo, error) {
return cd.threadInfo, nil
}

// OpenMappingFile implements the Process interface
// OpenMappingFile implements the Process interface.
func (cd *CoredumpProcess) OpenMappingFile(_ *Mapping) (ReadAtCloser, error) {
// No filesystem level backing file in coredumps
// Coredumps do not contain the original backing files.
return nil, errors.New("coredump does not support opening backing file")
}

// GetMappingFileLastModified implements the Process interface
// GetMappingFileLastModified implements the Process interface.
func (cd *CoredumpProcess) GetMappingFileLastModified(_ *Mapping) int64 {
return 0
}

// CalculateMappingFileID implements the Process interface
// CalculateMappingFileID implements the Process interface.
func (cd *CoredumpProcess) CalculateMappingFileID(m *Mapping) (libpf.FileID, error) {
// It is not possible to calculate the real FileID as the section headers
// are likely missing. So just return a synthesized FileID.
Expand All @@ -291,7 +291,7 @@ func (cd *CoredumpProcess) CalculateMappingFileID(m *Mapping) (libpf.FileID, err
return libpf.FileIDFromBytes(h.Sum(nil))
}

// OpenELF implements the ELFOpener and Process interfaces
// OpenELF implements the ELFOpener and Process interfaces.
func (cd *CoredumpProcess) OpenELF(path string) (*pfelf.File, error) {
// Fallback to directly returning the data from coredump. This comes with caveats:
//
Expand All @@ -312,13 +312,13 @@ func (cd *CoredumpProcess) OpenELF(path string) (*pfelf.File, error) {
return nil, fmt.Errorf("ELF file `%s` not found", path)
}

// ExtractAsFile implements the Process interface
// ExtractAsFile implements the Process interface.
func (cd *CoredumpProcess) ExtractAsFile(_ string) (string, error) {
// No filesystem level backing file in coredumps
// Coredumps do not contain the original backing files.
return "", errors.New("coredump does not support opening backing file")
}

// getFile returns (creating if needed) a matching CoredumpFile for given file name
// getFile returns (creating if needed) a matching CoredumpFile for given file name.
func (cd *CoredumpProcess) getFile(name string) *CoredumpFile {
if cf, ok := cd.files[name]; ok {
return cf
Expand All @@ -335,18 +335,18 @@ func (cd *CoredumpProcess) getFile(name string) *CoredumpFile {
return cf
}

// FileMappingHeader64 is the header for CORE/NT_FILE note
// FileMappingHeader64 is the header for CORE/NT_FILE note.
type FileMappingHeader64 struct {
Entries uint64
PageSize uint64
}

// FileMappingEntry64 is the per-mapping data header in CORE/NT_FILE note
// FileMappingEntry64 is the per-mapping data header in CORE/NT_FILE note.
type FileMappingEntry64 struct {
Start, End, FileOffset uint64
}

// parseMappings processes CORE/NT_FILE note with description of memory mappings
// parseMappings processes a CORE/NT_FILE note with the description of memory mappings.
func (cd *CoredumpProcess) parseMappings(desc []byte,
vaddrToMappings map[uint64]vaddrMappings) error {
hdrSize := uint64(unsafe.Sizeof(FileMappingHeader64{}))
Expand Down Expand Up @@ -392,7 +392,7 @@ func (cd *CoredumpProcess) parseMappings(desc []byte,
mapping := &cd.mappings[m.mappingIndex]
mapping.Path = cf.Name
mapping.FileOffset = entry.FileOffset * hdr.PageSize
// Synthesize non-zero device and inode indicating this is a filebacked mapping
// Synthesize non-zero device and inode indicating this is a filebacked mapping.
mapping.Device = 1
mapping.Inode = cf.inode
}
Expand All @@ -401,7 +401,7 @@ func (cd *CoredumpProcess) parseMappings(desc []byte,
return nil
}

// parseAuxVector processes CORE/NT_AUXV note
// parseAuxVector processes a CORE/NT_AUXV note.
func (cd *CoredumpProcess) parseAuxVector(desc []byte, vaddrToMappings map[uint64]vaddrMappings) {
for i := 0; i+16 <= len(desc); i += 16 {
value := binary.LittleEndian.Uint64(desc[i+8:])
Expand Down Expand Up @@ -429,7 +429,7 @@ func (cd *CoredumpProcess) parseAuxVector(desc []byte, vaddrToMappings map[uint6
}
}

// PrpsInfo64 is the 64-bit NT_PRPSINFO note header
// PrpsInfo64 is the 64-bit NT_PRPSINFO note header.
type PrpsInfo64 struct {
State uint8
Sname uint8
Expand All @@ -447,7 +447,7 @@ type PrpsInfo64 struct {
Args [80]byte
}

// parseProcessInfo processes CORE/NT_PRPSINFO note
// parseProcessInfo processes a CORE/NT_PRPSINFO note.
func (cd *CoredumpProcess) parseProcessInfo(desc []byte) error {
if len(desc) == int(unsafe.Sizeof(PrpsInfo64{})) {
info := (*PrpsInfo64)(unsafe.Pointer(&desc[0]))
Expand All @@ -457,7 +457,7 @@ func (cd *CoredumpProcess) parseProcessInfo(desc []byte) error {
return fmt.Errorf("unsupported NT_PRPSINFO size: %d", len(desc))
}

// parseProcessStatus processes CORE/NT_PRSTATUS note
// parseProcessStatus processes a CORE/NT_PRSTATUS note.
func (cd *CoredumpProcess) parseProcessStatus(desc []byte) error {
// The corresponding struct definition can be found here:
// https://github.com/torvalds/linux/blob/49d766f3a0e4/include/linux/elfcore.h#L48
Expand Down
50 changes: 25 additions & 25 deletions process/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,27 @@ import (
"go.opentelemetry.io/ebpf-profiler/util"
)

// VdsoPathName is the path to use for VDSO mappings
// VdsoPathName is the path to use for VDSO mappings.
const VdsoPathName = "linux-vdso.1.so"

// vdsoInode is the synthesized inode number for VDSO mappings
// vdsoInode is the synthesized inode number for VDSO mappings.
const vdsoInode = 50

// Mapping contains information about a memory mapping
// Mapping contains information about a memory mapping.
type Mapping struct {
// Vaddr is the virtual memory start for this mapping
// Vaddr is the virtual memory start for this mapping.
Vaddr uint64
// Length is the length of the mapping
// Length is the length of the mapping.
Length uint64
// Flags contains the mapping flags and permissions
// Flags contains the mapping flags and permissions.
Flags elf.ProgFlag
// FileOffset contains for file backed mappings the offset from the file start
// FileOffset contains for file backed mappings the offset from the file start.
FileOffset uint64
// Device holds the device ID where the file is located
// Device holds the device ID where the file is located.
Device uint64
// Inode holds the mapped file's inode number
// Inode holds the mapped file's inode number.
Inode uint64
// Path contains the file name for file backed mappings
// Path contains the file name for file backed mappings.
Path string
}

Expand All @@ -63,27 +63,27 @@ func (m *Mapping) GetOnDiskFileIdentifier() util.OnDiskFileIdentifier {
}
}

// ThreadInfo contains the information about a thread CPU state needed for unwinding
// ThreadInfo contains the information about a thread CPU state needed for unwinding.
type ThreadInfo struct {
// TPBase contains the Thread Pointer Base value
// TPBase contains the Thread Pointer Base value.
TPBase uint64
// GPRegs contains the CPU state (registers) for the thread
// GPRegs contains the CPU state (registers) for the thread.
GPRegs []byte
// LWP is the Light Weight Process ID (thread ID)
// LWP is the Light Weight Process ID (thread ID).
LWP uint32
}

// MachineData contains machine specific information about the process
// MachineData contains machine specific information about the process.
type MachineData struct {
// Machine is the Process Machine type
// Machine is the Process Machine type.
Machine elf.Machine
// CodePACMask contains the PAC mask for code pointers. ARM64 specific, otherwise 0.
CodePACMask uint64
// DataPACMask contains the PAC mask for data pointers. ARM64 specific, otherwise 0.
DataPACMask uint64
}

// ReadAtCloser interfaces implements io.ReaderAt and io.Closer
// ReadAtCloser combines the io.ReaderAt and io.Closer interfaces.
type ReadAtCloser interface {
io.ReaderAt
io.Closer
Expand All @@ -94,29 +94,29 @@ type ReadAtCloser interface {
// from different goroutines. As an exception the ELFOpener and the returned
// GetRemoteMemory object are safe for concurrent use.
type Process interface {
// PID returns the process identifier
// PID returns the process identifier.
PID() libpf.PID

// GetMachineData reads machine specific data from the target process
// GetMachineData reads machine specific data from the target process.
GetMachineData() MachineData

// GetMappings reads and parses process memory mappings
// GetMappings reads and parses process memory mappings.
GetMappings() ([]Mapping, uint32, error)

// GetThreads reads the process thread states
// GetThreads reads the process thread states.
GetThreads() ([]ThreadInfo, error)

// GetRemoteMemory returns a remote memory reader accessing the target process
// GetRemoteMemory returns a remote memory reader accessing the target process.
GetRemoteMemory() remotememory.RemoteMemory

// OpenMappingFile returns ReadAtCloser accessing the backing file of the mapping
// OpenMappingFile returns ReadAtCloser accessing the backing file of the mapping.
OpenMappingFile(*Mapping) (ReadAtCloser, error)

// GetMappingFileLastModifed returns the timestamp when the backing file was last modified
// or zero if an error occurs or mapping file is not accessible via filesystem
// or zero if an error occurs or mapping file is not accessible via filesystem.
GetMappingFileLastModified(*Mapping) int64

// CalculateMappingFileID calculates FileID of the backing file
// CalculateMappingFileID calculates FileID of the backing file.
CalculateMappingFileID(*Mapping) (libpf.FileID, error)

// ExtractAsFile returns a filename suitable for opening the given file from
Expand Down