Subversion Repositories HelenOS

Rev

Rev 3401 | 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. #include <loader/pcb.h>
  40.  
  41. // for testing printf
  42. #include <stdio.h>
  43.  
  44. void __main(pcb_t *pcb);
  45. //void __io_init(void);
  46. void __exit(void);
  47.  
  48. static void kputint(unsigned i)
  49. {
  50. /*  asm volatile (
  51.         "mr %%r3, %0\n"
  52.         "li %%r9, 31\n"
  53.         "sc\n"
  54.         :
  55.         : "r" (i)
  56.         : "%r3","%r9"
  57.     ) ;*/
  58. }
  59.  
  60. #define __L(ptr) ((uint32_t)(ptr) & 0x0000ffff)
  61. #define __HA(ptr) ((uint32_t)(ptr) >> 16)
  62.  
  63. // ldis r11, .PLTtable@ha
  64. static inline uint32_t _ldis(unsigned rD, uint16_t imm16)
  65. {
  66.     /* Special case of addis: ldis rD,SIMM == addis rD,0,SIMM */
  67.     return 0x3C000000 | (rD << 21) | imm16;
  68. }
  69.  
  70. static inline uint32_t _lwz(unsigned rD, uint16_t disp16, unsigned rA)
  71. {
  72.     return 0x80000000 | (rD << 21) | (rA << 16) | disp16;
  73. }
  74.  
  75. static inline uint32_t _mtctr(unsigned rS)
  76. {
  77.     /* mtctr rD == mtspr 9, rD */
  78.     return 0x7c0003a6 | (rS << 21) | (9/*CTR*/ << 16);
  79. }
  80.  
  81. static inline uint32_t _bctr()
  82. {
  83.     /* bcctr 0x1f, 0 */
  84.     return 0x4c000420 | (0x1f/*always*/ << 21);
  85. }
  86.  
  87. /* branch */
  88. static inline uint32_t _b(uint32_t *addr, uint32_t *location)
  89. {
  90.     uint32_t raddr = ((uint32_t)addr - (uint32_t)location) & 0x03fffffc;
  91.     return 0x48000000 | raddr;
  92. }
  93.  
  94. void test_func(void)
  95. {
  96.     kputint(-1);
  97.     kputint(42);
  98.     kputint(-1);
  99. }
  100.  
  101. int test_var = 0x818283;
  102.  
  103. void __bootstrap(pcb_t *pcb);
  104.  
  105. void __bootstrap(pcb_t *pcb)
  106. {
  107.     unsigned bias;
  108.     uint32_t *plt;
  109.     elf_dyn_t *dynamic;
  110.     void *dptr;
  111.     unsigned dval;
  112.     int i;
  113.  
  114.     size_t rel_entries;
  115.     size_t r_offset;
  116.     elf_word r_info;
  117.     unsigned rel_type;
  118.     elf_word sym_idx;
  119.     uintptr_t sym_addr;
  120.    
  121.     elf_symbol_t *sym_table;
  122.     elf_rela_t *rel_table;
  123.     elf_rela_t *jmp_rel_table;
  124.     size_t jmp_rel_entries;
  125.     uint32_t a, res;
  126.     uint32_t *r_ptr;
  127.     uint32_t *_plt_ent;
  128.  
  129.     kputint(42);
  130.  
  131.     /* The program loader (iloader) kindly provided us with these */
  132.     dynamic = pcb->rtld_dynamic;
  133.     bias = pcb->rtld_bias;
  134.  
  135.     kputint(bias);
  136.     kputint((unsigned)dynamic);
  137.  
  138.     /* parse DYNAMIC */
  139.     plt = 0;
  140.     sym_table = 0;
  141.     rel_table = 0;
  142.     rel_entries = 0;
  143.     jmp_rel_table = 0;
  144.     jmp_rel_entries = 0;
  145. /*
  146.     i = 0;
  147.     while (dynamic[i].d_tag != 0) {
  148. //      kputint((uintptr_t)&dynamic[i]);
  149. //      kputint((uintptr_t)&(dynamic[i].d_tag));
  150. //      kputint(dynamic[i].d_tag);
  151.  
  152.         dptr = (void *)(dynamic[i].d_un.d_val + bias);
  153.         dval = dynamic[i].d_un.d_val;
  154.  
  155. //      kputint(0x10);
  156.         register unsigned tag = dynamic[i].d_tag;
  157. */
  158.         /*
  159.          * Note that switches only work because we are using
  160.          * -fno-jump-tables.
  161.          */
  162. /*      switch (tag) {
  163.         case DT_PLTRELSZ: jmp_rel_entries = dval/sizeof(elf_rela_t); break;
  164.         case DT_JMPREL: jmp_rel_table = dptr; break;
  165.         case DT_PLTGOT:*/
  166.             /* PLT address */
  167. /*          plt = dptr; break;
  168.         case DT_SYMTAB: sym_table = dptr; break;
  169.         case DT_RELA: rel_table = dptr; break;
  170.         case DT_RELASZ: rel_entries = dval / sizeof(elf_rela_t); break;
  171.         default: break;
  172.         }
  173. */
  174. //      kputint(0x20);
  175. /*
  176.         ++i;
  177.     }
  178.    
  179.     kputint(1);
  180.     kputint((unsigned)sym_table);
  181.     kputint((unsigned)rel_table);
  182.     kputint((unsigned)rel_entries);
  183.  
  184. */  /* Now relocate all our dynsyms */
  185.     kputint(-1);
  186.  
  187.     // PLT entries start here. However, each occupies 2 words
  188. //  _plt_ent = plt + 18;
  189.  
  190.     // By definition of the ppc ABI, there's 1:1 correspondence
  191.     // between JMPREL entries and PLT entries
  192. //  unsigned plt_n = jmp_rel_entries;
  193. /*
  194.     uint32_t *_plt_table;
  195.     uint32_t *_plt_call;
  196.     uint32_t *_plt_resolve;
  197.  
  198.     _plt_resolve = plt;
  199.     _plt_call = plt + 6;
  200.     _plt_table = plt + 18 + plt_n;
  201.    
  202.     for (i=0; i<rel_entries; i++) {
  203. //      kputint(i);
  204.         r_offset = rel_table[i].r_offset;
  205.         r_info = rel_table[i].r_info;
  206.         r_ptr = (uint32_t *)(r_offset + bias);
  207.         a = rel_table[i].r_addend;
  208. //      kputint(-2);
  209. //      kputint(a);
  210. //      kputint(ELF32_R_TYPE(r_info));
  211. //      kputint(ELF32_R_SYM(r_info));
  212.        
  213.         rel_type = ELF32_R_TYPE(r_info);
  214.  
  215. //      kputint(rel_type);
  216. //      kputint(r_offset);
  217.  
  218.         switch (rel_type) {
  219.         case R_PPC_JMP_SLOT:
  220. //          kputint(0xa);
  221.             sym_idx = ELF32_R_SYM(r_info);
  222.  
  223.             sym_addr = sym_table[sym_idx].st_value + bias;
  224. //          kputint(sym_idx);
  225. //          kputint(sym_addr);
  226.  
  227.             // r_ptr should point to a plt entry...
  228.             uint32_t pidx = (r_ptr - _plt_ent) / 2;
  229.             if (pidx >= plt_n) {
  230.                 kputint(0xee00ee00);
  231.                 while(1);
  232.             }
  233. //          _plt_table[pidx] = sym_addr;
  234. //          kputint(pidx);
  235.             plt[18+2*pidx] = _b((void *)sym_addr, &plt[18+2*pidx]);
  236. //          kputint(&plt[18]);
  237. //          kputint(plt[18]);
  238. //          while(1);
  239. //          while(1);
  240.             // *r_ptr = sym_addr;
  241.  
  242.             break;
  243.  
  244.         case R_PPC_ADDR32:
  245.             kputint(0xb);
  246.             sym_idx = ELF32_R_SYM(r_info);
  247.  
  248.             sym_addr = sym_table[sym_idx].st_value + bias;
  249.             kputint(sym_idx);
  250.             kputint(sym_addr);
  251.  
  252.             *r_ptr = a + sym_addr;
  253.             break;
  254.            
  255.         case R_PPC_RELATIVE:
  256.             kputint(0xc);
  257.             *r_ptr = a + bias;
  258.             break;
  259.  
  260.         case R_PPC_REL24:
  261.             kputint(0xd);
  262.             sym_idx = ELF32_R_SYM(r_info);
  263.             sym_addr = sym_table[sym_idx].st_value + bias;
  264.             kputint(sym_addr);
  265.             res = (sym_addr - (uint32_t)r_ptr + a) >> 2;
  266.             kputint(res);
  267.             if (res & 0xff000000) {*/
  268.                 /* out of range?? */
  269. /*              kputint(0xeeeeeeee);
  270.                 //while(1);
  271.             }
  272.             *r_ptr = (*r_ptr & ~0x00ffffff) | (res & 0x00ffffff);
  273.             kputint(0x1d);
  274.             break;
  275.         }
  276.     }
  277. */
  278.     kputint(-3);
  279. //  if (plt != 0) {
  280.  
  281. /* .PLTcall: */
  282. //  plt[6] = _ldis(11, __HA(_plt_table));   // ldis r11, .PLTtable@ha
  283. //  plt[7] = _lwz(11, __L(_plt_table), 11); // lwz r11, .PLTtable@l(r11)
  284. //  plt[8] = _mtctr(11);            // mtctr r11
  285. //  plt[9] = _bctr();
  286.  
  287. /* .PLTi, i = 0..N-1 */
  288. /*  kputint(-4);
  289.     for (i = 0; i < plt_n; ++i) {
  290.         //_plt_table[i] == function address;
  291.         plt[18+i] = _b(_plt_call, &plt[18+i]);  // b .PLTcall
  292.     }
  293. */
  294. //  kputint(-5);
  295. //  kputint(_plt_table[0]);
  296. //  }
  297.  
  298. //  kputint(-6);
  299.     /* This will come in handy */
  300. //  runtime_env.rtld_dynamic = dynamic;
  301. //  runtime_env.rtld.bias = bias;
  302.  
  303. //  volatile int ff=1;
  304. //  while(ff);
  305.     kputint(-7);
  306.     test_func();
  307.     kputint(0x42);
  308.     kputint(test_var);
  309. //  while(1);
  310. //  while(1);
  311.     /* Init libc and run rtld main */
  312.     kputint(0x22);
  313.     __main(pcb);
  314.  
  315. //  kputint(33);
  316. //  __io_init();
  317.     kputint(-1);
  318.     kputint(0x52);
  319. //  printf("Hello, world! (from ppc rtld)\n");
  320.     kputint(0x62);
  321. //  while(1);
  322.     kputint(34);
  323.     _rtld_main();
  324.     kputint(35);
  325.     __exit();
  326.  
  327.     kputint(36);
  328. }
  329.  
  330. /** @}
  331.  */
  332.