VirtualBox

Changeset 85501 in vbox for trunk


Ignore:
Timestamp:
Jul 29, 2020 9:10:35 AM (4 years ago)
Author:
vboxsync
Message:

IPRT/ldrELF: Early support for loading ET_DYN images. Current code is a bit cumbersome as it approaches it from the ET_REL/sections perspective rather than using program headers and the dynamic section. bugref:9801

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/formats/elf-common.h

    r76585 r85501  
    198198#define PT_LOPROC       0x70000000      /* First processor-specific type. */
    199199#define PT_HIPROC       0x7fffffff      /* Last processor-specific type. */
     200
     201#define PT_GNU_EH_FRAME 0x6474e550 /**< GNU/Linux -> .eh_frame_hdr */
     202#define PT_GNU_STACK    0x6474e551 /**< GNU/Linux -> stack prot (RWX or RW) */
     203#define PT_GNU_RELRO    0x6474e552 /**< GNU/Linux -> make RO after relocations */
     204#define PT_GNU_PROPERTY 0x6474e553 /**< GNU/Linux -> .note.gnu.property */
     205
    200206
    201207/* Values for p_flags. */
  • trunk/src/VBox/Runtime/common/ldr/ldrELF.cpp

    r82968 r85501  
    5252*********************************************************************************************************************************/
    5353/** Finds an ELF symbol table string. */
    54 #define ELF_STR(pHdrs, iStr) ((pHdrs)->pStr + (iStr))
     54#define ELF_STR(pHdrs, iStr)        ((pHdrs)->Rel.pStr + (iStr))
     55/** Finds an ELF symbol table string. */
     56#define ELF_DYN_STR(pHdrs, iStr)    ((pHdrs)->Dyn.pStr + (iStr))
    5557/** Finds an ELF section header string. */
    56 #define ELF_SH_STR(pHdrs, iStr) ((pHdrs)->pShStr + (iStr))
     58#define ELF_SH_STR(pHdrs, iStr)     ((pHdrs)->pShStr + (iStr))
    5759
    5860
     
    6365#ifdef LOG_ENABLED
    6466static const char *rtldrElfGetShdrType(uint32_t iType);
     67static const char *rtldrElfGetPhdrType(uint32_t iType);
    6568#endif
    6669
     
    8285
    8386#ifdef LOG_ENABLED
     87
    8488/**
    8589 * Gets the section type.
     
    9296    switch (iType)
    9397    {
    94         case SHT_NULL:          return "SHT_NULL";
    95         case SHT_PROGBITS:      return "SHT_PROGBITS";
    96         case SHT_SYMTAB:        return "SHT_SYMTAB";
    97         case SHT_STRTAB:        return "SHT_STRTAB";
    98         case SHT_RELA:          return "SHT_RELA";
    99         case SHT_HASH:          return "SHT_HASH";
    100         case SHT_DYNAMIC:       return "SHT_DYNAMIC";
    101         case SHT_NOTE:          return "SHT_NOTE";
    102         case SHT_NOBITS:        return "SHT_NOBITS";
    103         case SHT_REL:           return "SHT_REL";
    104         case SHT_SHLIB:         return "SHT_SHLIB";
    105         case SHT_DYNSYM:        return "SHT_DYNSYM";
     98        RT_CASE_RET_STR(SHT_NULL);
     99        RT_CASE_RET_STR(SHT_PROGBITS);
     100        RT_CASE_RET_STR(SHT_SYMTAB);
     101        RT_CASE_RET_STR(SHT_STRTAB);
     102        RT_CASE_RET_STR(SHT_RELA);
     103        RT_CASE_RET_STR(SHT_HASH);
     104        RT_CASE_RET_STR(SHT_DYNAMIC);
     105        RT_CASE_RET_STR(SHT_NOTE);
     106        RT_CASE_RET_STR(SHT_NOBITS);
     107        RT_CASE_RET_STR(SHT_REL);
     108        RT_CASE_RET_STR(SHT_SHLIB);
     109        RT_CASE_RET_STR(SHT_DYNSYM);
    106110        default:
    107111            return "";
    108112    }
    109113}
    110 #endif
     114
     115/**
     116 * Gets the program header type.
     117 *
     118 * @returns Pointer to read only string.
     119 * @param   iType       The section type index.
     120 */
     121static const char *rtldrElfGetPhdrType(uint32_t iType)
     122{
     123    switch (iType)
     124    {
     125        RT_CASE_RET_STR(PT_NULL);
     126        RT_CASE_RET_STR(PT_LOAD);
     127        RT_CASE_RET_STR(PT_DYNAMIC);
     128        RT_CASE_RET_STR(PT_INTERP);
     129        RT_CASE_RET_STR(PT_NOTE);
     130        RT_CASE_RET_STR(PT_SHLIB);
     131        RT_CASE_RET_STR(PT_PHDR);
     132        RT_CASE_RET_STR(PT_TLS);
     133        RT_CASE_RET_STR(PT_GNU_EH_FRAME);
     134        RT_CASE_RET_STR(PT_GNU_STACK);
     135        RT_CASE_RET_STR(PT_GNU_RELRO);
     136        RT_CASE_RET_STR(PT_GNU_PROPERTY);
     137        default:
     138            return "";
     139    }
     140}
     141
     142#endif /* LOG_ENABLED*/
    111143
    112144
     
    125157    const char *pszLogName = pReader->pfnLogName(pReader); NOREF(pszLogName);
    126158
    127     RT_NOREF_PV(pErrInfo); /** @todo implement */
    128 
    129159    /*
    130160     * Read the ident to decide if this is 32-bit or 64-bit
     
    135165    if (RT_FAILURE(rc))
    136166        return rc;
     167
    137168    if (    e_ident[EI_MAG0] != ELFMAG0
    138169        ||  e_ident[EI_MAG1] != ELFMAG1
     
    142173             && e_ident[EI_CLASS] != ELFCLASS64)
    143174       )
    144     {
    145         Log(("RTLdrELF: %s: Unsupported/invalid ident %.*Rhxs\n", pszLogName, sizeof(e_ident), e_ident));
    146         return VERR_BAD_EXE_FORMAT;
    147     }
     175        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     176                                   "%s: Unsupported/invalid ident %.*Rhxs", pszLogName, sizeof(e_ident), e_ident);
     177
    148178    if (e_ident[EI_DATA] != ELFDATA2LSB)
    149     {
    150         Log(("RTLdrELF: %s: ELF endian %x is unsupported\n", pszLogName, e_ident[EI_DATA]));
    151         return VERR_LDRELF_ODD_ENDIAN;
    152     }
     179        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_LDRELF_ODD_ENDIAN,
     180                                   "%s: ELF endian %x is unsupported", pszLogName, e_ident[EI_DATA]);
     181
    153182    if (e_ident[EI_CLASS] == ELFCLASS32)
    154         rc = rtldrELF32Open(pReader, fFlags, enmArch, phLdrMod);
     183        rc = rtldrELF32Open(pReader, fFlags, enmArch, phLdrMod, pErrInfo);
    155184    else
    156         rc = rtldrELF64Open(pReader, fFlags, enmArch, phLdrMod);
     185        rc = rtldrELF64Open(pReader, fFlags, enmArch, phLdrMod, pErrInfo);
    157186    return rc;
    158187}
  • trunk/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h

    r82968 r85501  
    3030*******************************************************************************/
    3131#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"
     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_ADDR7          "%07RX32"
     37# define FMT_ELF_HALF           "%04RX16"
     38# define FMT_ELF_OFF            "%08RX32"
     39# define FMT_ELF_SIZE           "%08RX32"
     40# define FMT_ELF_SWORD          "%RI32"
     41# define FMT_ELF_WORD           "%08RX32"
     42# define FMT_ELF_XWORD          "%08RX32"
     43# define FMT_ELF_SXWORD         "%RI32"
     44# define Elf_Xword              Elf32_Word
     45# define Elf_Sxword             Elf32_Sword
    4346
    4447#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"
     48# define RTLDRELF_NAME(name)    rtldrELF64##name
     49# define RTLDRELF_SUFF(name)    name##64
     50# define RTLDRELF_MID(pre,suff) pre##64##suff
     51# define FMT_ELF_ADDR           "%016RX64"
     52# define FMT_ELF_ADDR7          "%08RX64"
     53# define FMT_ELF_HALF           "%04RX16"
     54# define FMT_ELF_SHALF          "%RI16"
     55# define FMT_ELF_OFF            "%016RX64"
     56# define FMT_ELF_SIZE           "%016RX64"
     57# define FMT_ELF_SWORD          "%RI32"
     58# define FMT_ELF_WORD           "%08RX32"
     59# define FMT_ELF_XWORD          "%016RX64"
     60# define FMT_ELF_SXWORD         "%RI64"
     61# define Elf_Xword              Elf64_Xword
     62# define Elf_Sxword             Elf64_Sxword
    5763#endif
    5864
     
    7581#define PRTLDRMODELF        RTLDRELF_MID(PRTLDRMODELF,RT_NOTHING)
    7682
     83#define RTLDRMODELFSHX      RTLDRELF_MID(RTLDRMODELFSHX,RT_NOTHING)
     84#define PRTLDRMODELFSHX     RTLDRELF_MID(PRTLDRMODELFSHX,RT_NOTHING)
     85
    7786#define ELF_R_SYM(info)     RTLDRELF_MID(ELF,_R_SYM)(info)
    7887#define ELF_R_TYPE(info)    RTLDRELF_MID(ELF,_R_TYPE)(info)
     
    8695*   Structures and Typedefs                                                    *
    8796*******************************************************************************/
     97/**
     98 * Extra section info.
     99 */
     100typedef struct RTLDRMODELFSHX
     101{
     102    /** The corresponding program header. */
     103    uint16_t        idxPhdr;
     104    /** The corresponding dynamic section entry (address). */
     105    uint16_t        idxDt;
     106    /** The DT tag. */
     107    uint32_t        uDtTag;
     108} RTLDRMODELFSHX;
     109typedef RTLDRMODELFSHX *PRTLDRMODELFSHX;
     110
    88111/**
    89112 * The ELF loader structure.
     
    106129     * Not valid if the image is DONE. */
    107130    Elf_Shdr const         *paOrgShdrs;
     131    /** Runs parallel to paShdrs and is part of the same allocation. */
     132    PRTLDRMODELFSHX         paShdrExtras;
     133    /** Base section number, either 1 or zero depending on whether we've
     134     *  re-used the NULL entry for .elf.headers in ET_EXEC/ET_DYN. */
     135    unsigned                iFirstSect;
    108136    /** The size of the loaded image. */
    109137    size_t                  cbImage;
     
    112140    Elf_Addr                LinkAddress;
    113141
    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 
     142    struct
     143    {
     144        /** The symbol section index. */
     145        unsigned            iSymSh;
     146        /** Number of symbols in the table. */
     147        unsigned            cSyms;
     148        /** Pointer to symbol table within RTLDRMODELF::pvBits. */
     149        const Elf_Sym      *paSyms;
     150
     151        /** The string section index. */
     152        unsigned            iStrSh;
     153        /** Size of the string table. */
     154        unsigned            cbStr;
     155        /** Pointer to string table within RTLDRMODELF::pvBits. */
     156        const char         *pStr;
     157    } Rel /**< Regular symbols and strings. */
     158    , Dyn /**< Dynamic symbols and strings. */;
     159
     160    /** Pointer to section header string table within RTLDRMODELF::pvBits. */
     161    const char             *pShStr;
    128162    /** Size of the section header string table. */
    129163    unsigned                cbShStr;
    130     /** Pointer to section header string table within RTLDRMODELF::pvBits. */
    131     const char             *pShStr;
    132164
    133165    /** The '.eh_frame' section index.  Zero if not searched for, ~0U if not found. */
     
    135167    /** The '.eh_frame_hdr' section index.  Zero if not searched for, ~0U if not found. */
    136168    unsigned                iShEhFrameHdr;
    137 } RTLDRMODELF, *PRTLDRMODELF;
     169
     170    /** The '.dynamic' / SHT_DYNAMIC section index.  ~0U if not present. */
     171    unsigned                iShDynamic;
     172    /** Number of entries in paDynamic. */
     173    unsigned                cDynamic;
     174    /** The dynamic section (NULL for ET_REL). */
     175    Elf_Dyn                *paDynamic;
     176    /** Program headers (NULL for ET_REL). */
     177    Elf_Phdr               *paPhdrs;
     178
     179    /** Info extracted from PT_DYNAMIC and the program headers. */
     180    struct
     181    {
     182        /** DT_RELA/DT_REL. */
     183        Elf_Addr            uPtrRelocs;
     184        /** DT_RELASZ/DT_RELSZ. */
     185        Elf_Xword           cbRelocs;
     186        /** Non-zero if we've seen DT_RELAENT/DT_RELENT. */
     187        unsigned            cbRelocEntry;
     188        /** DT_RELA or DT_REL. */
     189        unsigned            uRelocType;
     190        /** The index of the section header matching DT_RELA/DT_REL. */
     191        unsigned            idxShRelocs;
     192
     193        /** DT_JMPREL. */
     194        Elf_Addr            uPtrJmpRelocs;
     195        /** DT_PLTRELSZ. */
     196        Elf_Xword           cbJmpRelocs;
     197        /** DT_RELA or DT_REL (if we've seen DT_PLTREL). */
     198        unsigned            uJmpRelocType;
     199        /** The index of the section header matching DT_JMPREL. */
     200        unsigned            idxShJmpRelocs;
     201    } DynInfo;
     202} RTLDRMODELF;
     203/** Pointer to an ELF module instance. */
     204typedef RTLDRMODELF *PRTLDRMODELF;
    138205
    139206
     
    155222    {
    156223        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);
     224        if (pModElf->Rel.iSymSh != ~0U)
     225            pModElf->Rel.paSyms = (const Elf_Sym *)(pu8 + pModElf->paShdrs[pModElf->Rel.iSymSh].sh_offset);
     226        if (pModElf->Rel.iStrSh != ~0U)
     227            pModElf->Rel.pStr   =    (const char *)(pu8 + pModElf->paShdrs[pModElf->Rel.iStrSh].sh_offset);
     228        if (pModElf->Dyn.iSymSh != ~0U)
     229            pModElf->Dyn.paSyms = (const Elf_Sym *)(pu8 + pModElf->paShdrs[pModElf->Dyn.iSymSh].sh_offset);
     230        if (pModElf->Dyn.iStrSh != ~0U)
     231            pModElf->Dyn.pStr   =    (const char *)(pu8 + pModElf->paShdrs[pModElf->Dyn.iStrSh].sh_offset);
     232        pModElf->pShStr         =    (const char *)(pu8 + pModElf->paShdrs[pModElf->Ehdr.e_shstrndx].sh_offset);
    162233
    163234        /*
     
    168239         * are safe to use.
    169240         */
    170         AssertMsgStmt(   pModElf->iStrSh == ~0U
    171                       || pModElf->pStr[pModElf->paShdrs[pModElf->iStrSh].sh_size - 1] == '\0',
     241        AssertMsgStmt(   pModElf->Rel.iStrSh == ~0U
     242                      || pModElf->Rel.pStr[pModElf->paShdrs[pModElf->Rel.iStrSh].sh_size - 1] == '\0',
     243                      ("The string table is not zero terminated!\n"),
     244                      rc = VERR_LDRELF_UNTERMINATED_STRING_TAB);
     245        AssertMsgStmt(   pModElf->Dyn.iStrSh == ~0U
     246                      || pModElf->Dyn.pStr[pModElf->paShdrs[pModElf->Dyn.iStrSh].sh_size - 1] == '\0',
    172247                      ("The string table is not zero terminated!\n"),
    173248                      rc = VERR_LDRELF_UNTERMINATED_STRING_TAB);
     
    181256            int rc2 = pModElf->Core.pReader->pfnUnmap(pModElf->Core.pReader, pModElf->pvBits);
    182257            AssertRC(rc2);
    183             pModElf->pvBits = NULL;
    184             pModElf->paSyms = NULL;
    185             pModElf->pStr   = NULL;
    186             pModElf->pShStr = NULL;
     258            pModElf->pvBits     = NULL;
     259            pModElf->Rel.paSyms = NULL;
     260            pModElf->Rel.pStr   = NULL;
     261            pModElf->Dyn.paSyms = NULL;
     262            pModElf->Dyn.pStr   = NULL;
     263            pModElf->pShStr     = NULL;
    187264        }
    188265    }
     
    200277 *
    201278 */
     279
     280/**
     281 * Get the symbol and symbol value.
     282 *
     283 * @returns iprt status code.
     284 * @param   pModElf         The ELF loader module instance data.
     285 * @param   BaseAddr        The base address which the module is being fixedup to.
     286 * @param   pfnGetImport    The callback function to use to resolve imports (aka unresolved externals).
     287 * @param   pvUser          User argument to pass to the callback.
     288 * @param   iSym            The symbol to get.
     289 * @param   ppSym           Where to store the symbol pointer on success. (read only)
     290 * @param   pSymValue       Where to store the symbol value on success.
     291 */
     292static int RTLDRELF_NAME(SymbolExecDyn)(PRTLDRMODELF pModElf, Elf_Addr BaseAddr, PFNRTLDRIMPORT pfnGetImport, void *pvUser,
     293                                        Elf_Size iSym, const Elf_Sym **ppSym, Elf_Addr *pSymValue)
     294{
     295    /*
     296     * Validate and find the symbol.
     297     */
     298    AssertMsgReturn(iSym < pModElf->Dyn.cSyms, ("iSym=%d is an invalid symbol index!\n", iSym), VERR_LDRELF_INVALID_SYMBOL_INDEX);
     299    const Elf_Sym *pSym = &pModElf->Dyn.paSyms[iSym];
     300    *ppSym = pSym;
     301
     302    AssertMsgReturn(pSym->st_name < pModElf->Dyn.cbStr,
     303                    ("iSym=%d st_name=%d str sh_size=%d\n", iSym, pSym->st_name, pModElf->Dyn.cbStr),
     304                    VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET);
     305    const char * const pszName = pModElf->Dyn.pStr + pSym->st_name;
     306
     307    /*
     308     * Determine the symbol value.
     309     *
     310     * Symbols needs different treatment depending on which section their are in.
     311     * Undefined and absolute symbols goes into special non-existing sections.
     312     */
     313    switch (pSym->st_shndx)
     314    {
     315        /*
     316         * Undefined symbol, needs resolving.
     317         *
     318         * Since ELF has no generic concept of importing from specific module (the OS/2 ELF format
     319         * has but that's an OS extension and only applies to programs and dlls), we'll have to ask
     320         * the resolver callback to do a global search.
     321         */
     322        case SHN_UNDEF:
     323        {
     324            /* Try to resolve the symbol. */
     325            RTUINTPTR Value;
     326            int rc = pfnGetImport(&pModElf->Core, "", pszName, ~0U, &Value, pvUser);
     327            AssertMsgRCReturn(rc, ("Failed to resolve '%s' (iSym=" FMT_ELF_SIZE " rc=%Rrc\n", pszName, iSym, rc), rc);
     328
     329            *pSymValue = (Elf_Addr)Value;
     330            AssertMsgReturn((RTUINTPTR)*pSymValue == Value,
     331                            ("Symbol value overflowed! '%s' (iSym=" FMT_ELF_SIZE "\n", pszName, iSym), VERR_SYMBOL_VALUE_TOO_BIG);
     332
     333            Log2(("rtldrELF: #%-3d - UNDEF " FMT_ELF_ADDR " '%s'\n", iSym, *pSymValue, pszName));
     334            break;
     335        }
     336
     337        /*
     338         * Absolute symbols needs no fixing since they are, well, absolute.
     339         */
     340        case SHN_ABS:
     341            *pSymValue = pSym->st_value;
     342            Log2(("rtldrELF: #%-3d - ABS   " FMT_ELF_ADDR " '%s'\n", iSym, *pSymValue, pszName));
     343            break;
     344
     345        /*
     346         * All other symbols are addressed relative the image base in DYN and EXEC binaries.
     347         */
     348        default:
     349            AssertMsgReturn(pSym->st_shndx < pModElf->Ehdr.e_shnum,
     350                            ("iSym=%d st_shndx=%d e_shnum=%d pszName=%s\n", iSym, pSym->st_shndx, pModElf->Ehdr.e_shnum, pszName),
     351                            VERR_BAD_EXE_FORMAT);
     352            *pSymValue = pSym->st_value + BaseAddr;
     353            Log2(("rtldrELF: #%-3d - %5d " FMT_ELF_ADDR " '%s'\n", iSym, pSym->st_shndx, *pSymValue, pszName));
     354            break;
     355    }
     356
     357    return VINF_SUCCESS;
     358}
     359
     360
     361#if   ELF_MODE == 32
     362/** Helper for RelocateSectionExecDyn. */
     363DECLINLINE(const Elf_Shdr *) RTLDRELF_NAME(RvaToSectionHeader)(PRTLDRMODELF pModElf, Elf_Addr uRva)
     364{
     365    const Elf_Shdr * const pShdrFirst = pModElf->paShdrs;
     366    const Elf_Shdr *pShdr = pShdrFirst + pModElf->Ehdr.e_shnum;
     367    while (--pShdr != pShdrFirst)
     368        if (uRva - pShdr->sh_addr /*rva*/ < pShdr->sh_size)
     369            return pShdr;
     370    AssertFailed();
     371    return pShdr;
     372}
     373#endif
    202374
    203375
     
    231403     * The relocations are stored in an array of Elf32_Rel records and covers the entire relocation section.
    232404     */
     405#if   ELF_MODE == 32
     406    const Elf_Shdr   *pShdr    = pModElf->paShdrs;
    233407    const Elf_Addr    offDelta = BaseAddr - pModElf->LinkAddress;
     408#endif
    234409    const Elf_Reloc  *paRels   = (const Elf_Reloc *)pvRelocs;
    235     const unsigned    iRelMax   = (unsigned)(cbRelocs / sizeof(paRels[0]));
     410    const unsigned    iRelMax  = (unsigned)(cbRelocs / sizeof(paRels[0]));
    236411    AssertMsgReturn(iRelMax == cbRelocs / sizeof(paRels[0]), (FMT_ELF_SIZE "\n", cbRelocs / sizeof(paRels[0])),
    237412                    VERR_IMAGE_TOO_BIG);
     
    239414    {
    240415        /*
    241          * Skip R_XXX_NONE entries early to avoid confusion in the symbol
    242          * getter code.
     416         * Apply fixups not taking a symbol (will 'continue' rather than 'break').
    243417         */
     418        AssertMsgReturn(paRels[iRel].r_offset < cbSec, (FMT_ELF_ADDR " " FMT_ELF_SIZE "\n", paRels[iRel].r_offset, cbSec),
     419                        VERR_LDRELF_INVALID_RELOCATION_OFFSET);
    244420#if   ELF_MODE == 32
    245         if (ELF_R_TYPE(paRels[iRel].r_info) == R_386_NONE)
    246             continue;
     421        if (paRels[iRel].r_offset - pShdr->sh_addr /*rva*/ >= pShdr->sh_size)
     422            pShdr = RTLDRELF_NAME(RvaToSectionHeader)(pModElf, paRels[iRel].r_offset);
     423        static const Elf_Addr s_uZero = 0;
     424        const Elf_Addr *pAddrR = RT_LIKELY(pShdr->sh_type != SHT_NOBITS)                     /* Where to read the addend. */
     425                               ? (const Elf_Addr *)(pu8SecBaseR + paRels[iRel].r_offset - pShdr->sh_addr /*rva*/
     426                                                    + pShdr->sh_offset)
     427                               : &s_uZero;
     428#endif
     429        Elf_Addr       *pAddrW =       (Elf_Addr *)(pu8SecBaseW + paRels[iRel].r_offset);    /* Where to write the fixup. */
     430        switch (ELF_R_TYPE(paRels[iRel].r_info))
     431        {
     432            /*
     433             * Image relative (addend + base).
     434             */
     435#if   ELF_MODE == 32
     436            case R_386_RELATIVE:
     437            {
     438                const Elf_Addr Value = *pAddrR + BaseAddr;
     439                *(uint32_t *)pAddrW = Value;
     440                Log4((FMT_ELF_ADDR "/" FMT_ELF_ADDR7 ": R_386_RELATIVE Value=" FMT_ELF_ADDR "\n",
     441                      SecAddr + paRels[iRel].r_offset + BaseAddr, paRels[iRel].r_offset, Value));
     442                AssertCompile(sizeof(Value) == sizeof(uint32_t));
     443                continue;
     444            }
    247445#elif ELF_MODE == 64
    248         if (ELF_R_TYPE(paRels[iRel].r_info) == R_X86_64_NONE)
    249             continue;
     446            case R_X86_64_RELATIVE:
     447            {
     448                const Elf_Addr Value = paRels[iRel].r_addend + BaseAddr;
     449                *(uint64_t *)pAddrW = (uint64_t)Value;
     450                Log4((FMT_ELF_ADDR "/" FMT_ELF_ADDR7 ": R_X86_64_RELATIVE Value=" FMT_ELF_ADDR "\n",
     451                      SecAddr + paRels[iRel].r_offset + BaseAddr, paRels[iRel].r_offset, Value));
     452                AssertCompile(sizeof(Value) == sizeof(uint64_t));
     453                continue;
     454            }
    250455#endif
     456
     457            /*
     458             * R_XXX_NONE.
     459             */
     460#if   ELF_MODE == 32
     461            case R_386_NONE:
     462#elif ELF_MODE == 64
     463            case R_X86_64_NONE:
     464#endif
     465                continue;
     466        }
    251467
    252468        /*
    253469         * Validate and find the symbol, resolve undefined ones.
    254470         */
    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
     471        const Elf_Sym  *pSym = NULL; /* shut up gcc */
     472        Elf_Addr        SymValue = 0; /* shut up gcc-4 */
     473        int rc = RTLDRELF_NAME(SymbolExecDyn)(pModElf, BaseAddr, pfnGetImport, pvUser, ELF_R_SYM(paRels[iRel].r_info), &pSym, &SymValue);
     474        if (RT_FAILURE(rc))
     475            return rc;
    298476
    299477        /*
    300478         * Apply the fixup.
    301479         */
    302         AssertMsgReturn(paRels[iRel].r_offset < cbSec, (FMT_ELF_ADDR " " FMT_ELF_SIZE "\n", paRels[iRel].r_offset, cbSec), VERR_LDRELF_INVALID_RELOCATION_OFFSET);
     480        switch (ELF_R_TYPE(paRels[iRel].r_info))
     481        {
    303482#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
     483            /*
     484             * GOT/PLT.
     485             */
     486            case R_386_GLOB_DAT:
     487            {
     488                *(uint32_t *)pAddrW = (uint32_t)SymValue;
     489                Log4((FMT_ELF_ADDR "/" FMT_ELF_ADDR7 ": R_386_GLOB_DAT Value=" FMT_ELF_ADDR "\n",
     490                      SecAddr + paRels[iRel].r_offset + BaseAddr, paRels[iRel].r_offset, SymValue));
     491                AssertCompile(sizeof(SymValue) == sizeof(uint32_t));
     492                break;
     493            }
     494
     495            case R_386_JMP_SLOT:
     496            {
     497                *(uint32_t *)pAddrW = (uint32_t)SymValue;
     498                Log4((FMT_ELF_ADDR "/" FMT_ELF_ADDR7 ": R_386_JMP_SLOT Value=" FMT_ELF_ADDR "\n",
     499                      SecAddr + paRels[iRel].r_offset + BaseAddr, paRels[iRel].r_offset, SymValue));
     500                AssertCompile(sizeof(SymValue) == sizeof(uint32_t));
     501                break;
     502            }
     503
    310504            /*
    311505             * Absolute addressing.
     
    323517                    AssertFailedReturn(VERR_LDR_GENERAL_FAILURE); /** @todo SHN_COMMON */
    324518                *(uint32_t *)pAddrW = Value;
    325                 Log4((FMT_ELF_ADDR": R_386_32   Value=" FMT_ELF_ADDR "\n", SecAddr + paRels[iRel].r_offset + BaseAddr, Value));
     519                Log4((FMT_ELF_ADDR "/" FMT_ELF_ADDR7 ": R_386_32   Value=" FMT_ELF_ADDR "\n",
     520                      SecAddr + paRels[iRel].r_offset + BaseAddr, paRels[iRel].r_offset, Value));
    326521                break;
    327522            }
     
    345540                else
    346541                    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));
     542                Log4((FMT_ELF_ADDR "/" FMT_ELF_ADDR7 ": R_386_PC32 Value=" FMT_ELF_ADDR "\n",
     543                      SecAddr + paRels[iRel].r_offset + BaseAddr, paRels[iRel].r_offset, Value));
    348544                break;
    349545            }
    350546
    351547#elif ELF_MODE == 64
    352 
    353548            /*
    354              * Absolute addressing
     549             * GOT/PLT.
     550             */
     551            case R_X86_64_GLOB_DAT:
     552            {
     553                *(uint64_t *)pAddrW = (uint64_t)SymValue;
     554                Log4((FMT_ELF_ADDR "/" FMT_ELF_ADDR7 ": R_X86_64_GLOB_DAT Value=" FMT_ELF_ADDR "\n",
     555                      SecAddr + paRels[iRel].r_offset + BaseAddr, paRels[iRel].r_offset, SymValue));
     556                AssertCompile(sizeof(SymValue) == sizeof(uint64_t));
     557                break;
     558            }
     559
     560            case R_X86_64_JMP_SLOT:
     561            {
     562                *(uint64_t *)pAddrW = (uint64_t)SymValue;
     563                Log4((FMT_ELF_ADDR "/" FMT_ELF_ADDR7 ": R_X86_64_JMP_SLOT Value=" FMT_ELF_ADDR "\n",
     564                      SecAddr + paRels[iRel].r_offset + BaseAddr, paRels[iRel].r_offset, SymValue));
     565                AssertCompile(sizeof(SymValue) == sizeof(uint64_t));
     566                break;
     567            }
     568
     569            /*
     570             * Absolute addressing.
    355571             */
    356572            case R_X86_64_64:
    357573            {
     574                const Elf_Addr Value = SymValue + paRels[iRel].r_addend;
    358575                *(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));
     576                Log4((FMT_ELF_ADDR "/" FMT_ELF_ADDR7 ": R_X86_64_64   Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
     577                      SecAddr + paRels[iRel].r_offset + BaseAddr, paRels[iRel].r_offset, Value, SymValue));
    361578                break;
    362579            }
     
    367584            case R_X86_64_32:
    368585            {
     586                const Elf_Addr Value = SymValue + paRels[iRel].r_addend;
    369587                *(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));
     588                Log4((FMT_ELF_ADDR "/" FMT_ELF_ADDR7 ": R_X86_64_32   Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
     589                      SecAddr + paRels[iRel].r_offset + BaseAddr, paRels[iRel].r_offset, Value, SymValue));
    372590                AssertMsgReturn((Elf_Addr)*(uint32_t *)pAddrW == SymValue, ("Value=" FMT_ELF_ADDR "\n", SymValue),
    373591                                VERR_SYMBOL_VALUE_TOO_BIG);
     
    380598            case R_X86_64_32S:
    381599            {
     600                const Elf_Addr Value = SymValue + paRels[iRel].r_addend;
    382601                *(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));
     602                Log4((FMT_ELF_ADDR "/" FMT_ELF_ADDR7 ": R_X86_64_32S  Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
     603                      SecAddr + paRels[iRel].r_offset + BaseAddr, paRels[iRel].r_offset, Value, SymValue));
    385604                AssertMsgReturn((Elf_Addr)*(int32_t *)pAddrW == Value, ("Value=" FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG); /** @todo check the sign-extending here. */
    386605                break;
     
    391610             */
    392611            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;
     612            {
     613                const Elf_Addr SourceAddr = SecAddr  + paRels[iRel].r_offset + BaseAddr; /* Where the source really is. */
     614                const Elf_Addr Value      = SymValue + paRels[iRel].r_addend - SourceAddr;
    397615                *(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));
     616                Log4((FMT_ELF_ADDR "/" FMT_ELF_ADDR7 ": R_X86_64_PC32 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
     617                      SourceAddr, paRels[iRel].r_offset, Value, SymValue));
    400618                AssertMsgReturn((Elf_Addr)*(int32_t *)pAddrW == Value, ("Value=" FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG); /** @todo check the sign-extending here. */
    401619                break;
    402620            }
     621
    403622#endif
    404 
    405623            default:
    406624                AssertMsgFailed(("Unknown relocation type: %d (iRel=%d iRelMax=%d)\n",
     
    443661     * Validate and find the symbol.
    444662     */
    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];
     663    AssertMsgReturn(iSym < pModElf->Rel.cSyms, ("iSym=%d is an invalid symbol index!\n", iSym), VERR_LDRELF_INVALID_SYMBOL_INDEX);
     664    const Elf_Sym *pSym = &pModElf->Rel.paSyms[iSym];
    451665    *ppSym = pSym;
    452666
    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     }
     667    AssertMsgReturn(pSym->st_name < pModElf->Rel.cbStr,
     668                    ("iSym=%d st_name=%d str sh_size=%d\n", iSym, pSym->st_name, pModElf->Rel.cbStr),
     669                    VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET);
    458670    const char *pszName = ELF_STR(pModElf, pSym->st_name);
    459671
     
    470682         *
    471683         * 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
     684         * has but that's an OS extension and only applies to programs and dlls), we'll have to ask
    473685         * the resolver callback to do a global search.
    474686         */
     
    478690            RTUINTPTR Value;
    479691            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             }
     692            AssertMsgRCReturn(rc, ("Failed to resolve '%s' (iSym=" FMT_ELF_SIZE " rc=%Rrc\n", pszName, iSym, rc), rc);
    485693            *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             }
     694
     695            AssertMsgReturn((RTUINTPTR)*pSymValue == Value,
     696                            ("Symbol value overflowed! '%s' (iSym=" FMT_ELF_SIZE ")\n", pszName, iSym),
     697                            VERR_SYMBOL_VALUE_TOO_BIG);
    491698
    492699            Log2(("rtldrELF: #%-3d - UNDEF " FMT_ELF_ADDR " '%s'\n", iSym, *pSymValue, pszName));
     
    537744 * @param   cbRelocs        Size of the relocations.
    538745 */
    539 static 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)
     746static int RTLDRELF_NAME(RelocateSectionRel)(PRTLDRMODELF pModElf, Elf_Addr BaseAddr, PFNRTLDRIMPORT pfnGetImport, void *pvUser,
     747                                             const Elf_Addr SecAddr, Elf_Size cbSec, const uint8_t *pu8SecBaseR,
     748                                             uint8_t *pu8SecBaseW, const void *pvRelocs, Elf_Size cbRelocs)
    542749{
    543750#if ELF_MODE != 32
     
    703910    }
    704911
     912    if (pModElf->paPhdrs)
     913    {
     914        RTMemFree(pModElf->paPhdrs);
     915        pModElf->paPhdrs = NULL;
     916    }
     917
     918    if (pModElf->paDynamic)
     919    {
     920        RTMemFree(pModElf->paDynamic);
     921        pModElf->paDynamic = NULL;
     922    }
     923
    705924    if (pModElf->pvBits)
    706925    {
     
    722941
    723942
    724 /** @copydoc RTLDROPS::EnumSymbols */
    725 static DECLCALLBACK(int) RTLDRELF_NAME(EnumSymbols)(PRTLDRMODINTERNAL pMod, unsigned fFlags, const void *pvBits, RTUINTPTR BaseAddress,
    726                                                     PFNRTLDRENUMSYMS pfnCallback, void *pvUser)
     943/** @copydoc RTLDROPS::pfnEnumSymbols */
     944static DECLCALLBACK(int) RTLDRELF_NAME(EnumSymbols)(PRTLDRMODINTERNAL pMod, unsigned fFlags, const void *pvBits,
     945                                                    RTUINTPTR BaseAddress, PFNRTLDRENUMSYMS pfnCallback, void *pvUser)
    727946{
    728947    PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
     
    745964     * Enumerate the symbol table.
    746965     */
    747     const Elf_Sym  *paSyms = pModElf->paSyms;
    748     unsigned        cSyms  = pModElf->cSyms;
     966    const Elf_Sym  *paSyms  = pModElf->Rel.paSyms;
     967    unsigned        cSyms   = pModElf->Rel.cSyms;
     968    const char     *pszzStr = pModElf->Rel.pStr;
     969    unsigned        cbStr   = pModElf->Rel.cbStr;
     970    if (   (   !(fFlags & RTLDR_ENUM_SYMBOL_FLAGS_ALL)
     971            && pModElf->Dyn.cSyms > 0)
     972        || cSyms == 0)
     973    {
     974        paSyms  = pModElf->Dyn.paSyms;
     975        cSyms   = pModElf->Dyn.cSyms;
     976        pszzStr = pModElf->Dyn.pStr;
     977        cbStr   = pModElf->Dyn.cbStr;
     978    }
     979
    749980    for (unsigned iSym = 1; iSym < cSyms; iSym++)
    750981    {
     
    7751006            }
    7761007
    777             AssertMsgReturn(paSyms[iSym].st_name < pModElf->cbStr,
     1008            AssertMsgReturn(paSyms[iSym].st_name < cbStr,
    7781009                            ("String outside string table! iSym=%d paSyms[iSym].st_name=%#x\n", iSym, paSyms[iSym].st_name),
    7791010                            VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET);
    780 
    781             const char *pszName = ELF_STR(pModElf, paSyms[iSym].st_name);
     1011            const char * const pszName = pszzStr + paSyms[iSym].st_name;
     1012
    7821013            /* String termination was already checked when the string table was mapped. */
    783             if (    (pszName && *pszName)
     1014            if (    *pszName != '\0'
    7841015                &&  (   (fFlags & RTLDR_ENUM_SYMBOL_FLAGS_ALL)
    785                      || ELF_ST_BIND(paSyms[iSym].st_info) == STB_GLOBAL)
    786                )
     1016                     || ELF_ST_BIND(paSyms[iSym].st_info) == STB_GLOBAL) )
    7871017            {
    7881018                /*
     
    7901020                 */
    7911021                AssertMsgReturn(Value == (RTUINTPTR)Value, (FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG);
    792                 rc = pfnCallback(pMod, pszName, ~0U, (RTUINTPTR)Value, pvUser);
     1022                rc = pfnCallback(pMod, pszName, iSym, (RTUINTPTR)Value, pvUser);
    7931023                if (rc)
    7941024                    return rc;
     
    8211051    {
    8221052        case ET_REL:
     1053        case ET_DYN:
    8231054            break;
    8241055        case ET_EXEC:
    8251056            Log(("RTLdrELF: %s: Executable images are not supported yet!\n", pModElf->Core.pReader->pfnLogName(pModElf->Core.pReader)));
    8261057            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;
    8301058        default: AssertFailedReturn(VERR_BAD_EXE_FORMAT);
    8311059    }
     
    8861114    {
    8871115        case ET_REL:
     1116        case ET_DYN:
    8881117            break;
    8891118        case ET_EXEC:
    8901119            Log(("RTLdrELF: %s: Executable images are not supported yet!\n", pszLogName));
    8911120            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;
    8951121        default: AssertFailedReturn(VERR_BAD_EXE_FORMAT);
    8961122    }
     
    9111137    /*
    9121138     * 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.
     1139     *
     1140     * In ET_REL files the SHT_REL[A] sections have the section index of
     1141     * the section they contain fixups for in the sh_info member.
    9151142     */
    9161143    const Elf_Shdr *paShdrs = pModElf->paShdrs;
     
    9291156#endif
    9301157            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. */
    9451158        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);
     1159        {
     1160            if (pShdrRel->sh_info >= pModElf->Ehdr.e_shnum)
     1161                continue;
     1162            const Elf_Shdr *pShdr = &paShdrs[pShdrRel->sh_info]; /* the section to fixup. */
     1163            if (!(pShdr->sh_flags & SHF_ALLOC))
     1164                continue;
     1165
     1166            /*
     1167             * Relocate the section.
     1168             */
     1169            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",
     1170                  pszLogName, (int)pShdrRel->sh_info, ELF_SH_STR(pModElf, pShdr->sh_name), (int)pShdr->sh_info, (int)pShdr->sh_link,
     1171                  iShdr, ELF_SH_STR(pModElf, pShdrRel->sh_name), (int)pShdrRel->sh_info, (int)pShdrRel->sh_link));
     1172
     1173            rc = RTLDRELF_NAME(RelocateSectionRel)(pModElf, BaseAddr, pfnGetImport, pvUser,
     1174                                                   pShdr->sh_addr,
     1175                                                   pShdr->sh_size,
     1176                                                   (const uint8_t *)pModElf->pvBits + pShdr->sh_offset,
     1177                                                   (uint8_t *)pvBits + pShdr->sh_addr,
     1178                                                   (const uint8_t *)pModElf->pvBits + pShdrRel->sh_offset,
     1179                                                   pShdrRel->sh_size);
     1180        }
    9531181        else
    9541182            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,
     1183                                                       0, pModElf->cbImage,
     1184                                                       (const uint8_t *)pModElf->pvBits /** @todo file offset ?? */,
     1185                                                       (uint8_t *)pvBits,
    9591186                                                       (const uint8_t *)pModElf->pvBits + pShdrRel->sh_offset,
    9601187                                                       pShdrRel->sh_size);
     1188
    9611189        if (RT_FAILURE(rc))
    9621190            return rc;
     
    10171245     * Calc all kinds of pointers before we start iterating the symbol table.
    10181246     */
    1019     const Elf_Sym     *paSyms = pModElf->paSyms;
    1020     unsigned            cSyms = pModElf->cSyms;
     1247    const Elf_Sym *paSyms  = pModElf->Rel.paSyms;
     1248    unsigned       cSyms   = pModElf->Rel.cSyms;
     1249    const char    *pszzStr = pModElf->Rel.pStr;
     1250    unsigned       cbStr   = pModElf->Rel.cbStr;
     1251    if (pModElf->Dyn.cSyms > 0)
     1252    {
     1253        paSyms  = pModElf->Dyn.paSyms;
     1254        cSyms   = pModElf->Dyn.cSyms;
     1255        pszzStr = pModElf->Dyn.pStr;
     1256        cbStr   = pModElf->Dyn.cbStr;
     1257    }
     1258
    10211259    if (iOrdinal == UINT32_MAX)
    10221260    {
    1023         const char     *pStr  = pModElf->pStr;
    10241261        for (unsigned iSym = 1; iSym < cSyms; iSym++)
    10251262        {
     
    10301267            {
    10311268                /* Validate the name string and try match with it. */
    1032                 if (paSyms[iSym].st_name < pModElf->cbStr)
     1269                AssertMsgReturn(paSyms[iSym].st_name < cbStr,
     1270                                ("String outside string table! iSym=%d paSyms[iSym].st_name=%#x\n", iSym, paSyms[iSym].st_name),
     1271                                VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET);
     1272                if (!strcmp(pszSymbol, pszzStr + paSyms[iSym].st_name))
    10331273                {
    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;
     1274                    /* matched! */
     1275                    return RTLDRELF_NAME(ReturnSymbol)(pModElf, &paSyms[iSym], uBaseAddr, pValue);
    10441276                }
    10451277            }
     
    11641396    const Elf_Shdr *paShdrs    = pModElf->paShdrs;
    11651397    const Elf_Shdr *paOrgShdrs = pModElf->paOrgShdrs;
    1166     for (unsigned iShdr = 1; iShdr < pModElf->Ehdr.e_shnum; iShdr++)
     1398    for (unsigned iShdr = pModElf->iFirstSect; iShdr < pModElf->Ehdr.e_shnum; iShdr++)
    11671399    {
    11681400        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);
     1401        if (iShdr != 0)
     1402        {
     1403            Seg.pszName     = ELF_SH_STR(pModElf, paShdrs[iShdr].sh_name);
     1404            Seg.cchName     = (uint32_t)strlen(Seg.pszName);
     1405            if (Seg.cchName == 0)
     1406            {
     1407                Seg.pszName = szName;
     1408                Seg.cchName = (uint32_t)RTStrPrintf(szName, sizeof(szName), "UnamedSect%02u", iShdr);
     1409            }
     1410        }
     1411        else
     1412        {
     1413            Seg.pszName = ".elf.headers";
     1414            Seg.cchName = 12;
    11751415        }
    11761416        Seg.SelFlat     = 0;
     
    12311471
    12321472    const Elf_Shdr *pShdrEnd = NULL;
    1233     unsigned        cLeft    = pModElf->Ehdr.e_shnum - 1;
    1234     const Elf_Shdr *pShdr    = &pModElf->paOrgShdrs[cLeft];
     1473    unsigned        cLeft    = pModElf->Ehdr.e_shnum - pModElf->iFirstSect;
     1474    const Elf_Shdr *pShdr    = &pModElf->paOrgShdrs[pModElf->Ehdr.e_shnum];
    12351475    while (cLeft-- > 0)
    12361476    {
     1477        pShdr--;
    12371478        if (pShdr->sh_flags & SHF_ALLOC)
    12381479        {
     
    12471488                pShdrEnd = pShdr;
    12481489        }
    1249         pShdr--;
    12501490    }
    12511491
     
    12531493    {
    12541494        *poffSeg = pShdrEnd->sh_size;
    1255         *piSeg   = pShdrEnd - pModElf->paOrgShdrs - 1;
     1495        *piSeg   = pShdrEnd - pModElf->paOrgShdrs - pModElf->iFirstSect;
    12561496        return VINF_SUCCESS;
    12571497    }
     
    12691509    int rc = RTLDRELF_NAME(LinkAddressToSegOffset)(pMod, LinkAddress, &iSeg, &offSeg);
    12701510    if (RT_SUCCESS(rc))
    1271         *pRva = pModElf->paShdrs[iSeg + 1].sh_addr + offSeg;
     1511        *pRva = pModElf->paShdrs[iSeg + pModElf->iFirstSect].sh_addr + offSeg;
    12721512    return rc;
    12731513}
     
    12791519{
    12801520    PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
    1281     if (iSeg >= pModElf->Ehdr.e_shnum - 1U)
     1521    if (iSeg >= pModElf->Ehdr.e_shnum - pModElf->iFirstSect)
    12821522        return VERR_LDR_INVALID_SEG_OFFSET;
    12831523
    1284     iSeg++; /* skip section 0 */
     1524    iSeg += pModElf->iFirstSect; /* skip section 0 if not used */
    12851525    if (offSeg > pModElf->paShdrs[iSeg].sh_size)
    12861526    {
     
    13041544                                                       uint32_t *piSeg, PRTLDRADDR poffSeg)
    13051545{
    1306     PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
    1307 
     1546    PRTLDRMODELF    pModElf  = (PRTLDRMODELF)pMod;
    13081547    Elf_Addr        PrevAddr = 0;
    1309     unsigned        cLeft    = pModElf->Ehdr.e_shnum - 1;
    1310     const Elf_Shdr *pShdr    = &pModElf->paShdrs[cLeft];
     1548    unsigned        cLeft    = pModElf->Ehdr.e_shnum - pModElf->iFirstSect;
     1549    const Elf_Shdr *pShdr    = &pModElf->paShdrs[pModElf->Ehdr.e_shnum];
    13111550    while (cLeft-- > 0)
    13121551    {
     1552        pShdr--;
    13131553        if (pShdr->sh_flags & SHF_ALLOC)
    13141554        {
     
    13231563            PrevAddr = pShdr->sh_addr;
    13241564        }
    1325         pShdr--;
    13261565    }
    13271566
     
    14141653         */
    14151654        if (pThis->Ehdr.e_type == ET_REL)
    1416             rc = RTLDRELF_NAME(RelocateSection)(pThis, pThis->LinkAddress,
    1417                                                 RTLDRELF_NAME(GetImportStubCallback), NULL /*pvUser*/,
    1418                                                 pThis->paShdrs[iDbgInfo].sh_addr,
    1419                                                 pThis->paShdrs[iDbgInfo].sh_size,
    1420                                                 (const uint8_t *)pvBuf,
    1421                                                 (uint8_t *)pvBuf,
    1422                                                 pbRelocs,
    1423                                                 pThis->paShdrs[iRelocs].sh_size);
     1655            rc = RTLDRELF_NAME(RelocateSectionRel)(pThis, pThis->LinkAddress,
     1656                                                   RTLDRELF_NAME(GetImportStubCallback), NULL /*pvUser*/,
     1657                                                   pThis->paShdrs[iDbgInfo].sh_addr,
     1658                                                   pThis->paShdrs[iDbgInfo].sh_size,
     1659                                                   (const uint8_t *)pvBuf,
     1660                                                   (uint8_t *)pvBuf,
     1661                                                   pbRelocs,
     1662                                                   pThis->paShdrs[iRelocs].sh_size);
    14241663        else
    14251664            rc = RTLDRELF_NAME(RelocateSectionExecDyn)(pThis, pThis->LinkAddress,
     
    15621801 * @returns iprt status code.
    15631802 * @param   pEhdr       Pointer to the ELF header.
     1803 * @param   cbRawImage  The size of the raw image.
    15641804 * @param   pszLogName  The log name.
    1565  * @param   cbRawImage  The size of the raw image.
     1805 * @param   penmArch    Where to return the architecture.
     1806 * @param   pErrInfo    Where to return extended error info. Optional.
    15661807 */
    1567 static int RTLDRELF_NAME(ValidateElfHeader)(const Elf_Ehdr *pEhdr, const char *pszLogName, uint64_t cbRawImage,
    1568                                             PRTLDRARCH penmArch)
     1808static int RTLDRELF_NAME(ValidateElfHeader)(const Elf_Ehdr *pEhdr, uint64_t cbRawImage, const char *pszLogName,
     1809                                            PRTLDRARCH penmArch, PRTERRINFO pErrInfo)
    15691810{
    15701811    Log3(("RTLdrELF:     e_ident: %.*Rhxs\n"
     
    15881829        ||  pEhdr->e_ident[EI_MAG1] != ELFMAG1
    15891830        ||  pEhdr->e_ident[EI_MAG2] != ELFMAG2
    1590         ||  pEhdr->e_ident[EI_MAG3] != ELFMAG3
    1591        )
    1592     {
    1593         Log(("RTLdrELF: %s: Invalid ELF magic (%.*Rhxs)\n", pszLogName, sizeof(pEhdr->e_ident), pEhdr->e_ident)); NOREF(pszLogName);
    1594         return VERR_BAD_EXE_FORMAT;
    1595     }
     1831        ||  pEhdr->e_ident[EI_MAG3] != ELFMAG3)
     1832        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     1833                                   "%s: Invalid ELF magic (%.*Rhxs)", pszLogName, sizeof(pEhdr->e_ident), pEhdr->e_ident);
    15961834    if (pEhdr->e_ident[EI_CLASS] != RTLDRELF_SUFF(ELFCLASS))
    1597     {
    1598         Log(("RTLdrELF: %s: Invalid ELF class (%.*Rhxs)\n", pszLogName, sizeof(pEhdr->e_ident), pEhdr->e_ident));
    1599         return VERR_BAD_EXE_FORMAT;
    1600     }
     1835        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     1836                                   "%s: Invalid ELF class (%.*Rhxs)", pszLogName, sizeof(pEhdr->e_ident), pEhdr->e_ident);
    16011837    if (pEhdr->e_ident[EI_DATA] != ELFDATA2LSB)
    1602     {
    1603         Log(("RTLdrELF: %s: ELF endian %x is unsupported\n", pszLogName, pEhdr->e_ident[EI_DATA]));
    1604         return VERR_LDRELF_ODD_ENDIAN;
    1605     }
     1838        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_LDRELF_ODD_ENDIAN,
     1839                                   "%s: ELF endian %x is unsupported", pszLogName, pEhdr->e_ident[EI_DATA]);
    16061840    if (pEhdr->e_version != EV_CURRENT)
    1607     {
    1608         Log(("RTLdrELF: %s: ELF version %x is unsupported\n", pszLogName, pEhdr->e_version));
    1609         return VERR_LDRELF_VERSION;
    1610     }
     1841        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_LDRELF_VERSION,
     1842                                   "%s: ELF version %x is unsupported", pszLogName, pEhdr->e_version);
    16111843
    16121844    if (sizeof(Elf_Ehdr) != pEhdr->e_ehsize)
    1613     {
    1614         Log(("RTLdrELF: %s: Elf header e_ehsize is %d expected %d!\n",
    1615              pszLogName, pEhdr->e_ehsize, sizeof(Elf_Ehdr)));
    1616         return VERR_BAD_EXE_FORMAT;
    1617     }
     1845        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     1846                                   "%s: Elf header e_ehsize is %d expected %d!", pszLogName, pEhdr->e_ehsize, sizeof(Elf_Ehdr));
    16181847    if (    sizeof(Elf_Phdr) != pEhdr->e_phentsize
    1619         &&  (    pEhdr->e_phnum != 0
    1620              ||  pEhdr->e_type == ET_DYN))
    1621     {
    1622         Log(("RTLdrELF: %s: Elf header e_phentsize is %d expected %d!\n",
    1623              pszLogName, pEhdr->e_phentsize, sizeof(Elf_Phdr)));
    1624         return VERR_BAD_EXE_FORMAT;
    1625     }
     1848        &&  (   pEhdr->e_phnum != 0
     1849             || pEhdr->e_type == ET_DYN
     1850             || pEhdr->e_type == ET_EXEC))
     1851        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: Elf header e_phentsize is %d expected %d!",
     1852                                   pszLogName, pEhdr->e_phentsize, sizeof(Elf_Phdr));
    16261853    if (sizeof(Elf_Shdr) != pEhdr->e_shentsize)
    1627     {
    1628         Log(("RTLdrELF: %s: Elf header e_shentsize is %d expected %d!\n",
    1629              pszLogName, pEhdr->e_shentsize, sizeof(Elf_Shdr)));
    1630         return VERR_BAD_EXE_FORMAT;
    1631     }
     1854        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: Elf header e_shentsize is %d expected %d!",
     1855                                   pszLogName, pEhdr->e_shentsize, sizeof(Elf_Shdr));
    16321856
    16331857    switch (pEhdr->e_type)
     
    16381862            break;
    16391863        default:
    1640             Log(("RTLdrELF: %s: image type %#x is not supported!\n", pszLogName, pEhdr->e_type));
    1641             return VERR_BAD_EXE_FORMAT;
     1864            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: image type %#x is not supported!",
     1865                                       pszLogName, pEhdr->e_type);
    16421866    }
    16431867
     
    16551879#endif
    16561880        default:
    1657             Log(("RTLdrELF: %s: machine type %u is not supported!\n", pszLogName, pEhdr->e_machine));
    1658             return VERR_LDRELF_MACHINE;
     1881            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_LDRELF_MACHINE,
     1882                                       "%s: machine type %u is not supported!", pszLogName, pEhdr->e_machine);
    16591883    }
    16601884
     
    16621886        &&  !(pEhdr->e_phoff && pEhdr->e_phnum)
    16631887        &&  pEhdr->e_phnum)
    1664     {
    1665         Log(("RTLdrELF: %s: The program headers overlap with the ELF header! e_phoff=" FMT_ELF_OFF "\n",
    1666              pszLogName, pEhdr->e_phoff));
    1667         return VERR_BAD_EXE_FORMAT;
    1668     }
     1888        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     1889                                   "%s: The program headers overlap with the ELF header! e_phoff=" FMT_ELF_OFF,
     1890                                   pszLogName, pEhdr->e_phoff);
    16691891    if (    pEhdr->e_phoff + pEhdr->e_phnum * pEhdr->e_phentsize > cbRawImage
    16701892        ||  pEhdr->e_phoff + pEhdr->e_phnum * pEhdr->e_phentsize < pEhdr->e_phoff)
    1671     {
    1672         Log(("RTLdrELF: %s: The program headers extends beyond the file! e_phoff=" FMT_ELF_OFF " e_phnum=" FMT_ELF_HALF "\n",
    1673              pszLogName, pEhdr->e_phoff, pEhdr->e_phnum));
    1674         return VERR_BAD_EXE_FORMAT;
    1675     }
     1893        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     1894                                   "%s: The program headers extends beyond the file! e_phoff=" FMT_ELF_OFF " e_phnum=" FMT_ELF_HALF,
     1895                                   pszLogName, pEhdr->e_phoff, pEhdr->e_phnum);
    16761896
    16771897
    16781898    if (    pEhdr->e_shoff < pEhdr->e_ehsize
    16791899        &&  !(pEhdr->e_shoff && pEhdr->e_shnum))
    1680     {
    1681         Log(("RTLdrELF: %s: The section headers overlap with the ELF header! e_shoff=" FMT_ELF_OFF "\n",
    1682              pszLogName, pEhdr->e_shoff));
    1683         return VERR_BAD_EXE_FORMAT;
    1684     }
     1900        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     1901                                   "%s: The section headers overlap with the ELF header! e_shoff=" FMT_ELF_OFF,
     1902                                   pszLogName, pEhdr->e_shoff);
    16851903    if (    pEhdr->e_shoff + pEhdr->e_shnum * pEhdr->e_shentsize > cbRawImage
    16861904        ||  pEhdr->e_shoff + pEhdr->e_shnum * pEhdr->e_shentsize < pEhdr->e_shoff)
    1687     {
    1688         Log(("RTLdrELF: %s: The section headers extends beyond the file! e_shoff=" FMT_ELF_OFF " e_shnum=" FMT_ELF_HALF "\n",
    1689              pszLogName, pEhdr->e_shoff, pEhdr->e_shnum));
    1690         return VERR_BAD_EXE_FORMAT;
    1691     }
     1905        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     1906                                   "%s: The section headers extends beyond the file! e_shoff=" FMT_ELF_OFF " e_shnum=" FMT_ELF_HALF,
     1907                                   pszLogName, pEhdr->e_shoff, pEhdr->e_shnum);
    16921908
    16931909    if (pEhdr->e_shstrndx == 0 || pEhdr->e_shstrndx > pEhdr->e_shnum)
    1694     {
    1695         Log(("RTLdrELF: %s: The section headers string table is out of bounds! e_shstrndx=" FMT_ELF_HALF " e_shnum=" FMT_ELF_HALF "\n",
    1696              pszLogName, pEhdr->e_shstrndx, pEhdr->e_shnum));
    1697         return VERR_BAD_EXE_FORMAT;
    1698     }
     1910        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     1911                                   "%s: The section headers string table is out of bounds! e_shstrndx=" FMT_ELF_HALF " e_shnum=" FMT_ELF_HALF,
     1912                                   pszLogName, pEhdr->e_shstrndx, pEhdr->e_shnum);
    16991913
    17001914    return VINF_SUCCESS;
    17011915}
     1916
    17021917
    17031918/**
     
    17401955 * @param   iShdr       The index of section header which should be validated.
    17411956 *                      The section headers are found in the pModElf->paShdrs array.
     1957 * @param   cbRawImage  The size of the raw image.
    17421958 * @param   pszLogName  The log name.
    1743  * @param   cbRawImage  The size of the raw image.
     1959 * @param   pErrInfo    Where to return extended error info. Optional.
    17441960 */
    1745 static int RTLDRELF_NAME(ValidateSectionHeader)(PRTLDRMODELF pModElf, unsigned iShdr, const char *pszLogName, uint64_t cbRawImage)
     1961static int RTLDRELF_NAME(ValidateSectionHeader)(PRTLDRMODELF pModElf, unsigned iShdr, uint64_t cbRawImage,
     1962                                                const char *pszLogName, PRTERRINFO pErrInfo)
    17461963{
    17471964    const Elf_Shdr *pShdr = &pModElf->paShdrs[iShdr];
     
    17751992            || pShdr->sh_addralign  != 0
    17761993            || pShdr->sh_entsize    != 0 )
    1777         {
    1778             Log(("RTLdrELF: %s: Bad #0 section: %.*Rhxs\n", pszLogName, sizeof(*pShdr), pShdr ));
    1779             return VERR_BAD_EXE_FORMAT;
    1780         }
     1994            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     1995                                       "%s: Bad #0 section: %.*Rhxs", pszLogName, sizeof(*pShdr), pShdr);
    17811996        return VINF_SUCCESS;
    17821997    }
    17831998
    17841999    if (pShdr->sh_name >= pModElf->cbShStr)
    1785     {
    1786         Log(("RTLdrELF: %s: Shdr #%d: sh_name (%d) is beyond the end of the section header string table (%d)!\n",
    1787              pszLogName, iShdr, pShdr->sh_name, pModElf->cbShStr)); NOREF(pszLogName);
    1788         return VERR_BAD_EXE_FORMAT;
    1789     }
     2000        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     2001                                   "%s: Shdr #%d: sh_name (%d) is beyond the end of the section header string table (%d)!",
     2002                                   pszLogName, iShdr, pShdr->sh_name, pModElf->cbShStr);
    17902003
    17912004    if (pShdr->sh_link >= pModElf->Ehdr.e_shnum)
    1792     {
    1793         Log(("RTLdrELF: %s: Shdr #%d: sh_link (%d) is beyond the end of the section table (%d)!\n",
    1794              pszLogName, iShdr, pShdr->sh_link, pModElf->Ehdr.e_shnum)); NOREF(pszLogName);
    1795         return VERR_BAD_EXE_FORMAT;
    1796     }
     2005        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     2006                                   "%s: Shdr #%d: sh_link (%d) is beyond the end of the section table (%d)!",
     2007                                   pszLogName, iShdr, pShdr->sh_link, pModElf->Ehdr.e_shnum);
    17972008
    17982009    switch (pShdr->sh_type)
     
    18012012        case 12301230:
    18022013            if (pShdr->sh_info >= pModElf->Ehdr.e_shnum)
    1803             {
    1804                 Log(("RTLdrELF: %s: Shdr #%d: sh_info (%d) is beyond the end of the section table (%d)!\n",
    1805                      pszLogName, iShdr, pShdr->sh_link, pModElf->Ehdr.e_shnum));
    1806                 return VERR_BAD_EXE_FORMAT;
    1807             }
     2014                return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     2015                                           "%s: Shdr #%d: sh_info (%d) is beyond the end of the section table (%d)!",
     2016                                           pszLogName, iShdr, pShdr->sh_link, pModElf->Ehdr.e_shnum);
    18082017            break;
    18092018
     
    18392048        if (    offEnd > cbRawImage
    18402049            ||  offEnd < (uint64_t)pShdr->sh_offset)
    1841         {
    1842             Log(("RTLdrELF: %s: Shdr #%d: sh_offset (" FMT_ELF_OFF ") + sh_size (" FMT_ELF_XWORD " = %RX64) is beyond the end of the file (%RX64)!\n",
    1843                  pszLogName, iShdr, pShdr->sh_offset, pShdr->sh_size, offEnd, cbRawImage));
    1844             return VERR_BAD_EXE_FORMAT;
    1845         }
     2050            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     2051                                       "%s: Shdr #%d: sh_offset (" FMT_ELF_OFF ") + sh_size (" FMT_ELF_XWORD " = %RX64) is beyond the end of the file (%RX64)!",
     2052                                       pszLogName, iShdr, pShdr->sh_offset, pShdr->sh_size, offEnd, cbRawImage);
    18462053        if (pShdr->sh_offset < sizeof(Elf_Ehdr))
    1847         {
    1848             Log(("RTLdrELF: %s: Shdr #%d: sh_offset (" FMT_ELF_OFF ") + sh_size (" FMT_ELF_XWORD ") is starting in the ELF header!\n",
    1849                  pszLogName, iShdr, pShdr->sh_offset, pShdr->sh_size));
    1850             return VERR_BAD_EXE_FORMAT;
    1851         }
    1852     }
     2054            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     2055                                       "%s: Shdr #%d: sh_offset (" FMT_ELF_OFF ") + sh_size (" FMT_ELF_XWORD ") is starting in the ELF header!",
     2056                                       pszLogName, iShdr, pShdr->sh_offset, pShdr->sh_size);
     2057    }
     2058
     2059    return VINF_SUCCESS;
     2060}
     2061
     2062
     2063/**
     2064 * Process the section headers.
     2065 *
     2066 * @returns iprt status code.
     2067 * @param   pModElf     Pointer to the module structure.
     2068 * @param   paShdrs     The section headers.
     2069 * @param   cbRawImage  The size of the raw image.
     2070 * @param   pszLogName  The log name.
     2071 * @param   pErrInfo    Where to return extended error info. Optional.
     2072 */
     2073static int RTLDRELF_NAME(ValidateAndProcessSectionHeaders)(PRTLDRMODELF pModElf, Elf_Shdr *paShdrs, uint64_t cbRawImage,
     2074                                                           const char *pszLogName, PRTERRINFO pErrInfo)
     2075{
     2076    Elf_Addr uNextAddr = 0;
     2077    for (unsigned i = 0; i < pModElf->Ehdr.e_shnum; i++)
     2078    {
     2079        int rc = RTLDRELF_NAME(ValidateSectionHeader)(pModElf, i, cbRawImage, pszLogName, pErrInfo);
     2080        if (RT_FAILURE(rc))
     2081            return rc;
     2082
     2083        /*
     2084         * We're looking for symbol tables.
     2085         */
     2086        if (paShdrs[i].sh_type == SHT_SYMTAB)
     2087        {
     2088            if (pModElf->Rel.iSymSh != ~0U)
     2089                return RTERRINFO_LOG_SET_F(pErrInfo, VERR_LDRELF_MULTIPLE_SYMTABS,
     2090                                           "%s: Multiple symbol tabs! iSymSh=%d i=%d", pszLogName, pModElf->Rel.iSymSh, i);
     2091            pModElf->Rel.iSymSh = i;
     2092            pModElf->Rel.cSyms  = (unsigned)(paShdrs[i].sh_size / sizeof(Elf_Sym));
     2093            AssertBreakStmt(pModElf->Rel.cSyms == paShdrs[i].sh_size / sizeof(Elf_Sym), rc = VERR_IMAGE_TOO_BIG);
     2094            pModElf->Rel.iStrSh = paShdrs[i].sh_link;
     2095            pModElf->Rel.cbStr  = (unsigned)paShdrs[pModElf->Rel.iStrSh].sh_size;
     2096            AssertBreakStmt(pModElf->Rel.cbStr == paShdrs[pModElf->Rel.iStrSh].sh_size, rc = VERR_IMAGE_TOO_BIG);
     2097        }
     2098        else if (paShdrs[i].sh_type == SHT_DYNSYM)
     2099        {
     2100            if (pModElf->Dyn.iSymSh != ~0U)
     2101                return RTERRINFO_LOG_SET_F(pErrInfo, VERR_LDRELF_MULTIPLE_SYMTABS,
     2102                                           "%s: Multiple dynamic symbol tabs! iSymSh=%d i=%d", pszLogName, pModElf->Dyn.iSymSh, i);
     2103            if (pModElf->Ehdr.e_type != ET_DYN && pModElf->Ehdr.e_type != ET_EXEC)
     2104                return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     2105                                           "%s: Unexpected SHT_DYNSYM (i=%d) for e_type=%d", pszLogName, i, pModElf->Ehdr.e_type);
     2106            pModElf->Dyn.iSymSh = i;
     2107            pModElf->Dyn.cSyms  = (unsigned)(paShdrs[i].sh_size / sizeof(Elf_Sym));
     2108            AssertBreakStmt(pModElf->Dyn.cSyms == paShdrs[i].sh_size / sizeof(Elf_Sym), rc = VERR_IMAGE_TOO_BIG);
     2109            pModElf->Dyn.iStrSh = paShdrs[i].sh_link;
     2110            pModElf->Dyn.cbStr  = (unsigned)paShdrs[pModElf->Dyn.iStrSh].sh_size;
     2111            AssertBreakStmt(pModElf->Dyn.cbStr == paShdrs[pModElf->Dyn.iStrSh].sh_size, rc = VERR_IMAGE_TOO_BIG);
     2112        }
     2113        /*
     2114         * We're also look for the dynamic section.
     2115         */
     2116        else if (paShdrs[i].sh_type == SHT_DYNAMIC)
     2117        {
     2118            if (pModElf->iShDynamic != ~0U)
     2119                return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     2120                                           "%s: Multiple dynamic sections! iShDynamic=%d i=%d",
     2121                                           pszLogName, pModElf->iShDynamic, i);
     2122            if (pModElf->Ehdr.e_type != ET_DYN && pModElf->Ehdr.e_type != ET_EXEC)
     2123                return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     2124                                           "Unexpected SHT_DYNAMIC (i=%d) for e_type=%d", pszLogName, i, pModElf->Ehdr.e_type);
     2125            if (paShdrs[i].sh_entsize != sizeof(Elf_Dyn))
     2126                return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     2127                                           "%s: SHT_DYNAMIC (i=%d) sh_entsize=" FMT_ELF_XWORD ",  expected %#zx",
     2128                                           pszLogName, i, paShdrs[i].sh_entsize, sizeof(Elf_Dyn));
     2129            pModElf->iShDynamic = i;
     2130            Elf_Xword const cDynamic = paShdrs[i].sh_size / sizeof(Elf_Dyn);
     2131            if (cDynamic > _64K || cDynamic < 2)
     2132                return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     2133                                           "%s: SHT_DYNAMIC (i=%d) sh_size=" FMT_ELF_XWORD " is out of range, expected %u",
     2134                                           pszLogName, i, paShdrs[i].sh_size);
     2135            pModElf->cDynamic = (unsigned)cDynamic;
     2136        }
     2137
     2138        /*
     2139         * Special checks for the section string table.
     2140         */
     2141        if (i == pModElf->Ehdr.e_shstrndx)
     2142        {
     2143            if (paShdrs[i].sh_type != SHT_STRTAB)
     2144                return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     2145                                           "%s: Section header string table is not a SHT_STRTAB: %#x",
     2146                                           pszLogName, paShdrs[i].sh_type);
     2147            if (paShdrs[i].sh_size == 0)
     2148                return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: Section header string table is empty", pszLogName);
     2149        }
     2150
     2151        /*
     2152         * Kluge for the .data..percpu segment in 64-bit linux kernels.
     2153         */
     2154        if (paShdrs[i].sh_flags & SHF_ALLOC)
     2155        {
     2156            if (   paShdrs[i].sh_addr == 0
     2157                && paShdrs[i].sh_addr < uNextAddr)
     2158            {
     2159                Elf_Addr uAddr = RT_ALIGN_T(uNextAddr, paShdrs[i].sh_addralign, Elf_Addr);
     2160                Log(("RTLdrElf: Out of order section #%d; adjusting sh_addr from " FMT_ELF_ADDR " to " FMT_ELF_ADDR "\n",
     2161                     i, paShdrs[i].sh_addr, uAddr));
     2162                paShdrs[i].sh_addr = uAddr;
     2163            }
     2164            uNextAddr = paShdrs[i].sh_addr + paShdrs[i].sh_size;
     2165        }
     2166    } /* for each section header */
     2167
     2168    return VINF_SUCCESS;
     2169}
     2170
     2171
     2172/**
     2173 * Process the section headers.
     2174 *
     2175 * @returns iprt status code.
     2176 * @param   pModElf     Pointer to the module structure.
     2177 * @param   paShdrs     The section headers.
     2178 * @param   cbRawImage  The size of the raw image.
     2179 * @param   pszLogName  The log name.
     2180 * @param   pErrInfo    Where to return extended error info. Optional.
     2181 */
     2182static int RTLDRELF_NAME(ValidateAndProcessDynamicInfo)(PRTLDRMODELF pModElf, uint64_t cbRawImage, uint32_t fFlags,
     2183                                                        const char *pszLogName, PRTERRINFO pErrInfo)
     2184{
     2185    /*
     2186     * Check preconditions.
     2187     */
     2188    AssertReturn(pModElf->Ehdr.e_type == ET_DYN || pModElf->Ehdr.e_type == ET_EXEC, VERR_INTERNAL_ERROR_2);
     2189    if (pModElf->Ehdr.e_phnum <= 1 || pModElf->Ehdr.e_phnum >= _32K)
     2190        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     2191                                   "%s: e_phnum=%u is out of bounds (2..32K)", pszLogName, pModElf->Ehdr.e_phnum);
     2192    if (pModElf->iShDynamic == ~0U)
     2193        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: no .dynamic section", pszLogName);
     2194    AssertReturn(pModElf->cDynamic > 1 && pModElf->cDynamic <= _64K, VERR_INTERNAL_ERROR_3);
     2195
     2196    /* ASSUME that the sections are ordered by address.  That simplifies
     2197       validation code further down. */
     2198    AssertReturn(pModElf->Ehdr.e_shnum >= 2, VERR_INTERNAL_ERROR_4);
     2199    Elf_Shdr const *paShdrs  = pModElf->paShdrs;
     2200    Elf_Addr        uPrevEnd = paShdrs[1].sh_addr + paShdrs[1].sh_size;
     2201    for (unsigned i = 2; i < pModElf->Ehdr.e_shnum; i++)
     2202        if (paShdrs[i].sh_flags & SHF_ALLOC)
     2203        {
     2204            if (uPrevEnd > paShdrs[i].sh_addr)
     2205                return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     2206                                           "%s: section %u is out of order: uPrevEnd=" FMT_ELF_ADDR " sh_addr=" FMT_ELF_ADDR,
     2207                                           pszLogName, i, uPrevEnd, paShdrs[i].sh_addr);
     2208            uPrevEnd = paShdrs[i].sh_addr + paShdrs[i].sh_size;
     2209        }
     2210
     2211    /* Must have string and symbol tables. */
     2212    if (pModElf->Dyn.iStrSh == ~0U)
     2213        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: No dynamic string table section", pszLogName);
     2214    if (pModElf->Dyn.iSymSh == ~0U)
     2215        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: No dynamic symbol table section", pszLogName);
     2216
     2217    /*
     2218     * Load the program headers.
     2219     */
     2220    size_t const cbPhdrs = sizeof(pModElf->paPhdrs[0]) * pModElf->Ehdr.e_phnum;
     2221    Elf_Phdr    *paPhdrs = (Elf_Phdr *)RTMemAllocZ(cbPhdrs);
     2222    pModElf->paPhdrs = paPhdrs;
     2223    AssertReturn(paPhdrs, VERR_NO_MEMORY);
     2224
     2225    int rc = pModElf->Core.pReader->pfnRead(pModElf->Core.pReader, paPhdrs, cbPhdrs, pModElf->Ehdr.e_phoff);
     2226    if (RT_FAILURE(rc))
     2227        return RTERRINFO_LOG_SET_F(pErrInfo, rc, "%s: pfnRead(,,%#zx, " FMT_ELF_OFF ") -> %Rrc",
     2228                                   pszLogName, cbPhdrs, pModElf->Ehdr.e_phoff, rc);
     2229
     2230    /*
     2231     * Validate them.
     2232     */
     2233    unsigned cbPage = _4K; /** @todo generalize architecture specific stuff using its own code template header.  */
     2234    switch (pModElf->Core.enmArch)
     2235    {
     2236        case RTLDRARCH_AMD64:
     2237        case RTLDRARCH_X86_32:
     2238            break;
     2239        default:
     2240            AssertFailedBreak(/** @todo page size for got.plt hacks */);
     2241    }
     2242    unsigned iLoad          = 0;
     2243    unsigned iLoadShdr      = 1; /* ASSUMES ordered (checked above). */
     2244    unsigned cDynamic       = 0;
     2245    Elf_Addr cbImage        = 0;
     2246    Elf_Addr uLinkAddress   = ~(Elf_Addr)0;
     2247    for (unsigned i = 0; i < pModElf->Ehdr.e_phnum; i++)
     2248    {
     2249        const Elf_Phdr * const pPhdr = &paPhdrs[i];
     2250        Log3(("RTLdrELF: Program Header #%d:\n"
     2251              "RTLdrELF:   p_type: " FMT_ELF_WORD " (%s)\n"
     2252              "RTLdrELF:  p_flags: " FMT_ELF_WORD "\n"
     2253              "RTLdrELF: p_offset: " FMT_ELF_OFF "\n"
     2254              "RTLdrELF:  p_vaddr: " FMT_ELF_ADDR "\n"
     2255              "RTLdrELF:  p_paddr: " FMT_ELF_ADDR "\n"
     2256              "RTLdrELF: p_filesz: " FMT_ELF_XWORD "\n"
     2257              "RTLdrELF:  p_memsz: " FMT_ELF_XWORD "\n"
     2258              "RTLdrELF:  p_align: " FMT_ELF_XWORD "\n",
     2259              i,
     2260              pPhdr->p_type, rtldrElfGetPhdrType(pPhdr->p_type), pPhdr->p_flags, pPhdr->p_offset,
     2261              pPhdr->p_vaddr, pPhdr->p_paddr, pPhdr->p_filesz, pPhdr->p_memsz, pPhdr->p_align));
     2262
     2263        if (pPhdr->p_type == DT_NULL)
     2264            continue;
     2265
     2266        if (   pPhdr->p_filesz != 0
     2267            && (   pPhdr->p_offset >= cbRawImage
     2268                || pPhdr->p_filesz > cbRawImage
     2269                || pPhdr->p_offset + pPhdr->p_filesz > cbRawImage))
     2270            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     2271                                       "%s: Prog Hdr #%u: bogus p_offset=" FMT_ELF_OFF " & p_filesz=" FMT_ELF_XWORD " (file size %#RX64)",
     2272                                       pszLogName, i, pPhdr->p_offset, pPhdr->p_filesz, cbRawImage);
     2273
     2274        if (pPhdr->p_flags & ~(Elf64_Word)(PF_X | PF_R | PF_W))
     2275            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: Prog Hdr #%u: bogus p_flags=" FMT_ELF_WORD,
     2276                                       pszLogName, i, pPhdr->p_flags);
     2277
     2278        if (!RT_IS_POWER_OF_TWO(pPhdr->p_align))
     2279            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: Prog Hdr #%u: bogus p_align=" FMT_ELF_XWORD,
     2280                                       pszLogName, i, pPhdr->p_align);
     2281
     2282        if (   pPhdr->p_align  > 1
     2283            && pPhdr->p_memsz  > 0
     2284            && pPhdr->p_filesz > 0
     2285            && (pPhdr->p_offset & (pPhdr->p_align - 1)) != (pPhdr->p_vaddr & (pPhdr->p_align - 1)))
     2286            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     2287                                       "%s: Prog Hdr #%u: misaligned p_offset=" FMT_ELF_OFF " p_vaddr=" FMT_ELF_ADDR " p_align=" FMT_ELF_XWORD,
     2288                                       pszLogName, i, pPhdr->p_offset, pPhdr->p_vaddr, pPhdr->p_align);
     2289
     2290        /* Do some type specfic checks: */
     2291        switch (pPhdr->p_type)
     2292        {
     2293            case PT_LOAD:
     2294            {
     2295                if (pPhdr->p_memsz < pPhdr->p_filesz)
     2296                    return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     2297                                               "%s: Prog Hdr #%u/LOAD#%u: bogus p_memsz=" FMT_ELF_XWORD " or p_filesz=" FMT_ELF_XWORD,
     2298                                               pszLogName, i, iLoad, pPhdr->p_memsz, pPhdr->p_filesz);
     2299                cbImage = pPhdr->p_vaddr + pPhdr->p_memsz;
     2300                if (iLoad == 0)
     2301                    uLinkAddress = pPhdr->p_vaddr;
     2302
     2303                /* Find the corresponding sections, checking their addresses and
     2304                   file offsets since the rest of the code is still section based
     2305                   rather than using program headers as it should... */
     2306                Elf_Off         off     = pPhdr->p_offset;
     2307                Elf_Addr        uAddr   = pPhdr->p_vaddr;
     2308                Elf_Xword       cbMem   = pPhdr->p_memsz;
     2309                Elf_Xword       cbFile  = pPhdr->p_filesz;
     2310                while (cbMem > 0)
     2311                {
     2312                    if (iLoadShdr < pModElf->Ehdr.e_shnum)
     2313                    { /* likely */ }
     2314                    else if (iLoadShdr == pModElf->Ehdr.e_shnum)
     2315                    {
     2316                        /** @todo anything else to check here? */
     2317                        iLoadShdr++;
     2318                        break;
     2319                    }
     2320                    else
     2321                        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     2322                                                   "%s: Prog Hdr #%u/LOAD#%u: Out of sections at " FMT_ELF_ADDR " LB " FMT_ELF_XWORD,
     2323                                                   pszLogName, i, iLoad, uAddr, cbMem);
     2324                    if (!(paShdrs[iLoadShdr].sh_flags & SHF_ALLOC))
     2325                    {
     2326                        if (   paShdrs[iLoadShdr].sh_type != SHT_NOBITS
     2327                            && paShdrs[iLoadShdr].sh_size > 0
     2328                            && off < paShdrs[iLoadShdr].sh_offset + paShdrs[iLoadShdr].sh_size
     2329                            && paShdrs[iLoadShdr].sh_offset < off + cbMem)
     2330                            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     2331                                                       "%s: Prog Hdr #%u/LOAD#%u: Overlaps with !SHF_ALLOC section at " FMT_ELF_OFF " LB " FMT_ELF_XWORD,
     2332                                                       pszLogName, i, iLoad, paShdrs[iLoadShdr].sh_offset, paShdrs[iLoadShdr].sh_size);
     2333                        pModElf->paShdrExtras[iLoadShdr].idxPhdr = UINT16_MAX;
     2334                        iLoadShdr++;
     2335                        continue;
     2336                    }
     2337
     2338                    if (uAddr != paShdrs[iLoadShdr].sh_addr)
     2339                    {
     2340                        /* Before the first section we expect headers to be loaded, so
     2341                           that the file is simply mapped from file offset zero. */
     2342                        if (   iLoadShdr == 1
     2343                            && iLoad     == 0
     2344                            && paShdrs[1].sh_addr == paShdrs[1].sh_offset
     2345                            && cbFile    >= paShdrs[1].sh_offset
     2346                            && cbMem     >= paShdrs[1].sh_offset)
     2347                        {
     2348                            /* Modify paShdrs[0] to describe the gap. ".elf.headers" */
     2349                            pModElf->iFirstSect              = 0;
     2350                            pModElf->paShdrs[0].sh_name      = 0;
     2351                            pModElf->paShdrs[0].sh_type      = SHT_PROGBITS;
     2352                            pModElf->paShdrs[0].sh_flags     = SHF_ALLOC
     2353                                                             | (pPhdr->p_flags & PF_W ? SHF_WRITE     : 0)
     2354                                                             | (pPhdr->p_flags & PF_X ? SHF_EXECINSTR : 0);
     2355                            pModElf->paShdrs[0].sh_addr      = uAddr;
     2356                            pModElf->paShdrs[0].sh_offset    = off;
     2357                            pModElf->paShdrs[0].sh_size      = paShdrs[1].sh_offset;
     2358                            pModElf->paShdrs[0].sh_link      = 0;
     2359                            pModElf->paShdrs[0].sh_info      = 0;
     2360                            pModElf->paShdrs[0].sh_addralign = pPhdr->p_align;
     2361                            pModElf->paShdrs[0].sh_entsize   = 0;
     2362                            *(Elf_Shdr *)pModElf->paOrgShdrs = pModElf->paShdrs[0]; /* (necessary for segment enumeration) */
     2363
     2364                            uAddr  += paShdrs[1].sh_offset;
     2365                            cbMem  -= paShdrs[1].sh_offset;
     2366                            cbFile -= paShdrs[1].sh_offset;
     2367                            off     = paShdrs[1].sh_offset;
     2368                        }
     2369                        /* Alignment padding?  Allow up to a page size. */
     2370                        else if (   paShdrs[iLoadShdr].sh_addr > uAddr
     2371                                 &&   paShdrs[iLoadShdr].sh_addr - uAddr
     2372                                    < RT_MAX(paShdrs[iLoadShdr].sh_addralign, cbPage /*got.plt hack*/))
     2373                        {
     2374                            Elf_Xword cbAlignPadding = paShdrs[iLoadShdr].sh_addr - uAddr;
     2375                            if (cbAlignPadding >= cbMem)
     2376                                break;
     2377                            cbMem -= cbAlignPadding;
     2378                            uAddr += cbAlignPadding;
     2379                            if (cbFile > cbAlignPadding)
     2380                            {
     2381                                off    += cbAlignPadding;
     2382                                cbFile -= cbAlignPadding;
     2383                            }
     2384                            else
     2385                            {
     2386                                off   += cbFile;
     2387                                cbFile = 0;
     2388                            }
     2389                        }
     2390                    }
     2391
     2392                    if (   uAddr == paShdrs[iLoadShdr].sh_addr
     2393                        && cbMem >= paShdrs[iLoadShdr].sh_size
     2394                        && (  paShdrs[iLoadShdr].sh_type != SHT_NOBITS
     2395                            ?    off    == paShdrs[iLoadShdr].sh_offset
     2396                              && cbFile >= paShdrs[iLoadShdr].sh_size /* this might be too strict... */
     2397                            : cbFile == 0) )
     2398                    {
     2399                        if (paShdrs[iLoadShdr].sh_type != SHT_NOBITS)
     2400                        {
     2401                            off    += paShdrs[iLoadShdr].sh_size;
     2402                            cbFile -= paShdrs[iLoadShdr].sh_size;
     2403                        }
     2404                        uAddr += paShdrs[iLoadShdr].sh_size;
     2405                        cbMem -= paShdrs[iLoadShdr].sh_size;
     2406                    }
     2407                    else
     2408                        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     2409                                                   "%s: Prog Hdr #%u/LOAD#%u: Mismatch at " FMT_ELF_ADDR " LB " FMT_ELF_XWORD " (file " FMT_ELF_OFF " LB " FMT_ELF_XWORD ") with section #%u " FMT_ELF_ADDR " LB " FMT_ELF_XWORD " (file " FMT_ELF_OFF " sh_type=" FMT_ELF_WORD ")",
     2410                                                   pszLogName, i, iLoad, uAddr, cbMem, off, cbFile,
     2411                                                   iLoadShdr, paShdrs[iLoadShdr].sh_addr, paShdrs[iLoadShdr].sh_size,
     2412                                                   paShdrs[iLoadShdr].sh_offset, paShdrs[iLoadShdr].sh_type);
     2413
     2414                    pModElf->paShdrExtras[iLoadShdr].idxPhdr = iLoad;
     2415                    iLoadShdr++;
     2416                } /* section loop */
     2417
     2418                iLoad++;
     2419                break;
     2420            }
     2421
     2422            case PT_DYNAMIC:
     2423            {
     2424                const Elf_Shdr *pShdr = &pModElf->paShdrs[pModElf->iShDynamic];
     2425                if (pPhdr->p_offset != pShdr->sh_offset)
     2426                    return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     2427                                               "%s: Prog Hdr #%u/DYNAMIC: p_offset=" FMT_ELF_OFF " expected " FMT_ELF_OFF,
     2428                                               pszLogName, i, pPhdr->p_offset, pShdr->sh_offset);
     2429                if (RT_MAX(pPhdr->p_memsz, pPhdr->p_filesz) != pShdr->sh_size)
     2430                    return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     2431                                               "%s: Prog Hdr #%u/DYNAMIC: expected " FMT_ELF_XWORD " for RT_MAX(p_memsz=" FMT_ELF_XWORD ", p_filesz=" FMT_ELF_XWORD ")",
     2432                                               pszLogName, i, pShdr->sh_size, pPhdr->p_memsz, pPhdr->p_filesz);
     2433                cDynamic++;
     2434                break;
     2435            }
     2436        }
     2437    }
     2438
     2439    if (iLoad == 0)
     2440        return RTERRINFO_LOG_SET_F(pErrInfo, rc, "%s: No PT_LOAD program headers", pszLogName);
     2441    if (cDynamic != 1)
     2442        return RTERRINFO_LOG_SET_F(pErrInfo, rc, "%s: No program header for the DYNAMIC section", pszLogName);
     2443
     2444    cbImage -= uLinkAddress;
     2445    pModElf->cbImage     = (uint64_t)cbImage;
     2446    pModElf->LinkAddress = uLinkAddress;
     2447    AssertReturn(pModElf->cbImage == cbImage, VERR_INTERNAL_ERROR_5);
     2448    Log3(("RTLdrELF: LinkAddress=" FMT_ELF_ADDR " cbImage=" FMT_ELF_ADDR " (from PT_LOAD)\n", uLinkAddress, cbImage));
     2449
     2450    for (; iLoadShdr < pModElf->Ehdr.e_shnum; iLoadShdr++)
     2451        if (   !(paShdrs[iLoadShdr].sh_flags & SHF_ALLOC)
     2452            || paShdrs[iLoadShdr].sh_size == 0)
     2453            pModElf->paShdrExtras[iLoadShdr].idxPhdr = UINT16_MAX;
     2454        else
     2455            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     2456                                       "%s: No PT_LOAD for section #%u " FMT_ELF_ADDR " LB " FMT_ELF_XWORD " (file " FMT_ELF_OFF " sh_type=" FMT_ELF_WORD ")",
     2457                                       pszLogName, iLoadShdr, paShdrs[iLoadShdr].sh_addr, paShdrs[iLoadShdr].sh_size,
     2458                                       paShdrs[iLoadShdr].sh_offset, paShdrs[iLoadShdr].sh_type);
     2459
     2460    /*
     2461     * Load and validate the dynamic table.  We have got / will get most of the
     2462     * info we need from the section table, so we must make sure this matches up.
     2463     */
     2464    Log3(("RTLdrELF: Dynamic section - %u entries\n", pModElf->cDynamic));
     2465    size_t const    cbDynamic = pModElf->cDynamic * sizeof(pModElf->paDynamic[0]);
     2466    Elf_Dyn * const paDynamic = (Elf_Dyn *)RTMemAlloc(cbDynamic);
     2467    AssertReturn(paDynamic, VERR_NO_MEMORY);
     2468    pModElf->paDynamic = paDynamic;
     2469
     2470    rc = pModElf->Core.pReader->pfnRead(pModElf->Core.pReader, paDynamic, cbDynamic, paShdrs[pModElf->iShDynamic].sh_offset);
     2471    if (RT_FAILURE(rc))
     2472        return RTERRINFO_LOG_SET_F(pErrInfo, rc, "%s: pfnRead(,,%#zx, " FMT_ELF_OFF ") -> %Rrc",
     2473                                   pszLogName, cbDynamic, paShdrs[pModElf->iShDynamic].sh_offset, rc);
     2474
     2475    for (uint32_t i = 0; i < pModElf->cDynamic; i++)
     2476    {
     2477#define LOG_VALIDATE_PTR_RET(szName) do { \
     2478            Log3(("RTLdrELF: DT[%u]: %16s " FMT_ELF_ADDR "\n", i, szName, paDynamic[i].d_un.d_ptr)); \
     2479            if ((uint64_t)paDynamic[i].d_un.d_ptr - uLinkAddress < cbImage) { /* likely */ } \
     2480            else return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT[%u]/" szName ": Invalid address " FMT_ELF_ADDR " (valid range: " FMT_ELF_ADDR " LB " FMT_ELF_ADDR ")", \
     2481                                            pszLogName, i, paDynamic[i].d_un.d_ptr, uLinkAddress, cbImage); \
     2482        } while (0)
     2483#define LOG_VALIDATE_PTR_VAL_RET(szName, uExpected) do { \
     2484            Log3(("RTLdrELF: DT[%u]: %16s " FMT_ELF_ADDR "\n", i, szName, (uint64_t)paDynamic[i].d_un.d_ptr)); \
     2485            if (paDynamic[i].d_un.d_ptr == (Elf_Addr)(uExpected)) { /* likely */ } \
     2486            else return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT[%u]/" szName ": " FMT_ELF_ADDR ", expected " FMT_ELF_ADDR, \
     2487                                            pszLogName, i, paDynamic[i].d_un.d_ptr, (Elf_Addr)(uExpected)); \
     2488        } while (0)
     2489#define LOG_VALIDATE_STR_RET(szName) do { \
     2490            Log3(("RTLdrELF: DT[%u]: %16s %#RX64\n", i, szName, (uint64_t)paDynamic[i].d_un.d_val)); \
     2491            if ((uint64_t)paDynamic[i].d_un.d_val < pModElf->Dyn.cbStr) { /* likely */ } \
     2492            else return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT[%u]/" szName ": Invalid string table offset %#RX64 (max %#x)", \
     2493                                            pszLogName, i, (uint64_t)paDynamic[i].d_un.d_val, pModElf->Dyn.cbStr); \
     2494        } while (0)
     2495#define LOG_VALIDATE_VAL_RET(szName, uExpected) do { \
     2496            Log3(("RTLdrELF: DT[%u]: %16s %#RX64\n", i, szName, (uint64_t)paDynamic[i].d_un.d_val)); \
     2497            if ((uint64_t)paDynamic[i].d_un.d_val == (uint64_t)(uExpected)) { /* likely */ } \
     2498            else return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT[%u]/" szName ": %#RX64, expected %#RX64", \
     2499                                            pszLogName, i, (uint64_t)paDynamic[i].d_un.d_val, (uint64_t)(uExpected)); \
     2500        } while (0)
     2501#define SET_RELOC_TYPE_RET(a_szName, a_uType) do { \
     2502            if (pModElf->DynInfo.uRelocType == 0 || pModElf->DynInfo.uRelocType == (a_uType)) \
     2503                pModElf->DynInfo.uRelocType = (a_uType); \
     2504            else return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT[%u]/" a_szName ": Mixing DT_RELA and DT_REL", pszLogName, i); \
     2505        } while (0)
     2506#define SET_INFO_FIELD_RET(a_szName, a_Field, a_Value, a_UnsetValue, a_szFmt) do { \
     2507            if ((a_Field) == (a_UnsetValue) && (a_Value) != (a_UnsetValue)) \
     2508                (a_Field) = (a_Value); /* likely */ \
     2509            else if ((a_Field) != (a_UnsetValue)) \
     2510                return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT[%u]/" a_szName ": Multiple entries (first value " a_szFmt ", second " a_szFmt ")", pszLogName, i, (a_Field), (a_Value)); \
     2511            else if ((a_Value) != (a_UnsetValue)) \
     2512                return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT[%u]/" a_szName ": Unexpected value " a_szFmt, pszLogName, i, (a_Value)); \
     2513        } while (0)
     2514#define FIND_MATCHING_SECTION_RET(a_szName, a_ExtraMatchExpr, a_idxShFieldToSet) do { \
     2515            unsigned iSh; \
     2516            for (iSh = 1; iSh < pModElf->Ehdr.e_shnum; iSh++) \
     2517                if (   paShdrs[iSh].sh_addr == paDynamic[i].d_un.d_ptr \
     2518                    && (a_ExtraMatchExpr)) \
     2519                { \
     2520                    (a_idxShFieldToSet) = iSh; \
     2521                    if (pModElf->paShdrExtras[iSh].idxDt != UINT16_MAX) \
     2522                        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, \
     2523                                                   "%s: DT[%u]/" a_szName ": section #%u (" FMT_ELF_ADDR ") already referenced by DT[%u]", \
     2524                                                   pszLogName, i, iSh, paShdrs[iSh].sh_addr, pModElf->paShdrExtras[iSh].idxDt); \
     2525                    pModElf->paShdrExtras[iSh].idxDt  = i; \
     2526                    pModElf->paShdrExtras[iSh].uDtTag = (uint32_t)paDynamic[i].d_tag; \
     2527                    break; \
     2528                } \
     2529            if (iSh < pModElf->Ehdr.e_shnum) { /* likely */ } \
     2530            else return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT[%u]/" a_szName ": No matching section for " FMT_ELF_ADDR, pszLogName, i, paDynamic[i].d_un.d_ptr); \
     2531        } while (0)
     2532#define ONLY_FOR_DEBUG_OR_VALIDATION_RET(a_szName) do { \
     2533            if (fFlags & (RTLDR_O_FOR_DEBUG | RTLDR_O_FOR_VALIDATION)) { /* likely */ } \
     2534            else return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT[%u]/" a_szName ": Not supported (" FMT_ELF_ADDR ")", pszLogName, i, paDynamic[i].d_un.d_ptr); \
     2535        } while (0)
     2536#define LOG_NON_VALUE_ENTRY(a_szName) Log3(("RTLdrELF: DT[%u]: %16s (%#RX64)\n", i, a_szName, (uint64_t)paDynamic[i].d_un.d_val))
     2537
     2538        switch (paDynamic[i].d_tag)
     2539        {
     2540            case DT_NULL:
     2541                LOG_NON_VALUE_ENTRY("DT_NULL");
     2542                for (unsigned iNull = i + 1; iNull < pModElf->cDynamic; iNull++)
     2543                    if (paDynamic[i].d_tag == DT_NULL) /* Not technically a bug, but let's try being extremely strict for now */
     2544                        LOG_NON_VALUE_ENTRY("DT_NULL");
     2545                    else if (!(fFlags & (RTLDR_O_FOR_DEBUG | RTLDR_O_FOR_VALIDATION)))
     2546                        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     2547                                                   "%s: DT[%u]/DT_NULL: Dynamic section isn't zero padded (extra #%u of #%u)",
     2548                                                   pszLogName, i, iNull - i, pModElf->cDynamic - i);
     2549                i = pModElf->cDynamic;
     2550                break;
     2551            case DT_NEEDED:
     2552                LOG_VALIDATE_STR_RET("DT_NEEDED");
     2553                break;
     2554            case DT_PLTRELSZ:
     2555                Log3(("RTLdrELF: DT[%u]: %16s %#RX64 bytes\n", i, "DT_PLTRELSZ", (uint64_t)paDynamic[i].d_un.d_val));
     2556                SET_INFO_FIELD_RET("DT_PLTRELSZ", pModElf->DynInfo.cbJmpRelocs, (Elf_Xword)paDynamic[i].d_un.d_val, 0, FMT_ELF_XWORD);
     2557                break;
     2558            case DT_PLTGOT:
     2559                LOG_VALIDATE_PTR_RET("DT_PLTGOT");
     2560                break;
     2561            case DT_HASH:
     2562                LOG_VALIDATE_PTR_RET("DT_HASH");
     2563                break;
     2564            case DT_STRTAB:
     2565                LOG_VALIDATE_PTR_VAL_RET("DT_STRTAB", paShdrs[pModElf->Dyn.iStrSh].sh_addr);
     2566                pModElf->paShdrExtras[pModElf->Dyn.iStrSh].idxDt  = i;
     2567                pModElf->paShdrExtras[pModElf->Dyn.iSymSh].uDtTag = DT_STRTAB;
     2568                break;
     2569            case DT_SYMTAB:
     2570                LOG_VALIDATE_PTR_VAL_RET("DT_SYMTAB", paShdrs[pModElf->Dyn.iSymSh].sh_addr);
     2571                pModElf->paShdrExtras[pModElf->Dyn.iSymSh].idxDt  = i;
     2572                pModElf->paShdrExtras[pModElf->Dyn.iSymSh].uDtTag = DT_SYMTAB;
     2573                break;
     2574            case DT_RELA:
     2575                LOG_VALIDATE_PTR_RET("DT_RELA");
     2576                SET_RELOC_TYPE_RET("DT_RELA", DT_RELA);
     2577                SET_INFO_FIELD_RET("DT_RELA", pModElf->DynInfo.uPtrRelocs, paDynamic[i].d_un.d_ptr, ~(Elf_Addr)0, FMT_ELF_ADDR);
     2578                FIND_MATCHING_SECTION_RET("DT_RELA", paShdrs[iSh].sh_type == SHT_RELA, pModElf->DynInfo.idxShRelocs);
     2579                break;
     2580            case DT_RELASZ:
     2581                Log3(("RTLdrELF: DT[%u]: %16s %#RX64 bytes\n", i, "DT_RELASZ", (uint64_t)paDynamic[i].d_un.d_val));
     2582                SET_RELOC_TYPE_RET("DT_RELASZ", DT_RELA);
     2583                SET_INFO_FIELD_RET("DT_RELASZ", pModElf->DynInfo.cbRelocs, (Elf_Xword)paDynamic[i].d_un.d_val, 0, FMT_ELF_XWORD);
     2584                break;
     2585            case DT_RELAENT:
     2586                LOG_VALIDATE_VAL_RET("DT_RELAENT", sizeof(Elf_Rela));
     2587                SET_RELOC_TYPE_RET("DT_RELAENT", DT_RELA);
     2588                SET_INFO_FIELD_RET("DT_RELAENT", pModElf->DynInfo.cbRelocEntry, (unsigned)sizeof(Elf_Rela), 0, "%u");
     2589                break;
     2590            case DT_STRSZ:
     2591                LOG_VALIDATE_VAL_RET("DT_STRSZ", pModElf->Dyn.cbStr);
     2592                break;
     2593            case DT_SYMENT:
     2594                LOG_VALIDATE_VAL_RET("DT_SYMENT", sizeof(Elf_Sym));
     2595                break;
     2596            case DT_INIT:
     2597                LOG_VALIDATE_PTR_RET("DT_INIT");
     2598                ONLY_FOR_DEBUG_OR_VALIDATION_RET("DT_INIT");
     2599                break;
     2600            case DT_FINI:
     2601                LOG_VALIDATE_PTR_RET("DT_FINI");
     2602                ONLY_FOR_DEBUG_OR_VALIDATION_RET("DT_FINI");
     2603                break;
     2604            case DT_SONAME:
     2605                LOG_VALIDATE_STR_RET("DT_SONAME");
     2606                break;
     2607            case DT_RPATH:
     2608                LOG_VALIDATE_STR_RET("DT_RPATH");
     2609                break;
     2610            case DT_SYMBOLIC:
     2611                LOG_NON_VALUE_ENTRY("DT_SYMBOLIC");
     2612                break;
     2613            case DT_REL:
     2614                LOG_VALIDATE_PTR_RET("DT_REL");
     2615                SET_RELOC_TYPE_RET("DT_REL", DT_REL);
     2616                SET_INFO_FIELD_RET("DT_REL", pModElf->DynInfo.uPtrRelocs, paDynamic[i].d_un.d_ptr, ~(Elf_Addr)0, FMT_ELF_ADDR);
     2617                FIND_MATCHING_SECTION_RET("DT_REL", paShdrs[iSh].sh_type == SHT_REL, pModElf->DynInfo.idxShRelocs);
     2618                break;
     2619            case DT_RELSZ:
     2620                Log3(("RTLdrELF: DT[%u]: %16s %#RX64 bytes\n", i, "DT_RELSZ", (uint64_t)paDynamic[i].d_un.d_val));
     2621                SET_RELOC_TYPE_RET("DT_RELSZ", DT_REL);
     2622                SET_INFO_FIELD_RET("DT_RELSZ", pModElf->DynInfo.cbRelocs, (Elf_Xword)paDynamic[i].d_un.d_val, 0, FMT_ELF_XWORD);
     2623                break;
     2624            case DT_RELENT:
     2625                LOG_VALIDATE_VAL_RET("DT_RELENT", sizeof(Elf_Rel));
     2626                SET_RELOC_TYPE_RET("DT_RELENT", DT_REL);
     2627                SET_INFO_FIELD_RET("DT_RELENT", pModElf->DynInfo.cbRelocEntry, (unsigned)sizeof(Elf_Rel), 0, "%u");
     2628                break;
     2629            case DT_PLTREL:
     2630                if (paDynamic[i].d_un.d_val != DT_RELA && paDynamic[i].d_un.d_val != DT_REL)
     2631                    return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT[%u]/DT_PLTREL: Invalid value %#RX64",
     2632                                               pszLogName, i, (uint64_t)paDynamic[i].d_un.d_val);
     2633                Log3(("RTLdrELF: DT[%u]: %16s DT_REL%s\n", i, "DT_PLTREL", paDynamic[i].d_un.d_val == DT_RELA ? "A" : ""));
     2634                SET_INFO_FIELD_RET("DT_PLTREL", pModElf->DynInfo.uJmpRelocType, (unsigned)paDynamic[i].d_un.d_val, 0, "%u");
     2635                break;
     2636            case DT_DEBUG:
     2637                LOG_VALIDATE_PTR_RET("DT_DEBUG");
     2638                break;
     2639            case DT_TEXTREL:
     2640                LOG_NON_VALUE_ENTRY("DT_TEXTREL");
     2641                break;
     2642            case DT_JMPREL:
     2643                LOG_VALIDATE_PTR_RET("DT_JMPREL");
     2644                SET_INFO_FIELD_RET("DT_JMPREL", pModElf->DynInfo.uPtrJmpRelocs, paDynamic[i].d_un.d_ptr, ~(Elf_Addr)0, FMT_ELF_ADDR);
     2645                FIND_MATCHING_SECTION_RET("DT_JMPREL", 1, pModElf->DynInfo.idxShJmpRelocs);
     2646                break;
     2647            case DT_BIND_NOW:
     2648                LOG_NON_VALUE_ENTRY("DT_BIND_NOW");
     2649                break;
     2650            case DT_INIT_ARRAY:
     2651                LOG_VALIDATE_PTR_RET("DT_INIT_ARRAY");
     2652                ONLY_FOR_DEBUG_OR_VALIDATION_RET("DT_INIT_ARRAY");
     2653                break;
     2654            case DT_FINI_ARRAY:
     2655                LOG_VALIDATE_PTR_RET("DT_FINI_ARRAY");
     2656                ONLY_FOR_DEBUG_OR_VALIDATION_RET("DT_FINI_ARRAY");
     2657                break;
     2658            case DT_INIT_ARRAYSZ:
     2659                Log3(("RTLdrELF: DT[%u]: %16s %#RX64 bytes\n", i, "DT_INIT_ARRAYSZ", (uint64_t)paDynamic[i].d_un.d_val));
     2660                ONLY_FOR_DEBUG_OR_VALIDATION_RET("DT_INIT_ARRAYSZ");
     2661                break;
     2662            case DT_FINI_ARRAYSZ:
     2663                Log3(("RTLdrELF: DT[%u]: %16s %#RX64 bytes\n", i, "DT_FINI_ARRAYSZ", (uint64_t)paDynamic[i].d_un.d_val));
     2664                ONLY_FOR_DEBUG_OR_VALIDATION_RET("DT_FINI_ARRAYSZ");
     2665                break;
     2666            case DT_RUNPATH:
     2667                LOG_VALIDATE_STR_RET("DT_RUNPATH");
     2668                break;
     2669            case DT_FLAGS:
     2670                Log3(("RTLdrELF: DT[%u]: %16s %#RX64\n", i, "DT_FLAGS", (uint64_t)paDynamic[i].d_un.d_val));
     2671                break;
     2672            case DT_PREINIT_ARRAY:
     2673                LOG_VALIDATE_PTR_RET("DT_PREINIT_ARRAY");
     2674                ONLY_FOR_DEBUG_OR_VALIDATION_RET("DT_PREINIT_ARRAY");
     2675                break;
     2676            case DT_PREINIT_ARRAYSZ:
     2677                Log3(("RTLdrELF: DT[%u]: %16s %#RX64 bytes\n", i, "DT_PREINIT_ARRAYSZ", (uint64_t)paDynamic[i].d_un.d_val));
     2678                ONLY_FOR_DEBUG_OR_VALIDATION_RET("DT_PREINIT_ARRAYSZ");
     2679                break;
     2680            default:
     2681                if (   paDynamic[i].d_un.d_val < DT_ENCODING
     2682                    || (paDynamic[i].d_un.d_val & 1))
     2683                    Log3(("RTLdrELF: DT[%u]: %#010RX64       %#RX64%s\n", i, (uint64_t)paDynamic[i].d_tag,
     2684                          (uint64_t)paDynamic[i].d_un.d_val, paDynamic[i].d_un.d_val >= DT_ENCODING ? " (val)" : ""));
     2685                else
     2686                {
     2687                    Log3(("RTLdrELF: DT[%u]: %#010RX64       " FMT_ELF_ADDR " (addr)\n",
     2688                          i, (uint64_t)paDynamic[i].d_tag, paDynamic[i].d_un.d_ptr));
     2689                    if ((uint64_t)paDynamic[i].d_un.d_ptr - uLinkAddress >= cbImage)
     2690                        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     2691                                                   "%s: DT[%u]/%#RX64: Invalid address " FMT_ELF_ADDR " (valid range: " FMT_ELF_ADDR " LB " FMT_ELF_ADDR ")",
     2692                                                   pszLogName, i, (uint64_t)paDynamic[i].d_tag,
     2693                                                   paDynamic[i].d_un.d_ptr, uLinkAddress, cbImage);
     2694                }
     2695                break;
     2696        }
     2697#undef LOG_VALIDATE_VAL_RET
     2698#undef LOG_VALIDATE_STR_RET
     2699#undef LOG_VALIDATE_PTR_VAL_RET
     2700#undef LOG_VALIDATE_PTR_RET
     2701#undef SET_RELOC_TYPE_RET
     2702#undef SET_INFO_FIELD_RET
     2703#undef FIND_MATCHING_SECTION_RET
     2704#undef ONLY_FOR_DEBUG_OR_VALIDATION_RET
     2705    }
     2706
     2707    /*
     2708     * Validate the relocation information we've gathered.
     2709     */
     2710    Elf_Word uShTypeArch = SHT_RELA; /** @todo generalize architecture specific stuff using its own code template header.  */
     2711    switch (pModElf->Core.enmArch)
     2712    {
     2713        case RTLDRARCH_AMD64:
     2714            break;
     2715        case RTLDRARCH_X86_32:
     2716            uShTypeArch = SHT_REL;
     2717            break;
     2718        default:
     2719            AssertFailedBreak(/** @todo page size for got.plt hacks */);
     2720
     2721    }
     2722
     2723    if (pModElf->DynInfo.uRelocType != 0)
     2724    {
     2725        const char * const pszModifier = pModElf->DynInfo.uRelocType == DT_RELA ? "A" : "";
     2726        if (pModElf->DynInfo.uPtrRelocs == ~(Elf_Addr)0)
     2727            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: Missing DT_REL%s", pszLogName, pszModifier);
     2728        if (pModElf->DynInfo.cbRelocs == 0)
     2729            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: Missing DT_REL%sSZ", pszLogName, pszModifier);
     2730        if (pModElf->DynInfo.cbRelocEntry == 0)
     2731            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: Missing DT_REL%sENT", pszLogName, pszModifier);
     2732        Elf_Shdr const *pShdrRelocs = &paShdrs[pModElf->DynInfo.idxShRelocs];
     2733        Elf_Word const  uShType     = pModElf->DynInfo.uJmpRelocType == DT_RELA ? SHT_RELA : SHT_REL;
     2734        if (pShdrRelocs->sh_type != uShType)
     2735            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT_REL%s* does not match section type: %u vs %u",
     2736                                       pszLogName, pszModifier, pShdrRelocs->sh_type, uShType);
     2737        if (pShdrRelocs->sh_size != pModElf->DynInfo.cbRelocs)
     2738            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT_REL%sSZ does not match section size: %u vs %u",
     2739                                       pszLogName, pszModifier, pShdrRelocs->sh_size, pModElf->DynInfo.cbRelocs);
     2740        if (uShType != uShTypeArch)
     2741            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT_REL%s* does not match architecture: %u, arch wants %u",
     2742                                       pszLogName, pszModifier, uShType, uShTypeArch);
     2743    }
     2744
     2745    if (   pModElf->DynInfo.uPtrJmpRelocs != ~(Elf_Addr)0
     2746        || pModElf->DynInfo.cbJmpRelocs   != 0
     2747        || pModElf->DynInfo.uJmpRelocType != 0)
     2748    {
     2749        if (pModElf->DynInfo.uPtrJmpRelocs == ~(Elf_Addr)0)
     2750            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: Missing DT_JMPREL", pszLogName);
     2751        if (pModElf->DynInfo.cbJmpRelocs == 0)
     2752            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: Missing DT_PLTRELSZ", pszLogName);
     2753        if (pModElf->DynInfo.uJmpRelocType == 0)
     2754            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: Missing DT_PLTREL", pszLogName);
     2755        Elf_Shdr const *pShdrRelocs = &paShdrs[pModElf->DynInfo.idxShJmpRelocs];
     2756        Elf_Word const  uShType     = pModElf->DynInfo.uJmpRelocType == DT_RELA ? SHT_RELA : SHT_REL;
     2757        if (pShdrRelocs->sh_type != uShType)
     2758            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT_PLTREL does not match section type: %u vs %u",
     2759                                       pszLogName, pShdrRelocs->sh_type, uShType);
     2760        if (pShdrRelocs->sh_size != pModElf->DynInfo.cbJmpRelocs)
     2761            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT_PLTRELSZ does not match section size: %u vs %u",
     2762                                       pszLogName, pShdrRelocs->sh_size, pModElf->DynInfo.cbJmpRelocs);
     2763        if (uShType != uShTypeArch)
     2764            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT_PLTREL does not match architecture: %u, arch wants %u",
     2765                                       pszLogName, uShType, uShTypeArch);
     2766    }
     2767
     2768    /*
     2769     * Check that there aren't any other relocations hiding in the section table.
     2770     */
     2771    for (uint32_t i = 1; i < pModElf->Ehdr.e_shnum; i++)
     2772        if (   (paShdrs[i].sh_type == SHT_REL || paShdrs[i].sh_type == SHT_RELA)
     2773            && pModElf->paShdrExtras[i].uDtTag != DT_REL
     2774            && pModElf->paShdrExtras[i].uDtTag != DT_RELA
     2775            && pModElf->paShdrExtras[i].uDtTag != DT_JMPREL)
     2776        {
     2777            char szSecHdrNm[80];
     2778            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
     2779                                       "%s: section header #%u (%s type=" FMT_ELF_WORD " size=" FMT_ELF_XWORD ") contains relocations not referenced by the dynamic section",
     2780                                       pszLogName,
     2781                                       RTLDRELF_NAME(GetSHdrName)(pModElf, paShdrs[i].sh_name, szSecHdrNm, sizeof(szSecHdrNm)),
     2782                                       paShdrs[i].sh_type, paShdrs[i].sh_size);
     2783        }
    18532784
    18542785    return VINF_SUCCESS;
     
    18652796 * @param   enmArch     Architecture specifier.
    18662797 * @param   phLdrMod    Where to store the handle.
     2798 * @param   pErrInfo    Where to return extended error info. Optional.
    18672799 */
    1868 static int RTLDRELF_NAME(Open)(PRTLDRREADER pReader, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod)
     2800static int RTLDRELF_NAME(Open)(PRTLDRREADER pReader, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod, PRTERRINFO pErrInfo)
    18692801{
    18702802    const char *pszLogName = pReader->pfnLogName(pReader);
     
    18902822    pModElf->Core.enmArch   = RTLDRARCH_AMD64;
    18912823#endif
    1892     //pModElf->pvBits         = NULL;
    1893     //pModElf->Ehdr           = {0};
    1894     //pModElf->paShdrs        = NULL;
    1895     //pModElf->paSyms         = NULL;
    1896     pModElf->iSymSh         = ~0U;
    1897     //pModElf->cSyms          = 0;
    1898     pModElf->iStrSh         = ~0U;
    1899     //pModElf->cbStr          = 0;
    1900     //pModElf->cbImage        = 0;
    1901     //pModElf->LinkAddress    = 0;
    1902     //pModElf->pStr           = NULL;
    1903     //pModElf->cbShStr        = 0;
    1904     //pModElf->pShStr         = NULL;
    1905     //pModElf->iShEhFrame      = 0;
    1906     //pModElf->iShEhFrameHdr   = 0;
     2824    //pModElf->pvBits       = NULL;
     2825    //pModElf->Ehdr         = {0};
     2826    //pModElf->paShdrs      = NULL;
     2827    //pModElf->Rel.paSyms   = NULL;
     2828    pModElf->Rel.iSymSh     = ~0U;
     2829    //pModElf->Rel.cSyms    = 0;
     2830    pModElf->Rel.iStrSh     = ~0U;
     2831    //pModElf->Rel.cbStr    = 0;
     2832    //pModElf->Rel.pStr     = NULL;
     2833    //pModElf->Dyn.paSyms   = NULL;
     2834    pModElf->Dyn.iSymSh     = ~0U;
     2835    //pModElf->Dyn.cSyms    = 0;
     2836    pModElf->Dyn.iStrSh     = ~0U;
     2837    //pModElf->Dyn.cbStr    = 0;
     2838    //pModElf->Dyn.pStr     = NULL;
     2839    //pModElf->iFirstSect   = 0;
     2840    //pModElf->cbImage      = 0;
     2841    pModElf->LinkAddress    = ~(Elf_Addr)0;
     2842    //pModElf->cbShStr      = 0;
     2843    //pModElf->pShStr       = NULL;
     2844    //pModElf->iShEhFrame   = 0;
     2845    //pModElf->iShEhFrameHdr= 0;
     2846    pModElf->iShDynamic     = ~0U;
     2847    //pModElf->cDynamic     = 0;
     2848    //pModElf->paDynamic    = NULL;
     2849    //pModElf->paPhdrs      = NULL;
     2850    pModElf->DynInfo.uPtrRelocs         = ~(Elf_Addr)0;
     2851    //pModElf->DynInfo.cbRelocs         = 0;
     2852    //pModElf->DynInfo.cbRelocEntry     = 0;
     2853    //pModElf->DynInfo.uRelocType       = 0;
     2854    //pModElf->DynInfo.idxShRelocs      = 0;
     2855    pModElf->DynInfo.uPtrJmpRelocs      = ~(Elf_Addr)0;
     2856    //pModElf->DynInfo.cbJmpRelocs      = 0;
     2857    //pModElf->DynInfo.uJmpRelocType    = 0;
     2858    //pModElf->DynInfo.idxShJmpRelocs   = 0;
    19072859
    19082860    /*
     
    19132865    {
    19142866        RTLDRARCH enmArchImage = RTLDRARCH_INVALID; /* shut up gcc */
    1915         rc = RTLDRELF_NAME(ValidateElfHeader)(&pModElf->Ehdr, pszLogName, cbRawImage, &enmArchImage);
     2867        rc = RTLDRELF_NAME(ValidateElfHeader)(&pModElf->Ehdr, cbRawImage, pszLogName, &enmArchImage, pErrInfo);
    19162868        if (RT_SUCCESS(rc))
    19172869        {
     
    19282880         */
    19292881        size_t const cbShdrs = pModElf->Ehdr.e_shnum * sizeof(Elf_Shdr);
    1930         Elf_Shdr *paShdrs = (Elf_Shdr *)RTMemAlloc(cbShdrs * 2);
     2882        Elf_Shdr *paShdrs = (Elf_Shdr *)RTMemAlloc(cbShdrs * 2 + sizeof(RTLDRMODELFSHX) * pModElf->Ehdr.e_shnum);
    19312883        if (paShdrs)
    19322884        {
     
    19382890                pModElf->paOrgShdrs = &paShdrs[pModElf->Ehdr.e_shnum];
    19392891
     2892                pModElf->paShdrExtras = (PRTLDRMODELFSHX)&pModElf->paOrgShdrs[pModElf->Ehdr.e_shnum];
     2893                memset(pModElf->paShdrExtras, 0xff, sizeof(RTLDRMODELFSHX) * pModElf->Ehdr.e_shnum);
     2894
    19402895                pModElf->cbShStr = paShdrs[pModElf->Ehdr.e_shstrndx].sh_size;
    19412896
     
    19432898                 * Validate the section headers and find relevant sections.
    19442899                 */
    1945                 Elf_Addr uNextAddr = 0;
    1946                 for (unsigned i = 0; i < pModElf->Ehdr.e_shnum; i++)
    1947                 {
    1948                     rc = RTLDRELF_NAME(ValidateSectionHeader)(pModElf, i, pszLogName, cbRawImage);
    1949                     if (RT_FAILURE(rc))
    1950                         break;
    1951 
    1952                     /* We're looking for symbol tables. */
    1953                     if (paShdrs[i].sh_type == SHT_SYMTAB)
    1954                     {
    1955                         if (pModElf->iSymSh != ~0U)
    1956                         {
    1957                             Log(("RTLdrElf: %s: Multiple symbol tabs! iSymSh=%d i=%d\n", pszLogName, pModElf->iSymSh, i));
    1958                             rc = VERR_LDRELF_MULTIPLE_SYMTABS;
    1959                             break;
    1960                         }
    1961                         pModElf->iSymSh = i;
    1962                         pModElf->cSyms  = (unsigned)(paShdrs[i].sh_size / sizeof(Elf_Sym));
    1963                         AssertBreakStmt(pModElf->cSyms == paShdrs[i].sh_size / sizeof(Elf_Sym), rc = VERR_IMAGE_TOO_BIG);
    1964                         pModElf->iStrSh = paShdrs[i].sh_link;
    1965                         pModElf->cbStr  = (unsigned)paShdrs[pModElf->iStrSh].sh_size;
    1966                         AssertBreakStmt(pModElf->cbStr == paShdrs[pModElf->iStrSh].sh_size, rc = VERR_IMAGE_TOO_BIG);
    1967                     }
    1968 
    1969                     /* Special checks for the section string table. */
    1970                     if (i == pModElf->Ehdr.e_shstrndx)
    1971                     {
    1972                         if (paShdrs[i].sh_type != SHT_STRTAB)
    1973                         {
    1974                             Log(("RTLdrElf: Section header string table is not a SHT_STRTAB: %#x\n", paShdrs[i].sh_type));
    1975                             rc = VERR_BAD_EXE_FORMAT;
    1976                             break;
    1977                         }
    1978                         if (paShdrs[i].sh_size == 0)
    1979                         {
    1980                             Log(("RTLdrElf: Section header string table is empty\n"));
    1981                             rc = VERR_BAD_EXE_FORMAT;
    1982                             break;
    1983                         }
    1984                     }
    1985 
    1986                     /* Kluge for the .data..percpu segment in 64-bit linux kernels. */
    1987                     if (paShdrs[i].sh_flags & SHF_ALLOC)
    1988                     {
    1989                         if (   paShdrs[i].sh_addr == 0
    1990                             && paShdrs[i].sh_addr < uNextAddr)
    1991                         {
    1992                             Elf_Addr uAddr = RT_ALIGN_T(uNextAddr, paShdrs[i].sh_addralign, Elf_Addr);
    1993                             Log(("RTLdrElf: Out of order section #%d; adjusting sh_addr from " FMT_ELF_ADDR " to " FMT_ELF_ADDR "\n",
    1994                                  i, paShdrs[i].sh_addr, uAddr));
    1995                             paShdrs[i].sh_addr = uAddr;
    1996                         }
    1997                         uNextAddr = paShdrs[i].sh_addr + paShdrs[i].sh_size;
    1998                     }
    1999                 } /* for each section header */
     2900                rc = RTLDRELF_NAME(ValidateAndProcessSectionHeaders)(pModElf, paShdrs, cbRawImage, pszLogName, pErrInfo);
    20002901
    20012902                /*
    2002                  * Calculate the image base address if the image isn't relocatable.
     2903                 * Read validate and process program headers if ET_DYN or ET_EXEC.
    20032904                 */
    2004                 if (RT_SUCCESS(rc) && pModElf->Ehdr.e_type != ET_REL)
    2005                 {
    2006                     pModElf->LinkAddress = ~(Elf_Addr)0;
    2007                     for (unsigned i = 0; i < pModElf->Ehdr.e_shnum; i++)
    2008                         if (   (paShdrs[i].sh_flags & SHF_ALLOC)
    2009                             && paShdrs[i].sh_addr < pModElf->LinkAddress)
    2010                             pModElf->LinkAddress = paShdrs[i].sh_addr;
    2011                     if (pModElf->LinkAddress == ~(Elf_Addr)0)
    2012                     {
    2013                         AssertFailed();
    2014                         rc = VERR_LDR_GENERAL_FAILURE;
    2015                     }
    2016                     if (pModElf->Ehdr.e_type == ET_DYN && pModElf->LinkAddress < 0x1000)
    2017                         pModElf->LinkAddress = 0;
    2018                 }
     2905                if (RT_SUCCESS(rc) && (pModElf->Ehdr.e_type == ET_DYN || pModElf->Ehdr.e_type == ET_EXEC))
     2906                    rc = RTLDRELF_NAME(ValidateAndProcessDynamicInfo)(pModElf, cbRawImage, fFlags, pszLogName, pErrInfo);
    20192907
    20202908                /*
    2021                  * Perform allocations / RVA calculations, determine the image size.
     2909                 * Massage the section headers.
    20222910                 */
    20232911                if (RT_SUCCESS(rc))
    2024                     for (unsigned i = 0; i < pModElf->Ehdr.e_shnum; i++)
    2025                         if (paShdrs[i].sh_flags & SHF_ALLOC)
    2026                         {
    2027                             if (pModElf->Ehdr.e_type == ET_REL)
     2912                {
     2913                    if (pModElf->Ehdr.e_type == ET_REL)
     2914                    {
     2915                        /* Do allocations and figure the image size: */
     2916                        pModElf->LinkAddress = 0;
     2917                        for (unsigned i = 1; i < pModElf->Ehdr.e_shnum; i++)
     2918                            if (paShdrs[i].sh_flags & SHF_ALLOC)
     2919                            {
    20282920                                paShdrs[i].sh_addr = paShdrs[i].sh_addralign
    20292921                                                   ? RT_ALIGN_T(pModElf->cbImage, paShdrs[i].sh_addralign, Elf_Addr)
    20302922                                                   : (Elf_Addr)pModElf->cbImage;
    2031                             else
    2032                                 paShdrs[i].sh_addr -= pModElf->LinkAddress;
    2033                             Elf_Addr EndAddr = paShdrs[i].sh_addr + paShdrs[i].sh_size;
    2034                             if (pModElf->cbImage < EndAddr)
    2035                             {
    2036                                 pModElf->cbImage = (size_t)EndAddr;
    2037                                 AssertMsgBreakStmt(pModElf->cbImage == EndAddr, (FMT_ELF_ADDR "\n", EndAddr), rc = VERR_IMAGE_TOO_BIG);
     2923                                Elf_Addr EndAddr = paShdrs[i].sh_addr + paShdrs[i].sh_size;
     2924                                if (pModElf->cbImage < EndAddr)
     2925                                {
     2926                                    pModElf->cbImage = (size_t)EndAddr;
     2927                                    AssertMsgBreakStmt(pModElf->cbImage == EndAddr, (FMT_ELF_ADDR "\n", EndAddr), rc = VERR_IMAGE_TOO_BIG);
     2928                                }
     2929                                Log2(("RTLdrElf: %s: Assigned " FMT_ELF_ADDR " to section #%d\n", pszLogName, paShdrs[i].sh_addr, i));
    20382930                            }
    2039                             Log2(("RTLdrElf: %s: Assigned " FMT_ELF_ADDR " to section #%d\n", pszLogName, paShdrs[i].sh_addr, i));
    2040                         }
     2931                    }
     2932                    else
     2933                    {
     2934                        /* Convert sh_addr to RVA: */
     2935                        Assert(pModElf->LinkAddress != ~(Elf_Addr)0);
     2936                        for (unsigned i = 0 /*!*/; i < pModElf->Ehdr.e_shnum; i++)
     2937                            if (paShdrs[i].sh_flags & SHF_ALLOC)
     2938                                    paShdrs[i].sh_addr -= pModElf->LinkAddress;
     2939                    }
     2940                }
    20412941
    20422942                Log2(("RTLdrElf: iSymSh=%u cSyms=%u iStrSh=%u cbStr=%u rc=%Rrc cbImage=%#zx LinkAddress=" FMT_ELF_ADDR "\n",
    2043                       pModElf->iSymSh, pModElf->cSyms, pModElf->iStrSh, pModElf->cbStr, rc,
     2943                      pModElf->Rel.iSymSh, pModElf->Rel.cSyms, pModElf->Rel.iStrSh, pModElf->Rel.cbStr, rc,
    20442944                      pModElf->cbImage, pModElf->LinkAddress));
    20452945                if (RT_SUCCESS(rc))
     
    20762976
    20772977#undef FMT_ELF_ADDR
     2978#undef FMT_ELF_ADDR7
    20782979#undef FMT_ELF_HALF
    20792980#undef FMT_ELF_SHALF
     
    21013002#undef Elf_Sword
    21023003#undef Elf_Word
     3004#undef Elf_Xword
     3005#undef Elf_Sxword
    21033006
    21043007#undef RTLDRMODELF
Note: See TracChangeset for help on using the changeset viewer.

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