Пример #1
0
static bool
rtems_rtl_unresolved_resolve_iterator (rtems_rtl_unresolv_rec_t* rec,
                                       void*                     data)
{
    if (rec->type == rtems_rtl_unresolved_name)
    {
        rtems_rtl_unresolved_reloc_data_t* rd;
        rd = (rtems_rtl_unresolved_reloc_data_t*) data;

        ++rd->name;

        if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
            printf ("rtl: unresolv: lookup: %d: %s\n", rd->name, rec->rec.name.name);

        rd->sym = rtems_rtl_symbol_global_find (rec->rec.name.name);

        if (rd->sym)
        {
            if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
                printf ("rtl: unresolv: found: %s\n", rec->rec.name.name);

            rd->name_rec = rec;

            rtems_rtl_unresolved_interate (rtems_rtl_unresolved_resolve_reloc, rd);

            rd->name_rec = NULL;
            rd->sym = NULL;
        }
    }

    return false;
}
Пример #2
0
static bool
rtems_rtl_unresolved_resolve_reloc (rtems_rtl_unresolv_rec_t* rec,
                                    void*                     data)
{
    if (rec->type == rtems_rtl_unresolved_reloc)
    {
        rtems_rtl_unresolved_reloc_data_t* rd;
        rd = (rtems_rtl_unresolved_reloc_data_t*) data;

        if (rec->rec.reloc.name == rd->name)
        {
            if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
                printf ("rtl: unresolv: resolve reloc: %s\n", rd->name_rec->rec.name.name);

            rtems_rtl_obj_relocate_unresolved (&rec->rec.reloc, rd->sym);

            /*
             * Set the object pointer to NULL to indicate the record is not used
             * anymore. Update the reference count of the name. The sweep after
             * relocating will remove the reloc records with obj set to NULL and
             * names with a reference count of 0.
             */
            rec->rec.reloc.obj = NULL;
            if (rd->name_rec && rd->name_rec->rec.name.refs)
                --rd->name_rec->rec.name.refs;
        }
    }
    return false;
}
Пример #3
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;
}
Пример #4
0
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 ();
}
Пример #5
0
static size_t
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_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))
    {
      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, sect->base, sect->size);

      if ((sect->flags & RTEMS_RTL_OBJ_SECT_LOAD) == RTEMS_RTL_OBJ_SECT_LOAD)
      {
        if (!handler (obj, fd, sect, data))
        {
          sect->base = 0;
          return false;
        }
      }
      else if ((sect->flags & RTEMS_RTL_OBJ_SECT_ZERO) == RTEMS_RTL_OBJ_SECT_ZERO)
      {
        memset (base + base_offset, 0, sect->size);
      }
      else
      {
        sect->base = 0;
        rtems_rtl_set_error (errno, "section has no load op");
        return false;
      }

      base_offset += sect->size;
      first = false;
    }

    node = rtems_chain_next (node);
  }

  return true;
}
Пример #6
0
void
rtems_rtl_unresolved_resolve (void)
{
    rtems_rtl_unresolved_reloc_data_t rd;
    if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
        printf ("rtl: unresolv: global resolve\n");
    rd.name = 0;
    rd.name_rec = NULL;
    rd.sym = NULL;
    rtems_rtl_unresolved_interate (rtems_rtl_unresolved_resolve_iterator, &rd);
    rtems_rtl_unresolved_compact ();
}
Пример #7
0
void
rtems_rtl_alloc_del (rtems_rtl_alloc_tag_t tag, void* address)
{
  rtems_rtl_data_t* rtl = rtems_rtl_lock ();

  if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
    printf ("rtl: alloc: del: %s addr=%p\n",
            rtems_rtl_trace_tag_label (tag), address);

  if (rtl && address)
    rtl->allocator.allocator (false, tag, &address, 0);

  rtems_rtl_unlock ();
}
Пример #8
0
void*
rtems_rtl_alloc_new (rtems_rtl_alloc_tag_t tag, size_t size, bool zero)
{
  rtems_rtl_data_t* rtl = rtems_rtl_lock ();
  void*             address = NULL;

  if (rtl)
    rtl->allocator.allocator (true, tag, &address, size);

  rtems_rtl_unlock ();

  if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
    printf ("rtl: alloc: new: %s addr=%p size=%zu\n",
            rtems_rtl_trace_tag_label (tag), address, size);

  if (zero)
    memset (address, 0, size);

  return address;
}
Пример #9
0
void
rtems_rtl_alloc_indirect_del (rtems_rtl_alloc_tag_t tag,
                              rtems_rtl_ptr_t*      handle)
{
  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: idel: %s handle=%p: is null\n",
              rtems_rtl_trace_tag_label (tag), handle);
    printf ("rtl: alloc: idel: %s handle=%p\n",
            rtems_rtl_trace_tag_label (tag), handle);
  }

  if (rtl && !rtems_rtl_ptr_null (handle))
  {
    rtems_chain_extract_unprotected (&handle->node);
    rtems_rtl_alloc_del (tag, &handle->pointer);
  }
}
Пример #10
0
/*
 * 1. _gp_disp symbol are not considered in this file.
 * 2. There is a local/external column;
 * local corresponds to (STB_LOCAL & STT_SECTION) and
 * all others are external. Because if the type of a
 * symbol is STT_SECTION, it must be STB_LOCAL. Thus
 * just consider symtype here.
 */
