Subversion Repositories HelenOS

Rev

Rev 3681 | Rev 3772 | Go to most recent revision | Blame | Compare with Previous | 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 <stdio.h>
  38. #include <stdlib.h>
  39.  
  40. #include <arch.h>
  41. #include <elf_dyn.h>
  42. #include <symbol.h>
  43. #include <rtld.h>
  44. #include <smc.h>
  45.  
  46. #define __L(ptr) ((uint32_t)(ptr) & 0x0000ffff)
  47. #define __HA(ptr) ((uint32_t)(ptr) >> 16)
  48.  
  49. // ldis r11, .PLTtable@ha
  50. static inline uint32_t _ldis(unsigned rD, uint16_t imm16)
  51. {
  52.     /* Special case of addis: ldis rD,SIMM == addis rD,0,SIMM */
  53.     return 0x3C000000 | (rD << 21) | imm16;
  54. }
  55.  
  56. static inline uint32_t _lwz(unsigned rD, uint16_t disp16, unsigned rA)
  57. {
  58.     return 0x80000000 | (rD << 21) | (rA << 16) | disp16;
  59. }
  60.  
  61. static inline uint32_t _mtctr(unsigned rS)
  62. {
  63.     /* mtctr rD == mtspr 9, rD */
  64.     return 0x7c0003a6 | (rS << 21) | (9/*CTR*/ << 16);
  65. }
  66.  
  67. static inline uint32_t _bctr()
  68. {
  69.     /* bcctr 0x1f, 0 */
  70.     return 0x4c000420 | (0x1f/*always*/ << 21);
  71. }
  72.  
  73. /* branch */
  74. static inline uint32_t _b(uint32_t *addr, uint32_t *location)
  75. {
  76.     uint32_t raddr = ((uint32_t)addr - (uint32_t)location) & 0x03fffffc;
  77.     return 0x48000000 | raddr;
  78. }
  79.  
  80.  
  81. /*
  82.  * Fill in PLT
  83.  */
  84. void module_process_pre_arch(module_t *m)
  85. {
  86.     uint32_t *plt;
  87.     uint32_t *_plt_ent;
  88.  
  89.     plt = m->dyn.plt_got;
  90.     if (!plt) {
  91.         /* Module has no PLT */
  92.         return;
  93.     }
  94.  
  95.     // PLT entries start here. However, each occupies 2 words
  96.     _plt_ent = plt + 18;
  97.  
  98.     // By definition of the ppc ABI, there's 1:1 correspondence
  99.     // between JMPREL entries and PLT entries
  100.     unsigned plt_n = m->dyn.plt_rel_sz / sizeof(elf_rela_t);
  101.  
  102.     uint32_t *_plt_table;
  103.     uint32_t *_plt_call;
  104.     uint32_t *_plt_resolve;
  105.  
  106.     _plt_resolve = plt;
  107.     _plt_call = plt + 6;
  108.     _plt_table = plt + 18 + plt_n;
  109.  
  110. /* .PLTcall: */
  111.     plt[6] = _ldis(11, __HA(_plt_table));   // ldis r11, .PLTtable@ha
  112.     plt[7] = _lwz(11, __L(_plt_table), 11); // lwz r11, .PLTtable@l(r11)
  113.     plt[8] = _mtctr(11);            // mtctr r11
  114.     plt[9] = _bctr();
  115.  
  116. /* .PLTi, i = 0..N-1 */
  117. //  kputint(-4);
  118. /*  for (i = 0; i < plt_n; ++i) {
  119.         //_plt_table[i] == function address;
  120.         plt[18+i] = _b(_plt_call, &plt[18+i]);  // b .PLTcall
  121.     }*/
  122. }
  123.  
  124. void rel_table_process(module_t *m, elf_rel_t *rt, size_t rt_size)
  125. {
  126.     /* Unused */
  127.     (void)m; (void)rt; (void)rt_size;
  128. }
  129.  
  130. /**
  131.  * Process (fixup) all relocations in a relocation table.
  132.  */
  133. void rela_table_process(module_t *m, elf_rela_t *rt, size_t rt_size)
  134. {
  135.     int i;
  136.  
  137.     size_t rt_entries;
  138.     size_t r_offset;
  139.     elf_word r_info;
  140.     unsigned rel_type;
  141.     elf_word sym_idx;
  142.     uintptr_t sym_addr;
  143.     uintptr_t r_addend;
  144.    
  145.     elf_symbol_t *sym_table;
  146.     elf_symbol_t *sym;
  147.     uint32_t *r_ptr;
  148.     uint16_t *r_ptr16;
  149.     char *str_tab;
  150.    
  151.     elf_symbol_t *sym_def;
  152.     module_t *dest;
  153.  
  154.     uint32_t *plt;
  155.     uint32_t *_plt_table;
  156.     uint32_t *_plt_ent;
  157.     uint32_t plt_n;
  158.     uint32_t pidx;
  159.     uint32_t t_addr;
  160.     uint32_t sym_size;
  161.  
  162.     plt = m->dyn.plt_got;
  163.     plt_n = m->dyn.plt_rel_sz / sizeof(elf_rela_t);
  164.     _plt_ent = plt+ 18;
  165.     _plt_table = plt + 18 + plt_n;
  166.  
  167.     DPRINTF("parse relocation table\n");
  168.  
  169.     sym_table = m->dyn.sym_tab;
  170.     rt_entries = rt_size / sizeof(elf_rela_t);
  171.     str_tab = m->dyn.str_tab;
  172.  
  173.     DPRINTF("address: 0x%x, entries: %d\n", (uintptr_t)rt, rt_entries);
  174.    
  175.     for (i = 0; i < rt_entries; ++i) {
  176.         DPRINTF("symbol %d: ", i);
  177.         r_offset = rt[i].r_offset;
  178.         r_info = rt[i].r_info;
  179.         r_addend = rt[i].r_addend;
  180.  
  181.         sym_idx = ELF32_R_SYM(r_info);
  182.         sym = &sym_table[sym_idx];
  183.  
  184.         DPRINTF("name '%s', value 0x%x, size 0x%x\n",
  185.             str_tab + sym->st_name,
  186.             sym->st_value,
  187.             sym->st_size);
  188.  
  189.         rel_type = ELF32_R_TYPE(r_info);
  190.         r_ptr = (uint32_t *)(r_offset + m->bias);
  191.         r_ptr16 = (uint16_t *)(r_offset + m->bias);
  192.  
  193.         if (sym->st_name != 0) {
  194.             DPRINTF("rel_type: %x, rel_offset: 0x%x\n", rel_type, r_offset);
  195.             sym_def = symbol_def_find(str_tab + sym->st_name,
  196.                 m, &dest);
  197.             DPRINTF("dest name: '%s'\n", dest->dyn.soname);
  198.             DPRINTF("dest bias: 0x%x\n", dest->bias);
  199.             if (sym_def) {
  200.                 sym_addr = symbol_get_addr(sym_def, dest);
  201.                 DPRINTF("symbol definition found, addr=0x%x\n", sym_addr);
  202.             } else {
  203.                 DPRINTF("symbol definition not found\n");
  204.                 continue;
  205.             }
  206.         }
  207.  
  208.         switch (rel_type) {
  209.         case R_PPC_ADDR16_LO:
  210.             DPRINTF("fixup R_PPC_ADDR16_LO (#lo(s+a))\n");
  211.             *r_ptr16 = (sym_addr + r_addend) & 0xffff;
  212.             break;
  213.  
  214.         case R_PPC_ADDR16_HI:
  215.             DPRINTF("fixup R_PPC_ADDR16_HI (#hi(s+a))\n");
  216.             *r_ptr16 = (sym_addr + r_addend) >> 16;
  217.             break;
  218.  
  219.         case R_PPC_ADDR16_HA:
  220.             DPRINTF("fixup R_PPC_ADDR16_HA (#ha(s+a))\n");
  221.             t_addr = sym_addr + r_addend;
  222.             *r_ptr16 = (t_addr >> 16) + ((t_addr & 0x8000) ? 1 : 0);
  223.             break;
  224.  
  225.         case R_PPC_JMP_SLOT:
  226.             DPRINTF("fixup R_PPC_JMP_SLOT (b+v)\n");
  227.             pidx = (r_ptr - _plt_ent) / 2;
  228.             if (pidx >= plt_n) {
  229.                 DPRINTF("error: proc index out of range\n");
  230.                 exit(1);
  231.             }
  232.             plt[18+2*pidx] = _b((void *)sym_addr, &plt[18+2*pidx]);
  233.             break;
  234.  
  235.         case R_PPC_ADDR32:
  236.             DPRINTF("fixup R_PPC_ADDR32 (b+v+a)\n");
  237.             *r_ptr = r_addend + sym_addr;
  238.             break;
  239.  
  240.         case R_PPC_COPY:
  241.             /*
  242.              * Copy symbol data from shared object to specified
  243.              * location.
  244.              */
  245.             DPRINTF("fixup R_PPC_COPY (s)\n");
  246.             sym_size = sym->st_size;
  247.             if (sym_size != sym_def->st_size) {
  248.                 printf("warning: mismatched symbol sizes\n");
  249.                 /* Take the lower value. */
  250.                 if (sym_size > sym_def->st_size)
  251.                     sym_size = sym_def->st_size;
  252.             }
  253.             memcpy(r_ptr, (const void *)sym_addr, sym_size);
  254.             break;
  255.            
  256.         case R_PPC_RELATIVE:
  257.             DPRINTF("fixup R_PPC_RELATIVE (b+a)\n");
  258.             *r_ptr = r_addend + m->bias;
  259.             break;
  260.  
  261.         case R_PPC_REL24:
  262.             DPRINTF("fixup R_PPC_REL24 (s+a-p)>>2\n");
  263.             *r_ptr = (sym_addr + r_addend - (uint32_t)r_ptr) >> 2;
  264.             break;
  265.  
  266.         case R_PPC_DTPMOD32:
  267.             /*
  268.              * We can ignore this as long as the only module
  269.              * with TLS variables is libc.so.
  270.              */
  271.             DPRINTF("Ignoring R_PPC_DTPMOD32\n");
  272.             break;
  273.  
  274.         default:
  275.             printf("Error: Unknown relocation type %d.\n",
  276.                 rel_type);
  277.             exit(1);
  278.             break;
  279.         }
  280.     }
  281.  
  282.     /*
  283.      * Synchronize the used portion of PLT. This is necessary since
  284.      * we are writing instructions.
  285.      */
  286.     smc_coherence(&plt[18], plt_n * 2 * sizeof(uint32_t));
  287. }
  288.  
  289. /** @}
  290.  */
  291.