forked from Imagelibrary/rtems
libdl: Add C++ exception support to loaded modules.
This has been tested on SPARC, i386, PowerPC and ARM. Closes #2767.
This commit is contained in:
@@ -49,14 +49,21 @@
|
||||
/**
|
||||
* The table of supported loader formats.
|
||||
*/
|
||||
static rtems_rtl_loader_table_t loaders[RTEMS_RTL_ELF_LOADER_COUNT +
|
||||
RTEMS_RTL_RAP_LOADER_COUNT] =
|
||||
#define RTEMS_RTL_LOADERS (RTEMS_RTL_ELF_LOADER_COUNT + RTEMS_RTL_RAP_LOADER_COUNT)
|
||||
static const rtems_rtl_loader_table_t loaders[RTEMS_RTL_LOADERS] =
|
||||
{
|
||||
#if RTEMS_RTL_RAP_LOADER
|
||||
{ rtems_rtl_rap_file_check, rtems_rtl_rap_file_load, rtems_rtl_rap_file_sig },
|
||||
{ .check = rtems_rtl_rap_file_check,
|
||||
.load = rtems_rtl_rap_file_load,
|
||||
.unload = rtems_rtl_rap_file_unload,
|
||||
.unload = rtems_rtl_rap_file_unload,
|
||||
.signature = rtems_rtl_rap_file_sig },
|
||||
#endif
|
||||
#if RTEMS_RTL_ELF_LOADER
|
||||
{ rtems_rtl_elf_file_check, rtems_rtl_elf_file_load, rtems_rtl_elf_file_sig },
|
||||
{ .check = rtems_rtl_elf_file_check,
|
||||
.load = rtems_rtl_elf_file_load,
|
||||
.unload = rtems_rtl_elf_file_unload,
|
||||
.signature = rtems_rtl_elf_file_sig },
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -72,6 +79,10 @@ rtems_rtl_obj_alloc (void)
|
||||
* Initialise the chains.
|
||||
*/
|
||||
rtems_chain_initialize_empty (&obj->sections);
|
||||
/*
|
||||
* No valid format.
|
||||
*/
|
||||
obj->format = -1;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
@@ -97,14 +108,14 @@ rtems_rtl_obj_free (rtems_rtl_obj_t* obj)
|
||||
}
|
||||
if (!rtems_chain_is_node_off_chain (&obj->link))
|
||||
rtems_chain_extract (&obj->link);
|
||||
rtems_rtl_alloc_module_del (&obj->text_base, &obj->const_base,
|
||||
rtems_rtl_alloc_module_del (&obj->text_base, &obj->const_base, &obj->eh_base,
|
||||
&obj->data_base, &obj->bss_base);
|
||||
rtems_rtl_symbol_obj_erase (obj);
|
||||
rtems_rtl_obj_free_names (obj);
|
||||
if (obj->sec_num)
|
||||
free (obj->sec_num);
|
||||
if (obj->detail)
|
||||
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*)obj->detail);
|
||||
if (obj->linkmap)
|
||||
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) obj->linkmap);
|
||||
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, obj);
|
||||
return true;
|
||||
}
|
||||
@@ -238,7 +249,7 @@ rtems_rtl_scan_decimal (const uint8_t* string, size_t len)
|
||||
static size_t
|
||||
rtems_rtl_sect_align (size_t offset, uint32_t alignment)
|
||||
{
|
||||
if ((alignment > 1) && ((offset & ~alignment) != 0))
|
||||
if ((alignment > 1) && ((offset & (alignment - 1)) != 0))
|
||||
offset = (offset + alignment) & ~(alignment - 1);
|
||||
return offset;
|
||||
}
|
||||
@@ -264,12 +275,12 @@ rtems_rtl_obj_sect_summer (rtems_chain_node* node, void* data)
|
||||
}
|
||||
|
||||
static size_t
|
||||
rtems_rtl_obj_section_size (rtems_rtl_obj_t* obj, uint32_t mask)
|
||||
rtems_rtl_obj_section_size (const rtems_rtl_obj_t* obj, uint32_t mask)
|
||||
{
|
||||
rtems_rtl_obj_sect_summer_t summer;
|
||||
summer.mask = mask;
|
||||
summer.size = 0;
|
||||
rtems_rtl_chain_iterate (&obj->sections,
|
||||
rtems_rtl_chain_iterate ((rtems_chain_control*) &obj->sections,
|
||||
rtems_rtl_obj_sect_summer,
|
||||
&summer);
|
||||
return summer.size;
|
||||
@@ -302,12 +313,12 @@ rtems_rtl_obj_sect_aligner (rtems_chain_node* node, void* data)
|
||||
}
|
||||
|
||||
static size_t
|
||||
rtems_rtl_obj_section_alignment (rtems_rtl_obj_t* obj, uint32_t mask)
|
||||
rtems_rtl_obj_section_alignment (const rtems_rtl_obj_t* obj, uint32_t mask)
|
||||
{
|
||||
rtems_rtl_obj_sect_aligner_t aligner;
|
||||
aligner.mask = mask;
|
||||
aligner.alignment = 0;
|
||||
rtems_rtl_chain_iterate (&obj->sections,
|
||||
rtems_rtl_chain_iterate ((rtems_chain_control*) &obj->sections,
|
||||
rtems_rtl_obj_sect_aligner,
|
||||
&aligner);
|
||||
return aligner.alignment;
|
||||
@@ -401,26 +412,30 @@ rtems_rtl_obj_add_section (rtems_rtl_obj_t* obj,
|
||||
int info,
|
||||
uint32_t flags)
|
||||
{
|
||||
rtems_rtl_obj_sect_t* sect = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
|
||||
sizeof (rtems_rtl_obj_sect_t), true);
|
||||
if (!sect)
|
||||
if (size > 0)
|
||||
{
|
||||
rtems_rtl_set_error (ENOMEM, "adding allocated section");
|
||||
return false;
|
||||
}
|
||||
sect->section = section;
|
||||
sect->name = rtems_rtl_strdup (name);
|
||||
sect->size = size;
|
||||
sect->offset = offset;
|
||||
sect->alignment = alignment;
|
||||
sect->link = link;
|
||||
sect->info = info;
|
||||
sect->flags = flags;
|
||||
sect->base = NULL;
|
||||
rtems_chain_append (&obj->sections, §->node);
|
||||
rtems_rtl_obj_sect_t* sect = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
|
||||
sizeof (rtems_rtl_obj_sect_t),
|
||||
true);
|
||||
if (!sect)
|
||||
{
|
||||
rtems_rtl_set_error (ENOMEM, "adding allocated section");
|
||||
return false;
|
||||
}
|
||||
sect->section = section;
|
||||
sect->name = rtems_rtl_strdup (name);
|
||||
sect->size = size;
|
||||
sect->offset = offset;
|
||||
sect->alignment = alignment;
|
||||
sect->link = link;
|
||||
sect->info = info;
|
||||
sect->flags = flags;
|
||||
sect->base = NULL;
|
||||
rtems_chain_append (&obj->sections, §->node);
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_SECTION))
|
||||
printf ("rtl: sect: %-2d: %s\n", section, name);
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_SECTION))
|
||||
printf ("rtl: sect: %-2d: %s (%zu)\n", section, name, size);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -464,12 +479,13 @@ rtems_rtl_obj_sect_match_name (rtems_chain_node* node, void* data)
|
||||
}
|
||||
|
||||
rtems_rtl_obj_sect_t*
|
||||
rtems_rtl_obj_find_section (rtems_rtl_obj_t* obj, const char* name)
|
||||
rtems_rtl_obj_find_section (const rtems_rtl_obj_t* obj,
|
||||
const char* name)
|
||||
{
|
||||
rtems_rtl_obj_sect_finder_t match;
|
||||
match.sect = NULL;
|
||||
match.name = name;
|
||||
rtems_rtl_chain_iterate (&obj->sections,
|
||||
rtems_rtl_chain_iterate ((rtems_chain_control*) &obj->sections,
|
||||
rtems_rtl_obj_sect_match_name,
|
||||
&match);
|
||||
return match.sect;
|
||||
@@ -489,61 +505,74 @@ rtems_rtl_obj_sect_match_index (rtems_chain_node* node, void* data)
|
||||
}
|
||||
|
||||
rtems_rtl_obj_sect_t*
|
||||
rtems_rtl_obj_find_section_by_index (rtems_rtl_obj_t* obj, int index)
|
||||
rtems_rtl_obj_find_section_by_index (const rtems_rtl_obj_t* obj,
|
||||
int index)
|
||||
{
|
||||
rtems_rtl_obj_sect_finder_t match;
|
||||
match.sect = NULL;
|
||||
match.index = index;
|
||||
rtems_rtl_chain_iterate (&obj->sections,
|
||||
rtems_rtl_chain_iterate ((rtems_chain_control*) &obj->sections,
|
||||
rtems_rtl_obj_sect_match_index,
|
||||
&match);
|
||||
return match.sect;
|
||||
}
|
||||
|
||||
size_t
|
||||
rtems_rtl_obj_text_size (rtems_rtl_obj_t* obj)
|
||||
rtems_rtl_obj_text_size (const rtems_rtl_obj_t* obj)
|
||||
{
|
||||
return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_TEXT);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
rtems_rtl_obj_text_alignment (rtems_rtl_obj_t* obj)
|
||||
rtems_rtl_obj_text_alignment (const rtems_rtl_obj_t* obj)
|
||||
{
|
||||
return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_TEXT);
|
||||
}
|
||||
|
||||
size_t
|
||||
rtems_rtl_obj_const_size (rtems_rtl_obj_t* obj)
|
||||
rtems_rtl_obj_const_size (const rtems_rtl_obj_t* obj)
|
||||
{
|
||||
return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_CONST);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
rtems_rtl_obj_const_alignment (rtems_rtl_obj_t* obj)
|
||||
rtems_rtl_obj_eh_alignment (const rtems_rtl_obj_t* obj)
|
||||
{
|
||||
return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_EH);
|
||||
}
|
||||
|
||||
size_t
|
||||
rtems_rtl_obj_eh_size (const rtems_rtl_obj_t* obj)
|
||||
{
|
||||
return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_EH);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
rtems_rtl_obj_const_alignment (const rtems_rtl_obj_t* obj)
|
||||
{
|
||||
return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_CONST);
|
||||
}
|
||||
|
||||
size_t
|
||||
rtems_rtl_obj_data_size (rtems_rtl_obj_t* obj)
|
||||
rtems_rtl_obj_data_size (const rtems_rtl_obj_t* obj)
|
||||
{
|
||||
return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_DATA);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
rtems_rtl_obj_data_alignment (rtems_rtl_obj_t* obj)
|
||||
rtems_rtl_obj_data_alignment (const rtems_rtl_obj_t* obj)
|
||||
{
|
||||
return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_DATA);
|
||||
}
|
||||
|
||||
size_t
|
||||
rtems_rtl_obj_bss_size (rtems_rtl_obj_t* obj)
|
||||
rtems_rtl_obj_bss_size (const rtems_rtl_obj_t* obj)
|
||||
{
|
||||
return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_BSS);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
rtems_rtl_obj_bss_alignment (rtems_rtl_obj_t* obj)
|
||||
rtems_rtl_obj_bss_alignment (const rtems_rtl_obj_t* obj)
|
||||
{
|
||||
return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_BSS);
|
||||
}
|
||||
@@ -580,13 +609,17 @@ rtems_rtl_obj_sect_sync_handler (rtems_chain_node* node, void* data)
|
||||
if ( !(sect->flags & sync_ctx->mask) || !sect->size)
|
||||
return true;
|
||||
|
||||
if (sync_ctx->end_va == sync_ctx->start_va) {
|
||||
if (sync_ctx->end_va == sync_ctx->start_va)
|
||||
{
|
||||
sync_ctx->start_va = sect->base;
|
||||
} else {
|
||||
old_end = (uintptr_t)sync_ctx->end_va & ~(sync_ctx->cache_line_size - 1);
|
||||
new_start = (uintptr_t)sect->base & ~(sync_ctx->cache_line_size - 1);
|
||||
if ( (sect->base < sync_ctx->start_va) ||
|
||||
(new_start - old_end > sync_ctx->cache_line_size) ) {
|
||||
}
|
||||
else
|
||||
{
|
||||
old_end = (uintptr_t) sync_ctx->end_va & ~(sync_ctx->cache_line_size - 1);
|
||||
new_start = (uintptr_t) sect->base & ~(sync_ctx->cache_line_size - 1);
|
||||
if ((sect->base < sync_ctx->start_va) ||
|
||||
(new_start - old_end > sync_ctx->cache_line_size))
|
||||
{
|
||||
rtems_cache_instruction_sync_after_code_change(sync_ctx->start_va,
|
||||
sync_ctx->end_va - sync_ctx->start_va + 1);
|
||||
sync_ctx->start_va = sect->base;
|
||||
@@ -658,8 +691,8 @@ rtems_rtl_obj_sections_loader (uint32_t mask,
|
||||
sect->base = base + base_offset;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
|
||||
printf ("rtl: loading: %s -> %8p (%zi)\n",
|
||||
sect->name, sect->base, sect->size);
|
||||
printf ("rtl: loading: %s -> %8p (l:%zi m:%04lx)\n",
|
||||
sect->name, sect->base, sect->size, sect->flags);
|
||||
|
||||
if ((sect->flags & RTEMS_RTL_OBJ_SECT_LOAD) == RTEMS_RTL_OBJ_SECT_LOAD)
|
||||
{
|
||||
@@ -698,20 +731,30 @@ rtems_rtl_obj_load_sections (rtems_rtl_obj_t* obj,
|
||||
{
|
||||
size_t text_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);
|
||||
const_size = rtems_rtl_obj_const_size (obj) + rtems_rtl_obj_data_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);
|
||||
bss_size = rtems_rtl_obj_bss_size (obj);
|
||||
|
||||
/*
|
||||
* Set the sizes held in the object data. We need this for a fast reference.
|
||||
*/
|
||||
obj->text_size = text_size;
|
||||
obj->eh_size = eh_size;
|
||||
obj->bss_size = bss_size;
|
||||
|
||||
/*
|
||||
* 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))
|
||||
{
|
||||
@@ -728,6 +771,8 @@ rtems_rtl_obj_load_sections (rtems_rtl_obj_t* obj,
|
||||
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",
|
||||
@@ -742,12 +787,14 @@ rtems_rtl_obj_load_sections (rtems_rtl_obj_t* obj,
|
||||
obj, fd, obj->text_base, handler, data) ||
|
||||
!rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_CONST,
|
||||
obj, fd, obj->const_base, handler, data) ||
|
||||
!rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_EH,
|
||||
obj, fd, obj->eh_base, handler, data) ||
|
||||
!rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_DATA,
|
||||
obj, fd, obj->data_base, handler, data) ||
|
||||
!rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_BSS,
|
||||
obj, fd, obj->bss_base, handler, data))
|
||||
{
|
||||
rtems_rtl_alloc_module_del (&obj->text_base, &obj->const_base,
|
||||
rtems_rtl_alloc_module_del (&obj->text_base, &obj->const_base, &obj->eh_base,
|
||||
&obj->data_base, &obj->bss_base);
|
||||
obj->exec_size = 0;
|
||||
return false;
|
||||
@@ -972,7 +1019,7 @@ rtems_rtl_obj_archive_find (rtems_rtl_obj_t* obj, int fd)
|
||||
* name from the table and compare with the name we are after.
|
||||
*/
|
||||
#define RTEMS_RTL_MAX_FILE_SIZE (256)
|
||||
char name[RTEMS_RTL_MAX_FILE_SIZE];
|
||||
char name[RTEMS_RTL_MAX_FILE_SIZE];
|
||||
|
||||
if (!rtems_rtl_seek_read (fd, extended_file_names + extended_off,
|
||||
RTEMS_RTL_MAX_FILE_SIZE, (uint8_t*) &name[0]))
|
||||
@@ -1016,7 +1063,7 @@ rtems_rtl_obj_archive_find (rtems_rtl_obj_t* obj, int fd)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
static bool
|
||||
rtems_rtl_obj_file_load (rtems_rtl_obj_t* obj, int fd)
|
||||
{
|
||||
int l;
|
||||
@@ -1024,13 +1071,24 @@ rtems_rtl_obj_file_load (rtems_rtl_obj_t* obj, int fd)
|
||||
for (l = 0; l < (sizeof (loaders) / sizeof (rtems_rtl_loader_table_t)); ++l)
|
||||
{
|
||||
if (loaders[l].check (obj, fd))
|
||||
{
|
||||
obj->format = l;
|
||||
return loaders[l].load (obj, fd);
|
||||
}
|
||||
}
|
||||
|
||||
rtems_rtl_set_error (ENOENT, "no format loader found");
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
rtems_rtl_obj_file_unload (rtems_rtl_obj_t* obj)
|
||||
{
|
||||
if (obj->format >= 0 && obj->format < RTEMS_RTL_LOADERS)
|
||||
return loaders[obj->format].unload (obj);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_obj_load (rtems_rtl_obj_t* obj)
|
||||
{
|
||||
@@ -1057,20 +1115,16 @@ rtems_rtl_obj_load (rtems_rtl_obj_t* obj)
|
||||
{
|
||||
if (!rtems_rtl_obj_archive_find (obj, fd))
|
||||
{
|
||||
rtems_rtl_obj_caches_flush ();
|
||||
close (fd);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Call the format specific loader. Currently this is a call to the ELF
|
||||
* loader. This call could be changed to allow probes then calls if more than
|
||||
* one format is supported.
|
||||
* Call the format specific loader.
|
||||
*/
|
||||
if (!rtems_rtl_obj_file_load (obj, fd))
|
||||
{
|
||||
rtems_rtl_obj_caches_flush ();
|
||||
close (fd);
|
||||
return false;
|
||||
}
|
||||
@@ -1081,8 +1135,6 @@ rtems_rtl_obj_load (rtems_rtl_obj_t* obj)
|
||||
return false;
|
||||
}
|
||||
|
||||
rtems_rtl_obj_caches_flush ();
|
||||
|
||||
close (fd);
|
||||
|
||||
return true;
|
||||
@@ -1092,6 +1144,6 @@ bool
|
||||
rtems_rtl_obj_unload (rtems_rtl_obj_t* obj)
|
||||
{
|
||||
_rtld_linkmap_delete(obj);
|
||||
rtems_rtl_symbol_obj_erase (obj);
|
||||
return rtems_rtl_obj_free (obj);
|
||||
rtems_rtl_obj_file_unload (obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user