Index: /trunk/kLdr/Makefile.kmk
===================================================================
--- /trunk/kLdr/Makefile.kmk	(revision 2954)
+++ /trunk/kLdr/Makefile.kmk	(revision 2955)
@@ -100,4 +100,5 @@
 	kLdrDyldMod.c \
 	kLdrDyldOS.c \
+	kLdrErr.c \
 	kLdrHlp.c \
 	kLdrHlpHeap.c \
@@ -125,4 +126,7 @@
 kLdr_SOURCES.win64 = $(kLdr_SOURCES.win)
 
+kLdrErr.c_DEPS = $(PATH_TARGET)/kldrErrConsts.h
+kLdrErr.c_INCS = $(PATH_TARGET)
+
 #
 # The OS/2 stub program.
@@ -190,5 +194,17 @@
 
 
-# generate rules.
+# Generate rules.
 include $(PATH_KBUILD)/footer.kmk
 
+
+#
+# Generate case statements for kLdrErrStr().
+#
+$(PATH_TARGET)/kldrErrConsts.h: kLdr.h Makefile.kmk | $(call DIRDEP,$(PATH_TARGET))
+	$(RM) -f $@
+	$(SED) \
+		-e '/^#define  *\(KLDR_ERR_[^ ()]*\) .*$$/!d' \
+		-e 's/^#define  *\(KLDR_ERR_[^ ()]*\) .*$$/ERR_CONST(\1)/' \
+		-e '/KLDR_ERR_[^_]*_BASE/d' \
+		kLdr.h > $@
+
Index: /trunk/kLdr/kLdr-os2.def
===================================================================
--- /trunk/kLdr/kLdr-os2.def	(revision 2954)
+++ /trunk/kLdr/kLdr-os2.def	(revision 2955)
@@ -107,2 +107,6 @@
 ;    _kLdrDlFunc
 
+    ; Error APIs:
+    _kLdrErrStr
+
+
Index: /trunk/kLdr/kLdr-win.def
===================================================================
--- /trunk/kLdr/kLdr-win.def	(revision 2954)
+++ /trunk/kLdr/kLdr-win.def	(revision 2955)
@@ -106,2 +106,5 @@
 ;    _kLdrDlFunc
 
+    ; Error APIs:
+    kLdrErrStr
+
Index: /trunk/kLdr/kLdr.h
===================================================================
--- /trunk/kLdr/kLdr.h	(revision 2954)
+++ /trunk/kLdr/kLdr.h	(revision 2955)
@@ -1265,8 +1265,14 @@
 /** The sections aren't ordered by segment as expected by the loader. */
 #define KLDR_ERR_MACHO_BAD_SECTION_ORDER                    (KLDR_ERR_MACHO_BASE + 11)
+/** The image is 32-bit and contains 64-bit load commands or vise versa. */
+#define KLDR_ERR_MACHO_BIT_MIX                              (KLDR_ERR_MACHO_BASE + 12)
+/** The bad MH_OBJECT file. */
+#define KLDR_ERR_MACHO_BAD_OBJECT_FILE                      (KLDR_ERR_MACHO_BASE + 13)
 /** @} */
 
 /** End of the valid kLdr status codes. */
-#define KLDR_ERR_END                                        (KLDR_ERR_MACHO_BASE + 12)
+#define KLDR_ERR_END                                        (KLDR_ERR_MACHO_BASE + 14)
+
+const char *kLdrErrStr(int rc);
 
 /** @} */
Index: /trunk/kLdr/kLdrErr.c
===================================================================
--- /trunk/kLdr/kLdrErr.c	(revision 2955)
+++ /trunk/kLdr/kLdrErr.c	(revision 2955)
@@ -0,0 +1,55 @@
+/* $Id$ */
+/** @file
+ *
+ * kLdr - The Dynamic Loader, Error Code Methods.
+ *
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ *
+ * This file is part of kLdr.
+ *
+ * kLdr is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * kLdr is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with kLdr; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <kLdr.h>
+
+
+/**
+ * Translate the error code into a string containing 
+ * the error constant. 
+ * 
+ * @returns Read only string with the constant name.
+ * @param   rc      The error code.
+ */
+const char *kLdrErrStr(int rc)
+{
+    switch (rc)
+    {
+        case 0: return "SUCCESS";
+#define ERR_CONST(c) case c: return #c;
+#include "kldrErrConsts.h"
+#undef ERR_CONST
+        default:
+            break;
+    }
+    return "KLDR_ERR_UNKNOWN_ERROR";
+}
+
+
Index: /trunk/kLdr/kLdrHlp.h
===================================================================
--- /trunk/kLdr/kLdrHlp.h	(revision 2954)
+++ /trunk/kLdr/kLdrHlp.h	(revision 2955)
@@ -43,4 +43,6 @@
 /** Align a void * value. */
 #define KLDR_ALIGN_P(pv, align)     ( (void *)( ((uintptr_t)(pv) + ((align) - 1)) & ~(uintptr_t)((align) - 1) ) )
+/** Align a size_t value. */
+#define KLDR_ALIGN_ADDR(val, align) ( ((val) + ((align) - 1)) & ~(KLDRADDR)((align) - 1) )
 /** Number of elements in an array. */
 #define KLDR_ELEMENTS(a)            ( sizeof(a) / sizeof((a)[0]) )
@@ -239,4 +241,5 @@
 #endif
 
+size_t  kLdrHlpStrNLen(const char *psz, size_t cchMax);
 int     kLdrHlpMemIComp(const void *pv1, const void *pv2, size_t cb);
 int     kLdrHlpStrIComp(const char *pv1, const char *pv2);
Index: /trunk/kLdr/kLdrHlpStr.c
===================================================================
--- /trunk/kLdr/kLdrHlpStr.c	(revision 2954)
+++ /trunk/kLdr/kLdrHlpStr.c	(revision 2955)
@@ -78,4 +78,13 @@
 
     return pszRet;
+}
+
+
+size_t  kLdrHlpStrNLen(const char *psz, size_t cchMax)
+{
+    const char * const pszStart = psz;
+    while (*psz && cchMax--)
+        psz++;
+    return psz - pszStart;
 }
 
Index: /trunk/kLdr/kLdrModMachO.c
===================================================================
--- /trunk/kLdr/kLdrModMachO.c	(revision 2954)
+++ /trunk/kLdr/kLdrModMachO.c	(revision 2955)
@@ -99,4 +99,10 @@
     /** The link address. */
     KLDRADDR                LinkAddress;
+    /** The size of the mapped image. */
+    KLDRADDR                cbImage;
+    /** When set the load commands will be used when mapping / loading the bits.
+     * This is the case when segments are made up of sections that doesn't have
+     * proper ordering and/or aligning in the file alignment. */
+    int                     fMapUsingLoadCommands;
 
     /** Pointer to the load commands. (endian converted) */
@@ -353,4 +359,6 @@
         pModMachO->Hdr.reserved = 0;
     pModMachO->LinkAddress = 0;
+    pModMachO->cbImage = 0;
+    pModMachO->fMapUsingLoadCommands = 0;
     pModMachO->offSymbols = 0;
     pModMachO->cSymbols = 0;
@@ -408,4 +416,5 @@
     uint32_t cbLeft = pHdr->sizeofcmds;
     uint8_t *pb = pbLoadCommands;
+    int      cSegmentCommands = 0;
     int      fConvertEndian = pHdr->magic == IMAGE_MACHO32_SIGNATURE_OE
                            || pHdr->magic == IMAGE_MACHO64_SIGNATURE_OE;
@@ -447,4 +456,7 @@
                 if (u.pLoadCmd->cmdsize < sizeof(segment_command_32_t))
                     return KLDR_ERR_MACHO_BAD_LOAD_COMMAND;
+                if (    pHdr->magic != IMAGE_MACHO32_SIGNATURE_OE
+                    &&  pHdr->magic != IMAGE_MACHO32_SIGNATURE)
+                    return KLDR_ERR_MACHO_BIT_MIX;
                 if (fConvertEndian)
                 {
@@ -473,4 +485,8 @@
                 if (u.pSeg32->nsects * sizeof(section_32_t) > u.pLoadCmd->cmdsize - sizeof(segment_command_32_t))
                     return KLDR_ERR_MACHO_BAD_LOAD_COMMAND;
+                if (    pHdr->filetype == MH_OBJECT
+                    &&  cSegmentCommands > 0)
+                    return KLDR_ERR_MACHO_BAD_OBJECT_FILE;
+                cSegmentCommands++;
 
                 /* 
@@ -566,5 +582,5 @@
 
                             /* a new segment? */
-                            if (    pSect == pFirstSect
+                            if (    !cSegments
                                 ||  kLdrHlpStrNComp(pSect->segname, (pSect - 1)->segname, sizeof(pSect->segname)))
                             {
@@ -580,5 +596,5 @@
                                 /* ok. count it and the string. */
                                 cSegments++;
-                                cbStringPool += kLdrHlpStrLen(pSect->segname) + 1;
+                                cbStringPool += kLdrHlpStrNLen(&pSect->segname[0], sizeof(pSect->segname)) + 1;
                             }
                             break;
@@ -595,7 +611,8 @@
             }
 
-            case LC_SEGMENT_64:
-                /* copy 32-bit code */
+            /*case LC_SEGMENT_64:
+                 copy 32-bit code 
                 break;
+            */
 
             case LC_SYMTAB:
@@ -656,4 +673,5 @@
                 break;
 
+            case LC_SEGMENT_64:
             case LC_LOADFVMLIB:
             case LC_IDFVMLIB:
@@ -684,10 +702,18 @@
     }
 
