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 not 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 not include a matching entry", filename); return false; #endif }
extern bool getResourceFromFile(const char *filename, MemoryBuffer &data, const char * type, unsigned id) { #ifdef _WIN32 HINSTANCE dllHandle = LoadLibraryEx(filename, NULL, LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); if (dllHandle == NULL) dllHandle = LoadLibraryEx(filename, NULL, LOAD_LIBRARY_AS_DATAFILE); // the LOAD_LIBRARY_AS_IMAGE_RESOURCE flag is not supported on all versions of Windows if (dllHandle == NULL) { DBGLOG("Failed to load library %s: %d", filename, GetLastError()); return false; } HRSRC hrsrc = FindResource(dllHandle, MAKEINTRESOURCE(id), type); if (!hrsrc) return false; size32_t len = SizeofResource(dllHandle, hrsrc); const void *rdata = (const void *) LoadResource(dllHandle, hrsrc); data.append(len, rdata); FreeLibrary(dllHandle); return true; #elif defined (_USE_BINUTILS) CriticalBlock block(bfdCs); bfd_init (); bfd *file = bfd_openr(filename, NULL); if (file) { StringBuffer sectionName; sectionName.append(type).append("_").append(id).append(".data"); SecScanParam param(data, sectionName.str()); if (bfd_check_format (file, bfd_object)) bfd_map_over_sections (file, secscan, ¶m); bfd_close (file); } return data.length() != 0; #else struct stat stat_buf; VStringBuffer sectname("%s_%u", type, id); int fd = open(filename, O_RDONLY); if (fd == -1 || fstat(fd, &stat_buf) == -1) { DBGLOG("Failed to load library %s: %d", filename, errno); return false; } bool ok = false; __uint64 size = stat_buf.st_size; 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 { ok = getResourceFromMappedFile(filename, start_addr, data, type, id); munmap((void *)start_addr, size); } close(fd); return ok; #endif }