source: rtems-tools/linkers/rld-outputter.cpp @ d54e81c

4.104.115
Last change on this file since d54e81c was 803c60a, checked in by Chris Johns <chrisj@…>, on 11/30/12 at 21:05:47

RAP format up to relocation records completed.

Do not write the script into the RAP file rather just write the
init and fini labels. These are appended to the string table and
offsets in the string table added to the image.

Fi the sizes so the sections can be correctly loaded on the target.

  • Property mode set to 100644
File size: 8.8 KB
Line 
1/*
2 * Copyright (c) 2011, Chris Johns <chrisj@rtems.org>
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16/**
17 * @file
18 *
19 * @ingroup rtems_ld
20 *
21 * @brief RTEMS Linker.
22 *
23 */
24
25#if HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29#include <fstream>
30#include <iostream>
31
32#include <errno.h>
33#include <string.h>
34
35#include <rld.h>
36#include <rld-rap.h>
37
38namespace rld
39{
40  namespace outputter
41  {
42    const std::string
43    script_text (const std::string&        entry,
44                 const std::string&        exit,
45                 const files::object_list& dependents,
46                 const files::cache&       cache,
47                 bool                      not_in_archive)
48    {
49      std::ostringstream out;
50      files::object_list objects;
51      files::object_list dep_copy (dependents);
52
53      cache.get_objects (objects);
54      objects.merge (dep_copy);
55      objects.unique ();
56
57      if (rld::verbose () >= RLD_VERBOSE_INFO)
58        std::cout << " E: " << entry << std::endl;
59
60      out << "E: " << entry << std::endl;
61
62      if (!exit.empty ())
63      {
64        if (rld::verbose () >= RLD_VERBOSE_INFO)
65          std::cout << " e: " << exit << std::endl;
66        out << "e: " << exit << std::endl;
67      }
68
69      for (files::object_list::iterator oi = objects.begin ();
70           oi != objects.end ();
71           ++oi)
72      {
73        files::object& obj = *(*oi);
74        std::string    name = obj.name ().basename ();
75
76        if (not_in_archive)
77        {
78          size_t pos = name.find (':');
79          if (pos != std::string::npos)
80            name[pos] = '_';
81          pos = name.find ('@');
82          if (pos != std::string::npos)
83            name = name.substr (0, pos);
84        }
85
86        if (rld::verbose () >= RLD_VERBOSE_INFO)
87          std::cout << " o: " << name << std::endl;
88
89        out << "o:" << name << std::endl;
90
91        symbols::table& unresolved = obj.unresolved_symbols ();
92
93        int count = 0;
94        for (symbols::table::iterator ursi = unresolved.begin ();
95             ursi != unresolved.begin ();
96             ++ursi)
97        {
98          symbols::symbol& urs = *((*ursi).second);
99
100          ++count;
101
102          if (rld::verbose () >= RLD_VERBOSE_INFO)
103            std::cout << " u: " << count << ':' << urs.name () << std::endl;
104
105          out << " u:" << count << ':' << urs.name () << std::endl;
106        }
107      }
108
109      return out.str ();
110    }
111
112    void
113    metadata_object (files::object&            metadata,
114                     const std::string&        entry,
115                     const std::string&        exit,
116                     const files::object_list& dependents,
117                     const files::cache&       cache)
118    {
119      if (rld::verbose () >= RLD_VERBOSE_INFO)
120        std::cout << "metadata: " << metadata.name ().full () << std::endl;
121
122      const std::string script =
123        script_text (entry, exit, dependents, cache, true);
124
125      metadata.open (true);
126      metadata.begin ();
127
128      elf::file& elf = metadata.elf ();
129
130      elf.set_header (ET_EXEC,
131                      elf::object_class (),
132                      elf::object_datatype (),
133                      elf::object_machine_type ());
134
135      elf::section md (elf,
136                       elf.section_count () + 1,
137                       ".rtemsmd",
138                       SHT_STRTAB,
139                       1,
140                       0,
141                       0,
142                       0,
143                       script.length ());
144
145      md.add_data (ELF_T_BYTE,
146                   1,
147                   script.length (),
148                   (void*) script.c_str ());
149
150      elf.add (md);
151      elf.write ();
152
153      metadata.end ();
154      metadata.close ();
155    }
156
157    void
158    archive (const std::string&        name,
159             const std::string&        entry,
160             const std::string&        exit,
161             const files::object_list& dependents,
162             const files::cache&       cache)
163    {
164      if (rld::verbose () >= RLD_VERBOSE_INFO)
165        std::cout << "outputter:archive: " << name
166                  << ", dependents: " << dependents.size () << std::endl;
167
168      std::string ext = files::extension (name);
169      std::string mdname =
170        name.substr (0, name.length () - ext.length ()) + "-metadata.o";
171
172      files::object metadata (mdname);
173
174      metadata_object (metadata, entry, exit, dependents, cache);
175
176      files::object_list dep_copy (dependents);
177      files::object_list objects;
178
179      cache.get_objects (objects);
180      objects.merge (dep_copy);
181      objects.push_front (&metadata);
182      objects.unique ();
183
184      files::archive arch (name);
185      arch.create (objects);
186    }
187
188    void
189    script (const std::string&        name,
190            const std::string&        entry,
191            const std::string&        exit,
192            const files::object_list& dependents,
193            const files::cache&       cache)
194    {
195      if (rld::verbose () >= RLD_VERBOSE_INFO)
196        std::cout << "outputter:script: " << name << std::endl;
197
198      std::fstream out (name.c_str (),
199                        std::ios_base::out | std::ios_base::trunc);
200
201      /*
202       * Tag for the shell to use.
203       */
204      out << "!# rls" << std::endl;
205
206      try
207      {
208        out << script_text (entry, exit, dependents, cache, false);
209      }
210      catch (...)
211      {
212        out.close ();
213        throw;
214      }
215
216      out.close ();
217    }
218
219    void
220    elf_application (const std::string&        name,
221                     const std::string&        entry,
222                     const std::string&        exit,
223                     const files::object_list& dependents,
224                     const files::cache&       cache)
225    {
226      if (rld::verbose () >= RLD_VERBOSE_INFO)
227        std::cout << "outputter:application: " << name << std::endl;
228
229      files::object_list dep_copy (dependents);
230      files::object_list objects;
231      std::string        header;
232      std::string        script;
233      files::image       app (name);
234
235      header = "RELF,00000000,0001,none,00000000\n";
236      header += '\0';
237
238      script = script_text (entry, exit, dependents, cache, true);
239
240      cache.get_objects (objects);
241      objects.merge (dep_copy);
242      objects.unique ();
243
244      app.open (true);
245      app.write (header.c_str (), header.size ());
246
247      #define APP_BUFFER_SIZE  (128 * 1024)
248
249      uint8_t* buffer = 0;
250
251      try
252      {
253        buffer = new uint8_t[APP_BUFFER_SIZE];
254
255        for (files::object_list::iterator oi = objects.begin ();
256             oi != objects.end ();
257             ++oi)
258        {
259          files::object& obj = *(*oi);
260
261          obj.open ();
262
263          try
264          {
265            obj.seek (0);
266
267            size_t in_size = obj.name ().size ();
268
269            while (in_size)
270            {
271              size_t reading =
272                in_size < APP_BUFFER_SIZE ? in_size : APP_BUFFER_SIZE;
273
274              app.write (buffer, obj.read (buffer, reading));
275
276              in_size -= reading;
277            }
278          }
279          catch (...)
280          {
281            obj.close ();
282            throw;
283          }
284
285          obj.close ();
286        }
287      }
288      catch (...)
289      {
290        delete [] buffer;
291        app.close ();
292        throw;
293      }
294
295      delete [] buffer;
296
297      app.close ();
298    }
299
300    void
301    application (const std::string&        name,
302                 const std::string&        entry,
303                 const std::string&        exit,
304                 const files::object_list& dependents,
305                 const files::cache&       cache,
306                 const symbols::table&     symbols)
307    {
308      if (rld::verbose () >= RLD_VERBOSE_INFO)
309        std::cout << "outputter:application: " << name << std::endl;
310
311      files::object_list dep_copy (dependents);
312      files::object_list objects;
313      std::string        header;
314      files::image       app (name);
315
316      header = "RAP,00000000,0001,LZ77,00000000\n";
317
318      cache.get_objects (objects);
319      objects.merge (dep_copy);
320      objects.unique ();
321
322      app.open (true);
323      app.write (header.c_str (), header.size ());
324
325      try
326      {
327        rap::write (app, entry, exit, objects, symbols);
328      }
329      catch (...)
330      {
331        app.close ();
332        throw;
333      }
334
335      app.close ();
336    }
337
338  }
339}
Note: See TracBrowser for help on using the repository browser.