Skip to content

Commit

Permalink
feedback changes
Browse files Browse the repository at this point in the history
  • Loading branch information
derekparker committed Oct 17, 2021
1 parent 6e978d7 commit e042108
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 98 deletions.
28 changes: 28 additions & 0 deletions pkg/proc/internal/ebpf/helpers.go
Expand Up @@ -6,6 +6,7 @@ package ebpf
// #include "./trace_probe/function_vals.bpf.h"
import "C"
import (
"debug/elf"
_ "embed"
"encoding/binary"
"errors"
Expand Down Expand Up @@ -206,3 +207,30 @@ func createFunctionParameterList(entry uint64, goidOffset int64, args []UProbeAr
}
return params
}

func AddressToOffset(f *elf.File, addr uint64) (uint32, error) {
sectionsToSearchForSymbol := []*elf.Section{}

for i := range f.Sections {
if f.Sections[i].Flags == elf.SHF_ALLOC+elf.SHF_EXECINSTR {
sectionsToSearchForSymbol = append(sectionsToSearchForSymbol, f.Sections[i])
}
}

var executableSection *elf.Section

// Find what section the symbol is in by checking the executable section's
// addr space.
for m := range sectionsToSearchForSymbol {
if addr > sectionsToSearchForSymbol[m].Addr &&
addr < sectionsToSearchForSymbol[m].Addr+sectionsToSearchForSymbol[m].Size {
executableSection = sectionsToSearchForSymbol[m]
}
}

if executableSection == nil {
return 0, errors.New("could not find symbol in executable sections of binary")
}

return uint32(addr - executableSection.Addr + executableSection.Offset), nil
}
5 changes: 5 additions & 0 deletions pkg/proc/internal/ebpf/helpers_disabled.go
Expand Up @@ -4,6 +4,7 @@
package ebpf

import (
"debug/elf"
"errors"
)

