The following is an example: 0x00899a78: DW_TAG_subprogram DW_AT_low_pc (0xffffffff879be480) DW_AT_high_pc (0xffffffff879beac4) DW_AT_frame_base (DW_OP_reg7 RSP) DW_AT_call_all_calls (true) DW_AT_name ("split_mem_range") DW_AT_decl_file ("/home/yhs/work/bpf-next/arch/x86/mm/init.c") DW_AT_decl_line (401) DW_AT_prototyped (true) DW_AT_calling_convention (DW_CC_nocall) DW_AT_type (0x008861cb "int") 0x00899a8c: DW_TAG_formal_parameter DW_AT_location (indexed (0x3e) loclist = 0x000b2195: [0xffffffff879be485, 0xffffffff879be49a): DW_OP_reg5 RDI [0xffffffff879be49a, 0xffffffff879beac4): DW_OP_breg7 RSP+0) DW_AT_name ("mr") DW_AT_decl_file ("/home/yhs/work/bpf-next/arch/x86/mm/init.c") DW_AT_decl_line (401) DW_AT_type (0x00899c88 "map_range *") 0x00899a98: DW_TAG_formal_parameter DW_AT_location (indexed (0x41) loclist = 0x000b21d4: [0xffffffff879be480, 0xffffffff879be554): DW_OP_consts +0, DW_OP_stack_value [0xffffffff879be554, 0xffffffff879be56d): DW_OP_consts +1, DW_OP_stack_value [0xffffffff879be56d, 0xffffffff879be572): DW_OP_reg2 RCX [0xffffffff879be572, 0xffffffff879be638): DW_OP_breg7 RSP+8 [0xffffffff879be638, 0xffffffff879be63d): DW_OP_reg0 RAX [0xffffffff879be63d, 0xffffffff879be6ef): DW_OP_breg7 RSP+8 [0xffffffff879be6ef, 0xffffffff879be6f5): DW_OP_reg14 R14 [0xffffffff879be6f5, 0xffffffff879be6fd): DW_OP_breg7 RSP+8 [0xffffffff879be6fd, 0xffffffff879be879): DW_OP_reg14 R14 [0xffffffff879be879, 0xffffffff879be931): DW_OP_reg12 R12 [0xffffffff879be955, 0xffffffff879be961): DW_OP_reg14 R14 [0xffffffff879be961, 0xffffffff879be966): DW_OP_reg12 R12 [0xffffffff879be966, 0xffffffff879be976): DW_OP_reg14 R14 [0xffffffff879be976, 0xffffffff879be9df): DW_OP_reg12 R12 [0xffffffff879be9df, 0xffffffff879be9e5): DW_OP_reg14 R14 [0xffffffff879be9fc, 0xffffffff879bea24): DW_OP_consts +0, DW_OP_stack_value [0xffffffff879bea24, 0xffffffff879bea74): DW_OP_breg7 RSP+8 [0xffffffff879bea74, 0xffffffff879beac4): DW_OP_reg14 R14) DW_AT_name ("nr_range") DW_AT_decl_file ("/home/yhs/work/bpf-next/arch/x86/mm/init.c") DW_AT_decl_line (401) DW_AT_type (0x008861cb "int") 0x00899aa4: DW_TAG_formal_parameter DW_AT_location (indexed (0x3f) loclist = 0x000b21a7: [0xffffffff879be485, 0xffffffff879be4a4): DW_OP_reg4 RSI [0xffffffff879be4a4, 0xffffffff879be4e6): DW_OP_reg12 R12 [0xffffffff879be4e6, 0xffffffff879beac4): DW_OP_entry_value(DW_OP_reg4 RSI), DW_OP_stack_value) DW_AT_name ("start") DW_AT_decl_file ("/home/yhs/work/bpf-next/arch/x86/mm/init.c") DW_AT_decl_line (402) DW_AT_type (0x008861cf "unsigned long") 0x00899ab0: DW_TAG_formal_parameter DW_AT_location (indexed (0x40) loclist = 0x000b21c2: [0xffffffff879be485, 0xffffffff879be4a9): DW_OP_reg1 RDX [0xffffffff879be4a9, 0xffffffff879beac4): DW_OP_breg7 RSP+32) DW_AT_name ("end") DW_AT_decl_file ("/home/yhs/work/bpf-next/arch/x86/mm/init.c") DW_AT_decl_line (403) DW_AT_type (0x008861cf "unsigned long") The parameter 'nr_range' is a constant and won't consume any ABI register. Signed-off-by: Yonghong Song --- dwarf_loader.c | 46 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/dwarf_loader.c b/dwarf_loader.c index 2237e20..aa1f967 100644 --- a/dwarf_loader.c +++ b/dwarf_loader.c @@ -1197,6 +1197,21 @@ struct func_info { #define PARM_DEFAULT_FAIL -1 #define PARM_FAIL_CLANG -2 +#define PARM_OPTIMIZED_CLANG -3 +#define PARM_CONTINUE -4 + +static int parameter__multi_exprs(Dwarf_Op *expr, int loc_num) { + switch (expr[0].atom) { + case DW_OP_lit0 ... DW_OP_lit31: + case DW_OP_constu: + case DW_OP_consts: + if (loc_num != 0) + break; + return PARM_OPTIMIZED_CLANG; + } + + return PARM_CONTINUE; +} /* For DW_AT_location 'attr': * - if first location is DW_OP_regXX with expected number, return the register; @@ -1229,8 +1244,17 @@ static int parameter__reg(Dwarf_Attribute *attr, int expected_reg, struct cu *cu if (exprlen == 2 && expr[exprlen - 1].atom == DW_OP_stack_value) exprlen--; - if (exprlen != 1) - continue; + if (exprlen != 1) { + if (!cu->producer_clang || !conf->true_signature) + continue; + + int res; + res = parameter__multi_exprs(expr, loc_num); + if (res == PARM_CONTINUE) + continue; + ret = res; + goto out; + } switch (expr->atom) { /* match DW_OP_regXX at first location */ @@ -1251,6 +1275,16 @@ static int parameter__reg(Dwarf_Attribute *attr, int expected_reg, struct cu *cu if (cu->producer_clang && conf->true_signature) ret = PARM_FAIL_CLANG; break; + case DW_OP_lit0 ... DW_OP_lit31: + case DW_OP_constu: + case DW_OP_consts: + if (cu->producer_clang && conf->true_signature) { + if (loc_num != 0) + break; + ret = PARM_OPTIMIZED_CLANG; + goto out; + } + break; /* match DW_OP_entry_value(DW_OP_regXX) at any location */ case DW_OP_entry_value: case DW_OP_GNU_entry_value: @@ -1341,9 +1375,12 @@ static struct parameter *parameter__new(Dwarf_Die *die, struct cu *cu, int expected_reg = cu->register_params[reg_idx]; int actual_reg = parameter__reg(&attr, expected_reg, cu, conf); - if (actual_reg == PARM_DEFAULT_FAIL) + if (actual_reg == PARM_DEFAULT_FAIL) { parm->optimized = 1; - else if (actual_reg == PARM_FAIL_CLANG || (expected_reg >= 0 && expected_reg != actual_reg)) + } else if (actual_reg == PARM_OPTIMIZED_CLANG) { + parm->optimized = 1; + info->skip_idx++; + } else if (actual_reg == PARM_FAIL_CLANG || (expected_reg >= 0 && expected_reg != actual_reg)) { /* mark parameters that use an unexpected * register to hold a parameter; these will * be problematic for users of BTF as they @@ -1351,6 +1388,7 @@ static struct parameter *parameter__new(Dwarf_Die *die, struct cu *cu, * contents. */ parm->unexpected_reg = 1; + } } else if (!cu->producer_clang && has_const_value) { parm->optimized = 1; } else if (cu->producer_clang) { -- 2.47.3