VirtualBox

source: vbox/trunk/src/VBox/Debugger/DBGPlugInCommonELFTmpl.cpp.h@ 61571

Last change on this file since 61571 was 59747, checked in by vboxsync, 9 years ago

iprt/asm.h: Cleaned up the ASMMemIsAll8/U32 mess and implmeneted the former in assembly. (Found inverted usage due to bad naming in copyUtf8Block, but it is fortunately an unused method.) Replaces the complicated ASMBitFirstSet based scanning in RTSgBufIsZero with a simple call to the new ASMMemIsZero function.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 13.2 KB
Line 
1/* $Id: DBGPlugInCommonELFTmpl.cpp.h 59747 2016-02-19 23:18:18Z vboxsync $ */
2/** @file
3 * DBGPlugInCommonELF - Code Template for dealing with one kind of ELF.
4 */
5
6/*
7 * Copyright (C) 2008-2015 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#if ELF_MODE == 32
19# define Elf_Ehdr Elf32_Ehdr
20# define Elf_Shdr Elf32_Shdr
21# define Elf_Phdr Elf32_Phdr
22# define Elf_Sym Elf32_Sym
23# define MY_ELFCLASS ELFCLASS32
24# define ELF_ST_BIND ELF32_ST_BIND
25# define DBGDiggerCommonParseElfMod DBGDiggerCommonParseElf32Mod
26#else
27# define Elf_Ehdr Elf64_Ehdr
28# define Elf_Shdr Elf64_Shdr
29# define Elf_Phdr Elf64_Phdr
30# define Elf_Sym Elf64_Sym
31# define MY_ELFCLASS ELFCLASS64
32# define ELF_ST_BIND ELF64_ST_BIND
33# define DBGDiggerCommonParseElfMod DBGDiggerCommonParseElf64Mod
34#endif
35
36
37/**
38 * Common ELF module parser.
39 *
40 * It takes the essential bits of the ELF module (elf header, section headers,
41 * symbol table and string table), and inserts/updates the module and symbols.
42 *
43 *
44 * @returns VBox status code.
45 *
46 * @param pUVM The user mode VM handle.
47 * @param pszModName The module name.
48 * @param pszFilename The filename. optional.
49 * @param fFlags Flags.
50 * @param pEhdr Pointer to the ELF header.
51 * @param paShdrs Pointer to the section headers. The caller must verify that
52 * the e_shnum member of the ELF header is within the bounds of
53 * this table. The caller should also adjust the section addresses
54 * so these correspond to actual load addresses.
55 * @param paSyms Pointer to the symbol table.
56 * @param cMaxSyms The maximum number of symbols paSyms may hold. This isn't
57 * the exact count, it's just a cap for avoiding SIGSEGVs
58 * and general corruption.
59 * @param pbStrings Pointer to the string table.
60 * @param cbMaxStrings The size of the memory pbStrings points to. This doesn't
61 * have to match the string table size exactly, it's just to
62 * avoid SIGSEGV when a bad string index is encountered.
63 * @param MinAddr Min address to care about.
64 * @param MaxAddr Max address to care about (inclusive). Together
65 * with MinAddr this forms a valid address range for
66 * symbols and sections that we care about. Anything
67 * outside the range is ignored, except when doing
68 * sanity checks..
69 * @param uModTag Module tag. Pass 0 if tagging is of no interest.
70 */
71int DBGDiggerCommonParseElfMod(PUVM pUVM, const char *pszModName, const char *pszFilename, uint32_t fFlags,
72 Elf_Ehdr const *pEhdr, Elf_Shdr const *paShdrs,
73 Elf_Sym const *paSyms, size_t cMaxSyms,
74 char const *pbStrings, size_t cbMaxStrings,
75 RTGCPTR MinAddr, RTGCPTR MaxAddr, uint64_t uModTag)
76{
77 AssertPtrReturn(pUVM, VERR_INVALID_POINTER);
78 AssertPtrReturn(pszModName, VERR_INVALID_POINTER);
79 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
80 AssertReturn(!(fFlags & ~DBG_DIGGER_ELF_MASK), VERR_INVALID_PARAMETER);
81 AssertReturn((fFlags & (DBG_DIGGER_ELF_FUNNY_SHDRS | DBG_DIGGER_ELF_ADJUST_SYM_VALUE))
82 != (DBG_DIGGER_ELF_FUNNY_SHDRS | DBG_DIGGER_ELF_ADJUST_SYM_VALUE), VERR_INVALID_PARAMETER);
83 AssertPtrReturn(paShdrs, VERR_INVALID_POINTER);
84 AssertPtrReturn(paSyms, VERR_INVALID_POINTER);
85 AssertPtrReturn(pbStrings, VERR_INVALID_POINTER);
86
87 /*
88 * Validate the ELF header.
89 */
90 if ( pEhdr->e_ident[EI_MAG0] != ELFMAG0
91 || pEhdr->e_ident[EI_MAG1] != ELFMAG1
92 || pEhdr->e_ident[EI_MAG2] != ELFMAG2
93 || pEhdr->e_ident[EI_MAG3] != ELFMAG3)
94 return VERR_INVALID_EXE_SIGNATURE;
95 if (pEhdr->e_ident[EI_CLASS] != MY_ELFCLASS)
96 return VERR_LDRELF_MACHINE;
97
98 if (pEhdr->e_ident[EI_DATA] != ELFDATA2LSB)
99 return VERR_LDRELF_ODD_ENDIAN;
100 if (pEhdr->e_ident[EI_VERSION] != EV_CURRENT)
101 return VERR_LDRELF_VERSION;
102 if (pEhdr->e_version != EV_CURRENT)
103 return VERR_LDRELF_VERSION;
104 if (pEhdr->e_ehsize != sizeof(*pEhdr))
105 return VERR_BAD_EXE_FORMAT;
106
107#if ELF_MODE == 32
108 if ( pEhdr->e_machine != EM_386
109 && pEhdr->e_machine != EM_486)
110 return VERR_LDRELF_MACHINE;
111#else
112 if (pEhdr->e_machine != EM_X86_64)
113 return VERR_LDRELF_MACHINE;
114#endif
115
116 if ( pEhdr->e_type != ET_DYN
117 && pEhdr->e_type != ET_REL
118 && pEhdr->e_type != ET_EXEC) //??
119 return VERR_BAD_EXE_FORMAT;
120 if ( pEhdr->e_phentsize != sizeof(Elf_Phdr)
121 && pEhdr->e_phentsize) //??
122 return VERR_BAD_EXE_FORMAT;
123 if (pEhdr->e_shentsize != sizeof(Elf_Shdr))
124 return VERR_BAD_EXE_FORMAT;
125 if (pEhdr->e_shentsize != sizeof(Elf_Shdr))
126 return VERR_BAD_EXE_FORMAT;
127 if (!ASMMemIsZero(&pEhdr->e_ident[EI_PAD], EI_NIDENT - EI_PAD)) //??
128 return VERR_BAD_EXE_FORMAT;
129
130 /*
131 * Validate the section headers, finding the string and symbol table
132 * headers and the load address while at it.
133 */
134 uint64_t uLoadAddr = UINT64_MAX;
135 const Elf_Shdr *pSymShdr = NULL;
136 const Elf_Shdr *pStrShdr = NULL;
137 for (unsigned iSh = fFlags & DBG_DIGGER_ELF_FUNNY_SHDRS ? 1 : 0; iSh < pEhdr->e_shnum; iSh++)
138 {
139 /* Minimal validation. */
140 if (paShdrs[iSh].sh_link >= pEhdr->e_shnum)
141 return VERR_BAD_EXE_FORMAT;
142
143 /* Is it the symbol table?*/
144 if (paShdrs[iSh].sh_type == SHT_SYMTAB)
145 {
146 if (pSymShdr)
147 return VERR_LDRELF_MULTIPLE_SYMTABS;
148 pSymShdr = &paShdrs[iSh];
149 if (pSymShdr->sh_entsize != sizeof(Elf32_Sym))
150 return VERR_BAD_EXE_FORMAT;
151 pStrShdr = &paShdrs[paShdrs[iSh].sh_link];
152 }
153 if (uLoadAddr > paShdrs[iSh].sh_addr)
154 uLoadAddr = paShdrs[iSh].sh_addr;
155 }
156
157 /*
158 * Validate the symbol table and determine the max section index
159 * when DBG_DIGGER_ELF_FUNNY_SHDRS is flagged.
160 */
161 uint32_t uMaxShIdx = fFlags & DBG_DIGGER_ELF_FUNNY_SHDRS ? 0 : pEhdr->e_shnum - 1;
162 size_t const cbStrings = pStrShdr ? pStrShdr->sh_size : cbMaxStrings;
163 size_t const cSyms = pSymShdr
164 ? RT_MIN(cMaxSyms, pSymShdr->sh_size / sizeof(Elf_Sym))
165 : cMaxSyms;
166 for (size_t iSym = 1; iSym < cSyms; iSym++)
167 {
168 if (paSyms[iSym].st_name >= cbStrings)
169 return VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET;
170 if (fFlags & DBG_DIGGER_ELF_FUNNY_SHDRS)
171 {
172 if ( paSyms[iSym].st_shndx > uMaxShIdx
173 && paSyms[iSym].st_shndx < SHN_LORESERVE)
174 uMaxShIdx = paSyms[iSym].st_shndx;
175 }
176 else if ( paSyms[iSym].st_shndx >= pEhdr->e_shnum
177 && paSyms[iSym].st_shndx != SHN_UNDEF
178 && ( paSyms[iSym].st_shndx < SHN_LORESERVE
179 /*|| paSyms[iSym].st_shndx > SHN_HIRESERVE*/
180 || ELF_ST_BIND(paSyms[iSym].st_info) == STB_GLOBAL
181 || ELF_ST_BIND(paSyms[iSym].st_info) == STB_WEAK) )
182 return VERR_BAD_EXE_FORMAT;
183 }
184 if (uMaxShIdx > 4096)
185 return VERR_BAD_EXE_FORMAT;
186
187 /*
188 * Create new module.
189 * The funny ELF section headers on solaris makes this very complicated.
190 */
191 uint32_t cSegs = uMaxShIdx + 1;
192 PDBGDIGGERELFSEG paSegs = (PDBGDIGGERELFSEG)alloca(sizeof(paSegs[0]) * cSegs);
193 for (uint32_t i = 0; i < cSegs; i++)
194 {
195 paSegs[i].uLoadAddr = RTGCPTR_MAX;
196 paSegs[i].uLastAddr = 0;
197 paSegs[i].iSeg = NIL_RTDBGSEGIDX;
198 }
199
200 RTDBGMOD hMod;
201 int rc = RTDbgModCreate(&hMod, pszModName, 0 /*cbSeg*/, 0 /*fFlags*/);
202 if (RT_FAILURE(rc))
203 return rc;
204 rc = RTDbgModSetTag(hMod, uModTag); AssertRC(rc);
205
206 if (fFlags & DBG_DIGGER_ELF_FUNNY_SHDRS)
207 {
208 /* Seek out the min and max symbol values for each section. */
209 for (uint32_t iSym = 1; iSym < cSyms; iSym++)
210 {
211 /* Ignore undefined, absolute and weak symbols in this pass,
212 but include local ones as well as nameless. */
213 uint32_t iSh = paSyms[iSym].st_shndx;
214 if ( iSh != SHN_UNDEF
215 && iSh < cSegs
216 && ( ELF_ST_BIND(paSyms[iSym].st_info) == STB_GLOBAL
217 || ELF_ST_BIND(paSyms[iSym].st_info) == STB_LOCAL))
218 {
219 /* Calc the address and check that it doesn't wrap with the size. */
220 RTGCUINTPTR Address = paSyms[iSym].st_value;
221 RTGCUINTPTR AddressLast = Address + RT_MAX(paSyms[iSym].st_size, 1) - 1;
222 if (AddressLast < Address)
223 continue;
224 if ( Address < MinAddr
225 || AddressLast > MaxAddr)
226 continue;
227
228 /* update min/max. */
229 if (Address < paSegs[iSh].uLoadAddr)
230 paSegs[iSh].uLoadAddr = Address;
231 if (AddressLast > paSegs[iSh].uLastAddr)
232 paSegs[iSh].uLastAddr = AddressLast;
233 }
234 }
235
236 /* Add the segments and fill in the translation table. */
237 RTGCPTR uRvaNext = 0;
238 for (unsigned i = 0; i < cSegs; i++)
239 if (paSegs[i].uLastAddr != 0)
240 {
241 char szSeg[32];
242 RTStrPrintf(szSeg, sizeof(szSeg), "sec%02u", i);
243 RTGCPTR cbSeg = paSegs[i].uLastAddr - paSegs[i].uLoadAddr + 1;
244 rc = RTDbgModSegmentAdd(hMod, uRvaNext, cbSeg, szSeg, 0 /*fFlags*/, &paSegs[i].iSeg);
245 if (RT_FAILURE(rc))
246 break;
247 uRvaNext += RT_ALIGN_T(cbSeg, 32, RTGCPTR);
248 }
249 }
250 else
251 {
252 /* Add the segments and fill in the translation table. */
253 RTGCPTR uRvaNext = 0;
254 for (unsigned i = 0; i < cSegs; i++)
255 if (paShdrs[i].sh_flags & SHF_ALLOC)
256 {
257 char szSeg[32];
258 RTStrPrintf(szSeg, sizeof(szSeg), "sec%02u", i);
259 rc = RTDbgModSegmentAdd(hMod, paShdrs[i].sh_addr - uLoadAddr, paShdrs[i].sh_size, szSeg, 0 /*fFlags*/, &paSegs[i].iSeg);
260 if (RT_FAILURE(rc))
261 break;
262 paSegs[i].uLoadAddr = paShdrs[i].sh_addr;
263 paSegs[i].uLastAddr = paShdrs[i].sh_addr + paShdrs[i].sh_size - 1;
264 }
265 }
266 if (RT_FAILURE(rc))
267 {
268 RTDbgModRelease(hMod);
269 return rc;
270 }
271
272
273 /*
274 * Add all relevant symbols in the module
275 */
276 for (uint32_t iSym = 1; iSym < cSyms; iSym++)
277 {
278 /* Undefined symbols are not exports, they are imports. */
279 RTDBGSEGIDX iSeg = paSyms[iSym].st_shndx;
280 if ( iSeg != SHN_UNDEF
281 && ( ELF_ST_BIND(paSyms[iSym].st_info) == STB_GLOBAL
282 || ELF_ST_BIND(paSyms[iSym].st_info) == STB_LOCAL
283 || ELF_ST_BIND(paSyms[iSym].st_info) == STB_WEAK))
284 {
285 /* Get the symbol name. */
286 if (paSyms[iSym].st_name >= cbMaxStrings)
287 continue;
288 const char *pszSymbol = pbStrings + paSyms[iSym].st_name;
289 if (!*pszSymbol)
290 continue;
291
292 /* Calc the address (value) and size. */
293 RTGCUINTPTR cbSym = paSyms[iSym].st_size;
294 RTGCUINTPTR offSeg = paSyms[iSym].st_value;
295 if (iSeg == SHN_ABS)
296 iSeg = RTDBGSEGIDX_ABS; /* absolute symbols are not subject to any relocation. */
297 else
298 {
299 Assert(iSeg < cSegs);
300 if (fFlags & (DBG_DIGGER_ELF_FUNNY_SHDRS | DBG_DIGGER_ELF_ADJUST_SYM_VALUE))
301 offSeg -= paSegs[iSeg].uLoadAddr;
302 iSeg = paSegs[iSeg].iSeg;
303 if (iSeg == NIL_RTDBGSEGIDX)
304 continue;
305 }
306 if (offSeg + cbSym < offSeg)
307 continue;
308
309 rc = RTDbgModSymbolAdd(hMod, pszSymbol, iSeg, offSeg, cbSym, 0 /*fFlags*/, NULL);
310 Log(("%02x:%RGv %RGv %s!%s (rc=%Rrc)\n", paSyms[iSym].st_shndx, offSeg, cbSym, pszModName, pszSymbol, rc));
311 }
312 /*else: silently ignore */
313 }
314
315 /*
316 * Link it into the address space.
317 */
318 RTDBGAS hAs = DBGFR3AsResolveAndRetain(pUVM, DBGF_AS_KERNEL);
319 if (hAs != NIL_RTDBGAS)
320 rc = dbgDiggerCommonLinkElfSegs(hAs, hMod, paSegs, cSegs);
321 else
322 rc = VERR_INTERNAL_ERROR;
323 RTDbgModRelease(hMod);
324 RTDbgAsRelease(hAs);
325 return rc;
326}
327
328
329#undef Elf_Ehdr
330#undef Elf_Shdr
331#undef Elf_Phdr
332#undef Elf_Sym
333#undef MY_ELFCLASS
334#undef ELF_ST_BIND
335#undef DBGDiggerCommonParseElfMod
336
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette