Index: /trunk/src/VBox/ValidationKit/bootsectors/bs3kit/Makefile.kmk
===================================================================
--- /trunk/src/VBox/ValidationKit/bootsectors/bs3kit/Makefile.kmk	(revision 58647)
+++ /trunk/src/VBox/ValidationKit/bootsectors/bs3kit/Makefile.kmk	(revision 58648)
@@ -40,4 +40,9 @@
 VBoxBs3Linker_TEMPLATE = VBoxBldProg
 VBoxBs3Linker_SOURCES  = $(VBOX_PATH_BS3KIT_SRC)/VBoxBs3Linker.cpp
+
+# 64-bit relocation conversion tool
+BLDPROGS += VBoxBs3ObjConverter
+VBoxBs3ObjConverter_TEMPLATE = VBoxBldProg
+VBoxBs3ObjConverter_SOURCES  = $(VBOX_PATH_BS3KIT_SRC)/VBoxBs3ObjConverter.cpp
 
 # Dummy CP "linker" tool.
Index: /trunk/src/VBox/ValidationKit/bootsectors/bs3kit/VBoxBs3ObjConverter.cpp
===================================================================
--- /trunk/src/VBox/ValidationKit/bootsectors/bs3kit/VBoxBs3ObjConverter.cpp	(revision 58647)
+++ /trunk/src/VBox/ValidationKit/bootsectors/bs3kit/VBoxBs3ObjConverter.cpp	(revision 58648)
@@ -36,4 +36,6 @@
 #include <iprt/assert.h>
 
