VirtualBox

source: vbox/trunk/src/VBox/Runtime/ldrELFRelocatable.cpp.h@ 4953

Last change on this file since 4953 was 4071, checked in by vboxsync, 17 years ago

Biggest check-in ever. New source code headers for all (C) innotek files.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 42.2 KB
Line 
1/* $Id: ldrELFRelocatable.cpp.h 4071 2007-08-07 17:07:59Z vboxsync $ */
2/** @file
3 * innotek Portable Runtime - Binary Image Loader, Template for ELF Relocatable Images.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/*******************************************************************************
19* Defined Constants And Macros *
20*******************************************************************************/
21#if ELF_MODE == 32
22#define RTLDRELF_NAME(name) rtldrELF32##name
23#define RTLDRELF_SUFF(name) name##32
24#define RTLDRELF_MID(pre,suff) pre##32##suff
25#define FMT_ELF_ADDR "%08RX32"
26#define FMT_ELF_HALF "%04RX16"
27#define FMT_ELF_OFF "%08RX32"
28#define FMT_ELF_SIZE "%08RX32"
29#define FMT_ELF_SWORD "%RI32"
30#define FMT_ELF_WORD "%08RX32"
31#define FMT_ELF_XWORD "%08RX32"
32#define FMT_ELF_SXWORD "%RI32"
33
34#elif ELF_MODE == 64
35#define RTLDRELF_NAME(name) rtldrELF64##name
36#define RTLDRELF_SUFF(name) name##64
37#define RTLDRELF_MID(pre,suff) pre##64##suff
38#define FMT_ELF_ADDR "%016RX64"
39#define FMT_ELF_HALF "%04RX16"
40#define FMT_ELF_SHALF "%RI16"
41#define FMT_ELF_OFF "%016RX64"
42#define FMT_ELF_SIZE "%016RX64"
43#define FMT_ELF_SWORD "%RI32"
44#define FMT_ELF_WORD "%08RX32"
45#define FMT_ELF_XWORD "%016RX64"
46#define FMT_ELF_SXWORD "%RI64"
47#endif
48
49#define Elf_Ehdr RTLDRELF_MID(Elf,_Ehdr)
50#define Elf_Phdr RTLDRELF_MID(Elf,_Phdr)
51#define Elf_Shdr RTLDRELF_MID(Elf,_Shdr)
52#define Elf_Sym RTLDRELF_MID(Elf,_Sym)
53#define Elf_Rel RTLDRELF_MID(Elf,_Rel)
54#define Elf_Rela RTLDRELF_MID(Elf,_Rela)
55#define Elf_Nhdr RTLDRELF_MID(Elf,_Nhdr)
56#define Elf_Dyn RTLDRELF_MID(Elf,_Dyn)
57#define Elf_Addr RTLDRELF_MID(Elf,_Addr)
58#define Elf_Half RTLDRELF_MID(Elf,_Half)
59#define Elf_Off RTLDRELF_MID(Elf,_Off)
60#define Elf_Size RTLDRELF_MID(Elf,_Size)
61#define Elf_Sword RTLDRELF_MID(Elf,_Sword)
62#define Elf_Word RTLDRELF_MID(Elf,_Word)
63
64#define RTLDRMODELF RTLDRELF_MID(RTLDRMODELF,)
65#define PRTLDRMODELF RTLDRELF_MID(PRTLDRMODELF,)
66
67#define ELF_R_SYM(info) RTLDRELF_MID(ELF,_R_SYM)(info)
68#define ELF_R_TYPE(info) RTLDRELF_MID(ELF,_R_TYPE)(info)
69#define ELF_R_INFO(sym, type) RTLDRELF_MID(ELF,_R_INFO)(sym, type)
70
71#define ELF_ST_BIND(info) RTLDRELF_MID(ELF,_ST_BIND)(info)
72
73
74
75/*******************************************************************************
76* Structures and Typedefs *
77*******************************************************************************/
78/**
79 * The ELF loader structure.
80 */
81typedef struct RTLDRMODELF
82{
83 /** Core module structure. */
84 RTLDRMODINTERNAL Core;
85 /** Pointer to the reader instance. */
86 PRTLDRREADER pReader;
87 /** Pointer to readonly mapping of the image bits.
88 * This mapping is provided by the pReader. */
89 const void *pvBits;
90
91 /** The ELF header. */
92 Elf_Ehdr Ehdr;
93 /** Pointer to our copy of the section headers.
94 * The virtual addresses in this array is the 0 based assignments we've given the image.
95 * Not valid if the image is DONE. */
96 Elf_Shdr *paShdrs;
97 /** The size of the loaded image. */
98 size_t cbImage;
99
100 /** The symbol section index. */
101 unsigned iSymSh;
102 /** Number of symbols in the table. */
103 unsigned cSyms;
104 /** Pointer to symbol table within RTLDRMODELF::pvBits. */
105 const Elf_Sym *paSyms;
106
107 /** The string section index. */
108 unsigned iStrSh;
109 /** Size of the string table. */
110 unsigned cbStr;
111 /** Pointer to string table within RTLDRMODELF::pvBits. */
112 const char *pStr;
113} RTLDRMODELF, *PRTLDRMODELF;
114
115
116/**
117 * Maps the image bits into memory and resolve pointers into it.
118 *
119 * @returns iprt status code.
120 * @param pModElf The ELF loader module instance data.
121 * @param fNeedsBits Set if we actually need the pvBits member.
122 * If we don't, we can simply read the string and symbol sections, thus saving memory.
123 */
124static int RTLDRELF_NAME(MapBits)(PRTLDRMODELF pModElf, bool fNeedsBits)
125{
126 NOREF(fNeedsBits);
127 if (pModElf->pvBits)
128 return VINF_SUCCESS;
129 int rc = pModElf->pReader->pfnMap(pModElf->pReader, &pModElf->pvBits);
130 if (RT_SUCCESS(rc))
131 {
132 const uint8_t *pu8 = (const uint8_t *)pModElf->pvBits;
133 pModElf->paSyms = (const Elf_Sym *)(pu8 + pModElf->paShdrs[pModElf->iSymSh].sh_offset);
134 pModElf->pStr = (const char *)(pu8 + pModElf->paShdrs[pModElf->iStrSh].sh_offset);
135 }
136 return rc;
137}
138
139
140/**
141 * Get the symbol and symbol value.
142 *
143 * @returns iprt status code.
144 * @param pModElf The ELF loader module instance data.
145 * @param BaseAddr The base address which the module is being fixedup to.
146 * @param pfnGetImport The callback function to use to resolve imports (aka unresolved externals).
147 * @param pvUser User argument to pass to the callback.
148 * @param iSym The symbol to get.
149 * @param ppSym Where to store the symbol pointer on success. (read only)
150 * @param pSymValue Where to store the symbol value on success.
151 */
152static int RTLDRELF_NAME(Symbol)(PRTLDRMODELF pModElf, Elf_Addr BaseAddr, PFNRTLDRIMPORT pfnGetImport, void *pvUser,
153 Elf_Size iSym, const Elf_Sym **ppSym, Elf_Addr *pSymValue)
154{
155 /*
156 * Validate and find the symbol.
157 */
158 if (iSym >= pModElf->cSyms)
159 {
160 AssertMsgFailed(("iSym=%d is an invalid symbol index!\n", iSym));
161 return VERR_LDRELF_INVALID_SYMBOL_INDEX;
162 }
163 const Elf_Sym *pSym = &pModElf->paSyms[iSym];
164 *ppSym = pSym;
165
166 if (pSym->st_name >= pModElf->cbStr)
167 {
168 AssertMsgFailed(("iSym=%d st_name=%d str sh_size=%d\n", iSym, pSym->st_name, pModElf->cbStr));
169 return VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET;
170 }
171 const char *pszName = ELF_STR(pModElf, pSym->st_name);
172
173 /*
174 * Determin the symbol value.
175 *
176 * Symbols needs different treatment depending on which section their are in.
177 * Undefined and absolute symbols goes into special non-existing sections.
178 */
179 switch (pSym->st_shndx)
180 {
181 /*
182 * Undefined symbol, needs resolving.
183 *
184 * Since ELF has no generic concept of importing from specific module (the OS/2 ELF format
185 * has but that's a OS extension and only applies to programs and dlls), we'll have to ask
186 * the resolver callback to do a global search.
187 */
188 case SHN_UNDEF:
189 {
190 /* Try to resolve the symbol. */
191 RTUINTPTR Value;
192 int rc = pfnGetImport(&pModElf->Core, "", pszName, ~0, &Value, pvUser);
193 if (RT_FAILURE(rc))
194 {
195 AssertMsgFailed(("Failed to resolve '%s' rc=%Rrc\n", pszName, rc));
196 return rc;
197 }
198 *pSymValue = (Elf_Addr)Value;
199 if ((RTUINTPTR)*pSymValue != Value)
200 {
201 AssertMsgFailed(("Symbol value overflowed! '%s'\n", pszName));
202 return VERR_SYMBOL_VALUE_TOO_BIG;
203 }
204
205 Log2(("rtldrELF: #%-3d - UNDEF " FMT_ELF_ADDR " '%s'\n", iSym, *pSymValue, pszName));
206 break;
207 }
208
209 /*
210 * Absolute symbols needs no fixing since they are, well, absolute.
211 */
212 case SHN_ABS:
213 *pSymValue = pSym->st_value;
214 Log2(("rtldrELF: #%-3d - ABS " FMT_ELF_ADDR " '%s'\n", iSym, *pSymValue, pszName));
215 break;
216
217 /*
218 * All other symbols are adressed relative to their section and need to be fixed up.
219 */
220 default:
221 if (pSym->st_shndx >= pModElf->Ehdr.e_shnum)
222 {
223 /* what about common symbols? */
224 AssertMsg(pSym->st_shndx < pModElf->Ehdr.e_shnum,
225 ("iSym=%d st_shndx=%d e_shnum=%d pszName=%s\n", iSym, pSym->st_shndx, pModElf->Ehdr.e_shnum, pszName));
226 return VERR_BAD_EXE_FORMAT;
227 }
228 *pSymValue = pSym->st_value + pModElf->paShdrs[pSym->st_shndx].sh_addr + BaseAddr;
229 Log2(("rtldrELF: #%-3d - %5d " FMT_ELF_ADDR " '%s'\n", iSym, pSym->st_shndx, *pSymValue, pszName));
230 break;
231 }
232
233 return VINF_SUCCESS;
234}
235
236
237/**
238 * Applies the fixups for a sections.
239 *
240 * @returns iprt status code.
241 * @param pModElf The ELF loader module instance data.
242 * @param BaseAddr The base address which the module is being fixedup to.
243 * @param pfnGetImport The callback function to use to resolve imports (aka unresolved externals).
244 * @param pvUser User argument to pass to the callback.
245 * @param SecAddr The section address. This is the address the relocations are relative to.
246 * @param cbSec The section size. The relocations must be inside this.
247 * @param pu8SecBaseR Where we read section bits from.
248 * @param pu8SecBaseW Where we write section bits to.
249 * @param pvRelocs Pointer to where we read the relocations from.
250 * @param cbRelocs Size of the relocations.
251 */
252static int RTLDRELF_NAME(RelocateSection)(PRTLDRMODELF pModElf, Elf_Addr BaseAddr, PFNRTLDRIMPORT pfnGetImport, void *pvUser,
253 const Elf_Addr SecAddr, Elf_Size cbSec, const uint8_t *pu8SecBaseR, uint8_t *pu8SecBaseW,
254 const void *pvRelocs, Elf_Size cbRelocs)
255{
256 /*
257 * Iterate the relocations.
258 * The relocations are stored in an array of Elf32_Rel records and covers the entire relocation section.
259 */
260 const Elf_Reloc *paRels = (const Elf_Reloc *)pvRelocs;
261 const unsigned iRelMax = (unsigned)(cbRelocs / sizeof(paRels[0]));
262 AssertMsgReturn(iRelMax == cbRelocs / sizeof(paRels[0]), (FMT_ELF_SIZE "\n", cbRelocs / sizeof(paRels[0])), VERR_IMAGE_TOO_BIG);
263 for (unsigned iRel = 0; iRel < iRelMax; iRel++)
264 {
265 /*
266 * Get the symbol.
267 */
268 const Elf_Sym *pSym;
269 Elf_Addr SymValue = 0; /* shut up gcc-4 */
270 int rc = RTLDRELF_NAME(Symbol)(pModElf, BaseAddr, pfnGetImport, pvUser, ELF_R_SYM(paRels[iRel].r_info), &pSym, &SymValue);
271 if (RT_FAILURE(rc))
272 return rc;
273
274 Log3(("rtldrELF: " FMT_ELF_ADDR " %02x %06x - " FMT_ELF_ADDR " %3d %02x %s\n",
275 paRels[iRel].r_offset, ELF_R_TYPE(paRels[iRel].r_info), (unsigned)ELF_R_SYM(paRels[iRel].r_info),
276 SymValue, (unsigned)pSym->st_shndx, pSym->st_info, ELF_STR(pModElf, pSym->st_name)));
277
278 /*
279 * Apply the fixup.
280 */
281 AssertMsgReturn(paRels[iRel].r_offset < cbSec, (FMT_ELF_ADDR " " FMT_ELF_SIZE "\n", paRels[iRel].r_offset, cbSec), VERR_LDRELF_INVALID_RELOCATION_OFFSET);
282#if ELF_MODE == 32
283 const Elf_Addr *pAddrR = (const Elf_Addr *)(pu8SecBaseR + paRels[iRel].r_offset); /* Where to read the addend. */
284#endif
285 Elf_Addr *pAddrW = (Elf_Addr *)(pu8SecBaseW + paRels[iRel].r_offset); /* Where to write the fixup. */
286 switch (ELF_R_TYPE(paRels[iRel].r_info))
287 {
288#if ELF_MODE == 32
289 /*
290 * Absolute addressing.
291 */
292 case R_386_32:
293 {
294 const Elf_Addr Value = SymValue + *pAddrR;
295 *(uint32_t *)pAddrW = Value;
296 Log4((FMT_ELF_ADDR": R_386_32 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
297 SecAddr + paRels[iRel].r_offset + BaseAddr, Value, SymValue));
298 break;
299 }
300
301 /*
302 * PC relative addressing.
303 */
304 case R_386_PC32:
305 {
306 const Elf_Addr SourceAddr = SecAddr + paRels[iRel].r_offset + BaseAddr; /* Where the source really is. */
307 const Elf_Addr Value = SymValue + *(uint32_t *)pAddrR - SourceAddr;
308 *(uint32_t *)pAddrW = Value;
309 Log4((FMT_ELF_ADDR": R_386_PC32 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
310 SourceAddr, Value, SymValue));
311 break;
312 }
313
314 /* ignore */
315 case R_386_NONE:
316 break;
317
318#elif ELF_MODE == 64
319
320 /*
321 * Absolute addressing
322 */
323 case R_X86_64_64:
324 {
325 const Elf_Addr Value = SymValue + paRels[iRel].r_addend;
326 *(uint64_t *)pAddrW = Value;
327 Log4((FMT_ELF_ADDR": R_X86_64_64 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
328 SecAddr + paRels[iRel].r_offset + BaseAddr, Value, SymValue));
329 break;
330 }
331
332 /*
333 * Trunacated 32-bit value (zero-extendedable to the 64-bit value).
334 */
335 case R_X86_64_32:
336 {
337 const Elf_Addr Value = SymValue + paRels[iRel].r_addend;
338 *(uint32_t *)pAddrW = (uint32_t)Value;
339 Log4((FMT_ELF_ADDR": R_X86_64_32 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
340 SecAddr + paRels[iRel].r_offset + BaseAddr, Value, SymValue));
341 AssertMsgReturn((Elf_Addr)*(uint32_t *)pAddrW == Value, ("Value=" FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG);
342 break;
343 }
344
345 /*
346 * Truncated 32-bit value (sign-extendedable to the 64-bit value).
347 */
348 case R_X86_64_32S:
349 {
350 const Elf_Addr Value = SymValue + paRels[iRel].r_addend;
351 *(int32_t *)pAddrW = (int32_t)Value;
352 Log4((FMT_ELF_ADDR": R_X86_64_32S Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
353 SecAddr + paRels[iRel].r_offset + BaseAddr, Value, SymValue));
354 AssertMsgReturn((Elf_Addr)*(int32_t *)pAddrW == Value, ("Value=" FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG); /** @todo check the sign-extending here. */
355 break;
356 }
357
358 /*
359 * PC relative addressing.
360 */
361 case R_X86_64_PC32:
362 {
363 const Elf_Addr SourceAddr = SecAddr + paRels[iRel].r_offset + BaseAddr; /* Where the source really is. */
364 const Elf_Addr Value = SymValue + paRels[iRel].r_addend - SourceAddr;
365 *(int32_t *)pAddrW = (int32_t)Value;
366 Log4((FMT_ELF_ADDR": R_X86_64_PC32 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
367 SourceAddr, Value, SymValue));
368 AssertMsgReturn((Elf_Addr)*(int32_t *)pAddrW == Value, ("Value=" FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG); /** @todo check the sign-extending here. */
369 break;
370 }
371
372 /* ignore */
373 case R_X86_64_NONE:
374 break;
375#endif
376
377 default:
378 AssertMsgFailed(("Unknown relocation type: %d (iRel=%d iRelMax=%d)\n",
379 ELF_R_TYPE(paRels[iRel].r_info), iRel, iRelMax));
380 return VERR_LDRELF_RELOCATION_NOT_SUPPORTED;
381 }
382 }
383
384 return VINF_SUCCESS;
385}
386
387
388
389/** @copydoc RTLDROPS::pfnClose */
390static DECLCALLBACK(int) RTLDRELF_NAME(Close)(PRTLDRMODINTERNAL pMod)
391{
392 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
393
394 if (pModElf->paShdrs)
395 {
396 RTMemFree(pModElf->paShdrs);
397 pModElf->paShdrs = NULL;
398 }
399
400 if (pModElf->pReader)
401 {
402 pModElf->pReader->pfnDestroy(pModElf->pReader);
403 pModElf->pReader = NULL;
404 }
405
406 pModElf->pvBits = NULL;
407
408 return VINF_SUCCESS;
409}
410
411
412/** @copydoc RTLDROPS::Done */
413static DECLCALLBACK(int) RTLDRELF_NAME(Done)(PRTLDRMODINTERNAL pMod)
414{
415 //PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
416 /** @todo Have to think more about this .... */
417 return -1;
418}
419
420
421/** @copydoc RTLDROPS::EnumSymbols */
422static DECLCALLBACK(int) RTLDRELF_NAME(EnumSymbols)(PRTLDRMODINTERNAL pMod, unsigned fFlags, const void *pvBits, RTUINTPTR BaseAddress,
423 PFNRTLDRENUMSYMS pfnCallback, void *pvUser)
424{
425 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
426
427 /*
428 * Validate the input.
429 */
430 Elf_Addr BaseAddr = (Elf_Addr)BaseAddress;
431 AssertMsgReturn((RTUINTPTR)BaseAddr == BaseAddress, ("#RTptr", BaseAddress), VERR_IMAGE_BASE_TOO_HIGH);
432
433 /*
434 * Make sure we've got the string and symbol tables. (We don't need the pvBits.)
435 */
436 int rc = RTLDRELF_NAME(MapBits)(pModElf, false);
437 if (RT_FAILURE(rc))
438 return rc;
439
440 /*
441 * Enumerate the symbol table.
442 */
443 const Elf_Sym *paSyms = pModElf->paSyms;
444 unsigned cSyms = pModElf->cSyms;
445 for (unsigned iSym = 1; iSym < cSyms; iSym++)
446 {
447 /*
448 * Skip imports (undefined).
449 */
450 if (paSyms[iSym].st_shndx != SHN_UNDEF)
451 {
452 /*
453 * Calc value and get name.
454 */
455 Elf_Addr Value;
456 if (paSyms[iSym].st_shndx == SHN_ABS)
457 /* absolute symbols are not subject to any relocation. */
458 Value = paSyms[iSym].st_value;
459 else if (paSyms[iSym].st_shndx < pModElf->Ehdr.e_shnum)
460 /* relative to the section. */
461 Value = BaseAddr + paSyms[iSym].st_value + pModElf->paShdrs[paSyms[iSym].st_shndx].sh_addr;
462 else
463 {
464 AssertMsgFailed(("Arg! paSyms[%u].st_shndx=" FMT_ELF_HALF "\n", iSym, paSyms[iSym].st_shndx));
465 return VERR_BAD_EXE_FORMAT;
466 }
467 const char *pszName = ELF_STR(pModElf, paSyms[iSym].st_name);
468 if ( (pszName && *pszName)
469 && ( (fFlags & RTLDR_ENUM_SYMBOL_FLAGS_ALL)
470 || ELF_ST_BIND(paSyms[iSym].st_info) == STB_GLOBAL)
471 )
472 {
473 /*
474 * Call back.
475 */
476 AssertMsgReturn(Value == (RTUINTPTR)Value, (FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG);
477 int rc = pfnCallback(pMod, pszName, ~0, (RTUINTPTR)Value, pvUser);
478 if (rc)
479 return rc;
480 }
481 }
482 }
483
484 return VINF_SUCCESS;
485}
486
487
488/** @copydoc RTLDROPS::GetImageSize */
489static DECLCALLBACK(size_t) RTLDRELF_NAME(GetImageSize)(PRTLDRMODINTERNAL pMod)
490{
491 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
492
493 return pModElf->cbImage;
494}
495
496
497/** @copydoc RTLDROPS::GetBits */
498static DECLCALLBACK(int) RTLDRELF_NAME(GetBits)(PRTLDRMODINTERNAL pMod, void *pvBits, RTUINTPTR BaseAddress, PFNRTLDRIMPORT pfnGetImport, void *pvUser)
499{
500 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
501
502 /*
503 * Load the bits into pvBits.
504 */
505 const Elf_Shdr *paShdrs = pModElf->paShdrs;
506 for (unsigned iShdr = 0; iShdr < pModElf->Ehdr.e_shnum; iShdr++)
507 {
508 if (paShdrs[iShdr].sh_flags & SHF_ALLOC)
509 {
510 AssertMsgReturn((size_t)paShdrs[iShdr].sh_size == (size_t)paShdrs[iShdr].sh_size, (FMT_ELF_SIZE "\n", paShdrs[iShdr].sh_size), VERR_IMAGE_TOO_BIG);
511 switch (paShdrs[iShdr].sh_type)
512 {
513 case SHT_NOBITS:
514 memset((uint8_t *)pvBits + paShdrs[iShdr].sh_addr, 0, (size_t)paShdrs[iShdr].sh_size);
515 break;
516
517 case SHT_PROGBITS:
518 default:
519 {
520 int rc = pModElf->pReader->pfnRead(pModElf->pReader, (uint8_t *)pvBits + paShdrs[iShdr].sh_addr,
521 (size_t)paShdrs[iShdr].sh_size, paShdrs[iShdr].sh_offset);
522 if (RT_FAILURE(rc))
523 {
524 Log(("RTLdrELF: %s: Read error when reading " FMT_ELF_SIZE " bytes at " FMT_ELF_OFF ", iShdr=%d\n",
525 pModElf->pReader->pfnLogName(pModElf->pReader),
526 paShdrs[iShdr].sh_size, paShdrs[iShdr].sh_offset, iShdr));
527 return rc;
528 }
529 }
530 }
531 }
532 }
533
534 /*
535 * Relocate the image.
536 */
537 return pModElf->Core.pOps->pfnRelocate(pMod, pvBits, BaseAddress, ~(RTUINTPTR)0, pfnGetImport, pvUser);
538}
539
540
541/** @copydoc RTLDROPS::Relocate */
542static DECLCALLBACK(int) RTLDRELF_NAME(Relocate)(PRTLDRMODINTERNAL pMod, void *pvBits, RTUINTPTR NewBaseAddress, RTUINTPTR OldBaseAddress, PFNRTLDRIMPORT pfnGetImport, void *pvUser)
543{
544 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
545
546 /*
547 * Validate the input.
548 */
549 Elf_Addr BaseAddr = (Elf_Addr)NewBaseAddress;
550 AssertMsgReturn((RTUINTPTR)BaseAddr == NewBaseAddress, ("#RTptr", NewBaseAddress), VERR_IMAGE_BASE_TOO_HIGH);
551
552 /*
553 * Map the image bits if not already done and setup pointer into it.
554 */
555 int rc = RTLDRELF_NAME(MapBits)(pModElf, true);
556 if (RT_FAILURE(rc))
557 return rc;
558
559 /*
560 * Iterate the sections looking for interesting SHT_REL[A] sections.
561 * SHT_REL[A] sections have the section index of the section they contain fixups
562 * for in the sh_info member.
563 */
564 const Elf_Shdr *paShdrs = pModElf->paShdrs;
565#ifdef LOG_ENABLED
566 const char *pszLogName = pModElf->pReader->pfnLogName(pModElf->pReader);
567 Log2(("rtLdrElf: %s: Fixing up image\n", pszLogName));
568#endif
569 for (unsigned iShdr = 0; iShdr < pModElf->Ehdr.e_shnum; iShdr++)
570 {
571 const Elf_Shdr *pShdrRel = &paShdrs[iShdr];
572
573 /*
574 * Skip sections without interest to us.
575 */
576#if ELF_MODE == 32
577 if (pShdrRel->sh_type != SHT_REL)
578#else
579 if (pShdrRel->sh_type != SHT_RELA)
580#endif
581 continue;
582 if (pShdrRel->sh_info >= pModElf->Ehdr.e_shnum)
583 continue;
584 const Elf_Shdr *pShdr = &paShdrs[pShdrRel->sh_info]; /* the section to fixup. */
585 if (!(pShdr->sh_flags & SHF_ALLOC))
586 continue;
587
588 /*
589 * Relocate the section.
590 */
591 Log2(("rtldrELF: %s: Relocation records for #%d [%s] (sh_info=%d sh_link=%d) found in #%d [%s] (sh_info=%d sh_link=%d)\n",
592 pszLogName, (int)pShdrRel->sh_info, ELF_STR(pModElf, pShdr->sh_name), (int)pShdr->sh_info, (int)pShdr->sh_link,
593 iShdr, ELF_STR(pModElf, pShdrRel->sh_name), (int)pShdrRel->sh_info, (int)pShdrRel->sh_link));
594
595 /** @todo Make RelocateSection a function pointer so we can select the one corresponding to the machine when opening the image. */
596 rc = RTLDRELF_NAME(RelocateSection)(pModElf, BaseAddr, pfnGetImport, pvUser,
597 pShdr->sh_addr,
598 pShdr->sh_size,
599 (const uint8_t *)pModElf->pvBits + pShdr->sh_offset,
600 (uint8_t *)pvBits + pShdr->sh_addr,
601 (const uint8_t *)pModElf->pvBits + pShdrRel->sh_offset,
602 pShdrRel->sh_size);
603 if (RT_FAILURE(rc))
604 return rc;
605 }
606 return VINF_SUCCESS;
607}
608
609
610/** @copydoc RTLDROPS::pfnGetSymbolEx */
611static DECLCALLBACK(int) RTLDRELF_NAME(GetSymbolEx)(PRTLDRMODINTERNAL pMod, const void *pvBits, RTUINTPTR BaseAddress, const char *pszSymbol, RTUINTPTR *pValue)
612{
613 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
614 NOREF(pvBits);
615
616 /*
617 * Validate the input.
618 */
619 Elf_Addr BaseAddr = (Elf_Addr)BaseAddress;
620 AssertMsgReturn((RTUINTPTR)BaseAddr == BaseAddress, ("#RTptr", BaseAddress), VERR_IMAGE_BASE_TOO_HIGH);
621
622 /*
623 * Map the image bits if not already done and setup pointer into it.
624 */
625 int rc = RTLDRELF_NAME(MapBits)(pModElf, true);
626 if (RT_FAILURE(rc))
627 return rc;
628
629 /*
630 * Calc all kinds of pointers before we start iterating the symbol table.
631 */
632 const char *pStr = pModElf->pStr;
633 const Elf_Sym *paSyms = pModElf->paSyms;
634 unsigned cSyms = pModElf->cSyms;
635 for (unsigned iSym = 1; iSym < cSyms; iSym++)
636 {
637 /* Undefined symbols are not exports, they are imports. */
638 if ( paSyms[iSym].st_shndx != SHN_UNDEF
639 && ( ELF_ST_BIND(paSyms[iSym].st_info) == STB_GLOBAL
640 || ELF_ST_BIND(paSyms[iSym].st_info) == STB_WEAK))
641 {
642 /* Validate the name string and try match with it. */
643 if (paSyms[iSym].st_name < pModElf->cbStr)
644 {
645 if (!strcmp(pszSymbol, pStr + paSyms[iSym].st_name))
646 {
647 /* matched! */
648 Elf_Addr Value;
649 if (paSyms[iSym].st_shndx == SHN_ABS)
650 /* absolute symbols are not subject to any relocation. */
651 Value = paSyms[iSym].st_value;
652 else if (paSyms[iSym].st_shndx < pModElf->Ehdr.e_shnum)
653 /* relative to the section. */
654 Value = BaseAddr + paSyms[iSym].st_value + pModElf->paShdrs[paSyms[iSym].st_shndx].sh_addr;
655 else
656 {
657 AssertMsgFailed(("Arg. paSyms[iSym].st_shndx=%d\n", paSyms[iSym].st_shndx));
658 return VERR_BAD_EXE_FORMAT;
659 }
660 AssertMsgReturn(Value == (RTUINTPTR)Value, (FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG);
661 *pValue = (RTUINTPTR)Value;
662 return VINF_SUCCESS;
663 }
664 }
665 else
666 {
667 AssertMsgFailed(("String outside string table! iSym=%d paSyms[iSym].st_name=%#x\n", iSym, paSyms[iSym].st_name));
668 return VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET;
669 }
670 }
671 }
672
673 return VERR_SYMBOL_NOT_FOUND;
674}
675
676
677
678/**
679 * The ELF module operations.
680 */
681static RTLDROPS RTLDRELF_MID(s_rtldrElf,Ops) =
682{
683#if ELF_MODE == 32
684 "elf32",
685#elif ELF_MODE == 64
686 "elf64",
687#endif
688 RTLDRELF_NAME(Close),
689 NULL, /* Get Symbol */
690 RTLDRELF_NAME(Done),
691 RTLDRELF_NAME(EnumSymbols),
692 /* ext: */
693 RTLDRELF_NAME(GetImageSize),
694 RTLDRELF_NAME(GetBits),
695 RTLDRELF_NAME(Relocate),
696 RTLDRELF_NAME(GetSymbolEx),
697 0
698};
699
700
701
702/**
703 * Validates the ELF header.
704 *
705 * @returns iprt status code.
706 * @param pEhdr Pointer to the ELF header.
707 * @param pszLogName The log name.
708 * @param cbRawImage The size of the raw image.
709 */
710static int RTLDRELF_NAME(ValidateElfHeader)(const Elf_Ehdr *pEhdr, const char *pszLogName, uint64_t cbRawImage)
711{
712 Log3(("RTLdrELF: e_ident: %.*Rhxs\n"
713 "RTLdrELF: e_type: " FMT_ELF_HALF "\n"
714 "RTLdrELF: e_version: " FMT_ELF_HALF "\n"
715 "RTLdrELF: e_entry: " FMT_ELF_ADDR "\n"
716 "RTLdrELF: e_phoff: " FMT_ELF_OFF "\n"
717 "RTLdrELF: e_shoff: " FMT_ELF_OFF "\n"
718 "RTLdrELF: e_flags: " FMT_ELF_WORD "\n"
719 "RTLdrELF: e_ehsize: " FMT_ELF_HALF "\n"
720 "RTLdrELF: e_phentsize: " FMT_ELF_HALF "\n"
721 "RTLdrELF: e_phnum: " FMT_ELF_HALF "\n"
722 "RTLdrELF: e_shentsize: " FMT_ELF_HALF "\n"
723 "RTLdrELF: e_shnum: " FMT_ELF_HALF "\n"
724 "RTLdrELF: e_shstrndx: " FMT_ELF_HALF "\n",
725 ELEMENTS(pEhdr->e_ident), &pEhdr->e_ident[0], pEhdr->e_type, pEhdr->e_version,
726 pEhdr->e_entry, pEhdr->e_phoff, pEhdr->e_shoff,pEhdr->e_flags, pEhdr->e_ehsize, pEhdr->e_phentsize,
727 pEhdr->e_phnum, pEhdr->e_shentsize, pEhdr->e_shnum, pEhdr->e_shstrndx));
728
729 if ( pEhdr->e_ident[EI_MAG0] != ELFMAG0
730 || pEhdr->e_ident[EI_MAG1] != ELFMAG1
731 || pEhdr->e_ident[EI_MAG2] != ELFMAG2
732 || pEhdr->e_ident[EI_MAG3] != ELFMAG3
733 )
734 {
735 Log(("RTLdrELF: %s: Invalid ELF magic (%.*Rhxs)\n", pszLogName, sizeof(pEhdr->e_ident), pEhdr->e_ident));
736 return VERR_BAD_EXE_FORMAT;
737 }
738 if (pEhdr->e_ident[EI_CLASS] != RTLDRELF_SUFF(ELFCLASS))
739 {
740 Log(("RTLdrELF: %s: Invalid ELF class (%.*Rhxs)\n", pszLogName, sizeof(pEhdr->e_ident), pEhdr->e_ident));
741 return VERR_BAD_EXE_FORMAT;
742 }
743 if (pEhdr->e_ident[EI_DATA] != ELFDATA2LSB)
744 {
745 Log(("RTLdrELF: %s: ELF endian %x is unsupported\n", pEhdr->e_ident[EI_DATA]));
746 return VERR_LDRELF_ODD_ENDIAN;
747 }
748 if (pEhdr->e_version != EV_CURRENT)
749 {
750 Log(("RTLdrELF: %s: ELF version %x is unsupported\n", pEhdr->e_version));
751 return VERR_LDRELF_VERSION;
752 }
753
754 if (sizeof(Elf_Ehdr) != pEhdr->e_ehsize)
755 {
756 Log(("RTLdrELF: %s: Elf header e_ehsize is %d expected %d!\n",
757 pszLogName, pEhdr->e_ehsize, sizeof(Elf_Ehdr)));
758 return VERR_BAD_EXE_FORMAT;
759 }
760 if ( sizeof(Elf_Phdr) != pEhdr->e_phentsize
761 && ( pEhdr->e_phnum != 0
762 || pEhdr->e_type == ET_DYN))
763 {
764 Log(("RTLdrELF: %s: Elf header e_phentsize is %d expected %d!\n",
765 pszLogName, pEhdr->e_phentsize, sizeof(Elf_Phdr)));
766 return VERR_BAD_EXE_FORMAT;
767 }
768 if (sizeof(Elf_Shdr) != pEhdr->e_shentsize)
769 {
770 Log(("RTLdrELF: %s: Elf header e_shentsize is %d expected %d!\n",
771 pszLogName, pEhdr->e_shentsize, sizeof(Elf_Shdr)));
772 return VERR_BAD_EXE_FORMAT;
773 }
774
775 switch (pEhdr->e_type)
776 {
777 case ET_REL:
778 break;
779 case ET_EXEC:
780 Log(("RTLdrELF: %s: Executable images are not supported yet!\n", pszLogName));
781 return VERR_LDRELF_EXEC;
782 case ET_DYN:
783 Log(("RTLdrELF: %s: Dynamic images are not supported yet!\n", pszLogName));
784 return VERR_LDRELF_DYN;
785 default:
786 Log(("RTLdrELF: %s: image type %#x is not supported!\n", pszLogName, pEhdr->e_type));
787 return VERR_BAD_EXE_FORMAT;
788 }
789
790 switch (pEhdr->e_machine)
791 {
792#if ELF_MODE == 32
793 case EM_386:
794 case EM_486:
795#elif ELF_MODE == 64
796 case EM_X86_64:
797#endif
798 break;
799 default:
800 Log(("RTLdrELF: %s: machine type %u is not supported!\n", pEhdr->e_machine));
801 return VERR_LDRELF_MACHINE;
802 }
803
804 if ( pEhdr->e_phoff < pEhdr->e_ehsize
805 && !(pEhdr->e_phoff && pEhdr->e_phnum)
806 && pEhdr->e_phnum)
807 {
808 Log(("RTLdrELF: %s: The program headers overlap with the ELF header! e_phoff=" FMT_ELF_OFF "\n",
809 pszLogName, pEhdr->e_phoff));
810 return VERR_BAD_EXE_FORMAT;
811 }
812 if ( pEhdr->e_phoff + pEhdr->e_phnum * pEhdr->e_phentsize > cbRawImage
813 || pEhdr->e_phoff + pEhdr->e_phnum * pEhdr->e_phentsize < pEhdr->e_phoff)
814 {
815 Log(("RTLdrELF: %s: The program headers extends beyond the file! e_phoff=" FMT_ELF_OFF " e_phnum=" FMT_ELF_HALF "\n",
816 pszLogName, pEhdr->e_phoff, pEhdr->e_phnum));
817 return VERR_BAD_EXE_FORMAT;
818 }
819
820
821 if ( pEhdr->e_shoff < pEhdr->e_ehsize
822 && !(pEhdr->e_shoff && pEhdr->e_shnum))
823 {
824 Log(("RTLdrELF: %s: The section headers overlap with the ELF header! e_shoff=" FMT_ELF_OFF "\n",
825 pszLogName, pEhdr->e_shoff));
826 return VERR_BAD_EXE_FORMAT;
827 }
828 if ( pEhdr->e_shoff + pEhdr->e_shnum * pEhdr->e_shentsize > cbRawImage
829 || pEhdr->e_shoff + pEhdr->e_shnum * pEhdr->e_shentsize < pEhdr->e_shoff)
830 {
831 Log(("RTLdrELF: %s: The section headers extends beyond the file! e_shoff=" FMT_ELF_OFF " e_shnum=" FMT_ELF_HALF "\n",
832 pszLogName, pEhdr->e_shoff, pEhdr->e_shnum));
833 return VERR_BAD_EXE_FORMAT;
834 }
835
836 return VINF_SUCCESS;
837}
838
839/**
840 * Gets the section header name.
841 *
842 * @returns pszName.
843 * @param pReader The loader reader instance.
844 * @param pEhdr The elf header.
845 * @param offName The offset of the section header name.
846 * @param pszName Where to store the name.
847 * @param cbName The size of the buffer pointed to by pszName.
848 */
849const char *RTLDRELF_NAME(GetSHdrName)(PRTLDRMODELF pModElf, Elf_Word offName, char *pszName, size_t cbName)
850{
851 RTFOFF off = pModElf->paShdrs[pModElf->Ehdr.e_shstrndx].sh_offset + offName;
852 int rc = pModElf->pReader->pfnRead(pModElf->pReader, pszName, cbName - 1, off);
853 if (RT_FAILURE(rc))
854 {
855 /* read by for byte. */
856 for (unsigned i = 0; i < cbName; i++, off++)
857 {
858 int rc = pModElf->pReader->pfnRead(pModElf->pReader, pszName + i, 1, off);
859 if (RT_FAILURE(rc))
860 {
861 pszName[i] = '\0';
862 break;
863 }
864 }
865 }
866
867 pszName[cbName - 1] = '\0';
868 return pszName;
869}
870
871
872/**
873 * Validates a section header.
874 *
875 * @returns iprt status code.
876 * @param pModElf Pointer to the module structure.
877 * @param iShdr The index of section header which should be validated.
878 * The section headers are found in the pModElf->paShdrs array.
879 * @param pszLogName The log name.
880 * @param cbRawImage The size of the raw image.
881 */
882static int RTLDRELF_NAME(ValidateSectionHeader)(PRTLDRMODELF pModElf, unsigned iShdr, const char *pszLogName, RTFOFF cbRawImage)
883{
884 const Elf_Shdr *pShdr = &pModElf->paShdrs[iShdr];
885 char szSectionName[80]; NOREF(szSectionName);
886 Log3(("RTLdrELF: Section Header #%d:\n"
887 "RTLdrELF: sh_name: " FMT_ELF_WORD " - %s\n"
888 "RTLdrELF: sh_type: " FMT_ELF_WORD " (%s)\n"
889 "RTLdrELF: sh_flags: " FMT_ELF_XWORD "\n"
890 "RTLdrELF: sh_addr: " FMT_ELF_ADDR "\n"
891 "RTLdrELF: sh_offset: " FMT_ELF_OFF "\n"
892 "RTLdrELF: sh_size: " FMT_ELF_XWORD "\n"
893 "RTLdrELF: sh_link: " FMT_ELF_WORD "\n"
894 "RTLdrELF: sh_info: " FMT_ELF_WORD "\n"
895 "RTLdrELF: sh_addralign: " FMT_ELF_XWORD "\n"
896 "RTLdrELF: sh_entsize: " FMT_ELF_XWORD "\n",
897 iShdr,
898 pShdr->sh_name, RTLDRELF_NAME(GetSHdrName)(pModElf, pShdr->sh_name, szSectionName, sizeof(szSectionName)),
899 pShdr->sh_type, rtldrElfGetShdrType(pShdr->sh_type), pShdr->sh_flags, pShdr->sh_addr,
900 pShdr->sh_offset, pShdr->sh_size, pShdr->sh_link, pShdr->sh_info, pShdr->sh_addralign,
901 pShdr->sh_entsize));
902
903 if (pShdr->sh_link >= pModElf->Ehdr.e_shnum)
904 {
905 Log(("RTLdrELF: %s: Shdr #%d: sh_link (%d) is beyond the end of the section table (%d)!\n",
906 pszLogName, iShdr, pShdr->sh_link, pModElf->Ehdr.e_shnum));
907 return VERR_BAD_EXE_FORMAT;
908 }
909
910 switch (pShdr->sh_type)
911 {
912 /** @todo find specs and check up which sh_info fields indicates section table entries */
913 case 12301230:
914 if (pShdr->sh_info >= pModElf->Ehdr.e_shnum)
915 {
916 Log(("RTLdrELF: %s: Shdr #%d: sh_info (%d) is beyond the end of the section table (%d)!\n",
917 pszLogName, iShdr, pShdr->sh_link, pModElf->Ehdr.e_shnum));
918 return VERR_BAD_EXE_FORMAT;
919 }
920 break;
921
922 case SHT_NULL:
923 case SHT_PROGBITS:
924 case SHT_SYMTAB:
925 case SHT_STRTAB:
926 case SHT_RELA:
927 case SHT_HASH:
928 case SHT_DYNAMIC:
929 case SHT_NOTE:
930 case SHT_NOBITS:
931 case SHT_REL:
932 case SHT_SHLIB:
933 case SHT_DYNSYM:
934 /*
935 * For these types sh_info doesn't have any special meaning, or anything which
936 * we need/can validate now.
937 */
938 break;
939
940
941 default:
942 Log(("RTLdrELF: %s: Warning, unknown type %d!\n", pszLogName, pShdr->sh_type));
943 break;
944 }
945
946 if ( pShdr->sh_type != SHT_NOBITS
947 && pShdr->sh_size)
948 {
949 RTFOFF offEnd = pShdr->sh_offset + pShdr->sh_size;
950 if ( offEnd > cbRawImage
951 || offEnd < (RTFOFF)pShdr->sh_offset)
952 {
953 Log(("RTLdrELF: %s: Shdr #%d: sh_offset (" FMT_ELF_OFF ") + sh_size (" FMT_ELF_XWORD " = %RTfoff) is beyond the end of the file (%RTfoff)!\n",
954 pszLogName, iShdr, pShdr->sh_offset, pShdr->sh_size, offEnd, cbRawImage));
955 return VERR_BAD_EXE_FORMAT;
956 }
957 if (pShdr->sh_offset < sizeof(Elf_Ehdr))
958 {
959 Log(("RTLdrELF: %s: Shdr #%d: sh_offset (" FMT_ELF_OFF ") + sh_size (" FMT_ELF_XWORD ") is starting in the ELF header!\n",
960 pszLogName, iShdr, pShdr->sh_offset, pShdr->sh_size, cbRawImage));
961 return VERR_BAD_EXE_FORMAT;
962 }
963 }
964
965 return VINF_SUCCESS;
966}
967
968
969
970/**
971 * Opens an ELF image, fixed bitness.
972 *
973 * @returns iprt status code.
974 * @param pReader The loader reader instance which will provide the raw image bits.
975 * @param phLdrMod Where to store the handle.
976 */
977static int RTLDRELF_NAME(Open)(PRTLDRREADER pReader, PRTLDRMOD phLdrMod)
978{
979 const char *pszLogName = pReader->pfnLogName(pReader);
980 RTFOFF cbRawImage = pReader->pfnSize(pReader);
981
982 /*
983 * Create the loader module instance.
984 */
985 PRTLDRMODELF pModElf = (PRTLDRMODELF)RTMemAllocZ(sizeof(*pModElf));
986 if (!pModElf)
987 return VERR_NO_MEMORY;
988
989 pModElf->Core.u32Magic = RTLDRMOD_MAGIC;
990 pModElf->Core.eState = LDR_STATE_INVALID;
991 pModElf->pReader = pReader;
992 //pModElf->pvBits = NULL;
993 //pModElf->Ehdr = {0};
994 //pModElf->paShdrs = NULL;
995 //pModElf->paSyms = NULL;
996 pModElf->iSymSh = ~0U;
997 pModElf->cSyms = 0;
998 pModElf->iStrSh = ~0U;
999 pModElf->cbStr = 0;
1000 pModElf->cbImage = 0;
1001 //pModElf->pStr = NULL;
1002
1003 /*
1004 * Read and validate the ELF header.
1005 */
1006 int rc = pReader->pfnRead(pReader, &pModElf->Ehdr, sizeof(pModElf->Ehdr), 0);
1007 if (RT_SUCCESS(rc))
1008 rc = RTLDRELF_NAME(ValidateElfHeader)(&pModElf->Ehdr, pszLogName, cbRawImage);
1009 if (RT_SUCCESS(rc))
1010 {
1011 /*
1012 * Read the section headers.
1013 */
1014 Elf_Shdr *paShdrs = (Elf_Shdr *)RTMemAlloc(pModElf->Ehdr.e_shnum * sizeof(Elf_Shdr));
1015 if (paShdrs)
1016 {
1017 pModElf->paShdrs = paShdrs;
1018 rc = pReader->pfnRead(pReader, paShdrs, pModElf->Ehdr.e_shnum * sizeof(Elf_Shdr),
1019 pModElf->Ehdr.e_shoff);
1020 if (RT_SUCCESS(rc))
1021 {
1022 /*
1023 * Validate the section headers, allocate memory for the sections (determin the image size),
1024 * and find relevant sections.
1025 */
1026 for (unsigned i = 0; i < pModElf->Ehdr.e_shnum; i++)
1027 {
1028 rc = RTLDRELF_NAME(ValidateSectionHeader)(pModElf, i, pszLogName, cbRawImage);
1029 if (RT_FAILURE(rc))
1030 break;
1031
1032 /* Allocate memory addresses for the section. */
1033 if (paShdrs[i].sh_flags & SHF_ALLOC)
1034 {
1035 paShdrs[i].sh_addr = paShdrs[i].sh_addralign
1036 ? RT_ALIGN_T(pModElf->cbImage, paShdrs[i].sh_addralign, Elf_Addr)
1037 : pModElf->cbImage;
1038 pModElf->cbImage = (size_t)paShdrs[i].sh_addr + (size_t)paShdrs[i].sh_size;
1039 AssertMsgReturn(pModElf->cbImage == paShdrs[i].sh_addr + paShdrs[i].sh_size,
1040 (FMT_ELF_ADDR "\n", paShdrs[i].sh_addr + paShdrs[i].sh_size),
1041 VERR_IMAGE_TOO_BIG);
1042 Log2(("RTLdrElf: %s: Assigned " FMT_ELF_ADDR " to section #%d\n", pszLogName, paShdrs[i].sh_addr, i));
1043 }
1044
1045 /* We're looking for symbol tables. */
1046 if (paShdrs[i].sh_type == SHT_SYMTAB)
1047 {
1048 if (pModElf->iSymSh != ~0U)
1049 {
1050 Log(("RTLdrElf: %s: Multiple symbol tabs! iSymSh=%d i=%d\n", pszLogName, pModElf->iSymSh, i));
1051 rc = VERR_LDRELF_MULTIPLE_SYMTABS;
1052 break;
1053 }
1054 pModElf->iSymSh = i;
1055 pModElf->cSyms = (unsigned)(paShdrs[i].sh_size / sizeof(Elf_Sym));
1056 AssertReturn(pModElf->cSyms == paShdrs[i].sh_size / sizeof(Elf_Sym), VERR_IMAGE_TOO_BIG);
1057 pModElf->iStrSh = paShdrs[i].sh_link;
1058 pModElf->cbStr = (unsigned)paShdrs[pModElf->iStrSh].sh_size;
1059 AssertReturn(pModElf->cbStr == paShdrs[pModElf->iStrSh].sh_size, VERR_IMAGE_TOO_BIG);
1060 }
1061 } /* for each section header */
1062
1063 Log2(("RTLdrElf: iSymSh=%u cSyms=%u iStrSh=%u cbStr=%u rc=%Rrc cbImage=%#zx\n",
1064 pModElf->iSymSh, pModElf->cSyms, pModElf->iStrSh, pModElf->cbStr, rc, pModElf->cbImage));
1065
1066 /*
1067 * Are the section headers fine?
1068 * We require there to be symbol & string tables (at least for the time being).
1069 */
1070 if ( pModElf->iSymSh == ~0U
1071 || pModElf->iStrSh == ~0U)
1072 rc = VERR_LDRELF_NO_SYMBOL_OR_NO_STRING_TABS;
1073 if (RT_SUCCESS(rc))
1074 {
1075 pModElf->Core.pOps = &RTLDRELF_MID(s_rtldrElf,Ops);
1076 pModElf->Core.eState = LDR_STATE_OPENED;
1077 *phLdrMod = &pModElf->Core;
1078
1079 LogFlow(("%s: %s: returns VINF_SUCCESS *phLdrMod=%p\n", __FUNCTION__, pszLogName, *phLdrMod));
1080 return VINF_SUCCESS;
1081 }
1082 }
1083
1084 RTMemFree(paShdrs);
1085 }
1086 else
1087 rc = VERR_NO_MEMORY;
1088 }
1089
1090 RTMemFree(pModElf);
1091 LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
1092 return rc;
1093}
1094
1095
1096
1097
1098/*******************************************************************************
1099* Cleanup Constants And Macros *
1100*******************************************************************************/
1101#undef RTLDRELF_NAME
1102#undef RTLDRELF_SUFF
1103#undef RTLDRELF_MID
1104
1105#undef FMT_ELF_ADDR
1106#undef FMT_ELF_HALF
1107#undef FMT_ELF_SHALF
1108#undef FMT_ELF_OFF
1109#undef FMT_ELF_SIZE
1110#undef FMT_ELF_SWORD
1111#undef FMT_ELF_WORD
1112#undef FMT_ELF_XWORD
1113#undef FMT_ELF_SXWORD
1114
1115#undef Elf_Ehdr
1116#undef Elf_Phdr
1117#undef Elf_Shdr
1118#undef Elf_Sym
1119#undef Elf_Rel
1120#undef Elf_Rela
1121#undef Elf_Reloc
1122#undef Elf_Nhdr
1123#undef Elf_Dyn
1124
1125#undef Elf_Addr
1126#undef Elf_Half
1127#undef Elf_Off
1128#undef Elf_Size
1129#undef Elf_Sword
1130#undef Elf_Word
1131
1132#undef RTLDRMODELF
1133#undef PRTLDRMODELF
1134
1135#undef ELF_R_SYM
1136#undef ELF_R_TYPE
1137#undef ELF_R_INFO
1138
1139#undef ELF_ST_BIND
1140
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