comparison dynload/dynload_syms_elf.c @ 0:3e629dc19168

initial from svn dyncall-1745
author Daniel Adler
date Thu, 19 Mar 2015 22:24:28 +0100
parents
children 011b5e3a8548
comparison
equal deleted inserted replaced
-1:000000000000 0:3e629dc19168
1 /*
2
3 Package: dyncall
4 Library: dynload
5 File: dynload/dynload_syms_elf.c
6 Description:
7 License:
8
9 Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
10 Tassilo Philipp <tphilipp@potion-studios.com>,
11 Olivier Chafik <olivier.chafik@gmail.com>
12
13 Permission to use, copy, modify, and distribute this software for any
14 purpose with or without fee is hereby granted, provided that the above
15 copyright notice and this permission notice appear in all copies.
16
17 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
18 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
19 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
20 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
22 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
23 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25 */
26
27
28
29 #include "../autovar/autovar_OS.h"
30
31 /*
32
33 dynamic symbol resolver for elf
34
35 */
36
37 #include "dynload.h"
38 #if defined(OS_OpenBSD)
39 # include <stdint.h>
40 # include <elf_abi.h>
41 #elif defined(OS_SunOS)
42 # include <libelf.h>
43 #elif defined(OS_BeOS)
44 # include <elf32.h>
45 #else
46 # include <elf.h>
47 #endif
48
49 #if defined(__GLIBC__)
50 # define _GNU_SOURCE
51 # define __USE_GNU
52 #endif
53
54 #include "dynload_alloc.h"
55
56 #include <assert.h>
57 #include <fcntl.h>
58 #include <dlfcn.h>
59 #include <stdio.h>
60 #include <string.h>
61 #include <sys/stat.h>
62 #include <sys/types.h>
63 #include <sys/mman.h>
64 #include <unistd.h>
65
66 /* run-time configuration 64/32 */
67 #if defined(OS_OpenBSD)
68 #else
69 # include "../autovar/autovar_ABI.h"
70 # ifdef ABI_ELF64
71
72 typedef Elf64_Ehdr Elf_Ehdr;
73 typedef Elf64_Phdr Elf_Phdr;
74 typedef Elf64_Shdr Elf_Shdr;
75 typedef Elf64_Sym Elf_Sym;
76 # ifndef OS_SunOS
77 typedef Elf64_Dyn Elf_Dyn;
78 # endif
79 typedef Elf64_Sxword Elf_tag;
80 typedef Elf64_Addr Elf_Addr;
81
82 # else
83 # if defined(OS_BeOS)
84 typedef struct Elf32_Ehdr Elf_Ehdr;
85 typedef struct Elf32_Phdr Elf_Phdr;
86 typedef struct Elf32_Shdr Elf_Shdr;
87 typedef struct Elf32_Sym Elf_Sym;
88 typedef struct Elf32_Dyn Elf_Dyn;
89 typedef Elf32_Sword Elf_tag;
90 typedef Elf32_Addr Elf_Addr;
91
92 # else
93
94 typedef Elf32_Ehdr Elf_Ehdr;
95 typedef Elf32_Phdr Elf_Phdr;
96 typedef Elf32_Shdr Elf_Shdr;
97 typedef Elf32_Sym Elf_Sym;
98 # ifndef OS_SunOS
99 typedef Elf32_Dyn Elf_Dyn;
100 # endif
101 typedef Elf32_Sword Elf_tag;
102 typedef Elf32_Addr Elf_Addr;
103
104 # endif
105 # endif
106 #endif
107
108
109 struct DLSyms_
110 {
111 const char* pStrTab;
112 Elf_Sym* pSymTab;
113 size_t strTabSize;
114 size_t nSymbols;
115 Elf_Ehdr* pElf_Ehdr; /* pointer to elf header */
116 int file; /* fd of lib */
117 size_t fileSize; /* filesize of open lib */
118 };
119
120
121 DLSyms* dlSymsInit(const char* libPath)
122 {
123 unsigned char* pMem;
124 void* pSectionContent;
125 int i;
126 struct stat st;
127 Elf_Shdr* pS;
128 DLSyms* pSyms = (DLSyms*)dlAllocMem(sizeof(DLSyms));
129 memset(pSyms, 0, sizeof(DLSyms));
130 pSyms->file = open(libPath, O_RDONLY);
131 stat(libPath, &st);
132 pSyms->fileSize = st.st_size;
133 pSyms->pElf_Ehdr = (Elf_Ehdr*) mmap((void*) NULL, pSyms->fileSize, PROT_READ, MAP_SHARED, pSyms->file, 0);
134
135 #ifdef ABI_ELF32
136 assert(pSyms->pElf_Ehdr->e_ident[EI_CLASS] == ELFCLASS32);
137 #else
138 assert(pSyms->pElf_Ehdr->e_ident[EI_CLASS] == ELFCLASS64);
139 #endif
140
141 assert(pSyms->pElf_Ehdr->e_phoff > 0);
142 assert(pSyms->pElf_Ehdr->e_shoff > 0);
143
144
145 pMem = (unsigned char*)pSyms->pElf_Ehdr;
146
147 /* traverse section headers */
148 pS = (Elf_Shdr*) ( pMem + pSyms->pElf_Ehdr->e_shoff );
149 /* skip section 0 which is always zero due to the Elf standard. */
150 for (i = 1; i < pSyms->pElf_Ehdr->e_shnum; i++)
151 {
152 Elf_Shdr* pSection = &pS[i];
153 pSectionContent = ((char*)pMem) + pSection->sh_offset;
154 switch (pSection->sh_type)
155 {
156 case SHT_DYNSYM:
157 if (!pSyms->pSymTab) {
158 pSyms->pSymTab = (Elf_Sym*)pSectionContent;
159 pSyms->nSymbols = pSection->sh_size / pSection->sh_entsize;
160 }
161 break;
162 case SHT_STRTAB:
163 // Do not trust pSyms->pElf_Ehdr->e_shstrndx!
164 if (!pSyms->pStrTab) {
165 pSyms->pStrTab = (const char*)pSectionContent;
166 pSyms->strTabSize = pSection->sh_size;
167 }
168 break;
169 }
170 if (pSyms->pSymTab && pSyms->pStrTab)
171 break;
172 }
173 return pSyms;
174 }
175
176
177 void dlSymsCleanup(DLSyms* pSyms)
178 {
179 if(pSyms) {
180 munmap((void*) pSyms->pElf_Ehdr, pSyms->fileSize);
181 close(pSyms->file);
182 dlFreeMem(pSyms);
183 }
184 }
185
186
187 int dlSymsCount(DLSyms* pSyms)
188 {
189 if (!pSyms)
190 return 0;
191 return pSyms->nSymbols;
192 }
193
194
195 const char* dlSymsName(DLSyms* pSyms, int index)
196 {
197 int str_index;
198 if(!pSyms || !pSyms->pSymTab || index < 0 || index >= pSyms->nSymbols)
199 return NULL;
200
201 str_index = pSyms->pSymTab[index].st_name;
202 if (str_index < 0 || str_index >= pSyms->strTabSize)
203 return NULL;
204 return &pSyms->pStrTab[str_index];
205 }
206
207
208 const char* dlSymsNameFromValue(DLSyms* pSyms, void* value)
209 {
210 Dl_info info;
211 return (dladdr(value, &info) && (value == info.dli_saddr))
212 ? info.dli_sname
213 : NULL;
214 }
215