Skip to content

Commit

Permalink
refine stack merge, process some race condition
Browse files Browse the repository at this point in the history
  • Loading branch information
findstr committed Nov 24, 2023
1 parent 89e53c5 commit ed35497
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 28 deletions.
16 changes: 14 additions & 2 deletions src/bpf/profile.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ unwind_c(u32 i, void *ud)
lua->buf[x] = lua->L;
lua->cnt[x] = lua->L_cnt;
lua->L = L;
lua->L_cnt = 1;
lua->L_cnt = 1;
lua->count++;
}
DEBUG("unwind_c lua stack change:%lx", L);
Expand Down Expand Up @@ -268,6 +268,18 @@ unwind_lua(u32 i, void *ud)
DEBUG("unwind_lua read L error:%d", err);
return LOOP_BREAK;
}
//try extend more one lua frame for race condition
if (ctx->lua_index == 0 && ctx->ci != NULL) {
err = bpf_probe_read_user(ci, sizeof(*ci), (void *)ctx->ci);
if (err != 0) {
ERROR("unwind_lua read ci error:%d", err);
return LOOP_BREAK;
}
if (ci->next != NULL) {
ctx->ci = ci->next;
ctx->calln++;
}
}
ctx->lua_index++;
}
err = bpf_probe_read_user(ci, sizeof(*ci), (void *)ctx->ci);
Expand Down Expand Up @@ -295,7 +307,7 @@ unwind_lua(u32 i, void *ud)
ci->previous = NULL;
}
}
ctx->ci = ci->previous;
ctx->ci = ci->previous;
return LOOP_CONTINUE;
}

Expand Down
3 changes: 2 additions & 1 deletion src/bpf/profile.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ static __always_inline void cache_str_cpy(struct string *dst, const struct strin
}

