Procházet zdrojové kódy

HPCC-13580 Support ELF format resource without binutils

Signed-off-by: Gavin Halliday <gavin.halliday@lexisnexis.com>
Gavin Halliday před 10 roky
rodič
revize
b374187ee6

+ 73 - 19
common/dllserver/thorplugin.cpp

@@ -29,6 +29,10 @@
 #include <mach-o/getsect.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
+#elif !defined(_WIN32)
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <elf.h>
 #endif
 
 #include "thorplugin.hpp"
@@ -201,7 +205,7 @@ bool HelperDll::getResource(size32_t & len, const void * & data, const char * ty
     if (!data)
     {
         if (trace)
-            printf("Failed to locate symbol %s", symName.str());
+            printf("Failed to locate symbol %s\n", symName.str());
         return false;
     }
     byte bom;
@@ -245,6 +249,67 @@ static void secscan (bfd *file, sec_ptr sec, void *userParam)
 }
 #endif
 
+static bool getResourceFromMappedFile(const char * filename, const byte * start_addr, MemoryBuffer &data, const char * type, unsigned id)
+{
+#if defined(_WIN32) || defined (_USE_BINUTILS)
+    throwUnexpected();
+#elif defined(__APPLE__)
+    VStringBuffer sectname("%s_%u", type, id);
+    // The first bytes are the Mach-O header
+    const struct mach_header_64 *mh = (const struct mach_header_64 *) start_addr;
+    if (mh->magic != MH_MAGIC_64)
+    {
+        DBGLOG("Failed to extract resource %s: Does not appear to be a Mach-O 64-bit binary", filename);
+        return false;
+    }
+
+    unsigned long len = 0;
+    unsigned char *data2 = getsectiondata(mh, "__TEXT", sectname.str(), &len);
+    data.append(len, data2);
+    return true;
+#else
+    // The first bytes are the ELF header
+    const Elf64_Ehdr * hdr = (const Elf64_Ehdr *) start_addr;
+    if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0)
+    {
+        DBGLOG("Failed to extract resource %s: Does not appear to be a ELF binary", filename);
+        return false;
+    }
+    if (hdr->e_ident[EI_CLASS] != ELFCLASS64)
+    {
+        DBGLOG("Failed to extract resource %s: Does not appear to be a ELF 64-bit binary", filename);
+        return false;
+    }
+
+    //Check that there is a symbol table for the sections.
+    if (hdr->e_shstrndx == SHN_UNDEF)
+    {
+        DBGLOG("Failed to extract resource %s: Does include a section symbol table", filename);
+        return false;
+    }
+
+    //Now walk the sections comparing the section names
+    Elf64_Half numSections = hdr->e_shnum;
+    const Elf64_Shdr * sectionHeaders = reinterpret_cast<const Elf64_Shdr *>(start_addr + hdr->e_shoff);
+    const Elf64_Shdr & symbolTableSection = sectionHeaders[hdr->e_shstrndx];
+    const char * symbolTable = (const char *)start_addr + symbolTableSection.sh_offset;
+    VStringBuffer sectname("%s_%u", type, id);
+    for (unsigned iSect= 0; iSect < numSections; iSect++)
+    {
+        const Elf64_Shdr & section = sectionHeaders[iSect];
+        const char * sectionName = symbolTable + section.sh_name;
+        if (streq(sectionName, sectname))
+        {
+            data.append(section.sh_size, start_addr + section.sh_offset);
+            return true;
+        }
+    }
+
+    DBGLOG("Failed to extract resource %s: Does include a matching entry", filename);
+    return false;
+#endif
+}
+
 extern bool getResourceFromFile(const char *filename, MemoryBuffer &data, const char * type, unsigned id)
 {
 #ifdef _WIN32
@@ -277,8 +342,7 @@ extern bool getResourceFromFile(const char *filename, MemoryBuffer &data, const
         bfd_close (file);
    }
    return data.length() != 0;
-#elif defined(__APPLE__)
-    unsigned long len = 0;
+#else
     struct stat stat_buf;
     VStringBuffer sectname("%s_%u", type, id);
     int fd = open(filename, O_RDONLY);
@@ -287,31 +351,21 @@ extern bool getResourceFromFile(const char *filename, MemoryBuffer &data, const
         DBGLOG("Failed to load library %s: %d", filename, errno);
         return false;
     }
+
+    bool ok = false;
     __uint64 size = stat_buf.st_size;
-    byte *start_addr = (byte *) mmap(0, size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
+    const byte *start_addr = (const byte *) mmap(0, size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
     if (start_addr == MAP_FAILED)
     {
         DBGLOG("Failed to load library %s: %d", filename, errno);
     }
     else
     {
-        // The first bytes are the Mach-O header
-        struct mach_header_64 *mh = (struct mach_header_64 *) start_addr;
-        if (mh->magic != MH_MAGIC_64)
-        {
-            DBGLOG("Failed to load library %s: Does not appear to be a Mach-O 64-bit binary", filename);
-        }
-        else
-        {
-            unsigned char *data2 = getsectiondata(mh, "__TEXT", sectname.str(), &len);
-            data.append(len, data2);
-        }
-        munmap(start_addr, size);
+        ok = getResourceFromMappedFile(filename, start_addr, data, type, id);
+        munmap((void *)start_addr, size);
     }
     close(fd);
-    return len != 0;
-#else
-    UNIMPLEMENTED;
+    return ok;
 #endif
 }
 

+ 13 - 13
ecl/eclccserver/eclccserver.cpp

@@ -390,20 +390,20 @@ class EclccCompileThread : public CInterface, implements IPooledThread, implemen
                 realdllfilename.append(SharedObjectPrefix).append(wuid).append(SharedObjectExtension);
 
                 StringBuffer wuXML;
-                if (getWorkunitXMLFromFile(realdllfilename, wuXML))
+                if (!getWorkunitXMLFromFile(realdllfilename, wuXML))
+                    throw makeStringException(999, "Failed to extract workunit from query dll");
+
+                Owned<ILocalWorkUnit> embeddedWU = createLocalWorkUnit();
+                embeddedWU->loadXML(wuXML);
+                queryExtendedWU(workunit)->copyWorkUnit(embeddedWU, true);
+                workunit->setIsClone(false);
+                SCMStringBuffer jobname;
+                if (embeddedWU->getJobName(jobname).length()) //let ECL win naming job during initial compile
+                    workunit->setJobName(jobname.str());
+                if (!workunit->getDebugValueBool("obfuscateOutput", false))
                 {
-                    Owned<ILocalWorkUnit> embeddedWU = createLocalWorkUnit();
-                    embeddedWU->loadXML(wuXML);
-                    queryExtendedWU(workunit)->copyWorkUnit(embeddedWU, true);
-                    workunit->setIsClone(false);
-                    SCMStringBuffer jobname;
-                    if (embeddedWU->getJobName(jobname).length()) //let ECL win naming job during initial compile
-                        workunit->setJobName(jobname.str());
-                    if (!workunit->getDebugValueBool("obfuscateOutput", false))
-                    {
-                        Owned<IWUQuery> query = workunit->updateQuery();
-                        query->setQueryText(eclQuery.s.str());
-                    }
+                    Owned<IWUQuery> query = workunit->updateQuery();
+                    query->setQueryText(eclQuery.s.str());
                 }
 
                 createUNCFilename(realdllfilename.str(), dllurl);

+ 10 - 2
ecl/hqlcpp/hqlres.cpp

@@ -544,9 +544,17 @@ bool ResourceManager::flush(StringBuffer &filename, const char *basename, bool f
         const char *type = s.type.str();
         unsigned id = s.id;
         VStringBuffer binfile("%s_%s_%u.bin", filename.str(), type, id);
+        VStringBuffer label("%s_%u_txt_start", type, id);
+#if defined(__APPLE__)
         fprintf(f, " .section __TEXT,%s_%u\n", type, id);
-        fprintf(f, " .global _%s_%u_txt_start\n", type, id);  // For some reason apple needs a leading underbar and linux does not
-        fprintf(f, "_%s_%u_txt_start:\n", type, id);
+        fprintf(f, " .global _%s\n", label.str());  // For some reason apple needs a leading underbar and linux does not
+        fprintf(f, "_%s:\n", label.str());
+#else
+        fprintf(f, " .section %s_%u,\"a\"\n", type, id);
+        fprintf(f, " .global %s\n", label.str());
+        fprintf(f, " .type %s,STT_OBJECT\n", label.str());
+        fprintf(f, "%s:\n", label.str());
+#endif
         fprintf(f, " .incbin \"%s\"\n", binfile.str());
         FILE *bin = fopen(binfile, "wb");
         if (!bin)