All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Use symbol database to maintain module dependence
@ 2009-04-20 21:11 Bean
  2009-04-27  6:33 ` Bean
  0 siblings, 1 reply; 6+ messages in thread
From: Bean @ 2009-04-20 21:11 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 311 bytes --]

Hi,

This patch add a new tool grub-symdb to manage symbol database and
update module dependence as required. The build process is greatly
simplified, moddep.lst, def-*.lst, und-*.lst are not generated
anymore. grub-symdb will read the module files and update modsym.lst
and moddep.lst automatically.

-- 
Bean

[-- Attachment #2: symdb.diff --]
[-- Type: text/x-patch, Size: 26243 bytes --]

diff --git a/Makefile.in b/Makefile.in
index b24ee2e..06478af 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -139,11 +139,9 @@ include $(srcdir)/conf/$(target_cpu)-$(platform).mk
 ### General targets.
 
 CLEANFILES += $(pkglib_DATA) $(pkgdata_DATA)
-pkglib_DATA += moddep.lst command.lst fs.lst partmap.lst handler.lst
-moddep.lst: $(DEFSYMFILES) $(UNDSYMFILES) genmoddep.awk
-	cat $(DEFSYMFILES) /dev/null \
-	  | $(AWK) -f $(srcdir)/genmoddep.awk $(UNDSYMFILES) > $@ \
-	  || (rm -f $@; exit 1)
+pkglib_DATA += modsym.lst command.lst fs.lst partmap.lst handler.lst
+modsym.lst: $(MODFILES) grub-symdb
+	./grub-symdb -d . update $?
 
 command.lst: $(COMMANDFILES)
 	cat $^ /dev/null | sort > $@
diff --git a/conf/common.rmk b/conf/common.rmk
index 0e63da6..20a1b89 100644
--- a/conf/common.rmk
+++ b/conf/common.rmk
@@ -23,6 +23,10 @@ grub_probe_SOURCES = util/grub-probe.c	\
 	kern/fs.c kern/env.c fs/fshelp.c			\
 	disk/raid.c disk/mdraid_linux.c disk/lvm.c grub_probe_init.c
 
+# For grub-symdb
+bin_UTILITIES += grub-symdb
+grub_symdb_SOURCES = util/grub-symdb.c util/misc.c util/resolve.c
+
 ifeq ($(enable_grub_fstest), yes)
 bin_UTILITIES += grub-fstest
 endif
diff --git a/genmk.rb b/genmk.rb
index b619421..c119fad 100644
--- a/genmk.rb
+++ b/genmk.rb
@@ -99,18 +99,10 @@ class PModule
     pre_obj = 'pre-' + @name.suffix('o')
     mod_src = 'mod-' + @name.suffix('c')
     mod_obj = mod_src.suffix('o')
-    defsym = 'def-' + @name.suffix('lst')
-    undsym = 'und-' + @name.suffix('lst')
     mod_name = File.basename(@name, '.mod')
     symbolic_name = mod_name.sub(/\.[^\.]*$/, '')
     
-    "CLEANFILES += #{@name} #{mod_obj} #{mod_src} #{pre_obj} #{objs_str} #{undsym}
-ifneq ($(#{prefix}_EXPORTS),no)
-CLEANFILES += #{defsym}
-DEFSYMFILES += #{defsym}
-endif
-MOSTLYCLEANFILES += #{deps_str}
-UNDSYMFILES += #{undsym}
+    "CLEANFILES += #{@name} #{mod_obj} #{mod_src} #{pre_obj} #{objs_str} 
 
 #{@name}: #{pre_obj} #{mod_obj} $(TARGET_OBJ2ELF)
 	-rm -f $@
@@ -125,17 +117,10 @@ UNDSYMFILES += #{undsym}
 #{mod_obj}: #{mod_src}
 	$(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(#{prefix}_CFLAGS) -c -o $@ $<
 
-#{mod_src}: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
-	sh $(srcdir)/genmodsrc.sh '#{mod_name}' $< > $@ || (rm -f $@; exit 1)
-
-ifneq ($(#{prefix}_EXPORTS),no)
-#{defsym}: #{pre_obj}
-	$(NM) -g --defined-only -P -p $< | sed 's/^\\([^ ]*\\).*/\\1 #{mod_name}/' > $@
-endif
+#{mod_src}: $(srcdir)/genmodsrc.sh
+	sh $(srcdir)/genmodsrc.sh '#{mod_name}' > $@ || (rm -f $@; exit 1)
 
-#{undsym}: #{pre_obj}
-	echo '#{mod_name}' > $@
-	$(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+MODFILES += #{@name}
 
 " + objs.collect_with_index do |obj, i|
       src = sources[i]
diff --git a/genmodsrc.sh b/genmodsrc.sh
index 2d42055..b334c7e 100644
--- a/genmodsrc.sh
+++ b/genmodsrc.sh
@@ -41,7 +41,4 @@ cat <<EOF
 EOF
 
 echo "GRUB_MOD_NAME(${mod_name});"
-
-for mod in `grep "^${mod_name}:" ${deps} | sed 's/^[^:]*://'`; do
-  echo "GRUB_MOD_DEP(${mod});"
-done
+echo 'GRUB_MOD_DEP("");'
diff --git a/include/grub/util/resolve.h b/include/grub/util/resolve.h
index f42df32..80e69e5 100644
--- a/include/grub/util/resolve.h
+++ b/include/grub/util/resolve.h
@@ -32,4 +32,7 @@ grub_util_resolve_dependencies (const char *prefix,
 				const char *dep_list_file,
 				char *modules[]);
 
+char * grub_util_get_module_name (const char *str);
+char * grub_util_get_module_path (const char *prefix, const char *str);
+
 #endif /* ! GRUB_UTIL_RESOLVE_HEADER */
diff --git a/util/grub-symdb.c b/util/grub-symdb.c
new file mode 100644
index 0000000..2d9b0e7
--- /dev/null
+++ b/util/grub-symdb.c
@@ -0,0 +1,1050 @@
+/* grub-symdb.c - manage symbol database  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <grub/types.h>
+#include <grub/elf.h>
+#include <grub/util/misc.h>
+#include <grub/util/resolve.h>
+#include <grub/list.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#define _GNU_SOURCE	1
+#include <getopt.h>
+
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
+
+typedef Elf32_Word Elf_Word;
+typedef Elf32_Addr Elf_Addr;
+typedef Elf32_Ehdr Elf_Ehdr;
+typedef Elf32_Shdr Elf_Shdr;
+typedef Elf32_Sym Elf_Sym;
+typedef Elf32_Half Elf_Half;
+typedef Elf32_Off Elf_Off;
+typedef Elf32_Section Elf_Section;
+
+#define ELF_ST_BIND		ELF32_ST_BIND
+#define grub_target_to_host	grub_target_to_host32
+#define grub_host_to_target	grub_host_to_target32
+
+#elif GRUB_TARGET_SIZEOF_VOID_P == 8
+
+typedef Elf64_Word Elf_Word;
+typedef Elf64_Addr Elf_Addr;
+typedef Elf64_Ehdr Elf_Ehdr;
+typedef Elf64_Shdr Elf_Shdr;
+typedef Elf64_Sym Elf_Sym;
+typedef Elf64_Half Elf_Half;
+typedef Elf64_Off Elf_Off;
+typedef Elf64_Section Elf_Section;
+
+#define ELF_ST_BIND		ELF64_ST_BIND
+#define grub_target_to_host	grub_target_to_host64
+#define grub_host_to_target	grub_host_to_target64
+
+#endif
+
+struct grub_symbol_list
+{
+  struct grub_symbol_list *next;
+  char *name;
+  struct grub_named_list *defs;
+  struct grub_named_list *unds;
+};
+
+static struct grub_symbol_list *symbol_list;
+
+struct grub_update_list
+{
+  struct grub_update_list *next;
+  char *name;
+  struct grub_named_list *add_mods;
+  struct grub_named_list *del_mods;
+  struct grub_named_list *cur_mods;
+};
+
+static struct grub_update_list *update_list;
+
+struct grub_mod_syms
+{
+  struct grub_named_list *defs;
+  struct grub_named_list *unds;
+};
+
+static void *
+insert_named_list (grub_named_list_t *head, grub_named_list_t item)
+{
+  grub_named_list_t *p, q;
+
+  for (p = head, q = *p; q; p = &(q->next), q = q->next)
+    {
+      int r;
+
+      r = strcmp (item->name, q->name);
+      if (! r)
+	return q;
+
+      if (r < 0)
+	break;
+    }
+
+  *p = item;
+  item->next = q;
+
+  return item;
+}
+
+static void
+free_named_list (grub_named_list_t *head)
+{
+  grub_named_list_t cur = *head;
+
+  while (cur)
+    {
+      grub_named_list_t tmp;
+
+      tmp = cur;
+      cur = cur->next;
+      free ((char *) tmp->name);
+      free (tmp);
+    }
+
+  *head = 0;
+}
+
+static int
+remove_string (grub_named_list_t *head, char *name)
+{
+  grub_named_list_t *p, q;
+
+  for (p = head, q = *p; q; p = &(q->next), q = q->next)
+    {
+      int r;
+
+      r = strcmp (name, q->name);
+      if (! r)
+	{
+	  *p = q->next;
+	  free ((char *) q->name);
+	  free (q);
+
+	  return 1;
+	}
+
+      if (r < 0)
+	break;
+    }
+
+  return 0;
+}
+
+static int
+insert_string (grub_named_list_t *head, char *name)
+{
+  struct grub_named_list *item, *n;
+
+  item = xmalloc (sizeof (struct grub_named_list));
+  item->name = xstrdup (name);
+
+  n = insert_named_list (head, item);
+  if (n != item)
+    {
+      free ((char *) item->name);
+      free (item);
+
+      return 0;
+    }
+
+  return 1;
+}
+
+static struct grub_symbol_list *
+insert_symbol (char *name)
+{
+  struct grub_symbol_list *s, *n;
+
+  s = xmalloc (sizeof (struct grub_symbol_list));
+  s->name = xstrdup (name);
+  s->defs = 0;
+  s->unds = 0;
+
+  n = insert_named_list (GRUB_AS_NAMED_LIST_P (&symbol_list),
+			 GRUB_AS_NAMED_LIST (s));
+
+  if (n != s)
+    {
+      free (s->name);
+      free (s);
+    }
+
+  return n;
+}
+
+static struct grub_update_list *
+insert_update (char *name)
+{
+  struct grub_update_list *u, *n;
+
+  u = xmalloc (sizeof (struct grub_update_list));
+  u->name = xstrdup (name);
+  u->add_mods = 0;
+  u->del_mods = 0;
+  u->cur_mods = 0;
+
+  n = insert_named_list (GRUB_AS_NAMED_LIST_P (&update_list),
+			 GRUB_AS_NAMED_LIST (u));
+
+  if (n != u)
+    {
+      free (u->name);
+      free (u);
+    }
+
+  return n;
+}
+
+static void
+add_update (char *m1, char *m2, int is_add)
+{
+  struct grub_update_list *u;
+
+  u = insert_update (m2);
+  if (is_add)
+    {
+      remove_string (&u->del_mods, m1);
+      insert_string (&u->add_mods, m1);
+    }
+  else
+    insert_string (&u->del_mods, m1);
+}
+
+static void
+read_symdb (char *path)
+{
+  FILE *fp;
+  char line[512];
+  struct grub_symbol_list *sym = 0;
+
+  fp = fopen (path, "r");
+  if (! fp)
+    return;
+
+  while (fgets (line, sizeof (line), fp))
+    {
+      char *p;
+
+      p = line + strlen (line) - 1;
+      while ((p >= line) && ((*p == '\r') || (*p == '\n') || (*p == ' ')))
+	p--;
+
+      if (p < line)
+	continue;
+
+      *(p + 1) = 0;
+
+      p = line;
+      while (*p == ' ')
+	p++;
+
+      if (*p == '#')
+	continue;
+
+      if ((*p == '+') || (*p == '-'))
+	{
+	  if (! sym)
+	    grub_util_error ("No current symbol.");
+
+	  insert_string ((*p == '+') ? &sym->defs : &sym->unds, p + 1);
+	}
+      else
+	sym = insert_symbol (p);
+    }
+
+  fclose (fp);
+}
+
+static void
+write_symdb (char *path)
+{
+  FILE *fp;
+  struct grub_symbol_list *sym;
+
+  fp = fopen (path, "w");
+  if (! fp)
+    grub_util_error ("Can\'t write to ", path);
+
+  sym = symbol_list;
+  while (sym)
+    {
+      struct grub_named_list *mod;
+
+      fprintf (fp, "%s\n", sym->name);
+      mod = sym->defs;
+      while (mod)
+	{
+	  fprintf (fp, "+%s\n", mod->name);
+	  mod = mod->next;
+	}
+      mod = sym->unds;
+      while (mod)
+	{
+	  fprintf (fp, "-%s\n", mod->name);
+	  mod = mod->next;
+	}
+
+      sym = sym->next;
+    }
+
+  fclose (fp);
+}
+
+static void
+check_symdb (void)
+{
+  struct grub_symbol_list *sym;
+
+  sym = symbol_list;
+  while (sym)
+    {
+      if (! sym->defs)
+	printf ("undefined: %s\n", sym->name);
+      else if (sym->defs->next)
+	printf ("duplicate: %s\n", sym->name);
+
+      sym = sym->next;
+    }
+}
+
+/* Return if the ELF header is valid.  */
+static int
+check_elf_header (Elf_Ehdr *e, size_t size)
+{
+  if (size < sizeof (*e)
+      || e->e_ident[EI_MAG0] != ELFMAG0
+      || e->e_ident[EI_MAG1] != ELFMAG1
+      || e->e_ident[EI_MAG2] != ELFMAG2
+      || e->e_ident[EI_MAG3] != ELFMAG3
+      || e->e_ident[EI_VERSION] != EV_CURRENT
+      || e->e_version != EV_CURRENT)
+     return 0;
+
+  return 1;
+}
+
+/* Return the symbol table section, if any.  */
+static Elf_Shdr *
+find_symtab_section (Elf_Shdr *sections,
+		     Elf_Half section_entsize, Elf_Half num_sections)
+{
+  int i;
+  Elf_Shdr *s;
+
+  for (i = 0, s = sections;
+       i < num_sections;
+       i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+    if (s->sh_type == grub_target_to_host32 (SHT_SYMTAB))
+      return s;
+
+  return 0;
+}
+
+/* Return the address of the string table.  */
+static char *
+find_strtab (Elf_Ehdr *e, Elf_Shdr *sections, Elf_Half section_entsize)
+{
+  Elf_Shdr *s;
+  char *strtab;
+
+  s = (Elf_Shdr *) ((char *) sections
+		    + grub_target_to_host16 (e->e_shstrndx) * section_entsize);
+  strtab = (char *) e + grub_target_to_host (s->sh_offset);
+  return strtab;
+}
+
+static Elf_Shdr *
+find_moddep_section (Elf_Shdr *sections,
+		     Elf_Half section_entsize, Elf_Half num_sections,
+		     char *strtab)
+{
+  int i;
+  Elf_Shdr *s;
+
+  for (i = 0, s = sections;
+       i < num_sections;
+       i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+    {
+      char *name = strtab + grub_target_to_host32 (s->sh_name);
+
+      if (! strcmp (name, ".moddeps"))
+	return s;
+    }
+
+  return 0;
+}
+
+static void
+read_elf_symbols (struct grub_mod_syms *mod_syms,
+		  Elf_Ehdr *e, Elf_Shdr *sections,
+		  Elf_Shdr *symtab_section, Elf_Half section_entsize,
+		  Elf_Half num_sections)
+{
+  Elf_Word symtab_size, sym_size, num_syms;
+  Elf_Off symtab_offset;
+  Elf_Word i;
+  Elf_Sym *sym;
+  Elf_Shdr *strtab_section;
+  const char *strtab;
+
+  strtab_section
+    = (Elf_Shdr *) ((char *) sections
+		    + (grub_target_to_host32 (symtab_section->sh_link)
+		       * section_entsize));
+  strtab = (char *) e + grub_target_to_host32 (strtab_section->sh_offset);
+
+  symtab_size = grub_target_to_host32 (symtab_section->sh_size);
+  sym_size = grub_target_to_host32 (symtab_section->sh_entsize);
+  symtab_offset = grub_target_to_host (symtab_section->sh_offset);
+  num_syms = symtab_size / sym_size;
+
+  for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
+       i < num_syms;
+       i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
+    {
+      Elf_Section index;
+      struct grub_named_list **p = &mod_syms->defs;
+
+      if (ELF_ST_BIND (sym->st_info) == STB_LOCAL)
+	continue;
+
+      index = grub_target_to_host16 (sym->st_shndx);
+      if (index == STN_ABS)
+	{
+	  continue;
+	}
+      else if (index == STN_UNDEF)
+	{
+	  p = &mod_syms->unds;
+	}
+      else if (index >= num_sections)
+	grub_util_error ("section %d does not exist", index);
+
+      insert_string (p,
+		     (char *) (strtab + grub_target_to_host32 (sym->st_name)));
+    }
+}
+
+static void
+read_mod_syms (struct grub_mod_syms *mod_syms, char *path)
+{
+  size_t size;
+  char *image;
+  Elf_Ehdr *e;
+  Elf_Off section_offset;
+  Elf_Half section_entsize;
+  Elf_Half num_sections;
+  Elf_Shdr *sections;
+  Elf_Shdr *symtab_section;
+
+  mod_syms->defs = 0;
+  mod_syms->unds = 0;
+
+  size = grub_util_get_image_size (path);
+  image = grub_util_read_image (path);
+
+  e = (Elf_Ehdr *) image;
+  if (! check_elf_header (e, size))
+    grub_util_error ("invalid ELF header");
+
+  section_offset = grub_target_to_host (e->e_shoff);
+  section_entsize = grub_target_to_host16 (e->e_shentsize);
+  num_sections = grub_target_to_host16 (e->e_shnum);
+
+  if (size < section_offset + section_entsize * num_sections)
+    grub_util_error ("invalid ELF format");
+
+  sections = (Elf_Shdr *) (image + section_offset);
+  symtab_section = find_symtab_section (sections,
+					section_entsize, num_sections);
+  if (! symtab_section)
+    grub_util_error ("no symbol table");
+
+  read_elf_symbols (mod_syms, e, sections, symtab_section, section_entsize,
+		    num_sections);
+
+  free (image);
+}
+
+static void
+update_mods (char *mods[], const char *dir)
+{
+  for (; mods[0]; mods++)
+    {
+      char *mod_name, *mod_path;
+      struct grub_mod_syms mod_syms;
+      struct grub_named_list *m;
+
+      mod_name = grub_util_get_module_name (mods[0]);
+      mod_path = grub_util_get_module_path (dir, mod_name);
+
+      if (! strcmp (mod_name, "grub-symdb"))
+	{
+	  free (mod_name);
+	  free (mod_path);
+	  continue;
+	}
+
+      read_mod_syms (&mod_syms, mod_path);
+
+      m = mod_syms.defs;
+      while (m)
+	{
+	  struct grub_symbol_list *sym;
+	  struct grub_named_list *n;
+
+	  sym = insert_symbol ((char *) m->name);
+	  insert_string (&sym->defs, mod_name);
+
+	  n = sym->unds;
+	  while (n)
+	    {
+	      add_update ((char *) mod_name, (char *) n->name, 1);
+	      n = n->next;
+	    }
+
+	  m = m->next;
+	}
+
+      m = mod_syms.unds;
+      while (m)
+	{
+	  struct grub_symbol_list *sym;
+	  struct grub_named_list *n;
+
+	  sym = insert_symbol ((char *) m->name);
+	  insert_string (&sym->unds, mod_name);
+
+	  n = sym->defs;
+	  while (n)
+	    {
+	      add_update ((char *) n->name, (char *) mod_name, 1);
+	      n = n->next;
+	    }
+
+	  m = m->next;
+	}
+
+      free (mod_name);
+      free (mod_path);
+    }
+}
+
+static void
+remove_mods (char *mods[])
+{
+  for (; mods[0]; mods++)
+    {
+      char *mod_name;
+      struct grub_symbol_list *sym;
+
+      mod_name = grub_util_get_module_name (mods[0]);
+
+      sym = symbol_list;
+      while (sym)
+	{
+	  struct grub_named_list *m, *n;
+
+	  m = sym->defs;
+	  while (m)
+	    {
+	      int r;
+
+	      r = strcmp (mod_name, m->name);
+	      if (! r)
+		break;
+
+	      if (r < 0)
+		{
+		  m = 0;
+		  break;
+		}
+
+	      m = m->next;
+	    }
+
+	  n = sym->unds;
+	  while (n)
+	    {
+	      if (m)
+		{
+		  add_update ((char *) m->name, (char *) n->name, 0);
+		}
+	      else
+		{
+		  int r;
+
+		  r = strcmp (mod_name, n->name);
+		  if (! r)
+		    {
+		      m = sym->defs;
+		      while (m)
+			{
+			  add_update ((char *) m->name, (char *) n->name, 0);
+			  m = m->next;
+			}
+
+		      break;
+		    }
+
+		  if (r < 0)
+		    break;
+		}
+
+	      n = n->next;
+	    }
+
+	  sym = sym->next;
+	}
+
+      free (mod_name);
+    }
+}
+
+static void
+dump_update (void)
+{
+  struct grub_update_list *u;
+
+  u = update_list;
+  while (u)
+    {
+      struct grub_named_list *n;
+
+      printf ("%s:" , u->name);
+      n = u->add_mods;
+      while (n)
+	{
+	  printf (" +%s", n->name);
+	  n = n->next;
+	}
+
+      n = u->del_mods;
+      while (n)
+	{
+	  printf (" -%s", n->name);
+	  n = n->next;
+	}
+
+      printf ("\n");
+      u = u->next;
+    }
+}
+
+static void
+update_deps (struct grub_update_list *u, char *path)
+{
+  size_t size;
+  char *image;
+  Elf_Ehdr *e;
+  Elf_Off section_offset;
+  Elf_Half section_entsize;
+  Elf_Half num_sections;
+  Elf_Shdr *sections;
+  Elf_Shdr *moddep_section;
+  char *strtab, *pb, *pe;
+  struct grub_named_list *n;
+  int modified;
+
+  size = grub_util_get_image_size (path);
+  image = grub_util_read_image (path);
+
+  e = (Elf_Ehdr *) image;
+  if (! check_elf_header (e, size))
+    grub_util_error ("invalid ELF header");
+
+  section_offset = grub_target_to_host (e->e_shoff);
+  section_entsize = grub_target_to_host16 (e->e_shentsize);
+  num_sections = grub_target_to_host16 (e->e_shnum);
+
+  if (size < section_offset + section_entsize * num_sections)
+    grub_util_error ("invalid ELF format");
+
+  sections = (Elf_Shdr *) (image + section_offset);
+  strtab = find_strtab (e, sections, section_entsize);
+
+  moddep_section = find_moddep_section (sections, section_entsize,
+					num_sections, strtab);
+  if (! moddep_section)
+    grub_util_error ("no .moddeps section");
+
+  pb = (char *) e + grub_target_to_host (moddep_section->sh_offset);
+  pe = pb + grub_target_to_host32 (moddep_section->sh_size);
+  while (pb < pe)
+    {
+      if (! *pb)
+	break;
+
+      insert_string (&u->cur_mods, pb);
+      pb += strlen (pb) + 1;
+    }
+
+  modified = 0;
+  n = u->del_mods;
+  while (n)
+    {
+      modified += remove_string (&u->cur_mods, (char *) n->name);
+      n = n->next;
+    }
+  n = u->add_mods;
+  while (n)
+    {
+      modified += insert_string (&u->cur_mods, (char *) n->name);
+      n = n->next;
+    }
+
+  if (modified)
+    {
+      char *new_image, *p;
+      int old_size, new_size, delta, ofs;
+      Elf_Shdr *s;
+      int i;
+      FILE *fp;
+
+      new_size = 0;
+      n = u->cur_mods;
+      while (n)
+	{
+	  new_size += strlen (n->name) + 1;
+	  n = n->next;
+	}
+
+      old_size = (int) grub_target_to_host32 (moddep_section->sh_size);
+      delta = new_size - old_size ;
+
+      ofs = grub_target_to_host (moddep_section->sh_offset);
+      new_image = xmalloc ((int) size + delta);
+      e = (Elf_Ehdr *) new_image;
+
+      memcpy (new_image, image, ofs);
+
+      p = new_image + ofs;
+      n = u->cur_mods;
+      while (n)
+	{
+	  strcpy (p, n->name);
+	  p += strlen (p) + 1;
+	  n = n->next;
+	}
+
+      if (ofs + old_size < (int) size)
+	memcpy (p, image + ofs + old_size, (int) size - ofs - old_size);
+
+      if ((int) section_offset > ofs)
+	{
+	  section_offset = (int) section_offset + delta;
+	  e->e_shoff = grub_host_to_target (section_offset);
+	}
+
+      sections = (Elf_Shdr *) (new_image + section_offset);
+      moddep_section = find_moddep_section (sections, section_entsize,
+					    num_sections, strtab);
+      if (! moddep_section)
+	grub_util_error ("no .moddeps section");
+
+      moddep_section->sh_size = grub_host_to_target32 (new_size);
+
+      for (i = 0, s = sections;
+	   i < num_sections;
+	   i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+	{
+	  Elf_Off off;
+
+	  off = grub_target_to_host (s->sh_offset);
+	  if ((int) off > ofs)
+	    {
+	      off = (int) off + delta;
+	      s->sh_offset = grub_host_to_target (off);
+	    }
+	}
+
+      fp = fopen (path, "wb");
+      if (! fp)
+	grub_util_error ("Can\'t write to %s", path);
+
+      grub_util_write_image (new_image, (int) size + delta, fp);
+
+      fclose (fp);
+
+      free (new_image);
+    }
+
+  free (image);
+}
+
+static void
+write_moddep (struct grub_update_list *u, FILE *fp)
+{
+  struct grub_named_list *n;
+
+  if (! u->cur_mods)
+    return;
+
+  fprintf (fp, "%s:", u->name);
+  n = u->cur_mods;
+  while (n)
+    {
+      fprintf (fp, " %s", n->name);
+      n = n->next;
+    }
+
+  fprintf (fp, "\n");
+  free_named_list (&u->cur_mods);
+}
+
+static void
+update_moddep (char *dir)
+{
+  FILE *fp;
+  struct stat st;
+  char *path, *image;
+  struct grub_update_list *u;
+
+  path = grub_util_get_path (dir, "moddep.lst");
+  image = (stat (path, &st) == 0) ? grub_util_read_image (path) : 0;
+
+  fp = fopen (path, "w");
+  if (! fp)
+    grub_util_error ("Can\'t write to ", path);
+
+  if (image)
+    {
+      char *line;
+
+      line = image;
+      while (*line)
+	{
+	  char *p, *c;
+	  int n;
+
+	  n = strcspn (line, "\r\n");
+	  p = line;
+
+	  line += n;
+	  while ((*line == '\r') || (*line == '\n'))
+	    line++;
+
+	  *(p + n) = 0;
+
+	  c = strchr (p, ':');
+	  if (! c)
+	    continue;
+
+	  *c = 0;
+	  u = update_list;
+	  while (u)
+	    {
+	      int r;
+
+	      r = strcmp (p, u->name);
+	      if (! r)
+		break;
+
+	      if (r < 0)
+		{
+		  u = 0;
+		  break;
+		}
+
+	      u = u->next;
+	    }
+	  *c = ':';
+
+	  if (u)
+	    write_moddep (u, fp);
+	  else
+	    fprintf (fp, "%s\n", p);
+	}
+    }
+
+
+  u = update_list;
+  while (u)
+    {
+      write_moddep (u, fp);
+      u = u->next;
+    }
+
+  fclose (fp);
+  free (path);
+  free (image);
+}
+
+static void
+apply_update (char *dir)
+{
+  struct grub_update_list *u;
+
+  u = update_list;
+  while (u)
+    {
+      char *mod_path;
+
+      mod_path = grub_util_get_module_path (dir, u->name);
+      update_deps (u, mod_path);
+      free (mod_path);
+      u = u->next;
+    }
+
+  update_moddep (dir);
+}
+
+static struct option options[] =
+  {
+    {"directory", required_argument, 0, 'd'},
+    {"test", no_argument, 0, 't'},
+    {"help", no_argument, 0, 'h'},
+    {"version", no_argument, 0, 'V'},
+    {"verbose", no_argument, 0, 'v'},
+    {0, 0, 0, 0}
+  };
+
+static void
+usage (int status)
+{
+  if (status)
+    fprintf (stderr, "Try ``grub-symdb --help'' for more information.\n");
+  else
+    printf ("\
+Usage: grub-symdb [OPTION]... COMMAND\n\
+\n\
+Manage the symbol database of GRUB.\n\
+\nCommands:\n\
+  update MODULES          add/update modules to the symbol database\n\
+  remove MODULES          remove modules from the symbol databsae\n\
+  check                   check for duplicate and unresolved symbols\n\
+\n\
+  -d, --directory=DIR     use images and modules under DIR [default=%s]\n\
+  -t, --test              test mode\n\
+  -h, --help              display this message and exit\n\
+  -V, --version           print version information and exit\n\
+  -v, --verbose           print verbose messages\n\
+\n\
+Report bugs to <%s>.\n\
+", GRUB_LIBDIR, PACKAGE_BUGREPORT);
+
+  exit (status);
+}
+
+int
+main (int argc, char *argv[])
+{
+  char *dir = NULL;
+  char *path;
+  int test_mode = 0;
+
+  progname = "grub-symdb";
+
+  while (1)
+    {
+      int c = getopt_long (argc, argv, "d:thVv", options, 0);
+
+      if (c == -1)
+	break;
+      else
+	switch (c)
+	  {
+	  case 'd':
+	    if (dir)
+	      free (dir);
+
+	    dir = xstrdup (optarg);
+	    break;
+
+	  case 't':
+	    test_mode++;
+	    break;
+
+	  case 'h':
+	    usage (0);
+	    break;
+
+	  case 'V':
+	    printf ("grub-mkimage (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
+	    return 0;
+
+	  case 'v':
+	    verbosity++;
+	    break;
+
+	  default:
+	    usage (1);
+	    break;
+	  }
+    }
+
+  if (! dir)
+    dir = xstrdup (GRUB_LIBDIR);
+
+  path = grub_util_get_path (dir, "modsym.lst");
+
+  argv += optind;
+  argc -= optind;
+  if (argc == 0)
+    grub_util_error ("No command specified.");
+
+  read_symdb (path);
+  if (! strcmp (argv[0], "update"))
+    {
+      remove_mods (argv + 1);
+      update_mods (argv + 1, dir);
+      if (test_mode)
+	dump_update ();
+      else
+	{
+	  apply_update (dir);
+	  write_symdb (path);
+	}
+    }
+  else if (! strcmp (argv[0], "remove"))
+    {
+      remove_mods (argv + 1);
+      if (test_mode)
+	dump_update ();
+      else
+	{
+	  apply_update (dir);
+	  write_symdb (path);
+	}
+    }
+  else if (! strcmp (argv[0], "check"))
+    {
+      check_symdb ();
+    }
+  else
+    grub_util_error ("Unkown command %s.", argv[0]);
+
+  free (path);
+  free (dir);
+
+  return 0;
+}
diff --git a/util/resolve.c b/util/resolve.c
index 85aec72..37ee020 100644
--- a/util/resolve.c
+++ b/util/resolve.c
@@ -126,8 +126,8 @@ read_dep_list (FILE *fp)
   return dep_list;
 }
 
-static char *
-get_module_name (const char *str)
+char *
+grub_util_get_module_name (const char *str)
 {
   char *base;
   char *ext;
@@ -152,8 +152,8 @@ get_module_name (const char *str)
   return xstrdup (base);
 }
 
-static char *
-get_module_path (const char *prefix, const char *str)
+char *
+grub_util_get_module_path (const char *prefix, const char *str)
 {
   char *dir;
   char *base;
@@ -190,7 +190,7 @@ add_module (const char *dir,
   struct mod_list *mod;
   struct dep_list *dep;
   
-  mod_name = get_module_name (name);
+  mod_name = grub_util_get_module_name (name);
 
   /* Check if the module has already been added.  */
   for (mod = *mod_head; mod; mod = mod->next)
@@ -218,7 +218,7 @@ add_module (const char *dir,
 
   /* Add this path.  */
   path = (struct grub_util_path_list *) xmalloc (sizeof (*path));
-  path->name = get_module_path (dir, name);
+  path->name = grub_util_get_module_path (dir, name);
   path->next = *path_head;
   *path_head = path;
 }

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH] Use symbol database to maintain module dependence
  2009-04-20 21:11 [PATCH] Use symbol database to maintain module dependence Bean
@ 2009-04-27  6:33 ` Bean
  2009-04-27 18:13   ` Vladimir 'phcoder' Serbinenko
  0 siblings, 1 reply; 6+ messages in thread
From: Bean @ 2009-04-27  6:33 UTC (permalink / raw)
  To: The development of GRUB 2

Hi,

ping ?

On Tue, Apr 21, 2009 at 5:11 AM, Bean <bean123ch@gmail.com> wrote:
> Hi,
>
> This patch add a new tool grub-symdb to manage symbol database and
> update module dependence as required. The build process is greatly
> simplified, moddep.lst, def-*.lst, und-*.lst are not generated
> anymore. grub-symdb will read the module files and update modsym.lst
> and moddep.lst automatically.
>
> --
> Bean
>



-- 
Bean



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Use symbol database to maintain module dependence
  2009-04-27  6:33 ` Bean
@ 2009-04-27 18:13   ` Vladimir 'phcoder' Serbinenko
  2009-04-27 19:58     ` Bean
  0 siblings, 1 reply; 6+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-04-27 18:13 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 1288 bytes --]

symdb code seems to duplicate your list code. Perhaps you could reuse the
file from kernel thus making maintaining easier
I liked the file modsym.lst: it gives clear view of symbols.
This patch brek grub-install because moddep.lst isn't copied correctly
Also check that
Also in some places I saw
+  while (n)
+    {
+      modified += remove_string (&u->cur_mods, (char *) n->name);
Here perhaps modified = remove_string (..) || modified; is more appropriate
+      n = n->next;
+    }

+  remove MODULES          remove modules from the symbol databsae\n\
Typo

On Mon, Apr 27, 2009 at 8:33 AM, Bean <bean123ch@gmail.com> wrote:

> Hi,
>
> ping ?
>
> On Tue, Apr 21, 2009 at 5:11 AM, Bean <bean123ch@gmail.com> wrote:
> > Hi,
> >
> > This patch add a new tool grub-symdb to manage symbol database and
> > update module dependence as required. The build process is greatly
> > simplified, moddep.lst, def-*.lst, und-*.lst are not generated
> > anymore. grub-symdb will read the module files and update modsym.lst
> > and moddep.lst automatically.
> >
> > --
> > Bean
> >
>
>
>
> --
> Bean
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>



-- 
Regards
Vladimir 'phcoder' Serbinenko

[-- Attachment #2: Type: text/html, Size: 2040 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Use symbol database to maintain module dependence
  2009-04-27 18:13   ` Vladimir 'phcoder' Serbinenko
@ 2009-04-27 19:58     ` Bean
  2009-05-04  0:18       ` Vladimir 'phcoder' Serbinenko
  0 siblings, 1 reply; 6+ messages in thread
From: Bean @ 2009-04-27 19:58 UTC (permalink / raw)
  To: The development of GRUB 2

On Tue, Apr 28, 2009 at 2:13 AM, Vladimir 'phcoder' Serbinenko
<phcoder@gmail.com> wrote:
> symdb code seems to duplicate your list code. Perhaps you could reuse the
> file from kernel thus making maintaining easier

Hi,

I'm planning to use kern/list.c at first, but there is some issue.
list.c uses grub_strcmp, which means we need to add kern/misc.c as
well. But kern/misc.c uses environment and terminal output, etc. I end
up adding a lot of unrelated stuff just to satisfy the dependence. So
perhaps it'd be better to keep it simple for now.

A better solution is to move the string function to a separate source
file, such as kern/string.c. But this is the subject of another patch.

> I liked the file modsym.lst: it gives clear view of symbols.
> This patch brek grub-install because moddep.lst isn't copied correctly
> Also check that
> Also in some places I saw
> +  while (n)
> +    {
> +      modified += remove_string (&u->cur_mods, (char *) n->name);
> Here perhaps modified = remove_string (..) || modified; is more appropriate
> +      n = n->next;
> +    }
>

Right, the += is a quick trick, || would be more meaningful.

> +  remove MODULES          remove modules from the symbol databsae\n\
> Typo
>

Oh, thanks for noticing this.

> On Mon, Apr 27, 2009 at 8:33 AM, Bean <bean123ch@gmail.com> wrote:
>>
>> Hi,
>>
>> ping ?
>>
>> On Tue, Apr 21, 2009 at 5:11 AM, Bean <bean123ch@gmail.com> wrote:
>> > Hi,
>> >
>> > This patch add a new tool grub-symdb to manage symbol database and
>> > update module dependence as required. The build process is greatly
>> > simplified, moddep.lst, def-*.lst, und-*.lst are not generated
>> > anymore. grub-symdb will read the module files and update modsym.lst
>> > and moddep.lst automatically.
>> >
>> > --
>> > Bean
>> >
>>
>>
>>
>> --
>> Bean
>>
>>
>> _______________________________________________
>> Grub-devel mailing list
>> Grub-devel@gnu.org
>> http://lists.gnu.org/mailman/listinfo/grub-devel
>
>
>
> --
> Regards
> Vladimir 'phcoder' Serbinenko
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>
>



-- 
Bean



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Use symbol database to maintain module dependence
  2009-04-27 19:58     ` Bean
@ 2009-05-04  0:18       ` Vladimir 'phcoder' Serbinenko
  2009-05-04  6:21         ` Bean
  0 siblings, 1 reply; 6+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-05-04  0:18 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 1156 bytes --]