bool
rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t*      obj,
                            const Elf_Rel*              rel,
                            const rtems_rtl_obj_sect_t* sect,
                            const char*                 symname,
                            const Elf_Byte              syminfo,
                            const Elf_Word              symvalue)
{
  Elf_Addr *where;
  Elf_Word  tmp;
  Elf_Word addend = (Elf_Word)0;
  Elf_Word local = 0;
  uint32_t t;


  static Elf_Addr *where_hi16;
  static Elf_Addr ahl;

  where = (Elf_Addr *)(sect->base + rel->r_offset);
  addend = *where;

  if (syminfo == STT_SECTION)
    local = 1;

  switch (ELF_R_TYPE(rel->r_info)) {
    case R_TYPE(NONE):
      break;

    case R_TYPE(16):
      tmp = addend & 0xffff;
      if ((tmp & 0x8000) == 0x8000)
        tmp |= 0xffff0000; /* Sign extend */
      tmp = symvalue + (int)tmp;
      if ((tmp & 0xffff0000) != 0) {
        printf("R_MIPS_16 Overflow\n");
        return false;
      }

      *where = (tmp & 0xffff) | (*where & 0xffff0000);

      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
        printf ("rtl: R_MIPS_16 %p @ %p in %s\n",
                (void *)*(where), where, rtems_rtl_obj_oname (obj));
      break;

    case R_TYPE(32):
      tmp = symvalue + addend;
      if (addend != tmp)
        *where = tmp;

      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
        printf ("rtl: R_MIPS_32 %p @ %p in %s\n",
                (void *)*(where), where, rtems_rtl_obj_oname (obj));
      break;

    case R_TYPE(26):

        addend &= 0x03ffffff;
        addend <<= 2;

      if (local == 1) { /* STB_LOCAL and STT_SECTION */
        tmp = symvalue + (((Elf_Addr)where & 0xf0000000) | addend);
        tmp >>= 2;

      } else { /* external */
Пример #11
0
bool
rtems_rtl_unresolved_add (rtems_rtl_obj_t*        obj,
                          const uint16_t          flags,
                          const char*             name,
                          const uint16_t          sect,
                          const rtems_rtl_word_t* rel)
{
    rtems_rtl_unresolved_t* unresolved;
    rtems_chain_node* node;
    rtems_rtl_unresolv_block_t* block;
    rtems_rtl_unresolv_rec_t* rec;
    int name_index;
    size_t name_recs;

    if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
        printf ("rtl: unresolv: add: %s(s:%d) -> %s\n",
                rtems_rtl_obj_oname (obj), sect, name);

    unresolved = rtems_rtl_unresolved ();
    if (!unresolved)
        return false;

    /*
     * Find the first block with a spare record.
     */
    node = rtems_chain_first (&unresolved->blocks);
    block = NULL;
    while (!rtems_chain_is_tail (&unresolved->blocks, node))
    {
        block = (rtems_rtl_unresolv_block_t*) node;
        if (block->recs < unresolved->block_recs)
            break;
        block = NULL;
        node = rtems_chain_next (node);
    }

    /*
     * No blocks with any spare records, allocate a new block.
     */
    if (!block)
    {
        block = rtems_rtl_unresolved_block_alloc (unresolved);
        if (!block)
            return false;
    }

    name_index = rtems_rtl_unresolved_find_name (unresolved, name, true);
    name_recs = rtems_rtl_unresolved_name_recs (name);

    /*
     * An index less than 0 means the name is present and "0 - index" is the next
     * index to use.
     */
    if (name_index < 0)
    {
        rtems_rtl_unresolv_block_t* name_block = block;

        /*
         * Is there enough room to fit the name ? It not add a new block.
         */
        if (name_recs > (unresolved->block_recs - block->recs))
        {
            name_block = rtems_rtl_unresolved_block_alloc (unresolved);
            if (!name_block)
                return false;
        }

        rec = rtems_rtl_unresolved_rec_first_free (name_block);
        rec->type = rtems_rtl_unresolved_name;
        rec->rec.name.refs = 1;
        rec->rec.name.length = strlen (name) + 1;
        memcpy ((void*) &rec->rec.name.name[0], name, rec->rec.name.length + 1);
        block->recs += name_recs;
        name_index = 0 - name_index;

        /*
         * If the name block is the reloc block and it is full allocate a new
         * block for the relocation record.
         */
        if ((block == name_block) && (block->recs >= unresolved->block_recs))
        {
            block = rtems_rtl_unresolved_block_alloc (unresolved);
            if (!block)
                return false;
        }
    }

    rec = rtems_rtl_unresolved_rec_first_free (block);
    rec->type = rtems_rtl_unresolved_reloc;
    rec->rec.reloc.obj = obj;
    rec->rec.reloc.flags = flags;
    rec->rec.reloc.name = name_index;
    rec->rec.reloc.sect = sect;
    rec->rec.reloc.rel[0] = rel[0];
    rec->rec.reloc.rel[1] = rel[1];
    rec->rec.reloc.rel[2] = rel[2];

    ++block->recs;

    return true;
}
Пример #12
0
bool
rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t*      obj,
                             const Elf_Rela*             rela,
                             const rtems_rtl_obj_sect_t* sect,
                             const char*                 symname,
                             const Elf_Byte              syminfo,
                             const Elf_Word              symvalue)
{
  Elf_Addr* where;
  Elf_Word tmp;
  uint32_t mask = 0;
  uint32_t bits = 0;

  where = (Elf_Addr *)(sect->base + rela->r_offset);
  switch (ELF_R_TYPE(rela->r_info)) {
    case R_TYPE(NONE):
      break;

    case R_TYPE(32):
      /*
       * value:1; Field: word32; Expression: S + A
       */
      *where = symvalue + rela->r_addend;
      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
        printf ("rtl: ADDR32 %p @ %p in %s\n",
                (void *)*(where), where, rtems_rtl_obj_oname (obj));
      break;

    case R_TYPE(14):
      /*
       * value:7; Field: low14*; Expression: (S + A) >> 2
       */
    case R_TYPE(24):
      /*
       * value:2; Field: low24*; Expression: (S + A) >> 2
       */
      if (ELF_R_TYPE(rela->r_info) == R_TYPE(14)) {
        bits = 14;
        mask = 0xfffc;
      } else {
        bits = 24;
        mask = 0x3fffffc;
      }
      tmp = (symvalue + rela->r_addend) >> 2;
      if (tmp > ((1<<bits) - 1 )) {
        printf("Overflow ADDR14/ADDR24\n");
        return false;
      }
      tmp = *where;
      tmp &= ~mask;
      tmp |= (symvalue + rela->r_addend) & mask;
      *where = tmp;
      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
        printf ("rtl: ADDR14/ADDR24 %p @ %p in %s\n",
                (void *)*where, where, rtems_rtl_obj_oname (obj));
      break;

    case R_TYPE(16_HA):
      /*
       * value:6; Field:half16; Expression: #ha(S+A)
       */

      tmp = symvalue + rela->r_addend;
      *(uint16_t *)where = (((tmp >> 16) + ((tmp & 0x8000) ? 1: 0)) & 0xffff);
      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
        printf ("rtl: 16_HA %p @ %p in %s\n",
                (void *)*(where), where, rtems_rtl_obj_oname (obj));
      break;

    case R_TYPE(16_HI):
      /*
       * value:5; Field:half16; Expression: #hi(S+A)
       */
      *(uint16_t *)where = ((symvalue + rela->r_addend) >> 16) & 0xffff;
      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
        printf ("rtl: 16_HI %p @ %p in %s\n",
                (void *)*where, where, rtems_rtl_obj_oname (obj));
      break;
    case R_TYPE(16_LO):
      /*
       * value:4; Field:half16; Expression: #lo(S+A)
       */
      *(uint16_t *)where = (symvalue + (rela->r_addend)) & 0xffff;
      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
        printf ("rtl: 16_LO %p @ %p in %s\n",
                (void *)*where, where, rtems_rtl_obj_oname (obj));
      break;

    case R_TYPE(REL14):
      /*
       * value:11; Field:low14*; Expression:(S+A-P)>>2
       */
    case R_TYPE(REL24):
      /*
       * value:10; Field:low24*; Expression:(S+A-P)>>2
       */
      if (ELF_R_TYPE(rela->r_info) == R_TYPE(REL24)) {
        mask = 0x3fffffc;
        bits = 24;
      }
      else if (ELF_R_TYPE(rela->r_info) == R_TYPE(REL14)) {
        mask = 0xfffc;
        bits = 14;
      }

      tmp =((int) (symvalue + rela->r_addend - (Elf_Addr)where)) >> 2;
      if (((Elf_Sword)tmp > ((1<<(bits-1)) - 1)) ||
          ((Elf_Sword)tmp < -(1<<(bits-1)))) {
        printf("Overflow REL14/REL24\n");
        return false;
      }

      tmp = *where;
      tmp &= ~mask;
      tmp |= (symvalue + rela->r_addend - (Elf_Addr)where) & mask;
      *where = tmp;
      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
        printf ("rtl: REL24/REL14 %p @ %p in %s\n",
                (void *)*where, where, rtems_rtl_obj_oname (obj));
      break;

    case R_TYPE(REL32):
      /*
       * value:26; Field:word32*; Expression:S+A-P
       */
      *where = symvalue + rela->r_addend - (Elf_Addr)where;
      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
        printf ("rtl: REL32 %p @ %p in %s\n",
                (void *)*where, where, rtems_rtl_obj_oname (obj));
      break;

    default:
      printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, "
              "contents = %p\n",
              ELF_R_SYM(rela->r_info), (uint32_t) ELF_R_TYPE(rela->r_info),
              (void *)rela->r_offset, (void *)*where);
      rtems_rtl_set_error (EINVAL,
                           "%s: Unsupported relocation type %ld "
                           "in non-PLT relocations",
                           sect->name, (uint32_t) ELF_R_TYPE(rela->r_info));
      return false;
  }
  return true;
}
Пример #13
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;
}
Пример #14
0
bool
rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t*      obj,
                            const Elf_Rel*              rel,
                            const rtems_rtl_obj_sect_t* sect,
                            const char*                 symname,
                            const Elf_Byte              syminfo,
                            const Elf_Word              symvalue)
{
	Elf_Addr  target = 0;
  Elf_Addr* where;
  Elf_Addr  tmp;

  where = (Elf_Addr *)(sect->base + rel->r_offset);

  switch (ELF_R_TYPE(rel->r_info)) {
    case R_TYPE(NONE):
      break;

    case R_TYPE(PC32):
      target = (Elf_Addr) symvalue;
      *where += target - (Elf_Addr)where;

      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
        printf ("rtl: reloc PC32 in %s --> %p (%p @ %p) in %s\n",
                sect->name, (void*) symvalue,
                (void *)*where, where, rtems_rtl_obj_oname (obj));
      break;

    case R_TYPE(GOT32):
    case R_TYPE(32):
    case R_TYPE(GLOB_DAT):
      target = (Elf_Addr) symvalue;

      tmp = target + *where;
      if (*where != tmp)
        *where = tmp;
      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
        printf ("rtl: reloc 32/GLOB_DAT in %s --> %p @ %p in %s\n",
                sect->name, (void *)*where, where,
                rtems_rtl_obj_oname (obj));
      break;

    case R_TYPE(RELATIVE):
      *where += (Elf_Addr)sect->base;
      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
        printf ("rtl: reloc RELATIVE in %s --> %p @ %p\n",
                rtems_rtl_obj_oname (obj), (void *)*where, where);
      break;

    case R_TYPE(COPY):
      printf ("rtl: reloc COPY (please report)\n");
      break;

    default:
      printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, "
              "contents = %p\n",
              ELF_R_SYM(rel->r_info), (uint32_t) ELF_R_TYPE(rel->r_info),
              (void *)rel->r_offset, (void *)*where);
      rtems_rtl_set_error (EINVAL,
                           "%s: Unsupported relocation type %ld "
                           "in non-PLT relocations",
                           sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
      return false;
  }

  return true;
}
Пример #15
0
bool
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;
  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);
  data_size  = rtems_rtl_obj_data_size (obj) + rtems_rtl_obj_bss_alignment (obj);
  bss_size   = rtems_rtl_obj_bss_size (obj);

  /*
   * 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->data_base, data_size,
                                   &obj->bss_base, bss_size))
  {
    obj->exec_size = 0;
    rtems_rtl_set_error (ENOMEM, "no memory to load obj");
    return false;
  }

  obj->exec_size = text_size + const_size + data_size + bss_size;

  if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
  {
    printf ("rtl: load sect: text  - b:%p s:%zi a:%" PRIu32 "\n",
            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: 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",
            obj->bss_base, bss_size, rtems_rtl_obj_bss_alignment (obj));
  }

  /*
   * 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 (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);
    obj->exec_size = 0;
    return false;
  }

  return true;
}
Пример #16
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;
}