1*0c0fea5dSIngo Weinhold /* 2*0c0fea5dSIngo Weinhold * Copyright 2003-2007, Axel Dörfler, axeld@pinc-software.de. 3*0c0fea5dSIngo Weinhold * Distributed under the terms of the MIT License. 4*0c0fea5dSIngo Weinhold * 5*0c0fea5dSIngo Weinhold * Copyright 2002, Manuel J. Petit. All rights reserved. 6*0c0fea5dSIngo Weinhold * Copyright 2001, Travis Geiselbrecht. All rights reserved. 7*0c0fea5dSIngo Weinhold * Distributed under the terms of the NewOS License. 8*0c0fea5dSIngo Weinhold */ 9*0c0fea5dSIngo Weinhold 10*0c0fea5dSIngo Weinhold 11*0c0fea5dSIngo Weinhold #include "runtime_loader_private.h" 12*0c0fea5dSIngo Weinhold 13*0c0fea5dSIngo Weinhold #include <OS.h> 14*0c0fea5dSIngo Weinhold 15*0c0fea5dSIngo Weinhold #include <elf32.h> 16*0c0fea5dSIngo Weinhold #include <user_runtime.h> 17*0c0fea5dSIngo Weinhold #include <syscalls.h> 18*0c0fea5dSIngo Weinhold #include <vm_types.h> 19*0c0fea5dSIngo Weinhold #include <arch/cpu.h> 20*0c0fea5dSIngo Weinhold #include <sem.h> 21*0c0fea5dSIngo Weinhold #include <runtime_loader.h> 22*0c0fea5dSIngo Weinhold 23*0c0fea5dSIngo Weinhold #include <string.h> 24*0c0fea5dSIngo Weinhold #include <stdio.h> 25*0c0fea5dSIngo Weinhold #include <stdlib.h> 26*0c0fea5dSIngo Weinhold 27*0c0fea5dSIngo Weinhold 28*0c0fea5dSIngo Weinhold //#define TRACE_RLD 29*0c0fea5dSIngo Weinhold #ifdef TRACE_RLD 30*0c0fea5dSIngo Weinhold # define TRACE(x) dprintf x 31*0c0fea5dSIngo Weinhold #else 32*0c0fea5dSIngo Weinhold # define TRACE(x) ; 33*0c0fea5dSIngo Weinhold #endif 34*0c0fea5dSIngo Weinhold 35*0c0fea5dSIngo Weinhold 36*0c0fea5dSIngo Weinhold // ToDo: implement better locking strategy 37*0c0fea5dSIngo Weinhold // ToDo: implement lazy binding 38*0c0fea5dSIngo Weinhold 39*0c0fea5dSIngo Weinhold #define PAGE_MASK (B_PAGE_SIZE - 1) 40*0c0fea5dSIngo Weinhold 41*0c0fea5dSIngo Weinhold #define PAGE_OFFSET(x) ((x) & (PAGE_MASK)) 42*0c0fea5dSIngo Weinhold #define PAGE_BASE(x) ((x) & ~(PAGE_MASK)) 43*0c0fea5dSIngo Weinhold #define TO_PAGE_SIZE(x) ((x + (PAGE_MASK)) & ~(PAGE_MASK)) 44*0c0fea5dSIngo Weinhold 45*0c0fea5dSIngo Weinhold #define RLD_PROGRAM_BASE 0x00200000 46*0c0fea5dSIngo Weinhold /* keep in sync with app ldscript */ 47*0c0fea5dSIngo Weinhold 48*0c0fea5dSIngo Weinhold enum { 49*0c0fea5dSIngo Weinhold RFLAG_RW = 0x0001, 50*0c0fea5dSIngo Weinhold RFLAG_ANON = 0x0002, 51*0c0fea5dSIngo Weinhold 52*0c0fea5dSIngo Weinhold RFLAG_TERMINATED = 0x0200, 53*0c0fea5dSIngo Weinhold RFLAG_INITIALIZED = 0x0400, 54*0c0fea5dSIngo Weinhold RFLAG_SYMBOLIC = 0x0800, 55*0c0fea5dSIngo Weinhold RFLAG_RELOCATED = 0x1000, 56*0c0fea5dSIngo Weinhold RFLAG_PROTECTED = 0x2000, 57*0c0fea5dSIngo Weinhold RFLAG_DEPENDENCIES_LOADED = 0x4000, 58*0c0fea5dSIngo Weinhold RFLAG_REMAPPED = 0x8000 59*0c0fea5dSIngo Weinhold }; 60*0c0fea5dSIngo Weinhold 61*0c0fea5dSIngo Weinhold 62*0c0fea5dSIngo Weinhold #define IMAGE_TYPE_TO_MASK(type) (1 << ((type) - 1)) 63*0c0fea5dSIngo Weinhold #define ALL_IMAGE_TYPES (IMAGE_TYPE_TO_MASK(B_APP_IMAGE) \ 64*0c0fea5dSIngo Weinhold | IMAGE_TYPE_TO_MASK(B_LIBRARY_IMAGE) \ 65*0c0fea5dSIngo Weinhold | IMAGE_TYPE_TO_MASK(B_ADD_ON_IMAGE) \ 66*0c0fea5dSIngo Weinhold | IMAGE_TYPE_TO_MASK(B_SYSTEM_IMAGE)) 67*0c0fea5dSIngo Weinhold #define APP_OR_LIBRARY_TYPE (IMAGE_TYPE_TO_MASK(B_APP_IMAGE) \ 68*0c0fea5dSIngo Weinhold | IMAGE_TYPE_TO_MASK(B_LIBRARY_IMAGE)) 69*0c0fea5dSIngo Weinhold 70*0c0fea5dSIngo Weinhold typedef void (*init_term_function)(image_id); 71*0c0fea5dSIngo Weinhold 72*0c0fea5dSIngo Weinhold static image_queue_t sLoadedImages = {0, 0}; 73*0c0fea5dSIngo Weinhold static image_queue_t sLoadingImages = {0, 0}; 74*0c0fea5dSIngo Weinhold static image_queue_t sDisposableImages = {0, 0}; 75*0c0fea5dSIngo Weinhold static uint32 sLoadedImageCount = 0; 76*0c0fea5dSIngo Weinhold static image_t *sProgramImage; 77*0c0fea5dSIngo Weinhold 78*0c0fea5dSIngo Weinhold // a recursive lock 79*0c0fea5dSIngo Weinhold static sem_id rld_sem; 80*0c0fea5dSIngo Weinhold static thread_id rld_sem_owner; 81*0c0fea5dSIngo Weinhold static int32 rld_sem_count; 82*0c0fea5dSIngo Weinhold 83*0c0fea5dSIngo Weinhold 84*0c0fea5dSIngo Weinhold #ifdef TRACE_RLD 85*0c0fea5dSIngo Weinhold # define FATAL(x...) dprintf("runtime_loader: " x); 86*0c0fea5dSIngo Weinhold 87*0c0fea5dSIngo Weinhold void 88*0c0fea5dSIngo Weinhold dprintf(const char *format, ...) 89*0c0fea5dSIngo Weinhold { 90*0c0fea5dSIngo Weinhold char buffer[1024]; 91*0c0fea5dSIngo Weinhold 92*0c0fea5dSIngo Weinhold va_list list; 93*0c0fea5dSIngo Weinhold va_start(list, format); 94*0c0fea5dSIngo Weinhold 95*0c0fea5dSIngo Weinhold vsnprintf(buffer, sizeof(buffer), format, list); 96*0c0fea5dSIngo Weinhold _kern_debug_output(buffer); 97*0c0fea5dSIngo Weinhold 98*0c0fea5dSIngo Weinhold va_end(list); 99*0c0fea5dSIngo Weinhold } 100*0c0fea5dSIngo Weinhold #else 101*0c0fea5dSIngo Weinhold # define FATAL(x...) printf("runtime_loader: " x); 102*0c0fea5dSIngo Weinhold #endif 103*0c0fea5dSIngo Weinhold 104*0c0fea5dSIngo Weinhold 105*0c0fea5dSIngo Weinhold static void 106*0c0fea5dSIngo Weinhold rld_unlock() 107*0c0fea5dSIngo Weinhold { 108*0c0fea5dSIngo Weinhold if (rld_sem_count-- == 1) { 109*0c0fea5dSIngo Weinhold rld_sem_owner = -1; 110*0c0fea5dSIngo Weinhold release_sem(rld_sem); 111*0c0fea5dSIngo Weinhold } 112*0c0fea5dSIngo Weinhold } 113*0c0fea5dSIngo Weinhold 114*0c0fea5dSIngo Weinhold 115*0c0fea5dSIngo Weinhold static void 116*0c0fea5dSIngo Weinhold rld_lock() 117*0c0fea5dSIngo Weinhold { 118*0c0fea5dSIngo Weinhold thread_id self = find_thread(NULL); 119*0c0fea5dSIngo Weinhold if (self != rld_sem_owner) { 120*0c0fea5dSIngo Weinhold acquire_sem(rld_sem); 121*0c0fea5dSIngo Weinhold rld_sem_owner = self; 122*0c0fea5dSIngo Weinhold } 123*0c0fea5dSIngo Weinhold rld_sem_count++; 124*0c0fea5dSIngo Weinhold } 125*0c0fea5dSIngo Weinhold 126*0c0fea5dSIngo Weinhold 127*0c0fea5dSIngo Weinhold static void 128*0c0fea5dSIngo Weinhold enqueue_image(image_queue_t *queue, image_t *image) 129*0c0fea5dSIngo Weinhold { 130*0c0fea5dSIngo Weinhold image->next = 0; 131*0c0fea5dSIngo Weinhold 132*0c0fea5dSIngo Weinhold image->prev = queue->tail; 133*0c0fea5dSIngo Weinhold if (queue->tail) 134*0c0fea5dSIngo Weinhold queue->tail->next = image; 135*0c0fea5dSIngo Weinhold 136*0c0fea5dSIngo Weinhold queue->tail = image; 137*0c0fea5dSIngo Weinhold if (!queue->head) 138*0c0fea5dSIngo Weinhold queue->head = image; 139*0c0fea5dSIngo Weinhold } 140*0c0fea5dSIngo Weinhold 141*0c0fea5dSIngo Weinhold 142*0c0fea5dSIngo Weinhold static void 143*0c0fea5dSIngo Weinhold dequeue_image(image_queue_t *queue, image_t *image) 144*0c0fea5dSIngo Weinhold { 145*0c0fea5dSIngo Weinhold if (image->next) 146*0c0fea5dSIngo Weinhold image->next->prev = image->prev; 147*0c0fea5dSIngo Weinhold else 148*0c0fea5dSIngo Weinhold queue->tail = image->prev; 149*0c0fea5dSIngo Weinhold 150*0c0fea5dSIngo Weinhold if (image->prev) 151*0c0fea5dSIngo Weinhold image->prev->next = image->next; 152*0c0fea5dSIngo Weinhold else 153*0c0fea5dSIngo Weinhold queue->head = image->next; 154*0c0fea5dSIngo Weinhold 155*0c0fea5dSIngo Weinhold image->prev = 0; 156*0c0fea5dSIngo Weinhold image->next = 0; 157*0c0fea5dSIngo Weinhold } 158*0c0fea5dSIngo Weinhold 159*0c0fea5dSIngo Weinhold 160*0c0fea5dSIngo Weinhold static uint32 161*0c0fea5dSIngo Weinhold elf_hash(const uint8 *name) 162*0c0fea5dSIngo Weinhold { 163*0c0fea5dSIngo Weinhold uint32 hash = 0; 164*0c0fea5dSIngo Weinhold uint32 temp; 165*0c0fea5dSIngo Weinhold 166*0c0fea5dSIngo Weinhold while (*name) { 167*0c0fea5dSIngo Weinhold hash = (hash << 4) + *name++; 168*0c0fea5dSIngo Weinhold if ((temp = hash & 0xf0000000)) { 169*0c0fea5dSIngo Weinhold hash ^= temp >> 24; 170*0c0fea5dSIngo Weinhold } 171*0c0fea5dSIngo Weinhold hash &= ~temp; 172*0c0fea5dSIngo Weinhold } 173*0c0fea5dSIngo Weinhold return hash; 174*0c0fea5dSIngo Weinhold } 175*0c0fea5dSIngo Weinhold 176*0c0fea5dSIngo Weinhold 177*0c0fea5dSIngo Weinhold static image_t * 178*0c0fea5dSIngo Weinhold find_image_in_queue(image_queue_t *queue, const char *name, bool isPath, 179*0c0fea5dSIngo Weinhold uint32 typeMask) 180*0c0fea5dSIngo Weinhold { 181*0c0fea5dSIngo Weinhold image_t *image; 182*0c0fea5dSIngo Weinhold 183*0c0fea5dSIngo Weinhold for (image = queue->head; image; image = image->next) { 184*0c0fea5dSIngo Weinhold const char *imageName = isPath ? image->path : image->name; 185*0c0fea5dSIngo Weinhold int length = isPath ? sizeof(image->path) : sizeof(image->name); 186*0c0fea5dSIngo Weinhold 187*0c0fea5dSIngo Weinhold if (!strncmp(imageName, name, length) 188*0c0fea5dSIngo Weinhold && (typeMask & IMAGE_TYPE_TO_MASK(image->type)) != 0) { 189*0c0fea5dSIngo Weinhold return image; 190*0c0fea5dSIngo Weinhold } 191*0c0fea5dSIngo Weinhold } 192*0c0fea5dSIngo Weinhold 193*0c0fea5dSIngo Weinhold return NULL; 194*0c0fea5dSIngo Weinhold } 195*0c0fea5dSIngo Weinhold 196*0c0fea5dSIngo Weinhold 197*0c0fea5dSIngo Weinhold static image_t * 198*0c0fea5dSIngo Weinhold find_image(char const *name, uint32 typeMask) 199*0c0fea5dSIngo Weinhold { 200*0c0fea5dSIngo Weinhold bool isPath = (strchr(name, '/') != NULL); 201*0c0fea5dSIngo Weinhold image_t *image; 202*0c0fea5dSIngo Weinhold 203*0c0fea5dSIngo Weinhold image = find_image_in_queue(&sLoadedImages, name, isPath, typeMask); 204*0c0fea5dSIngo Weinhold if (image == NULL) 205*0c0fea5dSIngo Weinhold image = find_image_in_queue(&sLoadingImages, name, isPath, typeMask); 206*0c0fea5dSIngo Weinhold 207*0c0fea5dSIngo Weinhold return image; 208*0c0fea5dSIngo Weinhold } 209*0c0fea5dSIngo Weinhold 210*0c0fea5dSIngo Weinhold 211*0c0fea5dSIngo Weinhold static image_t * 212*0c0fea5dSIngo Weinhold find_loaded_image_by_id(image_id id) 213*0c0fea5dSIngo Weinhold { 214*0c0fea5dSIngo Weinhold image_t *image; 215*0c0fea5dSIngo Weinhold 216*0c0fea5dSIngo Weinhold for (image = sLoadedImages.head; image; image = image->next) { 217*0c0fea5dSIngo Weinhold if (image->id == id) 218*0c0fea5dSIngo Weinhold return image; 219*0c0fea5dSIngo Weinhold } 220*0c0fea5dSIngo Weinhold 221*0c0fea5dSIngo Weinhold // For the termination routine, we need to look into the list of 222*0c0fea5dSIngo Weinhold // disposable images as well 223*0c0fea5dSIngo Weinhold for (image = sDisposableImages.head; image; image = image->next) { 224*0c0fea5dSIngo Weinhold if (image->id == id) 225*0c0fea5dSIngo Weinhold return image; 226*0c0fea5dSIngo Weinhold } 227*0c0fea5dSIngo Weinhold 228*0c0fea5dSIngo Weinhold return NULL; 229*0c0fea5dSIngo Weinhold } 230*0c0fea5dSIngo Weinhold 231*0c0fea5dSIngo Weinhold 232*0c0fea5dSIngo Weinhold static status_t 233*0c0fea5dSIngo Weinhold parse_elf_header(struct Elf32_Ehdr *eheader, int32 *_pheaderSize, int32 *_sheaderSize) 234*0c0fea5dSIngo Weinhold { 235*0c0fea5dSIngo Weinhold if (memcmp(eheader->e_ident, ELF_MAGIC, 4) != 0) 236*0c0fea5dSIngo Weinhold return B_NOT_AN_EXECUTABLE; 237*0c0fea5dSIngo Weinhold 238*0c0fea5dSIngo Weinhold if (eheader->e_ident[4] != ELFCLASS32) 239*0c0fea5dSIngo Weinhold return B_NOT_AN_EXECUTABLE; 240*0c0fea5dSIngo Weinhold 241*0c0fea5dSIngo Weinhold if (eheader->e_phoff == 0) 242*0c0fea5dSIngo Weinhold return B_NOT_AN_EXECUTABLE; 243*0c0fea5dSIngo Weinhold 244*0c0fea5dSIngo Weinhold if (eheader->e_phentsize < sizeof(struct Elf32_Phdr)) 245*0c0fea5dSIngo Weinhold return B_NOT_AN_EXECUTABLE; 246*0c0fea5dSIngo Weinhold 247*0c0fea5dSIngo Weinhold *_pheaderSize = eheader->e_phentsize * eheader->e_phnum; 248*0c0fea5dSIngo Weinhold *_sheaderSize = eheader->e_shentsize * eheader->e_shnum; 249*0c0fea5dSIngo Weinhold 250*0c0fea5dSIngo Weinhold return *_pheaderSize > 0 && *_sheaderSize > 0 ? B_OK : B_NOT_AN_EXECUTABLE; 251*0c0fea5dSIngo Weinhold } 252*0c0fea5dSIngo Weinhold 253*0c0fea5dSIngo Weinhold 254*0c0fea5dSIngo Weinhold static int32 255*0c0fea5dSIngo Weinhold count_regions(char const *buff, int phnum, int phentsize) 256*0c0fea5dSIngo Weinhold { 257*0c0fea5dSIngo Weinhold struct Elf32_Phdr *pheaders; 258*0c0fea5dSIngo Weinhold int32 count = 0; 259*0c0fea5dSIngo Weinhold int i; 260*0c0fea5dSIngo Weinhold 261*0c0fea5dSIngo Weinhold for (i = 0; i < phnum; i++) { 262*0c0fea5dSIngo Weinhold pheaders = (struct Elf32_Phdr *)(buff + i * phentsize); 263*0c0fea5dSIngo Weinhold 264*0c0fea5dSIngo Weinhold switch (pheaders->p_type) { 265*0c0fea5dSIngo Weinhold case PT_NULL: 266*0c0fea5dSIngo Weinhold /* NOP header */ 267*0c0fea5dSIngo Weinhold break; 268*0c0fea5dSIngo Weinhold case PT_LOAD: 269*0c0fea5dSIngo Weinhold count += 1; 270*0c0fea5dSIngo Weinhold if (pheaders->p_memsz != pheaders->p_filesz) { 271*0c0fea5dSIngo Weinhold addr_t A = TO_PAGE_SIZE(pheaders->p_vaddr + pheaders->p_memsz); 272*0c0fea5dSIngo Weinhold addr_t B = TO_PAGE_SIZE(pheaders->p_vaddr + pheaders->p_filesz); 273*0c0fea5dSIngo Weinhold 274*0c0fea5dSIngo Weinhold if (A != B) 275*0c0fea5dSIngo Weinhold count += 1; 276*0c0fea5dSIngo Weinhold } 277*0c0fea5dSIngo Weinhold break; 278*0c0fea5dSIngo Weinhold case PT_DYNAMIC: 279*0c0fea5dSIngo Weinhold /* will be handled at some other place */ 280*0c0fea5dSIngo Weinhold break; 281*0c0fea5dSIngo Weinhold case PT_INTERP: 282*0c0fea5dSIngo Weinhold /* should check here for appropiate interpreter */ 283*0c0fea5dSIngo Weinhold break; 284*0c0fea5dSIngo Weinhold case PT_NOTE: 285*0c0fea5dSIngo Weinhold /* unsupported */ 286*0c0fea5dSIngo Weinhold break; 287*0c0fea5dSIngo Weinhold case PT_SHLIB: 288*0c0fea5dSIngo Weinhold /* undefined semantics */ 289*0c0fea5dSIngo Weinhold break; 290*0c0fea5dSIngo Weinhold case PT_PHDR: 291*0c0fea5dSIngo Weinhold /* we don't use it */ 292*0c0fea5dSIngo Weinhold break; 293*0c0fea5dSIngo Weinhold default: 294*0c0fea5dSIngo Weinhold FATAL("unhandled pheader type 0x%lx\n", pheaders[i].p_type); 295*0c0fea5dSIngo Weinhold return B_BAD_DATA; 296*0c0fea5dSIngo Weinhold } 297*0c0fea5dSIngo Weinhold } 298*0c0fea5dSIngo Weinhold 299*0c0fea5dSIngo Weinhold return count; 300*0c0fea5dSIngo Weinhold } 301*0c0fea5dSIngo Weinhold 302*0c0fea5dSIngo Weinhold 303*0c0fea5dSIngo Weinhold /* 304*0c0fea5dSIngo Weinhold * create_image() & destroy_image() 305*0c0fea5dSIngo Weinhold * 306*0c0fea5dSIngo Weinhold * Create and destroy image_t structures. The destroyer makes sure that the 307*0c0fea5dSIngo Weinhold * memory buffers are full of garbage before freeing. 308*0c0fea5dSIngo Weinhold */ 309*0c0fea5dSIngo Weinhold 310*0c0fea5dSIngo Weinhold static image_t * 311*0c0fea5dSIngo Weinhold create_image(const char *name, const char *path, int num_regions) 312*0c0fea5dSIngo Weinhold { 313*0c0fea5dSIngo Weinhold size_t allocSize = sizeof(image_t) + (num_regions - 1) * sizeof(elf_region_t); 314*0c0fea5dSIngo Weinhold const char *lastSlash; 315*0c0fea5dSIngo Weinhold 316*0c0fea5dSIngo Weinhold image_t *image = (image_t*)malloc(allocSize); 317*0c0fea5dSIngo Weinhold if (image == NULL) { 318*0c0fea5dSIngo Weinhold FATAL("no memory for image %s\n", path); 319*0c0fea5dSIngo Weinhold return NULL; 320*0c0fea5dSIngo Weinhold } 321*0c0fea5dSIngo Weinhold 322*0c0fea5dSIngo Weinhold memset(image, 0, allocSize); 323*0c0fea5dSIngo Weinhold 324*0c0fea5dSIngo Weinhold strlcpy(image->path, path, sizeof(image->path)); 325*0c0fea5dSIngo Weinhold 326*0c0fea5dSIngo Weinhold // Make the last component of the supplied name the image name. 327*0c0fea5dSIngo Weinhold // If present, DT_SONAME will replace this name. 328*0c0fea5dSIngo Weinhold if ((lastSlash = strrchr(name, '/'))) 329*0c0fea5dSIngo Weinhold strlcpy(image->name, lastSlash + 1, sizeof(image->name)); 330*0c0fea5dSIngo Weinhold else 331*0c0fea5dSIngo Weinhold strlcpy(image->name, name, sizeof(image->name)); 332*0c0fea5dSIngo Weinhold 333*0c0fea5dSIngo Weinhold image->ref_count = 1; 334*0c0fea5dSIngo Weinhold image->num_regions = num_regions; 335*0c0fea5dSIngo Weinhold 336*0c0fea5dSIngo Weinhold return image; 337*0c0fea5dSIngo Weinhold } 338*0c0fea5dSIngo Weinhold 339*0c0fea5dSIngo Weinhold 340*0c0fea5dSIngo Weinhold static void 341*0c0fea5dSIngo Weinhold delete_image_struct(image_t *image) 342*0c0fea5dSIngo Weinhold { 343*0c0fea5dSIngo Weinhold #ifdef DEBUG 344*0c0fea5dSIngo Weinhold size_t size = sizeof(image_t) + (image->num_regions - 1) * sizeof(elf_region_t); 345*0c0fea5dSIngo Weinhold memset(image->needed, 0xa5, sizeof(image->needed[0]) * image->num_needed); 346*0c0fea5dSIngo Weinhold #endif 347*0c0fea5dSIngo Weinhold free(image->needed); 348*0c0fea5dSIngo Weinhold 349*0c0fea5dSIngo Weinhold #ifdef DEBUG 350*0c0fea5dSIngo Weinhold memset(image, 0xa5, size); 351*0c0fea5dSIngo Weinhold #endif 352*0c0fea5dSIngo Weinhold free(image); 353*0c0fea5dSIngo Weinhold } 354*0c0fea5dSIngo Weinhold 355*0c0fea5dSIngo Weinhold 356*0c0fea5dSIngo Weinhold static void 357*0c0fea5dSIngo Weinhold delete_image(image_t *image) 358*0c0fea5dSIngo Weinhold { 359*0c0fea5dSIngo Weinhold _kern_unregister_image(image->id); 360*0c0fea5dSIngo Weinhold // registered in load_container() 361*0c0fea5dSIngo Weinhold 362*0c0fea5dSIngo Weinhold delete_image_struct(image); 363*0c0fea5dSIngo Weinhold } 364*0c0fea5dSIngo Weinhold 365*0c0fea5dSIngo Weinhold 366*0c0fea5dSIngo Weinhold static status_t 367*0c0fea5dSIngo Weinhold parse_program_headers(image_t *image, char *buff, int phnum, int phentsize) 368*0c0fea5dSIngo Weinhold { 369*0c0fea5dSIngo Weinhold struct Elf32_Phdr *pheader; 370*0c0fea5dSIngo Weinhold int regcount; 371*0c0fea5dSIngo Weinhold int i; 372*0c0fea5dSIngo Weinhold 373*0c0fea5dSIngo Weinhold regcount = 0; 374*0c0fea5dSIngo Weinhold for (i = 0; i < phnum; i++) { 375*0c0fea5dSIngo Weinhold pheader = (struct Elf32_Phdr *)(buff + i * phentsize); 376*0c0fea5dSIngo Weinhold 377*0c0fea5dSIngo Weinhold switch (pheader->p_type) { 378*0c0fea5dSIngo Weinhold case PT_NULL: 379*0c0fea5dSIngo Weinhold /* NOP header */ 380*0c0fea5dSIngo Weinhold break; 381*0c0fea5dSIngo Weinhold case PT_LOAD: 382*0c0fea5dSIngo Weinhold if (pheader->p_memsz == pheader->p_filesz) { 383*0c0fea5dSIngo Weinhold /* 384*0c0fea5dSIngo Weinhold * everything in one area 385*0c0fea5dSIngo Weinhold */ 386*0c0fea5dSIngo Weinhold image->regions[regcount].start = pheader->p_vaddr; 387*0c0fea5dSIngo Weinhold image->regions[regcount].size = pheader->p_memsz; 388*0c0fea5dSIngo Weinhold image->regions[regcount].vmstart = PAGE_BASE(pheader->p_vaddr); 389*0c0fea5dSIngo Weinhold image->regions[regcount].vmsize = TO_PAGE_SIZE(pheader->p_memsz 390*0c0fea5dSIngo Weinhold + PAGE_OFFSET(pheader->p_vaddr)); 391*0c0fea5dSIngo Weinhold image->regions[regcount].fdstart = pheader->p_offset; 392*0c0fea5dSIngo Weinhold image->regions[regcount].fdsize = pheader->p_filesz; 393*0c0fea5dSIngo Weinhold image->regions[regcount].delta = 0; 394*0c0fea5dSIngo Weinhold image->regions[regcount].flags = 0; 395*0c0fea5dSIngo Weinhold if (pheader->p_flags & PF_WRITE) { 396*0c0fea5dSIngo Weinhold // this is a writable segment 397*0c0fea5dSIngo Weinhold image->regions[regcount].flags |= RFLAG_RW; 398*0c0fea5dSIngo Weinhold } 399*0c0fea5dSIngo Weinhold } else { 400*0c0fea5dSIngo Weinhold /* 401*0c0fea5dSIngo Weinhold * may require splitting 402*0c0fea5dSIngo Weinhold */ 403*0c0fea5dSIngo Weinhold addr_t A = TO_PAGE_SIZE(pheader->p_vaddr + pheader->p_memsz); 404*0c0fea5dSIngo Weinhold addr_t B = TO_PAGE_SIZE(pheader->p_vaddr + pheader->p_filesz); 405*0c0fea5dSIngo Weinhold 406*0c0fea5dSIngo Weinhold image->regions[regcount].start = pheader->p_vaddr; 407*0c0fea5dSIngo Weinhold image->regions[regcount].size = pheader->p_filesz; 408*0c0fea5dSIngo Weinhold image->regions[regcount].vmstart = PAGE_BASE(pheader->p_vaddr); 409*0c0fea5dSIngo Weinhold image->regions[regcount].vmsize = TO_PAGE_SIZE(pheader->p_filesz 410*0c0fea5dSIngo Weinhold + PAGE_OFFSET(pheader->p_vaddr)); 411*0c0fea5dSIngo Weinhold image->regions[regcount].fdstart = pheader->p_offset; 412*0c0fea5dSIngo Weinhold image->regions[regcount].fdsize = pheader->p_filesz; 413*0c0fea5dSIngo Weinhold image->regions[regcount].delta = 0; 414*0c0fea5dSIngo Weinhold image->regions[regcount].flags = 0; 415*0c0fea5dSIngo Weinhold if (pheader->p_flags & PF_WRITE) { 416*0c0fea5dSIngo Weinhold // this is a writable segment 417*0c0fea5dSIngo Weinhold image->regions[regcount].flags |= RFLAG_RW; 418*0c0fea5dSIngo Weinhold } 419*0c0fea5dSIngo Weinhold 420*0c0fea5dSIngo Weinhold if (A != B) { 421*0c0fea5dSIngo Weinhold /* 422*0c0fea5dSIngo Weinhold * yeah, it requires splitting 423*0c0fea5dSIngo Weinhold */ 424*0c0fea5dSIngo Weinhold regcount += 1; 425*0c0fea5dSIngo Weinhold image->regions[regcount].start = pheader->p_vaddr; 426*0c0fea5dSIngo Weinhold image->regions[regcount].size = pheader->p_memsz - pheader->p_filesz; 427*0c0fea5dSIngo Weinhold image->regions[regcount].vmstart = image->regions[regcount-1].vmstart + image->regions[regcount-1].vmsize; 428*0c0fea5dSIngo Weinhold image->regions[regcount].vmsize = TO_PAGE_SIZE(pheader->p_memsz + PAGE_OFFSET(pheader->p_vaddr)) 429*0c0fea5dSIngo Weinhold - image->regions[regcount-1].vmsize; 430*0c0fea5dSIngo Weinhold image->regions[regcount].fdstart = 0; 431*0c0fea5dSIngo Weinhold image->regions[regcount].fdsize = 0; 432*0c0fea5dSIngo Weinhold image->regions[regcount].delta = 0; 433*0c0fea5dSIngo Weinhold image->regions[regcount].flags = RFLAG_ANON; 434*0c0fea5dSIngo Weinhold if (pheader->p_flags & PF_WRITE) { 435*0c0fea5dSIngo Weinhold // this is a writable segment 436*0c0fea5dSIngo Weinhold image->regions[regcount].flags |= RFLAG_RW; 437*0c0fea5dSIngo Weinhold } 438*0c0fea5dSIngo Weinhold } 439*0c0fea5dSIngo Weinhold } 440*0c0fea5dSIngo Weinhold regcount += 1; 441*0c0fea5dSIngo Weinhold break; 442*0c0fea5dSIngo Weinhold case PT_DYNAMIC: 443*0c0fea5dSIngo Weinhold image->dynamic_ptr = pheader->p_vaddr; 444*0c0fea5dSIngo Weinhold break; 445*0c0fea5dSIngo Weinhold case PT_INTERP: 446*0c0fea5dSIngo Weinhold /* should check here for appropiate interpreter */ 447*0c0fea5dSIngo Weinhold break; 448*0c0fea5dSIngo Weinhold case PT_NOTE: 449*0c0fea5dSIngo Weinhold /* unsupported */ 450*0c0fea5dSIngo Weinhold break; 451*0c0fea5dSIngo Weinhold case PT_SHLIB: 452*0c0fea5dSIngo Weinhold /* undefined semantics */ 453*0c0fea5dSIngo Weinhold break; 454*0c0fea5dSIngo Weinhold case PT_PHDR: 455*0c0fea5dSIngo Weinhold /* we don't use it */ 456*0c0fea5dSIngo Weinhold break; 457*0c0fea5dSIngo Weinhold default: 458*0c0fea5dSIngo Weinhold FATAL("unhandled pheader type 0x%lx\n", pheader[i].p_type); 459*0c0fea5dSIngo Weinhold return B_BAD_DATA; 460*0c0fea5dSIngo Weinhold } 461*0c0fea5dSIngo Weinhold } 462*0c0fea5dSIngo Weinhold 463*0c0fea5dSIngo Weinhold return B_OK; 464*0c0fea5dSIngo Weinhold } 465*0c0fea5dSIngo Weinhold 466*0c0fea5dSIngo Weinhold 467*0c0fea5dSIngo Weinhold static bool 468*0c0fea5dSIngo Weinhold assert_dynamic_loadable(image_t *image) 469*0c0fea5dSIngo Weinhold { 470*0c0fea5dSIngo Weinhold uint32 i; 471*0c0fea5dSIngo Weinhold 472*0c0fea5dSIngo Weinhold if (!image->dynamic_ptr) 473*0c0fea5dSIngo Weinhold return true; 474*0c0fea5dSIngo Weinhold 475*0c0fea5dSIngo Weinhold for (i = 0; i < image->num_regions; i++) { 476*0c0fea5dSIngo Weinhold if (image->dynamic_ptr >= image->regions[i].start 477*0c0fea5dSIngo Weinhold && image->dynamic_ptr < image->regions[i].start + image->regions[i].size) 478*0c0fea5dSIngo Weinhold return true; 479*0c0fea5dSIngo Weinhold } 480*0c0fea5dSIngo Weinhold 481*0c0fea5dSIngo Weinhold return false; 482*0c0fea5dSIngo Weinhold } 483*0c0fea5dSIngo Weinhold 484*0c0fea5dSIngo Weinhold 485*0c0fea5dSIngo Weinhold /** This function will change the protection of all read-only segments 486*0c0fea5dSIngo Weinhold * to really be read-only. 487*0c0fea5dSIngo Weinhold * The areas have to be read/write first, so that they can be relocated. 488*0c0fea5dSIngo Weinhold */ 489*0c0fea5dSIngo Weinhold 490*0c0fea5dSIngo Weinhold static void 491*0c0fea5dSIngo Weinhold remap_images(void) 492*0c0fea5dSIngo Weinhold { 493*0c0fea5dSIngo Weinhold image_t *image; 494*0c0fea5dSIngo Weinhold uint32 i; 495*0c0fea5dSIngo Weinhold 496*0c0fea5dSIngo Weinhold for (image = sLoadedImages.head; image != NULL; image = image->next) { 497*0c0fea5dSIngo Weinhold for (i = 0; i < image->num_regions; i++) { 498*0c0fea5dSIngo Weinhold if ((image->regions[i].flags & RFLAG_RW) == 0 499*0c0fea5dSIngo Weinhold && (image->regions[i].flags & RFLAG_REMAPPED) == 0) { 500*0c0fea5dSIngo Weinhold // we only need to do this once, so we remember those we've already mapped 501*0c0fea5dSIngo Weinhold if (_kern_set_area_protection(image->regions[i].id, 502*0c0fea5dSIngo Weinhold B_READ_AREA | B_EXECUTE_AREA) == B_OK) 503*0c0fea5dSIngo Weinhold image->regions[i].flags |= RFLAG_REMAPPED; 504*0c0fea5dSIngo Weinhold } 505*0c0fea5dSIngo Weinhold } 506*0c0fea5dSIngo Weinhold } 507*0c0fea5dSIngo Weinhold } 508*0c0fea5dSIngo Weinhold 509*0c0fea5dSIngo Weinhold 510*0c0fea5dSIngo Weinhold static status_t 511*0c0fea5dSIngo Weinhold map_image(int fd, char const *path, image_t *image, bool fixed) 512*0c0fea5dSIngo Weinhold { 513*0c0fea5dSIngo Weinhold status_t status = B_OK; 514*0c0fea5dSIngo Weinhold const char *baseName; 515*0c0fea5dSIngo Weinhold uint32 i; 516*0c0fea5dSIngo Weinhold 517*0c0fea5dSIngo Weinhold (void)(fd); 518*0c0fea5dSIngo Weinhold 519*0c0fea5dSIngo Weinhold // cut the file name from the path as base name for the created areas 520*0c0fea5dSIngo Weinhold baseName = strrchr(path, '/'); 521*0c0fea5dSIngo Weinhold if (baseName != NULL) 522*0c0fea5dSIngo Weinhold baseName++; 523*0c0fea5dSIngo Weinhold else 524*0c0fea5dSIngo Weinhold baseName = path; 525*0c0fea5dSIngo Weinhold 526*0c0fea5dSIngo Weinhold for (i = 0; i < image->num_regions; i++) { 527*0c0fea5dSIngo Weinhold char regionName[B_OS_NAME_LENGTH]; 528*0c0fea5dSIngo Weinhold addr_t loadAddress; 529*0c0fea5dSIngo Weinhold uint32 addressSpecifier; 530*0c0fea5dSIngo Weinhold 531*0c0fea5dSIngo Weinhold // for BeOS compatibility: if we load an old BeOS executable, we 532*0c0fea5dSIngo Weinhold // have to relocate it, if possible - we recognize it because the 533*0c0fea5dSIngo Weinhold // vmstart is set to 0 (hopefully always) 534*0c0fea5dSIngo Weinhold if (fixed && image->regions[i].vmstart == 0) 535*0c0fea5dSIngo Weinhold fixed = false; 536*0c0fea5dSIngo Weinhold 537*0c0fea5dSIngo Weinhold snprintf(regionName, sizeof(regionName), "%s_seg%lu%s", 538*0c0fea5dSIngo Weinhold baseName, i, (image->regions[i].flags & RFLAG_RW) ? "rw" : "ro"); 539*0c0fea5dSIngo Weinhold 540*0c0fea5dSIngo Weinhold if (image->dynamic_ptr && !fixed) { 541*0c0fea5dSIngo Weinhold // relocatable image... we can afford to place wherever 542*0c0fea5dSIngo Weinhold if (i == 0) { 543*0c0fea5dSIngo Weinhold // but only the first segment gets a free ride 544*0c0fea5dSIngo Weinhold loadAddress = RLD_PROGRAM_BASE; 545*0c0fea5dSIngo Weinhold addressSpecifier = B_BASE_ADDRESS; 546*0c0fea5dSIngo Weinhold } else { 547*0c0fea5dSIngo Weinhold loadAddress = image->regions[i].vmstart + image->regions[i-1].delta; 548*0c0fea5dSIngo Weinhold addressSpecifier = B_EXACT_ADDRESS; 549*0c0fea5dSIngo Weinhold } 550*0c0fea5dSIngo Weinhold } else { 551*0c0fea5dSIngo Weinhold // not relocatable, put it where it asks or die trying 552*0c0fea5dSIngo Weinhold loadAddress = image->regions[i].vmstart; 553*0c0fea5dSIngo Weinhold addressSpecifier = B_EXACT_ADDRESS; 554*0c0fea5dSIngo Weinhold } 555*0c0fea5dSIngo Weinhold 556*0c0fea5dSIngo Weinhold if (image->regions[i].flags & RFLAG_ANON) { 557*0c0fea5dSIngo Weinhold image->regions[i].id = _kern_create_area(regionName, (void **)&loadAddress, 558*0c0fea5dSIngo Weinhold addressSpecifier, image->regions[i].vmsize, B_NO_LOCK, 559*0c0fea5dSIngo Weinhold B_READ_AREA | B_WRITE_AREA); 560*0c0fea5dSIngo Weinhold 561*0c0fea5dSIngo Weinhold if (image->regions[i].id < 0) { 562*0c0fea5dSIngo Weinhold status = image->regions[i].id; 563*0c0fea5dSIngo Weinhold goto error; 564*0c0fea5dSIngo Weinhold } 565*0c0fea5dSIngo Weinhold 566*0c0fea5dSIngo Weinhold image->regions[i].delta = loadAddress - image->regions[i].vmstart; 567*0c0fea5dSIngo Weinhold image->regions[i].vmstart = loadAddress; 568*0c0fea5dSIngo Weinhold } else { 569*0c0fea5dSIngo Weinhold image->regions[i].id = sys_vm_map_file(regionName, (void **)&loadAddress, 570*0c0fea5dSIngo Weinhold addressSpecifier, image->regions[i].vmsize, B_READ_AREA | B_WRITE_AREA, 571*0c0fea5dSIngo Weinhold REGION_PRIVATE_MAP, path, PAGE_BASE(image->regions[i].fdstart)); 572*0c0fea5dSIngo Weinhold 573*0c0fea5dSIngo Weinhold if (image->regions[i].id < 0) { 574*0c0fea5dSIngo Weinhold status = image->regions[i].id; 575*0c0fea5dSIngo Weinhold goto error; 576*0c0fea5dSIngo Weinhold } 577*0c0fea5dSIngo Weinhold 578*0c0fea5dSIngo Weinhold TRACE(("\"%s\" at %p, 0x%lx bytes (%s)\n", path, 579*0c0fea5dSIngo Weinhold (void *)loadAddress, image->regions[i].vmsize, 580*0c0fea5dSIngo Weinhold image->regions[i].flags & RFLAG_RW ? "rw" : "read-only")); 581*0c0fea5dSIngo Weinhold 582*0c0fea5dSIngo Weinhold image->regions[i].delta = loadAddress - image->regions[i].vmstart; 583*0c0fea5dSIngo Weinhold image->regions[i].vmstart = loadAddress; 584*0c0fea5dSIngo Weinhold 585*0c0fea5dSIngo Weinhold // handle trailer bits in data segment 586*0c0fea5dSIngo Weinhold if (image->regions[i].flags & RFLAG_RW) { 587*0c0fea5dSIngo Weinhold addr_t startClearing; 588*0c0fea5dSIngo Weinhold addr_t toClear; 589*0c0fea5dSIngo Weinhold 590*0c0fea5dSIngo Weinhold startClearing = image->regions[i].vmstart 591*0c0fea5dSIngo Weinhold + PAGE_OFFSET(image->regions[i].start) 592*0c0fea5dSIngo Weinhold + image->regions[i].size; 593*0c0fea5dSIngo Weinhold toClear = image->regions[i].vmsize 594*0c0fea5dSIngo Weinhold - PAGE_OFFSET(image->regions[i].start) 595*0c0fea5dSIngo Weinhold - image->regions[i].size; 596*0c0fea5dSIngo Weinhold 597*0c0fea5dSIngo Weinhold TRACE(("cleared 0x%lx and the following 0x%lx bytes\n", startClearing, toClear)); 598*0c0fea5dSIngo Weinhold memset((void *)startClearing, 0, toClear); 599*0c0fea5dSIngo Weinhold } 600*0c0fea5dSIngo Weinhold } 601*0c0fea5dSIngo Weinhold } 602*0c0fea5dSIngo Weinhold 603*0c0fea5dSIngo Weinhold if (image->dynamic_ptr) 604*0c0fea5dSIngo Weinhold image->dynamic_ptr += image->regions[0].delta; 605*0c0fea5dSIngo Weinhold 606*0c0fea5dSIngo Weinhold return B_OK; 607*0c0fea5dSIngo Weinhold 608*0c0fea5dSIngo Weinhold error: 609*0c0fea5dSIngo Weinhold return status; 610*0c0fea5dSIngo Weinhold } 611*0c0fea5dSIngo Weinhold 612*0c0fea5dSIngo Weinhold 613*0c0fea5dSIngo Weinhold static void 614*0c0fea5dSIngo Weinhold unmap_image(image_t *image) 615*0c0fea5dSIngo Weinhold { 616*0c0fea5dSIngo Weinhold uint32 i; 617*0c0fea5dSIngo Weinhold 618*0c0fea5dSIngo Weinhold for (i = 0; i < image->num_regions; i++) { 619*0c0fea5dSIngo Weinhold _kern_delete_area(image->regions[i].id); 620*0c0fea5dSIngo Weinhold 621*0c0fea5dSIngo Weinhold image->regions[i].id = -1; 622*0c0fea5dSIngo Weinhold } 623*0c0fea5dSIngo Weinhold } 624*0c0fea5dSIngo Weinhold 625*0c0fea5dSIngo Weinhold 626*0c0fea5dSIngo Weinhold static bool 627*0c0fea5dSIngo Weinhold parse_dynamic_segment(image_t *image) 628*0c0fea5dSIngo Weinhold { 629*0c0fea5dSIngo Weinhold struct Elf32_Dyn *d; 630*0c0fea5dSIngo Weinhold int i; 631*0c0fea5dSIngo Weinhold int sonameOffset = -1; 632*0c0fea5dSIngo Weinhold 633*0c0fea5dSIngo Weinhold image->symhash = 0; 634*0c0fea5dSIngo Weinhold image->syms = 0; 635*0c0fea5dSIngo Weinhold image->strtab = 0; 636*0c0fea5dSIngo Weinhold 637*0c0fea5dSIngo Weinhold d = (struct Elf32_Dyn *)image->dynamic_ptr; 638*0c0fea5dSIngo Weinhold if (!d) 639*0c0fea5dSIngo Weinhold return true; 640*0c0fea5dSIngo Weinhold 641*0c0fea5dSIngo Weinhold for (i = 0; d[i].d_tag != DT_NULL; i++) { 642*0c0fea5dSIngo Weinhold switch (d[i].d_tag) { 643*0c0fea5dSIngo Weinhold case DT_NEEDED: 644*0c0fea5dSIngo Weinhold image->num_needed += 1; 645*0c0fea5dSIngo Weinhold break; 646*0c0fea5dSIngo Weinhold case DT_HASH: 647*0c0fea5dSIngo Weinhold image->symhash = (uint32 *)(d[i].d_un.d_ptr + image->regions[0].delta); 648*0c0fea5dSIngo Weinhold break; 649*0c0fea5dSIngo Weinhold case DT_STRTAB: 650*0c0fea5dSIngo Weinhold image->strtab = (char *)(d[i].d_un.d_ptr + image->regions[0].delta); 651*0c0fea5dSIngo Weinhold break; 652*0c0fea5dSIngo Weinhold case DT_SYMTAB: 653*0c0fea5dSIngo Weinhold image->syms = (struct Elf32_Sym *)(d[i].d_un.d_ptr + image->regions[0].delta); 654*0c0fea5dSIngo Weinhold break; 655*0c0fea5dSIngo Weinhold case DT_REL: 656*0c0fea5dSIngo Weinhold image->rel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + image->regions[0].delta); 657*0c0fea5dSIngo Weinhold break; 658*0c0fea5dSIngo Weinhold case DT_RELSZ: 659*0c0fea5dSIngo Weinhold image->rel_len = d[i].d_un.d_val; 660*0c0fea5dSIngo Weinhold break; 661*0c0fea5dSIngo Weinhold case DT_RELA: 662*0c0fea5dSIngo Weinhold image->rela = (struct Elf32_Rela *)(d[i].d_un.d_ptr + image->regions[0].delta); 663*0c0fea5dSIngo Weinhold break; 664*0c0fea5dSIngo Weinhold case DT_RELASZ: 665*0c0fea5dSIngo Weinhold image->rela_len = d[i].d_un.d_val; 666*0c0fea5dSIngo Weinhold break; 667*0c0fea5dSIngo Weinhold // TK: procedure linkage table 668*0c0fea5dSIngo Weinhold case DT_JMPREL: 669*0c0fea5dSIngo Weinhold image->pltrel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + image->regions[0].delta); 670*0c0fea5dSIngo Weinhold break; 671*0c0fea5dSIngo Weinhold case DT_PLTRELSZ: 672*0c0fea5dSIngo Weinhold image->pltrel_len = d[i].d_un.d_val; 673*0c0fea5dSIngo Weinhold break; 674*0c0fea5dSIngo Weinhold case DT_INIT: 675*0c0fea5dSIngo Weinhold image->init_routine = (d[i].d_un.d_ptr + image->regions[0].delta); 676*0c0fea5dSIngo Weinhold break; 677*0c0fea5dSIngo Weinhold case DT_FINI: 678*0c0fea5dSIngo Weinhold image->term_routine = (d[i].d_un.d_ptr + image->regions[0].delta); 679*0c0fea5dSIngo Weinhold break; 680*0c0fea5dSIngo Weinhold case DT_SONAME: 681*0c0fea5dSIngo Weinhold sonameOffset = d[i].d_un.d_val; 682*0c0fea5dSIngo Weinhold break; 683*0c0fea5dSIngo Weinhold default: 684*0c0fea5dSIngo Weinhold continue; 685*0c0fea5dSIngo Weinhold } 686*0c0fea5dSIngo Weinhold } 687*0c0fea5dSIngo Weinhold 688*0c0fea5dSIngo Weinhold // lets make sure we found all the required sections 689*0c0fea5dSIngo Weinhold if (!image->symhash || !image->syms || !image->strtab) 690*0c0fea5dSIngo Weinhold return false; 691*0c0fea5dSIngo Weinhold 692*0c0fea5dSIngo Weinhold if (sonameOffset >= 0) 693*0c0fea5dSIngo Weinhold strlcpy(image->name, STRING(image, sonameOffset), sizeof(image->name)); 694*0c0fea5dSIngo Weinhold 695*0c0fea5dSIngo Weinhold return true; 696*0c0fea5dSIngo Weinhold } 697*0c0fea5dSIngo Weinhold 698*0c0fea5dSIngo Weinhold 699*0c0fea5dSIngo Weinhold static struct Elf32_Sym * 700*0c0fea5dSIngo Weinhold find_symbol(image_t *image, const char *name, int32 type) 701*0c0fea5dSIngo Weinhold { 702*0c0fea5dSIngo Weinhold uint32 hash, i; 703*0c0fea5dSIngo Weinhold 704*0c0fea5dSIngo Weinhold // ToDo: "type" is currently ignored! 705*0c0fea5dSIngo Weinhold (void)type; 706*0c0fea5dSIngo Weinhold 707*0c0fea5dSIngo Weinhold if (image->dynamic_ptr == NULL) 708*0c0fea5dSIngo Weinhold return NULL; 709*0c0fea5dSIngo Weinhold 710*0c0fea5dSIngo Weinhold hash = elf_hash((uint8 *)name) % HASHTABSIZE(image); 711*0c0fea5dSIngo Weinhold 712*0c0fea5dSIngo Weinhold for (i = HASHBUCKETS(image)[hash]; i != STN_UNDEF; i = HASHCHAINS(image)[i]) { 713*0c0fea5dSIngo Weinhold struct Elf32_Sym *symbol = &image->syms[i]; 714*0c0fea5dSIngo Weinhold 715*0c0fea5dSIngo Weinhold if (symbol->st_shndx != SHN_UNDEF 716*0c0fea5dSIngo Weinhold && ((ELF32_ST_BIND(symbol->st_info)== STB_GLOBAL) 717*0c0fea5dSIngo Weinhold || (ELF32_ST_BIND(symbol->st_info) == STB_WEAK)) 718*0c0fea5dSIngo Weinhold && !strcmp(SYMNAME(image, symbol), name)) { 719*0c0fea5dSIngo Weinhold // check if the type matches 720*0c0fea5dSIngo Weinhold if ((type == B_SYMBOL_TYPE_TEXT && ELF32_ST_TYPE(symbol->st_info) != STT_FUNC) 721*0c0fea5dSIngo Weinhold || (type == B_SYMBOL_TYPE_DATA && ELF32_ST_TYPE(symbol->st_info) != STT_OBJECT)) 722*0c0fea5dSIngo Weinhold continue; 723*0c0fea5dSIngo Weinhold 724*0c0fea5dSIngo Weinhold return symbol; 725*0c0fea5dSIngo Weinhold } 726*0c0fea5dSIngo Weinhold } 727*0c0fea5dSIngo Weinhold 728*0c0fea5dSIngo Weinhold return NULL; 729*0c0fea5dSIngo Weinhold } 730*0c0fea5dSIngo Weinhold 731*0c0fea5dSIngo Weinhold 732*0c0fea5dSIngo Weinhold static struct Elf32_Sym * 733*0c0fea5dSIngo Weinhold find_symbol_in_loaded_images(image_t **_image, const char *name) 734*0c0fea5dSIngo Weinhold { 735*0c0fea5dSIngo Weinhold image_t *image; 736*0c0fea5dSIngo Weinhold 737*0c0fea5dSIngo Weinhold for (image = sLoadedImages.head; image; image = image->next) { 738*0c0fea5dSIngo Weinhold struct Elf32_Sym *symbol; 739*0c0fea5dSIngo Weinhold 740*0c0fea5dSIngo Weinhold if (image->dynamic_ptr == NULL) 741*0c0fea5dSIngo Weinhold continue; 742*0c0fea5dSIngo Weinhold 743*0c0fea5dSIngo Weinhold symbol = find_symbol(image, name, B_SYMBOL_TYPE_ANY); 744*0c0fea5dSIngo Weinhold if (symbol) { 745*0c0fea5dSIngo Weinhold *_image = image; 746*0c0fea5dSIngo Weinhold return symbol; 747*0c0fea5dSIngo Weinhold } 748*0c0fea5dSIngo Weinhold } 749*0c0fea5dSIngo Weinhold 750*0c0fea5dSIngo Weinhold return NULL; 751*0c0fea5dSIngo Weinhold } 752*0c0fea5dSIngo Weinhold 753*0c0fea5dSIngo Weinhold 754*0c0fea5dSIngo Weinhold int 755*0c0fea5dSIngo Weinhold resolve_symbol(image_t *image, struct Elf32_Sym *sym, addr_t *sym_addr) 756*0c0fea5dSIngo Weinhold { 757*0c0fea5dSIngo Weinhold struct Elf32_Sym *sym2; 758*0c0fea5dSIngo Weinhold char *symname; 759*0c0fea5dSIngo Weinhold image_t *shimg; 760*0c0fea5dSIngo Weinhold 761*0c0fea5dSIngo Weinhold switch (sym->st_shndx) { 762*0c0fea5dSIngo Weinhold case SHN_UNDEF: 763*0c0fea5dSIngo Weinhold // patch the symbol name 764*0c0fea5dSIngo Weinhold symname = SYMNAME(image, sym); 765*0c0fea5dSIngo Weinhold 766*0c0fea5dSIngo Weinhold // it's undefined, must be outside this image, try the other image 767*0c0fea5dSIngo Weinhold sym2 = find_symbol_in_loaded_images(&shimg, symname); 768*0c0fea5dSIngo Weinhold if (!sym2) { 769*0c0fea5dSIngo Weinhold printf("elf_resolve_symbol: could not resolve symbol '%s'\n", symname); 770*0c0fea5dSIngo Weinhold return B_MISSING_SYMBOL; 771*0c0fea5dSIngo Weinhold } 772*0c0fea5dSIngo Weinhold 773*0c0fea5dSIngo Weinhold // make sure they're the same type 774*0c0fea5dSIngo Weinhold if (ELF32_ST_TYPE(sym->st_info) != STT_NOTYPE 775*0c0fea5dSIngo Weinhold && ELF32_ST_TYPE(sym->st_info) != ELF32_ST_TYPE(sym2->st_info)) { 776*0c0fea5dSIngo Weinhold printf("elf_resolve_symbol: found symbol '%s' in shared image but wrong type\n", symname); 777*0c0fea5dSIngo Weinhold return B_MISSING_SYMBOL; 778*0c0fea5dSIngo Weinhold } 779*0c0fea5dSIngo Weinhold 780*0c0fea5dSIngo Weinhold if (ELF32_ST_BIND(sym2->st_info) != STB_GLOBAL 781*0c0fea5dSIngo Weinhold && ELF32_ST_BIND(sym2->st_info) != STB_WEAK) { 782*0c0fea5dSIngo Weinhold printf("elf_resolve_symbol: found symbol '%s' but not exported\n", symname); 783*0c0fea5dSIngo Weinhold return B_MISSING_SYMBOL; 784*0c0fea5dSIngo Weinhold } 785*0c0fea5dSIngo Weinhold 786*0c0fea5dSIngo Weinhold *sym_addr = sym2->st_value + shimg->regions[0].delta; 787*0c0fea5dSIngo Weinhold return B_NO_ERROR; 788*0c0fea5dSIngo Weinhold 789*0c0fea5dSIngo Weinhold case SHN_ABS: 790*0c0fea5dSIngo Weinhold *sym_addr = sym->st_value + image->regions[0].delta; 791*0c0fea5dSIngo Weinhold return B_NO_ERROR; 792*0c0fea5dSIngo Weinhold 793*0c0fea5dSIngo Weinhold case SHN_COMMON: 794*0c0fea5dSIngo Weinhold // ToDo: finish this 795*0c0fea5dSIngo Weinhold printf("elf_resolve_symbol: COMMON symbol, finish me!\n"); 796*0c0fea5dSIngo Weinhold return B_ERROR; //ERR_NOT_IMPLEMENTED_YET; 797*0c0fea5dSIngo Weinhold 798*0c0fea5dSIngo Weinhold default: 799*0c0fea5dSIngo Weinhold // standard symbol 800*0c0fea5dSIngo Weinhold *sym_addr = sym->st_value + image->regions[0].delta; 801*0c0fea5dSIngo Weinhold return B_NO_ERROR; 802*0c0fea5dSIngo Weinhold } 803*0c0fea5dSIngo Weinhold } 804*0c0fea5dSIngo Weinhold 805*0c0fea5dSIngo Weinhold 806*0c0fea5dSIngo Weinhold static void 807*0c0fea5dSIngo Weinhold register_image(image_t *image, int fd, const char *path) 808*0c0fea5dSIngo Weinhold { 809*0c0fea5dSIngo Weinhold struct stat stat; 810*0c0fea5dSIngo Weinhold image_info info; 811*0c0fea5dSIngo Weinhold 812*0c0fea5dSIngo Weinhold // ToDo: set these correctly 813*0c0fea5dSIngo Weinhold info.id = 0; 814*0c0fea5dSIngo Weinhold info.type = image->type; 815*0c0fea5dSIngo Weinhold info.sequence = 0; 816*0c0fea5dSIngo Weinhold info.init_order = 0; 817*0c0fea5dSIngo Weinhold info.init_routine = (void (*)())image->init_routine; 818*0c0fea5dSIngo Weinhold info.term_routine = (void (*)())image->term_routine; 819*0c0fea5dSIngo Weinhold 820*0c0fea5dSIngo Weinhold if (_kern_read_stat(fd, NULL, false, &stat, sizeof(struct stat)) == B_OK) { 821*0c0fea5dSIngo Weinhold info.device = stat.st_dev; 822*0c0fea5dSIngo Weinhold info.node = stat.st_ino; 823*0c0fea5dSIngo Weinhold } else { 824*0c0fea5dSIngo Weinhold info.device = -1; 825*0c0fea5dSIngo Weinhold info.node = -1; 826*0c0fea5dSIngo Weinhold } 827*0c0fea5dSIngo Weinhold 828*0c0fea5dSIngo Weinhold strlcpy(info.name, path, sizeof(info.name)); 829*0c0fea5dSIngo Weinhold info.text = (void *)image->regions[0].vmstart; 830*0c0fea5dSIngo Weinhold info.text_size = image->regions[0].vmsize; 831*0c0fea5dSIngo Weinhold info.data = (void *)image->regions[1].vmstart; 832*0c0fea5dSIngo Weinhold info.data_size = image->regions[1].vmsize; 833*0c0fea5dSIngo Weinhold image->id = _kern_register_image(&info, sizeof(image_info)); 834*0c0fea5dSIngo Weinhold } 835*0c0fea5dSIngo Weinhold 836*0c0fea5dSIngo Weinhold 837*0c0fea5dSIngo Weinhold static status_t 838*0c0fea5dSIngo Weinhold relocate_image(image_t *image) 839*0c0fea5dSIngo Weinhold { 840*0c0fea5dSIngo Weinhold status_t status = arch_relocate_image(image); 841*0c0fea5dSIngo Weinhold if (status < B_OK) { 842*0c0fea5dSIngo Weinhold FATAL("troubles relocating: 0x%lx\n", status); 843*0c0fea5dSIngo Weinhold return status; 844*0c0fea5dSIngo Weinhold } 845*0c0fea5dSIngo Weinhold 846*0c0fea5dSIngo Weinhold _kern_image_relocated(image->id); 847*0c0fea5dSIngo Weinhold return B_OK; 848*0c0fea5dSIngo Weinhold } 849*0c0fea5dSIngo Weinhold 850*0c0fea5dSIngo Weinhold 851*0c0fea5dSIngo Weinhold static status_t 852*0c0fea5dSIngo Weinhold load_container(char const *name, image_type type, const char *rpath, image_t **_image) 853*0c0fea5dSIngo Weinhold { 854*0c0fea5dSIngo Weinhold int32 pheaderSize, sheaderSize; 855*0c0fea5dSIngo Weinhold char path[PATH_MAX]; 856*0c0fea5dSIngo Weinhold ssize_t length; 857*0c0fea5dSIngo Weinhold char ph_buff[4096]; 858*0c0fea5dSIngo Weinhold int32 numRegions; 859*0c0fea5dSIngo Weinhold image_t *found; 860*0c0fea5dSIngo Weinhold image_t *image; 861*0c0fea5dSIngo Weinhold status_t status; 862*0c0fea5dSIngo Weinhold int fd; 863*0c0fea5dSIngo Weinhold 864*0c0fea5dSIngo Weinhold struct Elf32_Ehdr eheader; 865*0c0fea5dSIngo Weinhold 866*0c0fea5dSIngo Weinhold // Have we already loaded that image? Don't check for add-ons -- we always 867*0c0fea5dSIngo Weinhold // reload them. 868*0c0fea5dSIngo Weinhold if (type != B_ADD_ON_IMAGE) { 869*0c0fea5dSIngo Weinhold found = find_image(name, APP_OR_LIBRARY_TYPE); 870*0c0fea5dSIngo Weinhold if (found) { 871*0c0fea5dSIngo Weinhold atomic_add(&found->ref_count, 1); 872*0c0fea5dSIngo Weinhold *_image = found; 873*0c0fea5dSIngo Weinhold return B_OK; 874*0c0fea5dSIngo Weinhold } 875*0c0fea5dSIngo Weinhold } 876*0c0fea5dSIngo Weinhold 877*0c0fea5dSIngo Weinhold strlcpy(path, name, sizeof(path)); 878*0c0fea5dSIngo Weinhold 879*0c0fea5dSIngo Weinhold // Try to load explicit image path first 880*0c0fea5dSIngo Weinhold fd = open_executable(path, type, rpath); 881*0c0fea5dSIngo Weinhold if (fd < 0) { 882*0c0fea5dSIngo Weinhold FATAL("cannot open file %s\n", path); 883*0c0fea5dSIngo Weinhold return fd; 884*0c0fea5dSIngo Weinhold } 885*0c0fea5dSIngo Weinhold 886*0c0fea5dSIngo Weinhold // If the path is not absolute, we prepend the CWD to make it one. 887*0c0fea5dSIngo Weinhold if (path[0] != '/') { 888*0c0fea5dSIngo Weinhold char relativePath[PATH_MAX]; 889*0c0fea5dSIngo Weinhold if (!strncmp(path, "./", 2)) 890*0c0fea5dSIngo Weinhold strcpy(relativePath, path + 2); 891*0c0fea5dSIngo Weinhold else 892*0c0fea5dSIngo Weinhold strcpy(relativePath, path); 893*0c0fea5dSIngo Weinhold 894*0c0fea5dSIngo Weinhold // get the CWD 895*0c0fea5dSIngo Weinhold status = _kern_getcwd(path, sizeof(path)); 896*0c0fea5dSIngo Weinhold if (status < B_OK) { 897*0c0fea5dSIngo Weinhold FATAL("_kern_getcwd() failed\n"); 898*0c0fea5dSIngo Weinhold goto err1; 899*0c0fea5dSIngo Weinhold } 900*0c0fea5dSIngo Weinhold 901*0c0fea5dSIngo Weinhold if (strlcat(path, "/", sizeof(path)) >= sizeof(path) 902*0c0fea5dSIngo Weinhold || strlcat(path, relativePath, sizeof(path)) >= sizeof(path)) { 903*0c0fea5dSIngo Weinhold status = B_NAME_TOO_LONG; 904*0c0fea5dSIngo Weinhold FATAL("Absolute path of image %s is too " 905*0c0fea5dSIngo Weinhold "long!\n", relativePath); 906*0c0fea5dSIngo Weinhold goto err1; 907*0c0fea5dSIngo Weinhold } 908*0c0fea5dSIngo Weinhold } 909*0c0fea5dSIngo Weinhold 910*0c0fea5dSIngo Weinhold // Test again if this image has been registered already - this time, 911*0c0fea5dSIngo Weinhold // we can check the full path, not just its name as noted. 912*0c0fea5dSIngo Weinhold // You could end up loading an image twice with symbolic links, else. 913*0c0fea5dSIngo Weinhold if (type != B_ADD_ON_IMAGE) { 914*0c0fea5dSIngo Weinhold found = find_image(path, APP_OR_LIBRARY_TYPE); 915*0c0fea5dSIngo Weinhold if (found) { 916*0c0fea5dSIngo Weinhold atomic_add(&found->ref_count, 1); 917*0c0fea5dSIngo Weinhold *_image = found; 918*0c0fea5dSIngo Weinhold return B_OK; 919*0c0fea5dSIngo Weinhold } 920*0c0fea5dSIngo Weinhold } 921*0c0fea5dSIngo Weinhold 922*0c0fea5dSIngo Weinhold length = _kern_read(fd, 0, &eheader, sizeof(eheader)); 923*0c0fea5dSIngo Weinhold if (length != sizeof(eheader)) { 924*0c0fea5dSIngo Weinhold status = B_NOT_AN_EXECUTABLE; 925*0c0fea5dSIngo Weinhold FATAL("troubles reading ELF header\n"); 926*0c0fea5dSIngo Weinhold goto err1; 927*0c0fea5dSIngo Weinhold } 928*0c0fea5dSIngo Weinhold 929*0c0fea5dSIngo Weinhold status = parse_elf_header(&eheader, &pheaderSize, &sheaderSize); 930*0c0fea5dSIngo Weinhold if (status < B_OK) { 931*0c0fea5dSIngo Weinhold FATAL("incorrect ELF header\n"); 932*0c0fea5dSIngo Weinhold goto err1; 933*0c0fea5dSIngo Weinhold } 934*0c0fea5dSIngo Weinhold 935*0c0fea5dSIngo Weinhold // ToDo: what to do about this restriction?? 936*0c0fea5dSIngo Weinhold if (pheaderSize > (int)sizeof(ph_buff)) { 937*0c0fea5dSIngo Weinhold FATAL("Cannot handle program headers bigger than %lu\n", sizeof(ph_buff)); 938*0c0fea5dSIngo Weinhold status = B_UNSUPPORTED; 939*0c0fea5dSIngo Weinhold goto err1; 940*0c0fea5dSIngo Weinhold } 941*0c0fea5dSIngo Weinhold 942*0c0fea5dSIngo Weinhold length = _kern_read(fd, eheader.e_phoff, ph_buff, pheaderSize); 943*0c0fea5dSIngo Weinhold if (length != pheaderSize) { 944*0c0fea5dSIngo Weinhold FATAL("Could not read program headers: %s\n", strerror(length)); 945*0c0fea5dSIngo Weinhold status = B_BAD_DATA; 946*0c0fea5dSIngo Weinhold goto err1; 947*0c0fea5dSIngo Weinhold } 948*0c0fea5dSIngo Weinhold 949*0c0fea5dSIngo Weinhold numRegions = count_regions(ph_buff, eheader.e_phnum, eheader.e_phentsize); 950*0c0fea5dSIngo Weinhold if (numRegions <= 0) { 951*0c0fea5dSIngo Weinhold FATAL("Troubles parsing Program headers, numRegions = %ld\n", numRegions); 952*0c0fea5dSIngo Weinhold status = B_BAD_DATA; 953*0c0fea5dSIngo Weinhold goto err1; 954*0c0fea5dSIngo Weinhold } 955*0c0fea5dSIngo Weinhold 956*0c0fea5dSIngo Weinhold image = create_image(name, path, numRegions); 957*0c0fea5dSIngo Weinhold if (image == NULL) { 958*0c0fea5dSIngo Weinhold FATAL("Failed to allocate image_t object\n"); 959*0c0fea5dSIngo Weinhold status = B_NO_MEMORY; 960*0c0fea5dSIngo Weinhold goto err1; 961*0c0fea5dSIngo Weinhold } 962*0c0fea5dSIngo Weinhold 963*0c0fea5dSIngo Weinhold status = parse_program_headers(image, ph_buff, eheader.e_phnum, eheader.e_phentsize); 964*0c0fea5dSIngo Weinhold if (status < B_OK) 965*0c0fea5dSIngo Weinhold goto err2; 966*0c0fea5dSIngo Weinhold 967*0c0fea5dSIngo Weinhold if (!assert_dynamic_loadable(image)) { 968*0c0fea5dSIngo Weinhold FATAL("Dynamic segment must be loadable (implementation restriction)\n"); 969*0c0fea5dSIngo Weinhold status = B_UNSUPPORTED; 970*0c0fea5dSIngo Weinhold goto err2; 971*0c0fea5dSIngo Weinhold } 972*0c0fea5dSIngo Weinhold 973*0c0fea5dSIngo Weinhold status = map_image(fd, path, image, type == B_APP_IMAGE); 974*0c0fea5dSIngo Weinhold if (status < B_OK) { 975*0c0fea5dSIngo Weinhold FATAL("Could not map image: %s\n", strerror(status)); 976*0c0fea5dSIngo Weinhold status = B_ERROR; 977*0c0fea5dSIngo Weinhold goto err2; 978*0c0fea5dSIngo Weinhold } 979*0c0fea5dSIngo Weinhold 980*0c0fea5dSIngo Weinhold if (!parse_dynamic_segment(image)) { 981*0c0fea5dSIngo Weinhold FATAL("Troubles handling dynamic section\n"); 982*0c0fea5dSIngo Weinhold status = B_BAD_DATA; 983*0c0fea5dSIngo Weinhold goto err3; 984*0c0fea5dSIngo Weinhold } 985*0c0fea5dSIngo Weinhold 986*0c0fea5dSIngo Weinhold if (eheader.e_entry != NULL) 987*0c0fea5dSIngo Weinhold image->entry_point = eheader.e_entry + image->regions[0].delta; 988*0c0fea5dSIngo Weinhold 989*0c0fea5dSIngo Weinhold image->type = type; 990*0c0fea5dSIngo Weinhold register_image(image, fd, path); 991*0c0fea5dSIngo Weinhold 992*0c0fea5dSIngo Weinhold _kern_close(fd); 993*0c0fea5dSIngo Weinhold 994*0c0fea5dSIngo Weinhold enqueue_image(&sLoadedImages, image); 995*0c0fea5dSIngo Weinhold sLoadedImageCount++; 996*0c0fea5dSIngo Weinhold 997*0c0fea5dSIngo Weinhold *_image = image; 998*0c0fea5dSIngo Weinhold return B_OK; 999*0c0fea5dSIngo Weinhold 1000*0c0fea5dSIngo Weinhold err3: 1001*0c0fea5dSIngo Weinhold unmap_image(image); 1002*0c0fea5dSIngo Weinhold err2: 1003*0c0fea5dSIngo Weinhold delete_image_struct(image); 1004*0c0fea5dSIngo Weinhold err1: 1005*0c0fea5dSIngo Weinhold _kern_close(fd); 1006*0c0fea5dSIngo Weinhold return status; 1007*0c0fea5dSIngo Weinhold } 1008*0c0fea5dSIngo Weinhold 1009*0c0fea5dSIngo Weinhold 1010*0c0fea5dSIngo Weinhold static const char * 1011*0c0fea5dSIngo Weinhold find_dt_rpath(image_t *image) 1012*0c0fea5dSIngo Weinhold { 1013*0c0fea5dSIngo Weinhold int i; 1014*0c0fea5dSIngo Weinhold struct Elf32_Dyn *d = (struct Elf32_Dyn *)image->dynamic_ptr; 1015*0c0fea5dSIngo Weinhold 1016*0c0fea5dSIngo Weinhold for (i = 0; d[i].d_tag != DT_NULL; i++) { 1017*0c0fea5dSIngo Weinhold if (d[i].d_tag == DT_RPATH) 1018*0c0fea5dSIngo Weinhold return STRING(image, d[i].d_un.d_val); 1019*0c0fea5dSIngo Weinhold } 1020*0c0fea5dSIngo Weinhold 1021*0c0fea5dSIngo Weinhold return NULL; 1022*0c0fea5dSIngo Weinhold } 1023*0c0fea5dSIngo Weinhold 1024*0c0fea5dSIngo Weinhold 1025*0c0fea5dSIngo Weinhold static status_t 1026*0c0fea5dSIngo Weinhold load_dependencies(image_t *image) 1027*0c0fea5dSIngo Weinhold { 1028*0c0fea5dSIngo Weinhold struct Elf32_Dyn *d = (struct Elf32_Dyn *)image->dynamic_ptr; 1029*0c0fea5dSIngo Weinhold int neededOffset; 1030*0c0fea5dSIngo Weinhold status_t status; 1031*0c0fea5dSIngo Weinhold uint32 i, j; 1032*0c0fea5dSIngo Weinhold const char *rpath; 1033*0c0fea5dSIngo Weinhold 1034*0c0fea5dSIngo Weinhold if (!d || (image->flags & RFLAG_DEPENDENCIES_LOADED)) 1035*0c0fea5dSIngo Weinhold return B_OK; 1036*0c0fea5dSIngo Weinhold 1037*0c0fea5dSIngo Weinhold image->flags |= RFLAG_DEPENDENCIES_LOADED; 1038*0c0fea5dSIngo Weinhold 1039*0c0fea5dSIngo Weinhold if (image->num_needed == 0) 1040*0c0fea5dSIngo Weinhold return B_OK; 1041*0c0fea5dSIngo Weinhold 1042*0c0fea5dSIngo Weinhold image->needed = (image_t**)malloc(image->num_needed * sizeof(image_t *)); 1043*0c0fea5dSIngo Weinhold if (image->needed == NULL) { 1044*0c0fea5dSIngo Weinhold FATAL("failed to allocate needed struct\n"); 1045*0c0fea5dSIngo Weinhold return B_NO_MEMORY; 1046*0c0fea5dSIngo Weinhold } 1047*0c0fea5dSIngo Weinhold 1048*0c0fea5dSIngo Weinhold memset(image->needed, 0, image->num_needed * sizeof(image_t *)); 1049*0c0fea5dSIngo Weinhold rpath = find_dt_rpath(image); 1050*0c0fea5dSIngo Weinhold 1051*0c0fea5dSIngo Weinhold for (i = 0, j = 0; d[i].d_tag != DT_NULL; i++) { 1052*0c0fea5dSIngo Weinhold switch (d[i].d_tag) { 1053*0c0fea5dSIngo Weinhold case DT_NEEDED: 1054*0c0fea5dSIngo Weinhold neededOffset = d[i].d_un.d_val; 1055*0c0fea5dSIngo Weinhold 1056*0c0fea5dSIngo Weinhold status = load_container(STRING(image, neededOffset), 1057*0c0fea5dSIngo Weinhold B_LIBRARY_IMAGE, rpath, &image->needed[j]); 1058*0c0fea5dSIngo Weinhold if (status < B_OK) 1059*0c0fea5dSIngo Weinhold return status; 1060*0c0fea5dSIngo Weinhold 1061*0c0fea5dSIngo Weinhold j += 1; 1062*0c0fea5dSIngo Weinhold break; 1063*0c0fea5dSIngo Weinhold 1064*0c0fea5dSIngo Weinhold default: 1065*0c0fea5dSIngo Weinhold // ignore any other tag 1066*0c0fea5dSIngo Weinhold continue; 1067*0c0fea5dSIngo Weinhold } 1068*0c0fea5dSIngo Weinhold } 1069*0c0fea5dSIngo Weinhold 1070*0c0fea5dSIngo Weinhold if (j != image->num_needed) { 1071*0c0fea5dSIngo Weinhold FATAL("Internal error at load_dependencies()"); 1072*0c0fea5dSIngo Weinhold return B_ERROR; 1073*0c0fea5dSIngo Weinhold } 1074*0c0fea5dSIngo Weinhold 1075*0c0fea5dSIngo Weinhold return B_OK; 1076*0c0fea5dSIngo Weinhold } 1077*0c0fea5dSIngo Weinhold 1078*0c0fea5dSIngo Weinhold 1079*0c0fea5dSIngo Weinhold static uint32 1080*0c0fea5dSIngo Weinhold topological_sort(image_t *image, uint32 slot, image_t **initList, 1081*0c0fea5dSIngo Weinhold uint32 sortFlag) 1082*0c0fea5dSIngo Weinhold { 1083*0c0fea5dSIngo Weinhold uint32 i; 1084*0c0fea5dSIngo Weinhold 1085*0c0fea5dSIngo Weinhold if (image->flags & sortFlag) 1086*0c0fea5dSIngo Weinhold return slot; 1087*0c0fea5dSIngo Weinhold 1088*0c0fea5dSIngo Weinhold image->flags |= sortFlag; /* make sure we don't visit this one */ 1089*0c0fea5dSIngo Weinhold for (i = 0; i < image->num_needed; i++) 1090*0c0fea5dSIngo Weinhold slot = topological_sort(image->needed[i], slot, initList, sortFlag); 1091*0c0fea5dSIngo Weinhold 1092*0c0fea5dSIngo Weinhold initList[slot] = image; 1093*0c0fea5dSIngo Weinhold return slot + 1; 1094*0c0fea5dSIngo Weinhold } 1095*0c0fea5dSIngo Weinhold 1096*0c0fea5dSIngo Weinhold 1097*0c0fea5dSIngo Weinhold static ssize_t 1098*0c0fea5dSIngo Weinhold get_sorted_image_list(image_t *image, image_t ***_list, uint32 sortFlag) 1099*0c0fea5dSIngo Weinhold { 1100*0c0fea5dSIngo Weinhold image_t **list; 1101*0c0fea5dSIngo Weinhold 1102*0c0fea5dSIngo Weinhold list = (image_t**)malloc(sLoadedImageCount * sizeof(image_t *)); 1103*0c0fea5dSIngo Weinhold if (list == NULL) { 1104*0c0fea5dSIngo Weinhold FATAL("memory shortage in get_sorted_image_list()"); 1105*0c0fea5dSIngo Weinhold *_list = NULL; 1106*0c0fea5dSIngo Weinhold return B_NO_MEMORY; 1107*0c0fea5dSIngo Weinhold } 1108*0c0fea5dSIngo Weinhold 1109*0c0fea5dSIngo Weinhold memset(list, 0, sLoadedImageCount * sizeof(image_t *)); 1110*0c0fea5dSIngo Weinhold 1111*0c0fea5dSIngo Weinhold *_list = list; 1112*0c0fea5dSIngo Weinhold return topological_sort(image, 0, list, sortFlag); 1113*0c0fea5dSIngo Weinhold } 1114*0c0fea5dSIngo Weinhold 1115*0c0fea5dSIngo Weinhold 1116*0c0fea5dSIngo Weinhold static status_t 1117*0c0fea5dSIngo Weinhold relocate_dependencies(image_t *image) 1118*0c0fea5dSIngo Weinhold { 1119*0c0fea5dSIngo Weinhold ssize_t count, i; 1120*0c0fea5dSIngo Weinhold image_t **list; 1121*0c0fea5dSIngo Weinhold 1122*0c0fea5dSIngo Weinhold count = get_sorted_image_list(image, &list, RFLAG_RELOCATED); 1123*0c0fea5dSIngo Weinhold if (count < B_OK) 1124*0c0fea5dSIngo Weinhold return count; 1125*0c0fea5dSIngo Weinhold 1126*0c0fea5dSIngo Weinhold for (i = 0; i < count; i++) { 1127*0c0fea5dSIngo Weinhold status_t status = relocate_image(list[i]); 1128*0c0fea5dSIngo Weinhold if (status < B_OK) 1129*0c0fea5dSIngo Weinhold return status; 1130*0c0fea5dSIngo Weinhold } 1131*0c0fea5dSIngo Weinhold 1132*0c0fea5dSIngo Weinhold free(list); 1133*0c0fea5dSIngo Weinhold return B_OK; 1134*0c0fea5dSIngo Weinhold } 1135*0c0fea5dSIngo Weinhold 1136*0c0fea5dSIngo Weinhold 1137*0c0fea5dSIngo Weinhold static void 1138*0c0fea5dSIngo Weinhold init_dependencies(image_t *image, bool initHead) 1139*0c0fea5dSIngo Weinhold { 1140*0c0fea5dSIngo Weinhold image_t **initList; 1141*0c0fea5dSIngo Weinhold ssize_t count, i; 1142*0c0fea5dSIngo Weinhold 1143*0c0fea5dSIngo Weinhold count = get_sorted_image_list(image, &initList, RFLAG_INITIALIZED); 1144*0c0fea5dSIngo Weinhold if (count <= 0) 1145*0c0fea5dSIngo Weinhold return; 1146*0c0fea5dSIngo Weinhold 1147*0c0fea5dSIngo Weinhold if (!initHead) { 1148*0c0fea5dSIngo Weinhold // this removes the "calling" image 1149*0c0fea5dSIngo Weinhold image->flags &= ~RFLAG_INITIALIZED; 1150*0c0fea5dSIngo Weinhold initList[--count] = NULL; 1151*0c0fea5dSIngo Weinhold } 1152*0c0fea5dSIngo Weinhold 1153*0c0fea5dSIngo Weinhold TRACE(("%ld: init dependencies\n", find_thread(NULL))); 1154*0c0fea5dSIngo Weinhold for (i = 0; i < count; i++) { 1155*0c0fea5dSIngo Weinhold image = initList[i]; 1156*0c0fea5dSIngo Weinhold 1157*0c0fea5dSIngo Weinhold TRACE(("%ld: init: %s\n", find_thread(NULL), image->name)); 1158*0c0fea5dSIngo Weinhold 1159*0c0fea5dSIngo Weinhold if (image->init_routine != NULL) 1160*0c0fea5dSIngo Weinhold ((init_term_function)image->init_routine)(image->id); 1161*0c0fea5dSIngo Weinhold } 1162*0c0fea5dSIngo Weinhold TRACE(("%ld: init done.\n", find_thread(NULL))); 1163*0c0fea5dSIngo Weinhold 1164*0c0fea5dSIngo Weinhold free(initList); 1165*0c0fea5dSIngo Weinhold } 1166*0c0fea5dSIngo Weinhold 1167*0c0fea5dSIngo Weinhold 1168*0c0fea5dSIngo Weinhold static void 1169*0c0fea5dSIngo Weinhold put_image(image_t *image) 1170*0c0fea5dSIngo Weinhold { 1171*0c0fea5dSIngo Weinhold // If all references to the image are gone, add it to the disposable list 1172*0c0fea5dSIngo Weinhold // and remove all dependencies 1173*0c0fea5dSIngo Weinhold 1174*0c0fea5dSIngo Weinhold if (atomic_add(&image->ref_count, -1) == 1) { 1175*0c0fea5dSIngo Weinhold size_t i; 1176*0c0fea5dSIngo Weinhold 1177*0c0fea5dSIngo Weinhold dequeue_image(&sLoadedImages, image); 1178*0c0fea5dSIngo Weinhold enqueue_image(&sDisposableImages, image); 1179*0c0fea5dSIngo Weinhold sLoadedImageCount--; 1180*0c0fea5dSIngo Weinhold 1181*0c0fea5dSIngo Weinhold for (i = 0; i < image->num_needed; i++) { 1182*0c0fea5dSIngo Weinhold put_image(image->needed[i]); 1183*0c0fea5dSIngo Weinhold } 1184*0c0fea5dSIngo Weinhold } 1185*0c0fea5dSIngo Weinhold } 1186*0c0fea5dSIngo Weinhold 1187*0c0fea5dSIngo Weinhold 1188*0c0fea5dSIngo Weinhold // #pragma mark - 1189*0c0fea5dSIngo Weinhold // Exported functions (to libroot.so) 1190*0c0fea5dSIngo Weinhold 1191*0c0fea5dSIngo Weinhold 1192*0c0fea5dSIngo Weinhold image_id 1193*0c0fea5dSIngo Weinhold load_program(char const *path, void **_entry) 1194*0c0fea5dSIngo Weinhold { 1195*0c0fea5dSIngo Weinhold status_t status; 1196*0c0fea5dSIngo Weinhold image_t *image; 1197*0c0fea5dSIngo Weinhold 1198*0c0fea5dSIngo Weinhold rld_lock(); 1199*0c0fea5dSIngo Weinhold // for now, just do stupid simple global locking 1200*0c0fea5dSIngo Weinhold 1201*0c0fea5dSIngo Weinhold TRACE(("rld: load %s\n", path)); 1202*0c0fea5dSIngo Weinhold 1203*0c0fea5dSIngo Weinhold status = load_container(path, B_APP_IMAGE, NULL, &sProgramImage); 1204*0c0fea5dSIngo Weinhold if (status < B_OK) { 1205*0c0fea5dSIngo Weinhold _kern_loading_app_failed(status); 1206*0c0fea5dSIngo Weinhold rld_unlock(); 1207*0c0fea5dSIngo Weinhold return status; 1208*0c0fea5dSIngo Weinhold } 1209*0c0fea5dSIngo Weinhold 1210*0c0fea5dSIngo Weinhold for (image = sLoadedImages.head; image != NULL; image = image->next) { 1211*0c0fea5dSIngo Weinhold status = load_dependencies(image); 1212*0c0fea5dSIngo Weinhold if (status < B_OK) 1213*0c0fea5dSIngo Weinhold goto err; 1214*0c0fea5dSIngo Weinhold } 1215*0c0fea5dSIngo Weinhold 1216*0c0fea5dSIngo Weinhold status = relocate_dependencies(sProgramImage); 1217*0c0fea5dSIngo Weinhold if (status < B_OK) 1218*0c0fea5dSIngo Weinhold goto err; 1219*0c0fea5dSIngo Weinhold 1220*0c0fea5dSIngo Weinhold // We patch any exported __gRuntimeLoader symbols to point to our private API 1221*0c0fea5dSIngo Weinhold { 1222*0c0fea5dSIngo Weinhold struct Elf32_Sym *symbol = find_symbol_in_loaded_images(&image, "__gRuntimeLoader"); 1223*0c0fea5dSIngo Weinhold if (symbol != NULL) { 1224*0c0fea5dSIngo Weinhold void **_export = (void **)(symbol->st_value + image->regions[0].delta); 1225*0c0fea5dSIngo Weinhold *_export = &gRuntimeLoader; 1226*0c0fea5dSIngo Weinhold } 1227*0c0fea5dSIngo Weinhold } 1228*0c0fea5dSIngo Weinhold 1229*0c0fea5dSIngo Weinhold init_dependencies(sLoadedImages.head, true); 1230*0c0fea5dSIngo Weinhold remap_images(); 1231*0c0fea5dSIngo Weinhold // ToDo: once setup_system_time() is fixed, move this one line higher! 1232*0c0fea5dSIngo Weinhold 1233*0c0fea5dSIngo Weinhold // Since the images are initialized now, we no longer should use our 1234*0c0fea5dSIngo Weinhold // getenv(), but use the one from libroot.so 1235*0c0fea5dSIngo Weinhold { 1236*0c0fea5dSIngo Weinhold struct Elf32_Sym *symbol = find_symbol_in_loaded_images(&image, "getenv"); 1237*0c0fea5dSIngo Weinhold if (symbol != NULL) 1238*0c0fea5dSIngo Weinhold gGetEnv = (char* (*)(const char*)) 1239*0c0fea5dSIngo Weinhold (symbol->st_value + image->regions[0].delta); 1240*0c0fea5dSIngo Weinhold } 1241*0c0fea5dSIngo Weinhold 1242*0c0fea5dSIngo Weinhold if (sProgramImage->entry_point == NULL) { 1243*0c0fea5dSIngo Weinhold status = B_NOT_AN_EXECUTABLE; 1244*0c0fea5dSIngo Weinhold goto err; 1245*0c0fea5dSIngo Weinhold } 1246*0c0fea5dSIngo Weinhold 1247*0c0fea5dSIngo Weinhold *_entry = (void *)(sProgramImage->entry_point); 1248*0c0fea5dSIngo Weinhold 1249*0c0fea5dSIngo Weinhold rld_unlock(); 1250*0c0fea5dSIngo Weinhold return sProgramImage->id; 1251*0c0fea5dSIngo Weinhold 1252*0c0fea5dSIngo Weinhold err: 1253*0c0fea5dSIngo Weinhold _kern_loading_app_failed(status); 1254*0c0fea5dSIngo Weinhold delete_image(sProgramImage); 1255*0c0fea5dSIngo Weinhold rld_unlock(); 1256*0c0fea5dSIngo Weinhold return status; 1257*0c0fea5dSIngo Weinhold } 1258*0c0fea5dSIngo Weinhold 1259*0c0fea5dSIngo Weinhold 1260*0c0fea5dSIngo Weinhold image_id 1261*0c0fea5dSIngo Weinhold load_library(char const *path, uint32 flags, bool addOn) 1262*0c0fea5dSIngo Weinhold { 1263*0c0fea5dSIngo Weinhold image_t *image = NULL; 1264*0c0fea5dSIngo Weinhold image_t *iter; 1265*0c0fea5dSIngo Weinhold image_type type = (addOn ? B_ADD_ON_IMAGE : B_LIBRARY_IMAGE); 1266*0c0fea5dSIngo Weinhold status_t status; 1267*0c0fea5dSIngo Weinhold 1268*0c0fea5dSIngo Weinhold if (path == NULL) 1269*0c0fea5dSIngo Weinhold return B_BAD_VALUE; 1270*0c0fea5dSIngo Weinhold 1271*0c0fea5dSIngo Weinhold // ToDo: implement flags 1272*0c0fea5dSIngo Weinhold (void)flags; 1273*0c0fea5dSIngo Weinhold 1274*0c0fea5dSIngo Weinhold rld_lock(); 1275*0c0fea5dSIngo Weinhold // for now, just do stupid simple global locking 1276*0c0fea5dSIngo Weinhold 1277*0c0fea5dSIngo Weinhold // have we already loaded this library? 1278*0c0fea5dSIngo Weinhold // Checking it at this stage saves loading its dependencies again 1279*0c0fea5dSIngo Weinhold if (!addOn) { 1280*0c0fea5dSIngo Weinhold image = find_image(path, APP_OR_LIBRARY_TYPE); 1281*0c0fea5dSIngo Weinhold if (image) { 1282*0c0fea5dSIngo Weinhold atomic_add(&image->ref_count, 1); 1283*0c0fea5dSIngo Weinhold rld_unlock(); 1284*0c0fea5dSIngo Weinhold return image->id; 1285*0c0fea5dSIngo Weinhold } 1286*0c0fea5dSIngo Weinhold } 1287*0c0fea5dSIngo Weinhold 1288*0c0fea5dSIngo Weinhold status = load_container(path, type, NULL, &image); 1289*0c0fea5dSIngo Weinhold if (status < B_OK) { 1290*0c0fea5dSIngo Weinhold rld_unlock(); 1291*0c0fea5dSIngo Weinhold return status; 1292*0c0fea5dSIngo Weinhold } 1293*0c0fea5dSIngo Weinhold 1294*0c0fea5dSIngo Weinhold for (iter = sLoadedImages.head; iter; iter = iter->next) { 1295*0c0fea5dSIngo Weinhold status = load_dependencies(iter); 1296*0c0fea5dSIngo Weinhold if (status < B_OK) 1297*0c0fea5dSIngo Weinhold goto err; 1298*0c0fea5dSIngo Weinhold } 1299*0c0fea5dSIngo Weinhold 1300*0c0fea5dSIngo Weinhold status = relocate_dependencies(image); 1301*0c0fea5dSIngo Weinhold if (status < B_OK) 1302*0c0fea5dSIngo Weinhold goto err; 1303*0c0fea5dSIngo Weinhold 1304*0c0fea5dSIngo Weinhold remap_images(); 1305*0c0fea5dSIngo Weinhold init_dependencies(image, true); 1306*0c0fea5dSIngo Weinhold 1307*0c0fea5dSIngo Weinhold rld_unlock(); 1308*0c0fea5dSIngo Weinhold return image->id; 1309*0c0fea5dSIngo Weinhold 1310*0c0fea5dSIngo Weinhold err: 1311*0c0fea5dSIngo Weinhold dequeue_image(&sLoadedImages, image); 1312*0c0fea5dSIngo Weinhold sLoadedImageCount--; 1313*0c0fea5dSIngo Weinhold delete_image(image); 1314*0c0fea5dSIngo Weinhold rld_unlock(); 1315*0c0fea5dSIngo Weinhold return status; 1316*0c0fea5dSIngo Weinhold } 1317*0c0fea5dSIngo Weinhold 1318*0c0fea5dSIngo Weinhold 1319*0c0fea5dSIngo Weinhold status_t 1320*0c0fea5dSIngo Weinhold unload_library(image_id imageID, bool addOn) 1321*0c0fea5dSIngo Weinhold { 1322*0c0fea5dSIngo Weinhold status_t status = B_BAD_IMAGE_ID; 1323*0c0fea5dSIngo Weinhold image_t *image; 1324*0c0fea5dSIngo Weinhold image_type type = addOn ? B_ADD_ON_IMAGE : B_LIBRARY_IMAGE; 1325*0c0fea5dSIngo Weinhold 1326*0c0fea5dSIngo Weinhold if (imageID < B_OK) 1327*0c0fea5dSIngo Weinhold return B_BAD_IMAGE_ID; 1328*0c0fea5dSIngo Weinhold 1329*0c0fea5dSIngo Weinhold rld_lock(); 1330*0c0fea5dSIngo Weinhold // for now, just do stupid simple global locking 1331*0c0fea5dSIngo Weinhold 1332*0c0fea5dSIngo Weinhold // we only check images that have been already initialized 1333*0c0fea5dSIngo Weinhold 1334*0c0fea5dSIngo Weinhold for (image = sLoadedImages.head; image; image = image->next) { 1335*0c0fea5dSIngo Weinhold if (image->id == imageID) { 1336*0c0fea5dSIngo Weinhold // unload image 1337*0c0fea5dSIngo Weinhold if (type == image->type) { 1338*0c0fea5dSIngo Weinhold put_image(image); 1339*0c0fea5dSIngo Weinhold status = B_OK; 1340*0c0fea5dSIngo Weinhold } else 1341*0c0fea5dSIngo Weinhold status = B_BAD_VALUE; 1342*0c0fea5dSIngo Weinhold break; 1343*0c0fea5dSIngo Weinhold } 1344*0c0fea5dSIngo Weinhold } 1345*0c0fea5dSIngo Weinhold 1346*0c0fea5dSIngo Weinhold if (status == B_OK) { 1347*0c0fea5dSIngo Weinhold while ((image = sDisposableImages.head) != NULL) { 1348*0c0fea5dSIngo Weinhold // call image fini here... 1349*0c0fea5dSIngo Weinhold if (image->term_routine) 1350*0c0fea5dSIngo Weinhold ((init_term_function)image->term_routine)(image->id); 1351*0c0fea5dSIngo Weinhold 1352*0c0fea5dSIngo Weinhold dequeue_image(&sDisposableImages, image); 1353*0c0fea5dSIngo Weinhold unmap_image(image); 1354*0c0fea5dSIngo Weinhold 1355*0c0fea5dSIngo Weinhold delete_image(image); 1356*0c0fea5dSIngo Weinhold } 1357*0c0fea5dSIngo Weinhold } 1358*0c0fea5dSIngo Weinhold 1359*0c0fea5dSIngo Weinhold rld_unlock(); 1360*0c0fea5dSIngo Weinhold return status; 1361*0c0fea5dSIngo Weinhold } 1362*0c0fea5dSIngo Weinhold 1363*0c0fea5dSIngo Weinhold 1364*0c0fea5dSIngo Weinhold status_t 1365*0c0fea5dSIngo Weinhold get_nth_symbol(image_id imageID, int32 num, char *nameBuffer, int32 *_nameLength, 1366*0c0fea5dSIngo Weinhold int32 *_type, void **_location) 1367*0c0fea5dSIngo Weinhold { 1368*0c0fea5dSIngo Weinhold int32 count = 0, j; 1369*0c0fea5dSIngo Weinhold uint32 i; 1370*0c0fea5dSIngo Weinhold image_t *image; 1371*0c0fea5dSIngo Weinhold 1372*0c0fea5dSIngo Weinhold rld_lock(); 1373*0c0fea5dSIngo Weinhold 1374*0c0fea5dSIngo Weinhold // get the image from those who have been already initialized 1375*0c0fea5dSIngo Weinhold image = find_loaded_image_by_id(imageID); 1376*0c0fea5dSIngo Weinhold if (image == NULL) { 1377*0c0fea5dSIngo Weinhold rld_unlock(); 1378*0c0fea5dSIngo Weinhold return B_BAD_IMAGE_ID; 1379*0c0fea5dSIngo Weinhold } 1380*0c0fea5dSIngo Weinhold 1381*0c0fea5dSIngo Weinhold // iterate through all the hash buckets until we've found the one 1382*0c0fea5dSIngo Weinhold for (i = 0; i < HASHTABSIZE(image); i++) { 1383*0c0fea5dSIngo Weinhold for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) { 1384*0c0fea5dSIngo Weinhold struct Elf32_Sym *symbol = &image->syms[i]; 1385*0c0fea5dSIngo Weinhold 1386*0c0fea5dSIngo Weinhold if (count == num) { 1387*0c0fea5dSIngo Weinhold strlcpy(nameBuffer, SYMNAME(image, symbol), *_nameLength); 1388*0c0fea5dSIngo Weinhold *_nameLength = strlen(SYMNAME(image, symbol)); 1389*0c0fea5dSIngo Weinhold 1390*0c0fea5dSIngo Weinhold if (_type != NULL) { 1391*0c0fea5dSIngo Weinhold // ToDo: check with the return types of that BeOS function 1392*0c0fea5dSIngo Weinhold if (ELF32_ST_TYPE(symbol->st_info) == STT_FUNC) 1393*0c0fea5dSIngo Weinhold *_type = B_SYMBOL_TYPE_TEXT; 1394*0c0fea5dSIngo Weinhold else if (ELF32_ST_TYPE(symbol->st_info) == STT_OBJECT) 1395*0c0fea5dSIngo Weinhold *_type = B_SYMBOL_TYPE_DATA; 1396*0c0fea5dSIngo Weinhold else 1397*0c0fea5dSIngo Weinhold *_type = B_SYMBOL_TYPE_ANY; 1398*0c0fea5dSIngo Weinhold } 1399*0c0fea5dSIngo Weinhold 1400*0c0fea5dSIngo Weinhold if (_location != NULL) 1401*0c0fea5dSIngo Weinhold *_location = (void *)(symbol->st_value + image->regions[0].delta); 1402*0c0fea5dSIngo Weinhold goto out; 1403*0c0fea5dSIngo Weinhold } 1404*0c0fea5dSIngo Weinhold count++; 1405*0c0fea5dSIngo Weinhold } 1406*0c0fea5dSIngo Weinhold } 1407*0c0fea5dSIngo Weinhold out: 1408*0c0fea5dSIngo Weinhold rld_unlock(); 1409*0c0fea5dSIngo Weinhold 1410*0c0fea5dSIngo Weinhold if (num != count) 1411*0c0fea5dSIngo Weinhold return B_BAD_INDEX; 1412*0c0fea5dSIngo Weinhold 1413*0c0fea5dSIngo Weinhold return B_OK; 1414*0c0fea5dSIngo Weinhold } 1415*0c0fea5dSIngo Weinhold 1416*0c0fea5dSIngo Weinhold 1417*0c0fea5dSIngo Weinhold status_t 1418*0c0fea5dSIngo Weinhold get_symbol(image_id imageID, char const *symbolName, int32 symbolType, void **_location) 1419*0c0fea5dSIngo Weinhold { 1420*0c0fea5dSIngo Weinhold status_t status = B_OK; 1421*0c0fea5dSIngo Weinhold image_t *image; 1422*0c0fea5dSIngo Weinhold 1423*0c0fea5dSIngo Weinhold if (imageID < B_OK) 1424*0c0fea5dSIngo Weinhold return B_BAD_IMAGE_ID; 1425*0c0fea5dSIngo Weinhold if (symbolName == NULL) 1426*0c0fea5dSIngo Weinhold return B_BAD_VALUE; 1427*0c0fea5dSIngo Weinhold 1428*0c0fea5dSIngo Weinhold rld_lock(); 1429*0c0fea5dSIngo Weinhold // for now, just do stupid simple global locking 1430*0c0fea5dSIngo Weinhold 1431*0c0fea5dSIngo Weinhold // get the image from those who have been already initialized 1432*0c0fea5dSIngo Weinhold image = find_loaded_image_by_id(imageID); 1433*0c0fea5dSIngo Weinhold if (image != NULL) { 1434*0c0fea5dSIngo Weinhold struct Elf32_Sym *symbol; 1435*0c0fea5dSIngo Weinhold 1436*0c0fea5dSIngo Weinhold // get the symbol in the image 1437*0c0fea5dSIngo Weinhold symbol = find_symbol(image, symbolName, symbolType); 1438*0c0fea5dSIngo Weinhold if (symbol) { 1439*0c0fea5dSIngo Weinhold if (_location != NULL) 1440*0c0fea5dSIngo Weinhold *_location = (void *)(symbol->st_value + image->regions[0].delta); 1441*0c0fea5dSIngo Weinhold } else 1442*0c0fea5dSIngo Weinhold status = B_ENTRY_NOT_FOUND; 1443*0c0fea5dSIngo Weinhold } else 1444*0c0fea5dSIngo Weinhold status = B_BAD_IMAGE_ID; 1445*0c0fea5dSIngo Weinhold 1446*0c0fea5dSIngo Weinhold rld_unlock(); 1447*0c0fea5dSIngo Weinhold return status; 1448*0c0fea5dSIngo Weinhold } 1449*0c0fea5dSIngo Weinhold 1450*0c0fea5dSIngo Weinhold 1451*0c0fea5dSIngo Weinhold status_t 1452*0c0fea5dSIngo Weinhold get_next_image_dependency(image_id id, uint32 *cookie, const char **_name) 1453*0c0fea5dSIngo Weinhold { 1454*0c0fea5dSIngo Weinhold uint32 i, j, searchIndex = *cookie; 1455*0c0fea5dSIngo Weinhold struct Elf32_Dyn *dynamicSection; 1456*0c0fea5dSIngo Weinhold image_t *image; 1457*0c0fea5dSIngo Weinhold 1458*0c0fea5dSIngo Weinhold if (_name == NULL) 1459*0c0fea5dSIngo Weinhold return B_BAD_VALUE; 1460*0c0fea5dSIngo Weinhold 1461*0c0fea5dSIngo Weinhold rld_lock(); 1462*0c0fea5dSIngo Weinhold 1463*0c0fea5dSIngo Weinhold image = find_loaded_image_by_id(id); 1464*0c0fea5dSIngo Weinhold if (image == NULL) { 1465*0c0fea5dSIngo Weinhold rld_unlock(); 1466*0c0fea5dSIngo Weinhold return B_BAD_IMAGE_ID; 1467*0c0fea5dSIngo Weinhold } 1468*0c0fea5dSIngo Weinhold 1469*0c0fea5dSIngo Weinhold dynamicSection = (struct Elf32_Dyn *)image->dynamic_ptr; 1470*0c0fea5dSIngo Weinhold if (dynamicSection == NULL || image->num_needed <= searchIndex) { 1471*0c0fea5dSIngo Weinhold rld_unlock(); 1472*0c0fea5dSIngo Weinhold return B_ENTRY_NOT_FOUND; 1473*0c0fea5dSIngo Weinhold } 1474*0c0fea5dSIngo Weinhold 1475*0c0fea5dSIngo Weinhold for (i = 0, j = 0; dynamicSection[i].d_tag != DT_NULL; i++) { 1476*0c0fea5dSIngo Weinhold if (dynamicSection[i].d_tag != DT_NEEDED) 1477*0c0fea5dSIngo Weinhold continue; 1478*0c0fea5dSIngo Weinhold 1479*0c0fea5dSIngo Weinhold if (j++ == searchIndex) { 1480*0c0fea5dSIngo Weinhold int32 neededOffset = dynamicSection[i].d_un.d_val; 1481*0c0fea5dSIngo Weinhold 1482*0c0fea5dSIngo Weinhold *_name = STRING(image, neededOffset); 1483*0c0fea5dSIngo Weinhold *cookie = searchIndex + 1; 1484*0c0fea5dSIngo Weinhold rld_unlock(); 1485*0c0fea5dSIngo Weinhold return B_OK; 1486*0c0fea5dSIngo Weinhold } 1487*0c0fea5dSIngo Weinhold } 1488*0c0fea5dSIngo Weinhold 1489*0c0fea5dSIngo Weinhold rld_unlock(); 1490*0c0fea5dSIngo Weinhold return B_ENTRY_NOT_FOUND; 1491*0c0fea5dSIngo Weinhold } 1492*0c0fea5dSIngo Weinhold 1493*0c0fea5dSIngo Weinhold 1494*0c0fea5dSIngo Weinhold // #pragma mark - 1495*0c0fea5dSIngo Weinhold 1496*0c0fea5dSIngo Weinhold 1497*0c0fea5dSIngo Weinhold /** Read and verify the ELF header */ 1498*0c0fea5dSIngo Weinhold 1499*0c0fea5dSIngo Weinhold status_t 1500*0c0fea5dSIngo Weinhold elf_verify_header(void *header, int32 length) 1501*0c0fea5dSIngo Weinhold { 1502*0c0fea5dSIngo Weinhold int32 programSize, sectionSize; 1503*0c0fea5dSIngo Weinhold 1504*0c0fea5dSIngo Weinhold if (length < (int32)sizeof(struct Elf32_Ehdr)) 1505*0c0fea5dSIngo Weinhold return B_NOT_AN_EXECUTABLE; 1506*0c0fea5dSIngo Weinhold 1507*0c0fea5dSIngo Weinhold return parse_elf_header((struct Elf32_Ehdr *)header, &programSize, §ionSize); 1508*0c0fea5dSIngo Weinhold } 1509*0c0fea5dSIngo Weinhold 1510*0c0fea5dSIngo Weinhold 1511*0c0fea5dSIngo Weinhold void 1512*0c0fea5dSIngo Weinhold terminate_program(void) 1513*0c0fea5dSIngo Weinhold { 1514*0c0fea5dSIngo Weinhold image_t **termList; 1515*0c0fea5dSIngo Weinhold ssize_t count, i; 1516*0c0fea5dSIngo Weinhold 1517*0c0fea5dSIngo Weinhold count = get_sorted_image_list(sProgramImage, &termList, RFLAG_TERMINATED); 1518*0c0fea5dSIngo Weinhold if (count < B_OK) 1519*0c0fea5dSIngo Weinhold return; 1520*0c0fea5dSIngo Weinhold 1521*0c0fea5dSIngo Weinhold TRACE(("%ld: terminate dependencies\n", find_thread(NULL))); 1522*0c0fea5dSIngo Weinhold for (i = count; i-- > 0;) { 1523*0c0fea5dSIngo Weinhold image_t *image = termList[i]; 1524*0c0fea5dSIngo Weinhold 1525*0c0fea5dSIngo Weinhold TRACE(("%ld: term: %s\n", find_thread(NULL), image->name)); 1526*0c0fea5dSIngo Weinhold 1527*0c0fea5dSIngo Weinhold if (image->term_routine) 1528*0c0fea5dSIngo Weinhold ((init_term_function)image->term_routine)(image->id); 1529*0c0fea5dSIngo Weinhold } 1530*0c0fea5dSIngo Weinhold TRACE(("%ld: term done.\n", find_thread(NULL))); 1531*0c0fea5dSIngo Weinhold 1532*0c0fea5dSIngo Weinhold free(termList); 1533*0c0fea5dSIngo Weinhold } 1534*0c0fea5dSIngo Weinhold 1535*0c0fea5dSIngo Weinhold 1536*0c0fea5dSIngo Weinhold void 1537*0c0fea5dSIngo Weinhold rldelf_init(void) 1538*0c0fea5dSIngo Weinhold { 1539*0c0fea5dSIngo Weinhold rld_sem = create_sem(1, "rld_lock"); 1540*0c0fea5dSIngo Weinhold rld_sem_owner = -1; 1541*0c0fea5dSIngo Weinhold rld_sem_count = 0; 1542*0c0fea5dSIngo Weinhold 1543*0c0fea5dSIngo Weinhold // create the debug area 1544*0c0fea5dSIngo Weinhold { 1545*0c0fea5dSIngo Weinhold int32 size = TO_PAGE_SIZE(sizeof(runtime_loader_debug_area)); 1546*0c0fea5dSIngo Weinhold 1547*0c0fea5dSIngo Weinhold runtime_loader_debug_area *area; 1548*0c0fea5dSIngo Weinhold area_id areaID = _kern_create_area(RUNTIME_LOADER_DEBUG_AREA_NAME, 1549*0c0fea5dSIngo Weinhold (void **)&area, B_ANY_ADDRESS, size, B_NO_LOCK, 1550*0c0fea5dSIngo Weinhold B_READ_AREA | B_WRITE_AREA); 1551*0c0fea5dSIngo Weinhold if (areaID < B_OK) { 1552*0c0fea5dSIngo Weinhold FATAL("Failed to create debug area.\n"); 1553*0c0fea5dSIngo Weinhold _kern_loading_app_failed(areaID); 1554*0c0fea5dSIngo Weinhold } 1555*0c0fea5dSIngo Weinhold 1556*0c0fea5dSIngo Weinhold area->loaded_images = &sLoadedImages; 1557*0c0fea5dSIngo Weinhold } 1558*0c0fea5dSIngo Weinhold } 1559