DECLARE_TMP_VAR(struct string, str_buf);
static __always_inline u32 string_to_id(char *str, size_t len)
static __always_inline u32 string_to_id(char *str, u32 len)
{
int err;
u32 hash, i;
Expand All @@ -299,6 +299,7 @@ static __always_inline u32 string_to_id(char *str, size_t len)
str += len - sizeof(str_buf->data);
len = sizeof(str_buf->data);
}
len &= 0xfffff;
str_buf->len = len;
err = bpf_probe_read_user(str_buf->data, str_buf->len, str);
if (err != 0) {
Expand Down
49 changes: 29 additions & 20 deletions src/perf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;
use std::vec::Vec;
use blazesym::symbolize;
use gimli::Register;
use gimli::X86_64;
use goblin::elf::Elf;
use libc::pid_t;
Expand Down Expand Up @@ -334,7 +333,7 @@ impl Perf {
let eh_list = result.0;
let lua_fn = result.1;
//tracing
let level = LevelFilter::DEBUG;
let level = LevelFilter::INFO;
let subscriber = FmtSubscriber::builder()
.with_max_level(level)
.with_span_events(FmtSpan::FULL)
Expand All @@ -343,7 +342,7 @@ impl Perf {
let () = set_global_subscriber(subscriber).expect("failed to set tracing subscriber");
let mut skel_builder = ProfileSkelBuilder::default();
//TODO:enable debug
skel_builder.obj_builder.debug(true);
skel_builder.obj_builder.debug(false);
let mut open_skel = skel_builder.open().unwrap();
//set max entries
open_skel.bss().EH_FRAME_COUNT = eh_list.len() as u32;
Expand All @@ -365,7 +364,6 @@ impl Perf {
open_skel.bss().ctrl.lua_eip_end = lua_fn.addr + lua_fn.size;
for (i, var) in lua_fn.vars.iter().enumerate() {
open_skel.bss().ctrl.lua_var_pos[i] = Self::bpf_var_pos(var);
println!("lua_var_pos:{:?}", open_skel.bss().ctrl.lua_var_pos[i]);
}

//open_skel.bss().ctrl
Expand Down Expand Up @@ -399,7 +397,7 @@ impl Perf {
buf.leak().as_mut_ptr() as *mut syscall::perf_event_attr
)
};
attr._type = syscall::PERF_TYPE_HARDWARE;
attr._type = syscall::PERF_TYPE_SOFTWARE;
attr.size = mem::size_of::<syscall::perf_event_attr>() as u32;
attr.config = syscall::PERF_COUNT_HW_CPU_CYCLES;
attr.sample.sample_freq = freq;
Expand Down Expand Up @@ -573,7 +571,8 @@ impl Perf {
println!();

let stack = StackFrame::from_event(event);
let stack_strs = self.combine_stack(skel, &stack);
let mut stack_strs = self.combine_stack(skel, &stack);
stack_strs.reverse();
println!("combined:");
println!("{}", stack_strs.join("\n"));
println!("=============");
Expand Down Expand Up @@ -698,6 +697,7 @@ impl Perf {
let mut chunk: Vec<LuaFrame> = Vec::new();
for addr in frame.lstack.iter() {
if *addr == 0 { //CIST_FRESH
chunk.reverse();
chunks.push(chunk);
chunk = Vec::new();
continue
Expand All @@ -713,17 +713,29 @@ impl Perf {
}
}
if chunk.len() > 0 {
chunk.reverse();
chunks.push(chunk);
}
chunks.reverse();
return chunks
}

fn split_c_chunk(&self, usym: &Vec<SymInfo>) -> Vec<Vec<SymInfo>> {
fn split_c_chunk(&self, usym: &Vec<SymInfo>, l_chunks: &Vec<Vec<LuaFrame>>) -> Vec<Vec<SymInfo>> {
let mut chunks: Vec<Vec<SymInfo>> = Vec::new();
let mut chunk: Vec<SymInfo> = Vec::new();
for sym in usym.iter() {
if sym.name.contains("luaV_execute") {
chunk.push(sym.clone());
for sym in usym.iter().rev() {
//TODO process recursive call
let start_addr = sym.addr - sym.offset;
let c_start = l_chunks.iter().find(|&x|
match x.first() {
Some(LuaFrame::C(addr)) => *addr == start_addr,
_ => false,
}
).is_some();
if c_start || sym.name.contains("luaV_execute") {
if !c_start {
chunk.push(sym.clone());
}
chunks.push(chunk);
chunk = Vec::new();
} else {
Expand All @@ -741,10 +753,10 @@ impl Perf {
let usyms = self.syms_of_stack(self.pid, &frame.ustack);
//split lua call chunk
let mut lua_chunks = self.split_lua_chunk(skel, frame);
let mut c_chunks = self.split_c_chunk(&usyms);
let mut frame_strs:Vec<String> = ksyms.iter().map(|s| s.name.clone()).collect();
let mut c_chunks = self.split_c_chunk(&usyms, &lua_chunks);
let mut frame_strs:Vec<String> = Vec::new();
for c_chunk in c_chunks.iter_mut() {
for i in 0..(c_chunk.len() - 1) {
for i in 0..(c_chunk.len()) {
frame_strs.push(c_chunk[i].name.clone());
}
if lua_chunks.len() > 0 { //has lua stack left
Expand All @@ -770,15 +782,14 @@ impl Perf {
}
};
}
//push c chunk
frame_strs.push(c_chunk.last().unwrap().name.clone());
}
let mut kstack = ksyms.iter().rev().map(|s| s.name.clone()).collect();
frame_strs.append(&mut kstack);
return frame_strs;
}

fn flame_entry(&self, skel: &ProfileSkel, frame: &StackFrame) -> String {
let mut strs = self.combine_stack(skel, frame);
strs.reverse();
let strs = self.combine_stack(skel, frame);
strs.join(";")
}
fn collect_flame(&self, skel: &ProfileSkel) {
Expand Down Expand Up @@ -846,8 +857,6 @@ impl Perf {
#[cfg(test)]
mod tests {
use goblin::elf::Elf;
use super::*;

#[test]
fn test_find_func_code() {
let paths = vec![
Expand All @@ -863,7 +872,7 @@ mod tests {
for path in paths.iter() {
let elf_data = std::fs::read(path).unwrap();
let data = &elf_data;
let elf = Elf::parse(data).unwrap();
let _elf = Elf::parse(data).unwrap();
//let fn_vars = var::parse_var(&elf, &elf_data);
//println!("========{}======:{:?}", path, fn_vars);
}
Expand Down
2 changes: 2 additions & 0 deletions src/perf/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ pub struct perf_event_attr {
pub __reserved_3: u32,
}

#[allow(dead_code)]
pub const PERF_TYPE_HARDWARE: u32 = 0;
pub const PERF_TYPE_SOFTWARE: u32 = 1;
pub const PERF_COUNT_HW_CPU_CYCLES: u64 = 0;

extern "C" {
Expand Down
6 changes: 1 addition & 5 deletions src/perf/var.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use capstone::arch::x86::X86OperandType;
use capstone::{prelude::*, Insn, arch::x86::X86Operand};
use goblin::elf::Elf;
use goblin::elf::section_header::{SHT_SYMTAB};
use goblin::elf::section_header::SHT_SYMTAB;

#[derive(Debug, Clone)]
pub enum VarPos {
Expand Down Expand Up @@ -129,7 +129,6 @@ pub fn collect_lua_fn_var_pos<'a>(elf: &'a Elf<'a>, elf_data: &'a Vec<u8>) -> Ve
if ops.len() == 2 && ops[1].op_type == X86OperandType::Reg(arch::x86::X86Reg::X86_REG_RDI.into()) {
mov_idx = i;
mov_ops = ops[0].clone();
//println!("{}: {} {}", caller.name, instr.mnemonic().unwrap(), instr.op_str().unwrap());
}
continue
},
Expand All @@ -146,14 +145,12 @@ pub fn collect_lua_fn_var_pos<'a>(elf: &'a Elf<'a>, elf_data: &'a Vec<u8>) -> Ve
_ => false
};
if hit {
//println!("{}: {} {}", caller.name, instr.mnemonic().unwrap(), instr.op_str().unwrap());
break
}
},
"luaD_rawrunprotected" => {
let hit = ops[0].op_type == X86OperandType::Imm(arch::x86::X86Reg::X86_REG_RDI.into());
if hit {
//println!("{}: {} {}", caller.name, instr.mnemonic().unwrap(), instr.op_str().unwrap());
break
}
},
Expand All @@ -174,7 +171,6 @@ pub fn collect_lua_fn_var_pos<'a>(elf: &'a Elf<'a>, elf_data: &'a Vec<u8>) -> Ve
}
_ => panic!("unsupported mov ops:{:?}", mov_ops.op_type),
};
println!("{}: {:?}", caller.name, pos);
fn_var_pos.push(FnVarPos {
addr: caller.addr,
size: caller.size,
Expand Down

0 comments on commit ed35497

Please sign in to comment.