summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2012-11-30 20:54:07 +1100
committerChris Johns <chrisj@rtems.org>2012-11-30 20:54:07 +1100
commit9856d096995e701ce68c6e0107146c7be3518502 (patch)
treeac1bbf4272a23e54b16eb09f28128cea5398e091
parentabb3dd4f73727756efd4856156acdbbbb271c26d (diff)
Add a section handler to load sections.
-rw-r--r--rtl-elf.c35
-rw-r--r--rtl-obj.c68
-rw-r--r--rtl-obj.h11
-rw-r--r--rtl-rap.c11
4 files changed, 81 insertions, 44 deletions
diff --git a/rtl-elf.c b/rtl-elf.c
index ec73907..76bdf1b 100644
--- a/rtl-elf.c
+++ b/rtl-elf.c
@@ -493,6 +493,39 @@ rtems_rtl_elf_symbols (rtems_rtl_obj_t* obj,
}
static bool
+rtems_rtl_elf_loader (rtems_rtl_obj_t* obj,
+ int fd,
+ rtems_rtl_obj_sect_t* sect,
+ void* data)
+{
+ uint8_t* base_offset;
+ size_t len;
+
+ if (lseek (fd, obj->ooffset + sect->offset, SEEK_SET) < 0)
+ {
+ rtems_rtl_set_error (errno, "section load seek failed");
+ return false;
+ }
+
+ base_offset = sect->base;
+ len = sect->size;
+
+ while (len)
+ {
+ ssize_t r = read (fd, base_offset, len);
+ if (r <= 0)
+ {
+ rtems_rtl_set_error (errno, "section load read failed");
+ return false;
+ }
+ base_offset += r;
+ len -= r;
+ }
+
+ return true;
+}
+
+static bool
rtems_rtl_elf_parse_sections (rtems_rtl_obj_t* obj, int fd, Elf_Ehdr* ehdr)
{
rtems_rtl_obj_cache_t* sects;
@@ -716,7 +749,7 @@ rtems_rtl_elf_file_load (rtems_rtl_obj_t* obj, int fd)
obj->entry = (void*)(uintptr_t) ehdr.e_entry;
- if (!rtems_rtl_obj_load_sections (obj, fd))
+ if (!rtems_rtl_obj_load_sections (obj, fd, rtems_rtl_elf_loader, &ehdr))
return false;
if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols, &ehdr))
diff --git a/rtl-obj.c b/rtl-obj.c
index 8f839e2..b5696ad 100644
--- a/rtl-obj.c
+++ b/rtl-obj.c
@@ -619,65 +619,52 @@ rtems_rtl_obj_load_symbols (rtems_rtl_obj_t* obj,
}
static size_t
-rtems_rtl_obj_sections_loader (rtems_chain_control* sections,
- uint32_t mask,
- int fd,
- off_t offset,
- uint8_t* base)
+rtems_rtl_obj_sections_loader (uint32_t mask,
+ rtems_rtl_obj_t* obj,
+ int fd,
+ uint8_t* base,
+ rtems_rtl_obj_sect_handler_t handler,
+ void* data)
{
- rtems_chain_node* node = rtems_chain_first (sections);
- size_t base_offset = 0;
- bool first = true;
+ rtems_chain_control* sections = &obj->sections;
+ rtems_chain_node* node = rtems_chain_first (sections);
+ size_t base_offset = 0;
+ bool first = true;
while (!rtems_chain_is_tail (sections, node))
{
rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node;
if ((sect->size != 0) && ((sect->flags & mask) != 0))
{
- uint8_t* sect_base = base + base_offset;
-
if (!first)
base_offset = rtems_rtl_sect_align (base_offset, sect->alignment);
+ sect->base = base + base_offset;
+
if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
printf ("rtl: loading: %s -> %8p (%zi)\n",
- sect->name, base + base_offset, sect->size);
+ sect->name, sect->base, sect->size);
if ((sect->flags & RTEMS_RTL_OBJ_SECT_LOAD) == RTEMS_RTL_OBJ_SECT_LOAD)
{
- size_t len;
-
- if (lseek (fd, offset + sect->offset, SEEK_SET) < 0)
+ if (!handler (obj, fd, sect, data))
{
- rtems_rtl_set_error (errno, "section load seek failed");
+ sect->base = 0;
return false;
}
-
- len = sect->size;
- while (len)
- {
- ssize_t r = read (fd, base + base_offset, len);
- if (r <= 0)
- {
- rtems_rtl_set_error (errno, "section load read failed");
- return false;
- }
- base_offset += r;
- len -= r;
- }
}
else if ((sect->flags & RTEMS_RTL_OBJ_SECT_ZERO) == RTEMS_RTL_OBJ_SECT_ZERO)
{
memset (base + base_offset, 0, sect->size);
- base_offset += sect->size;
}
else
{
+ sect->base = 0;
rtems_rtl_set_error (errno, "section has no load op");
return false;
}
- sect->base = sect_base;
+ base_offset += sect->size;
first = false;
}
@@ -688,7 +675,10 @@ rtems_rtl_obj_sections_loader (rtems_chain_control* sections,
}
bool
-rtems_rtl_obj_load_sections (rtems_rtl_obj_t* obj, int fd)
+rtems_rtl_obj_load_sections (rtems_rtl_obj_t* obj,
+ int fd,
+ rtems_rtl_obj_sect_handler_t handler,
+ void* data)
{
size_t text_size;
size_t const_size;
@@ -732,14 +722,14 @@ rtems_rtl_obj_load_sections (rtems_rtl_obj_t* obj, int fd)
* Load all text then data then bss sections in seperate operations so each
* type of section is grouped together.
*/
- if (!rtems_rtl_obj_sections_loader (&obj->sections, RTEMS_RTL_OBJ_SECT_TEXT,
- fd, obj->ooffset, obj->text_base) ||
- !rtems_rtl_obj_sections_loader (&obj->sections, RTEMS_RTL_OBJ_SECT_CONST,
- fd, obj->ooffset, obj->const_base) ||
- !rtems_rtl_obj_sections_loader (&obj->sections, RTEMS_RTL_OBJ_SECT_DATA,
- fd, obj->ooffset, obj->data_base) ||
- !rtems_rtl_obj_sections_loader (&obj->sections, RTEMS_RTL_OBJ_SECT_BSS,
- fd, obj->ooffset, obj->bss_base))
+ if (!rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_TEXT,
+ 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_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,
&obj->data_base, &obj->bss_base);
diff --git a/rtl-obj.h b/rtl-obj.h
index 943abb5..8df042f 100644
--- a/rtl-obj.h
+++ b/rtl-obj.h
@@ -55,7 +55,7 @@ typedef struct rtems_rtl_loader_table_s
#define RTEMS_RTL_OBJ_SECT_BSS (1 << 3) /**< Section holds program bss. */
#define RTEMS_RTL_OBJ_SECT_REL (1 << 4) /**< Section holds relocation records. */
#define RTEMS_RTL_OBJ_SECT_RELA (1 << 5) /**< Section holds relocation addend
- * records. */
+ * records. */
#define RTEMS_RTL_OBJ_SECT_SYM (1 << 6) /**< Section holds symbols. */
#define RTEMS_RTL_OBJ_SECT_STR (1 << 7) /**< Section holds strings. */
#define RTEMS_RTL_OBJ_SECT_ALLOC (1 << 8) /**< Section allocates runtime memory. */
@@ -84,7 +84,7 @@ struct rtems_rtl_obj_sect_s
int info; /**< Secfion info field. */
uint32_t flags; /**< The section's flags. */
void* base; /**< The base address of the section in
- * memory. */
+ * memory. */
};
/**
@@ -470,10 +470,15 @@ bool rtems_rtl_obj_load_symbols (rtems_rtl_obj_t* obj,
*
* @param obj The object file's descriptor.
* @param fd The object file's file descriptor.
+ * @param handler The object file's format specific load handler.
+ * @param data User specific data handle.
* @retval true The object has been sucessfully loaded.
* @retval false The load failed. The RTL error has been set.
*/
-bool rtems_rtl_obj_load_sections (rtems_rtl_obj_t* obj, int fd);
+bool rtems_rtl_obj_load_sections (rtems_rtl_obj_t* obj,
+ int fd,
+ rtems_rtl_obj_sect_handler_t handler,
+ void* data);
/**
* Invoke the constructors the object has. Constructors are a table of pointers
diff --git a/rtl-rap.c b/rtl-rap.c
index b54e38a..bc0faee 100644
--- a/rtl-rap.c
+++ b/rtl-rap.c
@@ -183,6 +183,15 @@ rtems_rtl_rap_read_uint32 (rtems_rtl_obj_comp_t* comp, uint32_t* value)
}
static bool
+rtems_rtl_rap_loader (rtems_rtl_obj_t* obj,
+ int fd,
+ rtems_rtl_obj_sect_t* sect,
+ void* data)
+{
+ return true;
+}
+
+static bool
rtems_rtl_rap_symbols (rtems_rtl_obj_t* obj,
int fd,
rtems_rtl_obj_sect_t* sect,
@@ -440,7 +449,7 @@ rtems_rtl_rap_file_load (rtems_rtl_obj_t* obj, int fd)
/** obj->entry = (void*)(uintptr_t) ehdr.e_entry; */
- if (!rtems_rtl_obj_load_sections (obj, fd))
+ if (!rtems_rtl_obj_load_sections (obj, fd, rtems_rtl_rap_loader, &rap))
return false;
if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_rap_symbols, &rap))