From 5937f746e5fc95c1688ef807cb7beb2cba2a0b50 Mon Sep 17 00:00:00 2001 From: sergio Date: Fri, 19 Jun 2026 13:51:15 -0400 Subject: [PATCH] =?UTF-8?q?recipes/elfutils:=20de-Alpinizar=20libelf=20(?= =?UTF-8?q?=C3=BAltimo=20build-dep=20Alpine=20del=20kernel)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tools/objtool del kernel enlaza -lelf (libelf+gelf.h); venía de `apk add elfutils-dev`. Ahora recipes/elfutils.toml construye SÓLO libelf (0.194, lo que objtool necesita — no libdw/libdwfl/src) desde fuente, wired como deps.build del kernel. Con esto NINGÚN build-dep del kernel viene de Alpine: el camino del kernel es 100% hammer-from-source. elfutils es glibc-céntrico; musl no trae ///fts/ obstack/rawmemchr. En vez del parche completo de Alpine, shims mínimos en compat/ (vía CPPFLAGS/-include): error.h y argp.h (sólo los usan color.c/printversion.c, cuyos .o van en libeu.a pero objtool NO referencia ⇒ basta que compilen); libintl no-op (+ --disable-nls); rawmemchr inline; y libargp/libfts/libobstack.a stubs para pasar los AC_SEARCH_LIBS del configure (símbolos inertes para libelf). CC=gcc. bootstrap-devfs.sh: elfutils-dev fuera del NEEDED. Validado: purgué elfutils-dev del devfs, rebuild → objtool linkea el libelf hammer (sin gelf.h Alpine), y HAMMER_KERNEL=1 verify → ✓ REPRODUCIBLE bit a bit, DRIVER_RC=0. Co-Authored-By: Claude Opus 4.8 (1M context) --- recipes/elfutils.toml | 123 +++++++++++++++++++++++++++++++++++++ recipes/linux.toml | 7 ++- scripts/bootstrap-devfs.sh | 10 +-- 3 files changed, 132 insertions(+), 8 deletions(-) create mode 100644 recipes/elfutils.toml diff --git a/recipes/elfutils.toml b/recipes/elfutils.toml new file mode 100644 index 00000000..e48b9a77 --- /dev/null +++ b/recipes/elfutils.toml @@ -0,0 +1,123 @@ +# elfutils 0.194 (sólo libelf) — de-Alpinización del último build-dep del kernel. +# +# `tools/objtool` del kernel enlaza -lelf (libelf + gelf.h) — en x86_64 las mitigaciones fuerzan +# CONFIG_OBJTOOL. Venía de `apk add elfutils-dev` (bootstrap-lib). Esta receta construye libelf desde +# fuente. Misma versión que Alpine 3.23 (0.194). Build-tool de build-time (objtool corre durante la +# compilación del kernel; libelf NO se enlaza en el bzImage) ⇒ no afecta el of_tree del 4/4. +# +# Construimos SÓLO libelf (+ lib/libeu.a, su helper) — objtool no necesita libdw/libdwfl/src, que son +# los que arrastran argp/obstack/fts (lo verdaderamente difícil en musl). elfutils es glibc-céntrico; +# musl no trae , , ni rawmemchr. Estrategia de shims (en compat/, vía +# CPPFLAGS/-include) en vez de los parches completos de Alpine: +# - : lo elimina --disable-nls (eu-config.h sólo lo incluye con ENABLE_NLS). +# - : shim con error()/error_at_line() (musl ya exporta program_invocation_short_name). +# - : shim de tipos/decls — sólo lo usan lib/color.c y lib/printversion.c, cuyos .o van en +# libeu.a pero objtool NO referencia (sólo necesita el core de libelf) ⇒ basta que +# COMPILEN; las funcs argp quedan como undefined inertes en el .a. +# - rawmemchr: shim inline (lo usa libelf/elf_getarsym.c), force-include global. +# CC=gcc (NO zig): consistente con binutils/openssl; evita miscompilación. + +name = "elfutils" +version = "0.194" + +[source] +tarball = "https://sourceware.org/elfutils/ftp/0.194/elfutils-0.194.tar.bz2" +sha256 = "09e2ff033d39baa8b388a2d7fbc5390bfde99ae3b7c67c7daaf7433fbcf0f01e" + +[build] +compiler = "zig-cc" +target = "x86_64-linux-musl" +link = "dynamic" + +[build.phases] +configure = """ +mkdir -p compat && \ +printf '%s\\n' \ + '#ifndef _COMPAT_ERROR_H' '#define _COMPAT_ERROR_H' \ + '#include ' '#include ' '#include ' '#include ' \ + 'extern char *program_invocation_short_name;' \ + 'static inline void error(int s,int e,const char*f,...){va_list a;fflush(stdout);' \ + ' fprintf(stderr,"%s: ",program_invocation_short_name);va_start(a,f);vfprintf(stderr,f,a);va_end(a);' \ + ' if(e)fprintf(stderr,": %s",strerror(e));fputc(0x0a,stderr);if(s)exit(s);}' \ + 'static inline void error_at_line(int s,int e,const char*fn,unsigned ln,const char*f,...){va_list a;' \ + ' fflush(stdout);fprintf(stderr,"%s:%s:%u: ",program_invocation_short_name,fn,ln);' \ + ' va_start(a,f);vfprintf(stderr,f,a);va_end(a);if(e)fprintf(stderr,": %s",strerror(e));' \ + ' fputc(0x0a,stderr);if(s)exit(s);}' \ + '#endif' > compat/error.h && \ +printf '%s\\n' \ + '#ifndef _COMPAT_ARGP_H' '#define _COMPAT_ARGP_H' '#include ' '#include ' \ + 'typedef int error_t;' \ + 'struct argp_option{const char*name;int key;const char*arg;int flags;const char*doc;int group;};' \ + 'struct argp;' \ + 'struct argp_state{const struct argp*root_argp;int argc;char**argv;int next;unsigned flags;' \ + ' unsigned arg_num;int quoted;void*input;void**child_inputs;void*hook;char*name;FILE*err_stream;' \ + ' FILE*out_stream;void*pstate;};' \ + 'typedef error_t(*argp_parser_t)(int,char*,struct argp_state*);' \ + 'struct argp_child;' \ + 'struct argp{const struct argp_option*options;argp_parser_t parser;const char*args_doc;' \ + ' const char*doc;const struct argp_child*children;char*(*help_filter)(int,const char*,void*);' \ + ' const char*argp_domain;};' \ + 'struct argp_child{const struct argp*argp;int flags;const char*header;int group;};' \ + '#define ARGP_ERR_UNKNOWN E2BIG' '#define ARGP_KEY_ARG 0' '#define ARGP_KEY_END 0x1000001' \ + '#define ARGP_KEY_INIT 0x1000003' '#define ARGP_KEY_FINI 0x1000007' '#define ARGP_KEY_SUCCESS 0x1000002' \ + '#define ARGP_HELP_SEE 0x04' '#define ARGP_HELP_STD_ERR 0x2a' \ + '#define OPTION_ARG_OPTIONAL 0x1' '#define OPTION_HIDDEN 0x2' '#define OPTION_ALIAS 0x4' \ + '#define OPTION_DOC 0x8' '#define OPTION_NO_USAGE 0x10' '#define ARGP_IN_ORDER 0x08' \ + '#define ARGP_NO_HELP 0x10' '#define ARGP_NO_EXIT 0x20' '#define ARGP_LONG_ONLY 0x40' \ + 'extern const char*argp_program_version;extern const char*argp_program_bug_address;' \ + 'extern void(*argp_program_version_hook)(FILE*,struct argp_state*);' \ + 'extern error_t argp_parse(const struct argp*,int,char**,unsigned,int*,void*);' \ + 'extern void argp_help(const struct argp*,FILE*,unsigned,char*);' \ + 'extern void argp_error(const struct argp_state*,const char*,...);' \ + '#endif' > compat/argp.h && \ +printf '%s\\n' \ + '#ifndef _COMPAT_MUSL_EXTRA_H' '#define _COMPAT_MUSL_EXTRA_H' '#include ' \ + '#ifndef __GLIBC__' \ + 'static inline void*rawmemchr(const void*s,int c){const unsigned char*p=s;' \ + ' for(;*p!=(unsigned char)c;p++){}' ' return(void*)p;}' \ + '#endif' '#endif' > compat/musl-extra.h && \ +printf '%s\\n' \ + '#ifndef _COMPAT_LIBINTL_H' '#define _COMPAT_LIBINTL_H' \ + '#define gettext(s) (s)' '#define dgettext(d,s) (s)' '#define dcgettext(d,s,c) (s)' \ + '#define ngettext(s,p,n) ((n)==1?(s):(p))' '#define dngettext(d,s,p,n) ((n)==1?(s):(p))' \ + '#define bindtextdomain(d,x) ((char*)0)' '#define textdomain(d) ((char*)0)' \ + '#define bind_textdomain_codeset(d,c) ((char*)0)' \ + '#endif' > compat/libintl.h && \ +printf '%s\\n' \ + '#include ' 'struct argp;struct argp_state;typedef int error_t;' \ + 'const char*argp_program_version;const char*argp_program_bug_address;' \ + 'void(*argp_program_version_hook)(FILE*,struct argp_state*);' \ + 'error_t argp_parse(const struct argp*a,int c,char**v,unsigned f,int*i,void*n){return 0;}' \ + 'void argp_help(const struct argp*a,FILE*s,unsigned f,char*n){}' \ + 'void argp_error(const struct argp_state*s,const char*f,...){}' \ + 'void argp_state_help(const struct argp_state*s,FILE*t,unsigned f){}' \ + 'void argp_usage(const struct argp_state*s){}' > compat/argp-stub.c && \ +gcc -c compat/argp-stub.c -o compat/argp-stub.o && ar rcs compat/libargp.a compat/argp-stub.o && \ +printf '%s\\n' \ + 'typedef struct{int x;}FTS;typedef struct{int y;}FTSENT;' \ + 'FTS*fts_open(char*const*p,int o,int(*c)(const FTSENT**,const FTSENT**)){return 0;}' \ + 'FTSENT*fts_read(FTS*f){return 0;}' 'FTSENT*fts_children(FTS*f,int o){return 0;}' \ + 'int fts_set(FTS*f,FTSENT*e,int o){return 0;}' 'int fts_close(FTS*f){return 0;}' > compat/fts-stub.c && \ +gcc -c compat/fts-stub.c -o compat/fts-stub.o && ar rcs compat/libfts.a compat/fts-stub.o && \ +printf '%s\\n' \ + 'struct obstack;void(*obstack_alloc_failed_handler)(void);int obstack_exit_failure;' \ + 'int _obstack_begin(struct obstack*o,int s,int a,void*(*c)(long),void(*f)(void*)){return 1;}' \ + 'int _obstack_begin_1(struct obstack*o,int s,int a,void*(*c)(void*,long),void(*f)(void*,void*),void*x){return 1;}' \ + 'void _obstack_newchunk(struct obstack*o,int l){}' 'int _obstack_allocated_p(struct obstack*o,void*p){return 0;}' \ + 'void _obstack_free(struct obstack*o,void*p){}' 'int _obstack_memory_used(struct obstack*o){return 0;}' \ + > compat/obstack-stub.c && \ +gcc -c compat/obstack-stub.c -o compat/obstack-stub.o && ar rcs compat/libobstack.a compat/obstack-stub.o && \ +CC=gcc CFLAGS="-O2 -g -I$PWD/compat" CPPFLAGS="-I$PWD/compat" LDFLAGS="-L$PWD/compat" \ + ./configure --prefix=/usr --libdir=/usr/lib --disable-nls --disable-demangler \ + --disable-libdebuginfod --disable-debuginfod --program-prefix=eu- +""" +# El -include del shim de rawmemchr va SÓLO en compile (en configure rompe el test "undeclared builtins" +# de autoconf). CFLAGS aquí reemplaza el de configure (mismo valor + el -include); AM_CFLAGS (warnings/ +# -Werror) se preserva. +compile = "CC=gcc make -C lib CFLAGS=\"-O2 -g -I$PWD/compat -include $PWD/compat/musl-extra.h\" && CC=gcc make -C libelf libelf.a libelf.so CFLAGS=\"-O2 -g -I$PWD/compat -include $PWD/compat/musl-extra.h\"" +install = """ +mkdir -p /out/usr/lib/pkgconfig /out/usr/include && \ +cp -a libelf/libelf.a libelf/libelf.so* /out/usr/lib/ && \ +cp -a libelf/libelf.h libelf/gelf.h /out/usr/include/ && \ +cp -a config/libelf.pc /out/usr/lib/pkgconfig/ 2>/dev/null || true +""" diff --git a/recipes/linux.toml b/recipes/linux.toml index 04fa19a2..dffde96c 100644 --- a/recipes/linux.toml +++ b/recipes/linux.toml @@ -47,9 +47,10 @@ link = "dynamic" # flex (lexer kconfig) + bison (parser kconfig) + m4 (bison lo invoca en runtime) + openssl (libcrypto # estática para certs/extract-cert). Se materializan como capa overlay en /usr (binarios en /usr/bin, # skeletons de bison en /usr/share/bison, libcrypto.a + headers + pkgconfig en /usr/{lib,include}). -# openssl de-Alpiniza el build-dep que antes venía de `apk add openssl-dev`. libelf (objtool) sigue -# como bootstrap-lib apk (elfutils-en-musl es el difícil); de-Alpinizable luego con recipes/elfutils.toml. -build = ["flex", "bison", "m4", "openssl"] +# openssl + elfutils de-Alpinizan los build-deps que antes venían de `apk add openssl-dev elfutils-dev`. +# elfutils.toml construye SÓLO libelf (lo que objtool enlaza) con shims musl (argp/error/libintl/fts/ +# obstack/rawmemchr); ver su cabecera. Todo el camino del kernel es ahora hammer-from-source. +build = ["flex", "bison", "m4", "openssl", "elfutils"] [build.phases] configure = """ diff --git a/scripts/bootstrap-devfs.sh b/scripts/bootstrap-devfs.sh index ee462fb7..be123bba 100755 --- a/scripts/bootstrap-devfs.sh +++ b/scripts/bootstrap-devfs.sh @@ -132,14 +132,14 @@ else # un compilador C++. (zlib-dev quedará reemplazado por recipes/zlib.toml cuando el frente avance.) # `flex bison`: build-deps del kernel (lexer/parser de kconfig). También hay recipes/{flex,bison}.toml # hammer-built; aquí en el devfs base son el arranque (frente kernel-from-source). - # `elfutils-dev`: aporta libelf + gelf.h, que `tools/objtool` del kernel necesita (en x86_64 las - # mitigaciones seleccionan CONFIG_OBJTOOL aunque se use frame-pointer unwinder). Build-tool de - # arranque (mismo status que g++/zlib-dev; no se enlaza en nada enviado, no afecta of_tree del 4/4); - # quedará reemplazado por recipes/elfutils.toml (libelf desde fuente) cuando el frente kernel avance. + # NOTA: `elfutils-dev` YA NO va aquí — de-Alpinizado a recipes/elfutils.toml (sólo libelf, con shims + # musl argp/error/libintl/fts/obstack/rawmemchr), deps.build del kernel. objtool enlaza el libelf + # hammer desde la capa overlay. (El runtime libelf.so.1 de Alpine, si algún otro tool lo necesita, + # es la misma versión 0.194 ABI-compatible.) # NOTA: `openssl-dev` YA NO va aquí — de-Alpinizado a recipes/openssl.toml (libcrypto estática, # deps.build del kernel). El host-tool certs/extract-cert lo enlaza desde la capa overlay hammer. # El runtime libcrypto3/libssl3 (que curl/git necesitan) lo trae Alpine aparte, no es openssl-dev. - NEEDED="make autoconf automake m4 patch coreutils libtool pkgconf bash binutils g++ zlib-dev flex bison elfutils-dev rust cargo linux-headers bubblewrap git curl kmod" + NEEDED="make autoconf automake m4 patch coreutils libtool pkgconf bash binutils g++ zlib-dev flex bison rust cargo linux-headers bubblewrap git curl kmod" missing="" for pkg in $NEEDED; do # apk info -e devuelve el paquete si está instalado, vacío si no.