tools/*: remove bcc and as86 as they are no longer required to compile the system...
[virtualbox.git] / src / VBox / Debugger / DBGPlugInCommonELFTmpl.cpp.h
blob50021fd99b2d5724f1fe287bccfdf95f34a15072
1 /* $Id$ */
2 /** @file
3 * DBGPlugInCommonELF - Code Template for dealing with one kind of ELF.
4 */
6 /*
7 * Copyright (C) 2008-2010 Oracle Corporation
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.
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
37 /**
38 * Common ELF module parser.
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.
44 * @returns VBox status code.
46 * @param pVM The 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.
71 int DBGDiggerCommonParseElfMod(PVM pVM, 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)
77 AssertPtrReturn(pVM, 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);
88 * Validate the ELF header.
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;
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;
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
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 (ASMMemIsAll8(&pEhdr->e_ident[EI_PAD], EI_NIDENT - EI_PAD, 0) != NULL) //??
128 return VERR_BAD_EXE_FORMAT;
131 * Validate the section headers, finding the string and symbol table
132 * headers and the load address while at it.
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++)
139 /* Minimal validation. */
140 if (paShdrs[iSh].sh_link >= pEhdr->e_shnum)
141 return VERR_BAD_EXE_FORMAT;
143 /* Is it the symbol table?*/
144 if (paShdrs[iSh].sh_type == SHT_SYMTAB)
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];
153 if (uLoadAddr > paShdrs[iSh].sh_addr)
154 uLoadAddr = paShdrs[iSh].sh_addr;
158 * Validate the symbol table and determine the max section index
159 * when DBG_DIGGER_ELF_FUNNY_SHDRS is flagged.
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++)
168 if (paSyms[iSym].st_name >= cbStrings)
169 return VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET;
170 if (fFlags & DBG_DIGGER_ELF_FUNNY_SHDRS)
172 if ( paSyms[iSym].st_shndx > uMaxShIdx
173 && paSyms[iSym].st_shndx < SHN_LORESERVE)
174 uMaxShIdx = paSyms[iSym].st_shndx;
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;
184 if (uMaxShIdx > 4096)
185 return VERR_BAD_EXE_FORMAT;
188 * Create new module.
189 * The funny ELF section headers on solaris makes this very complicated.
191 uint32_t cSegs = uMaxShIdx + 1;
192 PDBGDIGGERELFSEG paSegs = (PDBGDIGGERELFSEG)alloca(sizeof(paSegs[0]) * cSegs);
193 for (uint32_t i = 0; i < cSegs; i++)
195 paSegs[i].uLoadAddr = RTGCPTR_MAX;
196 paSegs[i].uLastAddr = 0;
197 paSegs[i].iSeg = NIL_RTDBGSEGIDX;
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);
206 if (fFlags & DBG_DIGGER_ELF_FUNNY_SHDRS)
208 /* Seek out the min and max symbol values for each section. */
209 for (uint32_t iSym = 1; iSym < cSyms; iSym++)
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))
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;
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;
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)
241 char szSeg[32];
242 RTStrPrintf(szSeg, sizeof(szSeg), "sec%02", 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);
250 else
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)
257 char szSeg[32];
258 RTStrPrintf(szSeg, sizeof(szSeg), "sec%02", 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;
266 if (RT_FAILURE(rc))
268 RTDbgModRelease(hMod);
269 return rc;
274 * Add all relevant symbols in the module
276 for (uint32_t iSym = 1; iSym < cSyms; iSym++)
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))
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;
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
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;
306 if (offSeg + cbSym < offSeg)
307 continue;
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));
312 /*else: silently ignore */
316 * Link it into the address space.
318 RTDBGAS hAs = DBGFR3AsResolveAndRetain(pVM, 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;
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