-    /* be strict (for now). */
+    /* be strict. */
     if (cbLeft)
         return KLDR_ERR_MACHO_BAD_LOAD_COMMAND;
 
+    switch (pHdr->filetype)
+    {
+        case MH_OBJECT:
+            if (!cSegments)
+                return KLDR_ERR_MACHO_BAD_OBJECT_FILE;
+            break;
+    }
+
     *pcSegments = cSegments;
-    *pcbStringPool = cLeft;
+    *pcbStringPool = cbStringPool;
 
     return 0;
@@ -708,4 +734,148 @@
 static int  kldrModMachOParseLoadCommands(PKLDRMODMACHO pModMachO, char *pbStringPool, uint32_t cbStringPool)
 {
+    union
+    {
+        const uint8_t              *pb;
+        const load_command_t       *pLoadCmd;
+        const segment_command_32_t *pSeg32;
+        const segment_command_64_t *pSeg64;
+        const symtab_command_t     *pSymTab;
+    } u;
+    uint32_t cLeft = pModMachO->Hdr.ncmds;
+    uint32_t cbLeft = pModMachO->Hdr.sizeofcmds;
+    const uint8_t *pb = pModMachO->pbLoadCommands;
+    int fFirstSegment = 1;
+    PKLDRSEG pSeg = &pModMachO->pMod->aSegments[0];
+    const uint32_t cSegments = pModMachO->pMod->cSegments;
+    uint32_t i;
+
+    while (cLeft-- > 0)
+    {
+        u.pb = pb;
+        cbLeft -= u.pLoadCmd->cmdsize;
+        pb += u.pLoadCmd->cmdsize;
+
+        /*
+         * Convert endian if needed, parse and validate the command.
+         */
+        switch (u.pLoadCmd->cmd)
+        {
+            case LC_SEGMENT_32:
+            {
+                section_32_t *pSect;
+                section_32_t *pFirstSect;
+                uint32_t cSectionsLeft;
+
+                pModMachO->LinkAddress = u.pSeg32->vmaddr;
+
+                /* 
+                 * convert, validate and parse the sections. 
+                 */
+                cSectionsLeft = u.pSeg32->nsects;
+                pFirstSect = pSect = (section_32_t *)(u.pSeg32 + 1);
+                while (cSectionsLeft-- > 0)
+                {
+                    switch (pModMachO->Hdr.filetype)
+                    {
+                        case MH_OBJECT:
+                        {
+                            /* Don't load debug symbols. (test this) */
+                            if (pSect->flags & S_ATTR_DEBUG)
+                                break;
+
+                            if (    fFirstSegment
+                                ||  kLdrHlpStrNComp(pSect->segname, (pSect - 1)->segname, sizeof(pSect->segname)))
+                            {
+                                /* new segment. */
+                                pSeg->pvUser = NULL;
+                                pSeg->pchName = pbStringPool;
+                                pSeg->cchName = (uint32_t)kLdrHlpStrNLen(&pSect->segname[0], sizeof(pSect->sectname));
+                                kLdrHlpMemCopy(pbStringPool, &pSect->segname[0], pSeg->cchName);
+                                pbStringPool += pSeg->cchName;
+                                *pbStringPool++ = '\0';
+                                pSeg->SelFlat = 0;
+                                pSeg->Sel16bit = 0;
+                                pSeg->fFlags = 0;
+                                pSeg->enmProt = KLDRPROT_EXECUTE_WRITECOPY; /** @todo fixme! */
+                                pSeg->cb = pSect->size;
+                                pSeg->Alignment = (1 << pSect->align);
+                                pSeg->LinkAddress = pSect->addr;
+                                pSeg->offFile = pSect->offset ? pSect->offset : -1;
+                                pSeg->cbFile  = pSect->offset ? pSect->size : -1;
+                                pSeg->RVA = pSect->addr - pModMachO->LinkAddress;
+                                pSeg->cbMapped = 0;
+                                pSeg->MapAddress = 0;
+
+                                pSeg++;
+                                fFirstSegment = 0;
+                            }
+                            else if (!fFirstSegment)
+                            {
+                                /* update exiting segment */
+                                if (pSeg[-1].Alignment < (1 << pSect->align))
+                                    pSeg[-1].Alignment = (1 << pSect->align);
+                                if (pSect->addr < pSeg[-1].LinkAddress)
+                                    return KLDR_ERR_MACHO_BAD_SECTION; /** @todo move up! */
+
+                                if (    pSect->offset 
+                                    &&  pSeg[-1].cbFile == pSeg[-1].cb)
+                                {
+                                    if (    pSeg[-1].offFile + pSeg[-1].cbFile == pSect->offset
+                                        &&  pSeg[-1].cbFile == pSect->addr - pSeg[-1].LinkAddress)
+                                        pSeg[-1].cbFile = (off_t)(pSect->addr - pSeg[-1].LinkAddress) + pSect->size;
+                                    else
+                                    {
+                                        pSeg[-1].cbFile = pSeg[-1].offFile = -1;
+                                        pModMachO->fMapUsingLoadCommands = 1;
+                                    }
+                                }
+                                pSeg[-1].cb = pSect->addr - pSeg[-1].LinkAddress + pSect->size;
+
+                                /** @todo update the protection... */
+                            }
+                            break;
+                        }
+
+                        default:
+                            return KLDR_ERR_INVALID_PARAMETER;
+                    }
+
+                    /* next */
+                    pSect++;
+                }
+                break;
+            }
+
+            default:
+                break;
+        }
+    }
+
+    /* 
+     * Adjust mapping addresses calculating the image size.
+     */
+    pSeg = &pModMachO->pMod->aSegments[0];
+    switch (pModMachO->Hdr.filetype)
+    {
+        case MH_OBJECT:
+        {
+            KLDRADDR cb1;
+            size_t cb2;
+
+            for (i = 0; i < cSegments - 1; i++)
+            {
+                cb1 = pSeg[i + 1].LinkAddress - pSeg[i].LinkAddress;
+                cb2 = (size_t)cb1;
+                pSeg[i].cbMapped = cb2 == cb1 ? cb2 : ~(size_t)0;
+            }
+            cb1 = KLDR_ALIGN_ADDR(pSeg[i].cb, pSeg[i].Alignment);
+            cb2 = (size_t)cb1;
+            pSeg[i].cbMapped = cb2 == cb1 ? cb2 : ~(size_t)0;
+
+            pModMachO->cbImage = pSeg[i].RVA + cb1;
+            break;
+        }
+    }
+
     return 0;
 }
