0
|
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
|