[PATCH dwarves 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 | 50 ++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 44 insertions(+), 6 deletions(-)

diff --git a/dwarf_loader.c b/dwarf_loader.c
index 684115d..712a957 100644
--- a/dwarf_loader.c
+++ b/dwarf_loader.c
@@ -1197,6 +1197,21 @@ struct func_info {
 
 #define	PARM_DEFAULT_FAIL	-1
 #define	PARM_FBREG_FAIL		-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;
@@ -1205,7 +1220,7 @@ struct func_info {
  *   list, return the register; otherwise save register for later return
  * - otherwise if no register was found for locations, return PARM_DEFAULT_FAIL.
  */
-static int parameter__reg(Dwarf_Attribute *attr, int expected_reg)
+static int parameter__reg(Dwarf_Attribute *attr, int expected_reg, struct cu *cu, struct conf_load *conf)
 {
 	Dwarf_Addr base, start, end;
 	Dwarf_Op *expr, *entry_ops;
@@ -1229,8 +1244,17 @@ static int parameter__reg(Dwarf_Attribute *attr, int expected_reg)
 		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 */
@@ -1250,6 +1274,16 @@ static int parameter__reg(Dwarf_Attribute *attr, int expected_reg)
 			 */
 			ret = PARM_FBREG_FAIL;
 			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:
@@ -1338,11 +1372,14 @@ static struct parameter *parameter__new(Dwarf_Die *die, struct cu *cu,
 
 		if (parm->has_loc) {
 			int expected_reg = cu->register_params[reg_idx];
-			int actual_reg = parameter__reg(&attr, expected_reg);
+			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_FBREG_FAIL || (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_FBREG_FAIL || (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
@@ -1350,6 +1387,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.