sym.c (4163B)
1 /* $Id: //depot/blt/lib/libdl/sym.c#8 $ 2 ** 3 ** Copyright 1999 Sidney Cammeresi 4 ** All rights reserved. 5 ** 6 ** Redistribution and use in source and binary forms, with or without 7 ** modification, are permitted provided that the following conditions 8 ** are met: 9 ** 1. Redistributions of source code must retain the above copyright 10 ** notice, this list of conditions, and the following disclaimer. 11 ** 2. 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 ** 3. 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 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <elf.h> 33 #include <dlfcn.h> 34 #include <blt/libsyms.h> 35 #include "dl-int.h" 36 37 weak_alias (_dlsym, dlsym) 38 39 extern lib_t *file; 40 41 void *_dlsym (void *handle, const char *symbol) 42 { 43 int i; 44 lib_t *lib; 45 46 lib = handle; 47 for (i = 0; i < lib->dynsym_size / sizeof (elf32_sym_t); i++) 48 if (!strcmp (lib->dynstr_data + lib->dynsym_data[i].st_name, symbol)) 49 return (void *) ((unsigned int) lib->hdr + 50 lib->dynsym_data[i].st_value); 51 for (i = 0; i < lib->symtab_size / sizeof (elf32_sym_t); i++) 52 if (!strcmp (lib->strtab_data + lib->symtab_data[i].st_name, symbol)) 53 return (void *) ((unsigned int) lib->hdr + 54 lib->symtab_data[i].st_value); 55 return NULL; 56 } 57 58 unsigned int __dl_lookup_sym (lib_t *lib, const char *name) 59 { 60 int i; 61 62 for (i = 0; i < lib->symtab_size / sizeof (elf32_sym_t); i++) 63 if (!strcmp (lib->strtab_data + lib->symtab_data[i].st_name, name)) 64 return lib->symtab_data[i].st_value; 65 return 0; 66 } 67 68 int __dl_patch_section (lib_t *lib, elf32_rel_t *rel, int size) 69 { 70 char *name; 71 int i; 72 unsigned int *word, sym = 0; 73 lib_t *p; 74 75 for (i = 0; i < size; i++) 76 { 77 //_printf ("patching at %x, type %d\n", rel[i].r_offset, 78 // ELF32_R_TYPE (rel[i].r_info)); 79 word = (unsigned int *) ((unsigned int) lib->hdr + rel[i].r_offset); 80 if (ELF32_R_SYM (rel[i].r_info)) 81 { 82 name = lib->dynstr_data + 83 lib->dynsym_data[ELF32_R_SYM (rel[i].r_info)].st_name; 84 if (!(sym = __dl_lookup_sym (lib, name))) 85 { 86 p = file; 87 while ((p != NULL) && !sym) 88 if (!(sym = __dl_lookup_sym (p, name))) 89 p = p->next; 90 if (!sym) 91 { 92 //_printf ("unresolved symbol %s\n", name); 93 return -1; 94 } 95 if (p != file) 96 sym += (unsigned int) p->hdr; 97 } 98 else 99 sym += (unsigned int) lib->hdr; 100 } 101 switch (ELF32_R_TYPE (rel[i].r_info)) 102 { 103 case R_386_32: 104 *word += sym; 105 break; 106 107 case R_386_PC32: 108 *word += sym - (unsigned int) word; 109 break; 110 111 case R_386_RELATIVE: 112 *word += (unsigned int) lib->hdr; 113 break; 114 115 default: 116 //_printf ("unknown relocation type %d; crashing soon...\n", 117 // ELF32_R_TYPE (rel[i].r_info)); 118 break; 119 } 120 } 121 return 0; 122 } 123 124 int __dl_patchup (lib_t *lib) 125 { 126 int size; 127 elf32_rel_t *rel; 128 129 rel = (elf32_rel_t *) elf_find_section_data (lib->hdr, ".rel.text"); 130 size = elf_section_size (lib->hdr, ".rel.text") / sizeof (elf32_rel_t); 131 if (__dl_patch_section (lib, rel, size)) 132 return -1; 133 rel = (elf32_rel_t *) elf_find_section_data (lib->hdr, ".rel.data"); 134 size = elf_section_size (lib->hdr, ".rel.data") / sizeof (elf32_rel_t); 135 if (__dl_patch_section (lib, rel, size)) 136 return -1; 137 return 0; 138 } 139