[PATCH dwarves v2 6/9] dwarf_loader: Detect optimized parameters with locations having constant values

Yonghong Song <[email protected]>
Newsgroups org.kernel.vger.dwarves,org.kernel.vger.bpf
Message-ID <[email protected]>
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 <[email protected]>
---
 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.