Subversion Repositories HelenOS

Rev

Rev 2998 | 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 <pcb.h>
  40.  
  41. // for testing printf
  42. #include <stdio.h>
  43.  
  44. void __main(void);
  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(void);
  104.  
  105. void __bootstrap(void)
  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.     pcb_t *pcb;
  126.     uint32_t a, res;
  127.     uint32_t *r_ptr;
  128.     uint32_t *_plt_ent;
  129.  
  130.     kputint(42);
  131.     pcb = __pcb_get();
  132.  
  133.     /* The program loader (iloader) kindly provided us with these */
  134.     dynamic = pcb->rtld_dynamic;
  135.     bias = pcb->rtld_bias;
  136.  
  137.     kputint(bias);
  138.     kputint((unsigned)dynamic);
  139.  
  140.     /* parse DYNAMIC */
  141.     plt = 0;
  142.     sym_table = 0;
  143.     rel_table = 0;
  144.     rel_entries = 0;
  145.     jmp_rel_table = 0;
  146.     jmp_rel_entries = 0;
  147.  
  148.     i = 0;
  149.     while (dynamic[i].d_tag != 0) {
  150. //      kputint((uintptr_t)&dynamic[i]);
  151. //      kputint((uintptr_t)&(dynamic[i].d_tag));
  152. //      kputint(dynamic[i].d_tag);
  153.  
  154.         dptr = (void *)(dynamic[i].d_un.d_val + bias);
  155.         dval = dynamic[i].d_un.d_val;
  156.  
  157. //      kputint(0x10);
  158.         register unsigned tag = dynamic[i].d_tag;
  159.  
  160.         /*
  161.          * Note that switches only work because we are using
  162.          * -fno-jump-tables.
  163.          */
  164.         switch (tag) {
  165.         case DT_PLTRELSZ: jmp_rel_entries = dval/sizeof(elf_rela_t); break;
  166.         case DT_JMPREL: jmp_rel_table = dptr; break;
  167.         case DT_PLTGOT:
  168.             /* PLT address */
  169.             plt = dptr; break;
  170.         case DT_SYMTAB: sym_table = dptr; break;
  171.         case DT_RELA: rel_table = dptr; break;
  172.         case DT_RELASZ: rel_entries = dval / sizeof(elf_rela_t); break;
  173.         default: break;
  174.         }
  175.  
  176. //      kputint(0x20);
  177.  
  178.         ++i;
  179.     }
  180.    
  181.     kputint(1);
  182.     kputint((unsigned)sym_table);
  183.     kputint((unsigned)rel_table);
  184.     kputint((unsigned)rel_entries);
  185.  
  186.     /* Now relocate all our dynsyms */
  187.     kputint(-1);
  188.  
  189.     // PLT entries start here. However, each occupies 2 words
  190.     _plt_ent = plt + 18;
  191.  
  192.     // By definition of the ppc ABI, there's 1:1 correspondence
  193.     // between JMPREL entries and PLT entries
  194.     unsigned plt_n = jmp_rel_entries;
  195.  
  196.     uint32_t *_plt_table;
  197.     uint32_t *_plt_call;
  198.     uint32_t *_plt_resolve;
  199.  
  200.     _plt_resolve = plt;
  201.     _plt_call = plt + 6;
  202.     _plt_table = plt + 18 + plt_n;
  203.    
  204.     for (i=0; i<rel_entries; i++) {
  205. //      kputint(i);
  206.         r_offset = rel_table[i].r_offset;
  207.         r_info = rel_table[i].r_info;
  208.         r_ptr = (uint32_t *)(r_offset + bias);
  209.         a = rel_table[i].r_addend;
  210. //      kputint(-2);
  211. //      kputint(a);
  212. //      kputint(ELF32_R_TYPE(r_info));
  213. //      kputint(ELF32_R_SYM(r_info));
  214.        
  215.         rel_type = ELF32_R_TYPE(r_info);
  216.  
  217. //      kputint(rel_type);
  218. //      kputint(r_offset);
  219.  
  220.         switch (rel_type) {
  221.         case R_PPC_JMP_SLOT:
  222. //          kputint(0xa);
  223.             sym_idx = ELF32_R_SYM(r_info);
  224.  
  225.             sym_addr = sym_table[sym_idx].st_value + bias;
  226. //          kputint(sym_idx);
  227. //          kputint(sym_addr);
  228.  
  229.             // r_ptr should point to a plt entry...
  230.             uint32_t pidx = (r_ptr - _plt_ent) / 2;
  231.             if (pidx >= plt_n) {
  232.                 kputint(0xee00ee00);
  233.                 while(1);
  234.             }
  235. //          _plt_table[pidx] = sym_addr;
  236. //          kputint(pidx);
  237.             plt[18+2*pidx] = _b((void *)sym_addr, &plt[18+2*pidx]);
  238. //          kputint(&plt[18]);
  239. //          kputint(plt[18]);
  240. //          while(1);
  241. //          while(1);
  242.             //*r_ptr = sym_addr;
  243.  
  244.             break;
  245.  
  246.         case R_PPC_ADDR32:
  247.             kputint(0xb);
  248.             sym_idx = ELF32_R_SYM(r_info);
  249.  
  250.             sym_addr = sym_table[sym_idx].st_value + bias;
  251.             kputint(sym_idx);
  252.             kputint(sym_addr);
  253.  
  254.             *r_ptr = a + sym_addr;
  255.             break;
  256.            
  257.         case R_PPC_RELATIVE:
  258.             kputint(0xc);
  259.             *r_ptr = a + bias;
  260.             break;
  261.  
  262.         case R_PPC_REL24:
  263.             kputint(0xd);
  264.             sym_idx = ELF32_R_SYM(r_info);
  265.             sym_addr = sym_table[sym_idx].st_value + bias;
  266.             kputint(sym_addr);
  267.             res = (sym_addr - (uint32_t)r_ptr + a) >> 2;
  268.             kputint(res);
  269.             if (res & 0xff000000) {
  270.                 /* out of range?? */
  271.                 kputint(0xeeeeeeee);
  272.                 //while(1);
  273.             }
  274.             *r_ptr = (*r_ptr & ~0x00ffffff) | (res & 0x00ffffff);
  275.             kputint(0x1d);
  276.             break;
  277.         }
  278.     }
  279.  
  280.     kputint(-3);
  281.     if (plt != 0) {
  282.  
  283. /* .PLTcall: */
  284.     plt[6] = _ldis(11, __HA(_plt_table));   // ldis r11, .PLTtable@ha
  285.     plt[7] = _lwz(11, __L(_plt_table), 11); // lwz r11, .PLTtable@l(r11)
  286.     plt[8] = _mtctr(11);            // mtctr r11
  287.     plt[9] = _bctr();
  288.  
  289. /* .PLTi, i = 0..N-1 */
  290. /*  kputint(-4);
  291.     for (i = 0; i < plt_n; ++i) {
  292.         //_plt_table[i] == function address;
  293.         plt[18+i] = _b(_plt_call, &plt[18+i]);  // b .PLTcall
  294.     }
  295. */
  296.     kputint(-5);
  297.     kputint(_plt_table[0]);
  298.     }
  299.  
  300.     kputint(-6);
  301.     /* This will come in handy */
  302.     runtime_env.rtld_dynamic = dynamic;
  303.     runtime_env.rtld.bias = bias;
  304.  
  305. //  volatile int ff=1;
  306. //  while(ff);
  307.     kputint(-7);
  308.     test_func();
  309.     kputint(0x42);
  310.     kputint(test_var);
  311. //  while(1);
  312. //  while(1);
  313.     /* Init libc and run rtld main */
  314.     kputint(0x22);
  315.     __main();
  316.  
  317.     kputint(33);
  318.     __io_init();
  319.     kputint(-1);
  320.     kputint(0x52);
  321. //  printf("Hello, world! (from ppc rtld)\n");
  322.     kputint(0x62);
  323. //  while(1);
  324.     kputint(34);
  325.     _rtld_main();
  326.     kputint(35);
  327.     __exit();
  328.  
  329.     kputint(36);
  330. }
  331.  
  332. /** @}
  333.  */
  334.