@@ -1978,10 +2148,6 @@
 static KLDRADDR kldrModMachOSize(PKLDRMOD pMod)
 {
-#if 0
     PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
-    return pModMachO->Hdrs.OptionalHeader.SizeOfImage;
-#else
-    return 0;
-#endif
+    return pModMachO->cbImage;
 }
 
Index: /trunk/kLdr/tstkLdrMod.c
===================================================================
--- /trunk/kLdr/tstkLdrMod.c	(revision 2954)
+++ /trunk/kLdr/tstkLdrMod.c	(revision 2955)
@@ -116,5 +116,5 @@
     rc = kLdrModGetBits(pMod, pvBits2, (uintptr_t)pvBits, BasicTestsGetImport, NULL);
     if (rc)
-        return Failure("failed to get image bits, rc=%d (a)", rc);
+        return Failure("failed to get image bits, rc=%d (%s) (a)", rc, kLdrErrStr(rc));
     if (TestMemComp(pvBits2, pvBits, cbImage))
         return Failure("relocation test failed, mismatching bits (a)");
@@ -125,8 +125,8 @@
     rc = kLdrModRelocateBits(pMod, pvBits2, 0x1000, (uintptr_t)pvBits, BasicTestsGetImport, NULL);
     if (rc)
-        return Failure("failed to relocate, rc=%d (b1)");
+        return Failure("failed to relocate, rc=%d (%s) (b1)", rc, kLdrErrStr(rc));
     rc = kLdrModRelocateBits(pMod, pvBits2, (uintptr_t)pvBits, 0x1000, BasicTestsGetImport, NULL);
     if (rc)
