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;
}
Example #2
0
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, &sect->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 ();
}
Example #4
0
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;
}
Example #5
0
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;
}
Example #6
0
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;
}
Example #7
0
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;
}
Example #8
0
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;
}
Example #9
0
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;
}
Example #10
0
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;
}
Example #11
0
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;
}