VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h@ 46050

Last change on this file since 46050 was 45994, checked in by vboxsync, 12 years ago

RTDbgModCreateFromPeImage: Mostly implemented.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 55.6 KB
Line 
1/* $Id: ldrELFRelocatable.cpp.h 45994 2013-05-12 19:16:16Z vboxsync $ */
2/** @file
3 * IPRT - Binary Image Loader, Template for ELF Relocatable Images.
4 */
5
6/*
7 * Copyright (C) 2006-2012 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 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*******************************************************************************
29* Defined Constants And Macros *
30*******************************************************************************/
31#if ELF_MODE == 32
32#define RTLDRELF_NAME(name) rtldrELF32##name
33#define RTLDRELF_SUFF(name) name##32
34#define RTLDRELF_MID(pre,suff) pre##32##suff
35#define FMT_ELF_ADDR "%08RX32"
36#define FMT_ELF_HALF "%04RX16"
37#define FMT_ELF_OFF "%08RX32"
38#define FMT_ELF_SIZE "%08RX32"
39#define FMT_ELF_SWORD "%RI32"
40#define FMT_ELF_WORD "%08RX32"
41#define FMT_ELF_XWORD "%08RX32"
42#define FMT_ELF_SXWORD "%RI32"
43
44#elif ELF_MODE == 64
45#define RTLDRELF_NAME(name) rtldrELF64##name
46#define RTLDRELF_SUFF(name) name##64
47#define RTLDRELF_MID(pre,suff) pre##64##suff
48#define FMT_ELF_ADDR "%016RX64"
49#define FMT_ELF_HALF "%04RX16"
50#define FMT_ELF_SHALF "%RI16"
51#define FMT_ELF_OFF "%016RX64"
52#define FMT_ELF_SIZE "%016RX64"
53#define FMT_ELF_SWORD "%RI32"
54#define FMT_ELF_WORD "%08RX32"
55#define FMT_ELF_XWORD "%016RX64"
56#define FMT_ELF_SXWORD "%RI64"
57#endif
58
59#define Elf_Ehdr RTLDRELF_MID(Elf,_Ehdr)
60#define Elf_Phdr RTLDRELF_MID(Elf,_Phdr)
61#define Elf_Shdr RTLDRELF_MID(Elf,_Shdr)
62#define Elf_Sym RTLDRELF_MID(Elf,_Sym)
63#define Elf_Rel RTLDRELF_MID(Elf,_Rel)
64#define Elf_Rela RTLDRELF_MID(Elf,_Rela)
65#define Elf_Nhdr RTLDRELF_MID(Elf,_Nhdr)
66#define Elf_Dyn RTLDRELF_MID(Elf,_Dyn)
67#define Elf_Addr RTLDRELF_MID(Elf,_Addr)
68#define Elf_Half RTLDRELF_MID(Elf,_Half)
69#define Elf_Off RTLDRELF_MID(Elf,_Off)
70#define Elf_Size RTLDRELF_MID(Elf,_Size)
71#define Elf_Sword RTLDRELF_MID(Elf,_Sword)
72#define Elf_Word RTLDRELF_MID(Elf,_Word)
73
74#define RTLDRMODELF RTLDRELF_MID(RTLDRMODELF,RT_NOTHING)
75#define PRTLDRMODELF RTLDRELF_MID(PRTLDRMODELF,RT_NOTHING)
76
77#define ELF_R_SYM(info) RTLDRELF_MID(ELF,_R_SYM)(info)
78#define ELF_R_TYPE(info) RTLDRELF_MID(ELF,_R_TYPE)(info)
79#define ELF_R_INFO(sym, type) RTLDRELF_MID(ELF,_R_INFO)(sym, type)
80
81#define ELF_ST_BIND(info) RTLDRELF_MID(ELF,_ST_BIND)(info)
82
83
84
85/*******************************************************************************
86* Structures and Typedefs *
87*******************************************************************************/
88/**
89 * The ELF loader structure.
90 */
91typedef struct RTLDRMODELF
92{
93 /** Core module structure. */
94 RTLDRMODINTERNAL Core;
95 /** Pointer to the reader instance. */
96 PRTLDRREADER pReader;
97 /** Pointer to readonly mapping of the image bits.
98 * This mapping is provided by the pReader. */
99 const void *pvBits;
100
101 /** The ELF header. */
102 Elf_Ehdr Ehdr;
103 /** Pointer to our copy of the section headers.
104 * The virtual addresses in this array is the 0 based assignments we've given the image.
105 * Not valid if the image is DONE. */
106 Elf_Shdr *paShdrs;
107 /** Unmodified section headers (allocated after paShdrs, so no need to free).
108 * Not valid if the image is DONE. */
109 Elf_Shdr const *paOrgShdrs;
110 /** The size of the loaded image. */
111 size_t cbImage;
112
113 /** The symbol section index. */
114 unsigned iSymSh;
115 /** Number of symbols in the table. */
116 unsigned cSyms;
117 /** Pointer to symbol table within RTLDRMODELF::pvBits. */
118 const Elf_Sym *paSyms;
119
120 /** The string section index. */
121 unsigned iStrSh;
122 /** Size of the string table. */
123 unsigned cbStr;
124 /** Pointer to string table within RTLDRMODELF::pvBits. */
125 const char *pStr;
126
127 /** Size of the section header string table. */
128 unsigned cbShStr;
129 /** Pointer to section header string table within RTLDRMODELF::pvBits. */
130 const char *pShStr;
131} RTLDRMODELF, *PRTLDRMODELF;
132
133
134/**
135 * Maps the image bits into memory and resolve pointers into it.
136 *
137 * @returns iprt status code.
138 * @param pModElf The ELF loader module instance data.
139 * @param fNeedsBits Set if we actually need the pvBits member.
140 * If we don't, we can simply read the string and symbol sections, thus saving memory.
141 */
142static int RTLDRELF_NAME(MapBits)(PRTLDRMODELF pModElf, bool fNeedsBits)
143{
144 NOREF(fNeedsBits);
145 if (pModElf->pvBits)
146 return VINF_SUCCESS;
147 int rc = pModElf->pReader->pfnMap(pModElf->pReader, &pModElf->pvBits);
148 if (RT_SUCCESS(rc))
149 {
150 const uint8_t *pu8 = (const uint8_t *)pModElf->pvBits;
151 if (pModElf->iSymSh != ~0U)
152 pModElf->paSyms = (const Elf_Sym *)(pu8 + pModElf->paShdrs[pModElf->iSymSh].sh_offset);
153 if (pModElf->iStrSh != ~0U)
154 pModElf->pStr = (const char *)(pu8 + pModElf->paShdrs[pModElf->iStrSh].sh_offset);
155 pModElf->pShStr = (const char *)(pu8 + pModElf->paShdrs[pModElf->Ehdr.e_shstrndx].sh_offset);
156 }
157 return rc;
158}
159
160
161/**
162 * Get the symbol and symbol value.
163 *
164 * @returns iprt status code.
165 * @param pModElf The ELF loader module instance data.
166 * @param BaseAddr The base address which the module is being fixedup to.
167 * @param pfnGetImport The callback function to use to resolve imports (aka unresolved externals).
168 * @param pvUser User argument to pass to the callback.
169 * @param iSym The symbol to get.
170 * @param ppSym Where to store the symbol pointer on success. (read only)
171 * @param pSymValue Where to store the symbol value on success.
172 */
173static int RTLDRELF_NAME(Symbol)(PRTLDRMODELF pModElf, Elf_Addr BaseAddr, PFNRTLDRIMPORT pfnGetImport, void *pvUser,
174 Elf_Size iSym, const Elf_Sym **ppSym, Elf_Addr *pSymValue)
175{
176 /*
177 * Validate and find the symbol.
178 */
179 if (iSym >= pModElf->cSyms)
180 {
181 AssertMsgFailed(("iSym=%d is an invalid symbol index!\n", iSym));
182 return VERR_LDRELF_INVALID_SYMBOL_INDEX;
183 }
184 const Elf_Sym *pSym = &pModElf->paSyms[iSym];
185 *ppSym = pSym;
186
187 if (pSym->st_name >= pModElf->cbStr)
188 {
189 AssertMsgFailed(("iSym=%d st_name=%d str sh_size=%d\n", iSym, pSym->st_name, pModElf->cbStr));
190 return VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET;
191 }
192 const char *pszName = ELF_STR(pModElf, pSym->st_name);
193
194 /*
195 * Determine the symbol value.
196 *
197 * Symbols needs different treatment depending on which section their are in.
198 * Undefined and absolute symbols goes into special non-existing sections.
199 */
200 switch (pSym->st_shndx)
201 {
202 /*
203 * Undefined symbol, needs resolving.
204 *
205 * Since ELF has no generic concept of importing from specific module (the OS/2 ELF format
206 * has but that's a OS extension and only applies to programs and dlls), we'll have to ask
207 * the resolver callback to do a global search.
208 */
209 case SHN_UNDEF:
210 {
211 /* Try to resolve the symbol. */
212 RTUINTPTR Value;
213 int rc = pfnGetImport(&pModElf->Core, "", pszName, ~0, &Value, pvUser);
214 if (RT_FAILURE(rc))
215 {
216 AssertMsgFailed(("Failed to resolve '%s' rc=%Rrc\n", pszName, rc));
217 return rc;
218 }
219 *pSymValue = (Elf_Addr)Value;
220 if ((RTUINTPTR)*pSymValue != Value)
221 {
222 AssertMsgFailed(("Symbol value overflowed! '%s'\n", pszName));
223 return VERR_SYMBOL_VALUE_TOO_BIG;
224 }
225
226 Log2(("rtldrELF: #%-3d - UNDEF " FMT_ELF_ADDR " '%s'\n", iSym, *pSymValue, pszName));
227 break;
228 }
229
230 /*
231 * Absolute symbols needs no fixing since they are, well, absolute.
232 */
233 case SHN_ABS:
234 *pSymValue = pSym->st_value;
235 Log2(("rtldrELF: #%-3d - ABS " FMT_ELF_ADDR " '%s'\n", iSym, *pSymValue, pszName));
236 break;
237
238 /*
239 * All other symbols are addressed relative to their section and need to be fixed up.
240 */
241 default:
242 if (pSym->st_shndx >= pModElf->Ehdr.e_shnum)
243 {
244 /* what about common symbols? */
245 AssertMsg(pSym->st_shndx < pModElf->Ehdr.e_shnum,
246 ("iSym=%d st_shndx=%d e_shnum=%d pszName=%s\n", iSym, pSym->st_shndx, pModElf->Ehdr.e_shnum, pszName));
247 return VERR_BAD_EXE_FORMAT;
248 }
249 *pSymValue = pSym->st_value + pModElf->paShdrs[pSym->st_shndx].sh_addr + BaseAddr;
250 Log2(("rtldrELF: #%-3d - %5d " FMT_ELF_ADDR " '%s'\n", iSym, pSym->st_shndx, *pSymValue, pszName));
251 break;
252 }
253
254 return VINF_SUCCESS;
255}
256
257
258/**
259 * Applies the fixups for a sections.
260 *
261 * @returns iprt status code.
262 * @param pModElf The ELF loader module instance data.
263 * @param BaseAddr The base address which the module is being fixedup to.
264 * @param pfnGetImport The callback function to use to resolve imports (aka unresolved externals).
265 * @param pvUser User argument to pass to the callback.
266 * @param SecAddr The section address. This is the address the relocations are relative to.
267 * @param cbSec The section size. The relocations must be inside this.
268 * @param pu8SecBaseR Where we read section bits from.
269 * @param pu8SecBaseW Where we write section bits to.
270 * @param pvRelocs Pointer to where we read the relocations from.
271 * @param cbRelocs Size of the relocations.
272 */
273static int RTLDRELF_NAME(RelocateSection)(PRTLDRMODELF pModElf, Elf_Addr BaseAddr, PFNRTLDRIMPORT pfnGetImport, void *pvUser,
274 const Elf_Addr SecAddr, Elf_Size cbSec, const uint8_t *pu8SecBaseR, uint8_t *pu8SecBaseW,
275 const void *pvRelocs, Elf_Size cbRelocs)
276{
277#if ELF_MODE != 32
278 NOREF(pu8SecBaseR);
279#endif
280
281 /*
282 * Iterate the relocations.
283 * The relocations are stored in an array of Elf32_Rel records and covers the entire relocation section.
284 */
285 const Elf_Reloc *paRels = (const Elf_Reloc *)pvRelocs;
286 const unsigned iRelMax = (unsigned)(cbRelocs / sizeof(paRels[0]));
287 AssertMsgReturn(iRelMax == cbRelocs / sizeof(paRels[0]), (FMT_ELF_SIZE "\n", cbRelocs / sizeof(paRels[0])), VERR_IMAGE_TOO_BIG);
288 for (unsigned iRel = 0; iRel < iRelMax; iRel++)
289 {
290 /*
291 * Get the symbol.
292 */
293 const Elf_Sym *pSym = NULL; /* shut up gcc */
294 Elf_Addr SymValue = 0; /* shut up gcc-4 */
295 int rc = RTLDRELF_NAME(Symbol)(pModElf, BaseAddr, pfnGetImport, pvUser, ELF_R_SYM(paRels[iRel].r_info), &pSym, &SymValue);
296 if (RT_FAILURE(rc))
297 return rc;
298
299 Log3(("rtldrELF: " FMT_ELF_ADDR " %02x %06x - " FMT_ELF_ADDR " %3d %02x %s\n",
300 paRels[iRel].r_offset, ELF_R_TYPE(paRels[iRel].r_info), (unsigned)ELF_R_SYM(paRels[iRel].r_info),
301 SymValue, (unsigned)pSym->st_shndx, pSym->st_info, ELF_STR(pModElf, pSym->st_name)));
302
303 /*
304 * Apply the fixup.
305 */
306 AssertMsgReturn(paRels[iRel].r_offset < cbSec, (FMT_ELF_ADDR " " FMT_ELF_SIZE "\n", paRels[iRel].r_offset, cbSec), VERR_LDRELF_INVALID_RELOCATION_OFFSET);
307#if ELF_MODE == 32
308 const Elf_Addr *pAddrR = (const Elf_Addr *)(pu8SecBaseR + paRels[iRel].r_offset); /* Where to read the addend. */
309#endif
310 Elf_Addr *pAddrW = (Elf_Addr *)(pu8SecBaseW + paRels[iRel].r_offset); /* Where to write the fixup. */
311 switch (ELF_R_TYPE(paRels[iRel].r_info))
312 {
313#if ELF_MODE == 32
314 /*
315 * Absolute addressing.
316 */
317 case R_386_32:
318 {
319 const Elf_Addr Value = SymValue + *pAddrR;
320 *(uint32_t *)pAddrW = Value;
321 Log4((FMT_ELF_ADDR": R_386_32 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
322 SecAddr + paRels[iRel].r_offset + BaseAddr, Value, SymValue));
323 break;
324 }
325
326 /*
327 * PC relative addressing.
328 */
329 case R_386_PC32:
330 {
331 const Elf_Addr SourceAddr = SecAddr + paRels[iRel].r_offset + BaseAddr; /* Where the source really is. */
332 const Elf_Addr Value = SymValue + *(uint32_t *)pAddrR - SourceAddr;
333 *(uint32_t *)pAddrW = Value;
334 Log4((FMT_ELF_ADDR": R_386_PC32 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
335 SourceAddr, Value, SymValue));
336 break;
337 }
338
339 /* ignore */
340 case R_386_NONE:
341 break;
342
343#elif ELF_MODE == 64
344
345 /*
346 * Absolute addressing
347 */
348 case R_X86_64_64:
349 {
350 const Elf_Addr Value = SymValue + paRels[iRel].r_addend;
351 *(uint64_t *)pAddrW = Value;
352 Log4((FMT_ELF_ADDR": R_X86_64_64 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
353 SecAddr + paRels[iRel].r_offset + BaseAddr, Value, SymValue));
354 break;
355 }
356
357 /*
358 * Truncated 32-bit value (zero-extendedable to the 64-bit value).
359 */
360 case R_X86_64_32:
361 {
362 const Elf_Addr Value = SymValue + paRels[iRel].r_addend;
363 *(uint32_t *)pAddrW = (uint32_t)Value;
364 Log4((FMT_ELF_ADDR": R_X86_64_32 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
365 SecAddr + paRels[iRel].r_offset + BaseAddr, Value, SymValue));
366 AssertMsgReturn((Elf_Addr)*(uint32_t *)pAddrW == Value, ("Value=" FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG);
367 break;
368 }
369
370 /*
371 * Truncated 32-bit value (sign-extendedable to the 64-bit value).
372 */
373 case R_X86_64_32S:
374 {
375 const Elf_Addr Value = SymValue + paRels[iRel].r_addend;
376 *(int32_t *)pAddrW = (int32_t)Value;
377 Log4((FMT_ELF_ADDR": R_X86_64_32S Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
378 SecAddr + paRels[iRel].r_offset + BaseAddr, Value, SymValue));
379 AssertMsgReturn((Elf_Addr)*(int32_t *)pAddrW == Value, ("Value=" FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG); /** @todo check the sign-extending here. */
380 break;
381 }
382
383 /*
384 * PC relative addressing.
385 */
386 case R_X86_64_PC32:
387 {
388 const Elf_Addr SourceAddr = SecAddr + paRels[iRel].r_offset + BaseAddr; /* Where the source really is. */
389 const Elf_Addr Value = SymValue + paRels[iRel].r_addend - SourceAddr;
390 *(int32_t *)pAddrW = (int32_t)Value;
391 Log4((FMT_ELF_ADDR": R_X86_64_PC32 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
392 SourceAddr, Value, SymValue));
393 AssertMsgReturn((Elf_Addr)*(int32_t *)pAddrW == Value, ("Value=" FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG); /** @todo check the sign-extending here. */
394 break;
395 }
396
397 /* ignore */
398 case R_X86_64_NONE:
399 break;
400#endif
401
402 default:
403 AssertMsgFailed(("Unknown relocation type: %d (iRel=%d iRelMax=%d)\n",
404 ELF_R_TYPE(paRels[iRel].r_info), iRel, iRelMax));
405 return VERR_LDRELF_RELOCATION_NOT_SUPPORTED;
406 }
407 }
408
409 return VINF_SUCCESS;
410}
411
412
413
414/** @copydoc RTLDROPS::pfnClose */
415static DECLCALLBACK(int) RTLDRELF_NAME(Close)(PRTLDRMODINTERNAL pMod)
416{
417 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
418
419 if (pModElf->paShdrs)
420 {
421 RTMemFree(pModElf->paShdrs);
422 pModElf->paShdrs = NULL;
423 }
424
425 if (pModElf->pReader)
426 {
427 pModElf->pReader->pfnDestroy(pModElf->pReader);
428 pModElf->pReader = NULL;
429 }
430
431 pModElf->pvBits = NULL;
432
433 return VINF_SUCCESS;
434}
435
436
437/** @copydoc RTLDROPS::Done */
438static DECLCALLBACK(int) RTLDRELF_NAME(Done)(PRTLDRMODINTERNAL pMod)
439{
440 NOREF(pMod); /*PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;*/
441 /** @todo Have to think more about this .... */
442 return -1;
443}
444
445
446/** @copydoc RTLDROPS::EnumSymbols */
447static DECLCALLBACK(int) RTLDRELF_NAME(EnumSymbols)(PRTLDRMODINTERNAL pMod, unsigned fFlags, const void *pvBits, RTUINTPTR BaseAddress,
448 PFNRTLDRENUMSYMS pfnCallback, void *pvUser)
449{
450 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
451 NOREF(pvBits);
452
453 /*
454 * Validate the input.
455 */
456 Elf_Addr BaseAddr = (Elf_Addr)BaseAddress;
457 AssertMsgReturn((RTUINTPTR)BaseAddr == BaseAddress, ("#RTptr", BaseAddress), VERR_IMAGE_BASE_TOO_HIGH);
458
459 /*
460 * Make sure we've got the string and symbol tables. (We don't need the pvBits.)
461 */
462 int rc = RTLDRELF_NAME(MapBits)(pModElf, false);
463 if (RT_FAILURE(rc))
464 return rc;
465
466 /*
467 * Enumerate the symbol table.
468 */
469 const Elf_Sym *paSyms = pModElf->paSyms;
470 unsigned cSyms = pModElf->cSyms;
471 for (unsigned iSym = 1; iSym < cSyms; iSym++)
472 {
473 /*
474 * Skip imports (undefined).
475 */
476 if (paSyms[iSym].st_shndx != SHN_UNDEF)
477 {
478 /*
479 * Calc value and get name.
480 */
481 Elf_Addr Value;
482 if (paSyms[iSym].st_shndx == SHN_ABS)
483 /* absolute symbols are not subject to any relocation. */
484 Value = paSyms[iSym].st_value;
485 else if (paSyms[iSym].st_shndx < pModElf->Ehdr.e_shnum)
486 /* relative to the section. */
487 Value = BaseAddr + paSyms[iSym].st_value + pModElf->paShdrs[paSyms[iSym].st_shndx].sh_addr;
488 else
489 {
490 AssertMsgFailed(("Arg! paSyms[%u].st_shndx=" FMT_ELF_HALF "\n", iSym, paSyms[iSym].st_shndx));
491 return VERR_BAD_EXE_FORMAT;
492 }
493 const char *pszName = ELF_STR(pModElf, paSyms[iSym].st_name);
494 if ( (pszName && *pszName)
495 && ( (fFlags & RTLDR_ENUM_SYMBOL_FLAGS_ALL)
496 || ELF_ST_BIND(paSyms[iSym].st_info) == STB_GLOBAL)
497 )
498 {
499 /*
500 * Call back.
501 */
502 AssertMsgReturn(Value == (RTUINTPTR)Value, (FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG);
503 rc = pfnCallback(pMod, pszName, ~0, (RTUINTPTR)Value, pvUser);
504 if (rc)
505 return rc;
506 }
507 }
508 }
509
510 return VINF_SUCCESS;
511}
512
513
514/** @copydoc RTLDROPS::GetImageSize */
515static DECLCALLBACK(size_t) RTLDRELF_NAME(GetImageSize)(PRTLDRMODINTERNAL pMod)
516{
517 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
518
519 return pModElf->cbImage;
520}
521
522
523/** @copydoc RTLDROPS::GetBits */
524static DECLCALLBACK(int) RTLDRELF_NAME(GetBits)(PRTLDRMODINTERNAL pMod, void *pvBits, RTUINTPTR BaseAddress, PFNRTLDRIMPORT pfnGetImport, void *pvUser)
525{
526 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
527
528 /*
529 * This operation is currently only available on relocatable images.
530 */
531 switch (pModElf->Ehdr.e_type)
532 {
533 case ET_REL:
534 break;
535 case ET_EXEC:
536 Log(("RTLdrELF: %s: Executable images are not supported yet!\n", pModElf->pReader->pfnLogName(pModElf->pReader)));
537 return VERR_LDRELF_EXEC;
538 case ET_DYN:
539 Log(("RTLdrELF: %s: Dynamic images are not supported yet!\n", pModElf->pReader->pfnLogName(pModElf->pReader)));
540 return VERR_LDRELF_DYN;
541 default: AssertFailedReturn(VERR_BAD_EXE_FORMAT);
542 }
543
544 /*
545 * Load the bits into pvBits.
546 */
547 const Elf_Shdr *paShdrs = pModElf->paShdrs;
548 for (unsigned iShdr = 0; iShdr < pModElf->Ehdr.e_shnum; iShdr++)
549 {
550 if (paShdrs[iShdr].sh_flags & SHF_ALLOC)
551 {
552 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);
553 switch (paShdrs[iShdr].sh_type)
554 {
555 case SHT_NOBITS:
556 memset((uint8_t *)pvBits + paShdrs[iShdr].sh_addr, 0, (size_t)paShdrs[iShdr].sh_size);
557 break;
558
559 case SHT_PROGBITS:
560 default:
561 {
562 int rc = pModElf->pReader->pfnRead(pModElf->pReader, (uint8_t *)pvBits + paShdrs[iShdr].sh_addr,
563 (size_t)paShdrs[iShdr].sh_size, paShdrs[iShdr].sh_offset);
564 if (RT_FAILURE(rc))
565 {
566 Log(("RTLdrELF: %s: Read error when reading " FMT_ELF_SIZE " bytes at " FMT_ELF_OFF ", iShdr=%d\n",
567 pModElf->pReader->pfnLogName(pModElf->pReader),
568 paShdrs[iShdr].sh_size, paShdrs[iShdr].sh_offset, iShdr));
569 return rc;
570 }
571 }
572 }
573 }
574 }
575
576 /*
577 * Relocate the image.
578 */
579 return pModElf->Core.pOps->pfnRelocate(pMod, pvBits, BaseAddress, ~(RTUINTPTR)0, pfnGetImport, pvUser);
580}
581
582
583/** @copydoc RTLDROPS::Relocate */
584static DECLCALLBACK(int) RTLDRELF_NAME(Relocate)(PRTLDRMODINTERNAL pMod, void *pvBits, RTUINTPTR NewBaseAddress,
585 RTUINTPTR OldBaseAddress, PFNRTLDRIMPORT pfnGetImport, void *pvUser)
586{
587 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
588#ifdef LOG_ENABLED
589 const char *pszLogName = pModElf->pReader->pfnLogName(pModElf->pReader);
590#endif
591 NOREF(OldBaseAddress);
592
593 /*
594 * This operation is currently only available on relocatable images.
595 */
596 switch (pModElf->Ehdr.e_type)
597 {
598 case ET_REL:
599 break;
600 case ET_EXEC:
601 Log(("RTLdrELF: %s: Executable images are not supported yet!\n", pszLogName));
602 return VERR_LDRELF_EXEC;
603 case ET_DYN:
604 Log(("RTLdrELF: %s: Dynamic images are not supported yet!\n", pszLogName));
605 return VERR_LDRELF_DYN;
606 default: AssertFailedReturn(VERR_BAD_EXE_FORMAT);
607 }
608
609 /*
610 * Validate the input.
611 */
612 Elf_Addr BaseAddr = (Elf_Addr)NewBaseAddress;
613 AssertMsgReturn((RTUINTPTR)BaseAddr == NewBaseAddress, ("#RTptr", NewBaseAddress), VERR_IMAGE_BASE_TOO_HIGH);
614
615 /*
616 * Map the image bits if not already done and setup pointer into it.
617 */
618 int rc = RTLDRELF_NAME(MapBits)(pModElf, true);
619 if (RT_FAILURE(rc))
620 return rc;
621
622 /*
623 * Iterate the sections looking for interesting SHT_REL[A] sections.
624 * SHT_REL[A] sections have the section index of the section they contain fixups
625 * for in the sh_info member.
626 */
627 const Elf_Shdr *paShdrs = pModElf->paShdrs;
628 Log2(("rtLdrElf: %s: Fixing up image\n", pszLogName));
629 for (unsigned iShdr = 0; iShdr < pModElf->Ehdr.e_shnum; iShdr++)
630 {
631 const Elf_Shdr *pShdrRel = &paShdrs[iShdr];
632
633 /*
634 * Skip sections without interest to us.
635 */
636#if ELF_MODE == 32
637 if (pShdrRel->sh_type != SHT_REL)
638#else
639 if (pShdrRel->sh_type != SHT_RELA)
640#endif
641 continue;
642 if (pShdrRel->sh_info >= pModElf->Ehdr.e_shnum)
643 continue;
644 const Elf_Shdr *pShdr = &paShdrs[pShdrRel->sh_info]; /* the section to fixup. */
645 if (!(pShdr->sh_flags & SHF_ALLOC))
646 continue;
647
648 /*
649 * Relocate the section.
650 */
651 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",
652 pszLogName, (int)pShdrRel->sh_info, ELF_SH_STR(pModElf, pShdr->sh_name), (int)pShdr->sh_info, (int)pShdr->sh_link,
653 iShdr, ELF_SH_STR(pModElf, pShdrRel->sh_name), (int)pShdrRel->sh_info, (int)pShdrRel->sh_link));
654
655 /** @todo Make RelocateSection a function pointer so we can select the one corresponding to the machine when opening the image. */
656 rc = RTLDRELF_NAME(RelocateSection)(pModElf, BaseAddr, pfnGetImport, pvUser,
657 pShdr->sh_addr,
658 pShdr->sh_size,
659 (const uint8_t *)pModElf->pvBits + pShdr->sh_offset,
660 (uint8_t *)pvBits + pShdr->sh_addr,
661 (const uint8_t *)pModElf->pvBits + pShdrRel->sh_offset,
662 pShdrRel->sh_size);
663 if (RT_FAILURE(rc))
664 return rc;
665 }
666 return VINF_SUCCESS;
667}
668
669
670/** @copydoc RTLDROPS::pfnGetSymbolEx */
671static DECLCALLBACK(int) RTLDRELF_NAME(GetSymbolEx)(PRTLDRMODINTERNAL pMod, const void *pvBits, RTUINTPTR BaseAddress, const char *pszSymbol, RTUINTPTR *pValue)
672{
673 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
674 NOREF(pvBits);
675
676 /*
677 * Validate the input.
678 */
679 Elf_Addr BaseAddr = (Elf_Addr)BaseAddress;
680 AssertMsgReturn((RTUINTPTR)BaseAddr == BaseAddress, ("#RTptr", BaseAddress), VERR_IMAGE_BASE_TOO_HIGH);
681
682 /*
683 * Map the image bits if not already done and setup pointer into it.
684 */
685 int rc = RTLDRELF_NAME(MapBits)(pModElf, true);
686 if (RT_FAILURE(rc))
687 return rc;
688
689 /*
690 * Calc all kinds of pointers before we start iterating the symbol table.
691 */
692 const char *pStr = pModElf->pStr;
693 const Elf_Sym *paSyms = pModElf->paSyms;
694 unsigned cSyms = pModElf->cSyms;
695 for (unsigned iSym = 1; iSym < cSyms; iSym++)
696 {
697 /* Undefined symbols are not exports, they are imports. */
698 if ( paSyms[iSym].st_shndx != SHN_UNDEF
699 && ( ELF_ST_BIND(paSyms[iSym].st_info) == STB_GLOBAL
700 || ELF_ST_BIND(paSyms[iSym].st_info) == STB_WEAK))
701 {
702 /* Validate the name string and try match with it. */
703 if (paSyms[iSym].st_name < pModElf->cbStr)
704 {
705 if (!strcmp(pszSymbol, pStr + paSyms[iSym].st_name))
706 {
707 /* matched! */
708 Elf_Addr Value;
709 if (paSyms[iSym].st_shndx == SHN_ABS)
710 /* absolute symbols are not subject to any relocation. */
711 Value = paSyms[iSym].st_value;
712 else if (paSyms[iSym].st_shndx < pModElf->Ehdr.e_shnum)
713 /* relative to the section. */
714 Value = BaseAddr + paSyms[iSym].st_value + pModElf->paShdrs[paSyms[iSym].st_shndx].sh_addr;
715 else
716 {
717 AssertMsgFailed(("Arg. paSyms[iSym].st_shndx=%d\n", paSyms[iSym].st_shndx));
718 return VERR_BAD_EXE_FORMAT;
719 }
720 AssertMsgReturn(Value == (RTUINTPTR)Value, (FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG);
721 *pValue = (RTUINTPTR)Value;
722 return VINF_SUCCESS;
723 }
724 }
725 else
726 {
727 AssertMsgFailed(("String outside string table! iSym=%d paSyms[iSym].st_name=%#x\n", iSym, paSyms[iSym].st_name));
728 return VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET;
729 }
730 }
731 }
732
733 return VERR_SYMBOL_NOT_FOUND;
734}
735
736
737/** @copydoc RTLDROPS::pfnEnumDbgInfo */
738static DECLCALLBACK(int) RTLDRELF_NAME(EnumDbgInfo)(PRTLDRMODINTERNAL pMod, const void *pvBits,
739 PFNRTLDRENUMDBG pfnCallback, void *pvUser)
740{
741 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
742
743 /*
744 * Map the image bits if not already done and setup pointer into it.
745 */
746 int rc = RTLDRELF_NAME(MapBits)(pModElf, true);
747 if (RT_FAILURE(rc))
748 return rc;
749
750 /*
751 * Do the enumeration.
752 */
753 const Elf_Shdr *paShdrs = pModElf->paOrgShdrs;
754 for (unsigned iShdr = 0; iShdr < pModElf->Ehdr.e_shnum; iShdr++)
755 {
756 /* Debug sections are expected to be PROGBITS and not allocated. */
757 if (paShdrs[iShdr].sh_type != SHT_PROGBITS)
758 continue;
759 if (paShdrs[iShdr].sh_flags & SHF_ALLOC)
760 continue;
761
762 RTLDRDBGINFO DbgInfo;
763 const char *pszSectName = ELF_SH_STR(pModElf, paShdrs[iShdr].sh_name);
764 if ( !strncmp(pszSectName, RT_STR_TUPLE(".debug_"))
765 || !strcmp(pszSectName, ".WATCOM_references") )
766 {
767 RT_ZERO(DbgInfo.u);
768 DbgInfo.enmType = RTLDRDBGINFOTYPE_DWARF;
769 DbgInfo.offFile = paShdrs[iShdr].sh_offset;
770 DbgInfo.cb = paShdrs[iShdr].sh_size;
771 DbgInfo.u.Dwarf.pszSection = pszSectName;
772 }
773 else if (!strcmp(pszSectName, ".gnu_debuglink"))
774 {
775 if ((paShdrs[iShdr].sh_size & 3) || paShdrs[iShdr].sh_size < 8)
776 return VERR_BAD_EXE_FORMAT;
777
778 RT_ZERO(DbgInfo.u);
779 DbgInfo.enmType = RTLDRDBGINFOTYPE_DWARF_DWO;
780 DbgInfo.pszExtFile = (const char *)((uintptr_t)pModElf->pvBits + paShdrs[iShdr].sh_offset);
781 if (!RTStrEnd(DbgInfo.pszExtFile, paShdrs[iShdr].sh_size))
782 return VERR_BAD_EXE_FORMAT;
783 DbgInfo.u.Dwo.uCrc32 = *(uint32_t *)((uintptr_t)DbgInfo.pszExtFile + paShdrs[iShdr].sh_size - sizeof(uint32_t));
784 DbgInfo.offFile = -1;
785 DbgInfo.cb = 0;
786 }
787 else
788 continue;
789
790 DbgInfo.LinkAddress = NIL_RTLDRADDR;
791 DbgInfo.iDbgInfo = iShdr - 1;
792
793 rc = pfnCallback(pMod, &DbgInfo, pvUser);
794 if (rc != VINF_SUCCESS)
795 return rc;
796
797 }
798
799 return VINF_SUCCESS;
800}
801
802
803/**
804 * Helper that locates the first allocated section.
805 *
806 * @returns Pointer to the section header if found, NULL if none.
807 * @param pShdr The section header to start searching at.
808 * @param cLeft The number of section headers left to search. Can be 0.
809 */
810static const Elf_Shdr *RTLDRELF_NAME(GetFirstAllocatedSection)(const Elf_Shdr *pShdr, unsigned cLeft)
811{
812 while (cLeft-- > 0)
813 {
814 if (pShdr->sh_flags & SHF_ALLOC)
815 return pShdr;
816 pShdr++;
817 }
818 return NULL;
819}
820
821/** @copydoc RTLDROPS::pfnEnumSegments. */
822static DECLCALLBACK(int) RTLDRELF_NAME(EnumSegments)(PRTLDRMODINTERNAL pMod, PFNRTLDRENUMSEGS pfnCallback, void *pvUser)
823{
824 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
825
826 /*
827 * Map the image bits if not already done and setup pointer into it.
828 */
829 int rc = RTLDRELF_NAME(MapBits)(pModElf, true);
830 if (RT_FAILURE(rc))
831 return rc;
832
833 /*
834 * Do the enumeration.
835 */
836 const Elf_Shdr *paShdrs = pModElf->paShdrs;
837 const Elf_Shdr *paOrgShdrs = pModElf->paOrgShdrs;
838 for (unsigned iShdr = 1; iShdr < pModElf->Ehdr.e_shnum; iShdr++)
839 {
840 RTLDRSEG Seg;
841 Seg.pchName = ELF_SH_STR(pModElf, paShdrs[iShdr].sh_name);
842 Seg.cchName = (uint32_t)strlen(Seg.pchName);
843 Seg.SelFlat = 0;
844 Seg.Sel16bit = 0;
845 Seg.fFlags = 0;
846 Seg.fProt = RTMEM_PROT_READ;
847 if (paShdrs[iShdr].sh_flags & SHF_WRITE)
848 Seg.fProt |= RTMEM_PROT_WRITE;
849 if (paShdrs[iShdr].sh_flags & SHF_EXECINSTR)
850 Seg.fProt |= RTMEM_PROT_EXEC;
851 Seg.cb = paShdrs[iShdr].sh_size;
852 Seg.Alignment = paShdrs[iShdr].sh_addralign;
853 if (paShdrs[iShdr].sh_flags & SHF_ALLOC)
854 {
855 Seg.LinkAddress = paOrgShdrs[iShdr].sh_addr;
856 Seg.RVA = paShdrs[iShdr].sh_addr;
857 const Elf_Shdr *pShdr2 = RTLDRELF_NAME(GetFirstAllocatedSection)(&paShdrs[iShdr + 1],
858 pModElf->Ehdr.e_shnum - iShdr - 1);
859 Seg.cbMapped = pShdr2 ? pShdr2->sh_addr - paShdrs[iShdr].sh_addr : paShdrs[iShdr].sh_size;
860 }
861 else
862 {
863 Seg.LinkAddress = NIL_RTLDRADDR;
864 Seg.RVA = NIL_RTLDRADDR;
865 Seg.cbMapped = NIL_RTLDRADDR;
866 }
867 if (paShdrs[iShdr].sh_type != SHT_NOBITS)
868 {
869 Seg.offFile = paShdrs[iShdr].sh_offset;
870 Seg.cbFile = paShdrs[iShdr].sh_size;
871 }
872 else
873 {
874 Seg.offFile = -1;
875 Seg.cbFile = 0;
876 }
877
878 rc = pfnCallback(pMod, &Seg, pvUser);
879 if (rc != VINF_SUCCESS)
880 return rc;
881 }
882
883 return VINF_SUCCESS;
884}
885
886
887/** @copydoc RTLDROPS::pfnLinkAddressToSegOffset. */
888static DECLCALLBACK(int) RTLDRELF_NAME(LinkAddressToSegOffset)(PRTLDRMODINTERNAL pMod, RTLDRADDR LinkAddress,
889 uint32_t *piSeg, PRTLDRADDR poffSeg)
890{
891 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
892
893 const Elf_Shdr *pShdrEnd = NULL;
894 unsigned cLeft = pModElf->Ehdr.e_shnum - 1;
895 const Elf_Shdr *pShdr = &pModElf->paOrgShdrs[cLeft];
896 while (cLeft-- > 0)
897 {
898 pShdr--;
899 if (pShdr->sh_flags & SHF_ALLOC)
900 {
901 RTLDRADDR offSeg = LinkAddress - pShdr->sh_addr;
902 if (offSeg < pShdr->sh_size)
903 {
904 *poffSeg = offSeg;
905 *piSeg = cLeft;
906 return VINF_SUCCESS;
907 }
908 if (offSeg == pShdr->sh_size)
909 pShdrEnd = pShdr;
910 }
911 }
912
913 if (pShdrEnd)
914 {
915 *poffSeg = pShdrEnd->sh_size;
916 *piSeg = pShdrEnd - pModElf->paOrgShdrs - 1;
917 return VINF_SUCCESS;
918 }
919
920 return VERR_LDR_INVALID_LINK_ADDRESS;
921}
922
923
924/** @copydoc RTLDROPS::pfnLinkAddressToRva. */
925static DECLCALLBACK(int) RTLDRELF_NAME(LinkAddressToRva)(PRTLDRMODINTERNAL pMod, RTLDRADDR LinkAddress, PRTLDRADDR pRva)
926{
927 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
928 uint32_t iSeg;
929 RTLDRADDR offSeg;
930 int rc = RTLDRELF_NAME(LinkAddressToSegOffset)(pMod, LinkAddress, &iSeg, &offSeg);
931 if (RT_SUCCESS(rc))
932 *pRva = pModElf->paShdrs[iSeg].sh_addr + offSeg;
933 return rc;
934}
935
936
937/** @copydoc RTLDROPS::pfnSegOffsetToRva. */
938static DECLCALLBACK(int) RTLDRELF_NAME(SegOffsetToRva)(PRTLDRMODINTERNAL pMod, uint32_t iSeg, RTLDRADDR offSeg,
939 PRTLDRADDR pRva)
940{
941 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
942 if (iSeg >= pModElf->Ehdr.e_shnum - 1U)
943 return VERR_LDR_INVALID_SEG_OFFSET;
944
945 iSeg++; /* skip section 0 */
946 if (offSeg > pModElf->paShdrs[iSeg].sh_size)
947 {
948 const Elf_Shdr *pShdr2 = RTLDRELF_NAME(GetFirstAllocatedSection)(&pModElf->paShdrs[iSeg + 1],
949 pModElf->Ehdr.e_shnum - iSeg - 1);
950 if ( !pShdr2
951 || offSeg > (pShdr2->sh_addr - pModElf->paShdrs[iSeg].sh_addr))
952 return VERR_LDR_INVALID_SEG_OFFSET;
953 }
954
955 if (!(pModElf->paShdrs[iSeg].sh_flags & SHF_ALLOC))
956 return VERR_LDR_INVALID_SEG_OFFSET;
957
958 *pRva = pModElf->paShdrs[iSeg].sh_addr;
959 return VINF_SUCCESS;
960}
961
962
963/** @copydoc RTLDROPS::pfnRvaToSegOffset. */
964static DECLCALLBACK(int) RTLDRELF_NAME(RvaToSegOffset)(PRTLDRMODINTERNAL pMod, RTLDRADDR Rva,
965 uint32_t *piSeg, PRTLDRADDR poffSeg)
966{
967 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
968
969 Elf_Addr PrevAddr = 0;
970 unsigned cLeft = pModElf->Ehdr.e_shnum - 1;
971 const Elf_Shdr *pShdr = &pModElf->paShdrs[cLeft];
972 while (cLeft-- > 0)
973 {
974 pShdr--;
975 if (pShdr->sh_flags & SHF_ALLOC)
976 {
977 Elf_Addr cbSeg = PrevAddr ? PrevAddr - pShdr->sh_addr : pShdr->sh_size;
978 RTLDRADDR offSeg = Rva - pShdr->sh_addr;
979 if (offSeg <= cbSeg)
980 {
981 *poffSeg = offSeg;
982 *piSeg = cLeft;
983 return VINF_SUCCESS;
984 }
985 PrevAddr = pShdr->sh_addr;
986 }
987 }
988
989 return VERR_LDR_INVALID_RVA;
990}
991
992
993
994/**
995 * The ELF module operations.
996 */
997static RTLDROPS RTLDRELF_MID(s_rtldrElf,Ops) =
998{
999#if ELF_MODE == 32
1000 "elf32",
1001#elif ELF_MODE == 64
1002 "elf64",
1003#endif
1004 RTLDRELF_NAME(Close),
1005 NULL, /* Get Symbol */
1006 RTLDRELF_NAME(Done),
1007 RTLDRELF_NAME(EnumSymbols),
1008 /* ext: */
1009 RTLDRELF_NAME(GetImageSize),
1010 RTLDRELF_NAME(GetBits),
1011 RTLDRELF_NAME(Relocate),
1012 RTLDRELF_NAME(GetSymbolEx),
1013 RTLDRELF_NAME(EnumDbgInfo),
1014 RTLDRELF_NAME(EnumSegments),
1015 RTLDRELF_NAME(LinkAddressToSegOffset),
1016 RTLDRELF_NAME(LinkAddressToRva),
1017 RTLDRELF_NAME(SegOffsetToRva),
1018 RTLDRELF_NAME(RvaToSegOffset),
1019 42
1020};
1021
1022
1023
1024/**
1025 * Validates the ELF header.
1026 *
1027 * @returns iprt status code.
1028 * @param pEhdr Pointer to the ELF header.
1029 * @param pszLogName The log name.
1030 * @param cbRawImage The size of the raw image.
1031 */
1032static int RTLDRELF_NAME(ValidateElfHeader)(const Elf_Ehdr *pEhdr, const char *pszLogName, uint64_t cbRawImage,
1033 PRTLDRARCH penmArch)
1034{
1035 Log3(("RTLdrELF: e_ident: %.*Rhxs\n"
1036 "RTLdrELF: e_type: " FMT_ELF_HALF "\n"
1037 "RTLdrELF: e_version: " FMT_ELF_HALF "\n"
1038 "RTLdrELF: e_entry: " FMT_ELF_ADDR "\n"
1039 "RTLdrELF: e_phoff: " FMT_ELF_OFF "\n"
1040 "RTLdrELF: e_shoff: " FMT_ELF_OFF "\n"
1041 "RTLdrELF: e_flags: " FMT_ELF_WORD "\n"
1042 "RTLdrELF: e_ehsize: " FMT_ELF_HALF "\n"
1043 "RTLdrELF: e_phentsize: " FMT_ELF_HALF "\n"
1044 "RTLdrELF: e_phnum: " FMT_ELF_HALF "\n"
1045 "RTLdrELF: e_shentsize: " FMT_ELF_HALF "\n"
1046 "RTLdrELF: e_shnum: " FMT_ELF_HALF "\n"
1047 "RTLdrELF: e_shstrndx: " FMT_ELF_HALF "\n",
1048 RT_ELEMENTS(pEhdr->e_ident), &pEhdr->e_ident[0], pEhdr->e_type, pEhdr->e_version,
1049 pEhdr->e_entry, pEhdr->e_phoff, pEhdr->e_shoff,pEhdr->e_flags, pEhdr->e_ehsize, pEhdr->e_phentsize,
1050 pEhdr->e_phnum, pEhdr->e_shentsize, pEhdr->e_shnum, pEhdr->e_shstrndx));
1051
1052 if ( pEhdr->e_ident[EI_MAG0] != ELFMAG0
1053 || pEhdr->e_ident[EI_MAG1] != ELFMAG1
1054 || pEhdr->e_ident[EI_MAG2] != ELFMAG2
1055 || pEhdr->e_ident[EI_MAG3] != ELFMAG3
1056 )
1057 {
1058 Log(("RTLdrELF: %s: Invalid ELF magic (%.*Rhxs)\n", pszLogName, sizeof(pEhdr->e_ident), pEhdr->e_ident)); NOREF(pszLogName);
1059 return VERR_BAD_EXE_FORMAT;
1060 }
1061 if (pEhdr->e_ident[EI_CLASS] != RTLDRELF_SUFF(ELFCLASS))
1062 {
1063 Log(("RTLdrELF: %s: Invalid ELF class (%.*Rhxs)\n", pszLogName, sizeof(pEhdr->e_ident), pEhdr->e_ident));
1064 return VERR_BAD_EXE_FORMAT;
1065 }
1066 if (pEhdr->e_ident[EI_DATA] != ELFDATA2LSB)
1067 {
1068 Log(("RTLdrELF: %s: ELF endian %x is unsupported\n", pEhdr->e_ident[EI_DATA]));
1069 return VERR_LDRELF_ODD_ENDIAN;
1070 }
1071 if (pEhdr->e_version != EV_CURRENT)
1072 {
1073 Log(("RTLdrELF: %s: ELF version %x is unsupported\n", pEhdr->e_version));
1074 return VERR_LDRELF_VERSION;
1075 }
1076
1077 if (sizeof(Elf_Ehdr) != pEhdr->e_ehsize)
1078 {
1079 Log(("RTLdrELF: %s: Elf header e_ehsize is %d expected %d!\n",
1080 pszLogName, pEhdr->e_ehsize, sizeof(Elf_Ehdr)));
1081 return VERR_BAD_EXE_FORMAT;
1082 }
1083 if ( sizeof(Elf_Phdr) != pEhdr->e_phentsize
1084 && ( pEhdr->e_phnum != 0
1085 || pEhdr->e_type == ET_DYN))
1086 {
1087 Log(("RTLdrELF: %s: Elf header e_phentsize is %d expected %d!\n",
1088 pszLogName, pEhdr->e_phentsize, sizeof(Elf_Phdr)));
1089 return VERR_BAD_EXE_FORMAT;
1090 }
1091 if (sizeof(Elf_Shdr) != pEhdr->e_shentsize)
1092 {
1093 Log(("RTLdrELF: %s: Elf header e_shentsize is %d expected %d!\n",
1094 pszLogName, pEhdr->e_shentsize, sizeof(Elf_Shdr)));
1095 return VERR_BAD_EXE_FORMAT;
1096 }
1097
1098 switch (pEhdr->e_type)
1099 {
1100 case ET_REL:
1101 case ET_EXEC:
1102 case ET_DYN:
1103 break;
1104 default:
1105 Log(("RTLdrELF: %s: image type %#x is not supported!\n", pszLogName, pEhdr->e_type));
1106 return VERR_BAD_EXE_FORMAT;
1107 }
1108
1109 switch (pEhdr->e_machine)
1110 {
1111#if ELF_MODE == 32
1112 case EM_386:
1113 case EM_486:
1114 *penmArch = RTLDRARCH_X86_32;
1115 break;
1116#elif ELF_MODE == 64
1117 case EM_X86_64:
1118 *penmArch = RTLDRARCH_AMD64;
1119 break;
1120#endif
1121 default:
1122 Log(("RTLdrELF: %s: machine type %u is not supported!\n", pEhdr->e_machine));
1123 return VERR_LDRELF_MACHINE;
1124 }
1125
1126 if ( pEhdr->e_phoff < pEhdr->e_ehsize
1127 && !(pEhdr->e_phoff && pEhdr->e_phnum)
1128 && pEhdr->e_phnum)
1129 {
1130 Log(("RTLdrELF: %s: The program headers overlap with the ELF header! e_phoff=" FMT_ELF_OFF "\n",
1131 pszLogName, pEhdr->e_phoff));
1132 return VERR_BAD_EXE_FORMAT;
1133 }
1134 if ( pEhdr->e_phoff + pEhdr->e_phnum * pEhdr->e_phentsize > cbRawImage
1135 || pEhdr->e_phoff + pEhdr->e_phnum * pEhdr->e_phentsize < pEhdr->e_phoff)
1136 {
1137 Log(("RTLdrELF: %s: The program headers extends beyond the file! e_phoff=" FMT_ELF_OFF " e_phnum=" FMT_ELF_HALF "\n",
1138 pszLogName, pEhdr->e_phoff, pEhdr->e_phnum));
1139 return VERR_BAD_EXE_FORMAT;
1140 }
1141
1142
1143 if ( pEhdr->e_shoff < pEhdr->e_ehsize
1144 && !(pEhdr->e_shoff && pEhdr->e_shnum))
1145 {
1146 Log(("RTLdrELF: %s: The section headers overlap with the ELF header! e_shoff=" FMT_ELF_OFF "\n",
1147 pszLogName, pEhdr->e_shoff));
1148 return VERR_BAD_EXE_FORMAT;
1149 }
1150 if ( pEhdr->e_shoff + pEhdr->e_shnum * pEhdr->e_shentsize > cbRawImage
1151 || pEhdr->e_shoff + pEhdr->e_shnum * pEhdr->e_shentsize < pEhdr->e_shoff)
1152 {
1153 Log(("RTLdrELF: %s: The section headers extends beyond the file! e_shoff=" FMT_ELF_OFF " e_shnum=" FMT_ELF_HALF "\n",
1154 pszLogName, pEhdr->e_shoff, pEhdr->e_shnum));
1155 return VERR_BAD_EXE_FORMAT;
1156 }
1157
1158 if (pEhdr->e_shstrndx == 0 || pEhdr->e_shstrndx > pEhdr->e_shnum)
1159 {
1160 Log(("RTLdrELF: %s: The section headers string table is out of bounds! e_shstrndx=" FMT_ELF_HALF " e_shnum=" FMT_ELF_HALF "\n",
1161 pszLogName, pEhdr->e_shstrndx, pEhdr->e_shnum));
1162 return VERR_BAD_EXE_FORMAT;
1163 }
1164
1165 return VINF_SUCCESS;
1166}
1167
1168/**
1169 * Gets the section header name.
1170 *
1171 * @returns pszName.
1172 * @param pReader The loader reader instance.
1173 * @param pEhdr The elf header.
1174 * @param offName The offset of the section header name.
1175 * @param pszName Where to store the name.
1176 * @param cbName The size of the buffer pointed to by pszName.
1177 */
1178const char *RTLDRELF_NAME(GetSHdrName)(PRTLDRMODELF pModElf, Elf_Word offName, char *pszName, size_t cbName)
1179{
1180 RTFOFF off = pModElf->paShdrs[pModElf->Ehdr.e_shstrndx].sh_offset + offName;
1181 int rc = pModElf->pReader->pfnRead(pModElf->pReader, pszName, cbName - 1, off);
1182 if (RT_FAILURE(rc))
1183 {
1184 /* read by for byte. */
1185 for (unsigned i = 0; i < cbName; i++, off++)
1186 {
1187 rc = pModElf->pReader->pfnRead(pModElf->pReader, pszName + i, 1, off);
1188 if (RT_FAILURE(rc))
1189 {
1190 pszName[i] = '\0';
1191 break;
1192 }
1193 }
1194 }
1195
1196 pszName[cbName - 1] = '\0';
1197 return pszName;
1198}
1199
1200
1201/**
1202 * Validates a section header.
1203 *
1204 * @returns iprt status code.
1205 * @param pModElf Pointer to the module structure.
1206 * @param iShdr The index of section header which should be validated.
1207 * The section headers are found in the pModElf->paShdrs array.
1208 * @param pszLogName The log name.
1209 * @param cbRawImage The size of the raw image.
1210 */
1211static int RTLDRELF_NAME(ValidateSectionHeader)(PRTLDRMODELF pModElf, unsigned iShdr, const char *pszLogName, RTFOFF cbRawImage)
1212{
1213 const Elf_Shdr *pShdr = &pModElf->paShdrs[iShdr];
1214 char szSectionName[80]; NOREF(szSectionName);
1215 Log3(("RTLdrELF: Section Header #%d:\n"
1216 "RTLdrELF: sh_name: " FMT_ELF_WORD " - %s\n"
1217 "RTLdrELF: sh_type: " FMT_ELF_WORD " (%s)\n"
1218 "RTLdrELF: sh_flags: " FMT_ELF_XWORD "\n"
1219 "RTLdrELF: sh_addr: " FMT_ELF_ADDR "\n"
1220 "RTLdrELF: sh_offset: " FMT_ELF_OFF "\n"
1221 "RTLdrELF: sh_size: " FMT_ELF_XWORD "\n"
1222 "RTLdrELF: sh_link: " FMT_ELF_WORD "\n"
1223 "RTLdrELF: sh_info: " FMT_ELF_WORD "\n"
1224 "RTLdrELF: sh_addralign: " FMT_ELF_XWORD "\n"
1225 "RTLdrELF: sh_entsize: " FMT_ELF_XWORD "\n",
1226 iShdr,
1227 pShdr->sh_name, RTLDRELF_NAME(GetSHdrName)(pModElf, pShdr->sh_name, szSectionName, sizeof(szSectionName)),
1228 pShdr->sh_type, rtldrElfGetShdrType(pShdr->sh_type), pShdr->sh_flags, pShdr->sh_addr,
1229 pShdr->sh_offset, pShdr->sh_size, pShdr->sh_link, pShdr->sh_info, pShdr->sh_addralign,
1230 pShdr->sh_entsize));
1231
1232 if (iShdr == 0)
1233 {
1234 if ( pShdr->sh_name != 0
1235 || pShdr->sh_type != SHT_NULL
1236 || pShdr->sh_flags != 0
1237 || pShdr->sh_addr != 0
1238 || pShdr->sh_size != 0
1239 || pShdr->sh_offset != 0
1240 || pShdr->sh_link != SHN_UNDEF
1241 || pShdr->sh_addralign != 0
1242 || pShdr->sh_entsize != 0 )
1243 {
1244 Log(("RTLdrELF: %s: Bad #0 section: %.*Rhxs\n", pszLogName, sizeof(*pShdr), pShdr ));
1245 return VERR_BAD_EXE_FORMAT;
1246 }
1247 return VINF_SUCCESS;
1248 }
1249
1250 if (pShdr->sh_name >= pModElf->cbShStr)
1251 {
1252 Log(("RTLdrELF: %s: Shdr #%d: sh_name (%d) is beyond the end of the section header string table (%d)!\n",
1253 pszLogName, iShdr, pShdr->sh_name, pModElf->cbShStr)); NOREF(pszLogName);
1254 return VERR_BAD_EXE_FORMAT;
1255 }
1256
1257 if (pShdr->sh_link >= pModElf->Ehdr.e_shnum)
1258 {
1259 Log(("RTLdrELF: %s: Shdr #%d: sh_link (%d) is beyond the end of the section table (%d)!\n",
1260 pszLogName, iShdr, pShdr->sh_link, pModElf->Ehdr.e_shnum)); NOREF(pszLogName);
1261 return VERR_BAD_EXE_FORMAT;
1262 }
1263
1264 switch (pShdr->sh_type)
1265 {
1266 /** @todo find specs and check up which sh_info fields indicates section table entries */
1267 case 12301230:
1268 if (pShdr->sh_info >= pModElf->Ehdr.e_shnum)
1269 {
1270 Log(("RTLdrELF: %s: Shdr #%d: sh_info (%d) is beyond the end of the section table (%d)!\n",
1271 pszLogName, iShdr, pShdr->sh_link, pModElf->Ehdr.e_shnum));
1272 return VERR_BAD_EXE_FORMAT;
1273 }
1274 break;
1275
1276 case SHT_NULL:
1277 break;
1278 case SHT_PROGBITS:
1279 case SHT_SYMTAB:
1280 case SHT_STRTAB:
1281 case SHT_RELA:
1282 case SHT_HASH:
1283 case SHT_DYNAMIC:
1284 case SHT_NOTE:
1285 case SHT_NOBITS:
1286 case SHT_REL:
1287 case SHT_SHLIB:
1288 case SHT_DYNSYM:
1289 /*
1290 * For these types sh_info doesn't have any special meaning, or anything which
1291 * we need/can validate now.
1292 */
1293 break;
1294
1295
1296 default:
1297 Log(("RTLdrELF: %s: Warning, unknown type %d!\n", pszLogName, pShdr->sh_type));
1298 break;
1299 }
1300
1301 if ( pShdr->sh_type != SHT_NOBITS
1302 && pShdr->sh_size)
1303 {
1304 RTFOFF offEnd = pShdr->sh_offset + pShdr->sh_size;
1305 if ( offEnd > cbRawImage
1306 || offEnd < (RTFOFF)pShdr->sh_offset)
1307 {
1308 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",
1309 pszLogName, iShdr, pShdr->sh_offset, pShdr->sh_size, offEnd, cbRawImage));
1310 return VERR_BAD_EXE_FORMAT;
1311 }
1312 if (pShdr->sh_offset < sizeof(Elf_Ehdr))
1313 {
1314 Log(("RTLdrELF: %s: Shdr #%d: sh_offset (" FMT_ELF_OFF ") + sh_size (" FMT_ELF_XWORD ") is starting in the ELF header!\n",
1315 pszLogName, iShdr, pShdr->sh_offset, pShdr->sh_size, cbRawImage));
1316 return VERR_BAD_EXE_FORMAT;
1317 }
1318 }
1319
1320 return VINF_SUCCESS;
1321}
1322
1323
1324
1325/**
1326 * Opens an ELF image, fixed bitness.
1327 *
1328 * @returns iprt status code.
1329 * @param pReader The loader reader instance which will provide the raw image bits.
1330 * @param fFlags Reserved, MBZ.
1331 * @param enmArch Architecture specifier.
1332 * @param phLdrMod Where to store the handle.
1333 */
1334static int RTLDRELF_NAME(Open)(PRTLDRREADER pReader, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod)
1335{
1336 const char *pszLogName = pReader->pfnLogName(pReader);
1337 RTFOFF cbRawImage = pReader->pfnSize(pReader);
1338 AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
1339
1340 /*
1341 * Create the loader module instance.
1342 */
1343 PRTLDRMODELF pModElf = (PRTLDRMODELF)RTMemAllocZ(sizeof(*pModElf));
1344 if (!pModElf)
1345 return VERR_NO_MEMORY;
1346
1347 pModElf->Core.u32Magic = RTLDRMOD_MAGIC;
1348 pModElf->Core.eState = LDR_STATE_INVALID;
1349 pModElf->pReader = pReader;
1350 //pModElf->pvBits = NULL;
1351 //pModElf->Ehdr = {0};
1352 //pModElf->paShdrs = NULL;
1353 //pModElf->paSyms = NULL;
1354 pModElf->iSymSh = ~0U;
1355 //pModElf->cSyms = 0;
1356 pModElf->iStrSh = ~0U;
1357 //pModElf->cbStr = 0;
1358 //pModElf->cbImage = 0;
1359 //pModElf->pStr = NULL;
1360 //pModElf->cbShStr = 0;
1361 //pModElf->pShStr = NULL;
1362
1363 /*
1364 * Read and validate the ELF header and match up the CPU architecture.
1365 */
1366 int rc = pReader->pfnRead(pReader, &pModElf->Ehdr, sizeof(pModElf->Ehdr), 0);
1367 if (RT_SUCCESS(rc))
1368 {
1369 RTLDRARCH enmArchImage = RTLDRARCH_INVALID; /* shut up gcc */
1370 rc = RTLDRELF_NAME(ValidateElfHeader)(&pModElf->Ehdr, pszLogName, cbRawImage, &enmArchImage);
1371 if (RT_SUCCESS(rc))
1372 {
1373 if ( enmArch != RTLDRARCH_WHATEVER
1374 && enmArch != enmArchImage)
1375 rc = VERR_LDR_ARCH_MISMATCH;
1376 }
1377 }
1378 if (RT_SUCCESS(rc))
1379 {
1380 /*
1381 * Read the section headers, keeping a prestine copy for the module
1382 * introspection methods.
1383 */
1384 size_t const cbShdrs = pModElf->Ehdr.e_shnum * sizeof(Elf_Shdr);
1385 Elf_Shdr *paShdrs = (Elf_Shdr *)RTMemAlloc(cbShdrs * 2);
1386 if (paShdrs)
1387 {
1388 pModElf->paShdrs = paShdrs;
1389 rc = pReader->pfnRead(pReader, paShdrs, cbShdrs, pModElf->Ehdr.e_shoff);
1390 if (RT_SUCCESS(rc))
1391 {
1392 memcpy(&paShdrs[pModElf->Ehdr.e_shnum], paShdrs, cbShdrs);
1393 pModElf->paOrgShdrs = &paShdrs[pModElf->Ehdr.e_shnum];
1394
1395 pModElf->cbShStr = paShdrs[pModElf->Ehdr.e_shstrndx].sh_size;
1396
1397 /*
1398 * Validate the section headers, allocate memory for the sections (determine the image size),
1399 * and find relevant sections.
1400 */
1401 for (unsigned i = 0; i < pModElf->Ehdr.e_shnum; i++)
1402 {
1403 rc = RTLDRELF_NAME(ValidateSectionHeader)(pModElf, i, pszLogName, cbRawImage);
1404 if (RT_FAILURE(rc))
1405 break;
1406
1407 /* Allocate memory addresses for the section. */
1408 if (paShdrs[i].sh_flags & SHF_ALLOC)
1409 {
1410 paShdrs[i].sh_addr = paShdrs[i].sh_addralign
1411 ? RT_ALIGN_T(pModElf->cbImage, paShdrs[i].sh_addralign, Elf_Addr)
1412 : (Elf_Addr)pModElf->cbImage;
1413 pModElf->cbImage = (size_t)paShdrs[i].sh_addr + (size_t)paShdrs[i].sh_size;
1414 AssertMsgReturn(pModElf->cbImage == paShdrs[i].sh_addr + paShdrs[i].sh_size,
1415 (FMT_ELF_ADDR "\n", paShdrs[i].sh_addr + paShdrs[i].sh_size),
1416 VERR_IMAGE_TOO_BIG);
1417 Log2(("RTLdrElf: %s: Assigned " FMT_ELF_ADDR " to section #%d\n", pszLogName, paShdrs[i].sh_addr, i));
1418 }
1419
1420 /* We're looking for symbol tables. */
1421 if (paShdrs[i].sh_type == SHT_SYMTAB)
1422 {
1423 if (pModElf->iSymSh != ~0U)
1424 {
1425 Log(("RTLdrElf: %s: Multiple symbol tabs! iSymSh=%d i=%d\n", pszLogName, pModElf->iSymSh, i));
1426 rc = VERR_LDRELF_MULTIPLE_SYMTABS;
1427 break;
1428 }
1429 pModElf->iSymSh = i;
1430 pModElf->cSyms = (unsigned)(paShdrs[i].sh_size / sizeof(Elf_Sym));
1431 AssertReturn(pModElf->cSyms == paShdrs[i].sh_size / sizeof(Elf_Sym), VERR_IMAGE_TOO_BIG);
1432 pModElf->iStrSh = paShdrs[i].sh_link;
1433 pModElf->cbStr = (unsigned)paShdrs[pModElf->iStrSh].sh_size;
1434 AssertReturn(pModElf->cbStr == paShdrs[pModElf->iStrSh].sh_size, VERR_IMAGE_TOO_BIG);
1435 }
1436
1437 /* Special checks for the section string table. */
1438 if (i == pModElf->Ehdr.e_shstrndx)
1439 {
1440 if (paShdrs[i].sh_type != SHT_STRTAB)
1441 {
1442 Log(("RTLdrElf: Section header string table is not a SHT_STRTAB: %#x\n", paShdrs[i].sh_type));
1443 rc = VERR_BAD_EXE_FORMAT;
1444 break;
1445 }
1446 if (paShdrs[i].sh_size == 0)
1447 {
1448 Log(("RTLdrElf: Section header string table is empty\n"));
1449 rc = VERR_BAD_EXE_FORMAT;
1450 break;
1451 }
1452 }
1453
1454 } /* for each section header */
1455
1456 Log2(("RTLdrElf: iSymSh=%u cSyms=%u iStrSh=%u cbStr=%u rc=%Rrc cbImage=%#zx\n",
1457 pModElf->iSymSh, pModElf->cSyms, pModElf->iStrSh, pModElf->cbStr, rc, pModElf->cbImage));
1458 if (RT_SUCCESS(rc))
1459 {
1460 pModElf->Core.pOps = &RTLDRELF_MID(s_rtldrElf,Ops);
1461 pModElf->Core.eState = LDR_STATE_OPENED;
1462 *phLdrMod = &pModElf->Core;
1463
1464 LogFlow(("%s: %s: returns VINF_SUCCESS *phLdrMod=%p\n", __FUNCTION__, pszLogName, *phLdrMod));
1465 return VINF_SUCCESS;
1466 }
1467 }
1468
1469 RTMemFree(paShdrs);
1470 }
1471 else
1472 rc = VERR_NO_MEMORY;
1473 }
1474
1475 RTMemFree(pModElf);
1476 LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
1477 return rc;
1478}
1479
1480
1481
1482
1483/*******************************************************************************
1484* Cleanup Constants And Macros *
1485*******************************************************************************/
1486#undef RTLDRELF_NAME
1487#undef RTLDRELF_SUFF
1488#undef RTLDRELF_MID
1489
1490#undef FMT_ELF_ADDR
1491#undef FMT_ELF_HALF
1492#undef FMT_ELF_SHALF
1493#undef FMT_ELF_OFF
1494#undef FMT_ELF_SIZE
1495#undef FMT_ELF_SWORD
1496#undef FMT_ELF_WORD
1497#undef FMT_ELF_XWORD
1498#undef FMT_ELF_SXWORD
1499
1500#undef Elf_Ehdr
1501#undef Elf_Phdr
1502#undef Elf_Shdr
1503#undef Elf_Sym
1504#undef Elf_Rel
1505#undef Elf_Rela
1506#undef Elf_Reloc
1507#undef Elf_Nhdr
1508#undef Elf_Dyn
1509
1510#undef Elf_Addr
1511#undef Elf_Half
1512#undef Elf_Off
1513#undef Elf_Size
1514#undef Elf_Sword
1515#undef Elf_Word
1516
1517#undef RTLDRMODELF
1518#undef PRTLDRMODELF
1519
1520#undef ELF_R_SYM
1521#undef ELF_R_TYPE
1522#undef ELF_R_INFO
1523
1524#undef ELF_ST_BIND
1525
Note: See TracBrowser for help on using the repository browser.

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