-        return Failure("failed to relocate, rc=%d (b2)");
+        return Failure("failed to relocate, rc=%d (%s) (b2)", rc, kLdrErrStr(rc));
     if (TestMemComp(pvBits2, pvBits, cbImage))
         return Failure("relocation test failed, mismatching bits (b)");
@@ -138,9 +138,9 @@
     rc = kLdrModRelocateBits(pMod, pvBits, 0x1000000, (uintptr_t)pvBits, BasicTestsGetImport, NULL);
     if (rc)
-        return Failure("failed to relocate, rc=%d (c1)");
+        return Failure("failed to relocate, rc=%d (%s) (c1)", rc, kLdrErrStr(rc));
     memset(pvBits2, 0xfe, cbImage);
     rc = kLdrModGetBits(pMod, pvBits2, 0x1000000, BasicTestsGetImport, NULL);
     if (rc)
-        return Failure("failed to get image bits, rc=%d (c1)", rc);
+        return Failure("failed to get image bits, rc=%d (%s) (c1)", rc, kLdrErrStr(rc));
     if (TestMemComp(pvBits2, pvBits, cbImage))
         return Failure("relocation test failed, mismatching bits (c1)");
@@ -149,9 +149,9 @@
     rc = kLdrModRelocateBits(pMod, pvBits, ~(uintptr_t)0x1010000, 0x1000000, BasicTestsGetImport, NULL);
     if (rc)
-        return Failure("failed to relocate, rc=%d (c2)");
+        return Failure("failed to relocate, rc=%d (%s) (c2)", rc, kLdrErrStr(rc));
     memset(pvBits2, 0xef, cbImage);
     rc = kLdrModGetBits(pMod, pvBits2, ~(uintptr_t)0x1010000, BasicTestsGetImport, NULL);
     if (rc)
-        return Failure("failed to get image bits, rc=%d (c2)", rc);
+        return Failure("failed to get image bits, rc=%d (%s) (c2)", rc, kLdrErrStr(rc));
     if (TestMemComp(pvBits2, pvBits, cbImage))
         return Failure("relocation test failed, mismatching bits (c2)");
@@ -160,9 +160,9 @@
     rc = kLdrModRelocateBits(pMod, pvBits, MY_BASEADDRESS, ~(uintptr_t)0x1010000, BasicTestsGetImport, NULL);
     if (rc)
-        return Failure("failed to relocate, rc=%d (c3)");
+        return Failure("failed to relocate, rc=%d (%s) (c3)", rc, kLdrErrStr(rc));
     memset(pvBits2, 0xef, cbImage);
     rc = kLdrModGetBits(pMod, pvBits2, MY_BASEADDRESS, BasicTestsGetImport, NULL);
     if (rc)
-        return Failure("failed to get image bits, rc=%d (c3)", rc);
+        return Failure("failed to get image bits, rc=%d (%s) (c3)", rc, kLdrErrStr(rc));
     if (TestMemComp(pvBits2, pvBits, cbImage))
         return Failure("relocation test failed, mismatching bits (c3)");
@@ -171,9 +171,9 @@
     rc = kLdrModRelocateBits(pMod, pvBits, ~(uintptr_t)0 / 2 - 0x10000, MY_BASEADDRESS, BasicTestsGetImport, NULL);
     if (rc)
-        return Failure("failed to relocate, rc=%d (c4)");
+        return Failure("failed to relocate, rc=%d %(s) (c4)", rc, kLdrErrStr(rc));
     memset(pvBits2, 0xdc, cbImage);
     rc = kLdrModGetBits(pMod, pvBits2, ~(uintptr_t)0 / 2 - 0x10000, BasicTestsGetImport, NULL);
     if (rc)
-        return Failure("failed to get image bits, rc=%d (c4)", rc);
+        return Failure("failed to get image bits, rc=%d (%s) (c4)", rc, kLdrErrStr(rc));
     if (TestMemComp(pvBits2, pvBits, cbImage))
         return Failure("relocation test failed, mismatching bits (c4)");
