VirtualBox

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

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

Runtime/ldrELFRelocatable.cpp.h: several fixes

  • Check that the string tables are zero terminated (in theory a crazy linker could pad the string table with non zero bytes while technically being correct and triggering a false positive with the check is something we bother with when we encounter it)
  • Verify that st_name is within bounds of the string table
  • Plug a few memory leaks when opening a corrupted image fails
  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 79.7 KB
Line 
1/* $Id: ldrELFRelocatable.cpp.h 77941 2019-03-28 16:04:35Z 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.215389.xyz. 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 RTFOFF cbRawImage = pThis->Core.pReader->pfnSize(pThis->Core.pReader);
1359 AssertReturn(cbRawImage >= 0, VERR_INVALID_PARAMETER);
1360 AssertReturn(off >= 0 && cb <= (uint64_t)cbRawImage && (uint64_t)off + cb <= (uint64_t)cbRawImage, VERR_INVALID_PARAMETER);
1361
1362 /*
1363 * Read it from the file and look for fixup sections.
1364 */
1365 int rc;
1366 if (pThis->pvBits)
1367 memcpy(pvBuf, (const uint8_t *)pThis->pvBits + (size_t)off, cb);
1368 else
1369 {
1370 rc = pThis->Core.pReader->pfnRead(pThis->Core.pReader, pvBuf, cb, off);
1371 if (RT_FAILURE(rc))
1372 return rc;
1373 }
1374
1375 uint32_t iRelocs = iDbgInfo + 1;
1376 if ( iRelocs >= pThis->Ehdr.e_shnum
1377 || pThis->paShdrs[iRelocs].sh_info != iDbgInfo
1378 || ( pThis->paShdrs[iRelocs].sh_type != SHT_REL
1379 && pThis->paShdrs[iRelocs].sh_type != SHT_RELA) )
1380 {
1381 iRelocs = 0;
1382 while ( iRelocs < pThis->Ehdr.e_shnum
1383 && ( pThis->paShdrs[iRelocs].sh_info != iDbgInfo
1384 || ( pThis->paShdrs[iRelocs].sh_type != SHT_REL
1385 && pThis->paShdrs[iRelocs].sh_type != SHT_RELA)) )
1386 iRelocs++;
1387 }
1388 if ( iRelocs < pThis->Ehdr.e_shnum
1389 && pThis->paShdrs[iRelocs].sh_size > 0)
1390 {
1391 /*
1392 * Load the relocations.
1393 */
1394 uint8_t *pbRelocsBuf = NULL;
1395 const uint8_t *pbRelocs;
1396 if (pThis->pvBits)
1397 pbRelocs = (const uint8_t *)pThis->pvBits + pThis->paShdrs[iRelocs].sh_offset;
1398 else
1399 {
1400 pbRelocs = pbRelocsBuf = (uint8_t *)RTMemTmpAlloc(pThis->paShdrs[iRelocs].sh_size);
1401 if (!pbRelocsBuf)
1402 return VERR_NO_TMP_MEMORY;
1403 rc = pThis->Core.pReader->pfnRead(pThis->Core.pReader, pbRelocsBuf,
1404 pThis->paShdrs[iRelocs].sh_size,
1405 pThis->paShdrs[iRelocs].sh_offset);
1406 if (RT_FAILURE(rc))
1407 {
1408 RTMemTmpFree(pbRelocsBuf);
1409 return rc;
1410 }
1411 }
1412
1413 /*
1414 * Apply the relocations.
1415 */
1416 if (pThis->Ehdr.e_type == ET_REL)
1417 rc = RTLDRELF_NAME(RelocateSection)(pThis, pThis->LinkAddress,
1418 RTLDRELF_NAME(GetImportStubCallback), NULL /*pvUser*/,
1419 pThis->paShdrs[iDbgInfo].sh_addr,
1420 pThis->paShdrs[iDbgInfo].sh_size,
1421 (const uint8_t *)pvBuf,
1422 (uint8_t *)pvBuf,
1423 pbRelocs,
1424 pThis->paShdrs[iRelocs].sh_size);
1425 else
1426 rc = RTLDRELF_NAME(RelocateSectionExecDyn)(pThis, pThis->LinkAddress,
1427 RTLDRELF_NAME(GetImportStubCallback), NULL /*pvUser*/,
1428 pThis->paShdrs[iDbgInfo].sh_addr,
1429 pThis->paShdrs[iDbgInfo].sh_size,
1430 (const uint8_t *)pvBuf,
1431 (uint8_t *)pvBuf,
1432 pbRelocs,
1433 pThis->paShdrs[iRelocs].sh_size);
1434
1435 RTMemTmpFree(pbRelocsBuf);
1436 }
1437 else
1438 rc = VINF_SUCCESS;
1439 return rc;
1440}
1441
1442
1443/**
1444 * @interface_method_impl{RTLDROPS,pfnUnwindFrame}
1445 */
1446static DECLCALLBACK(int)
1447RTLDRELF_NAME(UnwindFrame)(PRTLDRMODINTERNAL pMod, void const *pvBits, uint32_t iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState)
1448{
1449 PRTLDRMODELF pThis = (PRTLDRMODELF)pMod;
1450 LogFlow(("%s: iSeg=%#x off=%RTptr\n", __FUNCTION__, iSeg, off));
1451
1452 /*
1453 * Process the input address, making us both RVA and proper seg:offset out of it.
1454 */
1455 int rc;
1456 RTLDRADDR uRva = off;
1457 if (iSeg == UINT32_MAX)
1458 rc = RTLDRELF_NAME(RvaToSegOffset)(pMod, uRva, &iSeg, &off);
1459 else
1460 rc = RTLDRELF_NAME(SegOffsetToRva)(pMod, iSeg, off, &uRva);
1461 AssertRCReturn(rc, rc);
1462
1463 /*
1464 * Map the image bits if not already done and setup pointer into it.
1465 */
1466 RT_NOREF(pvBits); /** @todo Try use passed in pvBits? */
1467 rc = RTLDRELF_NAME(MapBits)(pThis, true);
1468 if (RT_FAILURE(rc))
1469 return rc;
1470
1471 /*
1472 * Do we need to search for .eh_frame and .eh_frame_hdr?
1473 */
1474 if (pThis->iShEhFrame == 0)
1475 {
1476 pThis->iShEhFrame = ~0U;
1477 pThis->iShEhFrameHdr = ~0U;
1478 unsigned cLeft = 2;
1479 for (unsigned iShdr = 1; iShdr < pThis->Ehdr.e_shnum; iShdr++)
1480 {
1481 const char *pszName = ELF_SH_STR(pThis, pThis->paShdrs[iShdr].sh_name);
1482 if ( pszName[0] == '.'
1483 && pszName[1] == 'e'
1484 && pszName[2] == 'h'
1485 && pszName[3] == '_'
1486 && pszName[4] == 'f'
1487 && pszName[5] == 'r'
1488 && pszName[6] == 'a'
1489 && pszName[7] == 'm'
1490 && pszName[8] == 'e')
1491 {
1492 if (pszName[9] == '\0')
1493 pThis->iShEhFrame = iShdr;
1494 else if ( pszName[9] == '_'
1495 && pszName[10] == 'h'
1496 && pszName[11] == 'd'
1497 && pszName[12] == 'r'
1498 && pszName[13] == '\0')
1499 pThis->iShEhFrameHdr = iShdr;
1500 else
1501 continue;
1502 if (--cLeft == 0)
1503 break;
1504 }
1505 }
1506 }
1507
1508 /*
1509 * Any info present?
1510 */
1511 unsigned iShdr = pThis->iShEhFrame;
1512 if ( iShdr != ~0U
1513 && pThis->paShdrs[iShdr].sh_size > 0)
1514 {
1515 if (pThis->paShdrs[iShdr].sh_flags & SHF_ALLOC)
1516 return rtDwarfUnwind_EhData((uint8_t const *)pThis->pvBits + pThis->paShdrs[iShdr].sh_addr,
1517 pThis->paShdrs[iShdr].sh_size, pThis->paShdrs[iShdr].sh_addr,
1518 iSeg, off, uRva, pState, pThis->Core.enmArch);
1519 }
1520 return VERR_DBG_NO_UNWIND_INFO;
1521}
1522
1523
1524/**
1525 * The ELF module operations.
1526 */
1527static RTLDROPS RTLDRELF_MID(s_rtldrElf,Ops) =
1528{
1529#if ELF_MODE == 32
1530 "elf32",
1531#elif ELF_MODE == 64
1532 "elf64",
1533#endif
1534 RTLDRELF_NAME(Close),
1535 NULL, /* Get Symbol */
1536 RTLDRELF_NAME(Done),
1537 RTLDRELF_NAME(EnumSymbols),
1538 /* ext: */
1539 RTLDRELF_NAME(GetImageSize),
1540 RTLDRELF_NAME(GetBits),
1541 RTLDRELF_NAME(Relocate),
1542 RTLDRELF_NAME(GetSymbolEx),
1543 NULL /*pfnQueryForwarderInfo*/,
1544 RTLDRELF_NAME(EnumDbgInfo),
1545 RTLDRELF_NAME(EnumSegments),
1546 RTLDRELF_NAME(LinkAddressToSegOffset),
1547 RTLDRELF_NAME(LinkAddressToRva),
1548 RTLDRELF_NAME(SegOffsetToRva),
1549 RTLDRELF_NAME(RvaToSegOffset),
1550 RTLDRELF_NAME(ReadDbgInfo),
1551 NULL /*pfnQueryProp*/,
1552 NULL /*pfnVerifySignature*/,
1553 NULL /*pfnHashImage*/,
1554 RTLDRELF_NAME(UnwindFrame),
1555 42
1556};
1557
1558
1559
1560/**
1561 * Validates the ELF header.
1562 *
1563 * @returns iprt status code.
1564 * @param pEhdr Pointer to the ELF header.
1565 * @param pszLogName The log name.
1566 * @param cbRawImage The size of the raw image.
1567 */
1568static int RTLDRELF_NAME(ValidateElfHeader)(const Elf_Ehdr *pEhdr, const char *pszLogName, uint64_t cbRawImage,
1569 PRTLDRARCH penmArch)
1570{
1571 Log3(("RTLdrELF: e_ident: %.*Rhxs\n"
1572 "RTLdrELF: e_type: " FMT_ELF_HALF "\n"
1573 "RTLdrELF: e_version: " FMT_ELF_HALF "\n"
1574 "RTLdrELF: e_entry: " FMT_ELF_ADDR "\n"
1575 "RTLdrELF: e_phoff: " FMT_ELF_OFF "\n"
1576 "RTLdrELF: e_shoff: " FMT_ELF_OFF "\n"
1577 "RTLdrELF: e_flags: " FMT_ELF_WORD "\n"
1578 "RTLdrELF: e_ehsize: " FMT_ELF_HALF "\n"
1579 "RTLdrELF: e_phentsize: " FMT_ELF_HALF "\n"
1580 "RTLdrELF: e_phnum: " FMT_ELF_HALF "\n"
1581 "RTLdrELF: e_shentsize: " FMT_ELF_HALF "\n"
1582 "RTLdrELF: e_shnum: " FMT_ELF_HALF "\n"
1583 "RTLdrELF: e_shstrndx: " FMT_ELF_HALF "\n",
1584 RT_ELEMENTS(pEhdr->e_ident), &pEhdr->e_ident[0], pEhdr->e_type, pEhdr->e_version,
1585 pEhdr->e_entry, pEhdr->e_phoff, pEhdr->e_shoff,pEhdr->e_flags, pEhdr->e_ehsize, pEhdr->e_phentsize,
1586 pEhdr->e_phnum, pEhdr->e_shentsize, pEhdr->e_shnum, pEhdr->e_shstrndx));
1587
1588 if ( pEhdr->e_ident[EI_MAG0] != ELFMAG0
1589 || pEhdr->e_ident[EI_MAG1] != ELFMAG1
1590 || pEhdr->e_ident[EI_MAG2] != ELFMAG2
1591 || pEhdr->e_ident[EI_MAG3] != ELFMAG3
1592 )
1593 {
1594 Log(("RTLdrELF: %s: Invalid ELF magic (%.*Rhxs)\n", pszLogName, sizeof(pEhdr->e_ident), pEhdr->e_ident)); NOREF(pszLogName);
1595 return VERR_BAD_EXE_FORMAT;
1596 }
1597 if (pEhdr->e_ident[EI_CLASS] != RTLDRELF_SUFF(ELFCLASS))
1598 {
1599 Log(("RTLdrELF: %s: Invalid ELF class (%.*Rhxs)\n", pszLogName, sizeof(pEhdr->e_ident), pEhdr->e_ident));
1600 return VERR_BAD_EXE_FORMAT;
1601 }
1602 if (pEhdr->e_ident[EI_DATA] != ELFDATA2LSB)
1603 {
1604 Log(("RTLdrELF: %s: ELF endian %x is unsupported\n", pszLogName, pEhdr->e_ident[EI_DATA]));
1605 return VERR_LDRELF_ODD_ENDIAN;
1606 }
1607 if (pEhdr->e_version != EV_CURRENT)
1608 {
1609 Log(("RTLdrELF: %s: ELF version %x is unsupported\n", pszLogName, pEhdr->e_version));
1610 return VERR_LDRELF_VERSION;
1611 }
1612
1613 if (sizeof(Elf_Ehdr) != pEhdr->e_ehsize)
1614 {
1615 Log(("RTLdrELF: %s: Elf header e_ehsize is %d expected %d!\n",
1616 pszLogName, pEhdr->e_ehsize, sizeof(Elf_Ehdr)));
1617 return VERR_BAD_EXE_FORMAT;
1618 }
1619 if ( sizeof(Elf_Phdr) != pEhdr->e_phentsize
1620 && ( pEhdr->e_phnum != 0
1621 || pEhdr->e_type == ET_DYN))
1622 {
1623 Log(("RTLdrELF: %s: Elf header e_phentsize is %d expected %d!\n",
1624 pszLogName, pEhdr->e_phentsize, sizeof(Elf_Phdr)));
1625 return VERR_BAD_EXE_FORMAT;
1626 }
1627 if (sizeof(Elf_Shdr) != pEhdr->e_shentsize)
1628 {
1629 Log(("RTLdrELF: %s: Elf header e_shentsize is %d expected %d!\n",
1630 pszLogName, pEhdr->e_shentsize, sizeof(Elf_Shdr)));
1631 return VERR_BAD_EXE_FORMAT;
1632 }
1633
1634 switch (pEhdr->e_type)
1635 {
1636 case ET_REL:
1637 case ET_EXEC:
1638 case ET_DYN:
1639 break;
1640 default:
1641 Log(("RTLdrELF: %s: image type %#x is not supported!\n", pszLogName, pEhdr->e_type));
1642 return VERR_BAD_EXE_FORMAT;
1643 }
1644
1645 switch (pEhdr->e_machine)
1646 {
1647#if ELF_MODE == 32
1648 case EM_386:
1649 case EM_486:
1650 *penmArch = RTLDRARCH_X86_32;
1651 break;
1652#elif ELF_MODE == 64
1653 case EM_X86_64:
1654 *penmArch = RTLDRARCH_AMD64;
1655 break;
1656#endif
1657 default:
1658 Log(("RTLdrELF: %s: machine type %u is not supported!\n", pszLogName, pEhdr->e_machine));
1659 return VERR_LDRELF_MACHINE;
1660 }
1661
1662 if ( pEhdr->e_phoff < pEhdr->e_ehsize
1663 && !(pEhdr->e_phoff && pEhdr->e_phnum)
1664 && pEhdr->e_phnum)
1665 {
1666 Log(("RTLdrELF: %s: The program headers overlap with the ELF header! e_phoff=" FMT_ELF_OFF "\n",
1667 pszLogName, pEhdr->e_phoff));
1668 return VERR_BAD_EXE_FORMAT;
1669 }
1670 if ( pEhdr->e_phoff + pEhdr->e_phnum * pEhdr->e_phentsize > cbRawImage
1671 || pEhdr->e_phoff + pEhdr->e_phnum * pEhdr->e_phentsize < pEhdr->e_phoff)
1672 {
1673 Log(("RTLdrELF: %s: The program headers extends beyond the file! e_phoff=" FMT_ELF_OFF " e_phnum=" FMT_ELF_HALF "\n",
1674 pszLogName, pEhdr->e_phoff, pEhdr->e_phnum));
1675 return VERR_BAD_EXE_FORMAT;
1676 }
1677
1678
1679 if ( pEhdr->e_shoff < pEhdr->e_ehsize
1680 && !(pEhdr->e_shoff && pEhdr->e_shnum))
1681 {
1682 Log(("RTLdrELF: %s: The section headers overlap with the ELF header! e_shoff=" FMT_ELF_OFF "\n",
1683 pszLogName, pEhdr->e_shoff));
1684 return VERR_BAD_EXE_FORMAT;
1685 }
1686 if ( pEhdr->e_shoff + pEhdr->e_shnum * pEhdr->e_shentsize > cbRawImage
1687 || pEhdr->e_shoff + pEhdr->e_shnum * pEhdr->e_shentsize < pEhdr->e_shoff)
1688 {
1689 Log(("RTLdrELF: %s: The section headers extends beyond the file! e_shoff=" FMT_ELF_OFF " e_shnum=" FMT_ELF_HALF "\n",
1690 pszLogName, pEhdr->e_shoff, pEhdr->e_shnum));
1691 return VERR_BAD_EXE_FORMAT;
1692 }
1693
1694 if (pEhdr->e_shstrndx == 0 || pEhdr->e_shstrndx > pEhdr->e_shnum)
1695 {
1696 Log(("RTLdrELF: %s: The section headers string table is out of bounds! e_shstrndx=" FMT_ELF_HALF " e_shnum=" FMT_ELF_HALF "\n",
1697 pszLogName, pEhdr->e_shstrndx, pEhdr->e_shnum));
1698 return VERR_BAD_EXE_FORMAT;
1699 }
1700
1701 return VINF_SUCCESS;
1702}
1703
1704/**
1705 * Gets the section header name.
1706 *
1707 * @returns pszName.
1708 * @param pEhdr The elf header.
1709 * @param offName The offset of the section header name.
1710 * @param pszName Where to store the name.
1711 * @param cbName The size of the buffer pointed to by pszName.
1712 */
1713const char *RTLDRELF_NAME(GetSHdrName)(PRTLDRMODELF pModElf, Elf_Word offName, char *pszName, size_t cbName)
1714{
1715 RTFOFF off = pModElf->paShdrs[pModElf->Ehdr.e_shstrndx].sh_offset + offName;
1716 int rc = pModElf->Core.pReader->pfnRead(pModElf->Core.pReader, pszName, cbName - 1, off);
1717 if (RT_FAILURE(rc))
1718 {
1719 /* read by for byte. */
1720 for (unsigned i = 0; i < cbName; i++, off++)
1721 {
1722 rc = pModElf->Core.pReader->pfnRead(pModElf->Core.pReader, pszName + i, 1, off);
1723 if (RT_FAILURE(rc))
1724 {
1725 pszName[i] = '\0';
1726 break;
1727 }
1728 }
1729 }
1730
1731 pszName[cbName - 1] = '\0';
1732 return pszName;
1733}
1734
1735
1736/**
1737 * Validates a section header.
1738 *
1739 * @returns iprt status code.
1740 * @param pModElf Pointer to the module structure.
1741 * @param iShdr The index of section header which should be validated.
1742 * The section headers are found in the pModElf->paShdrs array.
1743 * @param pszLogName The log name.
1744 * @param cbRawImage The size of the raw image.
1745 */
1746static int RTLDRELF_NAME(ValidateSectionHeader)(PRTLDRMODELF pModElf, unsigned iShdr, const char *pszLogName, RTFOFF cbRawImage)
1747{
1748 const Elf_Shdr *pShdr = &pModElf->paShdrs[iShdr];
1749 char szSectionName[80]; NOREF(szSectionName);
1750 Log3(("RTLdrELF: Section Header #%d:\n"
1751 "RTLdrELF: sh_name: " FMT_ELF_WORD " - %s\n"
1752 "RTLdrELF: sh_type: " FMT_ELF_WORD " (%s)\n"
1753 "RTLdrELF: sh_flags: " FMT_ELF_XWORD "\n"
1754 "RTLdrELF: sh_addr: " FMT_ELF_ADDR "\n"
1755 "RTLdrELF: sh_offset: " FMT_ELF_OFF "\n"
1756 "RTLdrELF: sh_size: " FMT_ELF_XWORD "\n"
1757 "RTLdrELF: sh_link: " FMT_ELF_WORD "\n"
1758 "RTLdrELF: sh_info: " FMT_ELF_WORD "\n"
1759 "RTLdrELF: sh_addralign: " FMT_ELF_XWORD "\n"
1760 "RTLdrELF: sh_entsize: " FMT_ELF_XWORD "\n",
1761 iShdr,
1762 pShdr->sh_name, RTLDRELF_NAME(GetSHdrName)(pModElf, pShdr->sh_name, szSectionName, sizeof(szSectionName)),
1763 pShdr->sh_type, rtldrElfGetShdrType(pShdr->sh_type), pShdr->sh_flags, pShdr->sh_addr,
1764 pShdr->sh_offset, pShdr->sh_size, pShdr->sh_link, pShdr->sh_info, pShdr->sh_addralign,
1765 pShdr->sh_entsize));
1766
1767 if (iShdr == 0)
1768 {
1769 if ( pShdr->sh_name != 0
1770 || pShdr->sh_type != SHT_NULL
1771 || pShdr->sh_flags != 0
1772 || pShdr->sh_addr != 0
1773 || pShdr->sh_size != 0
1774 || pShdr->sh_offset != 0
1775 || pShdr->sh_link != SHN_UNDEF
1776 || pShdr->sh_addralign != 0
1777 || pShdr->sh_entsize != 0 )
1778 {
1779 Log(("RTLdrELF: %s: Bad #0 section: %.*Rhxs\n", pszLogName, sizeof(*pShdr), pShdr ));
1780 return VERR_BAD_EXE_FORMAT;
1781 }
1782 return VINF_SUCCESS;
1783 }
1784
1785 if (pShdr->sh_name >= pModElf->cbShStr)
1786 {
1787 Log(("RTLdrELF: %s: Shdr #%d: sh_name (%d) is beyond the end of the section header string table (%d)!\n",
1788 pszLogName, iShdr, pShdr->sh_name, pModElf->cbShStr)); NOREF(pszLogName);
1789 return VERR_BAD_EXE_FORMAT;
1790 }
1791
1792 if (pShdr->sh_link >= pModElf->Ehdr.e_shnum)
1793 {
1794 Log(("RTLdrELF: %s: Shdr #%d: sh_link (%d) is beyond the end of the section table (%d)!\n",
1795 pszLogName, iShdr, pShdr->sh_link, pModElf->Ehdr.e_shnum)); NOREF(pszLogName);
1796 return VERR_BAD_EXE_FORMAT;
1797 }
1798
1799 switch (pShdr->sh_type)
1800 {
1801 /** @todo find specs and check up which sh_info fields indicates section table entries */
1802 case 12301230:
1803 if (pShdr->sh_info >= pModElf->Ehdr.e_shnum)
1804 {
1805 Log(("RTLdrELF: %s: Shdr #%d: sh_info (%d) is beyond the end of the section table (%d)!\n",
1806 pszLogName, iShdr, pShdr->sh_link, pModElf->Ehdr.e_shnum));
1807 return VERR_BAD_EXE_FORMAT;
1808 }
1809 break;
1810
1811 case SHT_NULL:
1812 break;
1813 case SHT_PROGBITS:
1814 case SHT_SYMTAB:
1815 case SHT_STRTAB:
1816 case SHT_RELA:
1817 case SHT_HASH:
1818 case SHT_DYNAMIC:
1819 case SHT_NOTE:
1820 case SHT_NOBITS:
1821 case SHT_REL:
1822 case SHT_SHLIB:
1823 case SHT_DYNSYM:
1824 /*
1825 * For these types sh_info doesn't have any special meaning, or anything which
1826 * we need/can validate now.
1827 */
1828 break;
1829
1830
1831 default:
1832 Log(("RTLdrELF: %s: Warning, unknown type %d!\n", pszLogName, pShdr->sh_type));
1833 break;
1834 }
1835
1836 if ( pShdr->sh_type != SHT_NOBITS
1837 && pShdr->sh_size)
1838 {
1839 RTFOFF offEnd = pShdr->sh_offset + pShdr->sh_size;
1840 if ( offEnd > cbRawImage
1841 || offEnd < (RTFOFF)pShdr->sh_offset)
1842 {
1843 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",
1844 pszLogName, iShdr, pShdr->sh_offset, pShdr->sh_size, offEnd, cbRawImage));
1845 return VERR_BAD_EXE_FORMAT;
1846 }
1847 if (pShdr->sh_offset < sizeof(Elf_Ehdr))
1848 {
1849 Log(("RTLdrELF: %s: Shdr #%d: sh_offset (" FMT_ELF_OFF ") + sh_size (" FMT_ELF_XWORD ") is starting in the ELF header!\n",
1850 pszLogName, iShdr, pShdr->sh_offset, pShdr->sh_size));
1851 return VERR_BAD_EXE_FORMAT;
1852 }
1853 }
1854
1855 return VINF_SUCCESS;
1856}
1857
1858
1859
1860/**
1861 * Opens an ELF image, fixed bitness.
1862 *
1863 * @returns iprt status code.
1864 * @param pReader The loader reader instance which will provide the raw image bits.
1865 * @param fFlags Reserved, MBZ.
1866 * @param enmArch Architecture specifier.
1867 * @param phLdrMod Where to store the handle.
1868 */
1869static int RTLDRELF_NAME(Open)(PRTLDRREADER pReader, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod)
1870{
1871 const char *pszLogName = pReader->pfnLogName(pReader);
1872 RTFOFF cbRawImage = pReader->pfnSize(pReader);
1873 RT_NOREF_PV(fFlags);
1874
1875 /*
1876 * Create the loader module instance.
1877 */
1878 PRTLDRMODELF pModElf = (PRTLDRMODELF)RTMemAllocZ(sizeof(*pModElf));
1879 if (!pModElf)
1880 return VERR_NO_MEMORY;
1881
1882 pModElf->Core.u32Magic = RTLDRMOD_MAGIC;
1883 pModElf->Core.eState = LDR_STATE_INVALID;
1884 pModElf->Core.pReader = pReader;
1885 pModElf->Core.enmFormat = RTLDRFMT_ELF;
1886 pModElf->Core.enmType = RTLDRTYPE_OBJECT;
1887 pModElf->Core.enmEndian = RTLDRENDIAN_LITTLE;
1888#if ELF_MODE == 32
1889 pModElf->Core.enmArch = RTLDRARCH_X86_32;
1890#else
1891 pModElf->Core.enmArch = RTLDRARCH_AMD64;
1892#endif
1893 //pModElf->pvBits = NULL;
1894 //pModElf->Ehdr = {0};
1895 //pModElf->paShdrs = NULL;
1896 //pModElf->paSyms = NULL;
1897 pModElf->iSymSh = ~0U;
1898 //pModElf->cSyms = 0;
1899 pModElf->iStrSh = ~0U;
1900 //pModElf->cbStr = 0;
1901 //pModElf->cbImage = 0;
1902 //pModElf->LinkAddress = 0;
1903 //pModElf->pStr = NULL;
1904 //pModElf->cbShStr = 0;
1905 //pModElf->pShStr = NULL;
1906 //pModElf->iShEhFrame = 0;
1907 //pModElf->iShEhFrameHdr = 0;
1908
1909 /*
1910 * Read and validate the ELF header and match up the CPU architecture.
1911 */
1912 int rc = pReader->pfnRead(pReader, &pModElf->Ehdr, sizeof(pModElf->Ehdr), 0);
1913 if (RT_SUCCESS(rc))
1914 {
1915 RTLDRARCH enmArchImage = RTLDRARCH_INVALID; /* shut up gcc */
1916 rc = RTLDRELF_NAME(ValidateElfHeader)(&pModElf->Ehdr, pszLogName, cbRawImage, &enmArchImage);
1917 if (RT_SUCCESS(rc))
1918 {
1919 if ( enmArch != RTLDRARCH_WHATEVER
1920 && enmArch != enmArchImage)
1921 rc = VERR_LDR_ARCH_MISMATCH;
1922 }
1923 }
1924 if (RT_SUCCESS(rc))
1925 {
1926 /*
1927 * Read the section headers, keeping a prestine copy for the module
1928 * introspection methods.
1929 */
1930 size_t const cbShdrs = pModElf->Ehdr.e_shnum * sizeof(Elf_Shdr);
1931 Elf_Shdr *paShdrs = (Elf_Shdr *)RTMemAlloc(cbShdrs * 2);
1932 if (paShdrs)
1933 {
1934 pModElf->paShdrs = paShdrs;
1935 rc = pReader->pfnRead(pReader, paShdrs, cbShdrs, pModElf->Ehdr.e_shoff);
1936 if (RT_SUCCESS(rc))
1937 {
1938 memcpy(&paShdrs[pModElf->Ehdr.e_shnum], paShdrs, cbShdrs);
1939 pModElf->paOrgShdrs = &paShdrs[pModElf->Ehdr.e_shnum];
1940
1941 pModElf->cbShStr = paShdrs[pModElf->Ehdr.e_shstrndx].sh_size;
1942
1943 /*
1944 * Validate the section headers and find relevant sections.
1945 */
1946 Elf_Addr uNextAddr = 0;
1947 for (unsigned i = 0; i < pModElf->Ehdr.e_shnum; i++)
1948 {
1949 rc = RTLDRELF_NAME(ValidateSectionHeader)(pModElf, i, pszLogName, cbRawImage);
1950 if (RT_FAILURE(rc))
1951 break;
1952
1953 /* We're looking for symbol tables. */
1954 if (paShdrs[i].sh_type == SHT_SYMTAB)
1955 {
1956 if (pModElf->iSymSh != ~0U)
1957 {
1958 Log(("RTLdrElf: %s: Multiple symbol tabs! iSymSh=%d i=%d\n", pszLogName, pModElf->iSymSh, i));
1959 rc = VERR_LDRELF_MULTIPLE_SYMTABS;
1960 break;
1961 }
1962 pModElf->iSymSh = i;
1963 pModElf->cSyms = (unsigned)(paShdrs[i].sh_size / sizeof(Elf_Sym));
1964 AssertBreakStmt(pModElf->cSyms == paShdrs[i].sh_size / sizeof(Elf_Sym), rc = VERR_IMAGE_TOO_BIG);
1965 pModElf->iStrSh = paShdrs[i].sh_link;
1966 pModElf->cbStr = (unsigned)paShdrs[pModElf->iStrSh].sh_size;
1967 AssertBreakStmt(pModElf->cbStr == paShdrs[pModElf->iStrSh].sh_size, rc = VERR_IMAGE_TOO_BIG);
1968 }
1969
1970 /* Special checks for the section string table. */
1971 if (i == pModElf->Ehdr.e_shstrndx)
1972 {
1973 if (paShdrs[i].sh_type != SHT_STRTAB)
1974 {
1975 Log(("RTLdrElf: Section header string table is not a SHT_STRTAB: %#x\n", paShdrs[i].sh_type));
1976 rc = VERR_BAD_EXE_FORMAT;
1977 break;
1978 }
1979 if (paShdrs[i].sh_size == 0)
1980 {
1981 Log(("RTLdrElf: Section header string table is empty\n"));
1982 rc = VERR_BAD_EXE_FORMAT;
1983 break;
1984 }
1985 }
1986
1987 /* Kluge for the .data..percpu segment in 64-bit linux kernels. */
1988 if (paShdrs[i].sh_flags & SHF_ALLOC)
1989 {
1990 if ( paShdrs[i].sh_addr == 0
1991 && paShdrs[i].sh_addr < uNextAddr)
1992 {
1993 Elf_Addr uAddr = RT_ALIGN_T(uNextAddr, paShdrs[i].sh_addralign, Elf_Addr);
1994 Log(("RTLdrElf: Out of order section #%d; adjusting sh_addr from " FMT_ELF_ADDR " to " FMT_ELF_ADDR "\n",
1995 i, paShdrs[i].sh_addr, uAddr));
1996 paShdrs[i].sh_addr = uAddr;
1997 }
1998 uNextAddr = paShdrs[i].sh_addr + paShdrs[i].sh_size;
1999 }
2000 } /* for each section header */
2001
2002 /*
2003 * Calculate the image base address if the image isn't relocatable.
2004 */
2005 if (RT_SUCCESS(rc) && pModElf->Ehdr.e_type != ET_REL)
2006 {
2007 pModElf->LinkAddress = ~(Elf_Addr)0;
2008 for (unsigned i = 0; i < pModElf->Ehdr.e_shnum; i++)
2009 if ( (paShdrs[i].sh_flags & SHF_ALLOC)
2010 && paShdrs[i].sh_addr < pModElf->LinkAddress)
2011 pModElf->LinkAddress = paShdrs[i].sh_addr;
2012 if (pModElf->LinkAddress == ~(Elf_Addr)0)
2013 {
2014 AssertFailed();
2015 rc = VERR_LDR_GENERAL_FAILURE;
2016 }
2017 if (pModElf->Ehdr.e_type == ET_DYN && pModElf->LinkAddress < 0x1000)
2018 pModElf->LinkAddress = 0;
2019 }
2020
2021 /*
2022 * Perform allocations / RVA calculations, determine the image size.
2023 */
2024 if (RT_SUCCESS(rc))
2025 for (unsigned i = 0; i < pModElf->Ehdr.e_shnum; i++)
2026 if (paShdrs[i].sh_flags & SHF_ALLOC)
2027 {
2028 if (pModElf->Ehdr.e_type == ET_REL)
2029 paShdrs[i].sh_addr = paShdrs[i].sh_addralign
2030 ? RT_ALIGN_T(pModElf->cbImage, paShdrs[i].sh_addralign, Elf_Addr)
2031 : (Elf_Addr)pModElf->cbImage;
2032 else
2033 paShdrs[i].sh_addr -= pModElf->LinkAddress;
2034 Elf_Addr EndAddr = paShdrs[i].sh_addr + paShdrs[i].sh_size;
2035 if (pModElf->cbImage < EndAddr)
2036 {
2037 pModElf->cbImage = (size_t)EndAddr;
2038 AssertMsgBreakStmt(pModElf->cbImage == EndAddr, (FMT_ELF_ADDR "\n", EndAddr), rc = VERR_IMAGE_TOO_BIG);
2039 }
2040 Log2(("RTLdrElf: %s: Assigned " FMT_ELF_ADDR " to section #%d\n", pszLogName, paShdrs[i].sh_addr, i));
2041 }
2042
2043 Log2(("RTLdrElf: iSymSh=%u cSyms=%u iStrSh=%u cbStr=%u rc=%Rrc cbImage=%#zx LinkAddress=" FMT_ELF_ADDR "\n",
2044 pModElf->iSymSh, pModElf->cSyms, pModElf->iStrSh, pModElf->cbStr, rc,
2045 pModElf->cbImage, pModElf->LinkAddress));
2046 if (RT_SUCCESS(rc))
2047 {
2048 pModElf->Core.pOps = &RTLDRELF_MID(s_rtldrElf,Ops);
2049 pModElf->Core.eState = LDR_STATE_OPENED;
2050 *phLdrMod = &pModElf->Core;
2051
2052 LogFlow(("%s: %s: returns VINF_SUCCESS *phLdrMod=%p\n", __FUNCTION__, pszLogName, *phLdrMod));
2053 return VINF_SUCCESS;
2054 }
2055 }
2056
2057 RTMemFree(paShdrs);
2058 }
2059 else
2060 rc = VERR_NO_MEMORY;
2061 }
2062
2063 RTMemFree(pModElf);
2064 LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
2065 return rc;
2066}
2067
2068
2069
2070
2071/*******************************************************************************
2072* Cleanup Constants And Macros *
2073*******************************************************************************/
2074#undef RTLDRELF_NAME
2075#undef RTLDRELF_SUFF
2076#undef RTLDRELF_MID
2077
2078#undef FMT_ELF_ADDR
2079#undef FMT_ELF_HALF
2080#undef FMT_ELF_SHALF
2081#undef FMT_ELF_OFF
2082#undef FMT_ELF_SIZE
2083#undef FMT_ELF_SWORD
2084#undef FMT_ELF_WORD
2085#undef FMT_ELF_XWORD
2086#undef FMT_ELF_SXWORD
2087
2088#undef Elf_Ehdr
2089#undef Elf_Phdr
2090#undef Elf_Shdr
2091#undef Elf_Sym
2092#undef Elf_Rel
2093#undef Elf_Rela
2094#undef Elf_Reloc
2095#undef Elf_Nhdr
2096#undef Elf_Dyn
2097
2098#undef Elf_Addr
2099#undef Elf_Half
2100#undef Elf_Off
2101#undef Elf_Size
2102#undef Elf_Sword
2103#undef Elf_Word
2104
2105#undef RTLDRMODELF
2106#undef PRTLDRMODELF
2107
2108#undef ELF_R_SYM
2109#undef ELF_R_TYPE
2110#undef ELF_R_INFO
2111
2112#undef ELF_ST_BIND
2113
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