dl_iterate_phdr.c raw

   1  #include <elf.h>
   2  #include <link.h>
   3  #include "pthread_impl.h"
   4  #include "libc.h"
   5  
   6  #define AUX_CNT 38
   7  
   8  extern weak hidden const size_t _DYNAMIC[];
   9  
  10  static int static_dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size_t size, void *data), void *data)
  11  {
  12  	unsigned char *p;
  13  	ElfW(Phdr) *phdr, *tls_phdr=0;
  14  	size_t base = 0;
  15  	size_t n;
  16  	struct dl_phdr_info info;
  17  	size_t i, aux[AUX_CNT] = {0};
  18  
  19  	for (i=0; libc.auxv[i]; i+=2)
  20  		if (libc.auxv[i]<AUX_CNT) aux[libc.auxv[i]] = libc.auxv[i+1];
  21  
  22  	for (p=(void *)aux[AT_PHDR],n=aux[AT_PHNUM]; n; n--,p+=aux[AT_PHENT]) {
  23  		phdr = (void *)p;
  24  		if (phdr->p_type == PT_PHDR)
  25  			base = aux[AT_PHDR] - phdr->p_vaddr;
  26  		if (phdr->p_type == PT_DYNAMIC && _DYNAMIC)
  27  			base = (size_t)_DYNAMIC - phdr->p_vaddr;
  28  		if (phdr->p_type == PT_TLS)
  29  			tls_phdr = phdr;
  30  	}
  31  	info.dlpi_addr  = base;
  32  	info.dlpi_name  = "/proc/self/exe";
  33  	info.dlpi_phdr  = (void *)aux[AT_PHDR];
  34  	info.dlpi_phnum = aux[AT_PHNUM];
  35  	info.dlpi_adds  = 0;
  36  	info.dlpi_subs  = 0;
  37  	if (tls_phdr) {
  38  		info.dlpi_tls_modid = 1;
  39  		info.dlpi_tls_data = __tls_get_addr((tls_mod_off_t[]){1,0});
  40  	} else {
  41  		info.dlpi_tls_modid = 0;
  42  		info.dlpi_tls_data = 0;
  43  	}
  44  	return (callback)(&info, sizeof (info), data);
  45  }
  46  
  47  weak_alias(static_dl_iterate_phdr, dl_iterate_phdr);
  48