@ -56,6 +56,7 @@ struct dso {
Phdr * phdr ;
Phdr * phdr ;
int phnum ;
int phnum ;
size_t phentsize ;
int refcnt ;
int refcnt ;
Sym * syms ;
Sym * syms ;
uint32_t * hashtab ;
uint32_t * hashtab ;
@ -298,9 +299,12 @@ static void reclaim(struct dso *dso, size_t start, size_t end)
free ( a ) ;
free ( a ) ;
}
}
static void reclaim_gaps ( struct dso * dso , Phdr * ph , size_t phent , size_t phcnt )
static void reclaim_gaps ( struct dso * dso )
{
{
for ( ; phcnt - - ; ph = ( void * ) ( ( char * ) ph + phent ) ) {
Phdr * ph ;
size_t phcnt ;
for ( phcnt = dso - > phnum , ph = dso - > phdr ; phcnt - - ; ph = ( void * ) ( ( char * ) ph + dso - > phentsize ) ) {
if ( ph - > p_type ! = PT_LOAD ) continue ;
if ( ph - > p_type ! = PT_LOAD ) continue ;
if ( ( ph - > p_flags & ( PF_R | PF_W ) ) ! = ( PF_R | PF_W ) ) continue ;
if ( ( ph - > p_flags & ( PF_R | PF_W ) ) ! = ( PF_R | PF_W ) ) continue ;
reclaim ( dso , ph - > p_vaddr & - PAGE_SIZE , ph - > p_vaddr ) ;
reclaim ( dso , ph - > p_vaddr & - PAGE_SIZE , ph - > p_vaddr ) ;
@ -400,6 +404,7 @@ static void *map_library(int fd, struct dso *dso)
dso - > phdr = ( void * ) ( base + ph - > p_vaddr
dso - > phdr = ( void * ) ( base + ph - > p_vaddr
+ ( eh - > e_phoff - ph - > p_offset ) ) ;
+ ( eh - > e_phoff - ph - > p_offset ) ) ;
dso - > phnum = eh - > e_phnum ;
dso - > phnum = eh - > e_phnum ;
dso - > phentsize = eh - > e_phentsize ;
}
}
/* Reuse the existing mapping for the lowest-address LOAD */
/* Reuse the existing mapping for the lowest-address LOAD */
if ( ( ph - > p_vaddr & - PAGE_SIZE ) = = addr_min ) continue ;
if ( ( ph - > p_vaddr & - PAGE_SIZE ) = = addr_min ) continue ;
@ -430,7 +435,7 @@ static void *map_library(int fd, struct dso *dso)
dso - > base = base ;
dso - > base = base ;
dso - > dynv = ( void * ) ( base + dyn ) ;
dso - > dynv = ( void * ) ( base + dyn ) ;
if ( dso - > tls_size ) dso - > tls_image = ( void * ) ( base + tls_image ) ;
if ( dso - > tls_size ) dso - > tls_image = ( void * ) ( base + tls_image ) ;
if ( ! runtime ) reclaim_gaps ( dso , ph0 , eh - > e_phentsize , eh - > e_phnum ) ;
if ( ! runtime ) reclaim_gaps ( dso ) ;
free ( allocated_buf ) ;
free ( allocated_buf ) ;
return map ;
return map ;
noexec :
noexec :
@ -787,19 +792,14 @@ static void reloc_all(struct dso *p)
}
}
}
}
static size_t find_dyn ( Phdr * ph , size_t cnt , size_t stride )
static void kernel_mapped_dso ( struct dso * p )
{
for ( ; cnt - - ; ph = ( void * ) ( ( char * ) ph + stride ) )
if ( ph - > p_type = = PT_DYNAMIC )
return ph - > p_vaddr ;
return 0 ;
}
static void find_map_range ( Phdr * ph , size_t cnt , size_t stride , struct dso * p )
{
{
size_t min_addr = - 1 , max_addr = 0 ;
size_t min_addr = - 1 , max_addr = 0 , cnt ;
for ( ; cnt - - ; ph = ( void * ) ( ( char * ) ph + stride ) ) {
Phdr * ph = p - > phdr ;
if ( ph - > p_type = = PT_GNU_RELRO ) {
for ( cnt = p - > phnum ; cnt - - ; ph = ( void * ) ( ( char * ) ph + p - > phentsize ) ) {
if ( ph - > p_type = = PT_DYNAMIC ) {
p - > dynv = ( void * ) ( p - > base + ph - > p_vaddr ) ;
} else if ( ph - > p_type = = PT_GNU_RELRO ) {
p - > relro_start = ph - > p_vaddr & - PAGE_SIZE ;
p - > relro_start = ph - > p_vaddr & - PAGE_SIZE ;
p - > relro_end = ( ph - > p_vaddr + ph - > p_memsz ) & - PAGE_SIZE ;
p - > relro_end = ( ph - > p_vaddr + ph - > p_memsz ) & - PAGE_SIZE ;
}
}
@ -813,6 +813,7 @@ static void find_map_range(Phdr *ph, size_t cnt, size_t stride, struct dso *p)
max_addr = ( max_addr + PAGE_SIZE - 1 ) & - PAGE_SIZE ;
max_addr = ( max_addr + PAGE_SIZE - 1 ) & - PAGE_SIZE ;
p - > map = p - > base + min_addr ;
p - > map = p - > base + min_addr ;
p - > map_len = max_addr - min_addr ;
p - > map_len = max_addr - min_addr ;
p - > kernel_mapped = 1 ;
}
}
static void do_fini ( )
static void do_fini ( )
@ -1023,13 +1024,11 @@ void *__dynlink(int argc, char **argv)
lib - > base = ( void * ) aux [ AT_BASE ] ;
lib - > base = ( void * ) aux [ AT_BASE ] ;
lib - > name = lib - > shortname = " libc.so " ;
lib - > name = lib - > shortname = " libc.so " ;
lib - > global = 1 ;
lib - > global = 1 ;
lib - > kernel_mapped = 1 ;
ehdr = ( void * ) lib - > base ;
ehdr = ( void * ) lib - > base ;
lib - > phnum = ehdr - > e_phnum ;
lib - > phnum = ehdr - > e_phnum ;
lib - > phdr = ( void * ) ( aux [ AT_BASE ] + ehdr - > e_phoff ) ;
lib - > phdr = ( void * ) ( aux [ AT_BASE ] + ehdr - > e_phoff ) ;
find_map_range ( lib - > phdr , ehdr - > e_phnum , ehdr - > e_phentsize , lib ) ;
lib - > phentsize = ehdr - > e_phentsize ;
lib - > dynv = ( void * ) ( lib - > base + find_dyn ( lib - > phdr ,
kernel_mapped_dso ( lib ) ;
ehdr - > e_phnum , ehdr - > e_phentsize ) ) ;
decode_dyn ( lib ) ;
decode_dyn ( lib ) ;
if ( aux [ AT_PHDR ] ) {
if ( aux [ AT_PHDR ] ) {
@ -1038,6 +1037,7 @@ void *__dynlink(int argc, char **argv)
/* Find load address of the main program, via AT_PHDR vs PT_PHDR. */
/* Find load address of the main program, via AT_PHDR vs PT_PHDR. */
app - > phdr = phdr = ( void * ) aux [ AT_PHDR ] ;
app - > phdr = phdr = ( void * ) aux [ AT_PHDR ] ;
app - > phnum = aux [ AT_PHNUM ] ;
app - > phnum = aux [ AT_PHNUM ] ;
app - > phentsize = aux [ AT_PHENT ] ;
for ( i = aux [ AT_PHNUM ] ; i ; i - - , phdr = ( void * ) ( ( char * ) phdr + aux [ AT_PHENT ] ) ) {
for ( i = aux [ AT_PHNUM ] ; i ; i - - , phdr = ( void * ) ( ( char * ) phdr + aux [ AT_PHENT ] ) ) {
if ( phdr - > p_type = = PT_PHDR )
if ( phdr - > p_type = = PT_PHDR )
app - > base = ( void * ) ( aux [ AT_PHDR ] - phdr - > p_vaddr ) ;
app - > base = ( void * ) ( aux [ AT_PHDR ] - phdr - > p_vaddr ) ;
@ -1057,11 +1057,7 @@ void *__dynlink(int argc, char **argv)
app - > name = ( char * ) aux [ AT_EXECFN ] ;
app - > name = ( char * ) aux [ AT_EXECFN ] ;
else
else
app - > name = argv [ 0 ] ;
app - > name = argv [ 0 ] ;
app - > kernel_mapped = 1 ;
kernel_mapped_dso ( app ) ;
app - > dynv = ( void * ) ( app - > base + find_dyn (
( void * ) aux [ AT_PHDR ] , aux [ AT_PHNUM ] , aux [ AT_PHENT ] ) ) ;
find_map_range ( ( void * ) aux [ AT_PHDR ] ,
aux [ AT_PHNUM ] , aux [ AT_PHENT ] , app ) ;
} else {
} else {
int fd ;
int fd ;
char * ldname = argv [ 0 ] ;
char * ldname = argv [ 0 ] ;
@ -1127,6 +1123,7 @@ void *__dynlink(int argc, char **argv)
ehdr = ( void * ) vdso_base ;
ehdr = ( void * ) vdso_base ;
vdso - > phdr = phdr = ( void * ) ( vdso_base + ehdr - > e_phoff ) ;
vdso - > phdr = phdr = ( void * ) ( vdso_base + ehdr - > e_phoff ) ;
vdso - > phnum = ehdr - > e_phnum ;
vdso - > phnum = ehdr - > e_phnum ;
vdso - > phentsize = ehdr - > e_phentsize ;
for ( i = ehdr - > e_phnum ; i ; i - - , phdr = ( void * ) ( ( char * ) phdr + ehdr - > e_phentsize ) ) {
for ( i = ehdr - > e_phnum ; i ; i - - , phdr = ( void * ) ( ( char * ) phdr + ehdr - > e_phentsize ) ) {
if ( phdr - > p_type = = PT_DYNAMIC )
if ( phdr - > p_type = = PT_DYNAMIC )
vdso - > dynv = ( void * ) ( vdso_base + phdr - > p_offset ) ;
vdso - > dynv = ( void * ) ( vdso_base + phdr - > p_offset ) ;
@ -1154,10 +1151,8 @@ void *__dynlink(int argc, char **argv)
/* PAST THIS POINT, ALL LIBC INTERFACES ARE FULLY USABLE. */
/* PAST THIS POINT, ALL LIBC INTERFACES ARE FULLY USABLE. */
/* Donate unused parts of app and library mapping to malloc */
/* Donate unused parts of app and library mapping to malloc */
reclaim_gaps ( app , ( void * ) aux [ AT_PHDR ] , aux [ AT_PHENT ] , aux [ AT_PHNUM ] ) ;
reclaim_gaps ( app ) ;
ehdr = ( void * ) lib - > base ;
reclaim_gaps ( lib ) ;
reclaim_gaps ( lib , ( void * ) ( lib - > base + ehdr - > e_phoff ) ,
ehdr - > e_phentsize , ehdr - > e_phnum ) ;
/* Load preload/needed libraries, add their symbols to the global
/* Load preload/needed libraries, add their symbols to the global
* namespace , and perform all remaining relocations . The main
* namespace , and perform all remaining relocations . The main