On Mon, Apr 27, 2009 at 9:58 PM, Bean <bean123ch@gmail.com> wrote:

> On Tue, Apr 28, 2009 at 2:13 AM, Vladimir 'phcoder' Serbinenko
> <phcoder@gmail.com> wrote:
> > symdb code seems to duplicate your list code. Perhaps you could reuse the
> > file from kernel thus making maintaining easier
>
> Hi,
>
> I'm planning to use kern/list.c at first, but there is some issue.
> list.c uses grub_strcmp, which means we need to add kern/misc.c as
> well. But kern/misc.c uses environment and terminal output, etc. I end
> up adding a lot of unrelated stuff just to satisfy the dependence. So
> perhaps it'd be better to keep it simple for now.

why not just do
int
grub_strcmp (....)
{
  return strcmp(...);
}
like it's done it other utils?

>
>
> A better solution is to move the string function to a separate source
> file, such as kern/string.c. But this is the subject of another patch.
>

Also now I'm looking into compiling of grub2 with Apple's gcc and binutils
and this patch makes this easier. Was it done in perspective of compiling
with Apple's tools? Do you work on this? If you do we could share the effort

-- 
Regards
Vladimir 'phcoder' Serbinenko

[-- Attachment #2: Type: text/html, Size: 1775 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Use symbol database to maintain module dependence
  2009-05-04  0:18       ` Vladimir 'phcoder' Serbinenko
@ 2009-05-04  6:21         ` Bean
  0 siblings, 0 replies; 6+ messages in thread
From: Bean @ 2009-05-04  6:21 UTC (permalink / raw)
  To: The development of GRUB 2

On Mon, May 4, 2009 at 8:18 AM, Vladimir 'phcoder' Serbinenko
<phcoder@gmail.com> wrote:
>
>
> On Mon, Apr 27, 2009 at 9:58 PM, Bean <bean123ch@gmail.com> wrote:
>>
>> On Tue, Apr 28, 2009 at 2:13 AM, Vladimir 'phcoder' Serbinenko
>> <phcoder@gmail.com> wrote:
>> > symdb code seems to duplicate your list code. Perhaps you could reuse
>> > the
>> > file from kernel thus making maintaining easier
>>
>> Hi,
>>
>> I'm planning to use kern/list.c at first, but there is some issue.
>> list.c uses grub_strcmp, which means we need to add kern/misc.c as
>> well. But kern/misc.c uses environment and terminal output, etc. I end
>> up adding a lot of unrelated stuff just to satisfy the dependence. So
>> perhaps it'd be better to keep it simple for now.
>
> why not just do
> int
> grub_strcmp (....)
> {
>   return strcmp(...);
> }
> like it's done it other utils?
>>
>>

Hi,

Or perhaps just define macro in header files:

#ifdef GRUB_UTIL
#define grub_strcmp strcmp
#endif

I remember grub legacy used to do this.

>> A better solution is to move the string function to a separate source
>> file, such as kern/string.c. But this is the subject of another patch.
>
> Also now I'm looking into compiling of grub2 with Apple's gcc and binutils
> and this patch makes this easier. Was it done in perspective of compiling
> with Apple's tools? Do you work on this? If you do we could share the effort

My original plan for this patch is to lay the foundation for external
module support. I haven't try the apple build tools yet. In fact, I
scratched osx in testing sometime ago, and having find the time to
reinstall it yet.

>
> --
> Regards
> Vladimir 'phcoder' Serbinenko
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>
>



-- 
Bean



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2009-05-04  6:21 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-04-20 21:11 [PATCH] Use symbol database to maintain module dependence Bean
2009-04-27  6:33 ` Bean
2009-04-27 18:13   ` Vladimir 'phcoder' Serbinenko
2009-04-27 19:58     ` Bean
2009-05-04  0:18       ` Vladimir 'phcoder' Serbinenko
2009-05-04  6:21         ` Bean

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.