Util (Linux): add elf helper

This commit is contained in:
Carter Li
2024-08-08 15:03:10 +08:00
parent 2e2cf64452
commit a9373fb4e4
8 changed files with 115 additions and 0 deletions
+6
View File
@@ -69,6 +69,7 @@ cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF)
cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR SunOS" OFF)
cmake_dependent_option(ENABLE_DDCUTIL "Enable ddcutil" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_DIRECTX_HEADERS "Enable DirectX headers for WSL" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_ELF "Enable libelf" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF)
option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embedded) yyjson library" OFF)
@@ -480,6 +481,7 @@ if(LINUX)
src/detection/wmtheme/wmtheme_linux.c
src/detection/camera/camera_linux.c
src/util/platform/FFPlatform_unix.c
src/util/linux/elf.c
)
elseif(ANDROID)
list(APPEND LIBFASTFETCH_SRC
@@ -1075,6 +1077,10 @@ ff_lib_enable(DDCUTIL
"ddcutil"
"Ddcutil"
)
ff_lib_enable(ELF
"libelf"
"libelf"
)
ff_lib_enable(DIRECTX_HEADERS
"DirectX-Headers"
"DirectX-Headers"
+4
View File
@@ -730,6 +730,10 @@
"ddcutil": {
"description": "Used for brightness detection of external displays (Linux)",
"type": "string"
},
"elf": {
"description": "Used for st terminal font detection and systemd version detection (Linux)",
"type": "string"
}
}
},
+3
View File
@@ -248,6 +248,9 @@ void ffListFeatures(void)
#if FF_HAVE_DDCUTIL
"libddcutil\n"
#endif
#if FF_HAVE_ELF
"libelf\n"
#endif
#if FF_HAVE_DIRECTX_HEADERS
"Directx Headers\n"
#endif
+7
View File
@@ -935,6 +935,13 @@
"arg": {
"type": "path"
}
},
{
"long": "lib-elf",
"desc": "Used for st terminal font detection and systemd version detection",
"arg": {
"type": "path"
}
}
],
"Module specific": [
+4
View File
@@ -66,6 +66,8 @@ const char* ffOptionsParseLibraryJsonConfig(FFOptionsLibrary* options, yyjson_va
ffStrbufSetS(&options->libDdcutil, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "drm"))
ffStrbufSetS(&options->libdrm, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "elf"))
ffStrbufSetS(&options->libelf, yyjson_get_str(val));
#endif
else
@@ -131,6 +133,8 @@ bool ffOptionsParseLibraryCommandLine(FFOptionsLibrary* options, const char* key
ffOptionParseString(key, value, &options->libDdcutil);
else if(ffStrEqualsIgnCase(subkey, "drm"))
ffOptionParseString(key, value, &options->libdrm);
else if(ffStrEqualsIgnCase(subkey, "elf"))
ffOptionParseString(key, value, &options->libelf);
#endif
else
+1
View File
@@ -32,6 +32,7 @@ typedef struct FFOptionsLibrary
FFstrbuf libPulse;
FFstrbuf libDdcutil;
FFstrbuf libdrm;
FFstrbuf libelf;
#endif
} FFOptionsLibrary;
+85
View File
@@ -0,0 +1,85 @@
#include "elf.h"
#ifdef FF_HAVE_ELF
#include "common/io/io.h"
#include "common/library.h"
#include "util/stringUtils.h"
#include <libelf.h>
#include <fcntl.h>
const char* ffElfExtractStrings(const char* elfFile, bool (*cb)(const char* str, uint32_t len, void* userdata), void* userdata)
{
FF_LIBRARY_LOAD(libelf, &instance.config.library.libelf, "dlopen libelf" FF_LIBRARY_EXTENSION " failed", "libelf" FF_LIBRARY_EXTENSION, 1);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf_version)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf_begin)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf_getshdrstrndx)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf_nextscn)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf64_getshdr)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf32_getshdr)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf_getdata)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf_strptr)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf_end)
if (ffelf_version(EV_CURRENT) == EV_NONE) return "elf_version() failed";
FF_AUTO_CLOSE_FD int fd = open(elfFile, O_RDONLY, 0);
if (fd < 0) return "open() failed";
Elf* elf = ffelf_begin(fd, ELF_C_READ, NULL);
if (elf == NULL) return "elf_begin() failed";
size_t shstrndx = 0;
if (ffelf_getshdrstrndx(elf, &shstrndx) < 0)
{
ffelf_end(elf);
return "elf_getshdrstrndx() failed";
}
Elf_Scn* scn = NULL;
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
while ((scn = ffelf_nextscn(elf, scn)) != NULL)
{
Elf64_Shdr* shdr64 = ffelf64_getshdr(scn);
Elf32_Shdr* shdr32 = NULL;
if (shdr64 == NULL)
{
shdr32 = ffelf32_getshdr(scn);
if (shdr32 == NULL) continue;
}
const char* name = ffelf_strptr(elf, shstrndx, shdr64 ? shdr64->sh_name : shdr32->sh_name);
if (name == NULL || !ffStrEquals(name, ".rodata")) continue;
Elf_Data* data = ffelf_getdata(scn, NULL);
if (data == NULL) continue;
for (size_t off = 0; off < data->d_size; ++off)
{
const char* p = (const char*) data->d_buf + off;
if (*p == '\0') continue;
uint32_t len = (uint32_t) strlen(p);
if (*p >= ' ' && *p <= '~') // Ignore control characters
{
if (!cb(p, len, userdata)) break;
}
off += len;
}
break;
}
ffelf_end(elf);
return NULL;
}
#else
const char* ffElfExtractStrings(const char* elfFile, bool (*cb)(const char* str, uint32_t len, void* userdata), void* userdata)
{
FF_UNUSED(elfFile, cb, userdata);
return "Fastfetch was built without libelf support";
}
#endif
+5
View File
@@ -0,0 +1,5 @@
#pragma once
#include "fastfetch.h"
const char* ffElfExtractStrings(const char* elfFile, bool (*cb)(const char* str, uint32_t len, void* userdata), void* userdata);