+#include <iprt/formats/elf64.h>
+
 
 /*********************************************************************************************************************************
@@ -60,18 +62,203 @@
     if (!pFile)
         fprintf(stderr, "error: Failed to open '%s' for %s: %s (%d)\n",
-                fWrite ? "writing" : "reading", strerror(errno), errno);
+                pszFile, fWrite ? "writing" : "reading", strerror(errno), errno);
     return pFile;
 }
 
 
-static int readfile(const char *pszFile, void **ppvFile, size_t *pcbFile)
-{
-
-}
-
-
-static int writefile(const char *pszFile, void *pvFile, size_t cbFile)
-{
-
+/**
+ * Read the given file into memory.
+ *
+ * @returns true on success, false on failure.
+ * @param   pszFile     The file to read.
+ * @param   ppvFile     Where to return the memory.
+ * @param   pcbFile     Where to return the size.
+ */
+static bool readfile(const char *pszFile, void **ppvFile, size_t *pcbFile)
+{
+    FILE *pFile = openfile(pszFile, false);
+    if (pFile)
+    {
+        /*
+         * Figure the size.
+         */
+        if (fseek(pFile, SEEK_END, 0) == 0)
+        {
+            long cbFile = ftell(pFile);
+            if (cbFile > 0)
+            {
+                if (fseek(pFile, SEEK_SET, 0) == 0)
+                {
+                    /*
+                     * Allocate and read content.
+                     */
+                    void *pvFile = malloc((size_t)cbFile);
+                    if (pvFile)
+                    {
+                        if (fread(pvFile, cbFile, 1, pFile) == 1)
+                        {
+                            *ppvFile = pvFile;
+                            *pcbFile = (size_t)cbFile;
+                            fclose(pFile);
+                            return true;
+                        }
+                        free(pvFile);
+                        fprintf(stderr, "error: fread failed in '%s': %s (%d)\n", pszFile, strerror(errno), errno);
+                    }
+                    else
+                        fprintf(stderr, "error: failed to allocate %ld bytes of memory for '%s'\n", cbFile, pszFile);
+                }
+                else
+                    fprintf(stderr, "error: fseek #2 failed in '%s': %s (%d)\n", pszFile, strerror(errno), errno);
+            }
+            else
+                fprintf(stderr, "error: ftell failed in '%s': %s (%d)\n", pszFile, strerror(errno), errno);
+        }
+        else
+            fprintf(stderr, "error: fseek #1 failed in '%s': %s (%d)\n", pszFile, strerror(errno), errno);
+        fclose(pFile);
+    }
+    return false;
+}
+
+
+/**
+ * Write the given file into memory.
+ *
+ * @returns true on success, false on failure.
+ * @param   pszFile     The file to write.
+ * @param   pvFile      Where to return the memory.
+ * @param   cbFile      Where to return the size.
+ */
+static bool writefile(const char *pszFile, void const *pvFile, size_t cbFile)
+{
+    remove(pszFile);
+
+    int rc = -1;
+    FILE *pFile = openfile(pszFile, true);
+    if (pFile)
+    {
+        if (fwrite(pvFile, cbFile, 1, pFile) == 1)
+        {
+            fclose(pFile);
+            return true;
+        }
+        fprintf(stderr, "error: fwrite failed in '%s': %s (%d)\n", pszFile, strerror(errno), errno);
+        fclose(pFile);
+    }
+    return false;
+}
+
+
+/**
+ * Reports an error and returns false.
+ *
+ * @returns false
+ * @param   pszFile             The filename.
+ * @param   pszFormat           The message format string.
+ * @param   ...                 Format arguments.
+ */
+static bool error(const char *pszFile, const char *pszFormat, ...)
+{
+    fprintf(stderr, "error: %s: ", pszFile);
+    va_list va;
+    va_start(va, pszFormat);
+    vfprintf(stderr, pszFormat, va);
+    va_end(va);
+    return false;
+}
+
+
+static bool convertelf(const char *pszFile, uint8_t *pbFile, size_t cbFile)
+{
+    /*
+     * Validate the header.
+     */
+    Elf64_Ehdr const *pEhdr = (Elf64_Ehdr const *)pbFile;
+    if (   pEhdr->e_ident[EI_CLASS] != ELFCLASS64
+        || pEhdr->e_ident[EI_DATA]  != ELFDATA2LSB
+        || pEhdr->e_ehsize          != sizeof(Elf64_Ehdr)
+        || pEhdr->e_shentsize       != sizeof(Elf64_Shdr)
+        || pEhdr->e_version         != EV_CURRENT )
+        return error(pszFile, "Unsupported ELF config\n");
+    if (pEhdr->e_type != ET_REL)
+        return error(pszFile, "Expected relocatable ELF file (e_type=%d)\n", pEhdr->e_type);
+    if (pEhdr->e_machine != EM_X86_64)
+        return error(pszFile, "Expected relocatable ELF file (e_type=%d)\n", pEhdr->e_machine);
+
+#if 0
+    if (    pEhdr->e_phoff < pEhdr->e_ehsize
+        &&  !(pEhdr->e_phoff && pEhdr->e_phnum)
+        &&  pEhdr->e_phnum)
+    {
+        Log(("RTLdrELF: %s: The program headers overlap with the ELF header! e_phoff=" FMT_ELF_OFF "\n",
+             pszLogName, pEhdr->e_phoff));
+        return VERR_BAD_EXE_FORMAT;
+    }
+    if (    pEhdr->e_phoff + pEhdr->e_phnum * pEhdr->e_phentsize > cbRawImage
+        ||  pEhdr->e_phoff + pEhdr->e_phnum * pEhdr->e_phentsize < pEhdr->e_phoff)
+    {
+        Log(("RTLdrELF: %s: The program headers extends beyond the file! e_phoff=" FMT_ELF_OFF " e_phnum=" FMT_ELF_HALF "\n",
+             pszLogName, pEhdr->e_phoff, pEhdr->e_phnum));
+        return VERR_BAD_EXE_FORMAT;
+    }
+
+
+    if (    pEhdr->e_shoff < pEhdr->e_ehsize
+        &&  !(pEhdr->e_shoff && pEhdr->e_shnum))
+    {
+        Log(("RTLdrELF: %s: The section headers overlap with the ELF header! e_shoff=" FMT_ELF_OFF "\n",
+             pszLogName, pEhdr->e_shoff));
+        return VERR_BAD_EXE_FORMAT;
+    }
+    if (    pEhdr->e_shoff + pEhdr->e_shnum * pEhdr->e_shentsize > cbRawImage
+        ||  pEhdr->e_shoff + pEhdr->e_shnum * pEhdr->e_shentsize < pEhdr->e_shoff)
+    {
+        Log(("RTLdrELF: %s: The section headers extends beyond the file! e_shoff=" FMT_ELF_OFF " e_shnum=" FMT_ELF_HALF "\n",
+             pszLogName, pEhdr->e_shoff, pEhdr->e_shnum));
+        return VERR_BAD_EXE_FORMAT;
+    }
+
+    if (pEhdr->e_shstrndx == 0 || pEhdr->e_shstrndx > pEhdr->e_shnum)
+    {
+        Log(("RTLdrELF: %s: The section headers string table is out of bounds! e_shstrndx=" FMT_ELF_HALF " e_shnum=" FMT_ELF_HALF "\n",
+             pszLogName, pEhdr->e_shstrndx, pEhdr->e_shnum));
+        return VERR_BAD_EXE_FORMAT;
+    }
+#endif
+
+    return true;
+}
+
+
+/**
+ * Does the convertion using convertelf and convertcoff.
+ *
+ * @returns exit code (0 on success, non-zero on failure)
+ * @param   pszFile     The file to convert.
+ */
+static int convertit(const char *pszFile)
+{
+    void  *pvFile;
+    size_t cbFile;
+    if (readfile(pszFile, &pvFile, &cbFile))
+    {
+        bool fRc = false;
+        uint8_t *pbFile = (uint8_t *)pvFile;
+        if (   cbFile > sizeof(Elf64_Ehdr)
+            && pbFile[0] == ELFMAG0
+            && pbFile[1] == ELFMAG1
+            && pbFile[2] == ELFMAG2
+            && pbFile[3] == ELFMAG3)
+            fRc = convertelf(pszFile, pbFile, cbFile);
+        else
+            fprintf(stderr, "error: Don't recognize format of '%s'\n", pszFile);
+        if (fRc)
+            fRc = writefile(pszFile, pvFile, cbFile);
+        free(pvFile);
+        if (fRc)
+            return 0;
+    }
+    return 1;
 }
 
