00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00037 #include <stdio.h>
00038 #include <stdlib.h>
00039
00040 #include <libarch/rtld/elf_dyn.h>
00041 #include <rtld/symbol.h>
00042 #include <rtld/rtld.h>
00043 #include <rtld/rtld_debug.h>
00044 #include <rtld/rtld_arch.h>
00045
00046 void module_process_pre_arch(module_t *m)
00047 {
00048
00049 }
00050
00051
00055 void rel_table_process(module_t *m, elf_rel_t *rt, size_t rt_size)
00056 {
00057 unsigned i;
00058
00059 size_t rt_entries;
00060 size_t r_offset;
00061 elf_word r_info;
00062 unsigned rel_type;
00063 elf_word sym_idx;
00064 uint32_t sym_addr;
00065
00066 elf_symbol_t *sym_table;
00067 elf_symbol_t *sym;
00068 uint32_t *r_ptr;
00069 uint32_t sym_size;
00070 char *str_tab;
00071
00072 elf_symbol_t *sym_def;
00073 module_t *dest;
00074
00075 DPRINTF("parse relocation table\n");
00076
00077 sym_table = m->dyn.sym_tab;
00078 rt_entries = rt_size / sizeof(elf_rel_t);
00079 str_tab = m->dyn.str_tab;
00080
00081 DPRINTF("address: 0x%x, entries: %d\n", (uintptr_t)rt, rt_entries);
00082
00083 for (i = 0; i < rt_entries; ++i) {
00084
00085 r_offset = rt[i].r_offset;
00086 r_info = rt[i].r_info;
00087
00088 sym_idx = ELF32_R_SYM(r_info);
00089 sym = &sym_table[sym_idx];
00090
00091
00092
00093
00094
00095
00096 rel_type = ELF32_R_TYPE(r_info);
00097 r_ptr = (uint32_t *)(r_offset + m->bias);
00098
00099 if (sym->st_name != 0) {
00100
00101 sym_def = symbol_def_find(str_tab + sym->st_name,
00102 m, &dest);
00103
00104
00105 if (sym_def) {
00106 sym_addr = (uint32_t)
00107 symbol_get_addr(sym_def, dest);
00108
00109 } else {
00110 printf("Definition of '%s' not found.\n",
00111 str_tab + sym->st_name);
00112 continue;
00113 }
00114 } else {
00115 sym_addr = 0;
00116 sym_def = NULL;
00117 }
00118
00119 switch (rel_type) {
00120 case R_386_GLOB_DAT:
00121 case R_386_JUMP_SLOT:
00122 DPRINTF("fixup R_386_GLOB_DAT/JUMP_SLOT (b+v)\n");
00123 *r_ptr = sym_addr;
00124 break;
00125
00126 case R_386_32:
00127 DPRINTF("fixup R_386_32 (b+v+a)\n");
00128 *r_ptr += sym_addr;
00129 break;
00130
00131 case R_386_PC32:
00132 DPRINTF("fixup R_386_PC32 (b+v+a-p)\n");
00133 *r_ptr += sym_addr - (uint32_t) r_ptr;
00134 break;
00135
00136 case R_386_COPY:
00137
00138
00139
00140
00141 DPRINTF("fixup R_386_COPY (s)\n");
00142 sym_size = sym->st_size;
00143 if (sym_size != sym_def->st_size) {
00144 printf("Warning: Mismatched symbol sizes.\n");
00145
00146 if (sym_size > sym_def->st_size)
00147 sym_size = sym_def->st_size;
00148 }
00149 memcpy(r_ptr, (const void *)sym_addr, sym_size);
00150 break;
00151
00152 case R_386_RELATIVE:
00153 DPRINTF("fixup R_386_RELATIVE (b+a)\n");
00154 *r_ptr += m->bias;
00155 break;
00156
00157 case R_386_TLS_DTPMOD32:
00158
00159
00160
00161
00162 DPRINTF("Ignoring R_386_TLS_DTPMOD32\n");
00163 break;
00164
00165 default:
00166 printf("Error: Unknown relocation type %d\n",
00167 rel_type);
00168 exit(1);
00169 }
00170
00171 }
00172
00173 }
00174
00175 void rela_table_process(module_t *m, elf_rela_t *rt, size_t rt_size)
00176 {
00177
00178 (void)m; (void)rt; (void)rt_size;
00179 }
00180