VirtualBox

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

Last change on this file since 11836 was 8929, checked in by vboxsync, 17 years ago

gcc-4.3 warning

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.1 KB
Line 
1/* $Id: DBGPlugInCommonELF.cpp 8929 2008-05-19 18:57:04Z 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