[Crash-utility] [RFC] arm64: symbolize PLT entries in disassembling module functions

AKASHI Takahiro takahiro.akashi at linaro.org
Tue Oct 11 09:16:08 UTC 2016


Signed-off-by: AKASHI Takahiro <takahiro.akashi at linaro.org>
---
 arm64.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/arm64.c b/arm64.c
index b9fa14d..8235e3c 100644
--- a/arm64.c
+++ b/arm64.c
@@ -2540,6 +2540,59 @@ arm64_is_task_addr(ulong task)
 		return (IS_KVADDR(task) && (ALIGNED_STACK_OFFSET(task) == 0));
 }
 
+static ulong
+PLT_veneer_to_kvaddr(ulong value)
+{
+	uint32_t insn;
+	ulong addr = 0;
+	int i;
+
+	/*
+	 * PLT veneer always looks:
+         *   movn x16, #0x....
+         *   movk x16, #0x...., lsl #16
+         *   movk x16, #0x...., lsl #32
+         *   br   x16
+	 */
+	for (i = 0; i < 4; i++) {
+		if (!readmem(value + i * sizeof(insn), KVADDR, &insn,
+				sizeof(insn), "PLT veneer", RETURN_ON_ERROR)) {
+			error(WARNING, "cannot read PLT veneer\n");
+			return value;
+		}
+		switch (i) {
+		case 0:
+			if ((insn & 0xffe0001f) != 0x92800010)
+				goto not_plt;
+			addr = ~((ulong)(insn & 0x1fffe0) >> 5);
+			break;
+		case 1:
+			if ((insn & 0xffe0001f) != 0xf2a00010)
+				goto not_plt;
+			addr &= 0xffffffff0000ffff;
+			addr |= (ulong)(insn & 0x1fffe0) << (16 - 5);
+			break;
+		case 2:
+			if ((insn & 0xffe0001f) != 0xf2c00010)
+				goto not_plt;
+			addr &= 0xffff0000ffffffff;
+			addr |= (ulong)(insn & 0x1fffe0) << (32 - 5);
+			break;
+		case 3:
+			if (insn != 0xd61f0200)
+				goto not_plt;
+			break;
+		default:
+			return value; /* to avoid any warnings */
+		}
+	}
+
+	return addr;
+
+not_plt:
+	return value;
+}
+
 /*
  * Filter dissassembly output if the output radix is not gdb's default 10
  */
@@ -2589,6 +2642,22 @@ arm64_dis_filter(ulong vaddr, char *inbuf, unsigned int output_radix)
 		sprintf(p1, "%s", buf1);
 	}
 
+	if (IS_MODULE_VADDR(vaddr)) {
+		ulong orig_value;
+
+		p1 = &inbuf[strlen(inbuf)-1];
+		strcpy(buf1, inbuf);
+		argc = parse_line(buf1, argv);
+
+		if ((STREQ(argv[argc-2], "b") || STREQ(argv[argc-2], "bl")) &&
+		    extract_hex(argv[argc-1], &orig_value, NULLCHAR, TRUE)) {
+			value = PLT_veneer_to_kvaddr(orig_value);
+			sprintf(p1, " <%s%s>\n",
+				value == orig_value ? "" : "plt:",
+				value_to_symstr(value, buf2, output_radix));
+		}
+	}
+
 	console("    %s", inbuf);
 
 	return TRUE;
-- 
2.10.0




More information about the Crash-utility mailing list