From patchwork Tue Feb 6 12:45:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Chestnykh X-Patchwork-Id: 1895692 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=IYh+mgJu; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=uclibc-ng.org (client-ip=2a00:1828:2000:679::23; helo=helium.openadk.org; envelope-from=devel-bounces@uclibc-ng.org; receiver=patchwork.ozlabs.org) Received: from helium.openadk.org (helium.openadk.org [IPv6:2a00:1828:2000:679::23]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4TTjf24Px9z23gb for ; Tue, 6 Feb 2024 23:45:46 +1100 (AEDT) Received: from helium.openadk.org (localhost [IPv6:::1]) by helium.openadk.org (Postfix) with ESMTP id 9BAE035210D6; Tue, 6 Feb 2024 13:45:40 +0100 (CET) Authentication-Results: helium.openadk.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=IYh+mgJu; dkim-atps=neutral Received: from mail-lf1-f47.google.com (mail-lf1-f47.google.com [209.85.167.47]) by helium.openadk.org (Postfix) with ESMTPS id C3612352077B for ; Tue, 6 Feb 2024 13:45:35 +0100 (CET) Received: by mail-lf1-f47.google.com with SMTP id 2adb3069b0e04-51156cf5766so339035e87.0 for ; Tue, 06 Feb 2024 04:45:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1707223534; x=1707828334; darn=uclibc-ng.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=ZWznOdioM8L6c7vexCAEh7qdld0OCQuNwHr5nRTJbSA=; b=IYh+mgJu2CV7QTgkGc+pN46eoKeuMxtIsB4rOHEigCKaiMPXmIlfI9+2aMhfB0d5CY T5gcV1hQGlvopRU5nnyhFRTH/rves1dF0qFADmKQChjn1Tkm0Cp5hw+6t6U5iyg9tuW3 kppBFqY4CAtCCUKFQaqzGjerCyYsqDOGe+UMqxbPh5t7wP8FPIQ4yUGLAcOIrOOat8Lo 3VeUQaTRwzvGUmDxeFqeulqmyqvRn+5vuRrahOfsk7+qt3vQoxjP96qmov78g0nFHP4h VrYanchGoXrpLblw5LAXKvs94w66hBrIMhR1FAmOzAFk0ZmYUO/WthvEas7XABuo+I7c ijag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707223534; x=1707828334; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=ZWznOdioM8L6c7vexCAEh7qdld0OCQuNwHr5nRTJbSA=; b=TVefTp6Sly/xzznwrV8WXPqI3MxnS5zPnjqNnKRmUFD2gOkb/3Y2HgRAzVzHL5V41O rx5geGuXPc6ROW7QZvsLS3lyEmXD7qp44lwVq8jdzbG54y1CNiYAw+L+wGkFi1/FNzXq GC4Py5xXsOuKwnbaRpj+aElYYyf3fq+d9Acm9VZy3ljMEMUJTtVzceJA6AUAU71DjDnF caiklYSy4a29bavJerr5wCNpstU7R2MXDI7ppRedzzXLNql9Jm47OBf238WjgYdBVsP9 RL19PsC2ktUB4m0OxwrcHYrVJSHcWFTmEPcWPIHcXJJCR3nM3c0t8ot01vNSP1VGO4lR cogg== X-Gm-Message-State: AOJu0YwpXNojjPTLcxdDN2HeLg8+JctdXRuCvOJco3vR03l3qLMigm9V xVYbRpymtIPalGc9VeT5QPSLCLqy/zHA8FnoFWez/2iF3l06pC4Lgq/WvT3f X-Google-Smtp-Source: AGHT+IHVdRXzSAVK//sCq3id4Ck0Ae2wRCFhP2WKaZr3w5r7jubD4abYksLIYr6SP3kJz72Y68yzaw== X-Received: by 2002:a19:e01c:0:b0:511:56b6:afa3 with SMTP id x28-20020a19e01c000000b0051156b6afa3mr1523570lfg.3.1707223534162; Tue, 06 Feb 2024 04:45:34 -0800 (PST) Received: from localhost.localdomain ([2a00:1370:817a:d2b8:8d0a:b3b9:4a6d:fd16]) by smtp.gmail.com with ESMTPSA id o3-20020a05651205c300b0051145f90c3bsm233754lfo.67.2024.02.06.04.45.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Feb 2024 04:45:33 -0800 (PST) From: Dmitry Chestnykh To: devel@uclibc-ng.org Date: Tue, 6 Feb 2024 15:45:38 +0300 Message-ID: <20240206124538.27667-1-dm.chestnykh@gmail.com> X-Mailer: git-send-email 2.43.0 MIME-Version: 1.0 Message-ID-Hash: YTAPX2LU6F4NG3PMQ3RTSYYIK7ARDWEG X-Message-ID-Hash: YTAPX2LU6F4NG3PMQ3RTSYYIK7ARDWEG X-MailFrom: dm.chestnykh@gmail.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Dmitry Chestnykh X-Mailman-Version: 3.3.3 Precedence: list Subject: [uclibc-ng-devel] [PATCH] ld.so: Add support of DT_RELR relocation format. List-Id: uClibc-ng Development Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Nowadays modern libcs like Glibc and musl currently support processing of RELATIVE relocations compressed with DT_RELR format. However I have noticed that uClibc-ng doesn't support this feature and if the source will be linked with `-Wl,-z,pack-relative-relos` (bfd) or `-Wl,--pack-dyn-relocs=relr` (lld) then ld.so cannot properly load the produced DSO. This patch is intended to fix this issue and adds applying of DT_RELR relative relocation. Signed-off-by: Dmitry Chestnykh --- include/elf.h | 8 +++++- ldso/include/dl-elf.h | 38 ++++++++++++++++++++++++++ ldso/ldso/dl-elf.c | 3 ++ ldso/ldso/dl-startup.c | 3 ++ libc/misc/internals/reloc_static_pie.c | 1 + 5 files changed, 52 insertions(+), 1 deletion(-) diff --git a/include/elf.h b/include/elf.h index b7edbade2..c2efa9978 100644 --- a/include/elf.h +++ b/include/elf.h @@ -60,6 +60,9 @@ typedef uint16_t Elf64_Section; typedef Elf32_Half Elf32_Versym; typedef Elf64_Half Elf64_Versym; +/* Type for relative relocations in DT_RELR format */ +typedef Elf32_Word Elf32_Relr; +typedef Elf64_Xword Elf64_Relr; /* The ELF file header. This appears at the start of every ELF file. */ @@ -818,7 +821,10 @@ typedef struct #define DT_ENCODING 32 /* Start of encoded range */ #define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ #define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ -#define DT_NUM 34 /* Number used */ +#define DT_RELRSZ 35 /* Size in bytes, of DT_RELR table */ +#define DT_RELR 36 /* Address of Relr relocs */ +#define DT_RELRENT 37 /* Size in bytes of one DT_RELR entry */ +#define DT_NUM 38 /* Number used */ #define DT_LOOS 0x6000000d /* Start of OS-specific */ #define DT_HIOS 0x6ffff000 /* End of OS-specific */ #define DT_LOPROC 0x70000000 /* Start of processor-specific */ diff --git a/ldso/include/dl-elf.h b/ldso/include/dl-elf.h index 2b99958d9..10b895733 100644 --- a/ldso/include/dl-elf.h +++ b/ldso/include/dl-elf.h @@ -250,5 +250,43 @@ unsigned int __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info (((X) & PF_W) ? PROT_WRITE : 0) | \ (((X) & PF_X) ? PROT_EXEC : 0)) +/* Apply relocations in DT_RELR format */ +#define DL_DO_RELOCATE_RELR(load_addr, relr_start, relr_end) \ + do { \ + const ElfW(Relr) *relr = 0; \ + ElfW(Addr) *reloc_addr = 0; \ + for (relr = relr_start; relr < relr_end; relr++) { \ + ElfW(Relr) relr_entry = *relr; \ + if (!(relr_entry & 1)) \ + { \ + reloc_addr = (ElfW(Addr) *)DL_RELOC_ADDR(load_addr, relr_entry); \ + *reloc_addr = (ElfW(Addr))DL_RELOC_ADDR(load_addr, reloc_addr); \ + reloc_addr++; \ + } \ + else \ + { \ + for (long int i = 0; (relr_entry >>= 1) != 0; ++i) { \ + if ((relr_entry & 1) != 0) \ + reloc_addr[i] = (ElfW(Addr))DL_RELOC_ADDR(load_addr, reloc_addr[i]); \ + } \ + reloc_addr += CHAR_BIT * sizeof(ElfW(Relr)) - 1; \ + } \ + } \ + } while (0); + +/* The macro to prepare data for the above DL_DO_RELOCATE_RELR */ +#define DL_RELOCATE_RELR(dyn) \ + do { \ + if (dyn->dynamic_info[DT_RELRENT]) \ + _dl_assert(dyn->dynamic_info[DT_RELRENT] == sizeof(ElfW(Relr))); \ + if (dyn->dynamic_info[DT_RELR] && \ + dyn->dynamic_info[DT_RELRSZ]) { \ + ElfW(Relr) *relr_start = (ElfW(Relr) *)((ElfW(Addr))dyn->loadaddr + (ElfW(Addr))dyn->dynamic_info[DT_RELR]); \ + ElfW(Relr) *relr_end = (ElfW(Relr) *)((const char *)relr_start + dyn->dynamic_info[DT_RELRSZ]); \ + _dl_if_debug_dprint("Relocating DT_RELR in %s: start:%p, end:%p\n", \ + dyn->libname, (void *)relr_start, (void *)relr_end); \ + DL_DO_RELOCATE_RELR(dyn->loadaddr, relr_start, relr_end); \ + } \ + } while (0); #endif /* _DL_ELF_H */ diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c index 8210a012e..cc42b904f 100644 --- a/ldso/ldso/dl-elf.c +++ b/ldso/ldso/dl-elf.c @@ -1027,6 +1027,9 @@ int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int now_flag) return goof; } + /* Process DT_RELR relative relocations */ + DL_RELOCATE_RELR(tpnt); + reloc_size = tpnt->dynamic_info[DT_RELOC_TABLE_SIZE]; /* On some machines, notably SPARC & PPC, DT_REL* includes DT_JMPREL in its range. Note that according to the ELF spec, this is completely legal! */ diff --git a/ldso/ldso/dl-startup.c b/ldso/ldso/dl-startup.c index 989711fcc..674c4b7b9 100644 --- a/ldso/ldso/dl-startup.c +++ b/ldso/ldso/dl-startup.c @@ -264,6 +264,9 @@ DL_START(unsigned long args) that once we are done, we have considerably more flexibility. */ SEND_EARLY_STDERR_DEBUG("About to do library loader relocations\n"); + /* Process DT_RELR relative relocations */ + DL_RELOCATE_RELR(tpnt); + { int indx; #if defined(ELF_MACHINE_PLTREL_OVERLAP) diff --git a/libc/misc/internals/reloc_static_pie.c b/libc/misc/internals/reloc_static_pie.c index ab1923024..7ad80f97b 100644 --- a/libc/misc/internals/reloc_static_pie.c +++ b/libc/misc/internals/reloc_static_pie.c @@ -53,6 +53,7 @@ reloc_static_pie(ElfW(Addr) load_addr) PERFORM_BOOTSTRAP_GOT(tpnt); #endif + DL_RELOCATE_RELR(tpnt); #if defined(ELF_MACHINE_PLTREL_OVERLAP) # define INDX_MAX 1