[RFC,2/5] ELF: Add machine-dependent main link map setup hook

Message ID alpine.DEB.2.00.1511200640370.6915@tp.orcam.me.uk
State New, archived

Commit Message

Maciej W. Rozycki Nov. 20, 2015, 7:30 a.m. UTC
  Add a hook allowing machine-dependent code to initialize its parts of 
the main link map at run time, in a way which can fail, presumably due 
to an incompatibility between the binary loaded and hardware which can 
only be detected at run time in a machine-dependent way, and only in our 
startup such as in the case of a binary loaded through an explicit 
invocation of the run-time loader.

Handle any failure appropriately, observing however that the failure 
path is called too early for `__r_strerror' to be able to retrieve an 
error message corresponding to the code passed in all cases, so a 
numerical value might only be reported instead.  This is supposed to 
never happen for static startup as in this case the operating system's 
kernel is expected to have rejected any incompatible binary, however 
handle a failure anyway, for consistency.

Assume the compiler will optimize the failure path in the default case 
of empty `elf_machine_main_map_setup' always succeeding.

	* elf/dl-machine-main-map-setup.h: New file.
	* elf/dl-support.c (_dl_non_dynamic_init): Call 
	* elf/rtld.c (dl_main): Likewise.


Index: glibc/elf/dl-machine-main-map-setup.h
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ glibc/elf/dl-machine-main-map-setup.h	2015-11-10 14:06:46.530434265 +0000
@@ -0,0 +1,33 @@ 
+/* Machine-dependent main link map setup for the ELF loader.
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   Lesser General Public License for more details.
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+#include <stdbool.h>
+/* Set up machine-dependent parts of the main link map.  Return 0
+   if successful.  */
+static inline int
+elf_machine_main_map_setup (struct link_map *map, bool rtld_is_main)
+  return 0;
+#endif /* dl-machine-main-map-setup.h */
Index: glibc/elf/dl-support.c
--- glibc.orig/elf/dl-support.c	2015-11-10 13:56:21.472052201 +0000
+++ glibc/elf/dl-support.c	2015-11-10 14:06:46.548882325 +0000
@@ -27,6 +27,7 @@ 
 #include <stdint.h>
 #include <ldsodefs.h>
 #include <dl-machine.h>
+#include <dl-machine-main-map-setup.h>
 #include <libc-lock.h>
 #include <dl-cache.h>
 #include <dl-librecon.h>
@@ -311,6 +312,12 @@  _dl_non_dynamic_init (void)
   _dl_main_map.l_phdr = GL(dl_phdr);
   _dl_main_map.l_phnum = GL(dl_phnum);
+  int err = elf_machine_main_map_setup (&_dl_main_map, false);
+  if (__glibc_unlikely (err))
+    _dl_signal_error (err, NULL,
+		      N_ ("error while initializing executable"),
+		      N_ ("platform setup error"));
     HP_TIMING_NOW (_dl_cpuclock_offset);
Index: glibc/elf/rtld.c
--- glibc.orig/elf/rtld.c	2015-11-10 13:56:21.493513731 +0000
+++ glibc/elf/rtld.c	2015-11-10 14:06:46.617728628 +0000
@@ -19,6 +19,7 @@ 
 #include <errno.h>
 #include <dlfcn.h>
 #include <fcntl.h>
+#include <libintl.h>
 #include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
@@ -36,6 +37,7 @@ 
 #include <dl-librecon.h>
 #include <unsecvars.h>
 #include <dl-cache.h>
+#include <dl-machine-main-map-setup.h>
 #include <dl-osinfo.h>
 #include <dl-procinfo.h>
 #include <tls.h>
@@ -1453,6 +1455,13 @@  ERROR: ld.so: object '%s' cannot be load
     GL(dl_rtld_map).l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) r;
+  /* Let any machine setup process the main map before objects are added.  */
+  int err = elf_machine_main_map_setup (main_map, rtld_is_main);
+  if (__glibc_unlikely (err))
+    _dl_signal_error (err, NULL,
+		      N_ ("error while initializing executable"),
+		      N_ ("platform setup error"));
   /* We start adding objects.  */
   r->r_state = RT_ADD;
   _dl_debug_state ();