Subversion Repositories HelenOS

Rev

Rev 2933 | 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. void __main(void);
  38. void __io_init(void);
  39. void __exit(void);
  40.  
  41. void _rtld_main(void);
  42.  
  43. #define ELF32_R_SYM(i) ((i)>>8)
  44. #define ELF32_R_TYPE(i) ((unsigned char)(i))
  45.  
  46. typedef struct {
  47.     int d_tag;
  48.     union {
  49.         unsigned d_val;
  50.         unsigned *d_ptr;
  51.     } d_un;
  52. } elf32_dyn;
  53.  
  54. typedef struct {
  55.     unsigned r_offset;
  56.     unsigned r_info;
  57. } elf32_rel;
  58.  
  59. typedef struct {
  60.     unsigned st_name;
  61.     unsigned st_value;
  62.     unsigned st_size;
  63.     unsigned char st_info;
  64.     unsigned char st_other;
  65.     unsigned short st_shndx;
  66. } elf32_sym;
  67.  
  68. static void kputint(unsigned i)
  69. {
  70.     unsigned dummy;
  71.     asm volatile (
  72.         "movl $30, %%eax;"
  73.         "int $0x30"
  74.         : "=d" (dummy) /* output - %edx clobbered */
  75.         : "d" (i) /* input */
  76.         : "%eax","%ecx" /* all scratch registers clobbered */
  77.     ); 
  78. }
  79.  
  80. void __bootstrap(void)
  81. {
  82.     unsigned bias;
  83.     unsigned *got;
  84.     elf32_dyn *dynamic;
  85.     unsigned *dptr;
  86.     unsigned dval;
  87.     int i;
  88.  
  89.     unsigned rel_entries;
  90.     unsigned r_offset;
  91.     unsigned r_info;
  92.     unsigned rel_type;
  93.     unsigned sym_idx;
  94.     unsigned sym_addr;
  95.    
  96.     elf32_sym *sym_table;
  97.     elf32_rel *rel_table;
  98.     elf32_rel *jmp_rel_table;
  99.     elf32_rel *jmp_rel_entries;
  100.  
  101.     asm volatile (
  102.     "movl $30, %eax;"
  103.     "int $0x30"
  104.     );
  105.  
  106.     /* Copied from libc/arch/ia32/entry.s */
  107. /*asm volatile (
  108.     "mov %ss, %ax;"
  109.     "mov %ax, %ds;"
  110.     "mov %ax, %es;"
  111.     "mov %ax, %fs;"
  112. );*/
  113.  
  114.  
  115. asm volatile (
  116.     /* Calculate the bias into %0 */
  117.     /* Generates "fake" R_386_RELATIVE run-time relocation */
  118. "   call .L0;"
  119. ".L0:   pop %0;"
  120. "   subl $.L0, %0;"
  121.  
  122.     /* Calculate run-time address of _DYNAMIC into %1 */
  123.     /* Generates "fake" R_386_RELATIVE run-time relocation */
  124. "   movl $_DYNAMIC, %1;"    /* Again, at link time 0-based VMA gets in */
  125. "   addl %0, %1;"       /* Add bias to compute run-time address */
  126.  
  127. : "=r" (bias), "=r" (dynamic)
  128. );
  129.  
  130.     kputint(bias);
  131.     kputint((unsigned)dynamic);
  132.  
  133.     /* parse DYNAMIC */
  134.     got = 0;
  135.     sym_table = 0;
  136.     rel_table = 0;
  137.     rel_entries = 0;
  138.     jmp_rel_table = 0;
  139.     jmp_rel_entries = 0;
  140.  
  141.     i = 0;
  142.     while (dynamic[i].d_tag != 0) {
  143.         dptr = (unsigned *)(dynamic[i].d_un.d_val + bias);
  144.         dval = dynamic[i].d_un.d_val;
  145.  
  146.         switch (dynamic[i].d_tag) {
  147.         case 2/* DT_PLTRELSZ */: jmp_rel_entries = dval/8; break;
  148.         case 23/* DT_JMPREL */: jmp_rel_table = dptr; break;
  149.         case 3 /* DT_PLTGOT */:
  150.             /* GOT address */
  151.             got = dptr; break;
  152.         case 6 /* DT_SYMTAB */ : sym_table = dptr; break;
  153.         case 17 /* DT_REL */ : rel_table = dptr; break;
  154.         case 18 /* DT_RELSZ */ : rel_entries = dval / 8; break;
  155.         default: break;
  156.         }
  157.  
  158.         ++i;
  159.     }
  160.    
  161.     kputint(1);
  162.     kputint((unsigned)sym_table);
  163.     kputint((unsigned)rel_table);
  164.     kputint((unsigned)rel_entries);
  165.  
  166.     /* Now relocate all our dynsyms */
  167.     kputint(-1);
  168.    
  169.     for (i=0; i<rel_entries; i++) {
  170.         kputint(i);
  171.         r_offset = rel_table[i].r_offset;
  172.         r_info = rel_table[i].r_info;
  173.  
  174.         rel_type = ELF32_R_TYPE(r_info);
  175.  
  176.         kputint(rel_type);
  177.         kputint(r_offset);
  178.  
  179.         switch (rel_type) {
  180.         case 6: /* R_386_GLOB_DAT */
  181.         case 7: /* R_386_JUMP_SLOT */
  182.             kputint(16);
  183.             sym_idx = ELF32_R_SYM(r_info);
  184.  
  185.             sym_addr = sym_table[sym_idx].st_value + bias;
  186.             kputint(sym_idx);
  187.             kputint(sym_addr);
  188.  
  189.             *(unsigned *)(r_offset+bias) = sym_addr;
  190.             break;
  191.  
  192.         case 1: /* R_386_32 */
  193.             kputint(16);
  194.             sym_idx = ELF32_R_SYM(r_info);
  195.  
  196.             sym_addr = sym_table[sym_idx].st_value + bias;
  197.             kputint(sym_idx);
  198.             kputint(sym_addr);
  199.  
  200.             *(unsigned *)(r_offset+bias) += sym_addr;
  201.             break;
  202.            
  203.         case 8: /* R_386_RELATIVE */
  204.             kputint(16);
  205.             *(unsigned *)(r_offset+bias) += bias;
  206.             break;
  207.         }
  208.     }
  209.  
  210.     kputint(-1);
  211.    
  212.     for (i=0; i<jmp_rel_entries; i++) {
  213.         kputint(i);
  214.         r_offset = jmp_rel_table[i].r_offset;
  215.         r_info = jmp_rel_table[i].r_info;
  216.  
  217.         rel_type = ELF32_R_TYPE(r_info);
  218.  
  219.         kputint(rel_type);
  220.         kputint(r_offset);
  221.  
  222.         switch (rel_type) {
  223.         case 6: /* R_386_GLOB_DAT */
  224.         case 7: /* R_386_JUMP_SLOT */
  225.             kputint(16);
  226.             sym_idx = ELF32_R_SYM(r_info);
  227.  
  228.             sym_addr = sym_table[sym_idx].st_value + bias;
  229.             kputint(sym_idx);
  230.             kputint(sym_addr);
  231.  
  232.             *(unsigned *)(r_offset+bias) = sym_addr;
  233.             break;
  234.  
  235.         case 1: /* R_386_32 */
  236.             kputint(16);
  237.             sym_idx = ELF32_R_SYM(r_info);
  238.  
  239.             sym_addr = sym_table[sym_idx].st_value + bias;
  240.             kputint(sym_idx);
  241.             kputint(sym_addr);
  242.  
  243.             *(unsigned *)(r_offset+bias) += sym_addr;
  244.             break;
  245.            
  246.         case 8: /* R_386_RELATIVE */
  247.             kputint(16);
  248.             *(unsigned *)(r_offset+bias) += bias;
  249.             break;
  250.         }
  251.     }
  252.  
  253.     kputint(-1);
  254.    
  255.     /* Init libc and run rtld main */
  256.     __main();
  257.  
  258.     kputint(33);
  259.     __io_init();
  260.     kputint(34);
  261.     _rtld_main();
  262.     kputint(35);
  263.     __exit();
  264.  
  265.     kputint(36);
  266.  
  267.     asm (
  268.         "movl $250, %%eax;"
  269.         "int $0x30"
  270.         : /* output */
  271.         : /* input */
  272.         : "%eax","%ecx","%edx" /* all scratch registers clobbered */
  273.     );
  274. }
  275.  
  276. /** @}
  277.  */
  278.