Sys-Ebpf
view release on metacpan or search on metacpan
lib/Sys/Ebpf/Loader.pm view on Meta::CPAN
};
return $self->load_bpf_program($bpf_attrs);
}
sub load_bpf_program {
my ( $self, $bpf_attrs ) = @_;
my $defaults = {
prog_type => 0,
insn_cnt => 0,
insns => "",
license => "",
log_level => 1,
log_size => 1024 * 10,
log_buf => "\0" x ( 1024 * 10 ),
kern_version => 0,
prog_flags => 0,
};
my $attrs = { %$defaults, %$bpf_attrs, };
# bpf_attræ§é ä½ã®ããã¯
my $attr = pack(
"L L Q Q L L Q L L",
$attrs->{prog_type},
$attrs->{insn_cnt},
unpack( "Q", pack( "P", $attrs->{insns} ) ),
unpack( "Q", pack( "P", $attrs->{license} ) ),
$attrs->{log_level},
$attrs->{log_size},
unpack( "Q", pack( "P", $attrs->{log_buf} ) ),
$attrs->{kern_version},
$attrs->{prog_flags}
);
# syscallã®å®è¡
my $fd = syscall( Sys::Ebpf::Syscall::SYS_bpf(),
BPF_PROG_LOAD, $attr, length($attr) );
if ( $fd < 0 ) {
my $errno = $!;
warn "Errno: $errno\n";
if ( $errno == EACCES || $errno == EPERM ) {
warn "Permission denied. Are you running as root?\n";
}
warn "Log buffer content:\n", $attrs->{log_buf}, "\n";
die "BPF program load failed: $!\n";
}
return $fd;
}
# ãªãã±ã¼ã·ã§ã³ãé©ç¨
# args:
# prob_section: ããã°ã©ã ã»ã¯ã·ã§ã³
# reloc_sections: ãªãã±ã¼ã·ã§ã³ã»ã¯ã·ã§ã³
# elf: ELFãã¼ã¿
# map_hash_ref: ããããã¼ã¿ã®ãªãã¡ã¬ã³ã¹
# r_offsetã使ã£ã¦ãä¿®æ£ãã¹ãå½ä»¤ï¼ã¤ã³ã¹ãã©ã¯ã·ã§ã³ï¼ãkprobe/sys_execveã»ã¯ã·ã§ã³å
ããç¹å®ãã¾ãã
# r_infoããã·ã³ãã«ã¤ã³ããã¯ã¹ãåå¾ãããã®ã·ã³ãã«ã®ã¢ãã¬ã¹ãã·ã³ãã«ãã¼ãã«ï¼.symtabï¼ããåå¾ãã¾ãã
# ä¿®æ£ãã¹ãã¤ã³ã¹ãã©ã¯ã·ã§ã³ã«ãã·ã³ãã«ã®ã¢ãã¬ã¹ãé©ç¨ãã¦ãæ£ãããããã¸ã®åç
§ã«æ¸ãæãã¾ãã
sub apply_map_relocations {
my ( $self, $prob_section, $reloc_sections, $elf, $map_hash_ref ) = @_;
my $symbols_section = $elf->{symbols};
for my $reloc_section (@$reloc_sections) {
my $r_info = $reloc_section->{r_info};
my $r_offset
= $reloc_section->{r_offset} + $prob_section->{sh_offset};
my $sym_index = $r_info >> 32; # ã·ã³ãã«ã¤ã³ããã¯ã¹ãåå¾
my $reloc_type = $r_info & 0xFFFFFFFF; # ãªãã±ã¼ã·ã§ã³ã¿ã¤ããåå¾
# ã·ã³ãã«ãã¼ãã«ããrelocation対象ã«ãªãå¾ãã·ã³ãã«åãåå¾
my $symbol = $symbols_section->[$sym_index] // undef;
if ( !$symbol ) {
print "Symbol Table not found for index: $sym_index\n";
next;
}
my $sym_name = $symbol->{st_name};
if ( $symbol->{st_shndx} == 0 ) {
print "Symbol Name Table not found for index: $sym_index\n";
next;
}
# `$map_data` ã®ä¸ã®ã¿ãã«ã確èªãã¦ãæå¾
ãã¦ããããåãåå¨ããããã§ãã¯(fdãåå¾)
my $map_fd = undef;
for my $map_name ( keys %$map_hash_ref ) {
my $map = $map_hash_ref->{$map_name};
if ( $sym_name eq $map_name ) {
$map_fd = $map->{map_fd};
last; # ããããè¦ã¤ãã£ããã«ã¼ããæãã
}
}
if ( defined $map_fd ) {
# æå®ããããªãã»ããä½ç½®ã«ãã `lddw` å½ä»¤ï¼16ãã¤ãï¼ãåå¾
my $bpf_insn
= substr( $self->{reader}->{raw_elf_data}, $r_offset, 16 )
; # 16ãã¤ããåå¾
my $bpf_insn_len = length($bpf_insn);
my ( $high, $low )
= Sys::Ebpf::Asm::deserialize_128bit_instruction($bpf_insn);
# å³å¤ (64ããã) ã«ãããFDãè¨å®
$high->set_imm($map_fd);
$low->set_imm( $map_fd >> 32 );
# src_reg ã« PSEUDO_MAP_FD (1) ãè¨å®
$high->set_src_reg(1);
# ä¿®æ£å¾ã®å½ä»¤ãããã¯ãã¦ãå
ã®å ´æã«æ¸ãæ»ã
my $new_bpf_insn
= Sys::Ebpf::Asm::serialize_128bit_instruction( $high, $low );
substr( $self->{reader}->{raw_elf_data},
$r_offset, 16, $new_bpf_insn );
# æ¸ãæããå¾ã®å½ä»¤ãåºå
my $after_bpf_insn
= substr( $self->{reader}->{raw_elf_data}, $r_offset, 16 );
}
}
}
# BPF ããã°ã©ã ã¨ãããããã¼ã
# args:
# section_name: BPF ããã°ã©ã ã®ã»ã¯ã·ã§ã³å
# return:
# map_collection: ãããåã¨FDã®çµã«ãªã£ãhashã®ãªãã¡ã¬ã³ã¹
# prog_fd: ããã°ã©ã FD
sub load_bpf {
my ( $self, $section_name ) = @_;
my $bpfelf = $self->{bpfelf};
my $maps = $self->extract_bpf_map_attributes('maps');
my %map_collection;
# map_attr_refã®åãã¼ï¼ãããåï¼ã«å¯¾ãã¦å¦çãå®è¡
for my $map (@$maps) {
my $map_name = $map->{map_name};
my $map_instance = Sys::Ebpf::Map->create($map);
my $map_fd = $map_instance->{map_fd};
if ( $map_fd < 0 ) {
die "Failed to load BPF map: $map_name (FD: $map_fd})\n";
}
$map_collection{$map_name} = $map_instance;
}
# ãªãã±ã¼ã·ã§ã³ãé©ç¨
my $reloc_section = $bpfelf->{relocations}{ ".rel" . $section_name };
my $prob_section
= find_symbol_table_from_name( $bpfelf->{sections}, $section_name );
if ( defined $reloc_section ) {
$self->apply_map_relocations( $prob_section, $reloc_section, $bpfelf,
\%map_collection );
}
# todo: bpfprobãè¤æ°ããã±ã¼ã¹ã«ã対å¿ãã
# BPF ããã°ã©ã ããã¼ã
my $prog_fd = $self->load_bpf_program_from_elf($section_name);
return ( \%map_collection, $prog_fd );
}
1;
( run in 0.517 second using v1.01-cache-2.11-cpan-71847e10f99 )