
Date: Fri, 9 Dec 2011 09:47:29 +0900
Subject: [PATCH 1/5] add more module section via patch_module_section_layout()

Verify and update for validate sections which is not containing
named symbol such like ".rodata.str#", ".eh_frame".

If section patch succeed, mark MOD_NOPATCH and directly call gdb request
without kallsym helper.
Also this will drop calculate_load_order and add_symbol_file_kallsyms staff
if section patch can work out at everything about kernel or architecture.

Signed-off-by: Toshikazu Nakayama <nakayama.ts@ncos.nec.co.jp>
---
 symbols.c |  131 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 130 insertions(+), 1 deletions(-)

diff --git a/symbols.c b/symbols.c
index 6a9040b..e1a20b2 100755
--- a/symbols.c
+++ b/symbols.c
@@ -9467,7 +9467,126 @@ compare_prios(const void *v1, const void *v2)
 	return (md1->priority < md2->priority ? -1 : 1);
 }
 
+/*
+ * Try to resolve section layouts according by predefined layouts in kernel.
+ * This works well while bfd_map_over_sections() can callback each section
+ * with the same order as kernel's.
+ */
+static ulong
+section_align(bfd *mbfd, asection *section, ulong size)
+{
+	int sh_addralign;
+	ulong align;
+
+	sh_addralign = bfd_get_section_alignment(mbfd, section);
+	if (sh_addralign) {
+		align = 1 << sh_addralign;
+		size = roundup(size, align);
+	}
+	return size;
+}
+
+static void
+calc_module_section(bfd *mbfd, struct mod_section_data *section, ulong *offset)
+{
+	struct load_module *lm;
+	ulong start;
+
+	lm = st->current;
+	if (!lm)
+		return;
+
+	*offset = section_align(mbfd, section->section, *offset);
+	section->offset = *offset;
+
+	start = lm->mod_base + section->offset;
+	if (STREQ(section->name, ".text") == 0) {
+		lm->mod_text_start = start;
+		lm->mod_etext_guess = start + section->size;
+	} else if (STREQ(section->name, ".rodata") == 0)
+		lm->mod_rodata_start = start;
+	else if (STREQ(section->name, ".bss") == 0)
+		lm->mod_bss_start = start;
+	else if (STREQ(section->name, ".data") == 0)
+		lm->mod_data_start = start;
+
+	*offset += section->size;
+}
+
+static int
+patch_module_section_layout(bfd *mbfd, int do_init)
+{
+	struct load_module *lm;
+	ulong offset, verify;
+	int i, j;
+	int is_init;
+	ulong flags;
+	const ulong mask[][2] = {
+		/*
+		 * NOTE: all executable code must be the first section
+		 * in this array; otherwise modify the text_size
+		 * finder in the two loops below
+		 */
+		{ SEC_CODE | SEC_ALLOC, SEC_SMALL_DATA },
+		{ SEC_ALLOC | SEC_READONLY, SEC_CODE | SEC_SMALL_DATA },
+		{ SEC_ALLOC, SEC_READONLY | SEC_SMALL_DATA },
+		{ SEC_SMALL_DATA | SEC_ALLOC, 0 }
+	};
+
+	lm = st->current;
+	if (!lm)
+		return FALSE;
 
+#define ARRAY_SIZE(x)	(sizeof(x) / sizeof((x)[0]))
+	offset = 0;
+	for (i = 0; i < ARRAY_SIZE(mask); i++) {
+		for (j = 0; j < lm->mod_sections; j++) {
+			if (lm->mod_section_data[j].size == 0)
+				continue;
+			is_init = STRNEQ(lm->mod_section_data[j].name, ".init");
+			if (is_init != do_init)
+				continue;
+
+			flags = lm->mod_section_data[j].section->flags;
+			if ((flags & mask[i][0]) != mask[i][0] ||
+			    (flags & mask[i][1]))
+				continue;
+			/*
+			 * This layouts here, compare previous offset
+			 * if was resolved previously.
+			 */
+			if (lm->mod_section_data[j].flags & SEC_FOUND)
+				verify = lm->mod_section_data[j].offset;
+			calc_module_section(mbfd, &lm->mod_section_data[j],
+					    &offset);
+			if (lm->mod_section_data[j].flags & SEC_FOUND) {
+				if (verify == lm->mod_section_data[j].offset)
+					continue;
+				error(INFO,
+				      "Fail to resolve section layout for %s "
+				      "calc=%lu : orig=%lu\n",
+				      lm->mod_section_data[j].name,
+				      lm->mod_section_data[j].offset, verify);
+				lm->mod_section_data[j].offset = verify;
+				lm->mod_flags &= ~MOD_NOPATCH;
+				return FALSE;
+			}
+			/*
+			 * sections which don't own symbol entry are coming.
+			 */
+			lm->mod_section_data[j].flags |= SEC_FOUND;
+			if (CRASHDEBUG(2))
+				fprintf(fp,
+					"Resolved more secion %s offset %lx\n",
+					lm->mod_section_data[j].name,
+					lm->mod_section_data[j].offset);
+		}
+	}
+	lm->mod_flags |= MOD_NOPATCH;
+
+	return TRUE;
+#undef ARRAY_SIZE
+}
 
 /*
  *  This routine scours a module object file namelist for global text and
@@ -10060,7 +10179,17 @@ store_load_module_symbols(bfd *bfd, int dynamic, void *minisyms,
 	else
 		calculate_load_order_v2(lm, bfd, dynamic, minisyms,
 			symcount, size);
-
+	/*
+	 * Try to verify and update section layouts.
+	 */
+	if (!patch_module_section_layout(bfd, FALSE) ||
+	    (lm->mod_init_size > 0 &&
+	     !patch_module_section_layout(bfd, TRUE))) {
+		error(INFO, "module section layout could not work out yet.\n");
+		error(INFO, "ver: linux-%u.%u.%u mach: %s\n",
+		      kt->kernel_version[0], kt->kernel_version[1],
+		      kt->kernel_version[2], pc->machine_type);
+	}
 
         from = (bfd_byte *) minisyms;
         fromend = from + symcount * size;
-- 
1.7.7.rc0.72.g4b5ea

