
Date: Tue, 6 Dec 2011 10:41:06 +0900
Subject: [PATCH 1/2] section pseudo symbol for module

Add new helper pseudo symbol about found out sections
to module symbol table when module object file has been loaded.

Rolling up symbols as particular section group or cheking module
section layouts in memory visually make "sym -m <mod>" better.

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

diff --git a/symbols.c b/symbols.c
index 0cd3a01..30a142d 100755
--- a/symbols.c
+++ b/symbols.c
@@ -901,12 +901,15 @@ symname_hash_search(char *name)
 
 #define MODULE_PSEUDO_SYMBOL(sp) \
     ((STRNEQ((sp)->name, "_MODULE_START_") || STRNEQ((sp)->name, "_MODULE_END_")) || \
-    (STRNEQ((sp)->name, "_MODULE_INIT_START_") || STRNEQ((sp)->name, "_MODULE_INIT_END_")))
+    (STRNEQ((sp)->name, "_MODULE_INIT_START_") || STRNEQ((sp)->name, "_MODULE_INIT_END_")) || \
+    (STRNEQ((sp)->name, "_MODULE_SECTION_")))
 
 #define MODULE_START(sp) (STRNEQ((sp)->name, "_MODULE_START_"))
 #define MODULE_END(sp)   (STRNEQ((sp)->name, "_MODULE_END_"))
 #define MODULE_INIT_START(sp) (STRNEQ((sp)->name, "_MODULE_INIT_START_"))
 #define MODULE_INIT_END(sp)   (STRNEQ((sp)->name, "_MODULE_INIT_END_"))
+#define MODULE_SECTION_START(sp) (STRNEQ((sp)->name, "_MODULE_SECTION_START"))
+#define MODULE_SECTION_END(sp)   (STRNEQ((sp)->name, "_MODULE_SECTION_END"))
 
 static void
 symbol_dump(ulong flags, char *module)
@@ -957,7 +960,15 @@ symbol_dump(ulong flags, char *module)
 			}
 
 			if (MODULE_PSEUDO_SYMBOL(sp)) {
-				if (MODULE_START(sp)) {
+				if (MODULE_SECTION_START(sp)) {
+					p1 = sp->name +
+					     strlen("_MODULE_SECTION_START ");
+					p2 = "section start";
+				} else if (MODULE_SECTION_END(sp)) {
+					p1 = sp->name +
+					     strlen("_MODULE_SECTION_END ");
+					p2 = "section end";
+				} else if (MODULE_START(sp)) {
 					p1 = "MODULE START";
 					p2 = sp->name+strlen("_MODULE_START_");
 					start = TRUE;
@@ -2337,6 +2348,7 @@ static int
 compare_syms(const void *v1, const void *v2)
 {
 	struct syment *s1, *s2;
+	char sn1[BUFSIZE], sn2[BUFSIZE];
 
 	s1 = (struct syment *)v1;
 	s2 = (struct syment *)v2;
@@ -2348,6 +2360,55 @@ compare_syms(const void *v1, const void *v2)
 			return 1;
 		if (STRNEQ(s2->name, "_MODULE_START_"))
 			return 1;
+		/* Get pseudo section name. */
+		if (MODULE_SECTION_START(s1))
+			sscanf(s1->name, "_MODULE_SECTION_START [%s]", sn1);
+		else if (MODULE_SECTION_END(s1))
+			sscanf(s1->name, "_MODULE_SECTION_END [%s]", sn1);
+
+		if (MODULE_SECTION_START(s2))
+			sscanf(s2->name, "_MODULE_SECTION_START [%s]", sn2);
+		else if (MODULE_SECTION_END(s2))
+			sscanf(s2->name, "_MODULE_SECTION_END [%s]", sn2);
+
+		/*
+		 * Sort pseudo symbols in mind section.
+		 * The same values must be sorted like examples.
+		 * - exp1
+		 *  c9046000 MODULE START: sctp
+		 *  c9046000 [.data]: section start
+		 *  c9046000 (D) sctp_timer_events
+		 *
+		 * - exp2
+		 *  c9046c68 [.bss]: section end
+		 *  c9046c68 MODULE END: sctp
+		 *
+		 * - exp3
+		 *   c90e9b44 [.text]: section end
+		 *   c90e9b44 [.exit.text]: section start
+		 *   c90e9b44 (T) cleanup_module
+		 *   c90e9b44 (t) sctp_exit
+		 *   c90e9c81 [.exit.text]: section end
+		 */
+		if (MODULE_SECTION_END(s1)) {
+			if (!MODULE_PSEUDO_SYMBOL(s2) || MODULE_END(s2))
+				return -1;
+			else if (MODULE_SECTION_START(s2) && !STREQ(sn1, sn2))
+				return -1;
+			return 1;
+		}
+		if (MODULE_SECTION_END(s2)) {
+			if (MODULE_END(s1) || !MODULE_PSEUDO_SYMBOL(s1))
+				return 1;
+			else if (MODULE_SECTION_START(s1) && STREQ(sn1, sn2))
+				return 1;
+			return -1;
+		}
+		if (MODULE_SECTION_START(s2)) {
+			if (MODULE_START(s1))
+				return -1;
+			return 1;
+		}
 	}
 
 	return (s1->value < s2->value ? -1 : 
@@ -10178,6 +10239,39 @@ store_load_module_symbols(bfd *bfd, int dynamic, void *minisyms,
 		} 
 	}
 
+	/*
+	 * Append helpful pseudo symbols about found out sections.
+	 * Use 'S' as its type which is never seen in existing symbols.
+	 */
+	for (i = 0; i < lm->mod_sections; i++) {
+		if (!(lm->mod_section_data[i].flags & SEC_FOUND))
+			continue;
+		/* Section start */
+		lm->mod_load_symend->value = lm->mod_base +
+					     lm->mod_section_data[i].offset;
+		lm->mod_load_symend->type = 'S';
+		lm->mod_load_symend->flags |= MODULE_SYMBOL;
+		sprintf(name, "_MODULE_SECTION_START [%s]",
+			lm->mod_section_data[i].name);
+		namespace_ctl(NAMESPACE_INSTALL, &lm->mod_load_namespace,
+			      lm->mod_load_symend, name);
+		lm->mod_load_symend++;
+		lm->mod_load_symcnt++;
+
+		/* Section end */
+		lm->mod_load_symend->value = lm->mod_base +
+					     lm->mod_section_data[i].offset +
+					     lm->mod_section_data[i].size;
+		lm->mod_load_symend->type = 'S';
+		lm->mod_load_symend->flags |= MODULE_SYMBOL;
+		sprintf(name, "_MODULE_SECTION_END [%s]",
+			lm->mod_section_data[i].name);
+		namespace_ctl(NAMESPACE_INSTALL, &lm->mod_load_namespace,
+			      lm->mod_load_symend, name);
+		lm->mod_load_symend++;
+		lm->mod_load_symcnt++;
+	}
+
         namespace_ctl(NAMESPACE_COMPLETE, &lm->mod_load_namespace, 
 		lm->mod_load_symtable, lm->mod_load_symend);
 
-- 
1.7.7.rc0.72.g4b5ea