@@ -94,5 +281,5 @@
                 pszOpt--;
                 if (!strcmp(pszOpt, "--verbose"))
-                    pszOpt = 'v';
+                    pszOpt = "v";
                 else if (!strcmp(pszOpt, "--version"))
                     pszOpt = "V";
@@ -102,5 +289,4 @@
                 {
                     fprintf(stderr, "syntax errro: Unknown options '%s'\n", pszOpt);
-                    free(paInputs);
                     return 2;
                 }
@@ -133,4 +319,7 @@
              * File to convert.  Do the job right away.
              */
+            rcExit = convertit(argv[i]);
+            if (rcExit != 0)
+                break;
         }
     }
Index: /trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-docs.c
===================================================================
--- /trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-docs.c	(revision 58647)
+++ /trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-docs.c	(revision 58648)
@@ -41,7 +41,8 @@
  * in separate files and compiled/assembled into libraries, so the linker will
  * only include exactly what is needed.  The current linker is the OpenWatcom
- * one, wlink, that we're already using when building the BIOSes.  It's possible
- * that we might be able to convince the binutils ELF linker to do the job
- * eventually,
+ * one, wlink, that we're already using when building the BIOSes.  If it wasn't
+ * for the segment/selector fixups in 16-bit code (mostly), maybe we could
+ * convince the ELF linker from GNU binutils to do the job too (with help from
+ * the ).
  *
  *
