VirtualBox

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

Last change on this file since 49329 was 49044, checked in by vboxsync, 11 years ago

Darwin guest OS digger hacking in progress. Adding symbol cache util to iprt and started on the Mach-O code that'll make use of it (RTDbgModCreateFromMachOImage++). Updates kStuff from 53 to 55 for UUID query and 64-bit kext loading.

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