misc/186435: [patch] Allow for an alternative run-time loader

Yuri yuri at rawbw.com
Sun Feb 23 09:10:01 UTC 2014


The following reply was made to PR misc/186435; it has been noted by GNATS.

From: Yuri <yuri at rawbw.com>
To: bug-followup at FreeBSD.org
Cc: Alexander Kabaev <kabaev at gmail.com>
Subject: Re: misc/186435: [patch] Allow for an alternative run-time loader
Date: Sun, 23 Feb 2014 00:50:37 -0800

 This is a multi-part message in MIME format.
 --------------010107090807030709030204
 Content-Type: text/plain; charset=ISO-8859-1; format=flowed
 Content-Transfer-Encoding: 7bit
 
 Yes, I knew that exposing locks is not nice. However, the upside was 
 that the patch was extremely simple.
 
 I reworked it into the proper implementation. I added r_debug_add and 
 r_debug_delete, with all locks hidden in them. They by themselves are 
 sufficient for the goal. I also added r_debug_iterate, in order to 
 potentially gain access to the list we are manipulating with. This is 
 just in order to not lose any functionality that was made available with 
 the previous patch.
 
 Yuri
 
 --------------010107090807030709030204
 Content-Type: text/plain; charset=UTF-8;
  name="patch-rtld-elf-alt-loader.patch"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
  filename="patch-rtld-elf-alt-loader.patch"
 
 Index: libexec/rtld-elf/Symbol.map
 ===================================================================
 --- libexec/rtld-elf/Symbol.map	(revision 260894)
 +++ libexec/rtld-elf/Symbol.map	(working copy)
 @@ -15,6 +15,9 @@
      dlinfo;
      dl_iterate_phdr;
      r_debug_state;
 +    r_debug_add;
 +    r_debug_delete;
 +    r_debug_iterate;
      __tls_get_addr;
  };
  
 Index: libexec/rtld-elf/rtld.c
 ===================================================================
 --- libexec/rtld-elf/rtld.c	(revision 260894)
 +++ libexec/rtld-elf/rtld.c	(working copy)
 @@ -100,8 +100,10 @@
  static void init_rtld(caddr_t, Elf_Auxinfo **);
  static void initlist_add_neededs(Needed_Entry *, Objlist *);
  static void initlist_add_objects(Obj_Entry *, Obj_Entry **, Objlist *);
 -static void linkmap_add(Obj_Entry *);
 -static void linkmap_delete(Obj_Entry *);
 +static void linkmap_add_obj(Obj_Entry *);
 +static void linkmap_add_map(struct link_map *);
 +static void linkmap_delete_obj(Obj_Entry *);
 +static void linkmap_delete_map(struct link_map *);
  static void load_filtees(Obj_Entry *, int flags, RtldLockState *);
  static void unload_filtees(Obj_Entry *);
  static int load_needed_objects(Obj_Entry *, int);
 @@ -513,8 +515,8 @@
  	obj_main->path, obj_main->valid_hash_sysv, obj_main->valid_hash_gnu,
  	obj_main->dynsymcount);
  
 -    linkmap_add(obj_main);
 -    linkmap_add(&obj_rtld);
 +    linkmap_add_obj(obj_main);
 +    linkmap_add_obj(&obj_rtld);
  
      /* Link the main program into the list of objects. */
      *obj_tail = obj_main;
 @@ -2155,7 +2157,7 @@
      obj_tail = &obj->next;
      obj_count++;
      obj_loads++;
 -    linkmap_add(obj);	/* for GDB & dlinfo() */
 +    linkmap_add_obj(obj);	/* for GDB & dlinfo() */
      max_stack_flags |= obj->stack_flags;
  
      dbg("  %p .. %p: %s", obj->mapbase,
 @@ -3428,19 +3430,26 @@
  }
  
  static void
 -linkmap_add(Obj_Entry *obj)
 +linkmap_add_obj(Obj_Entry *obj)
  {
      struct link_map *l = &obj->linkmap;
 -    struct link_map *prev;
  
 -    obj->linkmap.l_name = obj->path;
 -    obj->linkmap.l_addr = obj->mapbase;
 -    obj->linkmap.l_ld = obj->dynamic;
 +    l->l_name = obj->path;
 +    l->l_addr = obj->mapbase;
 +    l->l_ld = obj->dynamic;
  #ifdef __mips__
      /* GDB needs load offset on MIPS to use the symbols */
 -    obj->linkmap.l_offs = obj->relocbase;
 +    l->l_offs = obj->relocbase;
  #endif
  
 +    linkmap_add_map(l);
 +}
 +
 +static void
 +linkmap_add_map(struct link_map *l)
 +{
 +    struct link_map *prev;
 +
      if (r_debug.r_map == NULL) {
  	r_debug.r_map = l;
  	return;
 @@ -3464,10 +3473,14 @@
  }
  
  static void
 -linkmap_delete(Obj_Entry *obj)
 +linkmap_delete_obj(Obj_Entry *obj)
  {
 -    struct link_map *l = &obj->linkmap;
 +    linkmap_delete_map(&obj->linkmap);
 +}
  
 +static void
 +linkmap_delete_map(struct link_map *l)
 +{
      if (l->l_prev == NULL) {
  	if ((r_debug.r_map = l->l_next) != NULL)
  	    l->l_next->l_prev = NULL;
 @@ -4092,7 +4105,7 @@
  	    dbg("unloading \"%s\"", obj->path);
  	    unload_filtees(root);
  	    munmap(obj->mapbase, obj->mapsize);
 -	    linkmap_delete(obj);
 +	    linkmap_delete_obj(obj);
  	    *linkp = obj->next;
  	    obj_count--;
  	    obj_free(obj);
 @@ -4809,6 +4822,58 @@
  int _thread_autoinit_dummy_decl = 1;
  
  /*
 + * Support for an alternative loader
 + */
 +
 +void
 +r_debug_add(struct link_map *m)
 +{
 +	RtldLockState lockstate;
 +	wlock_acquire(rtld_bind_lock, &lockstate);
 +	GDB_STATE(RT_ADD,NULL);
 +	linkmap_add_map(m);
 +	GDB_STATE(RT_CONSISTENT, m)
 +	lock_release(rtld_bind_lock, &lockstate);
 +}
 +
 +void
 +r_debug_delete(struct link_map *m)
 +{
 +	RtldLockState lockstate;
 +	wlock_acquire(rtld_bind_lock, &lockstate);
 +	GDB_STATE(RT_DELETE, m);
 +	linkmap_delete_map(m);
 +	GDB_STATE(RT_CONSISTENT, NULL);
 +	lock_release(rtld_bind_lock, &lockstate);
 +}
 +
 +int
 +r_debug_iterate(int wr, int (*callback)(struct link_map *, void *), void *param)
 +{
 +	struct link_map *m;
 +	int error = 0;
 +	RtldLockState lockstate;
 +
 +	if (wr) {
 +		wlock_acquire(rtld_bind_lock, &lockstate);
 +	} else {
 +		rlock_acquire(rtld_bind_lock, &lockstate);
 +	}
 +
 +	/*
 +	 * Iterate while callback returns zero
 +	 */
 +	for (m = r_debug.r_map;
 +	     m != NULL && (error = callback(m, param)) == 0;
 +	     m = m->l_next)
 +	     ;
 +
 +	lock_release(rtld_bind_lock, &lockstate);
 +
 +	return error;
 +}
 +
 +/*
   * No unresolved symbols for rtld.
   */
  void
 Index: sys/sys/link_elf.h
 ===================================================================
 --- sys/sys/link_elf.h	(revision 260894)
 +++ sys/sys/link_elf.h	(working copy)
 @@ -94,6 +94,9 @@
  extern int dl_iterate_phdr(__dl_iterate_hdr_callback, void *);
  int _rtld_addr_phdr(const void *, struct dl_phdr_info *);
  int _rtld_get_stack_prot(void);
 +void r_debug_add(struct link_map *);
 +void r_debug_delete(struct link_map *);
 +int r_debug_iterate(int, int (*callback)(struct link_map *, void *), void *);
  
  __END_DECLS
  
 
 --------------010107090807030709030204--


More information about the freebsd-bugs mailing list