From e309f7769fab9eed69079445a3f7f2354ea993c3 Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Thu, 14 Feb 2019 14:00:05 +1100 Subject: libdl: Allocator does not unlock and lock memory on loading. Close #3692 --- cpukit/include/rtems/rtl/rtl-allocator.h | 70 +++++++++++++++++++++++++- cpukit/libdl/rtl-alloc-heap.c | 6 +-- cpukit/libdl/rtl-alloc-heap.h | 4 +- cpukit/libdl/rtl-allocator.c | 84 ++++++++++++++++++++++++++++---- cpukit/libdl/rtl-obj.c | 11 +++++ 5 files changed, 158 insertions(+), 17 deletions(-) diff --git a/cpukit/include/rtems/rtl/rtl-allocator.h b/cpukit/include/rtems/rtl/rtl-allocator.h index c5b3d4ec72..1a5d615582 100644 --- a/cpukit/include/rtems/rtl/rtl-allocator.h +++ b/cpukit/include/rtems/rtl/rtl-allocator.h @@ -44,6 +44,21 @@ enum rtems_rtl_alloc_tags { */ typedef enum rtems_rtl_alloc_tags rtems_rtl_alloc_tag; +/** + * Define the allocation command the loader requires. + */ +enum rtems_rtl_alloc_cmd { + RTEMS_RTL_ALLOC_NEW, /**< Allocate new memory. */ + RTEMS_RTL_ALLOC_DEL, /**< Delete allocated memory. */ + RTEMS_RTL_ALLOC_WR_ENABLE, /**< Enable writes to the memory. */ + RTEMS_RTL_ALLOC_WR_DISABLE, /**< Disable writes to the memory. */ +}; + +/** + * The allocator command type. + */ +typedef enum rtems_rtl_alloc_cmd rtems_rtl_alloc_cmd; + /** * The number of tags. */ @@ -53,7 +68,7 @@ typedef enum rtems_rtl_alloc_tags rtems_rtl_alloc_tag; * Allocator handler handles all RTL allocations. It can be hooked and * overridded for customised allocation schemes or memory maps. * - * @param allocation If true the request is to allocate memory else free. + * @param allocation The request command. * @param tag The type of allocation request. * @param address Pointer to the memory address. If an allocation the value is * unspecific on entry and the allocated address or NULL on @@ -63,7 +78,7 @@ typedef enum rtems_rtl_alloc_tags rtems_rtl_alloc_tag; * @param size The size of the allocation if an allocation request and * not used if deleting or freeing a previous allocation. */ -typedef void (*rtems_rtl_allocator)(bool allocate, +typedef void (*rtems_rtl_allocator)(rtems_rtl_alloc_cmd cmd, rtems_rtl_alloc_tag tag, void** address, size_t size); @@ -106,6 +121,22 @@ 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 enable write on a bloc of allocated memory. + * + * @param tag The type of allocation request. Must match the address. + * @param address The memory address to write enable. A NULL is ignored. + */ +void rtems_rtl_alloc_wr_enable (rtems_rtl_alloc_tag tag, void* address); + +/** + * The Runtime Loader allocator disable write on a bloc of allocated memory. + * + * @param tag The type of allocation request. Must match the address. + * @param address The memory address to write disable. A NULL is ignored. + */ +void rtems_rtl_alloc_wr_disable (rtems_rtl_alloc_tag tag, void* address); + /** * Hook the Runtime Loader allocatior. A handler can call the previous handler * in the chain to use it for specific tags. The default handler uses the @@ -137,6 +168,41 @@ void rtems_rtl_alloc_indirect_new (rtems_rtl_alloc_tag tag, void rtems_rtl_alloc_indirect_del (rtems_rtl_alloc_tag tag, rtems_rtl_ptr* handle); +/** + * Return the default tag for text sections. + * + * @return The text tag. + */ +rtems_rtl_alloc_tag rtems_rtl_alloc_text_tag (void); + +/** + * Return the default tag for const sections. + * + * @return The const tag. + */ +rtems_rtl_alloc_tag rtems_rtl_alloc_const_tag (void); + +/** + * Return the default tag for exception sections. + * + * @return The eh tag. + */ +rtems_rtl_alloc_tag rtems_rtl_alloc_eh_tag (void); + +/** + * Return the default tag for data sections. + * + * @return The data tag. + */ +rtems_rtl_alloc_tag rtems_rtl_alloc_data_tag (void); + +/** + * Return the default tag for bss sections. + * + * @return The bss tag. + */ +rtems_rtl_alloc_tag rtems_rtl_alloc_bss_tag (void); + /** * Allocate the memory for a module given the size of the text, const, data and * bss sections. If any part of the allocation fails the no memory is diff --git a/cpukit/libdl/rtl-alloc-heap.c b/cpukit/libdl/rtl-alloc-heap.c index 2483e89fed..4ffdaf23b1 100644 --- a/cpukit/libdl/rtl-alloc-heap.c +++ b/cpukit/libdl/rtl-alloc-heap.c @@ -18,14 +18,14 @@ #include "rtl-alloc-heap.h" void -rtems_rtl_alloc_heap (bool allocate, +rtems_rtl_alloc_heap (rtems_rtl_alloc_cmd cmd, rtems_rtl_alloc_tag tag, void** address, size_t size) { - if (allocate) + if (cmd == RTEMS_RTL_ALLOC_NEW) *address = malloc (size); - else + else if (cmd == RTEMS_RTL_ALLOC_DEL) { free (*address); *address = NULL; diff --git a/cpukit/libdl/rtl-alloc-heap.h b/cpukit/libdl/rtl-alloc-heap.h index befcad19b0..6b7018b400 100644 --- a/cpukit/libdl/rtl-alloc-heap.h +++ b/cpukit/libdl/rtl-alloc-heap.h @@ -25,7 +25,7 @@ extern "C" { /** * Allocator handler for the standard libc heap. * - * @param allocation If true the request is to allocate memory else free. + * @param cmd The allocation command. * @param tag The type of allocation request. * @param address Pointer to the memory address. If an allocation the value is * unspecific on entry and the allocated address or NULL on @@ -35,7 +35,7 @@ extern "C" { * @param size The size of the allocation if an allocation request and * not used if deleting or freeing a previous allocation. */ -void rtems_rtl_alloc_heap(bool allocate, +void rtems_rtl_alloc_heap(rtems_rtl_alloc_cmd cmd, rtems_rtl_alloc_tag tag, void** address, size_t size); diff --git a/cpukit/libdl/rtl-allocator.c b/cpukit/libdl/rtl-allocator.c index 605cdbde83..01ce9e580f 100644 --- a/cpukit/libdl/rtl-allocator.c +++ b/cpukit/libdl/rtl-allocator.c @@ -57,8 +57,8 @@ rtems_rtl_alloc_new (rtems_rtl_alloc_tag tag, size_t size, bool zero) * Obtain memory from the allocator. The address field is set by the * allocator. */ - if (rtl) - rtl->allocator.allocator (true, tag, &address, size); + if (rtl != NULL) + rtl->allocator.allocator (RTEMS_RTL_ALLOC_NEW, tag, &address, size); rtems_rtl_unlock (); @@ -69,7 +69,7 @@ rtems_rtl_alloc_new (rtems_rtl_alloc_tag tag, size_t size, bool zero) /* * Only zero the memory if asked to and the allocation was successful. */ - if (address && zero) + if (address != NULL && zero) memset (address, 0, size); return address; @@ -84,8 +84,42 @@ rtems_rtl_alloc_del (rtems_rtl_alloc_tag tag, void* address) printf ("rtl: alloc: del: %s addr=%p\n", rtems_rtl_trace_tag_label (tag), address); - if (rtl && address) - rtl->allocator.allocator (false, tag, &address, 0); + if (rtl != NULL && address != NULL) + rtl->allocator.allocator (RTEMS_RTL_ALLOC_DEL, tag, &address, 0); + + rtems_rtl_unlock (); +} + +void +rtems_rtl_alloc_wr_enable (rtems_rtl_alloc_tag tag, void* address) +{ + rtems_rtl_data* rtl = rtems_rtl_lock (); + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR)) + printf ("rtl: alloc: wr-enable: addr=%p\n", address); + + if (rtl != NULL && address != NULL) + rtl->allocator.allocator (RTEMS_RTL_ALLOC_WR_ENABLE, + tag, + address, + 0); + + rtems_rtl_unlock (); +} + +void +rtems_rtl_alloc_wr_disable (rtems_rtl_alloc_tag tag, void* address) +{ + rtems_rtl_data* rtl = rtems_rtl_lock (); + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR)) + printf ("rtl: alloc: wr-enable: addr=%p\n", address); + + if (rtl != NULL && address != NULL) + rtl->allocator.allocator (RTEMS_RTL_ALLOC_WR_DISABLE, + tag, + address, + 0); rtems_rtl_unlock (); } @@ -150,6 +184,36 @@ rtems_rtl_alloc_indirect_del (rtems_rtl_alloc_tag tag, } } +rtems_rtl_alloc_tag +rtems_rtl_alloc_text_tag (void) +{ + return RTEMS_RTL_ALLOC_READ_EXEC; +} + +rtems_rtl_alloc_tag +rtems_rtl_alloc_const_tag (void) +{ + return RTEMS_RTL_ALLOC_READ; +} + +rtems_rtl_alloc_tag +rtems_rtl_alloc_eh_tag (void) +{ + return RTEMS_RTL_ALLOC_READ; +} + +rtems_rtl_alloc_tag +rtems_rtl_alloc_data_tag (void) +{ + return RTEMS_RTL_ALLOC_READ_WRITE; +} + +rtems_rtl_alloc_tag +rtems_rtl_alloc_bss_tag (void) +{ + return RTEMS_RTL_ALLOC_READ_WRITE; +} + bool rtems_rtl_alloc_module_new (void** text_base, size_t text_size, void** const_base, size_t const_size, @@ -161,7 +225,7 @@ rtems_rtl_alloc_module_new (void** text_base, size_t text_size, if (text_size) { - *text_base = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_READ_EXEC, + *text_base = rtems_rtl_alloc_new (rtems_rtl_alloc_text_tag (), text_size, false); if (!*text_base) { @@ -171,7 +235,7 @@ rtems_rtl_alloc_module_new (void** text_base, size_t text_size, if (const_size) { - *const_base = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_READ, + *const_base = rtems_rtl_alloc_new (rtems_rtl_alloc_const_tag (), const_size, false); if (!*const_base) { @@ -183,7 +247,7 @@ rtems_rtl_alloc_module_new (void** text_base, size_t text_size, if (eh_size) { - *eh_base = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_READ, + *eh_base = rtems_rtl_alloc_new (rtems_rtl_alloc_eh_tag (), eh_size, false); if (!*eh_base) { @@ -195,7 +259,7 @@ rtems_rtl_alloc_module_new (void** text_base, size_t text_size, if (data_size) { - *data_base = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_READ_WRITE, + *data_base = rtems_rtl_alloc_new (rtems_rtl_alloc_data_tag (), data_size, false); if (!*data_base) { @@ -207,7 +271,7 @@ rtems_rtl_alloc_module_new (void** text_base, size_t text_size, if (bss_size) { - *bss_base = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_READ_WRITE, + *bss_base = rtems_rtl_alloc_new (rtems_rtl_alloc_bss_tag (), bss_size, false); if (!*bss_base) { diff --git a/cpukit/libdl/rtl-obj.c b/cpukit/libdl/rtl-obj.c index 15e5bf1137..378678435d 100644 --- a/cpukit/libdl/rtl-obj.c +++ b/cpukit/libdl/rtl-obj.c @@ -1000,6 +1000,7 @@ rtems_rtl_obj_sections_link_order (uint32_t mask, rtems_rtl_obj* obj) static bool rtems_rtl_obj_sections_loader (uint32_t mask, + rtems_rtl_alloc_tag tag, rtems_rtl_obj* obj, int fd, uint8_t* base, @@ -1014,6 +1015,8 @@ rtems_rtl_obj_sections_loader (uint32_t mask, if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT)) printf ("rtl: loading section: mask:%08" PRIx32 " base:%p\n", mask, base); + rtems_rtl_alloc_wr_enable (tag, base); + while (!rtems_chain_is_tail (sections, node)) { rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node; @@ -1039,6 +1042,7 @@ rtems_rtl_obj_sections_loader (uint32_t mask, if (!handler (obj, fd, sect, data)) { sect->base = 0; + rtems_rtl_alloc_wr_disable (tag, base); return false; } } @@ -1067,6 +1071,8 @@ rtems_rtl_obj_sections_loader (uint32_t mask, node = rtems_chain_next (node); } + rtems_rtl_alloc_wr_disable (tag, base); + return true; } @@ -1168,14 +1174,19 @@ rtems_rtl_obj_load_sections (rtems_rtl_obj* obj, * sections. */ if (!rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_TEXT, + rtems_rtl_alloc_text_tag (), obj, fd, obj->text_base, handler, data) || !rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_CONST, + rtems_rtl_alloc_const_tag (), obj, fd, obj->const_base, handler, data) || !rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_EH, + rtems_rtl_alloc_eh_tag (), obj, fd, obj->eh_base, handler, data) || !rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_DATA, + rtems_rtl_alloc_data_tag (), obj, fd, obj->data_base, handler, data) || !rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_BSS, + rtems_rtl_alloc_bss_tag (), obj, fd, obj->bss_base, handler, data)) { rtems_rtl_alloc_module_del (&obj->text_base, &obj->const_base, &obj->eh_base, -- cgit v1.2.3