bool rtems_rtl_alloc_module_new (void** text_base, size_t text_size, void** const_base, size_t const_size, void** data_base, size_t data_size, void** bss_base, size_t bss_size) { *text_base = *const_base = *data_base = *bss_base = NULL; if (text_size) { *text_base = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_READ_EXEC, text_size, false); if (!*text_base) { return false; } } if (const_size) { *const_base = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_READ, const_size, false); if (!*const_base) { rtems_rtl_alloc_module_del (text_base, const_base, data_base, bss_base); return false; } } if (data_size) { *data_base = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_READ_WRITE, data_size, false); if (!*data_base) { rtems_rtl_alloc_module_del (text_base, const_base, data_base, bss_base); return false; } } if (bss_size) { *bss_base = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_READ_WRITE, bss_size, false); if (!*bss_base) { rtems_rtl_alloc_module_del (text_base, const_base, data_base, bss_base); return false; } } return true; }
bool rtems_rtl_obj_add_section (rtems_rtl_obj_t* obj, int section, const char* name, size_t size, off_t offset, uint32_t alignment, int link, 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) { 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); return true; }
void rtems_rtl_alloc_indirect_new (rtems_rtl_alloc_tag_t tag, rtems_rtl_ptr_t* handle, size_t size) { rtems_rtl_data_t* rtl = rtems_rtl_lock (); if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR)) { if (!rtems_rtl_ptr_null (handle)) printf ("rtl: alloc: inew: %s handle=%p: not null\n", rtems_rtl_trace_tag_label (tag), handle); printf ("rtl: alloc: inew: %s handle=%p size=%zd\n", rtems_rtl_trace_tag_label (tag), handle, size); } if (rtl) { rtems_rtl_alloc_data_t* allocator = &rtl->allocator; handle->pointer = rtems_rtl_alloc_new (tag, size, false); if (!rtems_rtl_ptr_null (handle)) rtems_chain_append_unprotected (&allocator->indirects[tag], &handle->node); } rtems_rtl_unlock (); }
rtems_rtl_obj_t* rtems_rtl_obj_alloc (void) { rtems_rtl_obj_t* obj = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, sizeof (rtems_rtl_obj_t), true); if (obj) { /* * Initialise the chains. */ rtems_chain_initialize_empty (&obj->sections); } return obj; }
bool rtems_rtl_obj_cache_open (rtems_rtl_obj_cache_t* cache, size_t size) { cache->fd = -1; cache->file_size = 0; cache->offset = 0; cache->size = size; cache->level = 0; cache->buffer = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, size, false); if (!cache->buffer) { rtems_rtl_set_error (ENOMEM, "no memory for cache buffer"); return false; } return true; }
static rtems_rtl_unresolv_block_t* rtems_rtl_unresolved_block_alloc (rtems_rtl_unresolved_t* unresolved) { /* * The block header contains a record. */ size_t size = (sizeof(rtems_rtl_unresolv_block_t) + (sizeof(rtems_rtl_unresolv_rec_t) * (unresolved->block_recs - 1))); rtems_rtl_unresolv_block_t* block = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_EXTERNAL, size, true); if (block) rtems_chain_append (&unresolved->blocks, &block->link); else rtems_rtl_set_error (ENOMEM, "no memory for unresolved block"); return block; }
bool rtems_rtl_symbol_table_open (rtems_rtl_symbols_t* symbols, size_t buckets) { symbols->buckets = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL, buckets * sizeof (rtems_chain_control), true); if (!symbols->buckets) { rtems_rtl_set_error (ENOMEM, "no memory for global symbol table"); return false; } symbols->nbuckets = buckets; for (buckets = 0; buckets < symbols->nbuckets; ++buckets) rtems_chain_initialize_empty (&symbols->buckets[buckets]); rtems_rtl_symbol_global_insert (symbols, &global_sym_add); return true; }
bool rtems_rtl_obj_comp_open (rtems_rtl_obj_comp_t* comp, size_t size) { comp->cache = NULL; comp->fd = -1; comp->compression = RTEMS_RTL_COMP_LZ77; comp->offset = 0; comp->size = size; comp->level = 0; comp->buffer = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, size, false); if (!comp->buffer) { rtems_rtl_set_error (ENOMEM, "no memory for compressor buffer"); return false; } comp->read = 0; return true; }
bool rtems_rtl_symbol_global_add (rtems_rtl_obj_t* obj, const unsigned char* esyms, unsigned int size) { rtems_rtl_symbols_t* symbols; rtems_rtl_obj_sym_t* sym; size_t count; size_t s; uint32_t marker; count = 0; s = 0; while ((s < size) && (esyms[s] != 0)) { int l = strlen ((char*) &esyms[s]); if ((esyms[s + l] != '\0') || ((s + l) > size)) { rtems_rtl_set_error (EINVAL, "invalid exported symbol table"); return false; } ++count; s += l + sizeof (unsigned long) + 1; } /* * Check this is the correct end of the table. */ marker = esyms[s + 1]; marker <<= 8; marker |= esyms[s + 2]; marker <<= 8; marker |= esyms[s + 3]; marker <<= 8; marker |= esyms[s + 4]; if (marker != 0xdeadbeefUL) { rtems_rtl_set_error (ENOMEM, "invalid export symbol table"); return false; } if (rtems_rtl_trace (RTEMS_RTL_TRACE_GLOBAL_SYM)) printf ("rtl: global symbol add: %zi\n", count); obj->global_size = count * sizeof (rtems_rtl_obj_sym_t); 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 global symbols"); return false; } symbols = rtems_rtl_global_symbols (); s = 0; sym = obj->global_table; while ((s < size) && (esyms[s] != 0)) { /* * Copy the void* using a union and memcpy to avoid any strict aliasing or * alignment issues. The variable length of the label and the packed nature * of the table means casting is not suitable. */ union { uint8_t data[sizeof (void*)]; void* value; } copy_voidp; int b; sym->name = (const char*) &esyms[s]; s += strlen (sym->name) + 1; for (b = 0; b < sizeof (void*); ++b, ++s) copy_voidp.data[b] = esyms[s]; sym->value = copy_voidp.value; if (rtems_rtl_trace (RTEMS_RTL_TRACE_GLOBAL_SYM)) printf ("rtl: esyms: %s -> %8p\n", sym->name, sym->value); if (rtems_rtl_symbol_global_find (sym->name) == NULL) rtems_rtl_symbol_global_insert (symbols, sym); ++sym; } obj->global_syms = count; return true; }
bool rtems_rtl_parse_name (const char* name, const char** aname, const char** oname, off_t* ooffset) { const char* laname = NULL; const char* loname = NULL; const char* colon; const char* end; /* * Parse the name to determine if the object file is part of an archive or it * is an object file. If an archive check the name for a '@' to see if the * archive contains an offset. */ end = name + strlen (name); colon = strrchr (name, ':'); if (colon == NULL || colon < strrchr(name, '/')) colon = end; loname = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, colon - name + 1, true); if (!oname) { rtems_rtl_set_error (ENOMEM, "no memory for object file name"); return false; } memcpy ((void*) loname, name, colon - name); /* * If the pointers match there is no ':' delimiter. */ if (colon != end) { const char* at; /* * The file name is an archive and the object file name is next after the * delimiter. Move the pointer to the archive name. */ laname = loname; ++colon; /* * See if there is a '@' to delimit an archive offset for the object in the * archive. */ at = strchr (colon, '@'); if (at == NULL) at = end; loname = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, at - colon + 1, true); if (!loname) { rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) laname); rtems_rtl_set_error (ENOMEM, "no memory for object file name"); return false; } memcpy ((void*) loname, colon, at - colon); if (at != end) { /* * The object name has an archive offset. If the number * does not parse 0 will be returned and the archive will be * searched. */ *ooffset = strtoul (at + 1, 0, 0); } } *oname = loname; *aname = laname; return true; }
bool rtems_rtl_find_file (const char* name, const char* paths, const char** file_name, size_t* size) { struct stat sb; *file_name = NULL; *size = 0; if (rtems_filesystem_is_delimiter (name[0]) || (name[0] == '.')) { if (stat (name, &sb) == 0) *file_name = rtems_rtl_strdup (name); } else if (paths) { const char* start; const char* end; int len; char* fname; start = paths; end = start + strlen (paths); len = strlen (name); while (!*file_name && (start != end)) { const char* delimiter = strchr (start, ':'); if (delimiter == NULL) delimiter = end; /* * Allocate the path fragment, separator, name, terminating nul. Form the * path then see if the stat call works. */ fname = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, (delimiter - start) + 1 + len + 1, true); if (!fname) { rtems_rtl_set_error (ENOMEM, "no memory searching for file"); return false; } memcpy (fname, start, delimiter - start); fname[delimiter - start] = '/'; memcpy (fname + (delimiter - start) + 1, name, len); if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD)) printf ("rtl: find-file: path: %s\n", fname); if (stat (fname, &sb) < 0) rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, fname); else *file_name = fname; start = delimiter; if (start != end) ++start; } } if (!*file_name) return false; *size = sb.st_size; return true; }