home *** CD-ROM | disk | FTP | other *** search
/ Serving the Web / ServingTheWeb1995.disc1of1.iso / linux / slacksrce / d / libc / libc-4.6 / libc-4 / libc-linux / elf / d-link.old / i386 / elfinterp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-20  |  9.5 KB  |  320 lines

  1. /* Run an ELF binary on a linux system.
  2.  
  3.    Copyright (C) 1993, Eric Youngdale.
  4.  
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 2, or (at your option)
  8.    any later version.
  9.  
  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.
  14.  
  15.    You should have received a copy of the GNU General Public License
  16.    along with this program; if not, write to the Free Software
  17.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #ifndef VERBOSE_DLINKER
  20. #define VERBOSE_DLINKER
  21. #endif
  22. #ifdef VERBOSE_DLINKER
  23. static char * _dl_reltypes[] = {"R_386_NONE","R_386_32","R_386_PC32","R_386_GOT32",
  24.                "R_386_PLT32","R_386_COPY","R_386_GLOB_DAT",
  25.                "R_386_JMP_SLOT","R_386_RELATIVE","R_386_GOTOFF",
  26.                "R_386_GOTPC","R_386_NUM"};
  27. #endif
  28.  
  29. /* Program to load an ELF binary on a linux system, and run it.
  30. References to symbols in sharable libraries can be resolved by either
  31. an ELF sharable library or a linux style of shared library. */
  32.  
  33. /* Disclaimer:  I have never seen any AT&T source code for SVr4, nor have
  34.    I ever taken any courses on internals.  This program was developed using
  35.    information available through the book "UNIX SYSTEM V RELEASE 4,
  36.    Programmers guide: Ansi C and Programming Support Tools", which did
  37.    a more than adequate job of explaining everything required to get this
  38.    working. */
  39.  
  40. #include <errno.h>
  41. #include <unistd.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44. #ifdef IBCS_COMPATIBLE
  45. #include <ibcs/unistd.h>
  46. #else
  47. #include <linux/unistd.h>
  48. #endif
  49. #include <fcntl.h>
  50. #include "hash.h"
  51. #include "linuxelf.h"
  52. #include "syscall.h"
  53. #include "string.h"
  54.  
  55. #define SVR4_COMPATIBILITY
  56.  
  57. extern _dl_linux_resolve(void);
  58.  
  59. unsigned int _dl_linux_resolver(int dummy, int i)
  60. {
  61.   unsigned int * sp;
  62.   int reloc_entry;
  63.   int reloc_type;
  64.   struct Elf32_Rel * this_reloc;
  65.   char * strtab;
  66.   struct Elf32_Sym * symtab; 
  67.   struct Elf32_Rel * rel_addr;
  68.   struct elf_resolve * tpnt;
  69.   int symtab_index;
  70.   char * new_addr;
  71.   char ** got_addr;
  72.   unsigned int instr_addr;
  73.   sp = &i;  
  74.   reloc_entry = sp[1];
  75.   tpnt = (struct elf_resolve *) sp[0];
  76.  
  77.   rel_addr = (struct Elf32_Rel *) (tpnt->dynamic_info[DT_JMPREL] + 
  78.                    tpnt->loadaddr);
  79.  
  80.   this_reloc = rel_addr + (reloc_entry >> 3);
  81.   reloc_type = ELF32_R_TYPE(this_reloc->info);
  82.   symtab_index = ELF32_R_SYM(this_reloc->info);
  83.  
  84.   symtab =  (struct Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
  85.   strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  86.  
  87.  
  88.   if (reloc_type != R_386_JMP_SLOT) {
  89.     SEND_STDERR("Incorrect relocation type in jump relocations.\n");
  90.     _dl_exit(1);
  91.   };
  92.  
  93.   /* Address of jump instruction to fix up */
  94.   instr_addr  = ((int)this_reloc->offset  + (int)tpnt->loadaddr);
  95.   got_addr = (char **) instr_addr;
  96.  
  97. #ifdef DEBUG
  98.   SEND_STDERR("Resolving symbol ");
  99.   SEND_STDERR(strtab + symtab[symtab_index].st_name);
  100.   SEND_STDERR("\n");
  101. #endif
  102.  
  103.   /* Get the address of the GOT entry */
  104.   new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name, 
  105.               tpnt->symbol_scope, (int) got_addr, tpnt);
  106.   if(!new_addr) {
  107.     SEND_STDERR("Unable to resolve symbol ");
  108.     SEND_STDERR(strtab + symtab[symtab_index].st_name);
  109.     SEND_STDERR("\n");
  110.     _dl_exit(1);
  111.   };
  112. /* #define DEBUG_LIBRARY */
  113. #ifdef DEBUG_LIBRARY
  114.   if((unsigned int) got_addr < 0x40000000) {
  115.     SEND_STDERR("Calling library function: ");
  116.     SEND_STDERR(strtab + symtab[symtab_index].st_name);
  117.     SEND_STDERR("\n");
  118.   } else {
  119.     *got_addr = new_addr;
  120.   }
  121. #else
  122.   *got_addr = new_addr;
  123. #endif
  124.   return (unsigned int) new_addr;
  125. }
  126.  
  127. void _dl_parse_lazy_relocation_information(struct elf_resolve * tpnt, int rel_addr,
  128.        int rel_size, int type){
  129.   int i;
  130.   char * strtab;
  131.   int reloc_type;
  132.   int symtab_index;
  133.   struct Elf32_Sym * symtab; 
  134.   struct Elf32_Rel * rpnt;
  135.   unsigned int * reloc_addr;
  136.  
  137.   /* Now parse the relocation information */
  138.   rpnt = (struct Elf32_Rel *) (rel_addr + tpnt->loadaddr);
  139.   rel_size = rel_size / sizeof(struct Elf32_Rel);
  140.  
  141.   symtab =  (struct Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
  142.   strtab = ( char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  143.  
  144.   for(i=0; i< rel_size; i++, rpnt++){
  145.     reloc_addr = (int *) (tpnt->loadaddr + (int)rpnt->offset);
  146.     reloc_type = ELF32_R_TYPE(rpnt->info);
  147.     symtab_index = ELF32_R_SYM(rpnt->info);
  148.  
  149.     /* When the dynamic linker bootstrapped itself, it resolved some symbols.
  150.        Make sure we do not do them again */
  151.     if(!symtab_index && tpnt->libtype == program_interpreter) continue;
  152.     if(symtab_index && tpnt->libtype == program_interpreter &&
  153.        _dl_symbol(strtab + symtab[symtab_index].st_name))
  154.       continue;
  155.  
  156.     switch(reloc_type){
  157.     case R_386_NONE: break;
  158.     case R_386_JMP_SLOT:
  159.       *reloc_addr += (unsigned int) tpnt->loadaddr;
  160.       break;
  161.     default:
  162.       SEND_STDERR("(LAZY) Unable to handle reloc type ");
  163. #ifdef VERBOSE_DLINKER
  164.       SEND_STDERR(_dl_reltypes[reloc_type]);
  165. #endif
  166.       if(symtab_index) SEND_STDERR(strtab + symtab[symtab_index].st_name);
  167.       SEND_STDERR("\n");
  168.       _dl_exit(1);
  169.     };
  170.   };
  171. }
  172.  
  173. int _dl_parse_relocation_information(struct elf_resolve * tpnt, int rel_addr,
  174.        int rel_size, int type){
  175.   int i;
  176.   char * strtab;
  177.   int reloc_type;
  178.   int goof = 0;
  179.   struct Elf32_Sym * symtab; 
  180.   struct Elf32_Rel * rpnt;
  181.   unsigned int * reloc_addr;
  182.   unsigned int symbol_addr;
  183.   int symtab_index;
  184.   /* Now parse the relocation information */
  185.  
  186.   rpnt = (struct Elf32_Rel *) (rel_addr + tpnt->loadaddr);
  187.   rel_size = rel_size / sizeof(struct Elf32_Rel);
  188.  
  189.   symtab =  (struct Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
  190.   strtab = ( char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  191.  
  192.   for(i=0; i< rel_size; i++, rpnt++){
  193.     reloc_addr = (int *) (tpnt->loadaddr + (int)rpnt->offset);
  194.     reloc_type = ELF32_R_TYPE(rpnt->info);
  195.     symtab_index = ELF32_R_SYM(rpnt->info);
  196.     symbol_addr = 0;
  197.  
  198.     if(!symtab_index && tpnt->libtype == program_interpreter) continue;
  199.  
  200.     if(symtab_index) {
  201.  
  202.       if(tpnt->libtype == program_interpreter && 
  203.      _dl_symbol(strtab + symtab[symtab_index].st_name))
  204.     continue;
  205.  
  206.       symbol_addr = (unsigned int) 
  207.     _dl_find_hash(strtab + symtab[symtab_index].st_name,
  208.                   tpnt->symbol_scope, (int) reloc_addr, 
  209.               (reloc_type == R_386_JMP_SLOT ? tpnt : NULL));
  210.  
  211.       if(!symbol_addr) {
  212.     SEND_STDERR("Unable to resolve symbol ");
  213.     SEND_STDERR(strtab + symtab[symtab_index].st_name);
  214.     SEND_STDERR("\n");
  215.     goof++;
  216.       };
  217.     };
  218.     switch(reloc_type){
  219.     case R_386_32:
  220.       *reloc_addr += symbol_addr;
  221.       break;
  222.     case R_386_PC32:
  223.       *reloc_addr += symbol_addr - (unsigned int) reloc_addr;
  224.       break;
  225.     case R_386_GLOB_DAT:
  226.     case R_386_JMP_SLOT:
  227.       *reloc_addr = symbol_addr;
  228.       break;
  229.     case R_386_RELATIVE:
  230.       *reloc_addr += (unsigned int) tpnt->loadaddr;
  231.       break;
  232.     case R_386_COPY:
  233. #if 0  /* Do this later */
  234.       SEND_STDERR("Doing copy for symbol ");
  235.       if(symtab_index) SEND_STDERR(strtab + symtab[symtab_index].st_name);
  236.       SEND_STDERR("\n");
  237.       _dl_memcpy((void *) symtab[symtab_index].st_value,
  238.          (void *) symbol_addr, 
  239.          symtab[symtab_index].st_size);
  240. #endif
  241.       break;
  242.     default:
  243.       SEND_STDERR("Unable to handle reloc type ");
  244. #ifdef VERBOSE_DLINKER
  245.       SEND_STDERR(_dl_reltypes[reloc_type]);
  246. #endif
  247.       if(symtab_index) SEND_STDERR(strtab + symtab[symtab_index].st_name);
  248.       SEND_STDERR("\n");
  249.       _dl_exit(1);
  250.     };
  251.  
  252.   };
  253.   return goof;
  254. }
  255.  
  256.  
  257. /* This is done as a separate step, because there are cases where
  258.    information is first copied and later initialized.  This results in
  259.    the wrong information being copied.  Someone at Sun was complaining about
  260.    a bug in the handling of _COPY by SVr4, and this may in fact be what he
  261.    was talking about.  Sigh. */
  262.  
  263. /* No, there are cases where the SVr4 linker fails to emit COPY relocs
  264.    at all */
  265.  
  266. #ifndef BROKEN_LINKER
  267. int _dl_parse_copy_information(struct dyn_elf * xpnt, int rel_addr,
  268.        int rel_size, int type){
  269.   int i;
  270.   char * strtab;
  271.   int reloc_type;
  272.   int goof = 0;
  273.   struct Elf32_Sym * symtab; 
  274.   struct Elf32_Rel * rpnt;
  275.   unsigned int * reloc_addr;
  276.   unsigned int symbol_addr;
  277.   struct elf_resolve *tpnt;
  278.   int symtab_index;
  279.   /* Now parse the relocation information */
  280.  
  281.   tpnt = xpnt->dyn;
  282.   
  283.   rpnt = (struct Elf32_Rel *) (rel_addr + tpnt->loadaddr);
  284.   rel_size = rel_size / sizeof(struct Elf32_Rel);
  285.  
  286.   symtab =  (struct Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
  287.   strtab = ( char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  288.  
  289.   for(i=0; i< rel_size; i++, rpnt++){
  290.     reloc_addr = (int *) (tpnt->loadaddr + (int)rpnt->offset);
  291.     reloc_type = ELF32_R_TYPE(rpnt->info);
  292.     if(reloc_type != R_386_COPY) continue;
  293.     symtab_index = ELF32_R_SYM(rpnt->info);
  294.     symbol_addr = 0;
  295.     if(!symtab_index && tpnt->libtype == program_interpreter) continue;
  296.     if(symtab_index) {
  297.  
  298.       if(tpnt->libtype == program_interpreter && 
  299.      _dl_symbol(strtab + symtab[symtab_index].st_name))
  300.     continue;
  301.  
  302.       symbol_addr = (unsigned int) 
  303.     _dl_find_hash(strtab + symtab[symtab_index].st_name,
  304.                   xpnt->next, (int) reloc_addr, NULL);
  305.       if(!symbol_addr) {
  306.     SEND_STDERR("Unable to resolve symbol ");
  307.     SEND_STDERR(strtab + symtab[symtab_index].st_name);
  308.     SEND_STDERR("\n");
  309.     goof++;
  310.       };
  311.     };
  312.       _dl_memcpy(symtab[symtab_index].st_value, symbol_addr, 
  313.          symtab[symtab_index].st_size);
  314.   };
  315.   return goof;
  316. }
  317. #endif
  318.  
  319.  
  320.