home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 1999 May / pcp151c.iso / misc / src / install / modutils / obj / obj_i386.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-06  |  4.8 KB  |  219 lines

  1. /* i386 specific support for Elf loading and relocation.
  2.    Copyright 1996, 1997 Linux International.
  3.  
  4.    Contributed by Richard Henderson <rth@tamu.edu>
  5.  
  6.    This file is part of the Linux modutils.
  7.  
  8.    This program is free software; you can redistribute it and/or modify it
  9.    under the terms of the GNU General Public License as published by the
  10.    Free Software Foundation; either version 2 of the License, or (at your
  11.    option) any later version.
  12.  
  13.    This program is distributed in the hope that it will be useful, but
  14.    WITHOUT ANY WARRANTY; without even the implied warranty of
  15.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.    General Public License for more details.
  17.  
  18.    You should have received a copy of the GNU General Public License
  19.    along with this program; if not, write to the Free Software Foundation,
  20.    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
  21.  
  22. #ident "$Id: obj_i386.c,v 1.1.1.1 1998/01/06 20:51:08 ewt Exp $"
  23.  
  24. #include <string.h>
  25. #include <assert.h>
  26.  
  27. #include <module.h>
  28. #include <obj.h>
  29. #include <util.h>
  30.  
  31.  
  32. /*======================================================================*/
  33.  
  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. };
  52.  
  53.  
  54. /*======================================================================*/
  55.  
  56. struct obj_file *
  57. arch_new_file (void)
  58. {
  59.   struct i386_file *f;
  60.   f = xmalloc(sizeof(*f));
  61.   f->got = NULL;
  62.   return &f->root;
  63. }
  64.  
  65. struct obj_section *
  66. arch_new_section (void)
  67. {
  68.   return xmalloc(sizeof(struct obj_section));
  69. }
  70.  
  71. struct obj_symbol *
  72. arch_new_symbol (void)
  73. {
  74.   struct i386_symbol *sym;
  75.   sym = xmalloc(sizeof(*sym));
  76.   memset(&sym->gotent, 0, sizeof(sym->gotent));
  77.   return &sym->root;
  78. }
  79.  
  80. enum obj_reloc
  81. arch_apply_relocation (struct obj_file *f,
  82.                struct obj_section *targsec,
  83.                struct obj_section *symsec,
  84.                struct obj_symbol *sym,
  85.                Elf32_Rel *rel,
  86.                Elf32_Addr v)
  87. {
  88.   struct i386_file *ifile = (struct i386_file *)f;
  89.   struct i386_symbol *isym  = (struct i386_symbol *)sym;
  90.  
  91.   Elf32_Addr *loc = (Elf32_Addr *)(targsec->contents + rel->r_offset);
  92.   Elf32_Addr dot = targsec->header.sh_addr + rel->r_offset;
  93.   Elf32_Addr got = ifile->got ? ifile->got->header.sh_addr : 0;
  94.  
  95.   enum obj_reloc ret = obj_reloc_ok;
  96.  
  97.   switch (ELF32_R_TYPE(rel->r_info))
  98.     {
  99.     case R_386_NONE:
  100.       break;
  101.  
  102.     case R_386_32:
  103.       *loc += v;
  104.       break;
  105.  
  106.     case R_386_PLT32:
  107.     case R_386_PC32:
  108.       *loc += v - dot;
  109.       break;
  110.  
  111.     case R_386_GLOB_DAT:
  112.     case R_386_JMP_SLOT:
  113.       *loc = v;
  114.       break;
  115.  
  116.     case R_386_RELATIVE:
  117.       *loc += f->baseaddr;
  118.       break;
  119.  
  120.     case R_386_GOTPC:
  121.       assert(got != 0);
  122.       *loc += got - dot;
  123.       break;
  124.  
  125.     case R_386_GOT32:
  126.       assert(isym != NULL);
  127.       if (!isym->gotent.reloc_done)
  128.     {
  129.       isym->gotent.reloc_done = 1;
  130.       *(Elf32_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
  131.     }
  132.       *loc += isym->gotent.offset;
  133.       break;
  134.  
  135.     case R_386_GOTOFF:
  136.       assert(got != 0);
  137.       *loc += v - got;
  138.       break;
  139.  
  140.     default:
  141.       ret = obj_reloc_unhandled;
  142.       break;
  143.     }
  144.  
  145.   return ret;
  146. }
  147.  
  148. int
  149. arch_create_got (struct obj_file *f)
  150. {
  151.   struct i386_file *ifile = (struct i386_file *)f;
  152.   int i, n, offset = 0, gotneeded = 0;
  153.  
  154.   n = ifile->root.header.e_shnum;
  155.   for (i = 0; i < n; ++i)
  156.     {
  157.       struct obj_section *relsec, *symsec, *strsec;
  158.       Elf32_Rel *rel, *relend;
  159.       Elf32_Sym *symtab;
  160.       const char *strtab;
  161.  
  162.       relsec = ifile->root.sections[i];
  163.       if (relsec->header.sh_type != SHT_REL)
  164.     continue;
  165.  
  166.       symsec = ifile->root.sections[relsec->header.sh_link];
  167.       strsec = ifile->root.sections[symsec->header.sh_link];
  168.  
  169.       rel = (Elf32_Rel *)relsec->contents;
  170.       relend = rel + (relsec->header.sh_size / sizeof(Elf32_Rel));
  171.       symtab = (Elf32_Sym *)symsec->contents;
  172.       strtab = (const char *)strsec->contents;
  173.  
  174.       for (; rel < relend; ++rel)
  175.     {
  176.       Elf32_Sym *extsym;
  177.       struct i386_symbol *intsym;
  178.       const char *name;
  179.  
  180.       switch (ELF32_R_TYPE(rel->r_info))
  181.         {
  182.         case R_386_GOTPC:
  183.         case R_386_GOTOFF:
  184.           gotneeded = 1;
  185.         default:
  186.           continue;
  187.  
  188.         case R_386_GOT32:
  189.           break;
  190.         }
  191.  
  192.       extsym = &symtab[ELF32_R_SYM(rel->r_info)];
  193.       if (extsym->st_name)
  194.         name = strtab + extsym->st_name;
  195.       else
  196.         name = f->sections[extsym->st_shndx]->name;
  197.       intsym = (struct i386_symbol *)obj_find_symbol(&ifile->root, name);
  198.  
  199.       if (!intsym->gotent.offset_done)
  200.         {
  201.           intsym->gotent.offset_done = 1;
  202.           intsym->gotent.offset = offset;
  203.           offset += 4;
  204.         }
  205.     }
  206.     }
  207.  
  208.   if (offset > 0 || gotneeded)
  209.     ifile->got = obj_create_alloced_section(&ifile->root, ".got", 4, offset);
  210.  
  211.   return 1;
  212. }
  213.  
  214. int
  215. arch_init_module (struct obj_file *f, struct new_module *mod)
  216. {
  217.   return 1;
  218. }
  219.