现在的位置: 首页 > 综合 > 正文

Modultils工具源码分析之insmod篇 (9)

2013年08月17日 ⁄ 综合 ⁄ 共 4383字 ⁄ 字号 评论关闭

处理完命令行参数,INSMOD_MAIN接下来调用arch_create_got。这个函数在./modutils-2.4.0/obj/obj_i386.c中。

Insmod——arch_create_got函数

158  int

159  arch_create_got (struct obj_file *f)

160  {

161    struct i386_file *ifile = (struct i386_file *)f;

162    int i, n, offset = 0, gotneeded = 0;

163

164    n = ifile->root.header.e_shnum;

165    for (i = 0; i < n; ++i)

166      {

167        struct obj_section *relsec, *symsec, *strsec;

168        Elf32_Rel *rel, *relend;

169        Elf32_Sym *symtab;

170        const char *strtab;

171

172        relsec = ifile->root.sections[i];

173       if (relsec->header.sh_type != SHT_REL)

174                continue;

175

176        symsec = ifile->root.sections[relsec->header.sh_link];

177       strsec = ifile->root.sections[symsec->header.sh_link];

178

179        rel = (Elf32_Rel *)relsec->contents;

180       relend = rel + (relsec->header.sh_size / sizeof(Elf32_Rel));

181       symtab = (Elf32_Sym *)symsec->contents;

182       strtab = (const char *)strsec->contents;

183

184      for (; rel < relend; ++rel)

185       {

186           Elf32_Sym *extsym;

187           struct i386_symbol *intsym;

188           const char *name;

189

190           switch (ELF32_R_TYPE(rel->r_info))

191               {

192             case R_386_GOTPC:

193             case R_386_GOTOFF:

194               gotneeded = 1;

195             default:

196               continue;

197

198             case R_386_GOT32:

199               break;

200             }

201

202           extsym = &symtab[ELF32_R_SYM(rel->r_info)];

203           if (extsym->st_name)

204             name = strtab + extsym->st_name;

205           else

206             name = f->sections[extsym->st_shndx]->name;

207           intsym = (struct i386_symbol *)obj_find_symbol(&ifile->root, name);

208

209           if (!intsym->gotent.offset_done)

210             {

211               intsym->gotent.offset_done = 1;

212               intsym->gotent.offset = offset;

213               offset += 4;

214             }

215         }

216      }

217

218    if (offset > 0 || gotneeded)

219      ifile->got = obj_create_alloced_section(&ifile->root, ".got", 4, offset);

220

221    return 1;

222          }

 

这个函数的作用是创建文件的.GOT段。这是怎么回事呢?.GOT的全称是global offset table。在这个段里保存的是绝对地址,这些地址不受重定位的影响。如果程序需要直接引用符号的绝对地址,这些符号就必须在.GOT段中出现(原文:that symbol will have a global offset table entry)。什么情况下程序需要引用符号的绝对地址呢?这跟重定位操作的类型有关。重定位操作为类型R_386_GOTOFFR_386_GOTPCR_386_GOT32的符号,会使用.GOT段。

函数里使用了i386_filei386_symbol结构,这2个结构定义在同一文件里。

 

34    struct i386_got_entry

35    {

36      int offset;

37      unsigned offset_done : 1;

38      unsigned reloc_done : 1;

39    };

40

41    struct i386_file

42    {

43      struct obj_file root;

44      struct obj_section *got;

45    };

46

47    struct i386_symbol

48    {

49      struct obj_symbol root;

50      struct i386_got_entry gotent;

51             };

 

这些结构都很简单,只是添加了些辅助控制位。

接下来,INSMOD_MAIN通过hide_special_symbols将符号“cleanup_module”,“init_module”,“kernel_version”的属性改为local,从而使其外部不可见。这个函数也在insmod.c里。

Insmod——hide_special_symbols函数

283  static void hide_special_symbols(struct obj_file *f)

284  {

285         struct obj_symbol *sym;

286         const char *const *p;

287         static const char *const specials[] =

288         {

289                "cleanup_module",

290                "init_module",

291                "kernel_version",

292                NULL

293         };

294

295         for (p = specials; *p; ++p)

296                if ((sym = obj_find_symbol(f, *p)) != NULL)

297                       sym->info = ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));

298          }

 

接下来,如果命令行参数来自文件,将文件名保存好,下面要从那里读出参数值。

 

1700    if (persist_parms && persist_name && *persist_name) {

1701              f->persist = persist_name;

1702              persist_name = NULL;

1703       }

1704

1705       if (persist_parms &&

1706           persist_name && !*persist_name) {

1707              /* -e "".  This is ugly.  Take the filename, compare it against

1708              * each of the module paths until we find a match on the start

1709              * of the filename, assume the rest is the relative path.  Have

1710              * to do it this way because modprobe uses absolute filenames

1711              * for module names in modules.dep and the format of modules.dep

1712              * does not allow for any backwards compatible changes, so there

1713              * is nowhere to store the relative filename.  The only way this

1714              * should fail to calculate a relative path is "insmod ./xxx", for

1715              * that case the user has to specify -e filename.

1716              */

1717              int j, l = strlen(filename);

1718              char *relative = NULL;

1719              char *p;

1720              for (i = 0; i < nmodpath; ++i) {

1721                     p = modpath[i].path;

1722                     j = strlen(p);

1723                     while (j && p[j] == '/')

1724                            --j;

1725                     if (j < l && strncmp(filename, p, j) == 0 && filename[j] == '/') {

抱歉!评论已关闭.