From 5a44f3805290d23bee892cfe128bd38f87365638 Mon Sep 17 00:00:00 2001 From: Brett Jia Date: Wed, 28 May 2025 14:39:43 -0400 Subject: [PATCH] Implement DragonFlyBSD support This patch adds support for running Blink on DragonFlyBSD. cpuid now has support for detecting DragonFlyBSD, and Blink's execve can detect if the requested executable is built for DragonFlyBSD using a helper to extract the OS name from ELF notes. --- blink/cpuid.c | 25 ++++++++++++++----------- blink/elf.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ blink/elf.h | 1 + blink/loader.c | 14 ++++++++++++++ 4 files changed, 73 insertions(+), 11 deletions(-) diff --git a/blink/cpuid.c b/blink/cpuid.c index 597c7c6ec..d9cd320de 100644 --- a/blink/cpuid.c +++ b/blink/cpuid.c @@ -20,17 +20,18 @@ #include "blink/endian.h" #include "blink/machine.h" -#define INTEL "GenuineIntel" -#define BLINK "GenuineBlink" -#define LINUX_ "Linux\0\0\0\0\0\0\0" -#define FREEBSD_ "FreeBSD\0\0\0\0\0\0" -#define NETBSD_ "NetBSD\0\0\0\0\0\0" -#define OPENBSD_ "OpenBSD\0\0\0\0\0" -#define XNU_ "XNU\0\0\0\0\0\0\0\0\0" -#define WINDOWS_ "Windows\0\0\0\0\0" -#define CYGWIN_ "Cygwin\0\0\0\0\0\0" -#define HAIKU_ "Haiku\0\0\0\0\0\0\0" -#define UNKNOWN_ "Unknown\0\0\0\0\0\0" +#define INTEL "GenuineIntel" +#define BLINK "GenuineBlink" +#define LINUX_ "Linux\0\0\0\0\0\0\0" +#define FREEBSD_ "FreeBSD\0\0\0\0\0\0" +#define NETBSD_ "NetBSD\0\0\0\0\0\0" +#define OPENBSD_ "OpenBSD\0\0\0\0\0" +#define DRAGONFLYBSD_ "DragonFlyBSD" +#define XNU_ "XNU\0\0\0\0\0\0\0\0\0" +#define WINDOWS_ "Windows\0\0\0\0\0" +#define CYGWIN_ "Cygwin\0\0\0\0\0\0" +#define HAIKU_ "Haiku\0\0\0\0\0\0\0" +#define UNKNOWN_ "Unknown\0\0\0\0\0\0" #ifdef __COSMOPOLITAN__ #define OS \ @@ -49,6 +50,8 @@ #define OS NETBSD_ #elif defined(__OpenBSD__) #define OS OPENBSD_ +#elif defined(__DragonFly__) +#define OS DRAGONFLYBSD_ #elif defined(__APPLE__) #define OS XNU_ #elif defined(__CYGWIN__) diff --git a/blink/elf.c b/blink/elf.c index 702370b95..7608479a4 100644 --- a/blink/elf.c +++ b/blink/elf.c @@ -178,3 +178,47 @@ Elf64_Sym_ *GetElfSymbolTable(const Elf64_Ehdr_ *elf, // } return res; } + +const char *GetElfOsNameInNoteTag(const Elf64_Ehdr_ *elf, size_t mapsize) { + int i; + Elf64_Shdr_ *shdr; + const char *sect_name; + const char *note, *note_end; + uint32_t namesz, descsz, type; + const char *os_name; + + for (i = 0; i < Read16(elf->shnum); ++i) { + shdr = GetElfSectionHeaderAddress(elf, mapsize, i); + if (!shdr) continue; + if (Read32(shdr->type) != SHT_NOTE_) continue; + + sect_name = GetElfSectionName(elf, mapsize, shdr); + if (!sect_name) continue; + if (strcmp(sect_name, ".note.ABI-tag") != 0 && + strcmp(sect_name, ".note.tag") != 0 && + strcmp(sect_name, ".note.gnu") != 0) + continue; + + note = (const char *)GetElfSectionAddress(elf, mapsize, shdr); + if (!note) continue; + note_end = note + Read64(shdr->size); + + while (note + 12 <= note_end) { + namesz = *(const uint32_t *)(note + 0); + descsz = *(const uint32_t *)(note + 4); + type = *(const uint32_t *)(note + 8); + + const char *name_field = note + 12; + const char *desc_field = name_field + ((namesz + 3) & ~3); + if (desc_field + ((descsz + 3) & ~3) > note_end) break; + + if (namesz && name_field[namesz-1] == '\0') { + return name_field; + } + + // Advance to next note + note = desc_field + ((descsz + 3) & ~3); + } + } + return NULL; +} \ No newline at end of file diff --git a/blink/elf.h b/blink/elf.h index 8a4a76bca..34910a9f7 100644 --- a/blink/elf.h +++ b/blink/elf.h @@ -629,5 +629,6 @@ char *GetElfSectionNameStringTable(const Elf64_Ehdr_ *, size_t); void *GetElfSectionAddress(const Elf64_Ehdr_ *, size_t, const Elf64_Shdr_ *); Elf64_Sym_ *GetElfSymbolTable(const Elf64_Ehdr_ *, size_t, int *); i64 GetElfMemorySize(const Elf64_Ehdr_ *, size_t, i64 *); +const char *GetElfOsNameInNoteTag(const Elf64_Ehdr_ *, size_t); #endif /* BLINK_ELF_H_ */ diff --git a/blink/loader.c b/blink/loader.c index fb244be31..03eebda3d 100644 --- a/blink/loader.c +++ b/blink/loader.c @@ -293,6 +293,16 @@ static bool IsHaikuExecutable(Elf64_Ehdr_ *ehdr, size_t size) { #endif } +static bool IsDragonflybsdExecutable(Elf64_Ehdr_ *ehdr, size_t size) { +#ifdef __DragonFly__ + const char *name = GetElfOsNameInNoteTag(ehdr, size); + if (name && !strcmp(name, "DragonFly")) { + return true; + } +#endif + return false; +} + static bool IsShebangExecutable(void *image, size_t size) { return size >= 2 && ((char *)image)[0] == '#' && ((char *)image)[1] == '!'; } @@ -342,6 +352,10 @@ bool IsSupportedExecutable(const char *path, void *image, size_t size) { ExplainWhyItCantBeEmulated(path, "ELF is Haiku executable"); return false; } + if (IsDragonflybsdExecutable(ehdr, size)) { + ExplainWhyItCantBeEmulated(path, "ELF is DragonFlyBSD executable"); + return false; + } #if defined(__ELF__) && !defined(__linux) LOGF("blink believes %s is an x86_64-linux executable", path); #endif