summaryrefslogtreecommitdiff
path: root/rtl-rap.c
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2012-12-01 21:23:29 +1100
committerChris Johns <chrisj@rtems.org>2012-12-01 21:23:29 +1100
commitc4e952ed97c76f971c9f9b08f61978f0550d9732 (patch)
treeb80975f2ce5ffbd90527bccc1ece223464447b69 /rtl-rap.c
parent57f4a27f26b0e9743f7516fab5e685983e46b7ab (diff)
Add symbol loading support for RAP files.
Diffstat (limited to 'rtl-rap.c')
-rw-r--r--rtl-rap.c98
1 files changed, 96 insertions, 2 deletions
diff --git a/rtl-rap.c b/rtl-rap.c
index 3350866..d8efcf8 100644
--- a/rtl-rap.c
+++ b/rtl-rap.c
@@ -104,6 +104,7 @@ typedef struct rtems_rtl_rap_s
uint32_t symtab_size; /**< The symbol table size. */
uint32_t strtab_size; /**< The string table size. */
uint32_t relocs_size; /**< The relocation table size. */
+ uint32_t symbols; /**< The number of symbols. */
} rtems_rtl_rap_t;
/**
@@ -211,6 +212,98 @@ rtems_rtl_rap_relocator (rtems_rtl_obj_t* obj,
}
static bool
+rtems_rtl_rap_load_symbols (rtems_rtl_rap_t* rap, rtems_rtl_obj_t* obj)
+{
+ char* string;
+ rtems_rtl_obj_sym_t* gsym;
+ int sym;
+
+ obj->global_size =
+ rap->symbols * sizeof (rtems_rtl_obj_sym_t) + rap->strtab_size;
+
+ obj->global_table = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL,
+ obj->global_size, true);
+ if (!obj->global_table)
+ {
+ obj->global_size = 0;
+ rtems_rtl_set_error (ENOMEM, "no memory for obj global syms");
+ return false;
+ }
+
+ obj->global_syms = rap->symbols;
+
+ string = (((char*) obj->global_table) +
+ (rap->symbols * sizeof (rtems_rtl_obj_sym_t)));
+
+ if (!rtems_rtl_obj_comp_read (rap->decomp, string, rap->strtab_size))
+ return false;
+
+ for (sym = 0, gsym = obj->global_table; sym < rap->symbols; ++sym)
+ {
+ rtems_rtl_obj_sect_t* symsect;
+ uint32_t data;
+ uint32_t name;
+ uint32_t value;
+
+ if (!rtems_rtl_rap_read_uint32 (rap->decomp, &data) ||
+ !rtems_rtl_rap_read_uint32 (rap->decomp, &name) ||
+ !rtems_rtl_rap_read_uint32 (rap->decomp, &value))
+ {
+ free (obj->global_table);
+ obj->global_table = NULL;
+ obj->global_syms = 0;
+ obj->global_size = 0;
+ return false;
+ }
+
+ /*
+ * If there is a globally exported symbol already present and this
+ * symbol is not weak raise an error. If the symbol is weak and present
+ * globally ignore this symbol and use the global one and if it is not
+ * present take this symbol global or weak. We accept the first weak
+ * symbol we find and make it globally exported.
+ */
+ if (rtems_rtl_symbol_global_find (string) &&
+ (ELF_ST_BIND (data & 0xffff) != STB_WEAK))
+ {
+ free (obj->global_table);
+ obj->global_table = NULL;
+ obj->global_syms = 0;
+ obj->global_size = 0;
+ rtems_rtl_set_error (ENOMEM, "duplicate global symbol: %s", string);
+ return false;
+ }
+
+ symsect = rtems_rtl_obj_find_section_by_index (obj, data >> 16);
+ if (!symsect)
+ {
+ free (obj->global_table);
+ obj->global_table = NULL;
+ obj->global_syms = 0;
+ obj->global_size = 0;
+ return false;
+ }
+
+ rtems_chain_set_off_chain (&gsym->node);
+ gsym->name = string;
+ gsym->value = (uint8_t*) (value + symsect->base);
+ gsym->data = data & 0xffff;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
+ printf ("rtl: sym:add:%-2d name:%-20s bind:%-2d type:%-2d val:%8p sect:%d\n",
+ sym, gsym->name,
+ (int) ELF_ST_BIND (data & 0xffff),
+ (int) ELF_ST_TYPE (data & 0xffff),
+ gsym->value, (int) (data >> 16));
+
+ string += strlen (string) + 1;
+ ++gsym;
+ }
+
+ return true;
+}
+
+static bool
rtems_rtl_rap_parse_header (uint8_t* rhdr,
size_t* rhdr_len,
uint32_t* length,
@@ -332,7 +425,6 @@ rtems_rtl_rap_file_load (rtems_rtl_obj_t* obj, int fd)
rtems_rtl_rap_t rap = { 0 };
uint8_t* rhdr = NULL;
size_t rlen = 64;
- uint32_t script_length = 0;
int section;
rtems_rtl_obj_caches (&rap.file, NULL, NULL);
@@ -422,6 +514,8 @@ rtems_rtl_rap_file_load (rtems_rtl_obj_t* obj, int fd)
if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.relocs_size))
return false;
+ rap.symbols = rap.symtab_size / (3 * sizeof (uint32_t));
+
/*
* uint32_t: text_size
* uint32_t: text_alignment
@@ -477,7 +571,7 @@ rtems_rtl_rap_file_load (rtems_rtl_obj_t* obj, int 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))
+ if (!rtems_rtl_rap_load_symbols (&rap, obj))
return false;
if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_rap_relocator, &rap))