3 Commits

4 changed files with 64 additions and 17 deletions

View File

@ -245,13 +245,17 @@ def _allocate_for_attribute(builder, var_name, rval, local_sym_tab, structs_sym_
# loaded_value = builder.load(field_ir, align=8) # loaded_value = builder.load(field_ir, align=8)
# #TODO: fatal flaw that this always assumes first argument of function to be the context of what this gets. # #TODO: fatal flaw that this always assumes first argument of function to be the context of what this gets.
# base_ptr = builder.function.args[0] base_ptr = builder.function.args[0]
local_sym_tab[
struct_var
].var = base_ptr # This is repurposing of var to store the pointer of the base type
local_sym_tab[struct_var].ir_type = field_ir
# gep_result = builder.gep( # gep_result = builder.gep(
# base_ptr, # base_ptr,
# [loaded_value], # [loaded_value],
# inbounds=False, # Not using inbounds GEP # inbounds=False, # Not using inbounds GEP
# ) # )
# print("DEBB", loaded_value, base_ptr, gep_result) # print("DEBUG", loaded_value, base_ptr, gep_result)
# Use i64 for allocation since that's what the global variable contains # Use i64 for allocation since that's what the global variable contains
actual_ir_type = ir.IntType(64) actual_ir_type = ir.IntType(64)

View File

@ -1,12 +1,11 @@
from enum import Enum, auto from enum import Enum, auto
from typing import Any, Dict, List, Optional, TypedDict from typing import Any, Dict, List, Optional
from dataclasses import dataclass from dataclasses import dataclass
import llvmlite.ir as ir import llvmlite.ir as ir
from pythonbpf.vmlinux_parser.dependency_node import Field from pythonbpf.vmlinux_parser.dependency_node import Field
@dataclass
class AssignmentType(Enum): class AssignmentType(Enum):
CONSTANT = auto() CONSTANT = auto()
STRUCT = auto() STRUCT = auto()
@ -16,7 +15,7 @@ class AssignmentType(Enum):
@dataclass @dataclass
class FunctionSignature(TypedDict): class FunctionSignature:
return_type: str return_type: str
param_types: List[str] param_types: List[str]
varargs: bool varargs: bool
@ -24,7 +23,7 @@ class FunctionSignature(TypedDict):
# Thew name of the assignment will be in the dict that uses this class # Thew name of the assignment will be in the dict that uses this class
@dataclass @dataclass
class AssignmentInfo(TypedDict): class AssignmentInfo:
value_type: AssignmentType value_type: AssignmentType
python_type: type python_type: type
value: Optional[Any] value: Optional[Any]

View File

@ -37,16 +37,16 @@ class VmlinuxHandler:
"""Check if name is a vmlinux enum constant""" """Check if name is a vmlinux enum constant"""
return ( return (
name in self.vmlinux_symtab name in self.vmlinux_symtab
and self.vmlinux_symtab[name]["value_type"] == AssignmentType.CONSTANT and self.vmlinux_symtab[name].value_type == AssignmentType.CONSTANT
) )
def get_vmlinux_struct_type(self, name): def get_vmlinux_struct_type(self, name):
"""Check if name is a vmlinux struct type""" """Check if name is a vmlinux struct type"""
if ( if (
name in self.vmlinux_symtab name in self.vmlinux_symtab
and self.vmlinux_symtab[name]["value_type"] == AssignmentType.STRUCT and self.vmlinux_symtab[name].value_type == AssignmentType.STRUCT
): ):
return self.vmlinux_symtab[name]["python_type"] return self.vmlinux_symtab[name].python_type
else: else:
raise ValueError(f"{name} is not a vmlinux struct type") raise ValueError(f"{name} is not a vmlinux struct type")
@ -54,13 +54,13 @@ class VmlinuxHandler:
"""Check if name is a vmlinux struct""" """Check if name is a vmlinux struct"""
return ( return (
name in self.vmlinux_symtab name in self.vmlinux_symtab
and self.vmlinux_symtab[name]["value_type"] == AssignmentType.STRUCT and self.vmlinux_symtab[name].value_type == AssignmentType.STRUCT
) )
def handle_vmlinux_enum(self, name): def handle_vmlinux_enum(self, name):
"""Handle vmlinux enum constants by returning LLVM IR constants""" """Handle vmlinux enum constants by returning LLVM IR constants"""
if self.is_vmlinux_enum(name): if self.is_vmlinux_enum(name):
value = self.vmlinux_symtab[name]["value"] value = self.vmlinux_symtab[name].value
logger.info(f"Resolving vmlinux enum {name} = {value}") logger.info(f"Resolving vmlinux enum {name} = {value}")
return ir.Constant(ir.IntType(64), value), ir.IntType(64) return ir.Constant(ir.IntType(64), value), ir.IntType(64)
return None return None
@ -68,7 +68,7 @@ class VmlinuxHandler:
def get_vmlinux_enum_value(self, name): def get_vmlinux_enum_value(self, name):
"""Handle vmlinux enum constants by returning LLVM IR constants""" """Handle vmlinux enum constants by returning LLVM IR constants"""
if self.is_vmlinux_enum(name): if self.is_vmlinux_enum(name):
value = self.vmlinux_symtab[name]["value"] value = self.vmlinux_symtab[name].value
logger.info(f"The value of vmlinux enum {name} = {value}") logger.info(f"The value of vmlinux enum {name} = {value}")
return value return value
return None return None
@ -98,24 +98,54 @@ class VmlinuxHandler:
python_type.__name__, field_name python_type.__name__, field_name
) )
# Load the offset value
offset = builder.load(globvar_ir)
# Convert pointer to integer
i64_type = ir.IntType(64)
ptr_as_int = builder.ptrtoint(var_info.var, i64_type)
# Add the offset
field_addr = builder.add(ptr_as_int, offset)
# Convert back to pointer
i8_ptr_type = ir.IntType(8).as_pointer()
field_ptr_i8 = builder.inttoptr(field_addr, i8_ptr_type)
logger.info(f"field_ptr_i8: {field_ptr_i8}")
# Return pointer to field and field type # Return pointer to field and field type
return None return field_ptr_i8, field_data
else: else:
raise RuntimeError("Variable accessed not found in symbol table") raise RuntimeError("Variable accessed not found in symbol table")
def has_field(self, struct_name, field_name): def has_field(self, struct_name, field_name):
"""Check if a vmlinux struct has a specific field""" """Check if a vmlinux struct has a specific field"""
if self.is_vmlinux_struct(struct_name): if self.is_vmlinux_struct(struct_name):
python_type = self.vmlinux_symtab[struct_name]["python_type"] python_type = self.vmlinux_symtab[struct_name].python_type
return hasattr(python_type, field_name) return hasattr(python_type, field_name)
return False return False
def get_field_type(self, vmlinux_struct_name, field_name): def get_field_type(self, vmlinux_struct_name, field_name):
"""Get the type of a field in a vmlinux struct""" """Get the type of a field in a vmlinux struct"""
if self.is_vmlinux_struct(vmlinux_struct_name): if self.is_vmlinux_struct(vmlinux_struct_name):
python_type = self.vmlinux_symtab[vmlinux_struct_name]["python_type"] python_type = self.vmlinux_symtab[vmlinux_struct_name].python_type
if hasattr(python_type, field_name): if hasattr(python_type, field_name):
return self.vmlinux_symtab[vmlinux_struct_name]["members"][field_name] return self.vmlinux_symtab[vmlinux_struct_name].members[field_name]
else:
raise ValueError(
f"Field {field_name} not found in vmlinux struct {vmlinux_struct_name}"
)
else:
raise ValueError(f"{vmlinux_struct_name} is not a vmlinux struct")
def get_field_index(self, vmlinux_struct_name, field_name):
"""Get the type of a field in a vmlinux struct"""
if self.is_vmlinux_struct(vmlinux_struct_name):
python_type = self.vmlinux_symtab[vmlinux_struct_name].python_type
if hasattr(python_type, field_name):
return list(
self.vmlinux_symtab[vmlinux_struct_name].members.keys()
).index(field_name)
else: else:
raise ValueError( raise ValueError(
f"Field {field_name} not found in vmlinux struct {vmlinux_struct_name}" f"Field {field_name} not found in vmlinux struct {vmlinux_struct_name}"

View File

@ -21,7 +21,21 @@ int handle_setuid_entry(struct trace_event_raw_sys_enter *ctx) {
// Access each argument separately with clear variable assignments // Access each argument separately with clear variable assignments
long int arg0 = ctx->id; long int arg0 = ctx->id;
bpf_printk("args[0]: %d", arg0); bpf_printk("args[0]: %d", arg0);
/*
* the IR to aim for is
* %2 = alloca ptr, align 8
* store ptr %0, ptr %2, align 8
* Above, %0 is the arg pointer
* %5 = load ptr, ptr %2, align 8
* %6 = getelementptr inbounds %struct.trace_event_raw_sys_enter, ptr %5, i32 0, i32 2
* %7 = load i64, ptr @"llvm.trace_event_raw_sys_enter:0:16$0:2:0", align 8
* %8 = bitcast ptr %5 to ptr
* %9 = getelementptr i8, ptr %8, i64 %7
* %10 = bitcast ptr %9 to ptr
* %11 = call ptr @llvm.bpf.passthrough.p0.p0(i32 0, ptr %10)
* %12 = load i64, ptr %11, align 8, !dbg !101
*
*/
return 0; return 0;
} }