@@ -182,9 +182,9 @@
     rc = kLdrModRelocateBits(pMod, pvBits, (uintptr_t)pvBits, ~(uintptr_t)0 / 2 - 0x10000, BasicTestsGetImport, NULL);
     if (rc)
-        return Failure("failed to relocate, rc=%d (c5)");
+        return Failure("failed to relocate, rc=%d (%s) (c5)", rc, kLdrErrStr(rc));
     memset(pvBits2, 0xcd, cbImage);
     rc = kLdrModGetBits(pMod, pvBits2, (uintptr_t)pvBits, BasicTestsGetImport, NULL);
     if (rc)
-        return Failure("failed to get image bits, rc=%d (c5)", rc);
+        return Failure("failed to get image bits, rc=%d (%s) (c5)", rc, kLdrErrStr(rc));
     if (TestMemComp(pvBits2, pvBits, cbImage))
         return Failure("relocation test failed, mismatching bits (c5)");
@@ -216,5 +216,5 @@
                                 &uValue2, &fKind2);
         if (rc)
-            return Failure("Couldn't find symbol %#x (%.*s) by ordinal. rc=%d", iSymbol, cchSymbol, pchSymbol, rc);
+            return Failure("Couldn't find symbol %#x (%.*s) by ordinal. rc=%d (%s)", iSymbol, cchSymbol, pchSymbol, rc, kLdrErrStr(rc));
         if (uValue != uValue2)
             return Failure("Symbol %#x (%.*s): Value mismatch %016" PRI_KLDRADDR " != %016" PRI_KLDRADDR " (enum!=query/ord)  pvBits=%p",
@@ -231,5 +231,5 @@
                                 NULL, NULL, &uValue2, &fKind2);
         if (rc)
-            return Failure("Couldn't find symbol %#x (%.*s) by name. rc=%d", iSymbol, cchSymbol, pchSymbol, rc);
+            return Failure("Couldn't find symbol %#x (%.*s) by name. rc=%d (%s)", iSymbol, cchSymbol, pchSymbol, rc, kLdrErrStr(rc));
         if (uValue != uValue2)
             return Failure("Symbol %#x (%.*s): Value mismatch %016" PRI_KLDRADDR " != %016" PRI_KLDRADDR " (enum!=query/name) pvBits=%p",
@@ -292,5 +292,5 @@
         rc = kLdrModGetImport(pMod, pvBits, i, szImportModule, sizeof(szImportModule));
         if (rc)
-            return Failure("failed to get import module name, rc=%d. (%.260s)", rc, szImportModule);
+            return Failure("failed to get import module name, rc=%d (%s). (%.260s)", rc, kLdrErrStr(rc), szImportModule);
         printf("import #%d: '%s'\n", i, szImportModule);
     }
@@ -305,5 +305,5 @@
     rc = kLdrModGetStackInfo(pMod, pvBits, MY_BASEADDRESS, &StackInfo);
     if (rc)
