From: Chris Johns <chr...@rtems.org> - Add resize to the allocator interface
- Rework the trampoline variables in the obj struct to make better sense of what is happening Closes #4944 --- cpukit/include/rtems/rtl/rtl-allocator.h | 46 +++++- cpukit/include/rtems/rtl/rtl-obj.h | 199 ++++++++++++---------- cpukit/libdl/rtl-alloc-heap.c | 5 +- cpukit/libdl/rtl-allocator.c | 135 ++++++++++++--- cpukit/libdl/rtl-elf.c | 35 ++-- cpukit/libdl/rtl-mdreloc-aarch64.c | 15 +- cpukit/libdl/rtl-mdreloc-arm.c | 6 + cpukit/libdl/rtl-mdreloc-bfin.c | 6 + cpukit/libdl/rtl-mdreloc-i386.c | 6 + cpukit/libdl/rtl-mdreloc-lm32.c | 6 + cpukit/libdl/rtl-mdreloc-m68k.c | 6 + cpukit/libdl/rtl-mdreloc-mips.c | 6 + cpukit/libdl/rtl-mdreloc-moxie.c | 6 + cpukit/libdl/rtl-mdreloc-powerpc.c | 6 + cpukit/libdl/rtl-mdreloc-riscv.c | 6 + cpukit/libdl/rtl-mdreloc-sparc.c | 6 + cpukit/libdl/rtl-mdreloc-v850.c | 6 + cpukit/libdl/rtl-obj.c | 202 +++++++++++++++-------- cpukit/libdl/rtl-shell.c | 2 +- testsuites/libtests/dl09/dl-load.c | 16 +- 20 files changed, 525 insertions(+), 196 deletions(-) diff --git a/cpukit/include/rtems/rtl/rtl-allocator.h b/cpukit/include/rtems/rtl/rtl-allocator.h index 8ffaf58c3c..7d291c65f4 100644 --- a/cpukit/include/rtems/rtl/rtl-allocator.h +++ b/cpukit/include/rtems/rtl/rtl-allocator.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-2-Clause */ /* - * COPYRIGHT (c) 2012, 2018 Chris Johns <chr...@rtems.org> + * COPYRIGHT (c) 2012, 2018, 2023 Chris Johns <chr...@rtems.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -69,6 +69,7 @@ typedef enum rtems_rtl_alloc_tags rtems_rtl_alloc_tag; enum rtems_rtl_alloc_cmd { RTEMS_RTL_ALLOC_NEW, /**< Allocate new memory. */ RTEMS_RTL_ALLOC_DEL, /**< Delete allocated memory. */ + RTEMS_RTL_ALLOC_RESIZE, /**< Resize allocated memory. */ RTEMS_RTL_ALLOC_LOCK, /**< Lock the allocator. */ RTEMS_RTL_ALLOC_UNLOCK, /**< Unlock the allocator. */ RTEMS_RTL_ALLOC_WR_ENABLE, /**< Enable writes to the memory. */ @@ -142,6 +143,25 @@ void* rtems_rtl_alloc_new (rtems_rtl_alloc_tag tag, size_t size, bool zero); */ void rtems_rtl_alloc_del (rtems_rtl_alloc_tag tag, void* address); +/** + * The Runtime Loader allocator resize resizes allocated memory. + * + * This call resizes a previously allocated block of memory. If the + * provided address cannot be resized it is deleted and a new block is + * allocated and the contents of the existing memory is copied. + * + * + * @param tag The type of allocation request. + * @param address The memory address to resize. A NULL is ignored. + * @param size The size of the allocation. + * @param zero If true the memory is cleared. + * @return void* The memory address or NULL is not memory available. + */ +void* rtems_rtl_alloc_resize (rtems_rtl_alloc_tag tag, + void* address, + size_t size, + bool zero); + /** * The Runtime Loader allocator lock. An allocator that depends on a * separate allocation process, for example the heap, may need to be @@ -266,6 +286,30 @@ bool rtems_rtl_alloc_module_new (void** text_base, size_t text_size, void** data_base, size_t data_size, void** bss_base, size_t bss_size); +/** + * Resize the allocated memory for a module given the new size of the text, + * const, data and bss sections. If any part of the allocation fails the + * allocated is deleted. + * + * @param text_base Pointer to the text base pointer. + * @param text_size The size of the read/exec section. + * @param const_base Pointer to the const base pointer. + * @param const_size The size of the read only section. + * @param eh_base Pointer to the eh base pointer. + * @param eh_size The size of the eh section. + * @param data_base Pointer to the data base pointer. + * @param data_size The size of the read/write secton. + * @param bss_base Pointer to the bss base pointer. + * @param bss_size The size of the read/write. + * @retval true The memory has been allocated. + * @retval false The allocation of memory has failed. + */ +bool rtems_rtl_alloc_module_resize (void** text_base, size_t text_size, + void** const_base, size_t const_size, + void** eh_base, size_t eh_size, + void** data_base, size_t data_size, + void** bss_base, size_t bss_size); + /** * Free the memory allocated to a module. * diff --git a/cpukit/include/rtems/rtl/rtl-obj.h b/cpukit/include/rtems/rtl/rtl-obj.h index 6b47eb1205..3523958bfd 100644 --- a/cpukit/include/rtems/rtl/rtl-obj.h +++ b/cpukit/include/rtems/rtl/rtl-obj.h @@ -198,65 +198,66 @@ typedef bool (*rtems_rtl_obj_depends_iterator) (rtems_rtl_obj* obj, */ struct rtems_rtl_obj { - rtems_chain_node link; /**< The node's link in the chain. */ - uint32_t flags; /**< The status of the object file. */ - size_t users; /**< Users of this object file, number of loads. */ - size_t refs; /**< References to the object file. */ - int format; /**< The format of the object file. */ - const char* fname; /**< The file name for the object. */ - const char* oname; /**< The object file name. Can be - * relative. */ - const char* aname; /**< The archive name containing the - * object. NULL means the object is not - * in a lib */ - off_t ooffset; /**< The object offset in the archive. */ - size_t fsize; /**< Size of the object file. */ - rtems_chain_control sections; /**< The sections of interest in the object - * file. */ - rtems_chain_control dependents; /**< The dependent object files. */ - rtems_rtl_obj_sym* local_table; /**< Local symbol table. */ - size_t local_syms; /**< Local symbol count. */ - size_t local_size; /**< Local symbol memory usage. */ - rtems_rtl_obj_sym* global_table; /**< Global symbol table. */ - size_t global_syms; /**< Global symbol count. */ - size_t global_size; /**< Global symbol memory usage. */ - size_t unresolved; /**< The number of unresolved relocations. */ - void* text_base; /**< The base address of the text section - * in memory. */ - size_t text_size; /**< The size of the text section. */ - void* const_base; /**< The base address of the const section - * in memory. */ - size_t const_size; /**< The size of the const section. */ - void* eh_base; /**< The base address of the eh section in - * memory. */ - size_t eh_size; /**< The size of the eh section. */ - void* data_base; /**< The base address of the data section - * in memory. */ - size_t data_size; /**< The size of the data section. */ - void* bss_base; /**< The base address of the bss section in - * memory. */ - size_t bss_size; /**< The size of the bss section. */ - size_t exec_size; /**< The amount of executable memory - * allocated */ - void* entry; /**< The entry point of the module. */ - uint32_t checksum; /**< The checksum of the text sections. A - * zero means do not checksum. */ - uint32_t* sec_num; /**< The sec nums of each obj. */ - uint32_t obj_num; /**< The count of elf files in an rtl - * obj. */ - void* trampoline; /**< Trampoline memory. Used for fixups or - * veneers */ - size_t tramp_size; /**< Size of a tramopline slot. */ - size_t tramps_size; /**< Size of the trampoline memory. */ - void* tramp_brk; /**< Trampoline memory allocator. MD - * relocators can take memory from the - * break up to the size. */ - size_t tramp_relocs; /**< Number of slots reserved for - * relocs. The remainder are for - * unresolved symbols. */ - struct link_map* linkmap; /**< For GDB. */ - void* loader; /**< The file details specific to a - * loader. */ + rtems_chain_node link; /**< The node's link in the chain. */ + uint32_t flags; /**< The status of the object file. */ + size_t users; /**< Users of this object file, number of loads. */ + size_t refs; /**< References to the object file. */ + int format; /**< The format of the object file. */ + const char* fname; /**< The file name for the object. */ + const char* oname; /**< The object file name. Can be + * relative. */ + const char* aname; /**< The archive name containing the + * object. NULL means the object is not + * in a lib */ + off_t ooffset; /**< The object offset in the archive. */ + size_t fsize; /**< Size of the object file. */ + rtems_chain_control sections; /**< The sections of interest in the object + * file. */ + rtems_chain_control dependents; /**< The dependent object files. */ + rtems_rtl_obj_sym* local_table; /**< Local symbol table. */ + size_t local_syms; /**< Local symbol count. */ + size_t local_size; /**< Local symbol memory usage. */ + rtems_rtl_obj_sym* global_table; /**< Global symbol table. */ + size_t global_syms; /**< Global symbol count. */ + size_t global_size; /**< Global symbol memory usage. */ + size_t unresolved; /**< The number of unresolved relocations. */ + void* text_base; /**< The base address of the text section + * in memory. */ + size_t text_size; /**< The size of the text section. */ + void* const_base; /**< The base address of the const section + * in memory. */ + size_t const_size; /**< The size of the const section. */ + void* eh_base; /**< The base address of the eh section in + * memory. */ + size_t eh_size; /**< The size of the eh section. */ + void* data_base; /**< The base address of the data section + * in memory. */ + size_t data_size; /**< The size of the data section. */ + void* bss_base; /**< The base address of the bss section in + * memory. */ + size_t bss_size; /**< The size of the bss section. */ + size_t exec_size; /**< The amount of executable memory + * allocated */ + void* entry; /**< The entry point of the module. */ + uint32_t checksum; /**< The checksum of the text sections. A + * zero means do not checksum. */ + uint32_t* sec_num; /**< The sec nums of each obj. */ + uint32_t obj_num; /**< The count of elf files in an rtl + * obj. */ + void* tramp_base; /**< Trampoline memory. Used for fixups or + * veneers */ + size_t tramp_size; /**< Size of a trampoline memory. */ + size_t tramp_slots; /**< The number of tampoline slots. */ + size_t tramp_slot_size; /**< The number of tampoline slots. */ + void* tramp_brk; /**< Trampoline memory allocator. MD + * relocators can take memory from the + * break up to the size. */ + size_t tramp_relocs; /**< Number of slots reserved for + * relocs. The remainder are for + * unresolved symbols. */ + struct link_map* linkmap; /**< For GDB. */ + void* loader; /**< The file details specific to a + * loader. */ }; /** @@ -386,6 +387,17 @@ static inline bool rtems_rtl_obj_has_symbol (const rtems_rtl_obj* obj, sym < (obj->global_table + obj->global_syms)); } +/** + * Does the object file have any trampolines? + * + * @param obj The object file's descriptor to check for available space. + * @retval bool Returns @true if the object file has trampolines + */ +static inline size_t rtems_rtl_obj_has_trampolines (const rtems_rtl_obj* obj) +{ + return obj->tramp_slot_size != 0 && obj->tramp_slots != 0; +} + /** * Is there space in the trampoline memory for a trapoline. * @@ -395,7 +407,7 @@ static inline bool rtems_rtl_obj_has_symbol (const rtems_rtl_obj* obj, */ static inline size_t rtems_rtl_obj_tramp_avail_space (const rtems_rtl_obj* obj) { - return (char*) obj->tramp_brk - (char*) obj->trampoline; + return (char*) obj->tramp_brk - (char*) obj->tramp_base; } /** @@ -408,8 +420,8 @@ static inline size_t rtems_rtl_obj_tramp_avail_space (const rtems_rtl_obj* obj) static inline bool rtems_rtl_obj_has_tramp_space (const rtems_rtl_obj* obj, const size_t size) { - return (obj->trampoline != NULL && - (rtems_rtl_obj_tramp_avail_space (obj) + size) <= obj->tramps_size); + return (obj->tramp_base != NULL && + (rtems_rtl_obj_tramp_avail_space (obj) + size) <= obj->tramp_size); } /** @@ -420,20 +432,19 @@ static inline bool rtems_rtl_obj_has_tramp_space (const rtems_rtl_obj* obj, */ static inline size_t rtems_rtl_obj_trampoline_slots (const rtems_rtl_obj* obj) { - return obj->trampoline == NULL || obj->tramp_size == 0 ? - 0 : obj->tramps_size / obj->tramp_size; + return obj->tramp_slots; } /** - * Number of trampolines. + * Number of trampoline slot available. * * @param obj The object file's descriptor. - * @retval size_t The number of trampolines. + * @retval size_t The number of trampoline slots available. */ static inline size_t rtems_rtl_obj_trampolines (const rtems_rtl_obj* obj) { - return obj->trampoline == NULL || obj->tramp_size == 0 ? - 0 : rtems_rtl_obj_tramp_avail_space (obj) / obj->tramp_size; + return obj->tramp_base == NULL || obj->tramp_slots == 0 ? + 0 : rtems_rtl_obj_tramp_avail_space (obj) / obj->tramp_slot_size; } /** @@ -571,22 +582,6 @@ rtems_rtl_obj_sect* rtems_rtl_obj_find_section_by_mask (const rtems_rtl_obj* obj int index, uint32_t mask); -/** - * Allocate a table for trampoline fixup calls. - * - * @param obj The object file's descriptor. - * @retval true The table was allocated. - * @retval false The alloction failed. - */ -bool rtems_rtl_obj_alloc_trampoline (rtems_rtl_obj* obj); - -/** - * Erase the object file descriptor's trampoline table.. - * - * @param obj The object file's descriptor. - */ -void rtems_rtl_obj_erase_trampoline (rtems_rtl_obj* obj); - /** * Allocate a table for dependent objects. * @@ -749,6 +744,24 @@ size_t rtems_rtl_obj_bss_size (const rtems_rtl_obj* obj); */ uint32_t rtems_rtl_obj_bss_alignment (const rtems_rtl_obj* obj); +/** + * The trampoline size. + * + * @param obj The object file's descriptor. + * @return size_t The size of the trampoline memory of the object file. + */ +size_t rtems_rtl_obj_tramp_size (const rtems_rtl_obj* obj); + +/** + * The trampolinme alignment for the architecture. + * + * This is implemented and set in the architecture backend. + * + * @param obj The object file's descriptor. + * @return uint32_t The alignment. Can be 0 or 1 for not aligned or the alignment. + */ +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj); + /** * Relocate the object file. The object file's section are parsed for any * relocation type sections. @@ -810,11 +823,19 @@ bool rtems_rtl_obj_load_symbols (rtems_rtl_obj* obj, * @retval true The object has been sucessfully loaded. * @retval false The load failed. The RTL error has been set. */ -bool -rtems_rtl_obj_alloc_sections (rtems_rtl_obj* obj, - int fd, - rtems_rtl_obj_sect_handler handler, - void* data); +bool rtems_rtl_obj_alloc_sections (rtems_rtl_obj* obj, + int fd, + rtems_rtl_obj_sect_handler handler, + void* data); + +/** + * Resize the sections. + * + * @param obj The object file's descriptor. + * @retval true The object has been sucessfully loaded. + * @retval false The load failed. The RTL error has been set. + */ +bool rtems_rtl_obj_resize_sections (rtems_rtl_obj* obj); /** * Load the sections that have been allocated memory in the target. The bss diff --git a/cpukit/libdl/rtl-alloc-heap.c b/cpukit/libdl/rtl-alloc-heap.c index 10150a0753..f90233874e 100644 --- a/cpukit/libdl/rtl-alloc-heap.c +++ b/cpukit/libdl/rtl-alloc-heap.c @@ -9,7 +9,7 @@ */ /* - * COPYRIGHT (c) 2012 Chris Johns <chr...@rtems.org> + * COPYRIGHT (c) 2012,2023 Chris Johns <chr...@rtems.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -54,6 +54,9 @@ rtems_rtl_alloc_heap (rtems_rtl_alloc_cmd cmd, free (*address); *address = NULL; break; + case RTEMS_RTL_ALLOC_RESIZE: + *address = realloc (*address, size); + break; case RTEMS_RTL_ALLOC_LOCK: _RTEMS_Lock_allocator(); break; diff --git a/cpukit/libdl/rtl-allocator.c b/cpukit/libdl/rtl-allocator.c index f09690d71a..7503183367 100644 --- a/cpukit/libdl/rtl-allocator.c +++ b/cpukit/libdl/rtl-allocator.c @@ -9,7 +9,7 @@ */ /* - * COPYRIGHT (c) 2012, 2018 Chris Johns <chr...@rtems.org> + * COPYRIGHT (c) 2012, 2018, 2023 Chris Johns <chr...@rtems.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -110,6 +110,39 @@ rtems_rtl_alloc_del (rtems_rtl_alloc_tag tag, void* address) rtems_rtl_unlock (); } +void* rtems_rtl_alloc_resize (rtems_rtl_alloc_tag tag, + void* address, + size_t size, + bool zero) +{ + rtems_rtl_data* rtl = rtems_rtl_lock (); + const void* prev_address = address; + + /* + * Resize memory of an existing allocation. The address field is set + * by the allocator and may change. + */ + if (rtl != NULL) + rtl->allocator.allocator (RTEMS_RTL_ALLOC_RESIZE, tag, &address, size); + + rtems_rtl_unlock (); + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR)) + printf ("rtl: alloc: resize: %s%s prev-addr=%p addr=%p size=%zu\n", + rtems_rtl_trace_tag_label (tag), prev_address == address ? "" : " MOVED", + prev_address, address, size); + + /* + * Only zero the memory if asked to and the resize was successful. We + * cannot clear the resized area if bigger than the previouis allocation + * because we do not have the original size. + */ + if (address != NULL && zero) + memset (address, 0, size); + + return address; +} + void rtems_rtl_alloc_wr_enable (rtems_rtl_alloc_tag tag, void* address) { @@ -277,21 +310,23 @@ rtems_rtl_alloc_module_new (void** text_base, size_t text_size, { *text_base = *const_base = *data_base = *bss_base = NULL; - if (text_size) + if (data_size != 0) { - *text_base = rtems_rtl_alloc_new (rtems_rtl_alloc_text_tag (), - text_size, false); - if (!*text_base) + *data_base = rtems_rtl_alloc_new (rtems_rtl_alloc_data_tag (), + data_size, false); + if (*data_base == NULL) { + rtems_rtl_alloc_module_del (text_base, const_base, eh_base, + data_base, bss_base); return false; } } - if (const_size) + if (bss_size != 0) { - *const_base = rtems_rtl_alloc_new (rtems_rtl_alloc_const_tag (), - const_size, false); - if (!*const_base) + *bss_base = rtems_rtl_alloc_new (rtems_rtl_alloc_bss_tag (), + bss_size, false); + if (*bss_base == NULL) { rtems_rtl_alloc_module_del (text_base, const_base, eh_base, data_base, bss_base); @@ -299,11 +334,11 @@ rtems_rtl_alloc_module_new (void** text_base, size_t text_size, } } - if (eh_size) + if (eh_size != 0) { *eh_base = rtems_rtl_alloc_new (rtems_rtl_alloc_eh_tag (), eh_size, false); - if (!*eh_base) + if (*eh_base == NULL) { rtems_rtl_alloc_module_del (text_base, const_base, eh_base, data_base, bss_base); @@ -311,11 +346,11 @@ rtems_rtl_alloc_module_new (void** text_base, size_t text_size, } } - if (data_size) + if (const_size != 0) { - *data_base = rtems_rtl_alloc_new (rtems_rtl_alloc_data_tag (), - data_size, false); - if (!*data_base) + *const_base = rtems_rtl_alloc_new (rtems_rtl_alloc_const_tag (), + const_size, false); + if (*const_base == NULL) { rtems_rtl_alloc_module_del (text_base, const_base, eh_base, data_base, bss_base); @@ -323,14 +358,72 @@ rtems_rtl_alloc_module_new (void** text_base, size_t text_size, } } - if (bss_size) + if (text_size != 0) { - *bss_base = rtems_rtl_alloc_new (rtems_rtl_alloc_bss_tag (), - bss_size, false); - if (!*bss_base) + *text_base = rtems_rtl_alloc_new (rtems_rtl_alloc_text_tag (), + text_size, false); + if (*text_base == NULL) + { + return false; + } + } + + return true; +} + +bool +rtems_rtl_alloc_module_resize (void** text_base, size_t text_size, + void** const_base, size_t const_size, + void** eh_base, size_t eh_size, + void** data_base, size_t data_size, + void** bss_base, size_t bss_size) +{ + if (data_size != 0) + { + *data_base = rtems_rtl_alloc_resize (rtems_rtl_alloc_data_tag (), + *data_base, data_size, false); + if (*data_base == NULL) + { + return false; + } + } + + if (bss_size != 0) + { + *bss_base = rtems_rtl_alloc_resize (rtems_rtl_alloc_bss_tag (), + *bss_base, bss_size, false); + if (*bss_base == NULL) + { + return false; + } + } + + if (eh_size != 0) + { + *eh_base = rtems_rtl_alloc_resize (rtems_rtl_alloc_eh_tag (), + *eh_base, eh_size, false); + if (*eh_base == NULL) + { + return false; + } + } + + if (const_size != 0) + { + *const_base = rtems_rtl_alloc_resize (rtems_rtl_alloc_const_tag (), + *const_base, const_size, false); + if (*const_base == NULL) + { + return false; + } + } + + if (text_size != 0) + { + *text_base = rtems_rtl_alloc_resize (rtems_rtl_alloc_text_tag (), + *text_base, text_size, false); + if (*text_base == NULL) { - rtems_rtl_alloc_module_del (text_base, const_base, eh_base, - data_base, bss_base); return false; } } diff --git a/cpukit/libdl/rtl-elf.c b/cpukit/libdl/rtl-elf.c index b46d2ac3a0..dd6d8617bb 100644 --- a/cpukit/libdl/rtl-elf.c +++ b/cpukit/libdl/rtl-elf.c @@ -805,7 +805,7 @@ rtems_rtl_elf_tramp_resolve_reloc (rtems_rtl_unresolv_rec* rec, } if (unresolved || rs == rtems_rtl_elf_rel_tramp_add) - tramp->obj->tramps_size += tramp->obj->tramp_size; + ++tramp->obj->tramp_slots; if (rs == rtems_rtl_elf_rel_failure) { *failure = true; @@ -818,7 +818,7 @@ rtems_rtl_elf_tramp_resolve_reloc (rtems_rtl_unresolv_rec* rec, } static bool -rtems_rtl_elf_alloc_trampoline (rtems_rtl_obj* obj, size_t unresolved) +rtems_rtl_elf_find_trampolines (rtems_rtl_obj* obj, size_t unresolved) { rtems_rtl_tramp_data td = { 0 }; td.obj = obj; @@ -829,21 +829,20 @@ rtems_rtl_elf_alloc_trampoline (rtems_rtl_obj* obj, size_t unresolved) if (td.failure) return false; rtems_rtl_trampoline_remove (obj); - obj->tramp_relocs = obj->tramp_size == 0 ? 0 : obj->tramps_size / obj->tramp_size; + obj->tramp_relocs = obj->tramp_slots; if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) - printf ("rtl: tramp:elf: tramps: %zu count:%zu total:%zu\n", + printf ("rtl: tramp:elf: tramps: slots:%zu count:%zu total:%zu\n", obj->tramp_relocs, td.count, td.total); /* * Add on enough space to handle the unresolved externals that need to be * resolved at some point in time. They could all require fixups and * trampolines. */ - obj->tramps_size += obj->tramp_size * unresolved; + obj->tramp_slots += unresolved; if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) - printf ("rtl: tramp:elf: slots: %zu (%zu)\n", - obj->tramp_size == 0 ? 0 : obj->tramps_size / obj->tramp_size, - obj->tramps_size); - return rtems_rtl_obj_alloc_trampoline (obj); + printf ("rtl: tramp:elf: slots:%zu (%zu)\n", + obj->tramp_slots, obj->tramp_slots * obj->tramp_slot_size); + return true; } static bool @@ -1730,7 +1729,7 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd) /* * Set the format's architecture's maximum tramp size. */ - obj->tramp_size = rtems_rtl_elf_relocate_tramp_max_size (); + obj->tramp_slot_size = rtems_rtl_elf_relocate_tramp_max_size (); /* * Parse the section information first so we have the memory map of the object @@ -1779,13 +1778,23 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd) if (!rtems_rtl_obj_alloc_sections (obj, fd, rtems_rtl_elf_arch_alloc, &ehdr)) return false; - if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols_locate, &ehdr)) + if (!rtems_rtl_elf_dependents (obj, &relocs)) return false; - if (!rtems_rtl_elf_dependents (obj, &relocs)) + if (!rtems_rtl_elf_find_trampolines (obj, relocs.unresolved)) return false; - if (!rtems_rtl_elf_alloc_trampoline (obj, relocs.unresolved)) + /* + * Resize the sections to allocate the trampoline memory as part of + * the text section. + */ + if (rtems_rtl_obj_has_trampolines (obj)) + { + if (!rtems_rtl_obj_resize_sections (obj)) + return false; + } + + if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols_locate, &ehdr)) return false; /* diff --git a/cpukit/libdl/rtl-mdreloc-aarch64.c b/cpukit/libdl/rtl-mdreloc-aarch64.c index e6c6ba3627..792dc91b2e 100644 --- a/cpukit/libdl/rtl-mdreloc-aarch64.c +++ b/cpukit/libdl/rtl-mdreloc-aarch64.c @@ -163,6 +163,12 @@ get_veneer_size(int type) return 16; } +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj) +{ + (void) obj; + return sizeof(uint64_t); +} + size_t rtems_rtl_elf_relocate_tramp_max_size (void) { @@ -386,6 +392,7 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj, target -= (uintptr_t)where >> 12; if (checkoverflow(target, 21, raddr, " x 4k", where, off)) { + printf("]] %d\n", __LINE__); return rtems_rtl_elf_rel_failure; } @@ -416,6 +423,10 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj, return rtems_rtl_elf_rel_failure; } + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: JUMP26/PC26/CALL: insn=%p where=%p target=%p raddr=%p parsing=%d\n", + insn, (void*) where, (void*) target, (void*) raddr, parsing); + target = (intptr_t)target >> 2; if (((Elf_Sword)target > 0x1FFFFFF) || ((Elf_Sword)target < -0x2000000)) { @@ -435,9 +446,8 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj, return rtems_rtl_elf_rel_failure; } - tramp_addr = ((Elf_Addr)(uintptr_t)obj->tramp_brk) | (symvalue & 1); + tramp_addr = ((Elf_Addr)(uintptr_t) obj->tramp_brk) | (symvalue & 1); obj->tramp_brk = set_veneer(obj->tramp_brk, symvalue); - target = tramp_addr + rela->r_addend - (uintptr_t)where; target = (uintptr_t)target >> 2; } @@ -462,6 +472,7 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj, raddr = (Elf_Addr)symvalue + rela->r_addend; target = raddr - (uintptr_t)where; if (checkoverflow(target, 32, raddr, "", where, off)) { + printf("]] %d\n", __LINE__); return rtems_rtl_elf_rel_failure; } *where32 = target; diff --git a/cpukit/libdl/rtl-mdreloc-arm.c b/cpukit/libdl/rtl-mdreloc-arm.c index b45708dd46..16efbe79da 100644 --- a/cpukit/libdl/rtl-mdreloc-arm.c +++ b/cpukit/libdl/rtl-mdreloc-arm.c @@ -108,6 +108,12 @@ get_veneer_size(int type) return 8; } +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj) +{ + (void) obj; + return sizeof(uint32_t); +} + size_t rtems_rtl_elf_relocate_tramp_max_size (void) { diff --git a/cpukit/libdl/rtl-mdreloc-bfin.c b/cpukit/libdl/rtl-mdreloc-bfin.c index f46b86ce34..cf3f3f88c0 100644 --- a/cpukit/libdl/rtl-mdreloc-bfin.c +++ b/cpukit/libdl/rtl-mdreloc-bfin.c @@ -99,6 +99,12 @@ load_ptr(void *where) return (res); } +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj) +{ + (void) obj; + return sizeof(uint32_t); +} + size_t rtems_rtl_elf_relocate_tramp_max_size (void) { diff --git a/cpukit/libdl/rtl-mdreloc-i386.c b/cpukit/libdl/rtl-mdreloc-i386.c index 40b09d4be2..09cbe4f42f 100644 --- a/cpukit/libdl/rtl-mdreloc-i386.c +++ b/cpukit/libdl/rtl-mdreloc-i386.c @@ -64,6 +64,12 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type) return true; } +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj) +{ + (void) obj; + return sizeof(uint32_t); +} + size_t rtems_rtl_elf_relocate_tramp_max_size (void) { diff --git a/cpukit/libdl/rtl-mdreloc-lm32.c b/cpukit/libdl/rtl-mdreloc-lm32.c index de0609345f..af904cd126 100644 --- a/cpukit/libdl/rtl-mdreloc-lm32.c +++ b/cpukit/libdl/rtl-mdreloc-lm32.c @@ -92,6 +92,12 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type) return true; } +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj) +{ + (void) obj; + return sizeof(uint32_t); +} + size_t rtems_rtl_elf_relocate_tramp_max_size (void) { diff --git a/cpukit/libdl/rtl-mdreloc-m68k.c b/cpukit/libdl/rtl-mdreloc-m68k.c index 873574ef7c..a88d612c28 100644 --- a/cpukit/libdl/rtl-mdreloc-m68k.c +++ b/cpukit/libdl/rtl-mdreloc-m68k.c @@ -77,6 +77,12 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type) return true; } +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj) +{ + (void) obj; + return sizeof(uint32_t); +} + size_t rtems_rtl_elf_relocate_tramp_max_size (void) { diff --git a/cpukit/libdl/rtl-mdreloc-mips.c b/cpukit/libdl/rtl-mdreloc-mips.c index d43b144895..91d88c9986 100644 --- a/cpukit/libdl/rtl-mdreloc-mips.c +++ b/cpukit/libdl/rtl-mdreloc-mips.c @@ -93,6 +93,12 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type) return true; } +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj) +{ + (void) obj; + return sizeof(uint32_t); +} + size_t rtems_rtl_elf_relocate_tramp_max_size (void) { diff --git a/cpukit/libdl/rtl-mdreloc-moxie.c b/cpukit/libdl/rtl-mdreloc-moxie.c index 6238ac99d2..a3cfe63b6a 100644 --- a/cpukit/libdl/rtl-mdreloc-moxie.c +++ b/cpukit/libdl/rtl-mdreloc-moxie.c @@ -93,6 +93,12 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type) return true; } +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj) +{ + (void) obj; + return sizeof(uint32_t); +} + size_t rtems_rtl_elf_relocate_tramp_max_size (void) { diff --git a/cpukit/libdl/rtl-mdreloc-powerpc.c b/cpukit/libdl/rtl-mdreloc-powerpc.c index 49ed9e848c..09c2ab1512 100644 --- a/cpukit/libdl/rtl-mdreloc-powerpc.c +++ b/cpukit/libdl/rtl-mdreloc-powerpc.c @@ -207,6 +207,12 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type) return true; } +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj) +{ + (void) obj; + return sizeof(uint32_t); +} + size_t rtems_rtl_elf_relocate_tramp_max_size (void) { diff --git a/cpukit/libdl/rtl-mdreloc-riscv.c b/cpukit/libdl/rtl-mdreloc-riscv.c index e6778dcc90..c0b7556366 100644 --- a/cpukit/libdl/rtl-mdreloc-riscv.c +++ b/cpukit/libdl/rtl-mdreloc-riscv.c @@ -89,6 +89,12 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type) { return true; } +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj) +{ + (void) obj; + return sizeof(uint32_t); +} + size_t rtems_rtl_elf_relocate_tramp_max_size (void) { /* diff --git a/cpukit/libdl/rtl-mdreloc-sparc.c b/cpukit/libdl/rtl-mdreloc-sparc.c index 7dd8a2af2f..9810de988e 100644 --- a/cpukit/libdl/rtl-mdreloc-sparc.c +++ b/cpukit/libdl/rtl-mdreloc-sparc.c @@ -209,6 +209,12 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type) return r; } +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj) +{ + (void) obj; + return sizeof(uint32_t); +} + size_t rtems_rtl_elf_relocate_tramp_max_size (void) { diff --git a/cpukit/libdl/rtl-mdreloc-v850.c b/cpukit/libdl/rtl-mdreloc-v850.c index 8d1f3c02a7..826763a2b5 100644 --- a/cpukit/libdl/rtl-mdreloc-v850.c +++ b/cpukit/libdl/rtl-mdreloc-v850.c @@ -93,6 +93,12 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type) return true; } +uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj) +{ + (void) obj; + return sizeof(uint32_t); +} + size_t rtems_rtl_elf_relocate_tramp_max_size (void) { diff --git a/cpukit/libdl/rtl-obj.c b/cpukit/libdl/rtl-obj.c index 24d1e09048..a35fbf9e8d 100644 --- a/cpukit/libdl/rtl-obj.c +++ b/cpukit/libdl/rtl-obj.c @@ -137,7 +137,6 @@ rtems_rtl_obj_free (rtems_rtl_obj* obj) rtems_rtl_obj_erase_sections (obj); rtems_rtl_obj_erase_dependents (obj); rtems_rtl_symbol_obj_erase (obj); - rtems_rtl_obj_erase_trampoline (obj); rtems_rtl_obj_free_names (obj); if (obj->sec_num != NULL) free (obj->sec_num); @@ -599,26 +598,6 @@ rtems_rtl_obj_find_section_by_mask (const rtems_rtl_obj* obj, return match.sect; } -bool -rtems_rtl_obj_alloc_trampoline (rtems_rtl_obj* obj) -{ - if (obj->tramps_size == 0) - return true; - obj->trampoline = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, - obj->tramps_size, - true); - if (obj->trampoline == NULL) - rtems_rtl_set_error (ENOMEM, "no memory for the trampoline"); - obj->tramp_brk = obj->trampoline; - return obj->trampoline != NULL; -} - -void -rtems_rtl_obj_erase_trampoline (rtems_rtl_obj* obj) -{ - rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, obj->trampoline); -} - bool rtems_rtl_obj_alloc_dependents (rtems_rtl_obj* obj, size_t dependents) { @@ -828,6 +807,12 @@ rtems_rtl_obj_bss_size (const rtems_rtl_obj* obj) return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_BSS); } +size_t +rtems_rtl_obj_tramp_size (const rtems_rtl_obj* obj) +{ + return obj->tramp_slots * obj->tramp_slot_size; +} + uint32_t rtems_rtl_obj_bss_alignment (const rtems_rtl_obj* obj) { @@ -919,10 +904,10 @@ rtems_rtl_obj_synchronize_cache (rtems_rtl_obj* obj) size); } - if (obj->trampoline != NULL) + if (obj->tramp_base != NULL) { - rtems_cache_instruction_sync_after_code_change(obj->trampoline, - obj->tramps_size); + rtems_cache_instruction_sync_after_code_change(obj->tramp_base, + obj->tramp_size); } } @@ -1069,19 +1054,29 @@ rtems_rtl_obj_sections_locate (uint32_t mask, } } -bool -rtems_rtl_obj_alloc_sections (rtems_rtl_obj* obj, - int fd, - rtems_rtl_obj_sect_handler handler, - void* data) +static void +rtems_rtl_obj_set_sizes (rtems_rtl_obj* obj) { size_t text_size; + size_t tramp_size; size_t const_size; size_t eh_size; size_t data_size; size_t bss_size; - text_size = rtems_rtl_obj_text_size (obj) + rtems_rtl_obj_const_alignment (obj); + text_size = rtems_rtl_obj_text_size (obj); + tramp_size = rtems_rtl_obj_tramp_size (obj); + + if (tramp_size != 0) + { + text_size += rtems_rtl_obj_tramp_alignment (obj); + tramp_size += rtems_rtl_obj_const_alignment (obj); + } + else + { + text_size += rtems_rtl_obj_const_alignment (obj); + } + const_size = rtems_rtl_obj_const_size (obj) + rtems_rtl_obj_eh_alignment (obj); eh_size = rtems_rtl_obj_eh_size (obj) + rtems_rtl_obj_data_alignment (obj); data_size = rtems_rtl_obj_data_size (obj) + rtems_rtl_obj_bss_alignment (obj); @@ -1090,13 +1085,69 @@ rtems_rtl_obj_alloc_sections (rtems_rtl_obj* obj, /* * Set the sizes held in the object data. We need this for a fast reference. */ - obj->text_size = text_size; + obj->text_size = text_size + tramp_size; + obj->tramp_size = tramp_size; obj->const_size = const_size; obj->data_size = data_size; obj->eh_size = eh_size; obj->bss_size = bss_size; + obj->exec_size = text_size + const_size + eh_size + data_size + bss_size; +} + +static void +rtems_rtl_obj_print_sizes (rtems_rtl_obj* obj, const char* label) +{ +if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT)) + { + printf ("rtl: %s sect: text - b:%p s:%zi a:%" PRIu32 "\n", + label, obj->text_base, obj->text_size, rtems_rtl_obj_text_alignment (obj)); + printf ("rtl: %s sect: tramp - b:%p s:%zi a:%" PRIu32 "\n", + label, obj->tramp_base, obj->tramp_size, rtems_rtl_obj_tramp_alignment (obj)); + printf ("rtl: %s sect: const - b:%p s:%zi a:%" PRIu32 "\n", + label, obj->const_base, obj->const_size, rtems_rtl_obj_const_alignment (obj)); + printf ("rtl: %s sect: eh - b:%p s:%zi a:%" PRIu32 "\n", + label, obj->eh_base, obj->eh_size, rtems_rtl_obj_eh_alignment (obj)); + printf ("rtl: %s sect: data - b:%p s:%zi a:%" PRIu32 "\n", + label, obj->data_base, obj->data_size, rtems_rtl_obj_data_alignment (obj)); + printf ("rtl: %s sect: bss - b:%p s:%zi a:%" PRIu32 "\n", + label, obj->bss_base, obj->bss_size, rtems_rtl_obj_bss_alignment (obj)); + } +} + +static void +rtems_rtl_obj_locate (rtems_rtl_obj* obj) +{ /* + * Locate all text, data and bss sections in seperate operations so each type of + * section is grouped together. + */ + rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_TEXT, + rtems_rtl_alloc_text_tag (), + obj, obj->text_base); + rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_CONST, + rtems_rtl_alloc_const_tag (), + obj, obj->const_base); + rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_EH, + rtems_rtl_alloc_eh_tag (), + obj, obj->eh_base); + rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_DATA, + rtems_rtl_alloc_data_tag (), + obj, obj->data_base); + rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_BSS, + rtems_rtl_alloc_bss_tag (), + obj, obj->bss_base); +} + +bool +rtems_rtl_obj_alloc_sections (rtems_rtl_obj* obj, + int fd, + rtems_rtl_obj_sect_handler handler, + void* data) +{ + rtems_rtl_obj_set_sizes (obj); + + /* * Perform any specific allocations for sections. */ if (handler != NULL) @@ -1116,33 +1167,28 @@ rtems_rtl_obj_alloc_sections (rtems_rtl_obj* obj, * Let the allocator manage the actual allocation. The user can use the * standard heap or provide a specific allocator with memory protection. */ - if (!rtems_rtl_alloc_module_new (&obj->text_base, text_size, - &obj->const_base, const_size, - &obj->eh_base, eh_size, - &obj->data_base, data_size, - &obj->bss_base, bss_size)) + if (!rtems_rtl_alloc_module_new (&obj->text_base, obj->text_size, + &obj->const_base, obj->const_size, + &obj->eh_base, obj->eh_size, + &obj->data_base, obj->data_size, + &obj->bss_base, obj->bss_size)) { obj->exec_size = 0; rtems_rtl_set_error (ENOMEM, "no memory to load obj"); return false; } - obj->exec_size = text_size + const_size + eh_size + data_size + bss_size; - - if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT)) + /* + * Set the trampoline base if there are trampolines + */ + if (obj->tramp_size != 0) { - printf ("rtl: load sect: text - b:%p s:%zi a:%" PRIu32 "\n", - obj->text_base, text_size, rtems_rtl_obj_text_alignment (obj)); - printf ("rtl: load sect: const - b:%p s:%zi a:%" PRIu32 "\n", - obj->const_base, const_size, rtems_rtl_obj_const_alignment (obj)); - printf ("rtl: load sect: eh - b:%p s:%zi a:%" PRIu32 "\n", - obj->eh_base, eh_size, rtems_rtl_obj_eh_alignment (obj)); - printf ("rtl: load sect: data - b:%p s:%zi a:%" PRIu32 "\n", - obj->data_base, data_size, rtems_rtl_obj_data_alignment (obj)); - printf ("rtl: load sect: bss - b:%p s:%zi a:%" PRIu32 "\n", - obj->bss_base, bss_size, rtems_rtl_obj_bss_alignment (obj)); + obj->tramp_base = obj->tramp_brk = + obj->text_base + obj->text_size - obj->tramp_size; } + rtems_rtl_obj_print_sizes (obj, "alloc"); + /* * Determine the load order. */ @@ -1153,24 +1199,48 @@ rtems_rtl_obj_alloc_sections (rtems_rtl_obj* obj, rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_BSS, obj); /* - * Locate all text, data and bss sections in seperate operations so each type of - * section is grouped together. + * Locate the sections to the allocated section bases */ - rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_TEXT, - rtems_rtl_alloc_text_tag (), - obj, obj->text_base); - rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_CONST, - rtems_rtl_alloc_const_tag (), - obj, obj->const_base); - rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_EH, - rtems_rtl_alloc_eh_tag (), - obj, obj->eh_base); - rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_DATA, - rtems_rtl_alloc_data_tag (), - obj, obj->data_base); - rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_BSS, - rtems_rtl_alloc_bss_tag (), - obj, obj->bss_base); + rtems_rtl_obj_locate (obj); + + return true; +} + +bool +rtems_rtl_obj_resize_sections (rtems_rtl_obj* obj) +{ + rtems_rtl_obj_set_sizes (obj); + + /* + * Let the allocator manage the resizing. + */ + if (!rtems_rtl_alloc_module_resize (&obj->text_base, obj->text_size, + &obj->const_base, obj->const_size, + &obj->eh_base, obj->eh_size, + &obj->data_base, obj->data_size, + &obj->bss_base, obj->bss_size)) + { + rtems_rtl_obj_free (obj); + obj->exec_size = 0; + rtems_rtl_set_error (ENOMEM, "no memory resize obj"); + return false; + } + + /* + * Set the trampoline base if there are trampolines + */ + if (obj->tramp_size != 0) + { + obj->tramp_base = obj->tramp_brk = + obj->text_base + obj->text_size - obj->tramp_size; + } + + rtems_rtl_obj_print_sizes (obj, "resize"); + + /* + * Locate the sections to the allocated section bases + */ + rtems_rtl_obj_locate (obj); return true; } diff --git a/cpukit/libdl/rtl-shell.c b/cpukit/libdl/rtl-shell.c index 69de6bad83..18f1e08901 100644 --- a/cpukit/libdl/rtl-shell.c +++ b/cpukit/libdl/rtl-shell.c @@ -572,7 +572,7 @@ rtems_rtl_obj_printer (rtems_rtl_obj_print* print, rtems_rtl_obj* obj) rtems_printf (print->printer, "%-*cslots : %zu\n", indent + 4, ' ', slots); rtems_printf (print->printer, "%-*csize : %zu\n", indent + 4, ' ', - obj->tramps_size); + obj->tramp_size); rtems_printf (print->printer, "%-*cslot size : %zu\n", indent + 4, ' ', obj->tramp_size); rtems_printf (print->printer, "%-*cused : %zu\n", indent + 4, ' ', diff --git a/testsuites/libtests/dl09/dl-load.c b/testsuites/libtests/dl09/dl-load.c index ce9708c3a3..216fb5a201 100644 --- a/testsuites/libtests/dl09/dl-load.c +++ b/testsuites/libtests/dl09/dl-load.c @@ -116,8 +116,12 @@ static void dl_check_resolved(void* handle, bool has_unresolved) rtems_test_assert (unresolved == 0); } } - printf ("handel: %p: %sunresolved externals\n", - handle, unresolved != 0 ? "" : "no "); + if (handle == RTLD_SELF) + printf ("handle: RTL_SELF: %sunresolved externals\n", + unresolved != 0 ? "" : "no "); + else + printf ("handle: %p: %sunresolved externals\n", + handle, unresolved != 0 ? "" : "no "); } static void* dl_load_obj (const char* name, bool has_unresolved) @@ -152,12 +156,20 @@ static void dl_close (void* handle) static int dl_call (void* handle, const char* func) { + static call_sig last_call; call_sig call = dlsym (handle, func); if (call == NULL) { printf("dlsym failed: symbol not found: %s\n", func); return 1; } + if (last_call != NULL && last_call != call) + { + printf("Call location different: moved by: %i (call:%p last:%p)\n", + (int) (call - last_call), + call, last_call); + } + last_call = call; call (); return 0; } -- 2.37.1 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel