[libc-commits] [libc] [libc] add dl_iterate_phdr and dladdr (PR #121179)

Tristan Ross via libc-commits libc-commits at lists.llvm.org
Thu Dec 26 21:28:33 PST 2024


https://github.com/RossComputerGuy updated https://github.com/llvm/llvm-project/pull/121179

>From 666662394a01447464bc0b471b0b3dfe717ed29f Mon Sep 17 00:00:00 2001
From: Tristan Ross <tristan.ross at midstall.com>
Date: Thu, 26 Dec 2024 20:52:43 -0800
Subject: [PATCH] [libc] add dl_iterate_phdr and dladdr

---
 libc/config/linux/aarch64/entrypoints.txt     |  4 ++
 libc/hdrgen/yaml/dlfcn.yaml                   | 10 +++-
 libc/hdrgen/yaml/link.yaml                    | 13 ++++-
 libc/include/CMakeLists.txt                   |  3 +
 libc/include/llvm-libc-types/CMakeLists.txt   |  3 +
 libc/include/llvm-libc-types/Dl_info.h        | 19 +++++++
 .../__dl_iterate_phdr_callback_t.h            | 18 ++++++
 .../llvm-libc-types/struct_dl_phdr_info.h     | 26 +++++++++
 libc/src/CMakeLists.txt                       |  1 +
 libc/src/dlfcn/CMakeLists.txt                 | 10 ++++
 libc/src/dlfcn/dladdr.cpp                     | 18 ++++++
 libc/src/dlfcn/dladdr.h                       | 21 +++++++
 libc/src/link/CMakeLists.txt                  | 10 ++++
 libc/src/link/dl_iterate_phdr.h               | 21 +++++++
 libc/src/link/linux/CMakeLists.txt            | 11 ++++
 libc/src/link/linux/dl_iterate_phdr.cpp       | 57 +++++++++++++++++++
 16 files changed, 242 insertions(+), 3 deletions(-)
 create mode 100644 libc/include/llvm-libc-types/Dl_info.h
 create mode 100644 libc/include/llvm-libc-types/__dl_iterate_phdr_callback_t.h
 create mode 100644 libc/include/llvm-libc-types/struct_dl_phdr_info.h
 create mode 100644 libc/src/dlfcn/dladdr.cpp
 create mode 100644 libc/src/dlfcn/dladdr.h
 create mode 100644 libc/src/link/CMakeLists.txt
 create mode 100644 libc/src/link/dl_iterate_phdr.h
 create mode 100644 libc/src/link/linux/CMakeLists.txt
 create mode 100644 libc/src/link/linux/dl_iterate_phdr.cpp

diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 00f0c6a8bfb8e4..ad71df4e6801d7 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -18,11 +18,15 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.ctype.toupper
 
     # dlfcn.h entrypoints
+    libc.src.dlfcn.dladdr
     libc.src.dlfcn.dlclose
     libc.src.dlfcn.dlerror
     libc.src.dlfcn.dlopen
     libc.src.dlfcn.dlsym
 
+    # link.h entrypoints
+    libc.src.link.dl_iterate_phdr
+
     # errno.h entrypoints
     libc.src.errno.errno
 
diff --git a/libc/hdrgen/yaml/dlfcn.yaml b/libc/hdrgen/yaml/dlfcn.yaml
index 725ee705714a75..56c37bf20b2f90 100644
--- a/libc/hdrgen/yaml/dlfcn.yaml
+++ b/libc/hdrgen/yaml/dlfcn.yaml
@@ -8,7 +8,8 @@ macros:
     macro_value: null
   - macro_name: RTLD_LOCAL
     macro_value: null
-types: []
+types:
+  - type_name: Dl_info
 enums: []
 objects: []
 functions:
@@ -37,3 +38,10 @@ functions:
     arguments:
       - type: void *__restrict
       - type: const char *__restrict
+  - name: dladdr
+    standards:
+      - GNUExtensions
+    return_type: int
+    arguments:
+      - type: const void *
+      - type: Dl_info *
diff --git a/libc/hdrgen/yaml/link.yaml b/libc/hdrgen/yaml/link.yaml
index d1963a86813af3..acc96eb8fc27b5 100644
--- a/libc/hdrgen/yaml/link.yaml
+++ b/libc/hdrgen/yaml/link.yaml
@@ -2,7 +2,16 @@ header: link.h
 standards:
   - Linux
 macros: []
-types: []
+types:
+  - type_name: struct_dl_phdr_info
+  - type_name: __dl_iterate_phdr_callback_t
 enums: []
 objects: []
-functions: []
+functions:
+  - name: dl_iterate_phdr
+    standards:
+      - Linux
+    return_type: int
+    arguments:
+      - type: __dl_iterate_phdr_callback_t
+      - type: void *
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 3a05c01abba5a4..21bb341664effe 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -75,6 +75,7 @@ add_header_macro(
   dlfcn.h
   DEPENDS
     .llvm-libc-macros.dlfcn_macros
+    .llvm-libc-types.Dl_info
     .llvm_libc_common_h
 )
 
@@ -444,6 +445,8 @@ add_header_macro(
   link.h
   DEPENDS
     .llvm_libc_common_h
+    .llvm-libc-types.__dl_iterate_phdr_callback_t
+    .llvm-libc-types.struct_dl_phdr_info
     .llvm-libc-macros.link_macros
 )
 
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index ee734eafce3620..6698516be189af 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -1,3 +1,4 @@
+add_header(Dl_info HDR Dl_info.h)
 add_header(off64_t HDR off64_t.h)
 add_header(size_t HDR size_t.h)
 add_header(ssize_t HDR ssize_t.h)
@@ -67,6 +68,8 @@ else()
 endif()
 add_header(stack_t HDR stack_t.h DEPENDS .size_t)
 add_header(suseconds_t HDR suseconds_t.h)
+add_header(struct_dl_phdr_info HDR struct_dl_phdr_info.h DEPENDS .size_t libc.include.llvm-libc-macros.link_macros)
+add_header(__dl_iterate_phdr_callback_t HDR __dl_iterate_phdr_callback_t.h DEPENDS .size_t .struct_dl_phdr_info)
 add_header(struct_flock HDR struct_flock.h DEPENDS .off_t .pid_t)
 add_header(struct_flock64 HDR struct_flock64.h DEPENDS .off64_t .pid_t)
 add_header(struct_f_owner_ex HDR struct_f_owner_ex.h DEPENDS .pid_t)
diff --git a/libc/include/llvm-libc-types/Dl_info.h b/libc/include/llvm-libc-types/Dl_info.h
new file mode 100644
index 00000000000000..b082e30549a020
--- /dev/null
+++ b/libc/include/llvm-libc-types/Dl_info.h
@@ -0,0 +1,19 @@
+//===-- Definition of Dl_info type ----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_TYPES_DL_INFO_H
+#define LLVM_LIBC_TYPES_DL_INFO_H
+
+typedef struct {
+  const char *dli_fname;
+  void *dli_fbase;
+  const char *dli_sname;
+  void *dli_saddr;
+} Dl_info;
+
+#endif // LLVM_LIBC_TYPES_DL_INFO_H
diff --git a/libc/include/llvm-libc-types/__dl_iterate_phdr_callback_t.h b/libc/include/llvm-libc-types/__dl_iterate_phdr_callback_t.h
new file mode 100644
index 00000000000000..2f9a14cf5706cf
--- /dev/null
+++ b/libc/include/llvm-libc-types/__dl_iterate_phdr_callback_t.h
@@ -0,0 +1,18 @@
+//===-- Definition of type __dl_iterate_phdr_callback_t -------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_TYPES___DL_ITERATE_PHDR_CALLBACK_T_H
+#define LLVM_LIBC_TYPES___DL_ITERATE_PHDR_CALLBACK_T_H
+
+#include "size_t.h"
+#include "struct_dl_phdr_info.h"
+
+typedef int (*__dl_iterate_phdr_callback_t)(struct dl_phdr_info *, size_t,
+                                            void *);
+
+#endif // LLVM_LIBC_TYPES___DL_ITERATE_PHDR_CALLBACK_T_H
diff --git a/libc/include/llvm-libc-types/struct_dl_phdr_info.h b/libc/include/llvm-libc-types/struct_dl_phdr_info.h
new file mode 100644
index 00000000000000..fc407e3e954e78
--- /dev/null
+++ b/libc/include/llvm-libc-types/struct_dl_phdr_info.h
@@ -0,0 +1,26 @@
+//===-- Definition of type struct dl_phdr_info ----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_TYPES_STRUCT_DL_PHDR_INFO_H
+#define LLVM_LIBC_TYPES_STRUCT_DL_PHDR_INFO_H
+
+#include "../llvm-libc-macros/link-macros.h"
+#include "size_t.h"
+
+struct dl_phdr_info {
+  ElfW(Addr) dlpi_addr;
+  const char *dlpi_name;
+  const ElfW(Phdr) * dlpi_phdr;
+  ElfW(Half) dlpi_phnum;
+  unsigned long long dlpi_adds;
+  unsigned long long dlpi_subs;
+  size_t dlpi_tls_modid;
+  void *dlpi_tls_data;
+};
+
+#endif // LLVM_LIBC_TYPES_STRUCT_DL_PHDR_INFO_H
diff --git a/libc/src/CMakeLists.txt b/libc/src/CMakeLists.txt
index 9fc331ad18a391..268d977d28a8c2 100644
--- a/libc/src/CMakeLists.txt
+++ b/libc/src/CMakeLists.txt
@@ -6,6 +6,7 @@ add_subdirectory(dlfcn)
 add_subdirectory(errno)
 add_subdirectory(fenv)
 add_subdirectory(inttypes)
+add_subdirectory(link)
 add_subdirectory(math)
 add_subdirectory(stdbit)
 add_subdirectory(stdfix)
diff --git a/libc/src/dlfcn/CMakeLists.txt b/libc/src/dlfcn/CMakeLists.txt
index e3a51ba65764d4..205275a6825739 100644
--- a/libc/src/dlfcn/CMakeLists.txt
+++ b/libc/src/dlfcn/CMakeLists.txt
@@ -1,3 +1,13 @@
+add_entrypoint_object(
+  dladdr
+  SRCS
+    dladdr.cpp
+  HDRS
+    dladdr.h
+  DEPENDS
+    libc.include.dlfcn
+)
+
 add_entrypoint_object(
   dlclose
   SRCS
diff --git a/libc/src/dlfcn/dladdr.cpp b/libc/src/dlfcn/dladdr.cpp
new file mode 100644
index 00000000000000..824b4553120a2a
--- /dev/null
+++ b/libc/src/dlfcn/dladdr.cpp
@@ -0,0 +1,18 @@
+//===-- Implementation of dladdr -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "dladdr.h"
+
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, dladdr, (const void *, Dl_info *)) { return -1; }
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/dlfcn/dladdr.h b/libc/src/dlfcn/dladdr.h
new file mode 100644
index 00000000000000..58b859ff91e7e8
--- /dev/null
+++ b/libc/src/dlfcn/dladdr.h
@@ -0,0 +1,21 @@
+//===-- Implementation header of dladdr ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_DLFCN_DLADDR_H
+#define LLVM_LIBC_SRC_DLFCN_DLADDR_H
+
+#include "include/llvm-libc-types/Dl_info.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int dladdr(const void *, Dl_info *);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_DLFCN_DLADDR_H
diff --git a/libc/src/link/CMakeLists.txt b/libc/src/link/CMakeLists.txt
new file mode 100644
index 00000000000000..05c73a999d5490
--- /dev/null
+++ b/libc/src/link/CMakeLists.txt
@@ -0,0 +1,10 @@
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+  add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+endif()
+
+add_entrypoint_object(
+  dl_iterate_phdr
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.dl_iterate_phdr
+)
diff --git a/libc/src/link/dl_iterate_phdr.h b/libc/src/link/dl_iterate_phdr.h
new file mode 100644
index 00000000000000..9ef12839b43037
--- /dev/null
+++ b/libc/src/link/dl_iterate_phdr.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for dl_iterate_phdr ---------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_LINK_DL_ITERATE_PHDR_H
+#define LLVM_LIBC_SRC_LINK_DL_ITERATE_PHDR_H
+
+#include "include/llvm-libc-types/__dl_iterate_phdr_callback_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int dl_iterate_phdr(__dl_iterate_phdr_callback_t callback, void *data);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STRING_MEMCHR_H
diff --git a/libc/src/link/linux/CMakeLists.txt b/libc/src/link/linux/CMakeLists.txt
new file mode 100644
index 00000000000000..295981b2cb2444
--- /dev/null
+++ b/libc/src/link/linux/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_entrypoint_object(
+  dl_iterate_phdr
+  SRCS
+    dl_iterate_phdr.cpp
+  HDRS
+    ../dl_iterate_phdr.h
+  DEPENDS
+    libc.include.llvm-libc-types.__dl_iterate_phdr_callback_t
+    libc.include.llvm-libc-types.struct_dl_phdr_info
+    libc.include.llvm-libc-types.size_t
+)
diff --git a/libc/src/link/linux/dl_iterate_phdr.cpp b/libc/src/link/linux/dl_iterate_phdr.cpp
new file mode 100644
index 00000000000000..abcceebfb87b01
--- /dev/null
+++ b/libc/src/link/linux/dl_iterate_phdr.cpp
@@ -0,0 +1,57 @@
+//===-- Implementation of dl_iterate_phdr ---------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/link/dl_iterate_phdr.h"
+#include "config/linux/app.h"
+#include "include/llvm-libc-macros/sys-auxv-macros.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+[[gnu::weak,
+  gnu::visibility("hidden")]] extern const ElfW(Dyn) _DYNAMIC[]; // NOLINT
+
+#define AUX_CNT 38
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, dl_iterate_phdr,
+                   (__dl_iterate_phdr_callback_t callback, void *data)) {
+  size_t *auxv_ptr = reinterpret_cast<size_t *>(app.auxv_ptr);
+  size_t aux[AUX_CNT] = {0};
+
+  for (size_t i = 0; auxv_ptr[i]; i += 2) {
+    if (auxv_ptr[i] < AUX_CNT) {
+      aux[auxv_ptr[i]] = auxv_ptr[i + 1];
+    }
+  }
+
+  void *p;
+  size_t n;
+  size_t base = 0;
+  for (p = (void *)aux[AT_PHDR], n = aux[AT_PHNUM]; n;
+       n--, p = reinterpret_cast<void *>((uintptr_t)p + aux[AT_PHENT])) {
+    ElfW(Phdr) *phdr = (ElfW(Phdr) *)p;
+    if (phdr->p_type == PT_PHDR)
+      base = aux[AT_PHDR] - phdr->p_vaddr;
+    if (phdr->p_type == PT_DYNAMIC && _DYNAMIC)
+      base = (size_t)_DYNAMIC - phdr->p_vaddr;
+  }
+
+  struct dl_phdr_info info;
+  info.dlpi_addr = base;
+  info.dlpi_name = "/proc/self/exe";
+  info.dlpi_phdr = (const ElfW(Phdr) *)aux[AT_PHDR];
+  info.dlpi_phnum = (ElfW(Half))aux[AT_PHNUM];
+  info.dlpi_adds = 0;
+  info.dlpi_subs = 0;
+  info.dlpi_tls_modid = 0;
+  info.dlpi_tls_data = 0;
+  return callback(&info, sizeof(struct dl_phdr_info), data);
+}
+
+} // namespace LIBC_NAMESPACE_DECL



More information about the libc-commits mailing list