Changeset 803eac9 in rtems


Ignore:
Timestamp:
Nov 13, 2018, 6:26:17 AM (5 months ago)
Author:
Chris Johns <chrisj@…>
Branches:
master
Children:
8e7c72a7
Parents:
69812aa
git-author:
Chris Johns <chrisj@…> (11/13/18 06:26:17)
git-committer:
Chris Johns <chrisj@…> (11/22/18 01:43:21)
Message:

libdl: Manage the allocation of common uninitialised variables.

The use of separate text and data results in uninitialised variables
being placed in the common section. There is no section in ELF for
the common variables so the loader needs to create the section and
allocate the variables in that section. This patch does that.

The patch adds a second pass over the symbols.

The issue can also be seen as a section 65522 error.

Updates #3604

Location:
cpukit
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • cpukit/include/rtems/rtl/rtl-obj.h

    r69812aa r803eac9  
    295295
    296296/**
     297 * Align the size to the next alignment point. Assume the alignment is a
     298 * positive integral power of 2 if not 0 or 1. If 0 or 1 then there is no
     299 * alignment.
     300 *
     301 * @param offset Offset to align up from.
     302 * @param alignment The alignment.
     303 * @return size_t Aligned offset.
     304 */
     305static inline size_t rtems_rtl_obj_align (size_t   offset,
     306                                          uint32_t alignment)
     307{
     308  if ((alignment > 1) && ((offset & (alignment - 1)) != 0))
     309    offset = (offset + alignment) & ~(alignment - 1);
     310  return offset;
     311}
     312
     313/**
    297314 * Allocate an object structure on the heap.
    298315 *
     
    411428
    412429/**
     430 * Find a section given a section's mask. The index is the section after which
     431 * the mask is matched. An index of -1 starts the search from the beginning of
     432 * the section list. You can find multiple matches for a mask by passing the
     433 * index of the last section that matched the mask on a subsequent call.
     434 *
     435 * @param obj The object file's descriptor.
     436 * @param index The section's index to start searching from, -1 for the start.
     437 * @param mask The section's mask to match against the section's flags.
     438 * @retval NULL The section was not found.
     439 * @return rtems_rtl_obj_sect_t* The found section.
     440 */
     441rtems_rtl_obj_sect* rtems_rtl_obj_find_section_by_mask (const rtems_rtl_obj* obj,
     442                                                        int                  index,
     443                                                        uint32_t             mask);
     444
     445/**
    413446 * The text section size. Only use once all the sections has been added. It
    414447 * includes alignments between sections that are part of the object's text
  • cpukit/libdl/rtl-elf.c

    r69812aa r803eac9  
    7373  rtems_rtl_obj_sect* sect;
    7474
    75   if (ELF_ST_TYPE(sym->st_info) == STT_NOTYPE)
     75  if (ELF_ST_TYPE(sym->st_info) == STT_NOTYPE ||
     76      sym->st_shndx == SHN_COMMON)
    7677  {
    7778    /*
     
    186187
    187188    /*
    188      * Only need the name of the symbol if global.
     189     * Only need the name of the symbol if global or a common symbol.
    189190     */
    190     if (ELF_ST_TYPE (sym.st_info) == STT_NOTYPE)
     191    if (ELF_ST_TYPE (sym.st_info) == STT_NOTYPE ||
     192        sym.st_shndx == SHN_COMMON)
    191193    {
    192194      size_t len;
     
    338340}
    339341
     342/**
     343 * Common symbol iterator data.
     344 */
     345typedef struct
     346{
     347  size_t   size;      /**< The size of the common section */
     348  uint32_t alignment; /**< The alignment of the common section. */
     349} rtems_rtl_elf_common_data;
     350
     351static bool
     352rtems_rtl_elf_common (rtems_rtl_obj*      obj,
     353                      int                 fd,
     354                      rtems_rtl_obj_sect* sect,
     355                      void*               data)
     356{
     357  rtems_rtl_elf_common_data* common = (rtems_rtl_elf_common_data*) data;
     358  rtems_rtl_obj_cache*       symbols;
     359  int                        sym;
     360
     361  rtems_rtl_obj_caches (&symbols, NULL, NULL);
     362
     363  if (!symbols)
     364    return false;
     365
     366  /*
     367   * Find the number size of the common section by finding all symbols that
     368   * reference the SHN_COMMON section.
     369   */
     370  for (sym = 0; sym < (sect->size / sizeof (Elf_Sym)); ++sym)
     371  {
     372    Elf_Sym symbol;
     373    off_t   off;
     374
     375    off = obj->ooffset + sect->offset + (sym * sizeof (symbol));
     376
     377    if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off,
     378                                         &symbol, sizeof (symbol)))
     379      return false;
     380
     381    if ((symbol.st_shndx == SHN_COMMON) &&
     382        ((ELF_ST_TYPE (symbol.st_info) == STT_OBJECT) ||
     383         (ELF_ST_TYPE (symbol.st_info) == STT_COMMON)))
     384    {
     385      if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
     386        printf ("rtl: com:elf:%-2d bind:%-2d type:%-2d size:%d value:%d\n",
     387                sym, (int) ELF_ST_BIND (symbol.st_info),
     388                (int) ELF_ST_TYPE (symbol.st_info),
     389                (int) symbol.st_size, (int) symbol.st_value);
     390      /*
     391       * If the size is zero this is the first entry, it defines the common
     392       * section's aligment. The symbol's value is the alignment.
     393       */
     394      if (common->size == 0)
     395        common->alignment = symbol.st_value;
     396      common->size +=
     397        rtems_rtl_obj_align (common->size, symbol.st_value) + symbol.st_size;
     398    }
     399  }
     400
     401  return true;
     402}
     403
    340404static bool
    341405rtems_rtl_elf_symbols (rtems_rtl_obj*      obj,
     
    355419  rtems_rtl_obj_sym*   gsym;
    356420  char*                gstring;
     421  size_t               common_offset;
    357422  int                  sym;
    358423
     
    404469     * we need to make sure there is a valid seciton.
    405470     */
     471    if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
     472      printf ("rtl: sym:elf:%-2d name:%-2d:%-20s bind:%-2d " \
     473              "type:%-2d sect:%d size:%d\n",
     474              sym, (int) symbol.st_name, name,
     475              (int) ELF_ST_BIND (symbol.st_info),
     476              (int) ELF_ST_TYPE (symbol.st_info),
     477              symbol.st_shndx,
     478              (int) symbol.st_size);
     479
    406480    if ((symbol.st_shndx != 0) &&
    407481        ((ELF_ST_TYPE (symbol.st_info) == STT_OBJECT) ||
     482         (ELF_ST_TYPE (symbol.st_info) == STT_COMMON) ||
    408483         (ELF_ST_TYPE (symbol.st_info) == STT_FUNC) ||
    409484         (ELF_ST_TYPE (symbol.st_info) == STT_NOTYPE)))
    410485    {
     486      /*
     487       * There needs to be a valid section for the symbol.
     488       */
    411489      rtems_rtl_obj_sect* symsect;
    412490
    413491      symsect = rtems_rtl_obj_find_section_by_index (obj, symbol.st_shndx);
    414       if (symsect)
     492      if (symsect != NULL)
    415493      {
    416494        if ((ELF_ST_BIND (symbol.st_info) == STB_GLOBAL) ||
     
    432510          else
    433511          {
     512            if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
     513              printf ("rtl: sym:elf:%-2d name:%-2d:%-20s: global\n",
     514                      sym, (int) symbol.st_name, name);
    434515            ++globals;
    435516            global_string_space += strlen (name) + 1;
     
    438519        else if (ELF_ST_BIND (symbol.st_info) == STB_LOCAL)
    439520        {
     521          if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
     522            printf ("rtl: sym:elf:%-2d name:%-2d:%-20s: local\n",
     523                    sym, (int) symbol.st_name, name);
    440524          ++locals;
    441525          local_string_space += strlen (name) + 1;
     
    487571  gstring =
    488572    (((char*) obj->global_table) + (globals * sizeof (rtems_rtl_obj_sym)));
     573
     574  common_offset = 0;
    489575
    490576  for (sym = 0; sym < (sect->size / sizeof (Elf_Sym)); ++sym)
     
    525611    if ((symbol.st_shndx != 0) &&
    526612        ((ELF_ST_TYPE (symbol.st_info) == STT_OBJECT) ||
     613         (ELF_ST_TYPE (symbol.st_info) == STT_COMMON) ||
    527614         (ELF_ST_TYPE (symbol.st_info) == STT_FUNC) ||
    528615         (ELF_ST_TYPE (symbol.st_info) == STT_NOTYPE)) &&
     
    534621        rtems_rtl_obj_sym*  osym;
    535622        char*               string;
     623        Elf_Word            value;
    536624
    537625        symsect = rtems_rtl_obj_find_section_by_index (obj, symbol.st_shndx);
     
    554642          }
    555643
     644          /*
     645           * Allocate any common symbols in the common section.
     646           */
     647          if (symbol.st_shndx == SHN_COMMON)
     648          {
     649            size_t value_off = rtems_rtl_obj_align (common_offset,
     650                                                    symbol.st_value);
     651            common_offset = value_off + symbol.st_size;
     652            value = value_off;
     653          }
     654          else
     655          {
     656            value = symbol.st_value;
     657          }
     658
    556659          rtems_chain_set_off_chain (&osym->node);
    557660          memcpy (string, name, strlen (name) + 1);
    558661          osym->name = string;
    559           osym->value = symbol.st_value + (uint8_t*) symsect->base;
     662          osym->value = value + (uint8_t*) symsect->base;
    560663          osym->data = symbol.st_info;
    561664
     
    657760      return false;
    658761
    659     flags = 0;
    660 
    661762    if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
    662763      printf ("rtl: section: %2d: type=%d flags=%08x link=%d info=%d\n",
    663764              section, (int) shdr.sh_type, (unsigned int) shdr.sh_flags,
    664765              (int) shdr.sh_link, (int) shdr.sh_info);
     766
     767    flags = 0;
    665768
    666769    switch (shdr.sh_type)
     
    769872  }
    770873
     874  return true;
     875}
     876
     877static bool
     878rtems_rtl_elf_add_common (rtems_rtl_obj* obj, size_t size, uint32_t alignment)
     879{
     880  if (size > 0)
     881  {
     882    if (!rtems_rtl_obj_add_section (obj, SHN_COMMON, ".common.rtems.rtl",
     883                                    size, 0, alignment, 0, 0,
     884                                    RTEMS_RTL_OBJ_SECT_BSS | RTEMS_RTL_OBJ_SECT_ZERO))
     885      return false;
     886  }
    771887  return true;
    772888}
     
    9071023rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd)
    9081024{
    909   rtems_rtl_obj_cache* header;
    910   Elf_Ehdr             ehdr;
     1025  rtems_rtl_obj_cache*      header;
     1026  Elf_Ehdr                  ehdr;
     1027  rtems_rtl_elf_common_data common = { .size = 0, .alignment = 0 };
    9111028
    9121029  rtems_rtl_obj_caches (&header, NULL, NULL);
     
    9661083    return false;
    9671084
     1085  /*
     1086   * See if there are any common variables and if there are add a common
     1087   * section.
     1088   */
     1089  if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_common, &common))
     1090    return false;
     1091  if (!rtems_rtl_elf_add_common (obj, common.size, common.alignment))
     1092    return false;
     1093
     1094  /*
     1095   * Set the entry point if there is one.
     1096   */
    9681097  obj->entry = (void*)(uintptr_t) ehdr.e_entry;
    9691098
     1099  /*
     1100   * Load the sections and symbols and then relocation to the base address.
     1101   */
    9701102  if (!rtems_rtl_obj_load_sections (obj, fd, rtems_rtl_elf_loader, &ehdr))
    9711103    return false;
  • cpukit/libdl/rtl-obj.c

    r69812aa r803eac9  
    247247
    248248/**
    249  * Align the size to the next alignment point. Assume the alignment is a
    250  * positive integral power of 2 if not 0 or 1. If 0 or 1 then there is no
    251  * alignment.
    252  */
    253 static size_t
    254 rtems_rtl_sect_align (size_t offset, uint32_t alignment)
    255 {
    256   if ((alignment > 1) && ((offset & (alignment - 1)) != 0))
    257     offset = (offset + alignment) & ~(alignment - 1);
    258   return offset;
    259 }
    260 
    261 /**
    262249 * Section size summer iterator data.
    263250 */
     
    275262  if ((sect->flags & summer->mask) == summer->mask)
    276263    summer->size =
    277       rtems_rtl_sect_align (summer->size, sect->alignment) + sect->size;
     264      rtems_rtl_obj_align (summer->size, sect->alignment) + sect->size;
    278265  return true;
    279266}
     
    439426
    440427    if (rtems_rtl_trace (RTEMS_RTL_TRACE_SECTION))
    441       printf ("rtl: sect: %-2d: %s (%zu)\n", section, name, size);
    442   }
    443 
     428      printf ("rtl: sect: add: %-2d: %s (%zu) 0x%08lx\n",
     429              section, name, size, flags);
     430  }
    444431  return true;
    445432}
     
    468455  const char*          name;  /**< The name to match. */
    469456  int                  index; /**< The index to match. */
     457  uint32_t             mask;  /**< The mask to match. */
     458  unsigned int         flags; /**< The flags to use when matching. */
    470459} rtems_rtl_obj_sect_finder;
    471460
     
    490479  match.sect = NULL;
    491480  match.name = name;
     481  match.mask = 0;
     482  match.flags = 0;
    492483  rtems_rtl_chain_iterate ((rtems_chain_control*) &obj->sections,
    493484                           rtems_rtl_obj_sect_match_name,
     
    516507  match.sect = NULL;
    517508  match.index = index;
     509  match.mask = 0;
     510  match.flags = 0;
    518511  rtems_rtl_chain_iterate ((rtems_chain_control*) &obj->sections,
    519512                           rtems_rtl_obj_sect_match_index,
     513                           &match);
     514  return match.sect;
     515}
     516
     517static bool
     518rtems_rtl_obj_sect_match_mask (rtems_chain_node* node, void* data)
     519{
     520  rtems_rtl_obj_sect*        sect = (rtems_rtl_obj_sect*) node;
     521  rtems_rtl_obj_sect_finder* match = data;
     522  if (match->flags == 0)
     523  {
     524    if (match->index < 0 || sect->section == match->index)
     525      match->flags = 1;
     526    if (match->index >= 0)
     527      return true;
     528  }
     529  if ((sect->flags & match->mask) != 0)
     530  {
     531    match->sect = sect;
     532    return false;
     533  }
     534  return true;
     535}
     536
     537rtems_rtl_obj_sect*
     538rtems_rtl_obj_find_section_by_mask (const rtems_rtl_obj* obj,
     539                                    int                  index,
     540                                    uint32_t             mask)
     541{
     542  rtems_rtl_obj_sect_finder match;
     543  match.sect = NULL;
     544  match.index = index;
     545  match.mask = mask;
     546  match.flags = 0;
     547  rtems_rtl_chain_iterate ((rtems_chain_control*) &obj->sections,
     548                           rtems_rtl_obj_sect_match_mask,
    520549                           &match);
    521550  return match.sect;
     
    776805      {
    777806        if (!first)
    778           base_offset = rtems_rtl_sect_align (base_offset, sect->alignment);
     807          base_offset = rtems_rtl_obj_align (base_offset, sect->alignment);
    779808
    780809        first = false;
Note: See TracChangeset for help on using the changeset viewer.