Changeset 544de91 in rtems-tools for linkers


Ignore:
Timestamp:
Dec 28, 2012, 11:20:22 PM (7 years ago)
Author:
Chris Johns <chrisj@…>
Branches:
4.10, 4.11, master
Children:
06a2cf6
Parents:
800d4fd
Message:

Fix managing weak symbols.

Weak symbols where not being managed correctly. The symbols table
is now a class with externals and weaks as separate symtabs so
the externals can be searched first then the weaks and if not
found an unresolved error is raised. This was found creating
a libbsdport RAP file where the drivers in the all driver table
resolved to the weak symbols and so linking in nothing.

Fixing the weak symbols as found in the libbsdport library
triggered a new resolver bug. The object files now contain the
resolver state and this is used to determine if an object file
has been resolved or is currently being resolved avoiding
rescursive loops with dependent object files.

The resolver trace output is a little easier to read.

Location:
linkers
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • linkers/rld-elf.cpp

    r800d4fd r544de91  
    854854            add = true;
    855855        }
    856         else if (!unresolved)
     856        else
    857857        {
    858858          if (((stype == STT_NOTYPE) ||
    859859               (stype == STT_OBJECT) ||
    860860               (stype == STT_FUNC)) &&
    861               ((local && (sbind == STB_LOCAL)) ||
    862                   (weak && (sbind == STB_WEAK)) ||
    863                (global && (sbind == STB_GLOBAL))))
     861              ((weak && (sbind == STB_WEAK)) ||
     862               (!unresolved && ((local && (sbind == STB_LOCAL)) ||
     863                                (global && (sbind == STB_GLOBAL))))))
    864864            add = true;
    865865        }
  • linkers/rld-files.cpp

    r800d4fd r544de91  
    980980      : image (name_),
    981981        archive_ (&archive_),
    982         valid_ (false)
     982        valid_ (false),
     983        resolving_ (false),
     984        resolved_ (false)
    983985    {
    984986      if (!name ().is_valid ())
     
    989991      : image (path),
    990992        archive_ (0),
    991         valid_ (false)
     993        valid_ (false),
     994        resolving_ (false),
     995        resolved_ (false)
    992996    {
    993997      if (!name ().is_valid ())
     
    9971001    object::object ()
    9981002      : archive_ (0),
    999         valid_ (false)
     1003        valid_ (false),
     1004        resolving_ (false),
     1005        resolved_ (false)
    10001006    {
    10011007    }
     
    11171123      rld::symbols::pointers syms;
    11181124
    1119       elf ().get_symbols (syms, false, local);
     1125      elf ().get_symbols (syms, false, local, false, true);
    11201126
    11211127      if (rld::verbose () >= RLD_VERBOSE_TRACE_SYMS)
     
    11331139
    11341140        sym.set_object (*this);
    1135         symbols[sym.name ()] = &sym;
     1141        symbols.add_external (sym);
    11361142        externals.push_back (&sym);
    11371143      }
    11381144
    1139       elf ().get_symbols (syms, true);
     1145      elf ().get_symbols (syms, false, false, true, false);
     1146
     1147      if (rld::verbose () >= RLD_VERBOSE_TRACE_SYMS)
     1148        std::cout << "object:load-sym: weak: total "
     1149                  << syms.size () << std::endl;
     1150
     1151      for (symbols::pointers::iterator si = syms.begin ();
     1152           si != syms.end ();
     1153           ++si)
     1154      {
     1155        symbols::symbol& sym = *(*si);
     1156
     1157        if (rld::verbose () >= RLD_VERBOSE_TRACE_SYMS)
     1158          std::cout << "object:load-sym: weak: " << sym << std::endl;
     1159
     1160        sym.set_object (*this);
     1161        symbols.add_weak (sym);
     1162        externals.push_back (&sym);
     1163      }
     1164
     1165      elf ().get_symbols (syms, true, false, true, true);
    11401166
    11411167      if (rld::verbose () >= RLD_VERBOSE_TRACE_SYMS)
     
    12161242    }
    12171243
    1218     rld::symbols::table&
     1244    rld::symbols::symtab&
    12191245    object::unresolved_symbols ()
    12201246    {
     
    12801306      throw rld::error ("Section index '" + rld::to_string (index) +
    12811307                        "' not found: " + name ().full (), "object::get-section");
     1308    }
     1309
     1310    void
     1311    object::resolve_set ()
     1312    {
     1313      resolving_ = true;
     1314    }
     1315
     1316    void
     1317    object::resolve_clear ()
     1318    {
     1319      resolving_ = false;
     1320    }
     1321
     1322    bool
     1323    object::resolving () const
     1324    {
     1325      return resolving_;
     1326    }
     1327
     1328    void
     1329    object::resolved_set ()
     1330    {
     1331      resolved_ = true;
     1332    }
     1333
     1334    bool
     1335    object::resolved () const
     1336    {
     1337      return resolved_;
    12821338    }
    12831339
  • linkers/rld-files.h

    r800d4fd r544de91  
    5757     * Container of archive files.
    5858     */
    59     typedef std::map < std::string, archive* > archives;
     59    typedef std::map < const std::string, archive* > archives;
    6060
    6161    /**
    6262     * Container of object files.
    6363     */
    64     typedef std::map < std::string, object* > objects;
     64    typedef std::map < const std::string, object* > objects;
    6565
    6666    /**
     
    701701       * Return the unresolved symbol table for this object file.
    702702       */
    703       symbols::table& unresolved_symbols ();
     703      symbols::symtab& unresolved_symbols ();
    704704
    705705      /**
     
    742742      const section& get_section (int index) const;
    743743
     744      /**
     745       * Set the object file's resolving flag.
     746       */
     747      void resolve_set ();
     748
     749      /**
     750       * Clear the object file's resolving flag.
     751       */
     752      void resolve_clear ();
     753
     754      /**
     755       * The resolving state.
     756       */
     757      bool resolving () const;
     758
     759      /**
     760       * Set the object file resolved flag.
     761       */
     762      void resolved_set ();
     763
     764      /**
     765       * The resolved state.
     766       */
     767      bool resolved () const;
     768
    744769    private:
    745770      archive*          archive_;   //< Points to the archive if part of an
    746771                                    //  archive.
    747772      bool              valid_;     //< If true begin has run and finished.
    748       symbols::table    unresolved; //< This object's unresolved symbols.
     773      symbols::symtab   unresolved; //< This object's unresolved symbols.
    749774      symbols::pointers externals;  //< This object's external symbols.
    750775      sections          secs;       //< The sections.
     776      bool              resolving_; //< The object is being resolved.
     777      bool              resolved_;  //< The object has been resolved.
    751778
    752779      /**
  • linkers/rld-outputter.cpp

    r800d4fd r544de91  
    8989        out << "o:" << name << std::endl;
    9090
    91         symbols::table& unresolved = obj.unresolved_symbols ();
     91        symbols::symtab& unresolved = obj.unresolved_symbols ();
    9292
    9393        int count = 0;
    94         for (symbols::table::iterator ursi = unresolved.begin ();
     94        for (symbols::symtab::iterator ursi = unresolved.begin ();
    9595             ursi != unresolved.begin ();
    9696             ++ursi)
  • linkers/rld-resolver.cpp

    r800d4fd r544de91  
    3939  namespace resolver
    4040  {
     41    static files::object*
     42    get_object (files::cache&      cache,
     43                const std::string& fullname)
     44    {
     45      files::objects&          objects = cache.get_objects ();
     46      files::objects::iterator oi = objects.find (fullname);
     47      if (oi == objects.end ())
     48        return 0;
     49      return (*oi).second;
     50    }
     51
    4152    static void
    42     resolve_symbols (rld::files::object_list& dependents,
    43                      rld::files::cache&       cache,
    44                      rld::symbols::table&     base_symbols,
    45                      rld::symbols::table&     symbols,
    46                      rld::symbols::table&     unresolved,
    47                      const std::string&       name)
     53    resolve_symbols (files::object_list& dependents,
     54                     files::cache&       cache,
     55                     symbols::table&     base_symbols,
     56                     symbols::table&     symbols,
     57                     symbols::symtab&    unresolved,
     58                     const std::string&  fullname)
    4859    {
     60      const std::string name = files::basename (fullname);
     61
    4962      static int nesting = 0;
    5063
     
    5972       * 'es' is the exported symbol.
    6073       */
     74
     75      files::object* object = get_object (cache, fullname);
     76
     77      if (object)
     78      {
     79        if (object->resolved () || object->resolving ())
     80        {
     81          if (rld::verbose () >= RLD_VERBOSE_INFO)
     82            std::cout << "resolver:resolving: "
     83                      << std::setw (nesting - 1) << ' '
     84                      << name
     85                      << " is resolved or resolving"
     86                      << std::endl;
     87          return;
     88        }
     89        object->resolve_set ();
     90      }
    6191
    6292      if (rld::verbose () >= RLD_VERBOSE_INFO)
     
    6898                  << std::endl;
    6999
    70       rld::files::object_list objects;
    71 
    72       for (rld::symbols::table::iterator ursi = unresolved.begin ();
    73            (ursi != unresolved.end ()) && !((*ursi).second)->object ();
     100      files::object_list objects;
     101
     102      for (symbols::symtab::iterator ursi = unresolved.begin ();
     103           ursi != unresolved.end ();
    74104           ++ursi)
    75105      {
    76         rld::symbols::symbol&         urs = *((*ursi).second);
    77         rld::symbols::table::iterator esi = base_symbols.find (urs.name ());
    78         bool                          base = true;
     106        symbols::symbol& urs = *((*ursi).second);
     107
     108        if ((urs.binding () != STB_WEAK) && urs.object ())
     109          continue;
     110
     111        symbols::symbol* es = base_symbols.find_external (urs.name ());
     112        bool             base = true;
    79113
    80114        if (rld::verbose () >= RLD_VERBOSE_INFO)
     
    82116          std::cout << "resolver:resolve  : "
    83117                    << std::setw (nesting + 1) << ' '
    84                     << urs.name () << std::endl;
    85         }
    86 
    87         if (esi == base_symbols.end ())
    88         {
    89           esi = symbols.find (urs.name ());
    90           if (esi == symbols.end ())
    91             throw rld::error ("symbol not found: " + urs.name (), name);
     118                    << " |- " << urs.name () << std::endl;
     119        }
     120
     121        if (!es)
     122        {
     123          es = symbols.find_external (urs.name ());
     124          if (!es)
     125          {
     126            es = symbols.find_weak (urs.name ());
     127            if (!es)
     128              throw rld::error ("symbol not found: " + urs.name (), name);
     129          }
    92130          base = false;
    93131        }
    94132
    95         rld::symbols::symbol& es = *((*esi).second);
     133        symbols::symbol& esym = *es;
    96134
    97135        if (rld::verbose () >= RLD_VERBOSE_INFO)
     
    99137          std::cout << "resolver:resolved : "
    100138                    << std::setw (nesting + 1) << ' '
    101                     << urs.name ()
    102                     << " -> ";
    103           if (es.object())
    104             std::cout << es.object()->name ().basename ();
     139                    << " |   `--> ";
     140          if (esym.object())
     141          {
     142            std::cout << esym.object()->name ().basename ();
     143            if (esym.object()->resolving ())
     144              std::cout << " (resolving)";
     145            else if (esym.object()->resolved ())
     146              std::cout << " (resolved)";
     147            else if (base)
     148              std::cout << " (base)";
     149            else
     150              std::cout << " (unresolved: " << objects.size () + 1 << ')';
     151          }
    105152          else
    106153            std::cout << "null";
     
    110157        if (!base)
    111158        {
    112           urs.set_object (*es.object ());
    113           objects.push_back (es.object ());
    114         }
    115 
    116         es.referenced ();
    117       }
    118 
    119       /*
    120        * Recurse into any references object files. First remove any duplicate
    121        * entries.
    122        */
    123       objects.unique ();
    124 
    125       for (rld::files::object_list::iterator oli = objects.begin ();
     159          files::object& eobj = *esym.object ();
     160          urs.set_object (eobj);
     161          if (!eobj.resolved () && !eobj.resolving ())
     162          {
     163            objects.push_back (&eobj);
     164            objects.unique ();
     165          }
     166        }
     167
     168        esym.referenced ();
     169      }
     170
     171      if (object)
     172      {
     173        object->resolve_clear ();
     174        object->resolved_set ();
     175      }
     176
     177      /*
     178       * Recurse into any references object files.
     179       */
     180
     181      if (rld::verbose () >= RLD_VERBOSE_INFO)
     182        std::cout << "resolver:resolved : "
     183                  << std::setw (nesting + 1) << ' '
     184                  << " +-- referenced objects: " << objects.size ()
     185                  << std::endl;
     186
     187      for (files::object_list::iterator oli = objects.begin ();
    126188           oli != objects.end ();
    127189           ++oli)
    128190      {
    129         rld::files::object& object = *(*oli);
    130         if (rld::verbose () >= RLD_VERBOSE_INFO)
    131           std::cout << "resolver:resolving:    : "
    132                     << object.name ().basename () << std::endl;
     191        files::object& obj = *(*oli);
     192        if (rld::verbose () >= RLD_VERBOSE_INFO)
     193          std::cout << "resolver:resolving: "
     194                    << std::setw (nesting) << ' '
     195                    << "] " << name << " ==> "
     196                    << obj.name ().basename () << std::endl;
    133197        resolve_symbols (dependents, cache, base_symbols, symbols,
    134                          object.unresolved_symbols (),
    135                          object.name ().basename ());
     198                         obj.unresolved_symbols (),
     199                         obj.name ().full ());
    136200      }
    137201
     
    143207
    144208    void
    145     resolve (rld::files::object_list& dependents,
    146              rld::files::cache&       cache,
    147              rld::symbols::table&     base_symbols,
    148              rld::symbols::table&     symbols,
    149              rld::symbols::table&     undefined)
     209    resolve (files::object_list& dependents,
     210             files::cache&       cache,
     211             symbols::table&     base_symbols,
     212             symbols::table&     symbols,
     213             symbols::symtab&    undefined)
    150214    {
    151       rld::files::object_list objects;
     215      files::object_list objects;
    152216      cache.get_objects (objects);
    153217
     
    162226       * Resolve the symbols in the object files.
    163227       */
    164       for (rld::files::object_list::iterator oi = objects.begin ();
     228      for (files::object_list::iterator oi = objects.begin ();
    165229           oi != objects.end ();
    166230           ++oi)
    167231      {
    168         rld::files::object& object = *(*oi);
     232        files::object& object = *(*oi);
    169233        if (rld::verbose () >= RLD_VERBOSE_INFO)
    170234          std::cout << "resolver:resolving: top: "
     
    172236        resolver::resolve_symbols (dependents, cache, base_symbols, symbols,
    173237                                   object.unresolved_symbols (),
    174                                    object.name ().basename ());
     238                                   object.name ().full ());
    175239      }
    176240    }
  • linkers/rld-resolver.h

    r800d4fd r544de91  
    11/*
    2  * Copyright (c) 2011, Chris Johns <chrisj@rtems.org> 
     2 * Copyright (c) 2011, Chris Johns <chrisj@rtems.org>
    33 *
    44 * Permission to use, copy, modify, and/or distribute this software for any
    55 * purpose with or without fee is hereby granted, provided that the above
    66 * copyright notice and this permission notice appear in all copies.
    7  * 
     7 *
    88 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    99 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     
    4444     *                  added for.
    4545     */
    46     void resolve (rld::files::object_list& dependents,
    47                   rld::files::cache&       cache,
    48                   rld::symbols::table&     base_symbols,
    49                   rld::symbols::table&     symbols,
    50                   rld::symbols::table&     undefined);
     46    void resolve (files::object_list& dependents,
     47                  files::cache&       cache,
     48                  symbols::table&     base_symbols,
     49                  symbols::table&     symbols,
     50                  symbols::symtab&    undefined);
    5151  }
    5252}
  • linkers/rld-symbols.cpp

    r800d4fd r544de91  
    267267    }
    268268
     269    table::table ()
     270    {
     271    }
     272
     273    table::~table ()
     274    {
     275    }
     276
     277    void
     278    table::add_external (symbol& sym)
     279    {
     280      _externals[sym.name ()] = &sym;
     281    }
     282
     283    void
     284    table::add_weak (symbol& sym)
     285    {
     286      _weaks[sym.name ()] = &sym;
     287    }
     288
     289    symbol*
     290    table::find_external (const std::string& name)
     291    {
     292      symtab::iterator sti = _externals.find (name);
     293      if (sti == _externals.end ())
     294        return 0;
     295      return (*sti).second;
     296    }
     297
     298    symbol*
     299    table::find_weak (const std::string& name)
     300    {
     301      symtab::iterator sti = _weaks.find (name);
     302      if (sti == _weaks.end ())
     303        return 0;
     304      return (*sti).second;
     305    }
     306
     307    size_t
     308    table::size () const
     309    {
     310      return _externals.size () + _weaks.size ();
     311    }
     312
     313    const symtab&
     314    table::externals () const
     315    {
     316      return _externals;
     317    }
     318
     319    const symtab&
     320    table::weaks () const
     321    {
     322      return _weaks;
     323    }
     324
    269325    void
    270326    load (bucket& bucket_, table& table_)
     327    {
     328      for (bucket::iterator sbi = bucket_.begin ();
     329           sbi != bucket_.end ();
     330           ++sbi)
     331      {
     332        table_.add_external (*sbi);
     333      }
     334    }
     335
     336    void
     337    load (bucket& bucket_, symtab& table_)
    271338    {
    272339      for (bucket::iterator sbi = bucket_.begin ();
     
    298365    output (std::ostream& out, const table& symbols)
    299366    {
     367      out << "Externals:" << std::endl;
     368      output (out, symbols.externals ());
     369      out << "Weaks:" << std::endl;
     370      output (out, symbols.weaks ());
     371    }
     372
     373    void
     374    output (std::ostream& out, const symtab& symbols)
     375    {
    300376      std::cout << " No.  Scope      Type        Address    Size    Name" << std::endl;
    301377      int index = 0;
    302       for (table::const_iterator si = symbols.begin ();
     378      for (symtab::const_iterator si = symbols.begin ();
    303379           si != symbols.end ();
    304380           ++si)
  • linkers/rld-symbols.h

    r800d4fd r544de91  
    188188     * symbols held in a bucket.
    189189     */
    190     typedef std::map < std::string, symbol* > table;
     190    typedef std::map < std::string, symbol* > symtab;
     191
     192    /**
     193     * A symbols contains a symbol table of externals and weak symbols.
     194     */
     195    class table
     196    {
     197    public:
     198      /**
     199       * Construct a table.
     200       */
     201      table ();
     202
     203      /**
     204       * Destruct a table.
     205       */
     206      ~table ();
     207
     208      /**
     209       * Add an external symbol.
     210       */
     211      void add_external (symbol& sym);
     212
     213      /**
     214       * Add a weak symbol.
     215       */
     216      void add_weak (symbol& sym);
     217
     218      /**
     219       * Find an external symbol.
     220       */
     221      symbol* find_external (const std::string& name);
     222
     223      /**
     224       * Find an weak symbol.
     225       */
     226      symbol* find_weak (const std::string& name);
     227
     228      /**
     229       * Return the size of the symbols loaded.
     230       */
     231      size_t size () const;
     232
     233      /**
     234       * Return the externals symbol table.
     235       */
     236      const symtab& externals () const;
     237
     238      /**
     239       * Return the weaks symbol table.
     240       */
     241      const symtab& weaks () const;
     242
     243    private:
     244
     245      /**
     246       * Cannot copy a table.
     247       */
     248      table (const table& orig);
     249
     250      /**
     251       * A table of external symbols.
     252       */
     253      symtab _externals;
     254
     255      /**
     256       * A table of weak symbols.
     257       */
     258      symtab _weaks;
     259    };
    191260
    192261    /**
     
    196265
    197266    /**
     267     * Load a table from a buckey.
     268     */
     269    void load (bucket& bucket_, symtab& table_);
     270
     271    /**
    198272     * Given a container of symbols return how many are referenced.
    199273     */
     
    204278     */
    205279    void output (std::ostream& out, const table& symbols);
     280
     281    /**
     282     * Output the symbol table.
     283     */
     284    void output (std::ostream& out, const symtab& symbols);
    206285  }
    207286}
  • linkers/rtems-ld.cpp

    r800d4fd r544de91  
    171171    rld::symbols::table  base_symbols;
    172172    rld::symbols::table  symbols;
    173     rld::symbols::table undefined;
     173    rld::symbols::symtab undefined;
    174174    std::string          entry = "rtems";
    175175    std::string          exit;
Note: See TracChangeset for help on using the changeset viewer.