Subversion Repositories HelenOS

Rev

Rev 2952 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2008 Jiri Svoboda
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup rtld rtld
  30.  * @brief
  31.  * @{
  32.  */
  33. /**
  34.  * @file
  35.  */
  36.  
  37. #include <elf_dyn.h>
  38. #include <rtld.h>
  39.  
  40. void __main(void);
  41. void __io_init(void);
  42. void __exit(void);
  43.  
  44. static void kputint(unsigned i)
  45. {
  46.     unsigned dummy;
  47.     asm volatile (
  48.         "movl $30, %%eax;"
  49.         "int $0x30"
  50.         : "=d" (dummy) /* output - %edx clobbered */
  51.         : "d" (i) /* input */
  52.         : "%eax","%ecx" /* all scratch registers clobbered */
  53.     ); 
  54. }
  55.  
  56. void __bootstrap(void)
  57. {
  58.     unsigned bias;
  59.     unsigned *got;
  60.     elf_dyn_t *dynamic;
  61.     void *dptr;
  62.     unsigned dval;
  63.     int i;
  64.  
  65.     size_t rel_entries;
  66.     size_t r_offset;
  67.     elf_word r_info;
  68.     unsigned rel_type;
  69.     elf_word sym_idx;
  70.     uintptr_t sym_addr;
  71.    
  72.     elf_symbol_t *sym_table;
  73.     elf_rel_t *rel_table;
  74.     elf_rel_t *jmp_rel_table;
  75.     size_t jmp_rel_entries;
  76.  
  77. asm volatile (
  78.     /* Calculate the bias into %0 */
  79.     /* Generates "fake" R_386_RELATIVE run-time relocation */
  80. "   call .L0;"
  81. ".L0:   pop %0;"
  82. "   subl $.L0, %0;"
  83.  
  84.     /* Calculate run-time address of _DYNAMIC into %1 */
  85.     /* Generates "fake" R_386_RELATIVE run-time relocation */
  86. "   movl $_DYNAMIC, %1;"    /* Again, at link time 0-based VMA gets in */
  87. "   addl %0, %1;"       /* Add bias to compute run-time address */
  88.  
  89. : "=r" (bias), "=r" (dynamic)
  90. );
  91.  
  92.     kputint(bias);
  93.     kputint((unsigned)dynamic);
  94.  
  95.     /* parse DYNAMIC */
  96.     got = 0;
  97.     sym_table = 0;
  98.     rel_table = 0;
  99.     rel_entries = 0;
  100.     jmp_rel_table = 0;
  101.     jmp_rel_entries = 0;
  102.  
  103.     i = 0;
  104.     while (dynamic[i].d_tag != 0) {
  105.         dptr = (void *)(dynamic[i].d_un.d_val + bias);
  106.         dval = dynamic[i].d_un.d_val;
  107.  
  108.         switch (dynamic[i].d_tag) {
  109.         case 2/* DT_PLTRELSZ */: jmp_rel_entries = dval/8; break;
  110.         case 23/* DT_JMPREL */: jmp_rel_table = dptr; break;
  111.         case 3 /* DT_PLTGOT */:
  112.             /* GOT address */
  113.             got = dptr; break;
  114.         case 6 /* DT_SYMTAB */ : sym_table = dptr; break;
  115.         case 17 /* DT_REL */ : rel_table = dptr; break;
  116.         case 18 /* DT_RELSZ */ : rel_entries = dval / 8; break;
  117.         default: break;
  118.         }
  119.  
  120.         ++i;
  121.     }
  122.    
  123.     kputint(1);
  124.     kputint((unsigned)sym_table);
  125.     kputint((unsigned)rel_table);
  126.     kputint((unsigned)rel_entries);
  127.  
  128.     /* Now relocate all our dynsyms */
  129.     kputint(-1);
  130.    
  131.     for (i=0; i<rel_entries; i++) {
  132.         kputint(i);
  133.         r_offset = rel_table[i].r_offset;
  134.         r_info = rel_table[i].r_info;
  135.  
  136.         rel_type = ELF32_R_TYPE(r_info);
  137.  
  138.         kputint(rel_type);
  139.         kputint(r_offset);
  140.  
  141.         switch (rel_type) {
  142.         case 6: /* R_386_GLOB_DAT */
  143.         case 7: /* R_386_JUMP_SLOT */
  144.             kputint(16);
  145.             sym_idx = ELF32_R_SYM(r_info);
  146.  
  147.             sym_addr = sym_table[sym_idx].st_value + bias;
  148.             kputint(sym_idx);
  149.             kputint(sym_addr);
  150.  
  151.             *(unsigned *)(r_offset+bias) = sym_addr;
  152.             break;
  153.  
  154.         case 1: /* R_386_32 */
  155.             kputint(16);
  156.             sym_idx = ELF32_R_SYM(r_info);
  157.  
  158.             sym_addr = sym_table[sym_idx].st_value + bias;
  159.             kputint(sym_idx);
  160.             kputint(sym_addr);
  161.  
  162.             *(unsigned *)(r_offset+bias) += sym_addr;
  163.             break;
  164.            
  165.         case 8: /* R_386_RELATIVE */
  166.             kputint(16);
  167.             *(unsigned *)(r_offset+bias) += bias;
  168.             break;
  169.         }
  170.     }
  171.  
  172.     kputint(-1);
  173.    
  174.     for (i=0; i<jmp_rel_entries; i++) {
  175.         kputint(i);
  176.         r_offset = jmp_rel_table[i].r_offset;
  177.         r_info = jmp_rel_table[i].r_info;
  178.  
  179.         rel_type = ELF32_R_TYPE(r_info);
  180.  
  181.         kputint(rel_type);
  182.         kputint(r_offset);
  183.  
  184.         switch (rel_type) {
  185.         case 6: /* R_386_GLOB_DAT */
  186.         case 7: /* R_386_JUMP_SLOT */
  187.             kputint(16);
  188.             sym_idx = ELF32_R_SYM(r_info);
  189.  
  190.             sym_addr = sym_table[sym_idx].st_value + bias;
  191.             kputint(sym_idx);
  192.             kputint(sym_addr);
  193.  
  194.             *(unsigned *)(r_offset+bias) = sym_addr;
  195.             break;
  196.  
  197.         case 1: /* R_386_32 */
  198.             kputint(16);
  199.             sym_idx = ELF32_R_SYM(r_info);
  200.  
  201.             sym_addr = sym_table[sym_idx].st_value + bias;
  202.             kputint(sym_idx);
  203.             kputint(sym_addr);
  204.  
  205.             *(unsigned *)(r_offset+bias) += sym_addr;
  206.             break;
  207.            
  208.         case 8: /* R_386_RELATIVE */
  209.             kputint(16);
  210.             *(unsigned *)(r_offset+bias) += bias;
  211.             break;
  212.         }
  213.     }
  214.  
  215.     kputint(-1);
  216.    
  217.     /* Init libc and run rtld main */
  218.     __main();
  219.  
  220.     kputint(33);
  221.     __io_init();
  222.     kputint(34);
  223.     _rtld_main();
  224.     kputint(35);
  225.     __exit();
  226.  
  227.     kputint(36);
  228.  
  229.     asm (
  230.         "movl $250, %%eax;"
  231.         "int $0x30"
  232.         : /* output */
  233.         : /* input */
  234.         : "%eax","%ecx","%edx" /* all scratch registers clobbered */
  235.     );
  236. }
  237.  
  238. /** @}
  239.  */
  240.