diff options
Diffstat (limited to 'cpukit/libdl')
-rw-r--r-- | cpukit/libdl/rtl-elf.c | 346 | ||||
-rw-r--r-- | cpukit/libdl/rtl-elf.h | 22 | ||||
-rw-r--r-- | cpukit/libdl/rtl-obj.c | 141 | ||||
-rw-r--r-- | cpukit/libdl/rtl-shell.c | 54 | ||||
-rw-r--r-- | cpukit/libdl/rtl-unresolved.c | 4 | ||||
-rw-r--r-- | cpukit/libdl/rtl.c | 48 |
6 files changed, 491 insertions, 124 deletions
diff --git a/cpukit/libdl/rtl-elf.c b/cpukit/libdl/rtl-elf.c index c1821bcfda..762130b9e7 100644 --- a/cpukit/libdl/rtl-elf.c +++ b/cpukit/libdl/rtl-elf.c @@ -64,31 +64,40 @@ rtems_rtl_elf_machine_check (Elf_Ehdr* ehdr) return true; } -bool -rtems_rtl_elf_find_symbol (rtems_rtl_obj* obj, - const Elf_Sym* sym, - const char* symname, - Elf_Word* value) +static bool +rtems_rtl_elf_find_symbol (rtems_rtl_obj* obj, + const Elf_Sym* sym, + const char* symname, + rtems_rtl_obj_sym** symbol, + Elf_Word* value) { rtems_rtl_obj_sect* sect; - if (ELF_ST_TYPE(sym->st_info) == STT_NOTYPE || - sym->st_shndx == SHN_COMMON) + /* + * If the symbol type is STT_NOTYPE the symbol references a global + * symbol. The gobal symbol table is searched to find it and that value + * returned. If the symbol is local to the object module the section for the + * symbol is located and it's base added to the symbol's value giving an + * absolute location. + */ + if (ELF_ST_TYPE(sym->st_info) == STT_NOTYPE || sym->st_shndx == SHN_COMMON) { /* * Search the object file then the global table for the symbol. */ - rtems_rtl_obj_sym* symbol = rtems_rtl_symbol_obj_find (obj, symname); - if (!symbol) + *symbol = rtems_rtl_symbol_obj_find (obj, symname); + if (!*symbol) { rtems_rtl_set_error (EINVAL, "global symbol not found: %s", symname); return false; } - *value = (Elf_Addr) symbol->value; + *value = (Elf_Addr) (*symbol)->value; return true; } + *symbol = NULL; + sect = rtems_rtl_obj_find_section_by_index (obj, sym->st_shndx); if (!sect) { @@ -100,11 +109,161 @@ rtems_rtl_elf_find_symbol (rtems_rtl_obj* obj, return true; } +/** + * Relocation worker routine. + */ +typedef bool (*rtems_rtl_elf_reloc_handler)(rtems_rtl_obj* obj, + bool is_rela, + void* relbuf, + rtems_rtl_obj_sect* targetsect, + rtems_rtl_obj_sym* symbol, + Elf_Sym* sym, + const char* symname, + Elf_Word symvalue, + bool resolved, + void* data); + +/** + * Relocation parser data. + */ +typedef struct +{ + size_t dependents; /**< The number of dependent object files. */ + size_t unresolved; /**< The number of unresolved symbols. */ +} rtems_rtl_elf_reloc_data; + +static bool +rtems_rtl_elf_reloc_parser (rtems_rtl_obj* obj, + bool is_rela, + void* relbuf, + rtems_rtl_obj_sect* targetsect, + rtems_rtl_obj_sym* symbol, + Elf_Sym* sym, + const char* symname, + Elf_Word symvalue, + bool resolved, + void* data) +{ + rtems_rtl_elf_reloc_data* rd = (rtems_rtl_elf_reloc_data*) data; + /* + * If the symbol has been resolved and there is a symbol name it is a global + * symbol and from another object file so add it as a dependency. + */ + if (!resolved) + { + ++rd->unresolved; + } + else if (resolved && symname != NULL) + { + /* + * Find the symbol's object file. It cannot be NULL so ignore that result + * if returned, it means something is corrupted. We are in an iterator. + */ + rtems_rtl_obj* sobj = rtems_rtl_find_obj_with_symbol (symbol); + if (sobj != NULL) + { + /* + * A dependency is not the base kernel image or itself. Tag the object as + * having been visited so we count it only once. + */ + if (sobj != rtems_rtl_baseimage () && obj != sobj && + (sobj->flags & RTEMS_RTL_OBJ_RELOC_TAG) == 0) + { + sobj->flags |= RTEMS_RTL_OBJ_RELOC_TAG; + ++rd->dependents; + } + } + } + return true; +} + +static bool +rtems_rtl_elf_reloc_relocator (rtems_rtl_obj* obj, + bool is_rela, + void* relbuf, + rtems_rtl_obj_sect* targetsect, + rtems_rtl_obj_sym* symbol, + Elf_Sym* sym, + const char* symname, + Elf_Word symvalue, + bool resolved, + void* data) +{ + const Elf_Rela* rela = (const Elf_Rela*) relbuf; + const Elf_Rel* rel = (const Elf_Rel*) relbuf; + + if (!resolved) + { + uint16_t flags = 0; + rtems_rtl_word rel_words[3]; + + if (is_rela) + { + flags = 1; + rel_words[REL_R_OFFSET] = rela->r_offset; + rel_words[REL_R_INFO] = rela->r_info; + rel_words[REL_R_ADDEND] = rela->r_addend; + } + else + { + rel_words[REL_R_OFFSET] = rel->r_offset; + rel_words[REL_R_INFO] = rel->r_info; + rel_words[REL_R_ADDEND] = 0; + } + + if (!rtems_rtl_unresolved_add (obj, + flags, + symname, + targetsect->section, + rel_words)) + return false; + + ++obj->unresolved; + } + else + { + rtems_rtl_obj* sobj; + + if (is_rela) + { + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: rela: sym:%s(%d)=%08jx type:%d off:%08jx addend:%d\n", + symname, (int) ELF_R_SYM (rela->r_info), + (uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info), + (uintmax_t) rela->r_offset, (int) rela->r_addend); + if (!rtems_rtl_elf_relocate_rela (obj, rela, targetsect, + symname, sym->st_info, symvalue)) + return false; + } + else + { + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: rel: sym:%s(%d)=%08jx type:%d off:%08jx\n", + symname, (int) ELF_R_SYM (rel->r_info), + (uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info), + (uintmax_t) rel->r_offset); + if (!rtems_rtl_elf_relocate_rel (obj, rel, targetsect, + symname, sym->st_info, symvalue)) + return false; + } + + sobj = rtems_rtl_find_obj_with_symbol (symbol); + if (sobj != NULL) + { + if (rtems_rtl_obj_add_dependent (obj, sobj)) + rtems_rtl_obj_inc_reference (sobj); + } + } + + return true; +} + static bool -rtems_rtl_elf_relocator (rtems_rtl_obj* obj, - int fd, - rtems_rtl_obj_sect* sect, - void* data) +rtems_rtl_elf_relocate_worker (rtems_rtl_obj* obj, + int fd, + rtems_rtl_obj_sect* sect, + rtems_rtl_elf_reloc_handler handler, + void* data) { rtems_rtl_obj_cache* symbols; rtems_rtl_obj_cache* strings; @@ -155,15 +314,16 @@ rtems_rtl_elf_relocator (rtems_rtl_obj* obj, for (reloc = 0; reloc < (sect->size / reloc_size); ++reloc) { - uint8_t relbuf[reloc_size]; - const Elf_Rela* rela = (const Elf_Rela*) relbuf; - const Elf_Rel* rel = (const Elf_Rel*) relbuf; - Elf_Sym sym; - const char* symname = NULL; - off_t off; - Elf_Word type; - Elf_Word symvalue = 0; - bool relocate; + uint8_t relbuf[reloc_size]; + const Elf_Rela* rela = (const Elf_Rela*) relbuf; + const Elf_Rel* rel = (const Elf_Rel*) relbuf; + rtems_rtl_obj_sym* symbol = NULL; + Elf_Sym sym; + const char* symname = NULL; + off_t off; + Elf_Word rel_type; + Elf_Word symvalue = 0; + bool resolved; off = obj->ooffset + sect->offset + (reloc * reloc_size); @@ -203,75 +363,26 @@ rtems_rtl_elf_relocator (rtems_rtl_obj* obj, /* * See if the record references an external symbol. If it does find the * symbol value. If the symbol cannot be found flag the object file as - * having unresolved externals and store the externals. The load of an + * having unresolved externals and store the external. The load of an * object after this one may provide the unresolved externals. */ if (is_rela) - type = ELF_R_TYPE(rela->r_info); + rel_type = ELF_R_TYPE(rela->r_info); else - type = ELF_R_TYPE(rel->r_info); - - relocate = true; - - if (rtems_rtl_elf_rel_resolve_sym (type)) - { - if (!rtems_rtl_elf_find_symbol (obj, &sym, symname, &symvalue)) - { - uint16_t flags = 0; - rtems_rtl_word rel_words[3]; - - relocate = false; - - if (is_rela) - { - flags = 1; - rel_words[REL_R_OFFSET] = rela->r_offset; - rel_words[REL_R_INFO] = rela->r_info; - rel_words[REL_R_ADDEND] = rela->r_addend; - } - else - { - rel_words[REL_R_OFFSET] = rel->r_offset; - rel_words[REL_R_INFO] = rel->r_info; - rel_words[REL_R_ADDEND] = 0; - } + rel_type = ELF_R_TYPE(rel->r_info); - if (!rtems_rtl_unresolved_add (obj, - flags, - symname, - targetsect->section, - rel_words)) - return false; + resolved = true; - ++obj->unresolved; - } - } + if (rtems_rtl_elf_rel_resolve_sym (rel_type)) + resolved = rtems_rtl_elf_find_symbol (obj, + &sym, symname, + &symbol, &symvalue); - if (relocate) - { - if (is_rela) - { - if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) - printf ("rtl: rela: sym:%s(%d)=%08jx type:%d off:%08jx addend:%d\n", - symname, (int) ELF_R_SYM (rela->r_info), - (uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info), - (uintmax_t) rela->r_offset, (int) rela->r_addend); - if (!rtems_rtl_elf_relocate_rela (obj, rela, targetsect, - symname, sym.st_info, symvalue)) - return false; - } - else - { - if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) - printf ("rtl: rel: sym:%s(%d)=%08jx type:%d off:%08jx\n", - symname, (int) ELF_R_SYM (rel->r_info), - (uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info), - (uintmax_t) rel->r_offset); - if (!rtems_rtl_elf_relocate_rel (obj, rel, targetsect, - symname, sym.st_info, symvalue)) - return false; - } - } + if (!handler (obj, + is_rela, relbuf, targetsect, + symbol, &sym, symname, symvalue, resolved, + data)) + return false; } /* @@ -283,6 +394,28 @@ rtems_rtl_elf_relocator (rtems_rtl_obj* obj, return true; } +static bool +rtems_rtl_elf_relocs_parser (rtems_rtl_obj* obj, + int fd, + rtems_rtl_obj_sect* sect, + void* data) +{ + bool r = rtems_rtl_elf_relocate_worker (obj, fd, sect, + rtems_rtl_elf_reloc_parser, data); + rtems_rtl_obj_update_flags (RTEMS_RTL_OBJ_RELOC_TAG, 0); + return r; +} + +static bool +rtems_rtl_elf_relocs_locator (rtems_rtl_obj* obj, + int fd, + rtems_rtl_obj_sect* sect, + void* data) +{ + return rtems_rtl_elf_relocate_worker (obj, fd, sect, + rtems_rtl_elf_reloc_relocator, data); +} + bool rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc* reloc, rtems_rtl_obj_sym* sym) @@ -290,8 +423,9 @@ rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc* reloc, rtems_rtl_obj_sect* sect; bool is_rela; Elf_Word symvalue; + rtems_rtl_obj* sobj; - is_rela =reloc->flags & 1; + is_rela = reloc->flags & 1; sect = rtems_rtl_obj_find_section_by_index (reloc->obj, reloc->sect); if (!sect) @@ -329,13 +463,20 @@ rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc* reloc, return false; } - if (reloc->obj->unresolved) + if (reloc->obj->unresolved > 0) { --reloc->obj->unresolved; - if (!reloc->obj->unresolved) + if (reloc->obj->unresolved == 0) reloc->obj->flags &= ~RTEMS_RTL_OBJ_UNRESOLVED; } + sobj = rtems_rtl_find_obj_with_symbol (sym); + if (sobj != NULL) + { + if (rtems_rtl_obj_add_dependent (reloc->obj, sobj)) + rtems_rtl_obj_inc_reference (sobj); + } + return true; } @@ -402,6 +543,24 @@ rtems_rtl_elf_common (rtems_rtl_obj* obj, } static bool +rtems_rtl_elf_dependents (rtems_rtl_obj* obj, rtems_rtl_elf_reloc_data* reloc) +{ + /* + * If there are dependencies and no unresolved externals allocate and size + * the dependency table to the number of dependent object files. If there are + * unresolved externals the number of dependencies is unknown at this point + * in time so use dynamic allocation to allocate the block size number of + * entries when the entries are added. + */ + if (reloc->dependents > 0 && reloc->unresolved == 0) + { + if (!rtems_rtl_obj_alloc_dependents (obj, reloc->dependents)) + return false; + } + return true; +} + +static bool rtems_rtl_elf_symbols (rtems_rtl_obj* obj, int fd, rtems_rtl_obj_sect* sect, @@ -1024,7 +1183,8 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd) { rtems_rtl_obj_cache* header; Elf_Ehdr ehdr; - rtems_rtl_elf_common_data common = { .size = 0, .alignment = 0 }; + rtems_rtl_elf_reloc_data relocs = { 0 }; + rtems_rtl_elf_common_data common = { 0 }; rtems_rtl_obj_caches (&header, NULL, NULL); @@ -1102,10 +1262,16 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd) if (!rtems_rtl_obj_load_sections (obj, fd, rtems_rtl_elf_loader, &ehdr)) return false; + if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_parser, &relocs)) + return false; + + if (!rtems_rtl_elf_dependents (obj, &relocs)) + return false; + if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols, &ehdr)) return false; - if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocator, &ehdr)) + if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_locator, &ehdr)) return false; rtems_rtl_obj_synchronize_cache (obj); diff --git a/cpukit/libdl/rtl-elf.h b/cpukit/libdl/rtl-elf.h index 5d560a0b34..1f5f82eb89 100644 --- a/cpukit/libdl/rtl-elf.h +++ b/cpukit/libdl/rtl-elf.h @@ -123,28 +123,6 @@ bool rtems_rtl_elf_relocate_rela (const rtems_rtl_obj* obj, const Elf_Word symvalue); /** - * Find the symbol. The symbol is passed as an ELF type symbol with the name - * and the value returned is the absolute address of the symbol. - * - * If the symbol type is STT_NOTYPE the symbol references a global symbol. The - * gobal symbol table is searched to find it and that value returned. If the - * symbol is local to the object module the section for the symbol is located - * and it's base added to the symbol's value giving an absolute location. - * - * @param obj The object the symbol is being resolved for. - * @param sym The ELF type symbol. - * @param symname The sym's name read from the symbol string table. - * @param value Return the value of the symbol. Only valid if the return value - * is true. - * @retval true The symbol resolved. - * @retval false The symbol could not be result. The RTL error is set. - */ -bool rtems_rtl_elf_find_symbol (rtems_rtl_obj* obj, - const Elf_Sym* sym, - const char* symname, - Elf_Word* value); - -/** * The ELF format check handler. * * @param obj The object being checked. diff --git a/cpukit/libdl/rtl-obj.c b/cpukit/libdl/rtl-obj.c index 7109b86fe8..0f58bf9bda 100644 --- a/cpukit/libdl/rtl-obj.c +++ b/cpukit/libdl/rtl-obj.c @@ -83,6 +83,7 @@ rtems_rtl_obj_alloc (void) * Initialise the chains. */ rtems_chain_initialize_empty (&obj->sections); + rtems_chain_initialize_empty (&obj->dependents); /* * No valid format. */ @@ -114,6 +115,8 @@ rtems_rtl_obj_free (rtems_rtl_obj* obj) rtems_chain_extract (&obj->link); rtems_rtl_alloc_module_del (&obj->text_base, &obj->const_base, &obj->eh_base, &obj->data_base, &obj->bss_base); + rtems_rtl_obj_erase_sections (obj); + rtems_rtl_obj_erase_dependents (obj); rtems_rtl_symbol_obj_erase (obj); rtems_rtl_obj_free_names (obj); if (obj->sec_num) @@ -550,6 +553,110 @@ rtems_rtl_obj_find_section_by_mask (const rtems_rtl_obj* obj, return match.sect; } +bool +rtems_rtl_obj_alloc_dependents (rtems_rtl_obj* obj, size_t dependents) +{ + rtems_rtl_obj_depends* depends; + size_t size; + + size = sizeof (rtems_rtl_obj_depends) + sizeof (rtems_rtl_obj*) * dependents; + + depends = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, + size, + true); + if (depends == NULL) + { + rtems_rtl_set_error (ENOMEM, "no memory for the dependency"); + } + else + { + depends->dependents = dependents; + rtems_chain_append (&obj->dependents, &depends->node); + } + + return depends != NULL; +} + +void +rtems_rtl_obj_erase_dependents (rtems_rtl_obj* obj) +{ + rtems_chain_node* node = rtems_chain_first (&obj->dependents); + while (!rtems_chain_is_tail (&obj->dependents, node)) + { + rtems_rtl_obj_depends* depends = (rtems_rtl_obj_depends*) node; + rtems_chain_node* next_node = rtems_chain_next (node); + rtems_chain_extract (node); + rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, depends); + node = next_node; + } +} + +bool +rtems_rtl_obj_add_dependent (rtems_rtl_obj* obj, rtems_rtl_obj* dependent) +{ + rtems_rtl_obj** free_slot; + rtems_chain_node* node; + if (obj == dependent || dependent == rtems_rtl_baseimage ()) + return false; + free_slot = NULL; + node = rtems_chain_first (&obj->dependents); + while (!rtems_chain_is_tail (&obj->dependents, node)) + { + rtems_rtl_obj_depends* depends = (rtems_rtl_obj_depends*) node; + size_t d; + for (d = 0; d < depends->dependents; ++d) + { + if (free_slot == NULL && depends->depends[d] == NULL) + free_slot = &(depends->depends[d]); + if (depends->depends[d] == dependent) + return false; + } + node = rtems_chain_next (node); + } + if (free_slot == NULL) + { + if (rtems_rtl_obj_alloc_dependents (obj, + RTEMS_RTL_DEPENDENCY_BLOCK_SIZE)) + { + rtems_rtl_obj_depends* depends; + node = rtems_chain_last (&obj->dependents); + depends = (rtems_rtl_obj_depends*) node; + free_slot = &(depends->depends[0]); + if (*free_slot != NULL) + { + rtems_rtl_set_error (EINVAL, "new dependency node not empty"); + free_slot = NULL; + } + } + } + if (free_slot != NULL) + *free_slot = dependent; + return free_slot != NULL; +} + +bool +rtems_rtl_obj_iterate_dependents (rtems_rtl_obj* obj, + rtems_rtl_obj_depends_iterator iterator, + void* data) +{ + rtems_chain_node* node = rtems_chain_first (&obj->dependents); + while (!rtems_chain_is_tail (&obj->dependents, node)) + { + rtems_rtl_obj_depends* depends = (rtems_rtl_obj_depends*) node; + size_t d; + for (d = 0; d < depends->dependents; ++d) + { + if (depends->depends[d]) + { + if (iterator (obj, depends->depends[d], data)) + return true; + } + } + node = rtems_chain_next (node); + } + return false; +} + size_t rtems_rtl_obj_text_size (const rtems_rtl_obj* obj) { @@ -1220,10 +1327,42 @@ static bool rtems_rtl_obj_file_unload (rtems_rtl_obj* obj) { if (obj->format >= 0 && obj->format < RTEMS_RTL_LOADERS) - return loaders[obj->format].unload (obj); + { + rtems_chain_node* node; + + if (!loaders[obj->format].unload (obj)) + return false; + + node = rtems_chain_first (&obj->dependents); + while (!rtems_chain_is_tail (&obj->dependents, node)) + { + rtems_rtl_obj_depends* depends = (rtems_rtl_obj_depends*) node; + size_t d; + for (d = 0; d < depends->dependents; ++d) + { + if (depends->depends[d] != NULL) + rtems_rtl_obj_dec_reference (depends->depends[d]); + } + node = rtems_chain_next (node); + } + } + return false; } +void +rtems_rtl_obj_inc_reference (rtems_rtl_obj* obj) +{ + ++obj->refs; +} + +void +rtems_rtl_obj_dec_reference (rtems_rtl_obj* obj) +{ + if (obj->refs) + --obj->refs; +} + bool rtems_rtl_obj_load (rtems_rtl_obj* obj) { diff --git a/cpukit/libdl/rtl-shell.c b/cpukit/libdl/rtl-shell.c index 5c144977a0..f3471d8d8e 100644 --- a/cpukit/libdl/rtl-shell.c +++ b/cpukit/libdl/rtl-shell.c @@ -117,13 +117,14 @@ rtems_rtl_shell_status (rtems_rtl_data* rtl, int argc, char *argv[]) */ typedef struct { - rtems_rtl_data* rtl; /**< The RTL data. */ - int indent; /**< Spaces to indent. */ - bool oname; /**< Print object names. */ - bool names; /**< Print details of all names. */ - bool memory_map; /**< Print the memory map. */ - bool symbols; /**< Print the global symbols. */ - bool base; /**< Include the base object file. */ + rtems_rtl_data* rtl; /**< The RTL data. */ + int indent; /**< Spaces to indent. */ + bool oname; /**< Print object names. */ + bool names; /**< Print details of all names. */ + bool memory_map; /**< Print the memory map. */ + bool symbols; /**< Print the global symbols. */ + bool dependencies; /**< Print any dependencies. */ + bool base; /**< Include the base object file. */ } rtems_rtl_obj_print; /** @@ -169,6 +170,29 @@ rtems_rtl_symbols_arg (int argc, char *argv[]) } /** + * Dependenncies printer. + */ +typedef struct +{ + bool first; /**< Is this the first line printed. */ + size_t indent; /**< The indent. */ +} rtems_rtl_dep_data; + +static bool +rtems_rtl_dependencies (rtems_rtl_obj* obj, + rtems_rtl_obj* dependent, + void* data) +{ + rtems_rtl_dep_data* dd = (rtems_rtl_dep_data*) data; + if (!dd->first) + printf ("\n%-*c: ", dd->indent, ' '); + else + dd->first = false; + printf ("%s", dependent->oname); + return false; +} + +/** * Object printer. */ static bool @@ -214,7 +238,9 @@ rtems_rtl_obj_printer (rtems_rtl_obj_print* print, rtems_rtl_obj* obj) printf ("%-*cbss base : %p (%zi)\n", print->indent, ' ', obj->bss_base, obj->bss_size); } - printf ("%-*cunresolved : %" PRIu32 "\n", print->indent, ' ', obj->unresolved); + printf ("%-*cunresolved : %zu\n", print->indent, ' ', obj->unresolved); + printf ("%-*cusers : %zu\n", print->indent, ' ', obj->users); + printf ("%-*creferences : %zu\n", print->indent, ' ', obj->refs); printf ("%-*csymbols : %zi\n", print->indent, ' ', obj->global_syms); printf ("%-*csymbol memory : %zi\n", print->indent, ' ', obj->global_size); if (print->symbols) @@ -231,6 +257,16 @@ rtems_rtl_obj_printer (rtems_rtl_obj_print* print, rtems_rtl_obj* obj) printf ("%-*c%-*s = %p\n", print->indent + 2, ' ', max_len, obj->global_table[s].name, obj->global_table[s].value); } + if (print->dependencies) + { + rtems_rtl_dep_data dd = { + .first = true, + .indent = strlen ("dependencies :") + print->indent + }; + printf ("%-*cdependencies : ", print->indent, ' '); + rtems_rtl_obj_iterate_dependents (obj, rtems_rtl_dependencies, &dd); + printf ("\n"); + } printf ("\n"); return true; } @@ -269,6 +305,7 @@ rtems_rtl_shell_list (rtems_rtl_data* rtl, int argc, char *argv[]) print.names = true; print.memory_map = true; print.symbols = rtems_rtl_symbols_arg (argc, argv); + print.dependencies = true; print.base = false; rtems_rtl_chain_iterate (&rtl->objects, rtems_rtl_obj_print_iterator, @@ -286,6 +323,7 @@ rtems_rtl_shell_sym (rtems_rtl_data* rtl, int argc, char *argv[]) print.names = false; print.memory_map = false; print.symbols = true; + print.dependencies = false; print.base = rtems_rtl_base_arg (argc, argv); rtems_rtl_chain_iterate (&rtl->objects, rtems_rtl_obj_print_iterator, diff --git a/cpukit/libdl/rtl-unresolved.c b/cpukit/libdl/rtl-unresolved.c index 4c0f6b3bf1..4992c3bb4a 100644 --- a/cpukit/libdl/rtl-unresolved.c +++ b/cpukit/libdl/rtl-unresolved.c @@ -171,7 +171,7 @@ rtems_rtl_unresolved_resolve_reloc (rtems_rtl_unresolv_rec* rec, rtems_rtl_unresolved_reloc_data* rd; rd = (rtems_rtl_unresolved_reloc_data*) data; - if (rec->rec.reloc.name == rd->name) + if (rec->rec.reloc.name == rd->name && rec->rec.reloc.obj != NULL) { if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED)) printf ("rtl: unresolv: resolve reloc: %s\n", rd->name_rec->rec.name.name); @@ -185,7 +185,7 @@ rtems_rtl_unresolved_resolve_reloc (rtems_rtl_unresolv_rec* rec, * names with a reference count of 0. */ rec->rec.reloc.obj = NULL; - if (rd->name_rec && rd->name_rec->rec.name.refs) + if (rd->name_rec != NULL && rd->name_rec->rec.name.refs > 0) --rd->name_rec->rec.name.refs; } } diff --git a/cpukit/libdl/rtl.c b/cpukit/libdl/rtl.c index 628fc771bc..fdf4c1229f 100644 --- a/cpukit/libdl/rtl.c +++ b/cpukit/libdl/rtl.c @@ -216,6 +216,11 @@ rtems_rtl_data_init (void) */ rtl->base->oname = rtems_rtl_strdup ("rtems-kernel"); + /* + * Lock the base image and flag it as the base image. + */ + rtl->base->flags |= RTEMS_RTL_OBJ_LOCKED | RTEMS_RTL_OBJ_BASE; + rtems_chain_append (&rtl->objects, &rtl->base->link); } @@ -312,6 +317,21 @@ rtems_rtl_obj_decompress (rtems_rtl_obj_comp** decomp, } } +void +rtems_rtl_obj_update_flags (uint32_t clear, uint32_t set) +{ + rtems_chain_node* node = rtems_chain_first (&rtl->objects); + while (!rtems_chain_is_tail (&rtl->objects, node)) + { + rtems_rtl_obj* obj = (rtems_rtl_obj*) node; + if (clear != 0) + obj->flags &= ~clear; + if (set != 0) + obj->flags |= set; + node = rtems_chain_next (node); + } +} + rtems_rtl_data* rtems_rtl_lock (void) { @@ -386,6 +406,21 @@ rtems_rtl_find_obj (const char* name) } rtems_rtl_obj* +rtems_rtl_find_obj_with_symbol (const rtems_rtl_obj_sym* sym) +{ + rtems_chain_node* node = rtems_chain_first (&rtl->objects); + while (!rtems_chain_is_tail (&rtl->objects, node)) + { + rtems_rtl_obj* obj = (rtems_rtl_obj*) node; + if (sym >= obj->global_table && + sym < (obj->global_table + obj->global_syms)) + return obj; + node = rtems_chain_next (node); + } + return NULL; +} + +rtems_rtl_obj* rtems_rtl_load_object (const char* name, int mode) { rtems_rtl_obj* obj; @@ -489,6 +524,11 @@ rtems_rtl_unload_object (rtems_rtl_obj* obj) if (obj->users == 0) { + if (obj->refs != 0) + { + rtems_rtl_set_error (EBUSY, "object file referenced"); + return false; + } obj->flags |= RTEMS_RTL_OBJ_LOCKED; rtems_rtl_unlock (); rtems_rtl_obj_run_dtors (obj); @@ -618,5 +658,11 @@ rtems_rtl_base_sym_global_add (const unsigned char* esyms, rtems_rtl_obj* rtems_rtl_baseimage (void) { - return NULL; + rtems_rtl_obj* base = NULL; + if (rtems_rtl_lock ()) + { + base = rtl->base; + rtems_rtl_unlock (); + } + return base; } |