Expand Down Expand Up @@ -37,3 +38,7 @@ func SymbolToOffset(file, symbol string) (uint32, error) {
func LoadEBPFTracingProgram() (*EBPFContext, error) {
return nil, errors.New("eBPF disabled")
}

func AddressToOffset(f *elf.File, addr uint64) (uint32, error) {
return 0, errors.New("eBPF disabled")
}
56 changes: 16 additions & 40 deletions pkg/proc/internal/ebpf/trace_probe/trace.bpf.c
Expand Up @@ -177,39 +177,22 @@ int get_goroutine_id(function_parameter_list_t *parsed_args) {
}

__always_inline
void parse_params(struct pt_regs *ctx, function_parameter_list_t *args, function_parameter_list_t *parsed_args, bool ret) {
void parse_params(struct pt_regs *ctx, unsigned int n_params, function_parameter_t params[6], bool ret) {
// Since we cannot loop in eBPF programs let's take adavantage of the
// fact that in C switch cases will pass through automatically.
if (!ret) {
switch (args->n_parameters) {
case 6:
parse_param(ctx, &parsed_args->params[5]);
case 5:
parse_param(ctx, &parsed_args->params[4]);
case 4:
parse_param(ctx, &parsed_args->params[3]);
case 3:
parse_param(ctx, &parsed_args->params[2]);
case 2:
parse_param(ctx, &parsed_args->params[1]);
case 1:
parse_param(ctx, &parsed_args->params[0]);
}
} else {
switch (args->n_ret_parameters) {
case 6:
parse_param(ctx, &parsed_args->ret_params[5]);
case 5:
parse_param(ctx, &parsed_args->ret_params[4]);
case 4:
parse_param(ctx, &parsed_args->ret_params[3]);
case 3:
parse_param(ctx, &parsed_args->ret_params[2]);
case 2:
parse_param(ctx, &parsed_args->ret_params[1]);
case 1:
parse_param(ctx, &parsed_args->ret_params[0]);
}
switch (n_params) {
case 6:
parse_param(ctx, &params[5]);
case 5:
parse_param(ctx, &params[4]);
case 4:
parse_param(ctx, &params[3]);
case 3:
parse_param(ctx, &params[2]);
case 2:
parse_param(ctx, &params[1]);
case 1:
parse_param(ctx, &params[0]);
}
}

Expand Down Expand Up @@ -247,20 +230,13 @@ int uprobe__dlv_trace(struct pt_regs *ctx) {
if (!args->is_ret) {
// In uprobe at function entry.

// We're in the entry point of the function at the uprobe we set.
// Get our return address and ensure that we set the parameter information
// at that address as well for the uretprobe.
size_t ret_addr;
bpf_probe_read_user(&ret_addr, sizeof(size_t), (void*)(ctx->sp));
bpf_map_update_elem(&arg_map, &ret_addr, args, 0);

// Parse input parameters.
parse_params(ctx, args, parsed_args, false);
parse_params(ctx, args->n_parameters, parsed_args->params, false);
} else {
// We are now stopped at the RET instruction for this function.

// Parse output parameters.
parse_params(ctx, args, parsed_args, true);
parse_params(ctx, args->n_ret_parameters, parsed_args->ret_params, true);
}

bpf_ringbuf_submit(parsed_args, 0);
Expand Down
73 changes: 23 additions & 50 deletions pkg/proc/native/proc_linux.go
Expand Up @@ -751,61 +751,34 @@ func (dbp *nativeProcess) SetUProbe(fnName string, goidOffset int64, args []ebpf
if err != nil {
return fmt.Errorf("could not open elf file to resolve symbol offset: %w", err)
}
syms, err := f.Symbols()

var regs proc.Registers
mem := dbp.Memory()
regs, _ = dbp.memthread.Registers()
instructions, err := proc.Disassemble(mem, regs, &proc.BreakpointMap{}, dbp.BinInfo(), fn.Entry, fn.End)
if err != nil {
return fmt.Errorf("could not open symbol section to resolve symbol offset: %w", err)
return err
}

sectionsToSearchForSymbol := []*elf.Section{}

for i := range f.Sections {
if f.Sections[i].Flags == elf.SHF_ALLOC+elf.SHF_EXECINSTR {
sectionsToSearchForSymbol = append(sectionsToSearchForSymbol, f.Sections[i])
var addrs []uint64
for _, instruction := range instructions {
if instruction.IsRet() {
addrs = append(addrs, instruction.Loc.PC)
}
}

var executableSection *elf.Section

for j := range syms {
if syms[j].Name == fnName {
// Find what section the symbol is in by checking the executable section's
// addr space.
for m := range sectionsToSearchForSymbol {
if syms[j].Value > sectionsToSearchForSymbol[m].Addr &&
syms[j].Value < sectionsToSearchForSymbol[m].Addr+sectionsToSearchForSymbol[m].Size {
executableSection = sectionsToSearchForSymbol[m]
}
}

if executableSection == nil {
return errors.New("could not find symbol in executable sections of binary")
}
var regs proc.Registers
mem := dbp.Memory()
regs, _ = dbp.memthread.Registers()
instructions, err := proc.Disassemble(mem, regs, &proc.BreakpointMap{}, dbp.BinInfo(), fn.Entry, fn.End)
if err != nil {
return err
}

var addrs []uint64
for _, instruction := range instructions {
if instruction.IsRet() {
addrs = append(addrs, instruction.Loc.PC)
}
}
addrs = append(addrs, proc.FindDeferReturnCalls(instructions)...)
for _, addr := range addrs {
err := dbp.os.ebpf.UpdateArgMap(addr, goidOffset, args, dbp.BinInfo().GStructOffset(), true)
if err != nil {
return err
}
off := uint32(addr - executableSection.Addr + executableSection.Offset)
err = dbp.os.ebpf.AttachUprobe(dbp.Pid(), debugname, off)
if err != nil {
return err
}
}
addrs = append(addrs, proc.FindDeferReturnCalls(instructions)...)
for _, addr := range addrs {
err := dbp.os.ebpf.UpdateArgMap(addr, goidOffset, args, dbp.BinInfo().GStructOffset(), true)
if err != nil {
return err
}
off, err := ebpf.AddressToOffset(f, addr)
if err != nil {
return err
}
err = dbp.os.ebpf.AttachUprobe(dbp.Pid(), debugname, off)
if err != nil {
return err
}
}

Expand Down
12 changes: 4 additions & 8 deletions pkg/proc/target.go
Expand Up @@ -426,6 +426,10 @@ func (t *Target) GetBufferedTracepoints() []*UProbeTraceResult {
compMem, _ := CreateCompositeMemory(cachedMem, t.BinInfo().Arch, op.DwarfRegisters{}, ip.Pieces)
v.mem = compMem

// Load the value here so that we don't have to export
// loadValue outside of proc.
v.loadValue(loadFullValue)

return v
}
for _, tp := range tracepoints {
Expand All @@ -434,18 +438,10 @@ func (t *Target) GetBufferedTracepoints() []*UProbeTraceResult {
r.GoroutineID = tp.GoroutineID
for _, ip := range tp.InputParams {
v := convertInputParamToVariable(ip)

// Load the value here so that we don't have to export
// loadValue outside of proc.
v.loadValue(loadFullValue)
r.InputParams = append(r.InputParams, v)
}
for _, ip := range tp.ReturnParams {
v := convertInputParamToVariable(ip)

// Load the value here so that we don't have to export
// loadValue outside of proc.
v.loadValue(loadFullValue)
r.ReturnParams = append(r.ReturnParams, v)
}
results = append(results, r)
Expand Down

0 comments on commit e042108

Please sign in to comment.