-        return Failure("kLdrModGetStackInfo failed with rc=%d", rc);
+        return Failure("kLdrModGetStackInfo failed with rc=%d (%s)", rc, kLdrErrStr(rc));
     printf("Stack: Address=%016" PRI_KLDRADDR "   LinkAddress=%016" PRI_KLDRADDR "\n"
            "       cbStack=%016" PRI_KLDRSIZE " cbStackThread=%016" PRI_KLDRSIZE "\n",
@@ -324,5 +324,5 @@
     rc = kLdrModQueryMainEntrypoint(pMod, pvBits, MY_BASEADDRESS, &MainEPAddress);
     if (rc)
-        return Failure("kLdrModQueryMainEntrypoint failed with rc=%d", rc);
+        return Failure("kLdrModQueryMainEntrypoint failed with rc=%d (%s)", rc, kLdrErrStr(rc));
     printf("Entrypoint: %016" PRI_KLDRADDR "\n", MainEPAddress);
     if (MainEPAddress == ~(KLDRADDR)42)
@@ -342,8 +342,8 @@
         printf("NO Debugger Information\n");
     else
-        return Failure("kLdrModHasDbgInfo failed with rc=%d", rc);
+        return Failure("kLdrModHasDbgInfo failed with rc=%d (%s)", rc, kLdrErrStr(rc));
     rc = kLdrModEnumDbgInfo(pMod, pvBits, BasicTestEnumDbgInfoCallback, NULL);
     if (rc)
-        return Failure("kLdrModEnumDbgInfo failed with rc=%d", rc);
+        return Failure("kLdrModEnumDbgInfo failed with rc=%d (%s)", rc, kLdrErrStr(rc));
 
 
@@ -381,5 +381,5 @@
     rc = kLdrModEnumSymbols(pMod, pvBits, MY_BASEADDRESS, 0, BasicTestsEnumSymCallback, pvBits);
     if (rc)
-        return Failure("kLdrModEnumSymbols failed with rc=%d", rc);
+        return Failure("kLdrModEnumSymbols failed with rc=%d (%s)", rc, kLdrErrStr(rc));
 
 
@@ -490,5 +490,5 @@
     rc = kLdrModGetBits(pMod, pvBits, (uintptr_t)pvBits, BasicTestsGetImport, NULL);
     if (rc)
-        return Failure("failed to get image bits, rc=%d", rc);
+        return Failure("failed to get image bits, rc=%d (%s)", rc, kLdrErrStr(rc));
 
     /*
@@ -525,26 +525,26 @@
     rc = kLdrModFixupMapping(pMod, BasicTestsGetImport, NULL);
     if (rc)
-        return Failure("kLdrModFixupMapping (a) failed, rc=%d", rc);
+        return Failure("kLdrModFixupMapping (a) failed, rc=%d (%s)", rc, kLdrErrStr(rc));
 
     rc = kLdrModReload(pMod);
     if (rc)
-        return Failure("kLdrModReload (a) failed, rc=%d", rc);
+        return Failure("kLdrModReload (a) failed, rc=%d (%s)", rc, kLdrErrStr(rc));
 
     rc = kLdrModReload(pMod);
     if (rc)
-        return Failure("kLdrModReload (b) failed, rc=%d", rc);
+        return Failure("kLdrModReload (b) failed, rc=%d (%s)", rc, kLdrErrStr(rc));
 
     rc = kLdrModFixupMapping(pMod, BasicTestsGetImport, NULL);
     if (rc)
-        return Failure("kLdrModFixupMapping (b) failed, rc=%d", rc);
+        return Failure("kLdrModFixupMapping (b) failed, rc=%d (%s)", rc, kLdrErrStr(rc));
 
     rc = kLdrModAllocTLS(pMod);
     if (rc)
-        return Failure("kLdrModAllocTLS (a) failed, rc=%d", rc);
+        return Failure("kLdrModAllocTLS (a) failed, rc=%d (%s)", rc, kLdrErrStr(rc));
     kLdrModFreeTLS(pMod);
 
     rc = kLdrModAllocTLS(pMod);
     if (rc)
-        return Failure("kLdrModAllocTLS (b) failed, rc=%d", rc);
+        return Failure("kLdrModAllocTLS (b) failed, rc=%d (%s)", rc, kLdrErrStr(rc));
     kLdrModFreeTLS(pMod);
 
@@ -555,5 +555,5 @@
     rc = BasicTestsSub2(pMod, NULL);
     if (rc)
-        return Failure("BasicTestsSub2 in Map2 failed, rc=%d", rc);
+        return Failure("BasicTestsSub2 in Map2 failed, rc=%d (%s)", rc, kLdrErrStr(rc));
     return 0;
 }
@@ -570,10 +570,10 @@
     rc = kLdrModMap(pMod);
     if (rc)
-        return Failure("kLdrModMap failed, rc=%d", rc);
+        return Failure("kLdrModMap failed, rc=%d (%s)", rc, kLdrErrStr(rc));
     rc = BasicTestsSubMap2(pMod);
     rc2 = kLdrModUnmap(pMod);
     if (rc2)
     {
-        Failure("kLdrModUnmap failed, rc=%d", rc2);
+        Failure("kLdrModUnmap failed, rc=%d (%s)", rc2, kLdrErrStr(rc2));
         rc = rc ? rc : rc2;
     }
@@ -603,10 +603,10 @@
         rc2 = kLdrModClose(pMod);
         if (rc2)
-            Failure("failed to close '%s', rc=%d", pszFilename, rc);
+            Failure("failed to close '%s', rc=%d (%s)", pszFilename, rc, kLdrErrStr(rc));
         if (rc2 && !rc)
             rc = rc2;
     }
     else
-        Failure("Failed to open '%s', rc=%d", pszFilename, rc);
+        Failure("Failed to open '%s', rc=%d (%s)", pszFilename, rc, kLdrErrStr(rc));
     return rc ? 1 : 0;
 }
