map.c
上传用户:hxtd_72
上传日期:2007-06-06
资源大小:64k
文件大小:8k
源码类别:

驱动编程

开发平台:

C/C++

  1. /*
  2.     map.c.
  3.     Read System.map for ksymoops, create merged System.map.
  4.     Copyright 1999 Keith Owens <kaos@ocs.com.au>.
  5.     Released under the GNU Public Licence, Version 2.
  6.  */
  7. #include "ksymoops.h"
  8. #include <malloc.h>
  9. #include <string.h>
  10. /* Read the symbols from System.map */
  11. void read_system_map(const OPTIONS *options)
  12. {
  13.     FILE *f;
  14.     char *line = NULL, **string = NULL;
  15.     int i, size = 0;
  16.     static int merged = 0;
  17.     static char const procname[] = "read_system_map";
  18.     const char *system_map = options->system_map;
  19.     if (!system_map)
  20. return;
  21.     ss_init(&ss_system_map, "System.map");
  22.     DEBUG(1, "%s", system_map);
  23.     if (!regular_file(system_map, procname))
  24. return;
  25.     if (!(f = fopen_local(system_map, "r", procname)))
  26. return;
  27.     while (fgets_local(&line, &size, f, procname)) {
  28. i = regexec(&re_nm, line, re_nm.re_nsub+1, re_nm_pmatch, 0);
  29. DEBUG(4, "regexec %d", i);
  30. if (i == 0) {
  31.     re_strings(&re_nm, line, re_nm_pmatch, &string);
  32.     /* If the input is a merged system map then it can contain module
  33.      * data, add these as if they came from ksyms.  The system map is
  34.      * read last so we can check if there is any other module data,
  35.      * reading from both a merged map and module data does not make
  36.      * sense.
  37.      */
  38.     if (string[5]) {
  39. if (++merged == 1 && ss_ksyms_modules)
  40.     ERROR("%s appears to be a merged System.map, it contains [module] names.n"
  41.   "ttYou also supplied ksyms, this combination makes no sense.n"
  42.   "ttPlease use -VKLO -m %s.",
  43.   system_map, system_map);
  44. add_ksyms(string[1], string[2][0], string[3], string[5], options);
  45.     }
  46.     else
  47. add_symbol(&ss_system_map, string[1], *string[2],
  48.        1, string[3]);
  49. }
  50.     }
  51.     fclose_local(f, procname);
  52.     re_strings_free(&re_nm, &string);
  53.     free(line);
  54.     if (ss_system_map.used) {
  55. ss_sort_na(&ss_system_map);
  56. extract_Version(&ss_system_map);
  57.     }
  58.     else {
  59. WARNING("no kernel symbols in System.map, is %s a valid System.map "
  60. "file?", system_map);
  61.     }
  62.     DEBUG(2, "%s used %d out of %d entries", ss_system_map.source,
  63. ss_system_map.used, ss_system_map.alloc);
  64. }
  65. /* Compare two maps, all symbols in the first should appear in the second. */
  66. void compare_maps(const SYMBOL_SET *ss1, const SYMBOL_SET *ss2,
  67.      int precedence)
  68. {
  69.     int i, start = 0;
  70.     SYMBOL *s1, *s2, **sdrop = precedence == 1 ? &s2 : &s1;
  71.     const SYMBOL_SET **ssdrop = precedence == 1 ? &ss2 : &ss1;
  72.     static char const procname[] = "compare_maps";
  73.     if (!(ss1->used && ss2->used))
  74. return;
  75.     DEBUG(2, "%s vs %s, %s takes precedence", ss1->source, ss2->source,
  76. precedence == 1 ? ss1->source : ss2->source);
  77.     for (i = 0; i < ss1->used; ++i) {
  78. s1 = ss1->symbol+i;
  79. if (!(s1->keep))
  80.     continue;
  81. s2 = find_symbol_name(ss2, s1->name, &start);
  82. if (!s2) {
  83.     /* Some types only appear in nm output, not in things
  84.      * like System.map.  Silently ignore them.
  85.      */
  86.     if (s1->type == 'a' || s1->type == 't')
  87. continue;
  88.     /* modutils assist uses generated symbols */
  89.     if (s1->type == 'G' || s1->type == 'g')
  90. continue;
  91.     WARNING("%s symbol %s not found in %s.  Ignoring %s entry",
  92. ss1->source, s1->name,
  93. ss2->source, (*ssdrop)->source);
  94.     if (*sdrop)
  95. (*sdrop)->keep = 0;
  96. }
  97. else if (s1->address != s2->address) {
  98.     /* Type C symbols cannot be resolved from nm to ksyms,
  99.      * silently ignore them.
  100.      */
  101.     if (s1->type == 'C' || s2->type == 'C')
  102. continue;
  103.     /* Jakub Jelinek says that ___[fbsahi]_.* symbols are relocated at
  104.      * boot time so silently ignore any mismatches on these symbols.
  105.      */
  106.     if (strncmp(s1->name, "___", 3) == 0 &&
  107. s1->name[4] == '_' &&
  108. (s1->name[3] == 'f' ||
  109.  s1->name[3] == 'b' ||
  110.  s1->name[3] == 's' ||
  111.  s1->name[3] == 'a' ||
  112.  s1->name[3] == 'h' ||
  113.  s1->name[3] == 'i'))
  114. continue;
  115.     WARNING("mismatch on symbol %s %c, %s says %llx, %s says %llx.  "
  116.     "Ignoring %s entry",
  117. s1->name, s1->type, ss1->source, s1->address,
  118. ss2->source, s2->address, (*ssdrop)->source);
  119.     if (*sdrop)
  120. (*sdrop)->keep = 0;
  121. }
  122. else
  123.     ++start;    /* step to next entry in ss2 */
  124.     }
  125. }
  126. /* Append the second symbol set onto the first */
  127. static void append_map(SYMBOL_SET *symbol, const SYMBOL_SET *related, char *module)
  128. {
  129.     int i, symnum;
  130.     SYMBOL *s;
  131.     static char const procname[] = "append_map";
  132.     if (!related || !related->used)
  133. return;
  134.     DEBUG_S(2, "%s to %s", related->source, symbol->source);
  135.     if (module)
  136. DEBUG_E(2, " [%s]", module);
  137.     else
  138. DEBUG_E(2, "%s", "");
  139.     for (i = 0; i < related->used; ++i) {
  140. s = related->symbol+i;
  141. if (s->keep) {
  142.     symnum = add_symbol_n(symbol, s->address, s->type, 1, s->name);
  143.     (symbol->symbol)[symnum].module = module;
  144. }
  145.     }
  146. }
  147. /* Compare the various sources and build a merged system map */
  148. void merge_maps(const OPTIONS *options)
  149. {
  150.     int i;
  151.     SYMBOL *s;
  152.     FILE *f;
  153.     static char const procname[] = "merge_maps";
  154.     const char *save_system_map = options->save_system_map;
  155.     DEBUG(1, "%s", "");
  156.     /* Using_Versions only appears in ksyms, copy to other tables */
  157.     if ((s = find_symbol_name(&ss_ksyms_base,
  158.     "Using_Versions", 0))) {
  159. if (ss_system_map.used) {
  160.     add_symbol_n(&ss_system_map, s->address,
  161. s->type, s->keep, s->name);
  162.     ss_sort_na(&ss_system_map);
  163. }
  164. if (ss_vmlinux.used) {
  165.     add_symbol_n(&ss_vmlinux, s->address, s->type,
  166. s->keep, s->name);
  167.     ss_sort_na(&ss_vmlinux);
  168. }
  169.     }
  170.     compare_Version();  /* highlight any version problems first */
  171.     compare_ksyms_lsmod();  /* highlight any missing modules next */
  172.     compare_maps(&ss_ksyms_base, &ss_vmlinux, 2);
  173.     compare_maps(&ss_system_map, &ss_vmlinux, 2);
  174.     compare_maps(&ss_vmlinux, &ss_system_map, 1);
  175.     compare_maps(&ss_ksyms_base, &ss_system_map, 2);
  176.     if (ss_objects) {
  177. map_ksyms_to_modules();
  178.     }
  179.     ss_init(&ss_merged, "merged");
  180.     append_map(&ss_merged, &ss_vmlinux, NULL);
  181.     append_map(&ss_merged, &ss_ksyms_base, NULL);
  182.     append_map(&ss_merged, &ss_system_map, NULL);
  183.     for (i = 0; i < ss_ksyms_modules; ++i)
  184. append_map(&ss_merged,
  185.     (ss_ksyms_module[i]->related ?
  186. ss_ksyms_module[i]->related :
  187. ss_ksyms_module[i]),
  188.     ss_ksyms_module[i]->source);
  189.     if (!ss_merged.used)
  190. WARNING("%s", "no symbols in merged map");
  191.     /* drop duplicates, type a (registers), type G (modutils assist) and
  192.      * gcc2_compiled.
  193.      */
  194.     ss_sort_atn(&ss_merged);
  195.     s = ss_merged.symbol;
  196.     for (i = 0; i < ss_merged.used-1; ++i) {
  197. if (s->type == 'a' || s->type == 'G' ||
  198.     (s->type == 't' && !strcmp(s->name, "gcc2_compiled."))) {
  199.     DEBUG(3, "dropping non duplicate %s %c", s->name, s->type);
  200.     s->keep = 0;
  201. }
  202. else if (strcmp(s->name, (s+1)->name) == 0 &&
  203.     s->address == (s+1)->address) {
  204.     if (s->type != ' ')
  205. (s+1)->keep = 0;
  206.     else
  207. s->keep = 0;
  208. }
  209. ++s;
  210.     }
  211.     ss_sort_atn(&ss_merged);    /* will remove dropped variables */
  212.     if (save_system_map) {
  213. DEBUG(1, "writing merged map to %s", save_system_map);
  214. if (!(f = fopen_local(save_system_map, "w", procname)))
  215.     return;
  216. s = ss_merged.symbol;
  217. for (i = 0; i < ss_merged.used; ++i) {
  218.     if (s->keep) {
  219. fprintf(f, "%s %c %s",
  220.     format_address(s->address, options),
  221.     s->type, s->name);
  222.     if (s->module)
  223. fprintf(f, "t[%s]", s->module);
  224.     fprintf(f, "n");
  225.     }
  226.     ++s;
  227. }
  228.     }
  229.     /* The merged map may contain symbols with an address of 0, e.g.
  230.      * Using_Versions.  These give incorrect results for low addresses in
  231.      * map_address, such addresses map to "Using_Versions+xxx".  Remove
  232.      * any addresses below (arbitrary) 4096 from the merged map.  AFAIK,
  233.      * Linux does not use the first page on any arch.
  234.      */
  235.     for (i = 0; i < ss_merged.used; ++i) {
  236. if ((ss_merged.symbol+i)->address < 4096) {
  237.     DEBUG(3, "dropping low address %s %c", s->name, s->type);
  238.     (ss_merged.symbol+i)->keep = 0;
  239. }
  240. else
  241.     break;
  242.     }
  243.     if (i)
  244. ss_sort_atn(&ss_merged);    /* remove dropped variables */
  245. }