diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2014-03-26 19:21:20 +0000 |
---|---|---|
committer | <> | 2014-05-08 15:03:54 +0000 |
commit | fb123f93f9f5ce42c8e5785d2f8e0edaf951740e (patch) | |
tree | c2103d76aec5f1f10892cd1d3a38e24f665ae5db /src/libs/kStuff | |
parent | 58ed4748338f9466599adfc8a9171280ed99e23f (diff) | |
download | VirtualBox-master.tar.gz |
Imported from /home/lorry/working-area/delta_VirtualBox/VirtualBox-4.3.10.tar.bz2.HEADVirtualBox-4.3.10master
Diffstat (limited to 'src/libs/kStuff')
-rw-r--r-- | src/libs/kStuff/Makefile.kmk | 5 | ||||
-rw-r--r-- | src/libs/kStuff/iprt/kHlpAlloc-iprt.cpp | 2 | ||||
-rw-r--r-- | src/libs/kStuff/iprt/kHlpAssert-iprt.cpp | 2 | ||||
-rw-r--r-- | src/libs/kStuff/iprt/kHlpEnv-iprt.cpp | 2 | ||||
-rw-r--r-- | src/libs/kStuff/iprt/kHlpPage-iprt.cpp | 2 | ||||
-rw-r--r-- | src/libs/kStuff/iprt/kHlpString-iprt.cpp | 2 | ||||
-rw-r--r-- | src/libs/kStuff/iprt/kRdrFile-iprt.cpp | 2 | ||||
-rw-r--r-- | src/libs/kStuff/kStuff/include/k/kLdr.h | 10 | ||||
-rw-r--r-- | src/libs/kStuff/kStuff/kLdr/kLdrMod.c | 4 | ||||
-rw-r--r-- | src/libs/kStuff/kStuff/kLdr/kLdrModMachO.c | 156 |
10 files changed, 131 insertions, 56 deletions
diff --git a/src/libs/kStuff/Makefile.kmk b/src/libs/kStuff/Makefile.kmk index da9587f8..9d74ae56 100644 --- a/src/libs/kStuff/Makefile.kmk +++ b/src/libs/kStuff/Makefile.kmk @@ -70,6 +70,11 @@ VBox-kStuff_SOURCES = \ iprt/kHlpString-iprt.cpp \ iprt/kRdrFile-iprt.cpp +ifdef VBOX_WITH_32_ON_64_MAIN_API # 32-bit edition. + LIBRARIES += VBox-kStuff-x86 + VBox-kStuff-x86_TEMPLATE = VBoxR3Dll-x86 + VBox-kStuff-x86_EXTENDS = VBox-kStuff +endif # # The library for static linking. diff --git a/src/libs/kStuff/iprt/kHlpAlloc-iprt.cpp b/src/libs/kStuff/iprt/kHlpAlloc-iprt.cpp index 6684bf33..7bf8cc3c 100644 --- a/src/libs/kStuff/iprt/kHlpAlloc-iprt.cpp +++ b/src/libs/kStuff/iprt/kHlpAlloc-iprt.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2007 Oracle Corporation + * Copyright (C) 2007-2010 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/libs/kStuff/iprt/kHlpAssert-iprt.cpp b/src/libs/kStuff/iprt/kHlpAssert-iprt.cpp index 406bc3e8..2dc3ba7d 100644 --- a/src/libs/kStuff/iprt/kHlpAssert-iprt.cpp +++ b/src/libs/kStuff/iprt/kHlpAssert-iprt.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2009 Oracle Corporation + * Copyright (C) 2009-2010 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/libs/kStuff/iprt/kHlpEnv-iprt.cpp b/src/libs/kStuff/iprt/kHlpEnv-iprt.cpp index 17661ca7..105c75c9 100644 --- a/src/libs/kStuff/iprt/kHlpEnv-iprt.cpp +++ b/src/libs/kStuff/iprt/kHlpEnv-iprt.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2007 Oracle Corporation + * Copyright (C) 2007-2010 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/libs/kStuff/iprt/kHlpPage-iprt.cpp b/src/libs/kStuff/iprt/kHlpPage-iprt.cpp index b808d997..a9a1c69b 100644 --- a/src/libs/kStuff/iprt/kHlpPage-iprt.cpp +++ b/src/libs/kStuff/iprt/kHlpPage-iprt.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2007 Oracle Corporation + * Copyright (C) 2007-2010 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/libs/kStuff/iprt/kHlpString-iprt.cpp b/src/libs/kStuff/iprt/kHlpString-iprt.cpp index 0c74fa55..d7105341 100644 --- a/src/libs/kStuff/iprt/kHlpString-iprt.cpp +++ b/src/libs/kStuff/iprt/kHlpString-iprt.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2007 Oracle Corporation + * Copyright (C) 2007-2010 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/libs/kStuff/iprt/kRdrFile-iprt.cpp b/src/libs/kStuff/iprt/kRdrFile-iprt.cpp index 2d890733..0b95962d 100644 --- a/src/libs/kStuff/iprt/kRdrFile-iprt.cpp +++ b/src/libs/kStuff/iprt/kRdrFile-iprt.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2007 Oracle Corporation + * Copyright (C) 2007-2010 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/libs/kStuff/kStuff/include/k/kLdr.h b/src/libs/kStuff/kStuff/include/k/kLdr.h index c7fe7899..795b3f64 100644 --- a/src/libs/kStuff/kStuff/include/k/kLdr.h +++ b/src/libs/kStuff/kStuff/include/k/kLdr.h @@ -1,4 +1,4 @@ -/* $Id: kLdr.h 41 2011-08-24 14:35:57Z bird $ */ +/* $Id: kLdr.h 52 2013-07-09 17:03:37Z bird $ */ /** @file * kLdr - The Dynamic Loader. */ @@ -588,6 +588,14 @@ typedef FNKLDRENUMRSRC *PFNKLDRENUMRSRC; #define KLDR_LANG_ID_UI_CUSTOM_DEFAULT ( ~(KU32)7 ) /** @} */ +/** @name Module Open Flags + * @{ */ +/** Indicates that we won't be loading the module, we're just getting + * information (like symbols and line numbers) out of it. */ +#define KLDRMOD_OPEN_FLAGS_FOR_INFO K_BIT32(0) +/** Mask of valid flags. */ +#define KLDRMOD_OPEN_FLAGS_VALID_MASK KU32_C(0x00000001) +/** @} */ int kLdrModOpen(const char *pszFilename, KU32 fFlags, KCPUARCH enmCpuArch, PPKLDRMOD ppMod); int kLdrModOpenFromRdr(PKRDR pRdr, KU32 fFlags, KCPUARCH enmCpuArch, PPKLDRMOD ppMod); diff --git a/src/libs/kStuff/kStuff/kLdr/kLdrMod.c b/src/libs/kStuff/kStuff/kLdr/kLdrMod.c index 740ae4b5..d3305c3d 100644 --- a/src/libs/kStuff/kStuff/kLdr/kLdrMod.c +++ b/src/libs/kStuff/kStuff/kLdr/kLdrMod.c @@ -1,4 +1,4 @@ -/* $Id: kLdrMod.c 41 2011-08-24 14:35:57Z bird $ */
+/* $Id: kLdrMod.c 52 2013-07-09 17:03:37Z bird $ */
/** @file
* kLdr - The Module Interpreter.
*/
@@ -300,6 +300,8 @@ int kLdrModOpenFromRdr(PKRDR pRdr, KU32 fFlags, KCPUARCH enmCpuArch, PPKLDRMOD p KLDRFOFF offHdr = 0;
int rc;
+ kHlpAssertReturn(!(fFlags & ~KLDRMOD_OPEN_FLAGS_VALID_MASK), KERR_INVALID_PARAMETER);
+
for (;;)
{
/*
diff --git a/src/libs/kStuff/kStuff/kLdr/kLdrModMachO.c b/src/libs/kStuff/kStuff/kLdr/kLdrModMachO.c index 4ad32e2a..6ccff89b 100644 --- a/src/libs/kStuff/kStuff/kLdr/kLdrModMachO.c +++ b/src/libs/kStuff/kStuff/kLdr/kLdrModMachO.c @@ -1,4 +1,4 @@ -/* $Id: kLdrModMachO.c 49 2012-08-28 23:49:20Z bird $ */ +/* $Id: kLdrModMachO.c 53 2013-07-09 17:18:44Z bird $ */ /** @file * kLdr - The Module Interpreter for the MACH-O format. */ @@ -102,6 +102,8 @@ typedef struct KLDRMODMACHOSECT */ typedef struct KLDRMODMACHOSEG { + /** The orignal segment number (in case we had to resort it). */ + KU32 iOrgSegNo; /** The number of sections in the segment. */ KU32 cSections; /** Pointer to the sections belonging to this segment. @@ -123,6 +125,8 @@ typedef struct KLDRMODMACHO const void *pvBits; /** Pointer to the user mapping. */ void *pvMapping; + /** The module open flags. */ + KU32 fOpenFlags; /** The offset of the image. (FAT fun.) */ KLDRFOFF offImage; @@ -185,9 +189,10 @@ static KI32 kldrModMachONumberOfImports(PKLDRMOD pMod, const void *pvBits); static int kldrModMachORelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); -static int kldrModMachODoCreate(PKRDR pRdr, KLDRFOFF offImage, PKLDRMODMACHO *ppMod); +static int kldrModMachODoCreate(PKRDR pRdr, KLDRFOFF offImage, KU32 fOpenFlags, PKLDRMODMACHO *ppMod); static int kldrModMachOPreParseLoadCommands(KU8 *pbLoadCommands, const mach_header_32_t *pHdr, PKRDR pRdr, KLDRFOFF offImage, - KU32 *pcSegments, KU32 *pcSections, KU32 *pcbStringPool, PKBOOL pfCanLoad); + KU32 fOpenFlags, KU32 *pcSegments, KU32 *pcSections, KU32 *pcbStringPool, + PKBOOL pfCanLoad, PKLDRADDR pLinkAddress); static int kldrModMachOParseLoadCommands(PKLDRMODMACHO pModMachO, char *pbStringPool, KU32 cbStringPool); static int kldrModMachOAdjustBaseAddress(PKLDRMODMACHO pModMachO, PKLDRADDR pBaseAddress); @@ -244,7 +249,7 @@ static int kldrModMachOCreate(PCKLDRMODOPS pOps, PKRDR pRdr, KU32 fFlags, KCPUAR /* * Create the instance data and do a minimal header validation. */ - rc = kldrModMachODoCreate(pRdr, offNewHdr == -1 ? 0 : offNewHdr, &pModMachO); + rc = kldrModMachODoCreate(pRdr, offNewHdr == -1 ? 0 : offNewHdr, fFlags, &pModMachO); if (!rc) { @@ -274,7 +279,7 @@ static int kldrModMachOCreate(PCKLDRMODOPS pOps, PKRDR pRdr, KU32 fFlags, KCPUAR * Separate function for reading creating the Mach-O module instance to * simplify cleanup on failure. */ -static int kldrModMachODoCreate(PKRDR pRdr, KLDRFOFF offImage, PKLDRMODMACHO *ppModMachO) +static int kldrModMachODoCreate(PKRDR pRdr, KLDRFOFF offImage, KU32 fOpenFlags, PKLDRMODMACHO *ppModMachO) { union { @@ -291,6 +296,7 @@ static int kldrModMachODoCreate(PKRDR pRdr, KLDRFOFF offImage, PKLDRMODMACHO *pp KSIZE cb; KBOOL fMakeGot; KBOOL fCanLoad = K_TRUE; + KLDRADDR LinkAddress; KU8 cbJmpStub; int rc; *ppModMachO = NULL; @@ -350,8 +356,8 @@ static int kldrModMachODoCreate(PKRDR pRdr, KLDRFOFF offImage, PKLDRMODMACHO *pp ? sizeof(mach_header_32_t) + offImage : sizeof(mach_header_64_t) + offImage); if (!rc) - rc = kldrModMachOPreParseLoadCommands(pbLoadCommands, &s.Hdr32, pRdr, offImage, - &cSegments, &cSections, &cbStringPool, &fCanLoad); + rc = kldrModMachOPreParseLoadCommands(pbLoadCommands, &s.Hdr32, pRdr, offImage, fOpenFlags, + &cSegments, &cSections, &cbStringPool, &fCanLoad, &LinkAddress); if (rc) { kHlpFree(pbLoadCommands); @@ -451,11 +457,12 @@ static int kldrModMachODoCreate(PKRDR pRdr, KLDRFOFF offImage, PKLDRMODMACHO *pp pModMachO->pMod = pMod; pModMachO->pvBits = NULL; pModMachO->pvMapping = NULL; + pModMachO->fOpenFlags = fOpenFlags; pModMachO->Hdr = s.Hdr64; if ( s.Hdr32.magic == IMAGE_MACHO32_SIGNATURE || s.Hdr32.magic == IMAGE_MACHO32_SIGNATURE_OE) pModMachO->Hdr.reserved = 0; - pModMachO->LinkAddress = 0; + pModMachO->LinkAddress = LinkAddress; pModMachO->cbImage = 0; pModMachO->fCanLoad = fCanLoad; pModMachO->fMakeGot = fMakeGot; @@ -503,9 +510,12 @@ static int kldrModMachODoCreate(PKRDR pRdr, KLDRFOFF offImage, PKLDRMODMACHO *pp * @param pcSegments Where to store the section count. * @param pcbStringPool Where to store the string pool size. * @param pfCanLoad Where to store the can-load-image indicator. + * @param pLinkAddress Where to store the image link address (i.e. the + * lowest segment address). */ static int kldrModMachOPreParseLoadCommands(KU8 *pbLoadCommands, const mach_header_32_t *pHdr, PKRDR pRdr, KLDRFOFF offImage, - KU32 *pcSegments, KU32 *pcSections, KU32 *pcbStringPool, PKBOOL pfCanLoad) + KU32 fOpenFlags, KU32 *pcSegments, KU32 *pcSections, KU32 *pcbStringPool, + PKBOOL pfCanLoad, PKLDRADDR pLinkAddress) { union { @@ -518,6 +528,7 @@ static int kldrModMachOPreParseLoadCommands(KU8 *pbLoadCommands, const mach_hea uuid_command_t *pUuid; } u; const KU64 cbFile = kRdrSize(pRdr) - offImage; + const char *pchCurSegName = NULL; KU32 cSegments = 0; KU32 cSections = 0; KU32 cbStringPool = 0; @@ -533,6 +544,7 @@ static int kldrModMachOPreParseLoadCommands(KU8 *pbLoadCommands, const mach_hea *pcSections = 0; *pcbStringPool = 0; *pfCanLoad = K_TRUE; + *pLinkAddress = ~(KLDRADDR)0; while (cLeft-- > 0) { @@ -586,8 +598,6 @@ static int kldrModMachOPreParseLoadCommands(KU8 *pbLoadCommands, const mach_hea && ( u.pSeg32->fileoff > cbFile || (KU64)u.pSeg32->fileoff + u.pSeg32->filesize > cbFile)) return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; - if (!u.pSeg32->filesize && u.pSeg32->fileoff) - return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; if (u.pSeg32->vmsize < u.pSeg32->filesize) return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; if ((u.pSeg32->maxprot & u.pSeg32->initprot) != u.pSeg32->initprot) @@ -655,16 +665,24 @@ static int kldrModMachOPreParseLoadCommands(KU8 *pbLoadCommands, const mach_hea if (pSect->reserved2) /* (reserved 1 is indirect symbol table index)*/ return KLDR_ERR_MACHO_BAD_SECTION; *pfCanLoad = K_FALSE; - fFileBits = 0; + fFileBits = -1; /* __DATA.__got in the 64-bit mach_kernel has bits, any things without bits? */ break; + case S_MOD_INIT_FUNC_POINTERS: /** @todo this requires a query API or flag... (e.g. C++ constructors) */ + if (!(fOpenFlags & KLDRMOD_OPEN_FLAGS_FOR_INFO)) + return KLDR_ERR_MACHO_UNSUPPORTED_INIT_SECTION; + case S_MOD_TERM_FUNC_POINTERS: /** @todo this requires a query API or flag... (e.g. C++ destructors) */ + if (!(fOpenFlags & KLDRMOD_OPEN_FLAGS_FOR_INFO)) + return KLDR_ERR_MACHO_UNSUPPORTED_TERM_SECTION; + if (pSect->reserved1 || pSect->reserved2) + return KLDR_ERR_MACHO_BAD_SECTION; + fFileBits = 1; + break; /* ignored */ + case S_LITERAL_POINTERS: case S_INTERPOSING: case S_GB_ZEROFILL: - case S_MOD_INIT_FUNC_POINTERS: - return KLDR_ERR_MACHO_UNSUPPORTED_INIT_SECTION; - case S_MOD_TERM_FUNC_POINTERS: - return KLDR_ERR_MACHO_UNSUPPORTED_TERM_SECTION; + return KLDR_ERR_MACHO_UNSUPPORTED_SECTION; default: return KLDR_ERR_MACHO_UNKNOWN_SECTION; @@ -695,7 +713,7 @@ static int kldrModMachOPreParseLoadCommands(KU8 *pbLoadCommands, const mach_hea return KLDR_ERR_MACHO_BAD_SECTION; - /* count segments and strings */ + /* count segments and strings, calculate image link address. */ switch (pHdr->filetype) { case MH_OBJECT: @@ -711,8 +729,8 @@ static int kldrModMachOPreParseLoadCommands(KU8 *pbLoadCommands, const mach_hea break; /* a new segment? */ - if ( !cSegments - || kHlpStrNComp(pSect->segname, (pSect - 1)->segname, sizeof(pSect->segname))) + if ( !pchCurSegName + || kHlpStrNComp(pSect->segname, pchCurSegName, sizeof(pSect->segname))) { #if 0 /** @todo This doesn't work because of BSS. */ /* verify that the linker/assembler has ordered sections correctly. */ @@ -726,8 +744,13 @@ static int kldrModMachOPreParseLoadCommands(KU8 *pbLoadCommands, const mach_hea #endif /* ok. count it and the string. */ - cSegments++; + pchCurSegName = &pSect->segname[0]; cbStringPool += kHlpStrNLen(&pSect->segname[0], sizeof(pSect->segname)) + 1; + cSegments++; + + /* Link address lower? */ + if (*pLinkAddress > u.pSeg32->vmaddr) + *pLinkAddress = u.pSeg32->vmaddr; } break; } @@ -770,8 +793,6 @@ static int kldrModMachOPreParseLoadCommands(KU8 *pbLoadCommands, const mach_hea && ( u.pSeg64->fileoff > cbFile || u.pSeg64->fileoff + u.pSeg64->filesize > cbFile)) return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; - if (!u.pSeg64->filesize && u.pSeg64->fileoff) - return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; if (u.pSeg64->vmsize < u.pSeg64->filesize) return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; if ((u.pSeg64->maxprot & u.pSeg64->initprot) != u.pSeg64->initprot) @@ -839,24 +860,24 @@ static int kldrModMachOPreParseLoadCommands(KU8 *pbLoadCommands, const mach_hea if (pSect->reserved2) /* (reserved 1 is indirect symbol table index)*/ return KLDR_ERR_MACHO_BAD_SECTION; *pfCanLoad = K_FALSE; - fFileBits = 0; + fFileBits = -1; /* __DATA.__got in the 64-bit mach_kernel has bits, any things without bits? */ break; + case S_MOD_INIT_FUNC_POINTERS: /** @todo this requires a query API or flag... (e.g. C++ constructors) */ + if (!(fOpenFlags & KLDRMOD_OPEN_FLAGS_FOR_INFO)) + return KLDR_ERR_MACHO_UNSUPPORTED_INIT_SECTION; + case S_MOD_TERM_FUNC_POINTERS: /** @todo this requires a query API or flag... (e.g. C++ destructors) */ + if (!(fOpenFlags & KLDRMOD_OPEN_FLAGS_FOR_INFO)) + return KLDR_ERR_MACHO_UNSUPPORTED_TERM_SECTION; + if (pSect->reserved1 || pSect->reserved2) + return KLDR_ERR_MACHO_BAD_SECTION; + fFileBits = 1; + break; /* ignored */ + case S_LITERAL_POINTERS: case S_INTERPOSING: case S_GB_ZEROFILL: return KLDR_ERR_MACHO_UNSUPPORTED_SECTION; -#if 1 /** @todo this requires a query API or flag... */ - case S_MOD_INIT_FUNC_POINTERS: - return KLDR_ERR_MACHO_UNSUPPORTED_INIT_SECTION; - case S_MOD_TERM_FUNC_POINTERS: - return KLDR_ERR_MACHO_UNSUPPORTED_TERM_SECTION; -#else - case S_MOD_INIT_FUNC_POINTERS: - case S_MOD_TERM_FUNC_POINTERS: - fFileBits = 1; - break; /* ignored */ -#endif default: return KLDR_ERR_MACHO_UNKNOWN_SECTION; @@ -887,7 +908,7 @@ static int kldrModMachOPreParseLoadCommands(KU8 *pbLoadCommands, const mach_hea return KLDR_ERR_MACHO_BAD_SECTION; - /* count segments and strings */ + /* count segments and strings, calculate image link address. */ switch (pHdr->filetype) { case MH_OBJECT: @@ -903,8 +924,8 @@ static int kldrModMachOPreParseLoadCommands(KU8 *pbLoadCommands, const mach_hea break; /* a new segment? */ - if ( !cSegments - || kHlpStrNComp(pSect->segname, (pSect - 1)->segname, sizeof(pSect->segname))) + if ( !pchCurSegName + || kHlpStrNComp(pSect->segname, pchCurSegName, sizeof(pSect->segname))) { #if 0 /** @todo This doesn't work because of BSS. */ /* verify that the linker/assembler has ordered sections correctly. */ @@ -918,8 +939,13 @@ static int kldrModMachOPreParseLoadCommands(KU8 *pbLoadCommands, const mach_hea #endif /* ok. count it and the string. */ - cSegments++; + pchCurSegName = &pSect->segname[0]; cbStringPool += kHlpStrNLen(&pSect->segname[0], sizeof(pSect->segname)) + 1; + cSegments++; + + /* Link address lower? */ + if (*pLinkAddress > u.pSeg64->vmaddr) + *pLinkAddress = u.pSeg64->vmaddr; } break; } @@ -1091,15 +1117,15 @@ static int kldrModMachOParseLoadCommands(PKLDRMODMACHO pModMachO, char *pbStrin const segment_command_64_t *pSeg64; const symtab_command_t *pSymTab; } u; + const char *pchCurSegName = NULL; KU32 cLeft = pModMachO->Hdr.ncmds; KU32 cbLeft = pModMachO->Hdr.sizeofcmds; const KU8 *pb = pModMachO->pbLoadCommands; - int fFirstSegment = 1; PKLDRSEG pSeg = &pModMachO->pMod->aSegments[0]; PKLDRMODMACHOSEG pSegExtra = &pModMachO->aSegments[0]; PKLDRMODMACHOSECT pSectExtra = pModMachO->paSections; const KU32 cSegments = pModMachO->pMod->cSegments; - KU32 i; + KU32 i, c; while (cLeft-- > 0) { @@ -1118,7 +1144,7 @@ static int kldrModMachOParseLoadCommands(PKLDRMODMACHO pModMachO, char *pbStrin section_32_t *pFirstSect; KU32 cSectionsLeft; - pModMachO->LinkAddress = u.pSeg32->vmaddr; + kHlpAssert(u.pSeg32->vmaddr >= pModMachO->LinkAddress); /* * convert, validate and parse the sections. @@ -1161,8 +1187,8 @@ static int kldrModMachOParseLoadCommands(PKLDRMODMACHO pModMachO, char *pbStrin break; } - if ( fFirstSegment - || kHlpStrNComp(pSect->segname, (pSect - 1)->segname, sizeof(pSect->segname))) + if ( !pchCurSegName + || kHlpStrNComp(pSect->segname, pchCurSegName, sizeof(pSect->segname))) { /* close the previous segment */ if (pSegExtra != &pModMachO->aSegments[0]) @@ -1196,12 +1222,13 @@ static int kldrModMachOParseLoadCommands(PKLDRMODMACHO pModMachO, char *pbStrin pSeg->cbMapped = 0; pSeg->MapAddress = 0; + pSegExtra->iOrgSegNo = pSegExtra - &pModMachO->aSegments[0]; pSegExtra->cSections = 0; pSegExtra->paSections = pSectExtra; pSeg++; pSegExtra++; - fFirstSegment = 0; + pchCurSegName = &pSect->segname[0]; } else { @@ -1253,7 +1280,7 @@ static int kldrModMachOParseLoadCommands(PKLDRMODMACHO pModMachO, char *pbStrin section_64_t *pFirstSect; KU32 cSectionsLeft; - pModMachO->LinkAddress = u.pSeg64->vmaddr; + kHlpAssert(u.pSeg64->vmaddr >= pModMachO->LinkAddress); /* * convert, validate and parse the sections. @@ -1296,8 +1323,8 @@ static int kldrModMachOParseLoadCommands(PKLDRMODMACHO pModMachO, char *pbStrin break; } - if ( fFirstSegment - || kHlpStrNComp(pSect->segname, (pSect - 1)->segname, sizeof(pSect->segname))) + if ( !pchCurSegName + || kHlpStrNComp(pSect->segname, pchCurSegName, sizeof(pSect->segname))) { /* close the previous segment */ if (pSegExtra != &pModMachO->aSegments[0]) @@ -1331,12 +1358,13 @@ static int kldrModMachOParseLoadCommands(PKLDRMODMACHO pModMachO, char *pbStrin pSeg->cbMapped = 0; pSeg->MapAddress = 0; + pSegExtra->iOrgSegNo = pSegExtra - &pModMachO->aSegments[0]; pSegExtra->cSections = 0; pSegExtra->paSections = pSectExtra; pSeg++; pSegExtra++; - fFirstSegment = 0; + pchCurSegName = &pSect->segname[0]; } else { @@ -1409,6 +1437,37 @@ static int kldrModMachOParseLoadCommands(PKLDRMODMACHO pModMachO, char *pbStrin pSegExtra[-1].cSections = pSectExtra - pSegExtra[-1].paSections; /* + * Make sure the segments are sorted, or we'll get screwed further down. + */ + c = pSeg - &pModMachO->pMod->aSegments[0]; + pSeg = &pModMachO->pMod->aSegments[0]; + for (i = 0; i < c - 1; i++) + { + KLDRADDR LinkAddress = pSeg[i + 1].LinkAddress; + if (LinkAddress < pSeg[i].LinkAddress) + { + /* Gotta move the next segment, find the correct location. */ + KLDRMODMACHOSEG TmpSegExtra; + KLDRSEG TmpSeg; + KU32 j = i; + KU32 cShift = 1; + + while (j > 0 && LinkAddress < pSeg[j - 1].LinkAddress) + j--, cShift++; + + TmpSegExtra = pModMachO->aSegments[i + 1]; + kHlpMemMove(&pModMachO->aSegments[j + 1], &pModMachO->aSegments[j], + cShift * sizeof(pModMachO->aSegments[0])); + pModMachO->aSegments[j] = TmpSegExtra; + + TmpSeg = pSeg[i + 1]; + kHlpMemMove(&pSeg[j + 1], &pSeg[j], cShift * sizeof(pSeg[0])); + pSeg[j] = TmpSeg; + } + } + pSeg = &pModMachO->pMod->aSegments[c]; + + /* * Make the GOT segment if necessary. */ if (pModMachO->fMakeGot) @@ -1453,6 +1512,7 @@ static int kldrModMachOParseLoadCommands(PKLDRMODMACHO pModMachO, char *pbStrin pSeg->cbMapped = 0; pSeg->MapAddress = 0; + pSegExtra->iOrgSegNo = KU32_MAX; pSegExtra->cSections = 0; pSegExtra->paSections = NULL; } |