void DSBT_release_entry(int32_t file_handle) { int32_t i; DSBT_Entry *client_dsbt = (DSBT_Entry *)(DSBT_master.buf); for (i = 0; i < AL_size(&DSBT_master); i++) { DSBT_Index_Request *curr_req = client_dsbt[i].index_request; if (curr_req && (curr_req->file_handle == file_handle)) { client_dsbt[i].index_request = NULL; if (i < DSBT_first_avail_index) DSBT_first_avail_index = i; DLIF_free(curr_req); } } }
void DLSYM_copy_globals(DLIMP_Dynamic_Module *dyn_module) { Elf32_Word i, global_index, global_symnum; DLIMP_Loaded_Module *module = dyn_module->loaded_module; #if LOADER_DEBUG if (debugging_on) DLIF_trace("DLSYM_copy_globals:\n"); #endif /*------------------------------------------------------------------------*/ /* The dynamic symbol table is sorted so that the local symbols come */ /* before the global symbols. gsymtab_offset points to the address where */ /* the first global symbol starts. Only the global symbols need to be */ /* copied into the persistent info. */ /*------------------------------------------------------------------------*/ global_index = dyn_module->gsymtab_offset / sizeof(struct Elf32_Sym); global_symnum = dyn_module->symnum - global_index; /*------------------------------------------------------------------------*/ /* Create space for the new global symbol table. */ /*------------------------------------------------------------------------*/ if (module->gsymtab) DLIF_free(module->gsymtab); module->gsymtab = DLIF_malloc(sizeof(struct Elf32_Sym) * global_symnum); module->gsymnum = global_symnum; if (module->gsymtab) memcpy(module->gsymtab, &dyn_module->symtab[global_index], sizeof(struct Elf32_Sym) * global_symnum); /*------------------------------------------------------------------------*/ /* Copy the string table part that contains the global symbol names. */ /*------------------------------------------------------------------------*/ if (module->gstrtab) DLIF_free(module->gstrtab); module->gstrsz = dyn_module->strsz - dyn_module->gstrtab_offset; module->gstrtab = DLIF_malloc(module->gstrsz); if (module->gstrtab) memcpy(module->gstrtab, dyn_module->strtab + dyn_module->gstrtab_offset, module->gstrsz); /*------------------------------------------------------------------------*/ /* Update the symbol names of the global symbol entries to point to */ /* the symbol names in the string table. */ /* NOTE: Note that we don't set the offset into the string table. We */ /* instead set the full address so that the st_name field can be accessed */ /* as char *. */ /*------------------------------------------------------------------------*/ for (i = 0; i < global_symnum; i++) { Elf32_Word old_offset = dyn_module->symtab[i + global_index].st_name - (Elf32_Addr) dyn_module->strtab; Elf32_Word new_offset = old_offset - dyn_module->gstrtab_offset; if(module->gsymtab) { struct Elf32_Sym *sym = &((struct Elf32_Sym*)(module->gsymtab))[i]; sym->st_name = new_offset + (Elf32_Addr)module->gstrtab; } #if LOADER_DEBUG if (debugging_on) DLIF_trace("Copying symbol: %s\n", (char *) dyn_module->symtab[i + global_index].st_name); #endif } }
BOOL DLIF_register_dsbt_index_request(DLOAD_HANDLE handle, const char *requestor_name, int32_t requestor_file_handle, int32_t requested_dsbt_index) { DSBT_Index_Request *new_request = NULL; /*------------------------------------------------------------------------*/ /* If requesting a specific DSBT index, check existing list of DSBT index */ /* requests to see if we've already seen a request for the specified */ /* DSBT index or if a request has already been received on behalf of the */ /* specified file. Both cases constitute an error and will abort the */ /* load. */ /*------------------------------------------------------------------------*/ if (requested_dsbt_index != DSBT_INDEX_INVALID) { dsbt_index_request_ptr_Queue_Node *ptr; /*---------------------------------------------------------------------*/ /* If the client's master DSBT model already has content, then check */ /* to see if the requested DSBT index is available in the master DSBT. */ /*---------------------------------------------------------------------*/ if (AL_size(&DSBT_master) > requested_dsbt_index) { DSBT_Entry *client_dsbt = (DSBT_Entry *)(DSBT_master.buf); if (client_dsbt[requested_dsbt_index].index_request != NULL) { DLIF_error(DLET_MISC, "%s is requesting a DSBT index, %d, that is already " "being used by an active module, %s", requestor_name, requested_dsbt_index, client_dsbt[requested_dsbt_index].index_request->name); return FALSE; } } for (ptr = DSBT_index_request_queue.front_ptr; ptr != NULL; ptr = ptr->next_ptr) { DSBT_Index_Request *existing_request = ptr->value; /*------------------------------------------------------------------*/ /* Have we seen a request for this file already? That would be a */ /* problem (likely internal). */ /*------------------------------------------------------------------*/ if (requestor_file_handle == existing_request->file_handle) { DLIF_error(DLET_MISC, "A DSBT index has already been requested on behalf " "of %s; cannot make a second DSBT index request for " "the same module", existing_request->name); return FALSE; } /*------------------------------------------------------------------*/ /* Have we seen a specific request for this DSBT index already? */ /* Report a conflict among specific requests in the same load. */ /*------------------------------------------------------------------*/ if (requested_dsbt_index == existing_request->requested_index) { DLIF_error(DLET_MISC, "Requested DSBT index, %d, requested by %s has " "already been requested by %s; load aborted", requested_dsbt_index, requestor_name, existing_request->name); return FALSE; } } } /*------------------------------------------------------------------------*/ /* If specified module is requesting a specific DSBT index that hasn't */ /* been encountered yet, or if it is making a general DSBT index request */ /* (to be assigned by the client when the current top-level load is */ /* sucessfully completed), make a DSBT index request entry for the */ /* current module and add it to the DSBT_Index_Request_List. */ /*------------------------------------------------------------------------*/ new_request = (DSBT_Index_Request *)DLIF_malloc(sizeof(DSBT_Index_Request)); new_request->name = (char *)DLIF_malloc(strlen(requestor_name) + 1); strcpy(new_request->name, requestor_name); new_request->file_handle = requestor_file_handle; new_request->dsbt_size = DLOAD_get_dsbt_size(handle, requestor_file_handle); if (!DLOAD_get_dsbt_base(handle, requestor_file_handle, &new_request->dsbt_base)) { DLIF_error(DLET_MISC, "Could not resolve DSBT base value for %s", requestor_name); DLIF_free(new_request->name); new_request->name = NULL; DLIF_free(new_request); new_request = NULL; return FALSE; } if (!DLOAD_get_static_base(handle, requestor_file_handle, &new_request->static_base)) { DLIF_error(DLET_MISC, "Could not resolve static base value for %s", requestor_name); DLIF_free(new_request->name); new_request->name = NULL; DLIF_free(new_request); new_request = NULL; return FALSE; } new_request->requested_index = requested_dsbt_index; new_request->assigned_index = DSBT_INDEX_INVALID; dsbt_index_request_ptr_enqueue(&DSBT_index_request_queue, new_request); return TRUE; }
void DLREL_c60_relocate(DLOAD_HANDLE handle, LOADER_FILE_DESC *fd, DLIMP_Dynamic_Module *dyn_module) { struct Elf32_Dyn *dyn_nugget = dyn_module->dyntab; struct Elf32_Rela *rela_table = NULL; struct Elf32_Rel *rel_table = NULL; struct Elf32_Rela *rela_plt_table = NULL; struct Elf32_Rel *rel_plt_table = NULL; /*------------------------------------------------------------------------*/ /* Read the size of the relocation table (DT_RELASZ) and the size per */ /* relocation (DT_RELAENT) from the dynamic segment. */ /*------------------------------------------------------------------------*/ uint32_t relasz = DLIMP_get_first_dyntag(DT_RELASZ, dyn_nugget); uint32_t relaent = DLIMP_get_first_dyntag(DT_RELAENT, dyn_nugget); uint32_t relanum = 0; /*------------------------------------------------------------------------*/ /* Read the size of the relocation table (DT_RELSZ) and the size per */ /* relocation (DT_RELENT) from the dynamic segment. */ /*------------------------------------------------------------------------*/ uint32_t relsz = DLIMP_get_first_dyntag(DT_RELSZ, dyn_nugget); uint32_t relent = DLIMP_get_first_dyntag(DT_RELENT, dyn_nugget); uint32_t relnum = 0; /*------------------------------------------------------------------------*/ /* Read the size of the relocation table (DT_PLTRELSZ) and the type of */ /* of the PLTGOT relocation table (DT_PLTREL): one of DT_REL or DT_RELA */ /*------------------------------------------------------------------------*/ uint32_t pltrelsz = DLIMP_get_first_dyntag(DT_PLTRELSZ, dyn_nugget); int pltreltyp = DLIMP_get_first_dyntag(DT_PLTREL, dyn_nugget); uint32_t pltnum = 0; /*------------------------------------------------------------------------*/ /* Find/record DSBT index associated with this module. */ /*------------------------------------------------------------------------*/ if (is_dsbt_module(dyn_module) && (dyn_module->dsbt_index == DSBT_INDEX_INVALID)) dyn_module->dsbt_index = DLIF_get_dsbt_index(dyn_module->loaded_module->file_handle); /*------------------------------------------------------------------------*/ /* Read the PLTGOT relocation table from the file */ /* The PLTGOT table is a subsection at the end of either the DT_REL or */ /* DT_RELA table. The size of the table it belongs to DT_REL(A)SZ */ /* includes the size of the PLTGOT table. So it must be adjusted so that */ /* the GOT relocation tables only contain actual GOT relocations. */ /*------------------------------------------------------------------------*/ if (pltrelsz != INT_MAX && pltrelsz != 0) { if (pltreltyp == DT_REL) { pltnum = pltrelsz/relent; relsz -= pltrelsz; read_rel_table((&rel_plt_table), DLIMP_get_first_dyntag(DT_JMPREL, dyn_nugget), pltnum, relent, fd, dyn_module->wrong_endian); } else if (pltreltyp == DT_RELA) { pltnum = pltrelsz/relaent; relasz -= pltrelsz; read_rela_table((&rela_plt_table), DLIMP_get_first_dyntag(DT_JMPREL, dyn_nugget), pltnum, relaent, fd, dyn_module->wrong_endian); } else { DLIF_error(DLET_RELOC, "DT_PLTREL is invalid: must be either %d or %d\n", DT_REL, DT_RELA); } } /*------------------------------------------------------------------------*/ /* Read the DT_RELA GOT relocation table from the file */ /*------------------------------------------------------------------------*/ if (relasz != INT_MAX && relasz != 0) { relanum = relasz/relaent; read_rela_table(&rela_table, DLIMP_get_first_dyntag(DT_RELA, dyn_nugget), relanum, relaent, fd, dyn_module->wrong_endian); } /*------------------------------------------------------------------------*/ /* Read the DT_REL GOT relocation table from the file */ /*------------------------------------------------------------------------*/ if (relsz != INT_MAX && relsz != 0) { relnum = relsz/relent; read_rel_table(&rel_table, DLIMP_get_first_dyntag(DT_REL, dyn_nugget), relnum, relent, fd, dyn_module->wrong_endian); } /*------------------------------------------------------------------------*/ /* Process the PLTGOT relocations */ /*------------------------------------------------------------------------*/ if (rela_plt_table) process_pltgot_relocs(handle, rela_plt_table, pltreltyp, pltnum, dyn_module); if (rel_plt_table) process_pltgot_relocs(handle, rel_plt_table, pltreltyp, pltnum, dyn_module); /*------------------------------------------------------------------------*/ /* Process the GOT relocations */ /*------------------------------------------------------------------------*/ if (rel_table || rela_table) process_got_relocs(handle, rel_table, relnum, rela_table, relanum, dyn_module); /*-------------------------------------------------------------------------*/ /* Free memory used for ELF relocation table copies. */ /*-------------------------------------------------------------------------*/ if (rela_table) DLIF_free(rela_table); if (rel_table) DLIF_free(rel_table); if (rela_plt_table) DLIF_free(rela_plt_table); if (rel_plt_table) DLIF_free(rel_plt_table); }