diff mbox series

[dwarves,2/3] dwarf_loader: Refactor function check_dwarf_locations()

Message ID 20241108180519.1198396-1-yonghong.song@linux.dev (mailing list archive)
State Not Applicable
Headers show
Series Check DW_OP_[GNU_]entry_value for possible parameter matching | expand

Checks

Context Check Description
netdev/tree_selection success Not a local patch

Commit Message

Yonghong Song Nov. 8, 2024, 6:05 p.m. UTC
The newly-added function check_dwarf_locations() supports two variants
of implementations: elfutils "version < 157" and "version >= 157".
The "version < 157" supports one single location (dwarf_getlocation())
and "version >= 157" supports location lists (dwarf_getlocations()).

Currently, even for dwarf_getlocations(), only the first location
and its first expression is checked. In the subsequent patch, all
locations and all expressions may be changed. So this patch refactors
the code such that two different implementations (based on elfutils
versions) are clearly separated. This makes subsequent change cleaner.

No functional change.

Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
---
 dwarf_loader.c | 40 +++++++++++++++++++++++++++++++++-------
 1 file changed, 33 insertions(+), 7 deletions(-)
diff mbox series

Patch

diff --git a/dwarf_loader.c b/dwarf_loader.c
index 4bb9096..e0b8c11 100644
--- a/dwarf_loader.c
+++ b/dwarf_loader.c
@@ -1160,22 +1160,47 @@  static struct template_parameter_pack *template_parameter_pack__new(Dwarf_Die *d
 static bool check_dwarf_locations(Dwarf_Attribute *attr, struct parameter *parm,
 				  struct cu *cu, int param_idx)
 {
+	int expected_reg = cu->register_params[param_idx];
 	Dwarf_Addr base, start, end;
 	struct location loc;
+	Dwarf_Op *expr;
 
+	if (!parm->has_loc)
+		return false;
+
+#if _ELFUTILS_PREREQ(0, 157)
 	/* dwarf_getlocations() handles location lists; here we are
 	 * only interested in the first expr.
 	 */
-	if (parm->has_loc &&
-#if _ELFUTILS_PREREQ(0, 157)
-	    dwarf_getlocations(attr, 0, &base, &start, &end,
+	if (dwarf_getlocations(attr, 0, &base, &start, &end,
 			       &loc.expr, &loc.exprlen) > 0 &&
+		loc.exprlen != 0) {
+		expr = loc.expr;
+
+		switch (expr->atom) {
+		case DW_OP_reg0 ... DW_OP_reg31:
+			/* mark parameters that use an unexpected
+			 * register to hold a parameter; these will
+			 * be problematic for users of BTF as they
+			 * violate expectations about register
+			 * contents.
+			 */
+			if (expected_reg >= 0 && expected_reg != expr->atom)
+				parm->unexpected_reg = 1;
+			break;
+		default:
+			parm->optimized = 1;
+			break;
+		}
+
+		return true;
+	}
+
+	return false;
 #else
-	    dwarf_getlocation(attr, &loc.expr, &loc.exprlen) == 0 &&
-#endif
+	if (dwarf_getlocation(attr, &loc.expr, &loc.exprlen) == 0 &&
 		loc.exprlen != 0) {
-		int expected_reg = cu->register_params[param_idx];
-		Dwarf_Op *expr = loc.expr;
+		expr = loc.expr;
 
 		switch (expr->atom) {
 		case DW_OP_reg0 ... DW_OP_reg31:
@@ -1197,6 +1222,7 @@  static bool check_dwarf_locations(Dwarf_Attribute *attr, struct parameter *parm,
 	}
 
 	return false;
+#endif
 }
 
 static struct parameter *parameter__new(Dwarf_Die *die, struct cu *cu,