Skip to content

Commit

Permalink
Change bininspect.InspectWithDWARF to take dwarf data
Browse files Browse the repository at this point in the history
This moves the loading of DWARF data into memory from inside the
bininspect InspectWithDWARF API to outside of it. This allows
dynamic instrumentation to re-use the allocated DWARF data which
would then get passed in. This should drastically reduce the size
of allocations in Go DI while having no effect in the one other
place where the function is used.

Signed-off-by: grantseltzer <[email protected]>
  • Loading branch information
grantseltzer committed Feb 3, 2025
1 parent e41a530 commit ea77939
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 35 deletions.
18 changes: 9 additions & 9 deletions pkg/dynamicinstrumentation/diconfig/binary_inspection.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
package diconfig

import (
"errors"
"fmt"
"reflect"

Expand Down Expand Up @@ -41,9 +42,14 @@ func AnalyzeBinary(procInfo *ditypes.ProcessInfo) error {
targetFunctions[probe.FuncName] = true
}

dwarfData, err := loadDWARF(procInfo.BinaryPath)
elfFile, err := safeelf.Open(procInfo.BinaryPath)
if err != nil {
return fmt.Errorf("could not retrieve debug information from binary: %w", err)
return fmt.Errorf("could not open elf file %w", err)
}

dwarfData, ok := bininspect.HasDwarfInfo(elfFile)
if !ok || dwarfData == nil {
return errors.New("could not get debug information from binary")
}

typeMap, err := getTypeMap(dwarfData, targetFunctions)
Expand All @@ -52,12 +58,6 @@ func AnalyzeBinary(procInfo *ditypes.ProcessInfo) error {
}

procInfo.TypeMap = typeMap

elfFile, err := safeelf.Open(procInfo.BinaryPath)
if err != nil {
return fmt.Errorf("could not open elf file %w", err)
}

procInfo.DwarfData = dwarfData

fieldIDs := make([]bininspect.FieldIdentifier, 0)
Expand All @@ -68,7 +68,7 @@ func AnalyzeBinary(procInfo *ditypes.ProcessInfo) error {
}
}

r, err := bininspect.InspectWithDWARF(elfFile, functions, fieldIDs)
r, err := bininspect.InspectWithDWARF(elfFile, dwarfData, functions, fieldIDs)
if err != nil {
return fmt.Errorf("could not determine locations of variables from debug information %w", err)
}
Expand Down
20 changes: 3 additions & 17 deletions pkg/dynamicinstrumentation/diconfig/dwarf.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (

"github.com/DataDog/datadog-agent/pkg/dynamicinstrumentation/ditypes"
"github.com/DataDog/datadog-agent/pkg/util/log"
"github.com/DataDog/datadog-agent/pkg/util/safeelf"
)

func getTypeMap(dwarfData *dwarf.Data, targetFunctions map[string]bool) (*ditypes.TypeMap, error) {
Expand All @@ -45,13 +44,15 @@ func loadFunctionDefinitions(dwarfData *dwarf.Data, targetFunctions map[string]b
name string
isReturn bool
typeFields *ditypes.Parameter
entry *dwarf.Entry
err error
)

entryLoop:
for {
seenTypes := make(map[string]*seenTypeCounter)

entry, err := entryReader.Next()
entry, err = entryReader.Next()
if err == io.EOF || entry == nil {
break
}
Expand All @@ -62,7 +63,6 @@ entryLoop:
}

if entry.Tag == dwarf.TagCompileUnit {

name, ok := entry.Val(dwarf.AttrName).(string)
if !ok {
continue entryLoop
Expand Down Expand Up @@ -141,7 +141,6 @@ entryLoop:
if err != nil {
return nil, fmt.Errorf("error while parsing debug information: %w", err)
}

}
}

Expand All @@ -163,19 +162,6 @@ entryLoop:
return &result, nil
}

func loadDWARF(binaryPath string) (*dwarf.Data, error) {
elfFile, err := safeelf.Open(binaryPath)
if err != nil {
return nil, fmt.Errorf("couldn't open elf binary: %w", err)
}
defer elfFile.Close()
dwarfData, err := elfFile.DWARF()
if err != nil {
return nil, fmt.Errorf("couldn't retrieve debug info from elf: %w", err)
}
return dwarfData, nil
}

func expandTypeData(offset dwarf.Offset, dwarfData *dwarf.Data, seenTypes map[string]*seenTypeCounter) (*ditypes.Parameter, error) {
typeReader := dwarfData.Reader()

Expand Down
8 changes: 1 addition & 7 deletions pkg/network/go/bininspect/dwarf.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ type dwarfInspector struct {
// It also returns some additional relevant metadata about the given file.
// It is using the DWARF debug data to obtain information, and therefore should be run on elf files that contain debug
// data, like our test binaries.
func InspectWithDWARF(elfFile *safeelf.File, functions []string, structFields []FieldIdentifier) (*Result, error) {
func InspectWithDWARF(elfFile *safeelf.File, dwarfData *dwarf.Data, functions []string, structFields []FieldIdentifier) (*Result, error) {
if elfFile == nil {
return nil, ErrNilElf
}
Expand All @@ -41,12 +41,6 @@ func InspectWithDWARF(elfFile *safeelf.File, functions []string, structFields []
return nil, err
}

dwarfData, ok := HasDwarfInfo(elfFile)

if !ok || dwarfData == nil {
return nil, errors.New("expected dwarf data")
}

inspector := dwarfInspector{
elf: elfMetadata{
file: elfFile,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ package main
import (
"context"
_ "embed"
"errors"
"flag"
"fmt"
"log"
Expand Down Expand Up @@ -260,8 +261,12 @@ func inspectBinary(binary lutgen.Binary) (interface{}, error) {
return bininspect.Result{}, err
}

// Inspect the binary using `binspect`
result, err := bininspect.InspectWithDWARF(elfFile, functionsToFind, FieldsToFind)
dwarfData, ok := bininspect.HasDwarfInfo(elfFile)
if !ok {
return bininspect.Result{}, errors.New("expected dwarf data")
}

result, err := bininspect.InspectWithDWARF(elfFile, dwarfData, functionsToFind, FieldsToFind)
if err != nil {
return bininspect.Result{}, err
}
Expand Down

0 comments on commit ea77939

Please sign in to comment.