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

驱动编程

开发平台:

C/C++

  1. /*
  2.     object.c.
  3.     object handling routines for ksymoops.  Read modules, vmlinux, etc.
  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. #include <sys/stat.h>
  11. /* Extract all symbols definitions from an object using nm */
  12. static void read_nm_symbols(SYMBOL_SET *ss, const char *file)
  13. {
  14.     FILE *f;
  15.     char *cmd, *line = NULL, **string = NULL;
  16.     int i, size = 0;
  17.     static char const procname[] = "read_nm_symbols";
  18.     if (!regular_file(file, procname))
  19. return;
  20.     cmd = malloc(strlen(path_nm)+strlen(file)+2);
  21.     if (!cmd)
  22. malloc_error("nm command");
  23.     strcpy(cmd, path_nm);
  24.     strcat(cmd, " ");
  25.     strcat(cmd, file);
  26.     DEBUG(2, "command '%s'", cmd);
  27.     if (!(f = popen_local(cmd, procname)))
  28. return;
  29.     free(cmd);
  30.     while (fgets_local(&line, &size, f, procname)) {
  31. i = regexec(&re_nm, line, re_nm.re_nsub+1, re_nm_pmatch, 0);
  32. DEBUG(4, "regexec %d", i);
  33. if (i == 0) {
  34.     re_strings(&re_nm, line, re_nm_pmatch, &string);
  35.     add_symbol(ss, string[1], *string[2], 1, string[3]);
  36. }
  37.     }
  38.     pclose_local(f, procname);
  39.     re_strings_free(&re_nm, &string);
  40.     free(line);
  41.     DEBUG(2, "%s used %d out of %d entries", ss->source, ss->used, ss->alloc);
  42. }
  43. /* Read the symbols from vmlinux */
  44. void read_vmlinux(const OPTIONS *options)
  45. {
  46.     static char procname[] = "read_vmlinux";
  47.     const char *vmlinux = options->vmlinux;
  48.     if (!vmlinux)
  49. return;
  50.     ss_init(&ss_vmlinux, "vmlinux");
  51.     read_nm_symbols(&ss_vmlinux, vmlinux);
  52.     if (ss_vmlinux.used) {
  53. ss_sort_na(&ss_vmlinux);
  54. extract_Version(&ss_vmlinux);
  55.     }
  56.     else
  57. WARNING("no kernel symbols in vmlinux, is %s a valid vmlinux file?",
  58.     vmlinux);
  59. }
  60. /* Read the symbols from one object (module) */
  61. void read_object(const char *object, int i)
  62. {
  63.     static char procname[] = "read_object";
  64.     ss_init(ss_object[i], object);
  65.     read_nm_symbols(ss_object[i], object);
  66.     if ((ss_object[i])->used) {
  67. ss_sort_na(ss_object[i]);
  68. extract_Version(ss_object[i]);
  69.     }
  70.     else
  71. WARNING("no symbols in %s", object);
  72. }
  73. /* Add a new entry to the list of objects */
  74. static SYMBOL_SET *add_ss_object(const char *file)
  75. {
  76.     struct stat statbuf;
  77.     int i;
  78.     static char const procname[] = "add_ss_object";
  79.     /* Avoid reading any object twice. */
  80.     for (i = 0; i < ss_objects; ++i) {
  81. if (strcmp((ss_object[i])->source, file) == 0)
  82.     return(ss_object[i]);
  83.     }
  84.     ++ss_objects;
  85.     ss_object = realloc(ss_object, ss_objects*sizeof(*ss_object));
  86.     if (!ss_object)
  87. malloc_error("realloc ss_object");
  88.     if (!(ss_object[ss_objects-1] = malloc(sizeof(*ss_object[0]))))
  89. malloc_error("alloc ss_object[n]");
  90.     ss_init(ss_object[ss_objects-1], file);
  91.     if (stat(file, &statbuf)) {
  92. ERROR("cannot stat(%s)", file);
  93. perror(prefix);
  94.     }
  95.     else {
  96. ss_object[ss_objects-1]->mtime = statbuf.st_mtime;
  97.     }
  98.     return(ss_object[ss_objects-1]);
  99. }
  100. /* Run a directory and its subdirectories, looking for *.o files */
  101. static void find_objects(const char *dir)
  102. {
  103.     FILE *f;
  104.     char *cmd, *line = NULL;
  105.     int size = 0, files = 0;
  106.     static char const procname[] = "find_objects";
  107.     static char const options[] = " -follow '(' -path '*/build' -prune ')' -o -name '*.o' -print";
  108.     cmd = malloc(strlen(path_find)+1+strlen(dir)+strlen(options)+1);
  109.     if (!cmd)
  110. malloc_error("find command");
  111.     strcpy(cmd, path_find);
  112.     strcat(cmd, " ");
  113.     strcat(cmd, dir);
  114.     strcat(cmd, options);
  115.     DEBUG(2, "command '%s'", cmd);
  116.     if (!(f = popen_local(cmd, procname)))
  117. return;
  118.     free(cmd);
  119.     while (fgets_local(&line, &size, f, procname)) {
  120. DEBUG(2, "%s", line);
  121. add_ss_object(line);
  122. ++files;
  123.     }
  124.     pclose_local(f, procname);
  125.     if (!files)
  126. WARNING("no *.o files in %s.  Is %s a valid module directory?",
  127.     dir, dir);
  128. }
  129. /* Run the object paths, extracting anything that looks like a module name.
  130.  */
  131. static void run_object_paths(const OPTIONS *options)
  132. {
  133.     struct stat statbuf;
  134.     int i;
  135.     const char *file;
  136.     static char const procname[] = "run_object_paths";
  137.     DEBUG(1, "%s", "");
  138.     for (i = 0; i < options->objects; ++i) {
  139. file = options->object[i];
  140. DEBUG_S(2, "checking %s - ", file);
  141. if (!stat(file, &statbuf) && S_ISDIR(statbuf.st_mode)) {
  142.     DEBUG_E(2, "%s", "directory, expanding");
  143.     find_objects(file);
  144. }
  145. else {
  146.     DEBUG_E(2, "%s", "not directory");
  147.     add_ss_object(file);
  148. }
  149.     }
  150. }
  151. /* Take the user supplied list of objects which can include directories.
  152.  * Expand directories into any *.o files.  The results are stored in
  153.  * ss_object, leaving the user supplied options untouched.  If a ksyms
  154.  * entry contains the name of its object file, use that by preference.
  155.  * If --ignore-insmod-path is set then use the first object with the
  156.  * same mtime and basename.
  157.  */
  158. void expand_objects(const OPTIONS *options)
  159. {
  160.     struct stat statbuf;
  161.     int i, do_the_lot = 0, run_objects = 0;
  162.     SYMBOL_SET *ss;
  163.     const char *file;
  164.     static char const procname[] = "expand_objects";
  165.     for (i = 0; i < ss_ksyms_modules; ++i) {
  166. ss = ss_ksyms_module[i];
  167. if (!ss->object) {
  168.     do_the_lot = 1;
  169.     continue;
  170. }
  171. file = ss->object;
  172. if (options->ignore_insmod_path) {
  173.     /* Use the basename and mtime from insmod */
  174.     const char *basename = strrchr(file, '/'), *p;
  175.     int j;
  176.     if (basename)
  177. ++basename;
  178.     else
  179. basename = file;
  180.     DEBUG(1, "looking for basename %s with mtime %ld for %s",
  181. basename, ss->mtime, ss->source);
  182.     if (!run_objects) {
  183. run_object_paths(options);
  184. run_objects = 1;
  185.     }
  186.     for (j = 0; j < ss_objects; ++j) {
  187. if (ss_object[j]->mtime == ss->mtime) {
  188.     p = strrchr(ss_object[j]->source, '/');
  189.     if (p)
  190. ++p;
  191.     else
  192. p = ss_object[j]->source;
  193.     if (strcmp(p, basename) == 0) {
  194. DEBUG(1, "found %s for %s", ss_object[j]->source, file);
  195. free((char *)(ss->object));
  196. ss->object = strdup(ss_object[j]->source);
  197. if (!ss->object)
  198.     malloc_error(procname);
  199. file = ss->object;
  200. ss->related = add_ss_object(file);
  201. break;
  202.     }
  203. }
  204.     }
  205.     if (j == ss_objects) {
  206. DEBUG(1, "no match on basename %s with mtime %ld", basename, ss->mtime);
  207. do_the_lot = 1;
  208. continue;
  209.     }
  210. }
  211. else {
  212.     /* Use the full pathname from insmod */
  213.     DEBUG(1, "using %s for %s", file, ss->source);
  214.     if (stat(ss->object, &statbuf)) {
  215. ERROR("cannot stat(%s) for %s", file, ss->source);
  216. perror(prefix);
  217. do_the_lot = 1;
  218. continue;
  219.     }
  220.     if (statbuf.st_mtime != ss->mtime)
  221. WARNING("object %s for module %s has changed since load",
  222.     file, ss->source);
  223.     ss->related = add_ss_object(file);
  224. }
  225.     }
  226.     if (!do_the_lot) {
  227. DEBUG(1, "%s", "all ksyms modules map to specific object files");
  228. return;
  229.     }
  230.     DEBUG(1, "%s", "missing or mismatched modutils assists, doing it the hard way");
  231.     if (!run_objects) {
  232. run_object_paths(options);
  233. run_objects = 1;
  234.     }
  235. }
  236. /* Map a symbol type to a section code. 0 - text, 1 - data, 2 - read only data,
  237.  * 3 - bss, 4 - sbss, 5 - C (cannot relocate), 6 - the rest.
  238.  */
  239. static int section(char type)
  240. {
  241.     switch (type) {
  242.     case 'T':
  243.     case 't':
  244.     case 'W': /* Resolved weak reference to text */
  245. return 0;
  246.     case 'D':
  247.     case 'd':
  248. return 1;
  249.     case 'R':
  250.     case 'r':
  251. return 2;
  252.     case 'B':
  253.     case 'b':
  254. return 3;
  255.     case 'S':
  256.     case 's':
  257. return 4;
  258.     case 'C':
  259. return 5;
  260.     default:
  261. return 6;
  262.     }
  263. }
  264. /* Given ksyms module data which has a related object, create a copy of the
  265.  * object data, adjusting the offsets to match where the module was loaded.
  266.  */
  267. SYMBOL_SET *adjust_object_offsets(SYMBOL_SET *ss)
  268. {
  269.     int i;
  270.     addr_t adjust[] = {0, 0, 0, 0, 0, 0, 0};
  271.     char type;
  272.     SYMBOL *sk, *so;
  273.     SYMBOL_SET *ssc;
  274.     static char const procname[] = "adjust_object_offsets";
  275.     ssc = ss_copy(ss->related);
  276.     /* For common symbols, calculate the adjustment */
  277.     for (i = 0; i < ss->used; ++i) {
  278. sk = ss->symbol+i;
  279. /* modutils assists have type G, the symbol contains the section name */
  280. if (sk->type == 'G') {
  281.     if (strstr(sk->name, "_S.text_"))
  282. type = 'T';
  283.     else if (strstr(sk->name, "_S.rodata_"))
  284. type = 'R';
  285.     else if (strstr(sk->name, "_S.data_"))
  286. type = 'D';
  287.     else if (strstr(sk->name, "_S.bss_"))
  288. type = 'B';
  289.     else if (strstr(sk->name, "_S.sbss_"))
  290. type = 'S';
  291.     else
  292. type = ' ';
  293.     /* Assumption: all sections start at relative offset 0 */
  294.     adjust[section(type)] = sk->address;
  295. }
  296. else if ((so = find_symbol_name(ssc, sk->name, NULL))) {
  297.     if (!adjust[section(so->type)])
  298. adjust[section(so->type)] = sk->address - so->address;
  299. }
  300.     }
  301.     for (i = 0; i < ssc->used; ++i) {
  302. so = ssc->symbol+i;
  303. /* Type C does not relocate well, silently ignore */
  304. if (so->type != 'C' && adjust[section(so->type)])
  305.     so->address += adjust[section(so->type)];
  306. else
  307.     so->keep = 0;  /* do not merge into final map */
  308.     }
  309.     /* Copy modutils assist symbols to object symbol table */
  310.     for (i = 0; i < ss->used; ++i) {
  311. sk = ss->symbol+i;
  312. if (sk->type == 'G' || sk->type == 'g')
  313.     add_symbol_n(ssc, sk->address, sk->type, 1, sk->name);
  314.     }
  315.     ss->related = ssc;  /* map using adjusted copy */
  316.     DEBUG(2, "%s text %llx rodata %llx data %llx bss %llx", ss->source, adjust[0], adjust[1], adjust[2], adjust[3]);
  317.     return(ssc);
  318. }