VirtualBox

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

Last change on this file since 80346 was 77971, checked in by vboxsync, 6 years ago

Runtime/ldr: Make RTLDRREADER::pfnSize return an unsigned 64bit value instead of a signed one for the raw image size and adapt all users. This avoids signed/unsigned confusions when comparing those value with others (bugref:9188)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 79.6 KB
Line 
1/* $Id: ldrELFRelocatable.cpp.h 77971 2019-04-01 09:35:17Z vboxsync $ */
2/** @file
3 * IPRT - Binary Image Loader, Template for ELF Relocatable Images.
4 */
5
6/*
7 * Copyright (C) 2006-2019 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 readonly mapping of the image bits.
96 * This mapping is provided by the pReader. */
97 const void *pvBits;
98
99 /** The ELF header. */
100 Elf_Ehdr Ehdr;
101 /** Pointer to our copy of the section headers with sh_addr as RVAs.
102 * The virtual addresses in this array is the 0 based assignments we've given the image.
103 * Not valid if the image is DONE. */
104 Elf_Shdr *paShdrs;
105 /** Unmodified section headers (allocated after paShdrs, so no need to free).
106 * Not valid if the image is DONE. */
107 Elf_Shdr const *paOrgShdrs;
108 /** The size of the loaded image. */
109 size_t cbImage;
110
111 /** The image base address if it's an EXEC or DYN image. */
112 Elf_Addr LinkAddress;
113
114 /** The symbol section index. */
115 unsigned iSymSh;
116 /** Number of symbols in the table. */
117 unsigned cSyms;
118 /** Pointer to symbol table within RTLDRMODELF::pvBits. */
119 const Elf_Sym *paSyms;
120
121 /** The string section index. */
122 unsigned iStrSh;
123 /** Size of the string table. */
124 unsigned cbStr;
125 /** Pointer to string table within RTLDRMODELF::pvBits. */
126 const char *pStr;
127
128 /** Size of the section header string table. */
129 unsigned cbShStr;
130 /** Pointer to section header string table within RTLDRMODELF::pvBits. */
131 const char *pShStr;
132
133 /** The '.eh_frame' section index. Zero if not searched for, ~0U if not found. */
134 unsigned iShEhFrame;
135 /** The '.eh_frame_hdr' section index. Zero if not searched for, ~0U if not found. */
136 unsigned iShEhFrameHdr;
137} RTLDRMODELF, *PRTLDRMODELF;
138
139
140/**
141 * Maps the image bits into memory and resolve pointers into it.
142 *
143 * @returns iprt status code.
144 * @param pModElf The ELF loader module instance data.
145 * @param fNeedsBits Set if we actually need the pvBits member.
146 * If we don't, we can simply read the string and symbol sections, thus saving memory.
147 */
148static int RTLDRELF_NAME(MapBits)(PRTLDRMODELF pModElf, bool fNeedsBits)
149{
150 NOREF(fNeedsBits);
151 if (pModElf->pvBits)
152 return VINF_SUCCESS;
153 int rc = pModElf->Core.pReader->pfnMap(pModElf->Core.pReader, &pModElf->pvBits);
154 if (RT_SUCCESS(rc))
155 {
156 const uint8_t *pu8 = (const uint8_t *)pModElf->pvBits;
157 if (pModElf->iSymSh != ~0U)
158 pModElf->paSyms = (const Elf_Sym *)(pu8 + pModElf->paShdrs[pModElf->iSymSh].sh_offset);
159 if (pModElf->iStrSh != ~0U)
160 pModElf->pStr = (const char *)(pu8 + pModElf->paShdrs[pModElf->iStrSh].sh_offset);
161 pModElf->pShStr = (const char *)(pu8 + pModElf->paShdrs[pModElf->Ehdr.e_shstrndx].sh_offset);
162
163 /*
164 * Verify that the ends of the string tables have a zero terminator
165 * (this avoids duplicating the appropriate checks later in the code accessing the string tables).
166 *
167 * sh_offset and sh_size were verfied in RTLDRELF_NAME(ValidateSectionHeader)() already so they
168 * are safe to use.
169 */
170 AssertMsgStmt( pModElf->iStrSh == ~0U
171 || pModElf->pStr[pModElf->paShdrs[pModElf->iStrSh].sh_size - 1] == '\0',
172 ("The string table is not zero terminated!\n"),
173 rc = VERR_LDRELF_UNTERMINATED_STRING_TAB);
174 AssertMsgStmt(pModElf->pShStr[pModElf->paShdrs[pModElf->Ehdr.e_shstrndx].sh_size - 1] == '\0',
175 ("The section header string table is not zero terminated!\n"),
176 rc = VERR_LDRELF_UNTERMINATED_STRING_TAB);
177
178 if (RT_FAILURE(rc))
179 {
180 /* Unmap. */
181 int rc2 = pModElf->Core.pReader->pfnUnmap(pModElf->Core.pReader, pModElf->pvBits);
182 AssertRC(rc2);
183 pModElf->pvBits = NULL;
184 pModElf->paSyms = NULL;
185 pModElf->pStr = NULL;
186 pModElf->pShStr = NULL;
187 }
188 }
189 return rc;
190}
191
192
193/*
194 *
195 * EXEC & DYN.
196 * EXEC & DYN.
197 * EXEC & DYN.
198 * EXEC & DYN.
199 * EXEC & DYN.
200 *
201 */
202
203
204/**
205 * Applies the fixups for a section in an executable image.
206 *
207 * @returns iprt status code.
208 * @param pModElf The ELF loader module instance data.
209 * @param BaseAddr The base address which the module is being fixedup to.
210 * @param pfnGetImport The callback function to use to resolve imports (aka unresolved externals).
211 * @param pvUser User argument to pass to the callback.
212 * @param SecAddr The section address. This is the address the relocations are relative to.
213 * @param cbSec The section size. The relocations must be inside this.
214 * @param pu8SecBaseR Where we read section bits from.
215 * @param pu8SecBaseW Where we write section bits to.
216 * @param pvRelocs Pointer to where we read the relocations from.
217 * @param cbRelocs Size of the relocations.
218 */
219static int RTLDRELF_NAME(RelocateSectionExecDyn)(PRTLDRMODELF pModElf, Elf_Addr BaseAddr,
220 PFNRTLDRIMPORT pfnGetImport, void *pvUser,
221 const Elf_Addr SecAddr, Elf_Size cbSec,
222 const uint8_t *pu8SecBaseR, uint8_t *pu8SecBaseW,
223 const void *pvRelocs, Elf_Size cbRelocs)
224{
225#if ELF_MODE != 32
226 NOREF(pu8SecBaseR);
227#endif
228
229 /*
230 * Iterate the relocations.
231 * The relocations are stored in an array of Elf32_Rel records and covers the entire relocation section.
232 */
233 const Elf_Addr offDelta = BaseAddr - pModElf->LinkAddress;
234 const Elf_Reloc *paRels = (const Elf_Reloc *)pvRelocs;
235 const unsigned iRelMax = (unsigned)(cbRelocs / sizeof(paRels[0]));
236 AssertMsgReturn(iRelMax == cbRelocs / sizeof(paRels[0]), (FMT_ELF_SIZE "\n", cbRelocs / sizeof(paRels[0])),
237 VERR_IMAGE_TOO_BIG);
238 for (unsigned iRel = 0; iRel < iRelMax; iRel++)
239 {
240 /*
241 * Skip R_XXX_NONE entries early to avoid confusion in the symbol
242 * getter code.
243 */
244#if ELF_MODE == 32
245 if (ELF_R_TYPE(paRels[iRel].r_info) == R_386_NONE)
246 continue;
247#elif ELF_MODE == 64
248 if (ELF_R_TYPE(paRels[iRel].r_info) == R_X86_64_NONE)
249 continue;
250#endif
251
252 /*
253 * Validate and find the symbol, resolve undefined ones.
254 */
255 Elf_Size iSym = ELF_R_SYM(paRels[iRel].r_info);
256 if (iSym >= pModElf->cSyms)
257 {
258 AssertMsgFailed(("iSym=%d is an invalid symbol index!\n", iSym));
259 return VERR_LDRELF_INVALID_SYMBOL_INDEX;
260 }
261 const Elf_Sym *pSym = &pModElf->paSyms[iSym];
262 if (pSym->st_name >= pModElf->cbStr)
263 {
264 AssertMsgFailed(("iSym=%d st_name=%d str sh_size=%d\n", iSym, pSym->st_name, pModElf->cbStr));
265 return VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET;
266 }
267
268 Elf_Addr SymValue = 0;
269 if (pSym->st_shndx == SHN_UNDEF)
270 {
271 /* Try to resolve the symbol. */
272 const char *pszName = ELF_STR(pModElf, pSym->st_name);
273 RTUINTPTR ExtValue;
274 int rc = pfnGetImport(&pModElf->Core, "", pszName, ~0U, &ExtValue, pvUser);
275 AssertMsgRCReturn(rc, ("Failed to resolve '%s' rc=%Rrc\n", pszName, rc), rc);
276 SymValue = (Elf_Addr)ExtValue;
277 AssertMsgReturn((RTUINTPTR)SymValue == ExtValue, ("Symbol value overflowed! '%s'\n", pszName),
278 VERR_SYMBOL_VALUE_TOO_BIG);
279 Log2(("rtldrELF: #%-3d - UNDEF " FMT_ELF_ADDR " '%s'\n", iSym, SymValue, pszName));
280 }
281 else
282 {
283 AssertMsgReturn(pSym->st_shndx < pModElf->Ehdr.e_shnum || pSym->st_shndx == SHN_ABS, ("%#x\n", pSym->st_shndx),
284 VERR_LDRELF_INVALID_RELOCATION_OFFSET);
285#if ELF_MODE == 64
286 SymValue = pSym->st_value;
287#endif
288 }
289
290#if ELF_MODE == 64
291 /* Calc the value (indexes checked above; assumes SHN_UNDEF == 0). */
292 Elf_Addr Value;
293 if (pSym->st_shndx < pModElf->Ehdr.e_shnum)
294 Value = SymValue + offDelta;
295 else /* SHN_ABS: */
296 Value = SymValue + paRels[iRel].r_addend;
297#endif
298
299 /*
300 * Apply the fixup.
301 */
302 AssertMsgReturn(paRels[iRel].r_offset < cbSec, (FMT_ELF_ADDR " " FMT_ELF_SIZE "\n", paRels[iRel].r_offset, cbSec), VERR_LDRELF_INVALID_RELOCATION_OFFSET);
303#if ELF_MODE == 32
304 const Elf_Addr *pAddrR = (const Elf_Addr *)(pu8SecBaseR + paRels[iRel].r_offset); /* Where to read the addend. */
305#endif
306 Elf_Addr *pAddrW = (Elf_Addr *)(pu8SecBaseW + paRels[iRel].r_offset); /* Where to write the fixup. */
307 switch (ELF_R_TYPE(paRels[iRel].r_info))
308 {
309#if ELF_MODE == 32
310 /*
311 * Absolute addressing.
312 */
313 case R_386_32:
314 {
315 Elf_Addr Value;
316 if (pSym->st_shndx < pModElf->Ehdr.e_shnum)
317 Value = *pAddrR + offDelta; /* Simplified. */
318 else if (pSym->st_shndx == SHN_ABS)
319 continue; /* Internal fixup, no need to apply it. */
320 else if (pSym->st_shndx == SHN_UNDEF)
321 Value = SymValue + *pAddrR;
322 else
323 AssertFailedReturn(VERR_LDR_GENERAL_FAILURE); /** @todo SHN_COMMON */
324 *(uint32_t *)pAddrW = Value;
325 Log4((FMT_ELF_ADDR": R_386_32 Value=" FMT_ELF_ADDR "\n", SecAddr + paRels[iRel].r_offset + BaseAddr, Value));
326 break;
327 }
328
329 /*
330 * PC relative addressing.
331 */
332 case R_386_PC32:
333 {
334 Elf_Addr Value;
335 if (pSym->st_shndx < pModElf->Ehdr.e_shnum)
336 continue; /* Internal fixup, no need to apply it. */
337 else if (pSym->st_shndx == SHN_ABS)
338 Value = *pAddrR + offDelta; /* Simplified. */
339 else if (pSym->st_shndx == SHN_UNDEF)
340 {
341 const Elf_Addr SourceAddr = SecAddr + paRels[iRel].r_offset + BaseAddr; /* Where the source really is. */
342 Value = SymValue + *(uint32_t *)pAddrR - SourceAddr;
343 *(uint32_t *)pAddrW = Value;
344 }
345 else
346 AssertFailedReturn(VERR_LDR_GENERAL_FAILURE); /** @todo SHN_COMMON */
347 Log4((FMT_ELF_ADDR": R_386_PC32 Value=" FMT_ELF_ADDR "\n", SecAddr + paRels[iRel].r_offset + BaseAddr, Value));
348 break;
349 }
350
351#elif ELF_MODE == 64
352
353 /*
354 * Absolute addressing
355 */
356 case R_X86_64_64:
357 {
358 *(uint64_t *)pAddrW = Value;
359 Log4((FMT_ELF_ADDR": R_X86_64_64 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
360 SecAddr + paRels[iRel].r_offset + BaseAddr, Value, SymValue));
361 break;
362 }
363
364 /*
365 * Truncated 32-bit value (zero-extendedable to the 64-bit value).
366 */
367 case R_X86_64_32:
368 {
369 *(uint32_t *)pAddrW = (uint32_t)Value;
370 Log4((FMT_ELF_ADDR": R_X86_64_32 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
371 SecAddr + paRels[iRel].r_offset + BaseAddr, Value, SymValue));
372 AssertMsgReturn((Elf_Addr)*(uint32_t *)pAddrW == SymValue, ("Value=" FMT_ELF_ADDR "\n", SymValue),
373 VERR_SYMBOL_VALUE_TOO_BIG);
374 break;
375 }
376
377 /*
378 * Truncated 32-bit value (sign-extendedable to the 64-bit value).
379 */
380 case R_X86_64_32S:
381 {
382 *(int32_t *)pAddrW = (int32_t)Value;
383 Log4((FMT_ELF_ADDR": R_X86_64_32S Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
384 SecAddr + paRels[iRel].r_offset + BaseAddr, Value, SymValue));
385 AssertMsgReturn((Elf_Addr)*(int32_t *)pAddrW == Value, ("Value=" FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG); /** @todo check the sign-extending here. */
386 break;
387 }
388
389 /*
390 * PC relative addressing.
391 */
392 case R_X86_64_PC32:
393 case R_X86_64_PLT32: /* binutils commit 451875b4f976a527395e9303224c7881b65e12ed feature/regression. */
394 {
395 const Elf_Addr SourceAddr = SecAddr + paRels[iRel].r_offset + BaseAddr; /* Where the source really is. */
396 Value -= SourceAddr;
397 *(int32_t *)pAddrW = (int32_t)Value;
398 Log4((FMT_ELF_ADDR": R_X86_64_PC32 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
399 SourceAddr, Value, SymValue));
400 AssertMsgReturn((Elf_Addr)*(int32_t *)pAddrW == Value, ("Value=" FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG); /** @todo check the sign-extending here. */
401 break;
402 }
403#endif
404
405 default:
406 AssertMsgFailed(("Unknown relocation type: %d (iRel=%d iRelMax=%d)\n",
407 ELF_R_TYPE(paRels[iRel].r_info), iRel, iRelMax));
408 return VERR_LDRELF_RELOCATION_NOT_SUPPORTED;
409 }
410 }
411
412 return VINF_SUCCESS;
413}
414
415
416
417/*
418 *
419 * REL
420 * REL
421 * REL
422 * REL
423 * REL
424 *
425 */
426
427/**
428 * Get the symbol and symbol value.
429 *
430 * @returns iprt status code.
431 * @param pModElf The ELF loader module instance data.
432 * @param BaseAddr The base address which the module is being fixedup to.
433 * @param pfnGetImport The callback function to use to resolve imports (aka unresolved externals).
434 * @param pvUser User argument to pass to the callback.
435 * @param iSym The symbol to get.
436 * @param ppSym Where to store the symbol pointer on success. (read only)
437 * @param pSymValue Where to store the symbol value on success.
438 */
439static int RTLDRELF_NAME(Symbol)(PRTLDRMODELF pModElf, Elf_Addr BaseAddr, PFNRTLDRIMPORT pfnGetImport, void *pvUser,
440 Elf_Size iSym, const Elf_Sym **ppSym, Elf_Addr *pSymValue)
441{
442 /*
443 * Validate and find the symbol.
444 */
445 if (iSym >= pModElf->cSyms)
446 {
447 AssertMsgFailed(("iSym=%d is an invalid symbol index!\n", iSym));
448 return VERR_LDRELF_INVALID_SYMBOL_INDEX;
449 }
450 const Elf_Sym *pSym = &pModElf->paSyms[iSym];
451 *ppSym = pSym;
452
453 if (pSym->st_name >= pModElf->cbStr)
454 {
455 AssertMsgFailed(("iSym=%d st_name=%d str sh_size=%d\n", iSym, pSym->st_name, pModElf->cbStr));
456 return VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET;
457 }
458 const char *pszName = ELF_STR(pModElf, pSym->st_name);
459
460 /*
461 * Determine the symbol value.
462 *
463 * Symbols needs different treatment depending on which section their are in.
464 * Undefined and absolute symbols goes into special non-existing sections.
465 */
466 switch (pSym->st_shndx)
467 {
468 /*
469 * Undefined symbol, needs resolving.
470 *
471 * Since ELF has no generic concept of importing from specific module (the OS/2 ELF format
472 * has but that's a OS extension and only applies to programs and dlls), we'll have to ask
473 * the resolver callback to do a global search.
474 */
475 case SHN_UNDEF:
476 {
477 /* Try to resolve the symbol. */
478 RTUINTPTR Value;
479 int rc = pfnGetImport(&pModElf->Core, "", pszName, ~0U, &Value, pvUser);
480 if (RT_FAILURE(rc))
481 {
482 AssertMsgFailed(("Failed to resolve '%s' rc=%Rrc\n", pszName, rc));
483 return rc;
484 }
485 *pSymValue = (Elf_Addr)Value;
486 if ((RTUINTPTR)*pSymValue != Value)
487 {
488 AssertMsgFailed(("Symbol value overflowed! '%s'\n", pszName));
489 return VERR_SYMBOL_VALUE_TOO_BIG;
490 }
491
492 Log2(("rtldrELF: #%-3d - UNDEF " FMT_ELF_ADDR " '%s'\n", iSym, *pSymValue, pszName));
493 break;
494 }
495
496 /*
497 * Absolute symbols needs no fixing since they are, well, absolute.
498 */
499 case SHN_ABS:
500 *pSymValue = pSym->st_value;
501 Log2(("rtldrELF: #%-3d - ABS " FMT_ELF_ADDR " '%s'\n", iSym, *pSymValue, pszName));
502 break;
503
504 /*
505 * All other symbols are addressed relative to their section and need to be fixed up.
506 */
507 default:
508 if (pSym->st_shndx >= pModElf->Ehdr.e_shnum)
509 {
510 /* what about common symbols? */
511 AssertMsg(pSym->st_shndx < pModElf->Ehdr.e_shnum,
512 ("iSym=%d st_shndx=%d e_shnum=%d pszName=%s\n", iSym, pSym->st_shndx, pModElf->Ehdr.e_shnum, pszName));
513 return VERR_BAD_EXE_FORMAT;
514 }
515 *pSymValue = pSym->st_value + pModElf->paShdrs[pSym->st_shndx].sh_addr + BaseAddr;
516 Log2(("rtldrELF: #%-3d - %5d " FMT_ELF_ADDR " '%s'\n", iSym, pSym->st_shndx, *pSymValue, pszName));
517 break;
518 }
519
520 return VINF_SUCCESS;
521}
522
523
524/**
525 * Applies the fixups for a sections.
526 *
527 * @returns iprt status code.
528 * @param pModElf The ELF loader module instance data.
529 * @param BaseAddr The base address which the module is being fixedup to.
530 * @param pfnGetImport The callback function to use to resolve imports (aka unresolved externals).
531 * @param pvUser User argument to pass to the callback.
532 * @param SecAddr The section address. This is the address the relocations are relative to.
533 * @param cbSec The section size. The relocations must be inside this.
534 * @param pu8SecBaseR Where we read section bits from.
535 * @param pu8SecBaseW Where we write section bits to.
536 * @param pvRelocs Pointer to where we read the relocations from.
537 * @param cbRelocs Size of the relocations.
538 */
539static int RTLDRELF_NAME(RelocateSection)(PRTLDRMODELF pModElf, Elf_Addr BaseAddr, PFNRTLDRIMPORT pfnGetImport, void *pvUser,
540 const Elf_Addr SecAddr, Elf_Size cbSec, const uint8_t *pu8SecBaseR, uint8_t *pu8SecBaseW,
541 const void *pvRelocs, Elf_Size cbRelocs)
542{
543#if ELF_MODE != 32
544 NOREF(pu8SecBaseR);
545#endif
546
547 /*
548 * Iterate the relocations.
549 * The relocations are stored in an array of Elf32_Rel records and covers the entire relocation section.
550 */
551 const Elf_Reloc *paRels = (const Elf_Reloc *)pvRelocs;
552 const unsigned iRelMax = (unsigned)(cbRelocs / sizeof(paRels[0]));
553 AssertMsgReturn(iRelMax == cbRelocs / sizeof(paRels[0]), (FMT_ELF_SIZE "\n", cbRelocs / sizeof(paRels[0])), VERR_IMAGE_TOO_BIG);
554 for (unsigned iRel = 0; iRel < iRelMax; iRel++)
555 {
556 /*
557 * Skip R_XXX_NONE entries early to avoid confusion in the symbol
558 * getter code.
559 */
560#if ELF_MODE == 32
561 if (ELF_R_TYPE(paRels[iRel].r_info) == R_386_NONE)
562 continue;
563#elif ELF_MODE == 64
564 if (ELF_R_TYPE(paRels[iRel].r_info) == R_X86_64_NONE)
565 continue;
566#endif
567
568
569 /*
570 * Get the symbol.
571 */
572 const Elf_Sym *pSym = NULL; /* shut up gcc */
573 Elf_Addr SymValue = 0; /* shut up gcc-4 */
574 int rc = RTLDRELF_NAME(Symbol)(pModElf, BaseAddr, pfnGetImport, pvUser, ELF_R_SYM(paRels[iRel].r_info), &pSym, &SymValue);
575 if (RT_FAILURE(rc))
576 return rc;
577
578 Log3(("rtldrELF: " FMT_ELF_ADDR " %02x %06x - " FMT_ELF_ADDR " %3d %02x %s\n",
579 paRels[iRel].r_offset, ELF_R_TYPE(paRels[iRel].r_info), (unsigned)ELF_R_SYM(paRels[iRel].r_info),
580 SymValue, (unsigned)pSym->st_shndx, pSym->st_info, ELF_STR(pModElf, pSym->st_name)));
581
582 /*
583 * Apply the fixup.
584 */
585 AssertMsgReturn(paRels[iRel].r_offset < cbSec, (FMT_ELF_ADDR " " FMT_ELF_SIZE "\n", paRels[iRel].r_offset, cbSec), VERR_LDRELF_INVALID_RELOCATION_OFFSET);
586#if ELF_MODE == 32
587 const Elf_Addr *pAddrR = (const Elf_Addr *)(pu8SecBaseR + paRels[iRel].r_offset); /* Where to read the addend. */
588#endif
589 Elf_Addr *pAddrW = (Elf_Addr *)(pu8SecBaseW + paRels[iRel].r_offset); /* Where to write the fixup. */
590 switch (ELF_R_TYPE(paRels[iRel].r_info))
591 {
592#if ELF_MODE == 32
593 /*
594 * Absolute addressing.
595 */
596 case R_386_32:
597 {
598 const Elf_Addr Value = SymValue + *pAddrR;
599 *(uint32_t *)pAddrW = Value;
600 Log4((FMT_ELF_ADDR": R_386_32 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
601 SecAddr + paRels[iRel].r_offset + BaseAddr, Value, SymValue));
602 break;
603 }
604
605 /*
606 * PC relative addressing.
607 */
608 case R_386_PC32:
609 {
610 const Elf_Addr SourceAddr = SecAddr + paRels[iRel].r_offset + BaseAddr; /* Where the source really is. */
611 const Elf_Addr Value = SymValue + *(uint32_t *)pAddrR - SourceAddr;
612 *(uint32_t *)pAddrW = Value;
613 Log4((FMT_ELF_ADDR": R_386_PC32 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
614 SourceAddr, Value, SymValue));
615 break;
616 }
617
618 /* ignore */
619 case R_386_NONE:
620 break;
621
622#elif ELF_MODE == 64
623
624 /*
625 * Absolute addressing
626 */
627 case R_X86_64_64:
628 {
629 const Elf_Addr Value = SymValue + paRels[iRel].r_addend;
630 *(uint64_t *)pAddrW = Value;
631 Log4((FMT_ELF_ADDR": R_X86_64_64 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
632 SecAddr + paRels[iRel].r_offset + BaseAddr, Value, SymValue));
633 break;
634 }
635
636 /*
637 * Truncated 32-bit value (zero-extendedable to the 64-bit value).
638 */
639 case R_X86_64_32:
640 {
641 const Elf_Addr Value = SymValue + paRels[iRel].r_addend;
642 *(uint32_t *)pAddrW = (uint32_t)Value;
643 Log4((FMT_ELF_ADDR": R_X86_64_32 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
644 SecAddr + paRels[iRel].r_offset + BaseAddr, Value, SymValue));
645 AssertMsgReturn((Elf_Addr)*(uint32_t *)pAddrW == Value, ("Value=" FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG);
646 break;
647 }
648
649 /*
650 * Truncated 32-bit value (sign-extendedable to the 64-bit value).
651 */
652 case R_X86_64_32S:
653 {
654 const Elf_Addr Value = SymValue + paRels[iRel].r_addend;
655 *(int32_t *)pAddrW = (int32_t)Value;
656 Log4((FMT_ELF_ADDR": R_X86_64_32S Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
657 SecAddr + paRels[iRel].r_offset + BaseAddr, Value, SymValue));
658 AssertMsgReturn((Elf_Addr)*(int32_t *)pAddrW == Value, ("Value=" FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG); /** @todo check the sign-extending here. */
659 break;
660 }
661
662 /*
663 * PC relative addressing.
664 */
665 case R_X86_64_PC32:
666 case R_X86_64_PLT32: /* binutils commit 451875b4f976a527395e9303224c7881b65e12ed feature/regression. */
667 {
668 const Elf_Addr SourceAddr = SecAddr + paRels[iRel].r_offset + BaseAddr; /* Where the source really is. */
669 const Elf_Addr Value = SymValue + paRels[iRel].r_addend - SourceAddr;
670 *(int32_t *)pAddrW = (int32_t)Value;
671 Log4((FMT_ELF_ADDR": R_X86_64_PC32 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
672 SourceAddr, Value, SymValue));
673 AssertMsgReturn((Elf_Addr)*(int32_t *)pAddrW == Value, ("Value=" FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG); /** @todo check the sign-extending here. */
674 break;
675 }
676
677 /* ignore */
678 case R_X86_64_NONE:
679 break;
680#endif
681
682 default:
683 AssertMsgFailed(("Unknown relocation type: %d (iRel=%d iRelMax=%d)\n",
684 ELF_R_TYPE(paRels[iRel].r_info), iRel, iRelMax));
685 return VERR_LDRELF_RELOCATION_NOT_SUPPORTED;
686 }
687 }
688
689 return VINF_SUCCESS;
690}
691
692
693
694/** @copydoc RTLDROPS::pfnClose */
695static DECLCALLBACK(int) RTLDRELF_NAME(Close)(PRTLDRMODINTERNAL pMod)
696{
697 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
698
699 if (pModElf->paShdrs)
700 {
701 RTMemFree(pModElf->paShdrs);
702 pModElf->paShdrs = NULL;
703 }
704
705 if (pModElf->pvBits)
706 {
707 pModElf->Core.pReader->pfnUnmap(pModElf->Core.pReader, pModElf->pvBits);
708 pModElf->pvBits = NULL;
709 }
710
711 return VINF_SUCCESS;
712}
713
714
715/** @copydoc RTLDROPS::Done */
716static DECLCALLBACK(int) RTLDRELF_NAME(Done)(PRTLDRMODINTERNAL pMod)
717{
718 NOREF(pMod); /*PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;*/
719 /** @todo Have to think more about this .... */
720 return -1;
721}
722
723
724/** @copydoc RTLDROPS::EnumSymbols */
725static DECLCALLBACK(int) RTLDRELF_NAME(EnumSymbols)(PRTLDRMODINTERNAL pMod, unsigned fFlags, const void *pvBits, RTUINTPTR BaseAddress,
726 PFNRTLDRENUMSYMS pfnCallback, void *pvUser)
727{
728 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
729 NOREF(pvBits);
730
731 /*
732 * Validate the input.
733 */
734 Elf_Addr BaseAddr = (Elf_Addr)BaseAddress;
735 AssertMsgReturn((RTUINTPTR)BaseAddr == BaseAddress, ("%RTptr", BaseAddress), VERR_IMAGE_BASE_TOO_HIGH);
736
737 /*
738 * Make sure we've got the string and symbol tables. (We don't need the pvBits.)
739 */
740 int rc = RTLDRELF_NAME(MapBits)(pModElf, false);
741 if (RT_FAILURE(rc))
742 return rc;
743
744 /*
745 * Enumerate the symbol table.
746 */
747 const Elf_Sym *paSyms = pModElf->paSyms;
748 unsigned cSyms = pModElf->cSyms;
749 for (unsigned iSym = 1; iSym < cSyms; iSym++)
750 {
751 /*
752 * Skip imports (undefined).
753 */
754 if (paSyms[iSym].st_shndx != SHN_UNDEF)
755 {
756 /*
757 * Calc value and get name.
758 */
759 Elf_Addr Value;
760 if (paSyms[iSym].st_shndx == SHN_ABS)
761 /* absolute symbols are not subject to any relocation. */
762 Value = paSyms[iSym].st_value;
763 else if (paSyms[iSym].st_shndx < pModElf->Ehdr.e_shnum)
764 {
765 if (pModElf->Ehdr.e_type == ET_REL)
766 /* relative to the section. */
767 Value = BaseAddr + paSyms[iSym].st_value + pModElf->paShdrs[paSyms[iSym].st_shndx].sh_addr;
768 else /* Fixed up for link address. */
769 Value = BaseAddr + paSyms[iSym].st_value - pModElf->LinkAddress;
770 }
771 else
772 {
773 AssertMsgFailed(("Arg! paSyms[%u].st_shndx=" FMT_ELF_HALF "\n", iSym, paSyms[iSym].st_shndx));
774 return VERR_BAD_EXE_FORMAT;
775 }
776
777 AssertMsgReturn(paSyms[iSym].st_name < pModElf->cbStr,
778 ("String outside string table! iSym=%d paSyms[iSym].st_name=%#x\n", iSym, paSyms[iSym].st_name),
779 VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET);
780
781 const char *pszName = ELF_STR(pModElf, paSyms[iSym].st_name);
782 /* String termination was already checked when the string table was mapped. */
783 if ( (pszName && *pszName)
784 && ( (fFlags & RTLDR_ENUM_SYMBOL_FLAGS_ALL)
785 || ELF_ST_BIND(paSyms[iSym].st_info) == STB_GLOBAL)
786 )
787 {
788 /*
789 * Call back.
790 */
791 AssertMsgReturn(Value == (RTUINTPTR)Value, (FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG);
792 rc = pfnCallback(pMod, pszName, ~0U, (RTUINTPTR)Value, pvUser);
793 if (rc)
794 return rc;
795 }
796 }
797 }
798
799 return VINF_SUCCESS;
800}
801
802
803/** @copydoc RTLDROPS::GetImageSize */
804static DECLCALLBACK(size_t) RTLDRELF_NAME(GetImageSize)(PRTLDRMODINTERNAL pMod)
805{
806 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
807
808 return pModElf->cbImage;
809}
810
811
812/** @copydoc RTLDROPS::GetBits */
813static DECLCALLBACK(int) RTLDRELF_NAME(GetBits)(PRTLDRMODINTERNAL pMod, void *pvBits, RTUINTPTR BaseAddress, PFNRTLDRIMPORT pfnGetImport, void *pvUser)
814{
815 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
816
817 /*
818 * This operation is currently only available on relocatable images.
819 */
820 switch (pModElf->Ehdr.e_type)
821 {
822 case ET_REL:
823 break;
824 case ET_EXEC:
825 Log(("RTLdrELF: %s: Executable images are not supported yet!\n", pModElf->Core.pReader->pfnLogName(pModElf->Core.pReader)));
826 return VERR_LDRELF_EXEC;
827 case ET_DYN:
828 Log(("RTLdrELF: %s: Dynamic images are not supported yet!\n", pModElf->Core.pReader->pfnLogName(pModElf->Core.pReader)));
829 return VERR_LDRELF_DYN;
830 default: AssertFailedReturn(VERR_BAD_EXE_FORMAT);
831 }
832
833 /*
834 * Load the bits into pvBits.
835 */
836 const Elf_Shdr *paShdrs = pModElf->paShdrs;
837 for (unsigned iShdr = 0; iShdr < pModElf->Ehdr.e_shnum; iShdr++)
838 {
839 if (paShdrs[iShdr].sh_flags & SHF_ALLOC)
840 {
841 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);
842 switch (paShdrs[iShdr].sh_type)
843 {
844 case SHT_NOBITS:
845 memset((uint8_t *)pvBits + paShdrs[iShdr].sh_addr, 0, (size_t)paShdrs[iShdr].sh_size);
846 break;
847
848 case SHT_PROGBITS:
849 default:
850 {
851 int rc = pModElf->Core.pReader->pfnRead(pModElf->Core.pReader, (uint8_t *)pvBits + paShdrs[iShdr].sh_addr,
852 (size_t)paShdrs[iShdr].sh_size, paShdrs[iShdr].sh_offset);
853 if (RT_FAILURE(rc))
854 {
855 Log(("RTLdrELF: %s: Read error when reading " FMT_ELF_SIZE " bytes at " FMT_ELF_OFF ", iShdr=%d\n",
856 pModElf->Core.pReader->pfnLogName(pModElf->Core.pReader),
857 paShdrs[iShdr].sh_size, paShdrs[iShdr].sh_offset, iShdr));
858 return rc;
859 }
860 }
861 }
862 }
863 }
864
865 /*
866 * Relocate the image.
867 */
868 return pModElf->Core.pOps->pfnRelocate(pMod, pvBits, BaseAddress, ~(RTUINTPTR)0, pfnGetImport, pvUser);
869}
870
871
872/** @copydoc RTLDROPS::Relocate */
873static DECLCALLBACK(int) RTLDRELF_NAME(Relocate)(PRTLDRMODINTERNAL pMod, void *pvBits, RTUINTPTR NewBaseAddress,
874 RTUINTPTR OldBaseAddress, PFNRTLDRIMPORT pfnGetImport, void *pvUser)
875{
876 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
877#ifdef LOG_ENABLED
878 const char *pszLogName = pModElf->Core.pReader->pfnLogName(pModElf->Core.pReader);
879#endif
880 NOREF(OldBaseAddress);
881
882 /*
883 * This operation is currently only available on relocatable images.
884 */
885 switch (pModElf->Ehdr.e_type)
886 {
887 case ET_REL:
888 break;
889 case ET_EXEC:
890 Log(("RTLdrELF: %s: Executable images are not supported yet!\n", pszLogName));
891 return VERR_LDRELF_EXEC;
892 case ET_DYN:
893 Log(("RTLdrELF: %s: Dynamic images are not supported yet!\n", pszLogName));
894 return VERR_LDRELF_DYN;
895 default: AssertFailedReturn(VERR_BAD_EXE_FORMAT);
896 }
897
898 /*
899 * Validate the input.
900 */
901 Elf_Addr BaseAddr = (Elf_Addr)NewBaseAddress;
902 AssertMsgReturn((RTUINTPTR)BaseAddr == NewBaseAddress, ("%RTptr", NewBaseAddress), VERR_IMAGE_BASE_TOO_HIGH);
903
904 /*
905 * Map the image bits if not already done and setup pointer into it.
906 */
907 int rc = RTLDRELF_NAME(MapBits)(pModElf, true);
908 if (RT_FAILURE(rc))
909 return rc;
910
911 /*
912 * Iterate the sections looking for interesting SHT_REL[A] sections.
913 * SHT_REL[A] sections have the section index of the section they contain fixups
914 * for in the sh_info member.
915 */
916 const Elf_Shdr *paShdrs = pModElf->paShdrs;
917 Log2(("rtLdrElf: %s: Fixing up image\n", pszLogName));
918 for (unsigned iShdr = 0; iShdr < pModElf->Ehdr.e_shnum; iShdr++)
919 {
920 const Elf_Shdr *pShdrRel = &paShdrs[iShdr];
921
922 /*
923 * Skip sections without interest to us.
924 */
925#if ELF_MODE == 32
926 if (pShdrRel->sh_type != SHT_REL)
927#else
928 if (pShdrRel->sh_type != SHT_RELA)
929#endif
930 continue;
931 if (pShdrRel->sh_info >= pModElf->Ehdr.e_shnum)
932 continue;
933 const Elf_Shdr *pShdr = &paShdrs[pShdrRel->sh_info]; /* the section to fixup. */
934 if (!(pShdr->sh_flags & SHF_ALLOC))
935 continue;
936
937 /*
938 * Relocate the section.
939 */
940 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",
941 pszLogName, (int)pShdrRel->sh_info, ELF_SH_STR(pModElf, pShdr->sh_name), (int)pShdr->sh_info, (int)pShdr->sh_link,
942 iShdr, ELF_SH_STR(pModElf, pShdrRel->sh_name), (int)pShdrRel->sh_info, (int)pShdrRel->sh_link));
943
944 /** @todo Make RelocateSection a function pointer so we can select the one corresponding to the machine when opening the image. */
945 if (pModElf->Ehdr.e_type == ET_REL)
946 rc = RTLDRELF_NAME(RelocateSection)(pModElf, BaseAddr, pfnGetImport, pvUser,
947 pShdr->sh_addr,
948 pShdr->sh_size,
949 (const uint8_t *)pModElf->pvBits + pShdr->sh_offset,
950 (uint8_t *)pvBits + pShdr->sh_addr,
951 (const uint8_t *)pModElf->pvBits + pShdrRel->sh_offset,
952 pShdrRel->sh_size);
953 else
954 rc = RTLDRELF_NAME(RelocateSectionExecDyn)(pModElf, BaseAddr, pfnGetImport, pvUser,
955 pShdr->sh_addr,
956 pShdr->sh_size,
957 (const uint8_t *)pModElf->pvBits + pShdr->sh_offset,
958 (uint8_t *)pvBits + pShdr->sh_addr,
959 (const uint8_t *)pModElf->pvBits + pShdrRel->sh_offset,
960 pShdrRel->sh_size);
961 if (RT_FAILURE(rc))
962 return rc;
963 }
964 return VINF_SUCCESS;
965}
966
967
968/**
969 * Worker for pfnGetSymbolEx.
970 */
971static int RTLDRELF_NAME(ReturnSymbol)(PRTLDRMODELF pThis, const Elf_Sym *pSym, Elf_Addr uBaseAddr, PRTUINTPTR pValue)
972{
973 Elf_Addr Value;
974 if (pSym->st_shndx == SHN_ABS)
975 /* absolute symbols are not subject to any relocation. */
976 Value = pSym->st_value;
977 else if (pSym->st_shndx < pThis->Ehdr.e_shnum)
978 {
979 if (pThis->Ehdr.e_type == ET_REL)
980 /* relative to the section. */
981 Value = uBaseAddr + pSym->st_value + pThis->paShdrs[pSym->st_shndx].sh_addr;
982 else /* Fixed up for link address. */
983 Value = uBaseAddr + pSym->st_value - pThis->LinkAddress;
984 }
985 else
986 {
987 AssertMsgFailed(("Arg! pSym->st_shndx=%d\n", pSym->st_shndx));
988 return VERR_BAD_EXE_FORMAT;
989 }
990 AssertMsgReturn(Value == (RTUINTPTR)Value, (FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG);
991 *pValue = (RTUINTPTR)Value;
992 return VINF_SUCCESS;
993}
994
995
996/** @copydoc RTLDROPS::pfnGetSymbolEx */
997static DECLCALLBACK(int) RTLDRELF_NAME(GetSymbolEx)(PRTLDRMODINTERNAL pMod, const void *pvBits, RTUINTPTR BaseAddress,
998 uint32_t iOrdinal, const char *pszSymbol, RTUINTPTR *pValue)
999{
1000 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
1001 NOREF(pvBits);
1002
1003 /*
1004 * Validate the input.
1005 */
1006 Elf_Addr uBaseAddr = (Elf_Addr)BaseAddress;
1007 AssertMsgReturn((RTUINTPTR)uBaseAddr == BaseAddress, ("%RTptr", BaseAddress), VERR_IMAGE_BASE_TOO_HIGH);
1008
1009 /*
1010 * Map the image bits if not already done and setup pointer into it.
1011 */
1012 int rc = RTLDRELF_NAME(MapBits)(pModElf, true);
1013 if (RT_FAILURE(rc))
1014 return rc;
1015
1016 /*
1017 * Calc all kinds of pointers before we start iterating the symbol table.
1018 */
1019 const Elf_Sym *paSyms = pModElf->paSyms;
1020 unsigned cSyms = pModElf->cSyms;
1021 if (iOrdinal == UINT32_MAX)
1022 {
1023 const char *pStr = pModElf->pStr;
1024 for (unsigned iSym = 1; iSym < cSyms; iSym++)
1025 {
1026 /* Undefined symbols are not exports, they are imports. */
1027 if ( paSyms[iSym].st_shndx != SHN_UNDEF
1028 && ( ELF_ST_BIND(paSyms[iSym].st_info) == STB_GLOBAL
1029 || ELF_ST_BIND(paSyms[iSym].st_info) == STB_WEAK))
1030 {
1031 /* Validate the name string and try match with it. */
1032 if (paSyms[iSym].st_name < pModElf->cbStr)
1033 {
1034 if (!strcmp(pszSymbol, pStr + paSyms[iSym].st_name))
1035 {
1036 /* matched! */
1037 return RTLDRELF_NAME(ReturnSymbol)(pModElf, &paSyms[iSym], uBaseAddr, pValue);
1038 }
1039 }
1040 else
1041 {
1042 AssertMsgFailed(("String outside string table! iSym=%d paSyms[iSym].st_name=%#x\n", iSym, paSyms[iSym].st_name));
1043 return VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET;
1044 }
1045 }
1046 }
1047 }
1048 else if (iOrdinal < cSyms)
1049 {
1050 if ( paSyms[iOrdinal].st_shndx != SHN_UNDEF
1051 && ( ELF_ST_BIND(paSyms[iOrdinal].st_info) == STB_GLOBAL
1052 || ELF_ST_BIND(paSyms[iOrdinal].st_info) == STB_WEAK))
1053 return RTLDRELF_NAME(ReturnSymbol)(pModElf, &paSyms[iOrdinal], uBaseAddr, pValue);
1054 }
1055
1056 return VERR_SYMBOL_NOT_FOUND;
1057}
1058
1059
1060/** @copydoc RTLDROPS::pfnEnumDbgInfo */
1061static DECLCALLBACK(int) RTLDRELF_NAME(EnumDbgInfo)(PRTLDRMODINTERNAL pMod, const void *pvBits,
1062 PFNRTLDRENUMDBG pfnCallback, void *pvUser)
1063{
1064 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
1065 RT_NOREF_PV(pvBits);
1066
1067 /*
1068 * Map the image bits if not already done and setup pointer into it.
1069 */
1070 int rc = RTLDRELF_NAME(MapBits)(pModElf, true);
1071 if (RT_FAILURE(rc))
1072 return rc;
1073
1074 /*
1075 * Do the enumeration.
1076 */
1077 const Elf_Shdr *paShdrs = pModElf->paOrgShdrs;
1078 for (unsigned iShdr = 0; iShdr < pModElf->Ehdr.e_shnum; iShdr++)
1079 {
1080 /* Debug sections are expected to be PROGBITS and not allocated. */
1081 if (paShdrs[iShdr].sh_type != SHT_PROGBITS)
1082 continue;
1083 if (paShdrs[iShdr].sh_flags & SHF_ALLOC)
1084 continue;
1085
1086 RTLDRDBGINFO DbgInfo;
1087 const char *pszSectName = ELF_SH_STR(pModElf, paShdrs[iShdr].sh_name);
1088 if ( !strncmp(pszSectName, RT_STR_TUPLE(".debug_"))
1089 || !strcmp(pszSectName, ".WATCOM_references") )
1090 {
1091 RT_ZERO(DbgInfo.u);
1092 DbgInfo.enmType = RTLDRDBGINFOTYPE_DWARF;
1093 DbgInfo.pszExtFile = NULL;
1094 DbgInfo.offFile = paShdrs[iShdr].sh_offset;
1095 DbgInfo.cb = paShdrs[iShdr].sh_size;
1096 DbgInfo.u.Dwarf.pszSection = pszSectName;
1097 }
1098 else if (!strcmp(pszSectName, ".gnu_debuglink"))
1099 {
1100 if ((paShdrs[iShdr].sh_size & 3) || paShdrs[iShdr].sh_size < 8)
1101 return VERR_BAD_EXE_FORMAT;
1102
1103 RT_ZERO(DbgInfo.u);
1104 DbgInfo.enmType = RTLDRDBGINFOTYPE_DWARF_DWO;
1105 DbgInfo.pszExtFile = (const char *)((uintptr_t)pModElf->pvBits + (uintptr_t)paShdrs[iShdr].sh_offset);
1106 if (!RTStrEnd(DbgInfo.pszExtFile, paShdrs[iShdr].sh_size))
1107 return VERR_BAD_EXE_FORMAT;
1108 DbgInfo.u.Dwo.uCrc32 = *(uint32_t *)((uintptr_t)DbgInfo.pszExtFile + (uintptr_t)paShdrs[iShdr].sh_size
1109 - sizeof(uint32_t));
1110 DbgInfo.offFile = -1;
1111 DbgInfo.cb = 0;
1112 }
1113 else
1114 continue;
1115
1116 DbgInfo.LinkAddress = NIL_RTLDRADDR;
1117 DbgInfo.iDbgInfo = iShdr - 1;
1118
1119 rc = pfnCallback(pMod, &DbgInfo, pvUser);
1120 if (rc != VINF_SUCCESS)
1121 return rc;
1122
1123 }
1124
1125 return VINF_SUCCESS;
1126}
1127
1128
1129/**
1130 * Helper that locates the first allocated section.
1131 *
1132 * @returns Pointer to the section header if found, NULL if none.
1133 * @param pShdr The section header to start searching at.
1134 * @param cLeft The number of section headers left to search. Can be 0.
1135 */
1136static const Elf_Shdr *RTLDRELF_NAME(GetFirstAllocatedSection)(const Elf_Shdr *pShdr, unsigned cLeft)
1137{
1138 while (cLeft-- > 0)
1139 {
1140 if (pShdr->sh_flags & SHF_ALLOC)
1141 return pShdr;
1142 pShdr++;
1143 }
1144 return NULL;
1145}
1146
1147/** @copydoc RTLDROPS::pfnEnumSegments. */
1148static DECLCALLBACK(int) RTLDRELF_NAME(EnumSegments)(PRTLDRMODINTERNAL pMod, PFNRTLDRENUMSEGS pfnCallback, void *pvUser)
1149{
1150 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
1151
1152 /*
1153 * Map the image bits if not already done and setup pointer into it.
1154 */
1155 int rc = RTLDRELF_NAME(MapBits)(pModElf, true);
1156 if (RT_FAILURE(rc))
1157 return rc;
1158
1159 /*
1160 * Do the enumeration.
1161 */
1162 char szName[32];
1163 Elf_Addr uPrevMappedRva = 0;
1164 const Elf_Shdr *paShdrs = pModElf->paShdrs;
1165 const Elf_Shdr *paOrgShdrs = pModElf->paOrgShdrs;
1166 for (unsigned iShdr = 1; iShdr < pModElf->Ehdr.e_shnum; iShdr++)
1167 {
1168 RTLDRSEG Seg;
1169 Seg.pszName = ELF_SH_STR(pModElf, paShdrs[iShdr].sh_name);
1170 Seg.cchName = (uint32_t)strlen(Seg.pszName);
1171 if (Seg.cchName == 0)
1172 {
1173 Seg.pszName = szName;
1174 Seg.cchName = (uint32_t)RTStrPrintf(szName, sizeof(szName), "UnamedSect%02u", iShdr);
1175 }
1176 Seg.SelFlat = 0;
1177 Seg.Sel16bit = 0;
1178 Seg.fFlags = 0;
1179 Seg.fProt = RTMEM_PROT_READ;
1180 if (paShdrs[iShdr].sh_flags & SHF_WRITE)
1181 Seg.fProt |= RTMEM_PROT_WRITE;
1182 if (paShdrs[iShdr].sh_flags & SHF_EXECINSTR)
1183 Seg.fProt |= RTMEM_PROT_EXEC;
1184 Seg.cb = paShdrs[iShdr].sh_size;
1185 Seg.Alignment = paShdrs[iShdr].sh_addralign;
1186 if (paShdrs[iShdr].sh_flags & SHF_ALLOC)
1187 {
1188 Seg.LinkAddress = paOrgShdrs[iShdr].sh_addr;
1189 Seg.RVA = paShdrs[iShdr].sh_addr;
1190 const Elf_Shdr *pShdr2 = RTLDRELF_NAME(GetFirstAllocatedSection)(&paShdrs[iShdr + 1],
1191 pModElf->Ehdr.e_shnum - iShdr - 1);
1192 if ( pShdr2
1193 && pShdr2->sh_addr >= paShdrs[iShdr].sh_addr
1194 && Seg.RVA >= uPrevMappedRva)
1195 Seg.cbMapped = pShdr2->sh_addr - paShdrs[iShdr].sh_addr;
1196 else
1197 Seg.cbMapped = RT_MAX(paShdrs[iShdr].sh_size, paShdrs[iShdr].sh_addralign);
1198 uPrevMappedRva = Seg.RVA;
1199 }
1200 else
1201 {
1202 Seg.LinkAddress = NIL_RTLDRADDR;
1203 Seg.RVA = NIL_RTLDRADDR;
1204 Seg.cbMapped = NIL_RTLDRADDR;
1205 }
1206 if (paShdrs[iShdr].sh_type != SHT_NOBITS)
1207 {
1208 Seg.offFile = paShdrs[iShdr].sh_offset;
1209 Seg.cbFile = paShdrs[iShdr].sh_size;
1210 }
1211 else
1212 {
1213 Seg.offFile = -1;
1214 Seg.cbFile = 0;
1215 }
1216
1217 rc = pfnCallback(pMod, &Seg, pvUser);
1218 if (rc != VINF_SUCCESS)
1219 return rc;
1220 }
1221
1222 return VINF_SUCCESS;
1223}
1224
1225
1226/** @copydoc RTLDROPS::pfnLinkAddressToSegOffset. */
1227static DECLCALLBACK(int) RTLDRELF_NAME(LinkAddressToSegOffset)(PRTLDRMODINTERNAL pMod, RTLDRADDR LinkAddress,
1228 uint32_t *piSeg, PRTLDRADDR poffSeg)
1229{
1230 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
1231
1232 const Elf_Shdr *pShdrEnd = NULL;
1233 unsigned cLeft = pModElf->Ehdr.e_shnum - 1;
1234 const Elf_Shdr *pShdr = &pModElf->paOrgShdrs[cLeft];
1235 while (cLeft-- > 0)
1236 {
1237 if (pShdr->sh_flags & SHF_ALLOC)
1238 {
1239 RTLDRADDR offSeg = LinkAddress - pShdr->sh_addr;
1240 if (offSeg < pShdr->sh_size)
1241 {
1242 *poffSeg = offSeg;
1243 *piSeg = cLeft;
1244 return VINF_SUCCESS;
1245 }
1246 if (offSeg == pShdr->sh_size)
1247 pShdrEnd = pShdr;
1248 }
1249 pShdr--;
1250 }
1251
1252 if (pShdrEnd)
1253 {
1254 *poffSeg = pShdrEnd->sh_size;
1255 *piSeg = pShdrEnd - pModElf->paOrgShdrs - 1;
1256 return VINF_SUCCESS;
1257 }
1258
1259 return VERR_LDR_INVALID_LINK_ADDRESS;
1260}
1261
1262
1263/** @copydoc RTLDROPS::pfnLinkAddressToRva. */
1264static DECLCALLBACK(int) RTLDRELF_NAME(LinkAddressToRva)(PRTLDRMODINTERNAL pMod, RTLDRADDR LinkAddress, PRTLDRADDR pRva)
1265{
1266 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
1267 uint32_t iSeg;
1268 RTLDRADDR offSeg;
1269 int rc = RTLDRELF_NAME(LinkAddressToSegOffset)(pMod, LinkAddress, &iSeg, &offSeg);
1270 if (RT_SUCCESS(rc))
1271 *pRva = pModElf->paShdrs[iSeg + 1].sh_addr + offSeg;
1272 return rc;
1273}
1274
1275
1276/** @copydoc RTLDROPS::pfnSegOffsetToRva. */
1277static DECLCALLBACK(int) RTLDRELF_NAME(SegOffsetToRva)(PRTLDRMODINTERNAL pMod, uint32_t iSeg, RTLDRADDR offSeg,
1278 PRTLDRADDR pRva)
1279{
1280 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
1281 if (iSeg >= pModElf->Ehdr.e_shnum - 1U)
1282 return VERR_LDR_INVALID_SEG_OFFSET;
1283
1284 iSeg++; /* skip section 0 */
1285 if (offSeg > pModElf->paShdrs[iSeg].sh_size)
1286 {
1287 const Elf_Shdr *pShdr2 = RTLDRELF_NAME(GetFirstAllocatedSection)(&pModElf->paShdrs[iSeg + 1],
1288 pModElf->Ehdr.e_shnum - iSeg - 1);
1289 if ( !pShdr2
1290 || offSeg > (pShdr2->sh_addr - pModElf->paShdrs[iSeg].sh_addr))
1291 return VERR_LDR_INVALID_SEG_OFFSET;
1292 }
1293
1294 if (!(pModElf->paShdrs[iSeg].sh_flags & SHF_ALLOC))
1295 return VERR_LDR_INVALID_SEG_OFFSET;
1296
1297 *pRva = pModElf->paShdrs[iSeg].sh_addr;
1298 return VINF_SUCCESS;
1299}
1300
1301
1302/** @copydoc RTLDROPS::pfnRvaToSegOffset. */
1303static DECLCALLBACK(int) RTLDRELF_NAME(RvaToSegOffset)(PRTLDRMODINTERNAL pMod, RTLDRADDR Rva,
1304 uint32_t *piSeg, PRTLDRADDR poffSeg)
1305{
1306 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
1307
1308 Elf_Addr PrevAddr = 0;
1309 unsigned cLeft = pModElf->Ehdr.e_shnum - 1;
1310 const Elf_Shdr *pShdr = &pModElf->paShdrs[cLeft];
1311 while (cLeft-- > 0)
1312 {
1313 if (pShdr->sh_flags & SHF_ALLOC)
1314 {
1315 Elf_Addr cbSeg = PrevAddr ? PrevAddr - pShdr->sh_addr : pShdr->sh_size;
1316 RTLDRADDR offSeg = Rva - pShdr->sh_addr;
1317 if (offSeg <= cbSeg)
1318 {
1319 *poffSeg = offSeg;
1320 *piSeg = cLeft;
1321 return VINF_SUCCESS;
1322 }
1323 PrevAddr = pShdr->sh_addr;
1324 }
1325 pShdr--;
1326 }
1327
1328 return VERR_LDR_INVALID_RVA;
1329}
1330
1331
1332/** @callback_method_impl{FNRTLDRIMPORT, Stub used by ReadDbgInfo.} */
1333static DECLCALLBACK(int) RTLDRELF_NAME(GetImportStubCallback)(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol,
1334 unsigned uSymbol, PRTLDRADDR pValue, void *pvUser)
1335{
1336 RT_NOREF_PV(hLdrMod); RT_NOREF_PV(pszModule); RT_NOREF_PV(pszSymbol);
1337 RT_NOREF_PV(uSymbol); RT_NOREF_PV(pValue); RT_NOREF_PV(pvUser);
1338 return VERR_SYMBOL_NOT_FOUND;
1339}
1340
1341
1342/** @copydoc RTLDROPS::pfnReadDbgInfo. */
1343static DECLCALLBACK(int) RTLDRELF_NAME(ReadDbgInfo)(PRTLDRMODINTERNAL pMod, uint32_t iDbgInfo, RTFOFF off,
1344 size_t cb, void *pvBuf)
1345{
1346 PRTLDRMODELF pThis = (PRTLDRMODELF)pMod;
1347 LogFlow(("%s: iDbgInfo=%#x off=%RTfoff cb=%#zu\n", __FUNCTION__, iDbgInfo, off, cb));
1348
1349 /*
1350 * Input validation.
1351 */
1352 AssertReturn(iDbgInfo < pThis->Ehdr.e_shnum && iDbgInfo + 1 < pThis->Ehdr.e_shnum, VERR_INVALID_PARAMETER);
1353 iDbgInfo++;
1354 AssertReturn(!(pThis->paShdrs[iDbgInfo].sh_flags & SHF_ALLOC), VERR_INVALID_PARAMETER);
1355 AssertReturn(pThis->paShdrs[iDbgInfo].sh_type == SHT_PROGBITS, VERR_INVALID_PARAMETER);
1356 AssertReturn(pThis->paShdrs[iDbgInfo].sh_offset == (uint64_t)off, VERR_INVALID_PARAMETER);
1357 AssertReturn(pThis->paShdrs[iDbgInfo].sh_size == cb, VERR_INVALID_PARAMETER);
1358 uint64_t cbRawImage = pThis->Core.pReader->pfnSize(pThis->Core.pReader);
1359 AssertReturn(off >= 0 && cb <= cbRawImage && (uint64_t)off + cb <= cbRawImage, VERR_INVALID_PARAMETER);
1360
1361 /*
1362 * Read it from the file and look for fixup sections.
1363 */
1364 int rc;
1365 if (pThis->pvBits)
1366 memcpy(pvBuf, (const uint8_t *)pThis->pvBits + (size_t)off, cb);
1367 else
1368 {
1369 rc = pThis->Core.pReader->pfnRead(pThis->Core.pReader, pvBuf, cb, off);
1370 if (RT_FAILURE(rc))
1371 return rc;
1372 }
1373
1374 uint32_t iRelocs = iDbgInfo + 1;
1375 if ( iRelocs >= pThis->Ehdr.e_shnum
1376 || pThis->paShdrs[iRelocs].sh_info != iDbgInfo
1377 || ( pThis->paShdrs[iRelocs].sh_type != SHT_REL
1378 && pThis->paShdrs[iRelocs].sh_type != SHT_RELA) )
1379 {
1380 iRelocs = 0;
1381 while ( iRelocs < pThis->Ehdr.e_shnum
1382 && ( pThis->paShdrs[iRelocs].sh_info != iDbgInfo
1383 || ( pThis->paShdrs[iRelocs].sh_type != SHT_REL
1384 && pThis->paShdrs[iRelocs].sh_type != SHT_RELA)) )
1385 iRelocs++;
1386 }
1387 if ( iRelocs < pThis->Ehdr.e_shnum
1388 && pThis->paShdrs[iRelocs].sh_size > 0)
1389 {
1390 /*
1391 * Load the relocations.
1392 */
1393 uint8_t *pbRelocsBuf = NULL;
1394 const uint8_t *pbRelocs;
1395 if (pThis->pvBits)
1396 pbRelocs = (const uint8_t *)pThis->pvBits + pThis->paShdrs[iRelocs].sh_offset;
1397 else
1398 {
1399 pbRelocs = pbRelocsBuf = (uint8_t *)RTMemTmpAlloc(pThis->paShdrs[iRelocs].sh_size);
1400 if (!pbRelocsBuf)
1401 return VERR_NO_TMP_MEMORY;
1402 rc = pThis->Core.pReader->pfnRead(pThis->Core.pReader, pbRelocsBuf,
1403 pThis->paShdrs[iRelocs].sh_size,
1404 pThis->paShdrs[iRelocs].sh_offset);
1405 if (RT_FAILURE(rc))
1406 {
1407 RTMemTmpFree(pbRelocsBuf);
1408 return rc;
1409 }
1410 }
1411
1412 /*
1413 * Apply the relocations.
1414 */
1415 if (pThis->Ehdr.e_type == ET_REL)
1416 rc = RTLDRELF_NAME(RelocateSection)(pThis, pThis->LinkAddress,
1417 RTLDRELF_NAME(GetImportStubCallback), NULL /*pvUser*/,
1418 pThis->paShdrs[iDbgInfo].sh_addr,
1419 pThis->paShdrs[iDbgInfo].sh_size,
1420 (const uint8_t *)pvBuf,
1421 (uint8_t *)pvBuf,
1422 pbRelocs,
1423 pThis->paShdrs[iRelocs].sh_size);
1424 else
1425 rc = RTLDRELF_NAME(RelocateSectionExecDyn)(pThis, pThis->LinkAddress,
1426 RTLDRELF_NAME(GetImportStubCallback), NULL /*pvUser*/,
1427 pThis->paShdrs[iDbgInfo].sh_addr,
1428 pThis->paShdrs[iDbgInfo].sh_size,
1429 (const uint8_t *)pvBuf,
1430 (uint8_t *)pvBuf,
1431 pbRelocs,
1432 pThis->paShdrs[iRelocs].sh_size);
1433
1434 RTMemTmpFree(pbRelocsBuf);
1435 }
1436 else
1437 rc = VINF_SUCCESS;
1438 return rc;
1439}
1440
1441
1442/**
1443 * @interface_method_impl{RTLDROPS,pfnUnwindFrame}
1444 */
1445static DECLCALLBACK(int)
1446RTLDRELF_NAME(UnwindFrame)(PRTLDRMODINTERNAL pMod, void const *pvBits, uint32_t iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState)
1447{
1448 PRTLDRMODELF pThis = (PRTLDRMODELF)pMod;
1449 LogFlow(("%s: iSeg=%#x off=%RTptr\n", __FUNCTION__, iSeg, off));
1450
1451 /*
1452 * Process the input address, making us both RVA and proper seg:offset out of it.
1453 */
1454 int rc;
1455 RTLDRADDR uRva = off;
1456 if (iSeg == UINT32_MAX)
1457 rc = RTLDRELF_NAME(RvaToSegOffset)(pMod, uRva, &iSeg, &off);
1458 else
1459 rc = RTLDRELF_NAME(SegOffsetToRva)(pMod, iSeg, off, &uRva);
1460 AssertRCReturn(rc, rc);
1461
1462 /*
1463 * Map the image bits if not already done and setup pointer into it.
1464 */
1465 RT_NOREF(pvBits); /** @todo Try use passed in pvBits? */
1466 rc = RTLDRELF_NAME(MapBits)(pThis, true);
1467 if (RT_FAILURE(rc))
1468 return rc;
1469
1470 /*
1471 * Do we need to search for .eh_frame and .eh_frame_hdr?
1472 */
1473 if (pThis->iShEhFrame == 0)
1474 {
1475 pThis->iShEhFrame = ~0U;
1476 pThis->iShEhFrameHdr = ~0U;
1477 unsigned cLeft = 2;
1478 for (unsigned iShdr = 1; iShdr < pThis->Ehdr.e_shnum; iShdr++)
1479 {
1480 const char *pszName = ELF_SH_STR(pThis, pThis->paShdrs[iShdr].sh_name);
1481 if ( pszName[0] == '.'
1482 && pszName[1] == 'e'
1483 && pszName[2] == 'h'
1484 && pszName[3] == '_'
1485 && pszName[4] == 'f'
1486 && pszName[5] == 'r'
1487 && pszName[6] == 'a'
1488 && pszName[7] == 'm'
1489 && pszName[8] == 'e')
1490 {
1491 if (pszName[9] == '\0')
1492 pThis->iShEhFrame = iShdr;
1493 else if ( pszName[9] == '_'
1494 && pszName[10] == 'h'
1495 && pszName[11] == 'd'
1496 && pszName[12] == 'r'
1497 && pszName[13] == '\0')
1498 pThis->iShEhFrameHdr = iShdr;
1499 else
1500 continue;
1501 if (--cLeft == 0)
1502 break;
1503 }
1504 }
1505 }
1506
1507 /*
1508 * Any info present?
1509 */
1510 unsigned iShdr = pThis->iShEhFrame;
1511 if ( iShdr != ~0U
1512 && pThis->paShdrs[iShdr].sh_size > 0)
1513 {
1514 if (pThis->paShdrs[iShdr].sh_flags & SHF_ALLOC)
1515 return rtDwarfUnwind_EhData((uint8_t const *)pThis->pvBits + pThis->paShdrs[iShdr].sh_addr,
1516 pThis->paShdrs[iShdr].sh_size, pThis->paShdrs[iShdr].sh_addr,
1517 iSeg, off, uRva, pState, pThis->Core.enmArch);
1518 }
1519 return VERR_DBG_NO_UNWIND_INFO;
1520}
1521
1522
1523/**
1524 * The ELF module operations.
1525 */
1526static RTLDROPS RTLDRELF_MID(s_rtldrElf,Ops) =
1527{
1528#if ELF_MODE == 32
1529 "elf32",
1530#elif ELF_MODE == 64
1531 "elf64",
1532#endif
1533 RTLDRELF_NAME(Close),
1534 NULL, /* Get Symbol */
1535 RTLDRELF_NAME(Done),
1536 RTLDRELF_NAME(EnumSymbols),
1537 /* ext: */
1538 RTLDRELF_NAME(GetImageSize),
1539 RTLDRELF_NAME(GetBits),
1540 RTLDRELF_NAME(Relocate),
1541 RTLDRELF_NAME(GetSymbolEx),
1542 NULL /*pfnQueryForwarderInfo*/,
1543 RTLDRELF_NAME(EnumDbgInfo),
1544 RTLDRELF_NAME(EnumSegments),
1545 RTLDRELF_NAME(LinkAddressToSegOffset),
1546 RTLDRELF_NAME(LinkAddressToRva),
1547 RTLDRELF_NAME(SegOffsetToRva),
1548 RTLDRELF_NAME(RvaToSegOffset),
1549 RTLDRELF_NAME(ReadDbgInfo),
1550 NULL /*pfnQueryProp*/,
1551 NULL /*pfnVerifySignature*/,
1552 NULL /*pfnHashImage*/,
1553 RTLDRELF_NAME(UnwindFrame),
1554 42
1555};
1556
1557
1558
1559/**
1560 * Validates the ELF header.
1561 *
1562 * @returns iprt status code.
1563 * @param pEhdr Pointer to the ELF header.
1564 * @param pszLogName The log name.
1565 * @param cbRawImage The size of the raw image.
1566 */
1567static int RTLDRELF_NAME(ValidateElfHeader)(const Elf_Ehdr *pEhdr, const char *pszLogName, uint64_t cbRawImage,
1568 PRTLDRARCH penmArch)
1569{
1570 Log3(("RTLdrELF: e_ident: %.*Rhxs\n"
1571 "RTLdrELF: e_type: " FMT_ELF_HALF "\n"
1572 "RTLdrELF: e_version: " FMT_ELF_HALF "\n"
1573 "RTLdrELF: e_entry: " FMT_ELF_ADDR "\n"
1574 "RTLdrELF: e_phoff: " FMT_ELF_OFF "\n"
1575 "RTLdrELF: e_shoff: " FMT_ELF_OFF "\n"
1576 "RTLdrELF: e_flags: " FMT_ELF_WORD "\n"
1577 "RTLdrELF: e_ehsize: " FMT_ELF_HALF "\n"
1578 "RTLdrELF: e_phentsize: " FMT_ELF_HALF "\n"
1579 "RTLdrELF: e_phnum: " FMT_ELF_HALF "\n"
1580 "RTLdrELF: e_shentsize: " FMT_ELF_HALF "\n"
1581 "RTLdrELF: e_shnum: " FMT_ELF_HALF "\n"
1582 "RTLdrELF: e_shstrndx: " FMT_ELF_HALF "\n",
1583 RT_ELEMENTS(pEhdr->e_ident), &pEhdr->e_ident[0], pEhdr->e_type, pEhdr->e_version,
1584 pEhdr->e_entry, pEhdr->e_phoff, pEhdr->e_shoff,pEhdr->e_flags, pEhdr->e_ehsize, pEhdr->e_phentsize,
1585 pEhdr->e_phnum, pEhdr->e_shentsize, pEhdr->e_shnum, pEhdr->e_shstrndx));
1586
1587 if ( pEhdr->e_ident[EI_MAG0] != ELFMAG0
1588 || pEhdr->e_ident[EI_MAG1] != ELFMAG1
1589 || pEhdr->e_ident[EI_MAG2] != ELFMAG2
1590 || pEhdr->e_ident[EI_MAG3] != ELFMAG3
1591 )
1592 {
1593 Log(("RTLdrELF: %s: Invalid ELF magic (%.*Rhxs)\n", pszLogName, sizeof(pEhdr->e_ident), pEhdr->e_ident)); NOREF(pszLogName);
1594 return VERR_BAD_EXE_FORMAT;
1595 }
1596 if (pEhdr->e_ident[EI_CLASS] != RTLDRELF_SUFF(ELFCLASS))
1597 {
1598 Log(("RTLdrELF: %s: Invalid ELF class (%.*Rhxs)\n", pszLogName, sizeof(pEhdr->e_ident), pEhdr->e_ident));
1599 return VERR_BAD_EXE_FORMAT;
1600 }
1601 if (pEhdr->e_ident[EI_DATA] != ELFDATA2LSB)
1602 {
1603 Log(("RTLdrELF: %s: ELF endian %x is unsupported\n", pszLogName, pEhdr->e_ident[EI_DATA]));
1604 return VERR_LDRELF_ODD_ENDIAN;
1605 }
1606 if (pEhdr->e_version != EV_CURRENT)
1607 {
1608 Log(("RTLdrELF: %s: ELF version %x is unsupported\n", pszLogName, pEhdr->e_version));
1609 return VERR_LDRELF_VERSION;
1610 }
1611
1612 if (sizeof(Elf_Ehdr) != pEhdr->e_ehsize)
1613 {
1614 Log(("RTLdrELF: %s: Elf header e_ehsize is %d expected %d!\n",
1615 pszLogName, pEhdr->e_ehsize, sizeof(Elf_Ehdr)));
1616 return VERR_BAD_EXE_FORMAT;
1617 }
1618 if ( sizeof(Elf_Phdr) != pEhdr->e_phentsize
1619 && ( pEhdr->e_phnum != 0
1620 || pEhdr->e_type == ET_DYN))
1621 {
1622 Log(("RTLdrELF: %s: Elf header e_phentsize is %d expected %d!\n",
1623 pszLogName, pEhdr->e_phentsize, sizeof(Elf_Phdr)));
1624 return VERR_BAD_EXE_FORMAT;
1625 }
1626 if (sizeof(Elf_Shdr) != pEhdr->e_shentsize)
1627 {
1628 Log(("RTLdrELF: %s: Elf header e_shentsize is %d expected %d!\n",
1629 pszLogName, pEhdr->e_shentsize, sizeof(Elf_Shdr)));
1630 return VERR_BAD_EXE_FORMAT;
1631 }
1632
1633 switch (pEhdr->e_type)
1634 {
1635 case ET_REL:
1636 case ET_EXEC:
1637 case ET_DYN:
1638 break;
1639 default:
1640 Log(("RTLdrELF: %s: image type %#x is not supported!\n", pszLogName, pEhdr->e_type));
1641 return VERR_BAD_EXE_FORMAT;
1642 }
1643
1644 switch (pEhdr->e_machine)
1645 {
1646#if ELF_MODE == 32
1647 case EM_386:
1648 case EM_486:
1649 *penmArch = RTLDRARCH_X86_32;
1650 break;
1651#elif ELF_MODE == 64
1652 case EM_X86_64:
1653 *penmArch = RTLDRARCH_AMD64;
1654 break;
1655#endif
1656 default:
1657 Log(("RTLdrELF: %s: machine type %u is not supported!\n", pszLogName, pEhdr->e_machine));
1658 return VERR_LDRELF_MACHINE;
1659 }
1660
1661 if ( pEhdr->e_phoff < pEhdr->e_ehsize
1662 && !(pEhdr->e_phoff && pEhdr->e_phnum)
1663 && pEhdr->e_phnum)
1664 {
1665 Log(("RTLdrELF: %s: The program headers overlap with the ELF header! e_phoff=" FMT_ELF_OFF "\n",
1666 pszLogName, pEhdr->e_phoff));
1667 return VERR_BAD_EXE_FORMAT;
1668 }
1669 if ( pEhdr->e_phoff + pEhdr->e_phnum * pEhdr->e_phentsize > cbRawImage
1670 || pEhdr->e_phoff + pEhdr->e_phnum * pEhdr->e_phentsize < pEhdr->e_phoff)
1671 {
1672 Log(("RTLdrELF: %s: The program headers extends beyond the file! e_phoff=" FMT_ELF_OFF " e_phnum=" FMT_ELF_HALF "\n",
1673 pszLogName, pEhdr->e_phoff, pEhdr->e_phnum));
1674 return VERR_BAD_EXE_FORMAT;
1675 }
1676
1677
1678 if ( pEhdr->e_shoff < pEhdr->e_ehsize
1679 && !(pEhdr->e_shoff && pEhdr->e_shnum))
1680 {
1681 Log(("RTLdrELF: %s: The section headers overlap with the ELF header! e_shoff=" FMT_ELF_OFF "\n",
1682 pszLogName, pEhdr->e_shoff));
1683 return VERR_BAD_EXE_FORMAT;
1684 }
1685 if ( pEhdr->e_shoff + pEhdr->e_shnum * pEhdr->e_shentsize > cbRawImage
1686 || pEhdr->e_shoff + pEhdr->e_shnum * pEhdr->e_shentsize < pEhdr->e_shoff)
1687 {
1688 Log(("RTLdrELF: %s: The section headers extends beyond the file! e_shoff=" FMT_ELF_OFF " e_shnum=" FMT_ELF_HALF "\n",
1689 pszLogName, pEhdr->e_shoff, pEhdr->e_shnum));
1690 return VERR_BAD_EXE_FORMAT;
1691 }
1692
1693 if (pEhdr->e_shstrndx == 0 || pEhdr->e_shstrndx > pEhdr->e_shnum)
1694 {
1695 Log(("RTLdrELF: %s: The section headers string table is out of bounds! e_shstrndx=" FMT_ELF_HALF " e_shnum=" FMT_ELF_HALF "\n",
1696 pszLogName, pEhdr->e_shstrndx, pEhdr->e_shnum));
1697 return VERR_BAD_EXE_FORMAT;
1698 }
1699
1700 return VINF_SUCCESS;
1701}
1702
1703/**
1704 * Gets the section header name.
1705 *
1706 * @returns pszName.
1707 * @param pEhdr The elf header.
1708 * @param offName The offset of the section header name.
1709 * @param pszName Where to store the name.
1710 * @param cbName The size of the buffer pointed to by pszName.
1711 */
1712const char *RTLDRELF_NAME(GetSHdrName)(PRTLDRMODELF pModElf, Elf_Word offName, char *pszName, size_t cbName)
1713{
1714 RTFOFF off = pModElf->paShdrs[pModElf->Ehdr.e_shstrndx].sh_offset + offName;
1715 int rc = pModElf->Core.pReader->pfnRead(pModElf->Core.pReader, pszName, cbName - 1, off);
1716 if (RT_FAILURE(rc))
1717 {
1718 /* read by for byte. */
1719 for (unsigned i = 0; i < cbName; i++, off++)
1720 {
1721 rc = pModElf->Core.pReader->pfnRead(pModElf->Core.pReader, pszName + i, 1, off);
1722 if (RT_FAILURE(rc))
1723 {
1724 pszName[i] = '\0';
1725 break;
1726 }
1727 }
1728 }
1729
1730 pszName[cbName - 1] = '\0';
1731 return pszName;
1732}
1733
1734
1735/**
1736 * Validates a section header.
1737 *
1738 * @returns iprt status code.
1739 * @param pModElf Pointer to the module structure.
1740 * @param iShdr The index of section header which should be validated.
1741 * The section headers are found in the pModElf->paShdrs array.
1742 * @param pszLogName The log name.
1743 * @param cbRawImage The size of the raw image.
1744 */
1745static int RTLDRELF_NAME(ValidateSectionHeader)(PRTLDRMODELF pModElf, unsigned iShdr, const char *pszLogName, uint64_t cbRawImage)
1746{
1747 const Elf_Shdr *pShdr = &pModElf->paShdrs[iShdr];
1748 char szSectionName[80]; NOREF(szSectionName);
1749 Log3(("RTLdrELF: Section Header #%d:\n"
1750 "RTLdrELF: sh_name: " FMT_ELF_WORD " - %s\n"
1751 "RTLdrELF: sh_type: " FMT_ELF_WORD " (%s)\n"
1752 "RTLdrELF: sh_flags: " FMT_ELF_XWORD "\n"
1753 "RTLdrELF: sh_addr: " FMT_ELF_ADDR "\n"
1754 "RTLdrELF: sh_offset: " FMT_ELF_OFF "\n"
1755 "RTLdrELF: sh_size: " FMT_ELF_XWORD "\n"
1756 "RTLdrELF: sh_link: " FMT_ELF_WORD "\n"
1757 "RTLdrELF: sh_info: " FMT_ELF_WORD "\n"
1758 "RTLdrELF: sh_addralign: " FMT_ELF_XWORD "\n"
1759 "RTLdrELF: sh_entsize: " FMT_ELF_XWORD "\n",
1760 iShdr,
1761 pShdr->sh_name, RTLDRELF_NAME(GetSHdrName)(pModElf, pShdr->sh_name, szSectionName, sizeof(szSectionName)),
1762 pShdr->sh_type, rtldrElfGetShdrType(pShdr->sh_type), pShdr->sh_flags, pShdr->sh_addr,
1763 pShdr->sh_offset, pShdr->sh_size, pShdr->sh_link, pShdr->sh_info, pShdr->sh_addralign,
1764 pShdr->sh_entsize));
1765
1766 if (iShdr == 0)
1767 {
1768 if ( pShdr->sh_name != 0
1769 || pShdr->sh_type != SHT_NULL
1770 || pShdr->sh_flags != 0
1771 || pShdr->sh_addr != 0
1772 || pShdr->sh_size != 0
1773 || pShdr->sh_offset != 0
1774 || pShdr->sh_link != SHN_UNDEF
1775 || pShdr->sh_addralign != 0
1776 || pShdr->sh_entsize != 0 )
1777 {
1778 Log(("RTLdrELF: %s: Bad #0 section: %.*Rhxs\n", pszLogName, sizeof(*pShdr), pShdr ));
1779 return VERR_BAD_EXE_FORMAT;
1780 }
1781 return VINF_SUCCESS;
1782 }
1783
1784 if (pShdr->sh_name >= pModElf->cbShStr)
1785 {
1786 Log(("RTLdrELF: %s: Shdr #%d: sh_name (%d) is beyond the end of the section header string table (%d)!\n",
1787 pszLogName, iShdr, pShdr->sh_name, pModElf->cbShStr)); NOREF(pszLogName);
1788 return VERR_BAD_EXE_FORMAT;
1789 }
1790
1791 if (pShdr->sh_link >= pModElf->Ehdr.e_shnum)
1792 {
1793 Log(("RTLdrELF: %s: Shdr #%d: sh_link (%d) is beyond the end of the section table (%d)!\n",
1794 pszLogName, iShdr, pShdr->sh_link, pModElf->Ehdr.e_shnum)); NOREF(pszLogName);
1795 return VERR_BAD_EXE_FORMAT;
1796 }
1797
1798 switch (pShdr->sh_type)
1799 {
1800 /** @todo find specs and check up which sh_info fields indicates section table entries */
1801 case 12301230:
1802 if (pShdr->sh_info >= pModElf->Ehdr.e_shnum)
1803 {
1804 Log(("RTLdrELF: %s: Shdr #%d: sh_info (%d) is beyond the end of the section table (%d)!\n",
1805 pszLogName, iShdr, pShdr->sh_link, pModElf->Ehdr.e_shnum));
1806 return VERR_BAD_EXE_FORMAT;
1807 }
1808 break;
1809
1810 case SHT_NULL:
1811 break;
1812 case SHT_PROGBITS:
1813 case SHT_SYMTAB:
1814 case SHT_STRTAB:
1815 case SHT_RELA:
1816 case SHT_HASH:
1817 case SHT_DYNAMIC:
1818 case SHT_NOTE:
1819 case SHT_NOBITS:
1820 case SHT_REL:
1821 case SHT_SHLIB:
1822 case SHT_DYNSYM:
1823 /*
1824 * For these types sh_info doesn't have any special meaning, or anything which
1825 * we need/can validate now.
1826 */
1827 break;
1828
1829
1830 default:
1831 Log(("RTLdrELF: %s: Warning, unknown type %d!\n", pszLogName, pShdr->sh_type));
1832 break;
1833 }
1834
1835 if ( pShdr->sh_type != SHT_NOBITS
1836 && pShdr->sh_size)
1837 {
1838 uint64_t offEnd = pShdr->sh_offset + pShdr->sh_size;
1839 if ( offEnd > cbRawImage
1840 || offEnd < (uint64_t)pShdr->sh_offset)
1841 {
1842 Log(("RTLdrELF: %s: Shdr #%d: sh_offset (" FMT_ELF_OFF ") + sh_size (" FMT_ELF_XWORD " = %RX64) is beyond the end of the file (%RX64)!\n",
1843 pszLogName, iShdr, pShdr->sh_offset, pShdr->sh_size, offEnd, cbRawImage));
1844 return VERR_BAD_EXE_FORMAT;
1845 }
1846 if (pShdr->sh_offset < sizeof(Elf_Ehdr))
1847 {
1848 Log(("RTLdrELF: %s: Shdr #%d: sh_offset (" FMT_ELF_OFF ") + sh_size (" FMT_ELF_XWORD ") is starting in the ELF header!\n",
1849 pszLogName, iShdr, pShdr->sh_offset, pShdr->sh_size));
1850 return VERR_BAD_EXE_FORMAT;
1851 }
1852 }
1853
1854 return VINF_SUCCESS;
1855}
1856
1857
1858
1859/**
1860 * Opens an ELF image, fixed bitness.
1861 *
1862 * @returns iprt status code.
1863 * @param pReader The loader reader instance which will provide the raw image bits.
1864 * @param fFlags Reserved, MBZ.
1865 * @param enmArch Architecture specifier.
1866 * @param phLdrMod Where to store the handle.
1867 */
1868static int RTLDRELF_NAME(Open)(PRTLDRREADER pReader, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod)
1869{
1870 const char *pszLogName = pReader->pfnLogName(pReader);
1871 uint64_t cbRawImage = pReader->pfnSize(pReader);
1872 RT_NOREF_PV(fFlags);
1873
1874 /*
1875 * Create the loader module instance.
1876 */
1877 PRTLDRMODELF pModElf = (PRTLDRMODELF)RTMemAllocZ(sizeof(*pModElf));
1878 if (!pModElf)
1879 return VERR_NO_MEMORY;
1880
1881 pModElf->Core.u32Magic = RTLDRMOD_MAGIC;
1882 pModElf->Core.eState = LDR_STATE_INVALID;
1883 pModElf->Core.pReader = pReader;
1884 pModElf->Core.enmFormat = RTLDRFMT_ELF;
1885 pModElf->Core.enmType = RTLDRTYPE_OBJECT;
1886 pModElf->Core.enmEndian = RTLDRENDIAN_LITTLE;
1887#if ELF_MODE == 32
1888 pModElf->Core.enmArch = RTLDRARCH_X86_32;
1889#else
1890 pModElf->Core.enmArch = RTLDRARCH_AMD64;
1891#endif
1892 //pModElf->pvBits = NULL;
1893 //pModElf->Ehdr = {0};
1894 //pModElf->paShdrs = NULL;
1895 //pModElf->paSyms = NULL;
1896 pModElf->iSymSh = ~0U;
1897 //pModElf->cSyms = 0;
1898 pModElf->iStrSh = ~0U;
1899 //pModElf->cbStr = 0;
1900 //pModElf->cbImage = 0;
1901 //pModElf->LinkAddress = 0;
1902 //pModElf->pStr = NULL;
1903 //pModElf->cbShStr = 0;
1904 //pModElf->pShStr = NULL;
1905 //pModElf->iShEhFrame = 0;
1906 //pModElf->iShEhFrameHdr = 0;
1907
1908 /*
1909 * Read and validate the ELF header and match up the CPU architecture.
1910 */
1911 int rc = pReader->pfnRead(pReader, &pModElf->Ehdr, sizeof(pModElf->Ehdr), 0);
1912 if (RT_SUCCESS(rc))
1913 {
1914 RTLDRARCH enmArchImage = RTLDRARCH_INVALID; /* shut up gcc */
1915 rc = RTLDRELF_NAME(ValidateElfHeader)(&pModElf->Ehdr, pszLogName, cbRawImage, &enmArchImage);
1916 if (RT_SUCCESS(rc))
1917 {
1918 if ( enmArch != RTLDRARCH_WHATEVER
1919 && enmArch != enmArchImage)
1920 rc = VERR_LDR_ARCH_MISMATCH;
1921 }
1922 }
1923 if (RT_SUCCESS(rc))
1924 {
1925 /*
1926 * Read the section headers, keeping a prestine copy for the module
1927 * introspection methods.
1928 */
1929 size_t const cbShdrs = pModElf->Ehdr.e_shnum * sizeof(Elf_Shdr);
1930 Elf_Shdr *paShdrs = (Elf_Shdr *)RTMemAlloc(cbShdrs * 2);
1931 if (paShdrs)
1932 {
1933 pModElf->paShdrs = paShdrs;
1934 rc = pReader->pfnRead(pReader, paShdrs, cbShdrs, pModElf->Ehdr.e_shoff);
1935 if (RT_SUCCESS(rc))
1936 {
1937 memcpy(&paShdrs[pModElf->Ehdr.e_shnum], paShdrs, cbShdrs);
1938 pModElf->paOrgShdrs = &paShdrs[pModElf->Ehdr.e_shnum];
1939
1940 pModElf->cbShStr = paShdrs[pModElf->Ehdr.e_shstrndx].sh_size;
1941
1942 /*
1943 * Validate the section headers and find relevant sections.
1944 */
1945 Elf_Addr uNextAddr = 0;
1946 for (unsigned i = 0; i < pModElf->Ehdr.e_shnum; i++)
1947 {
1948 rc = RTLDRELF_NAME(ValidateSectionHeader)(pModElf, i, pszLogName, cbRawImage);
1949 if (RT_FAILURE(rc))
1950 break;
1951
1952 /* We're looking for symbol tables. */
1953 if (paShdrs[i].sh_type == SHT_SYMTAB)
1954 {
1955 if (pModElf->iSymSh != ~0U)
1956 {
1957 Log(("RTLdrElf: %s: Multiple symbol tabs! iSymSh=%d i=%d\n", pszLogName, pModElf->iSymSh, i));
1958 rc = VERR_LDRELF_MULTIPLE_SYMTABS;
1959 break;
1960 }
1961 pModElf->iSymSh = i;
1962 pModElf->cSyms = (unsigned)(paShdrs[i].sh_size / sizeof(Elf_Sym));
1963 AssertBreakStmt(pModElf->cSyms == paShdrs[i].sh_size / sizeof(Elf_Sym), rc = VERR_IMAGE_TOO_BIG);
1964 pModElf->iStrSh = paShdrs[i].sh_link;
1965 pModElf->cbStr = (unsigned)paShdrs[pModElf->iStrSh].sh_size;
1966 AssertBreakStmt(pModElf->cbStr == paShdrs[pModElf->iStrSh].sh_size, rc = VERR_IMAGE_TOO_BIG);
1967 }
1968
1969 /* Special checks for the section string table. */
1970 if (i == pModElf->Ehdr.e_shstrndx)
1971 {
1972 if (paShdrs[i].sh_type != SHT_STRTAB)
1973 {
1974 Log(("RTLdrElf: Section header string table is not a SHT_STRTAB: %#x\n", paShdrs[i].sh_type));
1975 rc = VERR_BAD_EXE_FORMAT;
1976 break;
1977 }
1978 if (paShdrs[i].sh_size == 0)
1979 {
1980 Log(("RTLdrElf: Section header string table is empty\n"));
1981 rc = VERR_BAD_EXE_FORMAT;
1982 break;
1983 }
1984 }
1985
1986 /* Kluge for the .data..percpu segment in 64-bit linux kernels. */
1987 if (paShdrs[i].sh_flags & SHF_ALLOC)
1988 {
1989 if ( paShdrs[i].sh_addr == 0
1990 && paShdrs[i].sh_addr < uNextAddr)
1991 {
1992 Elf_Addr uAddr = RT_ALIGN_T(uNextAddr, paShdrs[i].sh_addralign, Elf_Addr);
1993 Log(("RTLdrElf: Out of order section #%d; adjusting sh_addr from " FMT_ELF_ADDR " to " FMT_ELF_ADDR "\n",
1994 i, paShdrs[i].sh_addr, uAddr));
1995 paShdrs[i].sh_addr = uAddr;
1996 }
1997 uNextAddr = paShdrs[i].sh_addr + paShdrs[i].sh_size;
1998 }
1999 } /* for each section header */
2000
2001 /*
2002 * Calculate the image base address if the image isn't relocatable.
2003 */
2004 if (RT_SUCCESS(rc) && pModElf->Ehdr.e_type != ET_REL)
2005 {
2006 pModElf->LinkAddress = ~(Elf_Addr)0;
2007 for (unsigned i = 0; i < pModElf->Ehdr.e_shnum; i++)
2008 if ( (paShdrs[i].sh_flags & SHF_ALLOC)
2009 && paShdrs[i].sh_addr < pModElf->LinkAddress)
2010 pModElf->LinkAddress = paShdrs[i].sh_addr;
2011 if (pModElf->LinkAddress == ~(Elf_Addr)0)
2012 {
2013 AssertFailed();
2014 rc = VERR_LDR_GENERAL_FAILURE;
2015 }
2016 if (pModElf->Ehdr.e_type == ET_DYN && pModElf->LinkAddress < 0x1000)
2017 pModElf->LinkAddress = 0;
2018 }
2019
2020 /*
2021 * Perform allocations / RVA calculations, determine the image size.
2022 */
2023 if (RT_SUCCESS(rc))
2024 for (unsigned i = 0; i < pModElf->Ehdr.e_shnum; i++)
2025 if (paShdrs[i].sh_flags & SHF_ALLOC)
2026 {
2027 if (pModElf->Ehdr.e_type == ET_REL)
2028 paShdrs[i].sh_addr = paShdrs[i].sh_addralign
2029 ? RT_ALIGN_T(pModElf->cbImage, paShdrs[i].sh_addralign, Elf_Addr)
2030 : (Elf_Addr)pModElf->cbImage;
2031 else
2032 paShdrs[i].sh_addr -= pModElf->LinkAddress;
2033 Elf_Addr EndAddr = paShdrs[i].sh_addr + paShdrs[i].sh_size;
2034 if (pModElf->cbImage < EndAddr)
2035 {
2036 pModElf->cbImage = (size_t)EndAddr;
2037 AssertMsgBreakStmt(pModElf->cbImage == EndAddr, (FMT_ELF_ADDR "\n", EndAddr), rc = VERR_IMAGE_TOO_BIG);
2038 }
2039 Log2(("RTLdrElf: %s: Assigned " FMT_ELF_ADDR " to section #%d\n", pszLogName, paShdrs[i].sh_addr, i));
2040 }
2041
2042 Log2(("RTLdrElf: iSymSh=%u cSyms=%u iStrSh=%u cbStr=%u rc=%Rrc cbImage=%#zx LinkAddress=" FMT_ELF_ADDR "\n",
2043 pModElf->iSymSh, pModElf->cSyms, pModElf->iStrSh, pModElf->cbStr, rc,
2044 pModElf->cbImage, pModElf->LinkAddress));
2045 if (RT_SUCCESS(rc))
2046 {
2047 pModElf->Core.pOps = &RTLDRELF_MID(s_rtldrElf,Ops);
2048 pModElf->Core.eState = LDR_STATE_OPENED;
2049 *phLdrMod = &pModElf->Core;
2050
2051 LogFlow(("%s: %s: returns VINF_SUCCESS *phLdrMod=%p\n", __FUNCTION__, pszLogName, *phLdrMod));
2052 return VINF_SUCCESS;
2053 }
2054 }
2055
2056 RTMemFree(paShdrs);
2057 }
2058 else
2059 rc = VERR_NO_MEMORY;
2060 }
2061
2062 RTMemFree(pModElf);
2063 LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
2064 return rc;
2065}
2066
2067
2068
2069
2070/*******************************************************************************
2071* Cleanup Constants And Macros *
2072*******************************************************************************/
2073#undef RTLDRELF_NAME
2074#undef RTLDRELF_SUFF
2075#undef RTLDRELF_MID
2076
2077#undef FMT_ELF_ADDR
2078#undef FMT_ELF_HALF
2079#undef FMT_ELF_SHALF
2080#undef FMT_ELF_OFF
2081#undef FMT_ELF_SIZE
2082#undef FMT_ELF_SWORD
2083#undef FMT_ELF_WORD
2084#undef FMT_ELF_XWORD
2085#undef FMT_ELF_SXWORD
2086
2087#undef Elf_Ehdr
2088#undef Elf_Phdr
2089#undef Elf_Shdr
2090#undef Elf_Sym
2091#undef Elf_Rel
2092#undef Elf_Rela
2093#undef Elf_Reloc
2094#undef Elf_Nhdr
2095#undef Elf_Dyn
2096
2097#undef Elf_Addr
2098#undef Elf_Half
2099#undef Elf_Off
2100#undef Elf_Size
2101#undef Elf_Sword
2102#undef Elf_Word
2103
2104#undef RTLDRMODELF
2105#undef PRTLDRMODELF
2106
2107#undef ELF_R_SYM
2108#undef ELF_R_TYPE
2109#undef ELF_R_INFO
2110
2111#undef ELF_ST_BIND
2112
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