VirtualBox

source: vbox/trunk/src/VBox/Debugger/DBGPlugInCommonELF.cpp@ 8841

Last change on this file since 8841 was 8820, checked in by vboxsync, 17 years ago

Dug out the solaris kernel symbols! Use the "detect" command in the debugger in order to do this.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.1 KB
Line 
1/* $Id: DBGPlugInCommonELF.cpp 8820 2008-05-14 19:49:42Z vboxsync $ */
2/** @file
3 * DBGPlugInCommonELF - Common code for dealing with ELF images.
4 */
5
6/*
7 * Copyright (C) 2008 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#define LOG_GROUP LOG_GROUP_DBGF ///@todo add new log group.
27#include "DBGPlugInCommonELF.h"
28#include <VBox/dbgf.h>
29#include <iprt/string.h>
30#include <iprt/mem.h>
31#include <iprt/assert.h>
32
33
34
35/**
36 * Common 32-bit ELF module parser.
37 *
38 * It takes the essential bits of the ELF module (elf header, section headers,
39 * symbol table and string table), and inserts/updates the module and symbols.
40 *
41 *
42 * @returns VBox status code.
43 *
44 * @param pVM The VM handle.
45 * @param pszModName The module name.
46 * @param pszFilename The filename. optional.
47 * @param fFlags Flags.
48 * @param pEhdr Pointer to the ELF header.
49 * @param paShdrs Pointer to the section headers. The caller must verify that
50 * the e_shnum member of the ELF header is within the bounds of
51 * this table. The caller should also adjust the section addresses
52 * so these correspond to actual load addresses.
53 * @param paSyms Pointer to the symbol table.
54 * @param cMaxSyms The maximum number of symbols paSyms may hold. This isn't
55 * the exact count, it's just a cap for avoiding SIGSEGVs
56 * and general corruption.
57 * @param pbStrings Pointer to the string table.
58 * @param cbMaxStrings The size of the memory pbStrings points to. This doesn't
59 * have to match the string table size exactly, it's just to
60 * avoid SIGSEGV when a bad string index is encountered.
61 */
62int DBGDiggerCommonParseElf32Mod(PVM pVM, const char *pszModName, const char *pszFilename, uint32_t fFlags,
63 Elf32_Ehdr const *pEhdr, Elf32_Shdr const *paShdrs,
64 Elf32_Sym const *paSyms, size_t cMaxSyms,
65 char const *pbStrings, size_t cbMaxStrings)
66{
67 AssertPtrReturn(pVM, VERR_INVALID_POINTER);
68 AssertPtrReturn(pszModName, VERR_INVALID_POINTER);
69 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
70 AssertReturn(!(fFlags & ~DBG_DIGGER_ELF_MASK), VERR_INVALID_PARAMETER);
71 AssertReturn(fFlags & (DBG_DIGGER_ELF_FUNNY_SHDRS | DBG_DIGGER_ELF_ADJUST_SYM_VALUE)
72 != DBG_DIGGER_ELF_FUNNY_SHDRS | DBG_DIGGER_ELF_ADJUST_SYM_VALUE, VERR_INVALID_PARAMETER);
73 AssertPtrReturn(paShdrs, VERR_INVALID_POINTER);
74 AssertPtrReturn(paSyms, VERR_INVALID_POINTER);
75 AssertPtrReturn(pbStrings, VERR_INVALID_POINTER);
76
77 /*
78 * Validate the ELF header.
79 */
80 if ( pEhdr->e_ident[EI_MAG0] != ELFMAG0
81 || pEhdr->e_ident[EI_MAG1] != ELFMAG1
82 || pEhdr->e_ident[EI_MAG2] != ELFMAG2
83 || pEhdr->e_ident[EI_MAG3] != ELFMAG3)
84 return VERR_INVALID_EXE_SIGNATURE;
85 if (pEhdr->e_ident[EI_CLASS] != ELFCLASS32)
86 return VERR_LDRELF_MACHINE;
87
88 if (pEhdr->e_ident[EI_DATA] != ELFDATA2LSB)
89 return VERR_LDRELF_ODD_ENDIAN;
90 if (pEhdr->e_ident[EI_VERSION] != EV_CURRENT)
91 return VERR_LDRELF_VERSION;
92 if (pEhdr->e_version != EV_CURRENT)
93 return VERR_LDRELF_VERSION;
94 if (pEhdr->e_ehsize != sizeof(*pEhdr))
95 return VERR_BAD_EXE_FORMAT;
96
97 if ( pEhdr->e_machine != EM_386
98 && pEhdr->e_machine != EM_486)
99 return VERR_LDRELF_MACHINE;
100
101 if ( pEhdr->e_type != ET_DYN
102 && pEhdr->e_type != ET_REL
103 && pEhdr->e_type != ET_EXEC) //??
104 return VERR_BAD_EXE_FORMAT;
105 if ( pEhdr->e_phentsize != sizeof(Elf32_Phdr)
106 && pEhdr->e_phentsize) //??
107 return VERR_BAD_EXE_FORMAT;
108 if (pEhdr->e_shentsize != sizeof(Elf32_Shdr))
109 return VERR_BAD_EXE_FORMAT;
110 if (pEhdr->e_shentsize != sizeof(Elf32_Shdr))
111 return VERR_BAD_EXE_FORMAT;
112 if (ASMMemIsAll8(&pEhdr->e_ident[EI_PAD], EI_NIDENT - EI_PAD, 0) != NULL) //??
113 return VERR_BAD_EXE_FORMAT;
114
115 /*
116 * Validate the section headers, finding the string
117 * and symbol table headers while at it.
118 */
119 const Elf32_Shdr *pSymShdr = NULL;
120 const Elf32_Shdr *pStrShdr = NULL;
121 for (unsigned iSh = fFlags & DBG_DIGGER_ELF_FUNNY_SHDRS ? 1 : 0; iSh < pEhdr->e_shnum; iSh++)
122 {
123 /* Minimal validation. */
124 if (paShdrs[iSh].sh_link >= pEhdr->e_shnum)
125 return VERR_BAD_EXE_FORMAT;
126
127 /* Is it the symbol table?*/
128 if (paShdrs[iSh].sh_type == SHT_SYMTAB)
129 {
130 if (pSymShdr)
131 return VERR_LDRELF_MULTIPLE_SYMTABS;
132 pSymShdr = &paShdrs[iSh];
133 if (pSymShdr->sh_entsize != sizeof(Elf32_Sym))
134 return VERR_BAD_EXE_FORMAT;
135 pStrShdr = &paShdrs[paShdrs[iSh].sh_link];
136 }
137 }
138
139 /*
140 * Validate the symbol table.
141 */
142 uint32_t const cbStrings = pStrShdr ? pStrShdr->sh_size : cbMaxStrings;
143 uint32_t const cSyms = pSymShdr
144 ? RT_MIN(cMaxSyms, pSymShdr->sh_size / sizeof(Elf32_Sym))
145 : cMaxSyms;
146 for (uint32_t iSym = 1; iSym < cSyms; iSym++)
147 {
148 if (paSyms[iSym].st_name >= cbStrings)
149 return VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET;
150 if ( !(fFlags & DBG_DIGGER_ELF_FUNNY_SHDRS)
151 && paSyms[iSym].st_shndx >= pEhdr->e_shnum
152 && paSyms[iSym].st_shndx != SHN_UNDEF
153 && ( paSyms[iSym].st_shndx < SHN_LORESERVE
154 /*|| paSyms[iSym].st_shndx > SHN_HIRESERVE*/
155 || ELF32_ST_BIND(paSyms[iSym].st_info) == STB_GLOBAL
156 || ELF32_ST_BIND(paSyms[iSym].st_info) == STB_WEAK))
157 return VERR_BAD_EXE_FORMAT;
158 }
159
160 /*
161 * Create a module / update it.
162 */
163 /** @todo debug modules - the funny shdrs (solaris) are going to be cool here... */
164
165 /*
166 * Add all relevant symbols in the module
167 */
168 for (uint32_t iSym = 1; iSym < cSyms; iSym++)
169 {
170 /* Undefined symbols are not exports, they are imports. */
171 if ( paSyms[iSym].st_shndx != SHN_UNDEF
172 && ( ELF32_ST_BIND(paSyms[iSym].st_info) == STB_GLOBAL
173 || ELF32_ST_BIND(paSyms[iSym].st_info) == STB_WEAK))
174 {
175 /* Get the symbol name. */
176 if (paSyms[iSym].st_name >= cbMaxStrings)
177 continue;
178 const char *pszSymbol = pbStrings + paSyms[iSym].st_name;
179 if (!*pszSymbol)
180 continue;
181
182 /* Calc the address (value) and size. */
183 RTGCUINTPTR Size = paSyms[iSym].st_size;
184 RTGCUINTPTR Address = paSyms[iSym].st_value;
185 if (paSyms[iSym].st_shndx == SHN_ABS)
186 /* absolute symbols are not subject to any relocation. */;
187 else if (fFlags & DBG_DIGGER_ELF_ADJUST_SYM_VALUE)
188 {
189 if (paSyms[iSym].st_shndx < pEhdr->e_shnum)
190 AssertFailed(/*impossible*/);
191 /* relative to the section. */
192 Address += paShdrs[paSyms[iSym].st_shndx].sh_addr;
193 }
194
195 DBGFR3SymbolAdd(pVM, 0, Address, Size, pszSymbol);
196 Log(("%RGv %RGv %s::%s\n", Address, Size, pszModName, pszSymbol));
197 }
198 /*else: silently ignore */
199 }
200
201 return VINF_SUCCESS;
202}
203
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