1 | /* |
---|
2 | * Copyright (c) 2012, 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 | * @todo Set the RAP alignment as the max of all alignments. |
---|
24 | */ |
---|
25 | |
---|
26 | #if HAVE_CONFIG_H |
---|
27 | #include "config.h" |
---|
28 | #endif |
---|
29 | |
---|
30 | #include <string.h> |
---|
31 | |
---|
32 | #include <algorithm> |
---|
33 | #include <list> |
---|
34 | #include <iomanip> |
---|
35 | |
---|
36 | #include <rld.h> |
---|
37 | #include <rld-compression.h> |
---|
38 | #include <rld-rap.h> |
---|
39 | |
---|
40 | namespace rld |
---|
41 | { |
---|
42 | namespace rap |
---|
43 | { |
---|
44 | |
---|
45 | /** |
---|
46 | * Output details or not. |
---|
47 | */ |
---|
48 | bool add_obj_details = true; |
---|
49 | |
---|
50 | /** |
---|
51 | * Store the path of object files. |
---|
52 | */ |
---|
53 | std::string rpath; |
---|
54 | |
---|
55 | /** |
---|
56 | * The names of the RAP sections. |
---|
57 | */ |
---|
58 | static const char* section_names[rap_secs] = |
---|
59 | { |
---|
60 | ".text", |
---|
61 | ".const", |
---|
62 | ".ctor", |
---|
63 | ".dtor", |
---|
64 | ".data", |
---|
65 | ".bss" |
---|
66 | }; |
---|
67 | |
---|
68 | /** |
---|
69 | * RAP relocation record. This one does not have const fields. |
---|
70 | */ |
---|
71 | struct relocation |
---|
72 | { |
---|
73 | uint32_t offset; //< The offset in the section to apply the fixup. |
---|
74 | uint32_t info; //< The ELF info record. |
---|
75 | uint32_t addend; //< The ELF constant addend. |
---|
76 | std::string symname; //< The symbol name if there is one. |
---|
77 | uint32_t symtype; //< The type of symbol. |
---|
78 | int symsect; //< The symbol's RAP section. |
---|
79 | uint32_t symvalue; //< The symbol's default value. |
---|
80 | uint32_t symbinding;//< The symbol's binding. |
---|
81 | |
---|
82 | /** |
---|
83 | * Construct the relocation using the file relocation, the offset of the |
---|
84 | * section in the target RAP section and the RAP section of the symbol. |
---|
85 | */ |
---|
86 | relocation (const files::relocation& reloc, const uint32_t offset); |
---|
87 | }; |
---|
88 | |
---|
89 | /** |
---|
90 | * Relocation records. |
---|
91 | */ |
---|
92 | typedef std::vector < relocation > relocations; |
---|
93 | |
---|
94 | /** |
---|
95 | * Relocation symname sorter for the relocations container. |
---|
96 | */ |
---|
97 | class reloc_symname_compare |
---|
98 | { |
---|
99 | public: |
---|
100 | bool operator () (const relocation& lhs, |
---|
101 | const relocation& rhs) const { |
---|
102 | return lhs.symname < rhs.symname; |
---|
103 | } |
---|
104 | }; |
---|
105 | |
---|
106 | /** |
---|
107 | * Relocation offset sorter for the relocations container. |
---|
108 | */ |
---|
109 | class reloc_offset_compare |
---|
110 | { |
---|
111 | public: |
---|
112 | bool operator () (const relocation& lhs, |
---|
113 | const relocation& rhs) const { |
---|
114 | if (lhs.symname == rhs.symname) |
---|
115 | return lhs.offset < rhs.offset; |
---|
116 | else return false; |
---|
117 | } |
---|
118 | }; |
---|
119 | |
---|
120 | /** |
---|
121 | * An object section's offset, size and alignment. |
---|
122 | */ |
---|
123 | struct osection |
---|
124 | { |
---|
125 | std::string name; //< The name of the section. |
---|
126 | uint32_t offset; //< The offset in the object file. |
---|
127 | uint32_t size; //< The size of this section. |
---|
128 | uint32_t align; //< The alignment. |
---|
129 | uint32_t relocs; //< The number of relocations. |
---|
130 | uint64_t flags; //< The flags. |
---|
131 | |
---|
132 | /** |
---|
133 | * Construct the object section. |
---|
134 | */ |
---|
135 | osection (const std::string& name, |
---|
136 | uint32_t offset, |
---|
137 | uint32_t size, |
---|
138 | uint32_t align, |
---|
139 | uint32_t relocs, |
---|
140 | uint64_t flags); |
---|
141 | |
---|
142 | /** |
---|
143 | * Default constructor. |
---|
144 | */ |
---|
145 | osection (); |
---|
146 | }; |
---|
147 | |
---|
148 | /** |
---|
149 | * Map of object file section offsets keyed by the object file section |
---|
150 | * index. This is used when adding the external symbols so the symbol's |
---|
151 | * value can be adjusted by the offset of the section in the RAP section. |
---|
152 | */ |
---|
153 | typedef std::map < const int, osection > osections; |
---|
154 | |
---|
155 | /** |
---|
156 | * An ordered container of object section indexes. We need the same |
---|
157 | * order so the alignments match up with the layout. |
---|
158 | */ |
---|
159 | typedef std::vector < int > osecindexes; |
---|
160 | |
---|
161 | /** |
---|
162 | * Section detail will be written into RAP file |
---|
163 | */ |
---|
164 | struct section_detail |
---|
165 | { |
---|
166 | uint32_t name; //< The offset in the strtable. |
---|
167 | uint32_t offset; //< The offset in the rap section. |
---|
168 | uint32_t id; //< The rap id. |
---|
169 | uint32_t size; //< The size of the section. |
---|
170 | |
---|
171 | /* Constructor */ |
---|
172 | section_detail (uint32_t name, uint32_t offset, uint32_t id, uint32_t size); |
---|
173 | }; |
---|
174 | |
---|
175 | /* |
---|
176 | * A container of section detail |
---|
177 | */ |
---|
178 | typedef std::list < section_detail > section_details; |
---|
179 | |
---|
180 | /** |
---|
181 | * The RAP section data. |
---|
182 | */ |
---|
183 | struct section |
---|
184 | { |
---|
185 | std::string name; //< The name of the section. |
---|
186 | uint32_t offset; //< The offset of the section. |
---|
187 | bool rela; //< The relocation record has an addend field. |
---|
188 | relocations relocs; //< The relocations for this section. |
---|
189 | osections osecs; //< The object section index. |
---|
190 | osecindexes osindexes; //< The object section indexes in order. |
---|
191 | |
---|
192 | /** |
---|
193 | * Default constructor. |
---|
194 | */ |
---|
195 | section (); |
---|
196 | |
---|
197 | /** |
---|
198 | * Clear the section. |
---|
199 | */ |
---|
200 | void clear (); |
---|
201 | |
---|
202 | /** |
---|
203 | * The size of the section given the offset. |
---|
204 | */ |
---|
205 | uint32_t size (uint32_t offset = 0) const; |
---|
206 | |
---|
207 | /** |
---|
208 | * The alignment of the first section. |
---|
209 | */ |
---|
210 | uint32_t alignment () const; |
---|
211 | |
---|
212 | /** |
---|
213 | * The alignment of the object section given its index. |
---|
214 | */ |
---|
215 | uint32_t alignment (int index) const; |
---|
216 | |
---|
217 | /** |
---|
218 | * Set the offset of this section based on the previous section. |
---|
219 | */ |
---|
220 | void set_offset (const section& sec); |
---|
221 | |
---|
222 | /** |
---|
223 | * Return the object section given the index. |
---|
224 | */ |
---|
225 | const osection& get_osection (int index) const; |
---|
226 | |
---|
227 | /** |
---|
228 | * Output helper function to report the sections in an object file. This |
---|
229 | * is useful when seeing the flags in the sections. |
---|
230 | */ |
---|
231 | void output (); |
---|
232 | }; |
---|
233 | |
---|
234 | /** |
---|
235 | * A symbol. This matches the symbol structure 'rtems_rtl_obj_sym_t' in the |
---|
236 | * target code. |
---|
237 | */ |
---|
238 | struct external |
---|
239 | { |
---|
240 | /** |
---|
241 | * Size of an external in the RAP file. |
---|
242 | */ |
---|
243 | static const uint32_t rap_size = sizeof (uint32_t) * 3; |
---|
244 | |
---|
245 | const uint32_t name; //< The string table's name index. |
---|
246 | const sections sec; //< The section the symbols belongs to. |
---|
247 | const uint32_t value; //< The offset from the section base. |
---|
248 | const uint32_t data; //< The ELF st.info field. |
---|
249 | |
---|
250 | /** |
---|
251 | * The constructor. |
---|
252 | */ |
---|
253 | external (const uint32_t name, |
---|
254 | const sections sec, |
---|
255 | const uint32_t value, |
---|
256 | const uint32_t data); |
---|
257 | |
---|
258 | /** |
---|
259 | * Copy constructor. |
---|
260 | */ |
---|
261 | external (const external& orig); |
---|
262 | |
---|
263 | }; |
---|
264 | |
---|
265 | /** |
---|
266 | * A container of externals. |
---|
267 | */ |
---|
268 | typedef std::list < external > externals; |
---|
269 | |
---|
270 | /** |
---|
271 | * The specific data for each object we need to collect to create the RAP |
---|
272 | * format file. |
---|
273 | */ |
---|
274 | struct object |
---|
275 | { |
---|
276 | files::object& obj; //< The object file. |
---|
277 | files::sections text; //< All executable code. |
---|
278 | files::sections const_; //< All read only data. |
---|
279 | files::sections ctor; //< The static constructor table. |
---|
280 | files::sections dtor; //< The static destructor table. |
---|
281 | files::sections data; //< All initialised read/write data. |
---|
282 | files::sections bss; //< All uninitialised read/write data |
---|
283 | files::sections symtab; //< All exported symbols. |
---|
284 | files::sections strtab; //< All exported strings. |
---|
285 | section secs[rap_secs]; //< The sections of interest. |
---|
286 | |
---|
287 | /** |
---|
288 | * The constructor. Need to have an object file to create. |
---|
289 | */ |
---|
290 | object (files::object& obj); |
---|
291 | |
---|
292 | /** |
---|
293 | * The copy constructor. |
---|
294 | */ |
---|
295 | object (const object& orig); |
---|
296 | |
---|
297 | /** |
---|
298 | * Find the section type that matches the section index. |
---|
299 | */ |
---|
300 | sections find (const uint32_t index) const; |
---|
301 | |
---|
302 | /** |
---|
303 | * The total number of relocations in the object file. |
---|
304 | */ |
---|
305 | uint32_t get_relocations () const; |
---|
306 | |
---|
307 | /** |
---|
308 | * The total number of relocations for a specific RAP section in the |
---|
309 | * object file. |
---|
310 | */ |
---|
311 | uint32_t get_relocations (int sec) const; |
---|
312 | |
---|
313 | /** |
---|
314 | * Output the object file details.. |
---|
315 | */ |
---|
316 | void output (); |
---|
317 | |
---|
318 | private: |
---|
319 | /** |
---|
320 | * No default constructor allowed. |
---|
321 | */ |
---|
322 | object (); |
---|
323 | }; |
---|
324 | |
---|
325 | /** |
---|
326 | * A container of objects. |
---|
327 | */ |
---|
328 | typedef std::list < object > objects; |
---|
329 | |
---|
330 | /** |
---|
331 | * The RAP image. |
---|
332 | */ |
---|
333 | class image |
---|
334 | { |
---|
335 | public: |
---|
336 | /** |
---|
337 | * Construct the image. |
---|
338 | */ |
---|
339 | image (); |
---|
340 | |
---|
341 | /** |
---|
342 | * Load the layout data from the object files. |
---|
343 | * |
---|
344 | * @param app_objects The object files in the application. |
---|
345 | * @param init The initialisation entry point label. |
---|
346 | * @param fini The finish entry point label. |
---|
347 | */ |
---|
348 | void layout (const files::object_list& app_objects, |
---|
349 | const std::string& init, |
---|
350 | const std::string& fini); |
---|
351 | |
---|
352 | /** |
---|
353 | * Collection the symbols from the object file. |
---|
354 | * |
---|
355 | * @param obj The object file to collection the symbol from. |
---|
356 | */ |
---|
357 | void collect_symbols (object& obj); |
---|
358 | |
---|
359 | /** |
---|
360 | * Write the compressed output file. This is the top level write |
---|
361 | * interface. |
---|
362 | * |
---|
363 | * @param comp The compressor. |
---|
364 | */ |
---|
365 | void write (compress::compressor& comp); |
---|
366 | |
---|
367 | /** |
---|
368 | * Write the RAP section to the compressed output file given the object files. |
---|
369 | * Check to make sure the size in the layout and the size written match. |
---|
370 | * |
---|
371 | * @param comp The compressor. |
---|
372 | * @param sec The RAP setion to write. |
---|
373 | */ |
---|
374 | void write (compress::compressor& comp, sections sec); |
---|
375 | |
---|
376 | /** |
---|
377 | * Write the sections to the compressed output file. The file sections |
---|
378 | * are used to ensure the alignment. The offset is used to ensure the |
---|
379 | * alignment of the first section of the object when it is written. |
---|
380 | * |
---|
381 | * @param comp The compressor. |
---|
382 | * @param obj The object file the sections are part of. |
---|
383 | * @param secs The container of file sections to write. |
---|
384 | * @param offset The current offset in the RAP section. |
---|
385 | */ |
---|
386 | void write (compress::compressor& comp, |
---|
387 | files::object& obj, |
---|
388 | const files::sections& secs, |
---|
389 | uint32_t& offset); |
---|
390 | |
---|
391 | /** |
---|
392 | * Write the external symbols. |
---|
393 | */ |
---|
394 | void write_externals (compress::compressor& comp); |
---|
395 | |
---|
396 | /** |
---|
397 | * Write the relocation records for all the object files. |
---|
398 | */ |
---|
399 | void write_relocations (compress::compressor& comp); |
---|
400 | |
---|
401 | /** |
---|
402 | * Write the details of the files. |
---|
403 | */ |
---|
404 | void write_details (compress::compressor& comp); |
---|
405 | |
---|
406 | /** |
---|
407 | * The total number of relocations for a specific RAP section in the |
---|
408 | * image. |
---|
409 | */ |
---|
410 | uint32_t get_relocations (int sec) const; |
---|
411 | |
---|
412 | /** |
---|
413 | * Clear the image values. |
---|
414 | */ |
---|
415 | void clear (); |
---|
416 | |
---|
417 | /** |
---|
418 | * Report the RAP section's size. |
---|
419 | */ |
---|
420 | uint32_t section_size (sections sec) const; |
---|
421 | |
---|
422 | /** |
---|
423 | * Find a symbol name in the string table. |
---|
424 | */ |
---|
425 | std::size_t find_in_strtab (const std::string& symname); |
---|
426 | |
---|
427 | private: |
---|
428 | |
---|
429 | objects objs; //< The RAP objects |
---|
430 | uint32_t sec_size[rap_secs]; //< The sections of interest. |
---|
431 | uint32_t sec_align[rap_secs]; //< The sections of interest. |
---|
432 | bool sec_rela[rap_secs]; //< The sections of interest. |
---|
433 | externals externs; //< The symbols in the image |
---|
434 | uint32_t symtab_size; //< The size of the symbols. |
---|
435 | std::string strtab; //< The strings table. |
---|
436 | uint32_t relocs_size; //< The relocations size. |
---|
437 | uint32_t init_off; //< The strtab offset to the init label. |
---|
438 | uint32_t fini_off; //< The strtab offset to the fini label. |
---|
439 | }; |
---|
440 | |
---|
441 | const char* |
---|
442 | section_name (int sec) |
---|
443 | { |
---|
444 | if (sec < rap_secs) |
---|
445 | return section_names[sec]; |
---|
446 | throw rld::error ("Invalid section '" + rld::to_string (sec) + "'", |
---|
447 | "rap::section-name"); |
---|
448 | } |
---|
449 | |
---|
450 | /** |
---|
451 | * Update the offset taking into account the alignment. |
---|
452 | * |
---|
453 | * @param offset The current offset. |
---|
454 | * @param size The size to move the offset by. |
---|
455 | * @param alignment The alignment of the offset. |
---|
456 | * @return uint32_t The new aligned offset. |
---|
457 | */ |
---|
458 | uint32_t align_offset (uint32_t offset, uint32_t size, uint32_t alignment) |
---|
459 | { |
---|
460 | offset += size; |
---|
461 | |
---|
462 | if (alignment > 1) |
---|
463 | { |
---|
464 | uint32_t mask = alignment - 1; |
---|
465 | if (offset & mask) |
---|
466 | { |
---|
467 | offset &= ~mask; |
---|
468 | offset += alignment; |
---|
469 | } |
---|
470 | } |
---|
471 | |
---|
472 | return offset; |
---|
473 | } |
---|
474 | |
---|
475 | relocation::relocation (const files::relocation& reloc, |
---|
476 | const uint32_t offset) |
---|
477 | : offset (reloc.offset + offset), |
---|
478 | info (reloc.info), |
---|
479 | addend (reloc.addend), |
---|
480 | symname (reloc.symname), |
---|
481 | symtype (reloc.symtype), |
---|
482 | symsect (reloc.symsect), |
---|
483 | symvalue (reloc.symvalue), |
---|
484 | symbinding (reloc.symbinding) |
---|
485 | { |
---|
486 | } |
---|
487 | |
---|
488 | section_detail::section_detail (uint32_t name, |
---|
489 | uint32_t offset, |
---|
490 | uint32_t id, |
---|
491 | uint32_t size) |
---|
492 | : name (name), |
---|
493 | offset (offset), |
---|
494 | id (id), |
---|
495 | size (size) |
---|
496 | { |
---|
497 | } |
---|
498 | |
---|
499 | osection::osection (const std::string& name, |
---|
500 | uint32_t offset, |
---|
501 | uint32_t size, |
---|
502 | uint32_t align, |
---|
503 | uint32_t relocs, |
---|
504 | uint64_t flags) |
---|
505 | : name (name), |
---|
506 | offset (offset), |
---|
507 | size (size), |
---|
508 | align (align), |
---|
509 | relocs (relocs), |
---|
510 | flags (flags) |
---|
511 | { |
---|
512 | } |
---|
513 | |
---|
514 | osection::osection () |
---|
515 | : offset (0), |
---|
516 | size (0), |
---|
517 | align (0), |
---|
518 | relocs (0), |
---|
519 | flags (0) |
---|
520 | { |
---|
521 | } |
---|
522 | |
---|
523 | section::section () |
---|
524 | : offset (0), |
---|
525 | rela (false) |
---|
526 | { |
---|
527 | } |
---|
528 | |
---|
529 | void |
---|
530 | section::clear () |
---|
531 | { |
---|
532 | offset = 0; |
---|
533 | rela = false; |
---|
534 | } |
---|
535 | |
---|
536 | uint32_t |
---|
537 | section::size (uint32_t offset_) const |
---|
538 | { |
---|
539 | uint32_t end = offset_; |
---|
540 | if (end == 0) |
---|
541 | end = offset; |
---|
542 | for (size_t si = 0; si < osindexes.size (); ++si) |
---|
543 | { |
---|
544 | const osection& osec = get_osection (osindexes[si]); |
---|
545 | end = align_offset (end, 0, osec.align); |
---|
546 | end += osec.size; |
---|
547 | } |
---|
548 | return end - offset; |
---|
549 | } |
---|
550 | |
---|
551 | uint32_t |
---|
552 | section::alignment () const |
---|
553 | { |
---|
554 | if (!osindexes.empty ()) |
---|
555 | { |
---|
556 | const osection& osec = get_osection (osindexes[0]); |
---|
557 | return osec.align; |
---|
558 | } |
---|
559 | return 0; |
---|
560 | } |
---|
561 | |
---|
562 | uint32_t |
---|
563 | section::alignment (int index) const |
---|
564 | { |
---|
565 | const osection& osec = get_osection (index); |
---|
566 | return osec.align; |
---|
567 | } |
---|
568 | |
---|
569 | void |
---|
570 | section::set_offset (const section& sec) |
---|
571 | { |
---|
572 | uint32_t align = alignment (); |
---|
573 | offset = align_offset (sec.offset, sec.size (), align); |
---|
574 | if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG) |
---|
575 | std::cout << "rap:section::set-offset: " << name |
---|
576 | << " offset=" << offset |
---|
577 | << " size=" << size () |
---|
578 | << " align=" << align |
---|
579 | << " sec.offset=" << sec.offset |
---|
580 | << " sec.size=" << sec.size (sec.offset) |
---|
581 | << std::endl; |
---|
582 | } |
---|
583 | |
---|
584 | const osection& |
---|
585 | section::get_osection (int index) const |
---|
586 | { |
---|
587 | osections::const_iterator osi = osecs.find (index); |
---|
588 | if (osi == osecs.end ()) |
---|
589 | throw rld::error ("Invalid object seciton index in '" + name +"': index=" + |
---|
590 | rld::to_string (index), |
---|
591 | "rap::section"); |
---|
592 | return (*osi).second; |
---|
593 | } |
---|
594 | |
---|
595 | /** |
---|
596 | * Output helper function to report the sections in an object file. This is |
---|
597 | * useful when seeing the flags in the sections. |
---|
598 | */ |
---|
599 | void |
---|
600 | section::output () |
---|
601 | { |
---|
602 | if (!osindexes.empty ()) |
---|
603 | { |
---|
604 | std::cout << ' ' << name |
---|
605 | << ": size: " << size (offset) |
---|
606 | << " offset: " << offset |
---|
607 | << " rela: " << (rela ? "yes" : "no") |
---|
608 | << std::endl; |
---|
609 | |
---|
610 | for (osecindexes::const_iterator osi = osindexes.begin (); |
---|
611 | osi != osindexes.end (); |
---|
612 | ++osi) |
---|
613 | { |
---|
614 | const osection& osec = get_osection (*osi); |
---|
615 | |
---|
616 | if (osec.size) |
---|
617 | { |
---|
618 | #define SF(f, i, c) if (osec.flags & (f)) flags[i] = c |
---|
619 | |
---|
620 | std::string flags ("--------------"); |
---|
621 | |
---|
622 | SF (SHF_WRITE, 0, 'W'); |
---|
623 | SF (SHF_ALLOC, 1, 'A'); |
---|
624 | SF (SHF_EXECINSTR, 2, 'E'); |
---|
625 | SF (SHF_MERGE, 3, 'M'); |
---|
626 | SF (SHF_STRINGS, 4, 'S'); |
---|
627 | SF (SHF_INFO_LINK, 5, 'I'); |
---|
628 | SF (SHF_LINK_ORDER, 6, 'L'); |
---|
629 | SF (SHF_OS_NONCONFORMING, 7, 'N'); |
---|
630 | SF (SHF_GROUP, 8, 'G'); |
---|
631 | SF (SHF_TLS, 9, 'T'); |
---|
632 | SF (SHF_AMD64_LARGE, 10, 'a'); |
---|
633 | SF (SHF_ENTRYSECT, 11, 'e'); |
---|
634 | SF (SHF_COMDEF, 12, 'c'); |
---|
635 | SF (SHF_ORDERED, 13, 'O'); |
---|
636 | |
---|
637 | std::cout << " " << std::left |
---|
638 | << std::setw (15) << osec.name |
---|
639 | << " " << flags |
---|
640 | << " size: " << std::setw (5) << osec.size |
---|
641 | << " align: " << std::setw (3) << osec.align |
---|
642 | << " relocs: " << std::setw (4) << osec.relocs |
---|
643 | << " offset: " << std::setw (5) << osec.offset |
---|
644 | << std::hex |
---|
645 | << " image: 0x" << offset + osec.offset |
---|
646 | << std::dec << std::right << std::endl; |
---|
647 | } |
---|
648 | } |
---|
649 | } |
---|
650 | } |
---|
651 | |
---|
652 | /** |
---|
653 | * Helper for for_each to merge the related object sections into the RAP |
---|
654 | * section. |
---|
655 | */ |
---|
656 | class section_merge: |
---|
657 | public std::unary_function < const files::section, void > |
---|
658 | { |
---|
659 | public: |
---|
660 | |
---|
661 | section_merge (object& obj, section& sec); |
---|
662 | |
---|
663 | ~section_merge (); |
---|
664 | |
---|
665 | void operator () (const files::section& fsec); |
---|
666 | |
---|
667 | private: |
---|
668 | |
---|
669 | object& obj; |
---|
670 | section& sec; |
---|
671 | }; |
---|
672 | |
---|
673 | section_merge::section_merge (object& obj, section& sec) |
---|
674 | : obj (obj), |
---|
675 | sec (sec) |
---|
676 | { |
---|
677 | sec.offset = 0; |
---|
678 | sec.rela = false; |
---|
679 | } |
---|
680 | |
---|
681 | section_merge::~section_merge () |
---|
682 | { |
---|
683 | if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG) |
---|
684 | std::cout << "rap:section-merge: " << sec.name |
---|
685 | << " size=" << sec.size () |
---|
686 | << " offset=" << sec.offset |
---|
687 | << " " << obj.obj.name ().full () << std::endl; |
---|
688 | } |
---|
689 | |
---|
690 | void |
---|
691 | section_merge::operator () (const files::section& fsec) |
---|
692 | { |
---|
693 | /* |
---|
694 | * Align the size up to the next alignment boundary and use that as the |
---|
695 | * offset for this object file section. |
---|
696 | */ |
---|
697 | uint32_t offset = align_offset (sec.size (), 0, fsec.alignment); |
---|
698 | |
---|
699 | if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG) |
---|
700 | std::cout << "rap:section-merge: " << fsec.name |
---|
701 | << " sec-size=" << sec.size () |
---|
702 | << " relocs=" << fsec.relocs.size () |
---|
703 | << " offset=" << offset |
---|
704 | << " fsec.size=" << fsec.size |
---|
705 | << " fsec.alignment=" << fsec.alignment |
---|
706 | << " fsec.rela=" << fsec.rela |
---|
707 | << " " << obj.obj.name ().full () << std::endl; |
---|
708 | |
---|
709 | /* |
---|
710 | * Add the object file's section offset to the map. This is needed |
---|
711 | * to adjust the external symbol offsets. |
---|
712 | */ |
---|
713 | osection osec (fsec.name, |
---|
714 | offset, |
---|
715 | fsec.size, |
---|
716 | fsec.alignment, |
---|
717 | fsec.relocs.size (), |
---|
718 | fsec.flags); |
---|
719 | sec.osecs[fsec.index] = osec; |
---|
720 | sec.osindexes.push_back (fsec.index); |
---|
721 | |
---|
722 | uint32_t rc = 0; |
---|
723 | |
---|
724 | for (files::relocations::const_iterator fri = fsec.relocs.begin (); |
---|
725 | fri != fsec.relocs.end (); |
---|
726 | ++fri, ++rc) |
---|
727 | { |
---|
728 | const files::relocation& freloc = *fri; |
---|
729 | |
---|
730 | if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG) |
---|
731 | std::cout << " " << std::setw (2) << sec.relocs.size () |
---|
732 | << '/' << std::setw (2) << rc |
---|
733 | << std::hex << ": reloc.info=0x" << freloc.info << std::dec |
---|
734 | << " reloc.offset=" << freloc.offset |
---|
735 | << " reloc.addend=" << freloc.addend |
---|
736 | << " reloc.symtype=" << freloc.symtype |
---|
737 | << " reloc.symsect=" << freloc.symsect |
---|
738 | << " reloc.symbinding=" << freloc.symbinding |
---|
739 | << std::endl; |
---|
740 | |
---|
741 | sec.relocs.push_back (relocation (freloc, offset)); |
---|
742 | } |
---|
743 | |
---|
744 | std::stable_sort (sec.relocs.begin (), |
---|
745 | sec.relocs.end (), |
---|
746 | reloc_symname_compare ()); |
---|
747 | std::stable_sort (sec.relocs.begin (), |
---|
748 | sec.relocs.end (), |
---|
749 | reloc_offset_compare ()); |
---|
750 | |
---|
751 | if (fsec.rela == true) |
---|
752 | sec.rela = fsec.rela; |
---|
753 | } |
---|
754 | |
---|
755 | external::external (const uint32_t name, |
---|
756 | const sections sec, |
---|
757 | const uint32_t value, |
---|
758 | const uint32_t data) |
---|
759 | : name (name), |
---|
760 | sec (sec), |
---|
761 | value (value), |
---|
762 | data (data) |
---|
763 | { |
---|
764 | } |
---|
765 | |
---|
766 | external::external (const external& orig) |
---|
767 | : name (orig.name), |
---|
768 | sec (orig.sec), |
---|
769 | value (orig.value), |
---|
770 | data (orig.data) |
---|
771 | { |
---|
772 | } |
---|
773 | |
---|
774 | object::object (files::object& obj) |
---|
775 | : obj (obj) |
---|
776 | { |
---|
777 | /* |
---|
778 | * Set up the names of the sections. |
---|
779 | */ |
---|
780 | for (int s = 0; s < rap_secs; ++s) |
---|
781 | secs[s].name = section_names[s]; |
---|
782 | |
---|
783 | /* |
---|
784 | * Get the relocation records. Collect the various section types from the |
---|
785 | * object file into the RAP sections. Merge those sections into the RAP |
---|
786 | * sections. |
---|
787 | */ |
---|
788 | |
---|
789 | obj.open (); |
---|
790 | try |
---|
791 | { |
---|
792 | obj.begin (); |
---|
793 | obj.load_relocations (); |
---|
794 | obj.end (); |
---|
795 | } |
---|
796 | catch (...) |
---|
797 | { |
---|
798 | obj.close (); |
---|
799 | throw; |
---|
800 | } |
---|
801 | obj.close (); |
---|
802 | |
---|
803 | obj.get_sections (text, SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); |
---|
804 | obj.get_sections (const_, SHT_PROGBITS, SHF_ALLOC, SHF_WRITE | SHF_EXECINSTR); |
---|
805 | obj.get_sections (ctor, ".ctors"); |
---|
806 | obj.get_sections (dtor, ".dtors"); |
---|
807 | obj.get_sections (data, SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); |
---|
808 | obj.get_sections (bss, SHT_NOBITS, SHF_ALLOC | SHF_WRITE); |
---|
809 | obj.get_sections (symtab, SHT_SYMTAB); |
---|
810 | obj.get_sections (strtab, ".strtab"); |
---|
811 | |
---|
812 | std::for_each (text.begin (), text.end (), |
---|
813 | section_merge (*this, secs[rap_text])); |
---|
814 | std::for_each (const_.begin (), const_.end (), |
---|
815 | section_merge (*this, secs[rap_const])); |
---|
816 | std::for_each (ctor.begin (), ctor.end (), |
---|
817 | section_merge (*this, secs[rap_ctor])); |
---|
818 | std::for_each (dtor.begin (), dtor.end (), |
---|
819 | section_merge (*this, secs[rap_dtor])); |
---|
820 | std::for_each (data.begin (), data.end (), |
---|
821 | section_merge (*this, secs[rap_data])); |
---|
822 | std::for_each (bss.begin (), bss.end (), |
---|
823 | section_merge (*this, secs[rap_bss])); |
---|
824 | } |
---|
825 | |
---|
826 | object::object (const object& orig) |
---|
827 | : obj (orig.obj), |
---|
828 | text (orig.text), |
---|
829 | const_ (orig.const_), |
---|
830 | ctor (orig.ctor), |
---|
831 | dtor (orig.dtor), |
---|
832 | data (orig.data), |
---|
833 | bss (orig.bss), |
---|
834 | symtab (orig.symtab), |
---|
835 | strtab (orig.strtab) |
---|
836 | { |
---|
837 | for (int s = 0; s < rap_secs; ++s) |
---|
838 | secs[s] = orig.secs[s]; |
---|
839 | } |
---|
840 | |
---|
841 | sections |
---|
842 | object::find (const uint32_t index) const |
---|
843 | { |
---|
844 | const files::section* sec; |
---|
845 | |
---|
846 | sec = files::find (text, index); |
---|
847 | if (sec) |
---|
848 | return rap_text; |
---|
849 | |
---|
850 | sec = files::find (const_, index); |
---|
851 | if (sec) |
---|
852 | return rap_const; |
---|
853 | |
---|
854 | sec = files::find (ctor, index); |
---|
855 | if (sec) |
---|
856 | return rap_ctor; |
---|
857 | |
---|
858 | sec = files::find (dtor, index); |
---|
859 | if (sec) |
---|
860 | return rap_dtor; |
---|
861 | |
---|
862 | sec = files::find (data, index); |
---|
863 | if (sec) |
---|
864 | return rap_data; |
---|
865 | |
---|
866 | sec = files::find (bss, index); |
---|
867 | if (sec) |
---|
868 | return rap_bss; |
---|
869 | |
---|
870 | throw rld::error ("Section index '" + rld::to_string (index) + |
---|
871 | "' not found: " + obj.name ().full (), "rap::object"); |
---|
872 | } |
---|
873 | |
---|
874 | uint32_t |
---|
875 | object::get_relocations () const |
---|
876 | { |
---|
877 | uint32_t relocs = 0; |
---|
878 | for (int s = 0; s < rap_secs; ++s) |
---|
879 | relocs += secs[s].relocs.size (); |
---|
880 | return relocs; |
---|
881 | } |
---|
882 | |
---|
883 | uint32_t |
---|
884 | object::get_relocations (int sec) const |
---|
885 | { |
---|
886 | if ((sec < 0) || (sec >= rap_secs)) |
---|
887 | throw rld::error ("Invalid section index '" + rld::to_string (sec), |
---|
888 | "rap::relocations"); |
---|
889 | return secs[sec].relocs.size (); |
---|
890 | } |
---|
891 | |
---|
892 | void |
---|
893 | object::output () |
---|
894 | { |
---|
895 | std::cout << "rap:object: " << obj.name ().full () << std::endl; |
---|
896 | secs[rap_text].output (); |
---|
897 | secs[rap_const].output (); |
---|
898 | secs[rap_ctor].output (); |
---|
899 | secs[rap_dtor].output (); |
---|
900 | secs[rap_data].output (); |
---|
901 | if (secs[rap_bss].size ()) |
---|
902 | std::cout << " bss: size: " << secs[rap_bss].size () << std::endl; |
---|
903 | } |
---|
904 | |
---|
905 | image::image () |
---|
906 | { |
---|
907 | clear (); |
---|
908 | } |
---|
909 | |
---|
910 | void |
---|
911 | image::layout (const files::object_list& app_objects, |
---|
912 | const std::string& init, |
---|
913 | const std::string& fini) |
---|
914 | { |
---|
915 | clear (); |
---|
916 | |
---|
917 | /* |
---|
918 | * Create the local objects which contain the layout information. |
---|
919 | */ |
---|
920 | for (files::object_list::const_iterator aoi = app_objects.begin (); |
---|
921 | aoi != app_objects.end (); |
---|
922 | ++aoi) |
---|
923 | { |
---|
924 | files::object& app_obj = *(*aoi); |
---|
925 | |
---|
926 | if (!app_obj.valid ()) |
---|
927 | throw rld::error ("Not valid: " + app_obj.name ().full (), |
---|
928 | "rap::layout"); |
---|
929 | |
---|
930 | objs.push_back (object (app_obj)); |
---|
931 | } |
---|
932 | |
---|
933 | for (objects::iterator oi = objs.begin (), poi = objs.begin (); |
---|
934 | oi != objs.end (); |
---|
935 | ++oi) |
---|
936 | { |
---|
937 | object& obj = *oi; |
---|
938 | |
---|
939 | /* |
---|
940 | * Update the offsets in the object file. We need the object's offset |
---|
941 | * to set the relocation offset's correctly as they are relative to the |
---|
942 | * object file. |
---|
943 | */ |
---|
944 | if (oi != objs.begin ()) |
---|
945 | { |
---|
946 | object& pobj = *poi; |
---|
947 | for (int s = 0; s < rap_secs; ++s) |
---|
948 | { |
---|
949 | obj.secs[s].set_offset (pobj.secs[s]); |
---|
950 | sec_size[s] = obj.secs[s].offset + obj.secs[s].size (); |
---|
951 | sec_align[s] = obj.secs[s].alignment (); |
---|
952 | if (obj.secs[s].rela == true) |
---|
953 | sec_rela[s] = obj.secs[s].rela; |
---|
954 | } |
---|
955 | ++poi; |
---|
956 | } |
---|
957 | else |
---|
958 | { |
---|
959 | for (int s = 0; s < rap_secs; ++s) |
---|
960 | { |
---|
961 | sec_size[s] = obj.secs[s].size (); |
---|
962 | sec_align[s] = obj.secs[s].alignment (); |
---|
963 | if (obj.secs[s].rela == true) |
---|
964 | sec_rela[s] = true; |
---|
965 | } |
---|
966 | } |
---|
967 | |
---|
968 | collect_symbols (obj); |
---|
969 | |
---|
970 | relocs_size += obj.get_relocations (); |
---|
971 | |
---|
972 | if (rld::verbose () >= RLD_VERBOSE_DETAILS) |
---|
973 | obj.output (); |
---|
974 | } |
---|
975 | |
---|
976 | init_off = strtab.size () + 1; |
---|
977 | strtab += '\0'; |
---|
978 | strtab += init; |
---|
979 | |
---|
980 | fini_off = strtab.size () + 1; |
---|
981 | strtab += '\0'; |
---|
982 | strtab += fini; |
---|
983 | |
---|
984 | if (rld::verbose () >= RLD_VERBOSE_INFO) |
---|
985 | { |
---|
986 | uint32_t total = (sec_size[rap_text] + sec_size[rap_const] + |
---|
987 | sec_size[rap_data] + sec_size[rap_bss] + |
---|
988 | symtab_size + strtab.size() + relocs_size); |
---|
989 | std::cout << "rap::layout: total:" << total |
---|
990 | << " text:" << sec_size[rap_text] |
---|
991 | << " const:" << sec_size[rap_const] |
---|
992 | << " ctor:" << sec_size[rap_ctor] |
---|
993 | << " dtor:" << sec_size[rap_dtor] |
---|
994 | << " data:" << sec_size[rap_data] |
---|
995 | << " bss:" << sec_size[rap_bss] |
---|
996 | << " symbols:" << symtab_size << " (" << externs.size () << ')' |
---|
997 | << " strings:" << strtab.size () + 1 |
---|
998 | << " relocs:" << relocs_size |
---|
999 | << std::endl; |
---|
1000 | } |
---|
1001 | } |
---|
1002 | |
---|
1003 | void |
---|
1004 | image::collect_symbols (object& obj) |
---|
1005 | { |
---|
1006 | symbols::pointers& esyms = obj.obj.external_symbols (); |
---|
1007 | for (symbols::pointers::const_iterator ei = esyms.begin (); |
---|
1008 | ei != esyms.end (); |
---|
1009 | ++ei) |
---|
1010 | { |
---|
1011 | const symbols::symbol& sym = *(*ei); |
---|
1012 | |
---|
1013 | if ((sym.type () == STT_OBJECT) || (sym.type () == STT_FUNC) || (sym.type () == STT_NOTYPE)) |
---|
1014 | { |
---|
1015 | if ((sym.binding () == STB_GLOBAL) || (sym.binding () == STB_WEAK)) |
---|
1016 | { |
---|
1017 | int symsec = sym.section_index (); |
---|
1018 | |
---|
1019 | /* Ignore section index 0 */ |
---|
1020 | if (symsec == 0) |
---|
1021 | continue; |
---|
1022 | /* Ignore sparc common section */ |
---|
1023 | if ((elf::object_machine_type () == EM_SPARC) && (symsec == 65522)) |
---|
1024 | continue; |
---|
1025 | |
---|
1026 | sections rap_sec = obj.find (symsec); |
---|
1027 | section& sec = obj.secs[rap_sec]; |
---|
1028 | std::size_t name; |
---|
1029 | |
---|
1030 | /* |
---|
1031 | * See if the name is already in the string table. |
---|
1032 | */ |
---|
1033 | name = find_in_strtab (sym.name ()); |
---|
1034 | |
---|
1035 | if (name == std::string::npos) |
---|
1036 | { |
---|
1037 | name = strtab.size () + 1; |
---|
1038 | strtab += '\0'; |
---|
1039 | strtab += sym.name (); |
---|
1040 | } |
---|
1041 | |
---|
1042 | /* |
---|
1043 | * The symbol's value is the symbols value plus the offset of the |
---|
1044 | * object file's section offset in the RAP section. |
---|
1045 | */ |
---|
1046 | externs.push_back (external (name, |
---|
1047 | rap_sec, |
---|
1048 | sec.offset + sec.osecs[symsec].offset + |
---|
1049 | sym.value (), |
---|
1050 | sym.info ())); |
---|
1051 | |
---|
1052 | symtab_size += external::rap_size; |
---|
1053 | } |
---|
1054 | } |
---|
1055 | } |
---|
1056 | } |
---|
1057 | |
---|
1058 | void |
---|
1059 | image::write (compress::compressor& comp) |
---|
1060 | { |
---|
1061 | /* |
---|
1062 | * Start with the machine type so the target can check the applicatiion |
---|
1063 | * is ok and can be loaded. Add the init and fini labels to the string |
---|
1064 | * table and add the references to the string table next. Follow this |
---|
1065 | * with the section details then the string table and symbol table then |
---|
1066 | * finally the relocation records. |
---|
1067 | */ |
---|
1068 | |
---|
1069 | if (rld::verbose () >= RLD_VERBOSE_INFO) |
---|
1070 | std::cout << "rap:output: machine=" << comp.transferred () << std::endl; |
---|
1071 | |
---|
1072 | comp << elf::object_machine_type () |
---|
1073 | << elf::object_datatype () |
---|
1074 | << elf::object_class (); |
---|
1075 | |
---|
1076 | /* |
---|
1077 | * The init and fini label offsets. Then the symbol table and string |
---|
1078 | * table sizes. |
---|
1079 | */ |
---|
1080 | |
---|
1081 | if (rld::verbose () >= RLD_VERBOSE_INFO) |
---|
1082 | std::cout << "rap:output: header=" << comp.transferred () << std::endl; |
---|
1083 | |
---|
1084 | comp << init_off |
---|
1085 | << fini_off |
---|
1086 | << symtab_size |
---|
1087 | << (uint32_t) strtab.size () + 1 |
---|
1088 | << (uint32_t) 0; |
---|
1089 | |
---|
1090 | /* |
---|
1091 | * Output file details |
---|
1092 | */ |
---|
1093 | if (add_obj_details) |
---|
1094 | { |
---|
1095 | write_details (comp); |
---|
1096 | } |
---|
1097 | else |
---|
1098 | { |
---|
1099 | comp << (uint32_t)0; /* No file details */ |
---|
1100 | } |
---|
1101 | |
---|
1102 | /* |
---|
1103 | * The sections. |
---|
1104 | */ |
---|
1105 | for (int s = 0; s < rap_secs; ++s) |
---|
1106 | comp << sec_size[s] |
---|
1107 | << sec_align[s]; |
---|
1108 | |
---|
1109 | /* |
---|
1110 | * Output the sections from each object file. |
---|
1111 | */ |
---|
1112 | write (comp, rap_text); |
---|
1113 | write (comp, rap_const); |
---|
1114 | write (comp, rap_ctor); |
---|
1115 | write (comp, rap_dtor); |
---|
1116 | write (comp, rap_data); |
---|
1117 | |
---|
1118 | if (rld::verbose () >= RLD_VERBOSE_INFO) |
---|
1119 | std::cout << "rap:output: strtab=" << comp.transferred () << std::endl; |
---|
1120 | |
---|
1121 | strtab += '\0'; |
---|
1122 | comp << strtab; |
---|
1123 | |
---|
1124 | if (rld::verbose () >= RLD_VERBOSE_INFO) |
---|
1125 | std::cout << "rap:output: symbols=" << comp.transferred () << std::endl; |
---|
1126 | |
---|
1127 | write_externals (comp); |
---|
1128 | |
---|
1129 | if (rld::verbose () >= RLD_VERBOSE_INFO) |
---|
1130 | std::cout << "rap:output: relocs=" << comp.transferred () << std::endl; |
---|
1131 | |
---|
1132 | write_relocations (comp); |
---|
1133 | } |
---|
1134 | |
---|
1135 | /** |
---|
1136 | * Helper for for_each to write out the various sections. |
---|
1137 | */ |
---|
1138 | class section_writer: |
---|
1139 | public std::unary_function < object, void > |
---|
1140 | { |
---|
1141 | public: |
---|
1142 | |
---|
1143 | section_writer (image& img, |
---|
1144 | compress::compressor& comp, |
---|
1145 | sections sec); |
---|
1146 | |
---|
1147 | void operator () (object& obj); |
---|
1148 | |
---|
1149 | private: |
---|
1150 | |
---|
1151 | image& img; |
---|
1152 | compress::compressor& comp; |
---|
1153 | sections sec; |
---|
1154 | uint32_t offset; |
---|
1155 | }; |
---|
1156 | |
---|
1157 | section_writer::section_writer (image& img, |
---|
1158 | compress::compressor& comp, |
---|
1159 | sections sec) |
---|
1160 | : img (img), |
---|
1161 | comp (comp), |
---|
1162 | sec (sec), |
---|
1163 | offset (0) |
---|
1164 | { |
---|
1165 | if (rld::verbose () >= RLD_VERBOSE_INFO) |
---|
1166 | std::cout << "rap:output: " << section_names[sec] |
---|
1167 | << ": offset=" << comp.transferred () |
---|
1168 | << " size=" << img.section_size (sec) << std::endl; |
---|
1169 | } |
---|
1170 | |
---|
1171 | void |
---|
1172 | section_writer::operator () (object& obj) |
---|
1173 | { |
---|
1174 | if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG) |
---|
1175 | std::cout << "rap:writing: " << section_names[sec] << std::endl; |
---|
1176 | |
---|
1177 | switch (sec) |
---|
1178 | { |
---|
1179 | case rap_text: |
---|
1180 | img.write (comp, obj.obj, obj.text, offset); |
---|
1181 | break; |
---|
1182 | case rap_const: |
---|
1183 | img.write (comp, obj.obj, obj.const_, offset); |
---|
1184 | break; |
---|
1185 | case rap_ctor: |
---|
1186 | img.write (comp, obj.obj, obj.ctor, offset); |
---|
1187 | break; |
---|
1188 | case rap_dtor: |
---|
1189 | img.write (comp, obj.obj, obj.dtor, offset); |
---|
1190 | break; |
---|
1191 | case rap_data: |
---|
1192 | img.write (comp, obj.obj, obj.data, offset); |
---|
1193 | break; |
---|
1194 | default: |
---|
1195 | break; |
---|
1196 | } |
---|
1197 | } |
---|
1198 | |
---|
1199 | void |
---|
1200 | image::write (compress::compressor& comp, sections sec) |
---|
1201 | { |
---|
1202 | uint32_t image_offset = comp.transferred (); |
---|
1203 | |
---|
1204 | std::for_each (objs.begin (), objs.end (), |
---|
1205 | section_writer (*this, comp, sec)); |
---|
1206 | |
---|
1207 | uint32_t written = comp.transferred () - image_offset; |
---|
1208 | |
---|
1209 | if (written != sec_size[sec]) |
---|
1210 | { |
---|
1211 | std::string msg = "Image output size does not match layout size: "; |
---|
1212 | msg += section_names[sec]; |
---|
1213 | msg += ": layout-size=" + rld::to_string (sec_size[sec]); |
---|
1214 | msg += " image-size=" + rld::to_string (written); |
---|
1215 | throw rld::error (msg, "rap::write"); |
---|
1216 | } |
---|
1217 | } |
---|
1218 | |
---|
1219 | void |
---|
1220 | image::write (compress::compressor& comp, |
---|
1221 | files::object& obj, |
---|
1222 | const files::sections& secs, |
---|
1223 | uint32_t& offset) |
---|
1224 | { |
---|
1225 | uint32_t size = 0; |
---|
1226 | |
---|
1227 | obj.open (); |
---|
1228 | |
---|
1229 | try |
---|
1230 | { |
---|
1231 | obj.begin (); |
---|
1232 | |
---|
1233 | if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG) |
---|
1234 | std::cout << "rap:write sections: " << obj.name ().full () << std::endl; |
---|
1235 | |
---|
1236 | for (files::sections::const_iterator si = secs.begin (); |
---|
1237 | si != secs.end (); |
---|
1238 | ++si) |
---|
1239 | { |
---|
1240 | const files::section& sec = *si; |
---|
1241 | uint32_t unaligned_offset = offset + size; |
---|
1242 | |
---|
1243 | offset = align_offset (offset, size, sec.alignment); |
---|
1244 | |
---|
1245 | if (offset != unaligned_offset) |
---|
1246 | { |
---|
1247 | char ee = '\xee'; |
---|
1248 | for (uint32_t p = 0; p < (offset - unaligned_offset); ++p) |
---|
1249 | comp.write (&ee, 1); |
---|
1250 | } |
---|
1251 | |
---|
1252 | comp.write (obj, sec.offset, sec.size); |
---|
1253 | |
---|
1254 | if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG) |
---|
1255 | std::cout << " sec: " << sec.index << ' ' << sec.name |
---|
1256 | << " offset=" << offset |
---|
1257 | << " size=" << sec.size |
---|
1258 | << " align=" << sec.alignment |
---|
1259 | << " padding=" << (offset - unaligned_offset) << std::endl; |
---|
1260 | |
---|
1261 | size = sec.size; |
---|
1262 | } |
---|
1263 | |
---|
1264 | offset += size; |
---|
1265 | |
---|
1266 | if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG) |
---|
1267 | std::cout << " total size=" << offset << std::endl; |
---|
1268 | |
---|
1269 | obj.end (); |
---|
1270 | } |
---|
1271 | catch (...) |
---|
1272 | { |
---|
1273 | obj.close (); |
---|
1274 | throw; |
---|
1275 | } |
---|
1276 | |
---|
1277 | obj.close (); |
---|
1278 | } |
---|
1279 | |
---|
1280 | void |
---|
1281 | image::write_externals (compress::compressor& comp) |
---|
1282 | { |
---|
1283 | int count = 0; |
---|
1284 | for (externals::const_iterator ei = externs.begin (); |
---|
1285 | ei != externs.end (); |
---|
1286 | ++ei, ++count) |
---|
1287 | { |
---|
1288 | const external& ext = *ei; |
---|
1289 | |
---|
1290 | if (rld::verbose () >= RLD_VERBOSE_TRACE) |
---|
1291 | std::cout << "rap:externs: " << count |
---|
1292 | << " name=" << &strtab[ext.name] << " (" << ext.name << ')' |
---|
1293 | << " section=" << section_names[ext.sec] |
---|
1294 | << " data=" << ext.data |
---|
1295 | << " value=0x" << std::hex << ext.value << std::dec |
---|
1296 | << std::endl; |
---|
1297 | |
---|
1298 | if ((ext.data & 0xffff0000) != 0) |
---|
1299 | throw rld::error ("Data value has data in bits higher than 15", |
---|
1300 | "rap::write-externs"); |
---|
1301 | |
---|
1302 | comp << (uint32_t) ((ext.sec << 16) | ext.data) |
---|
1303 | << ext.name |
---|
1304 | << ext.value; |
---|
1305 | } |
---|
1306 | } |
---|
1307 | |
---|
1308 | void |
---|
1309 | image::write_relocations (compress::compressor& comp) |
---|
1310 | { |
---|
1311 | for (int s = 0; s < rap_secs; ++s) |
---|
1312 | { |
---|
1313 | uint32_t count = get_relocations (s); |
---|
1314 | uint32_t sr = 0; |
---|
1315 | uint32_t header; |
---|
1316 | |
---|
1317 | if (rld::verbose () >= RLD_VERBOSE_TRACE) |
---|
1318 | std::cout << "rap:relocation: section:" << section_names[s] |
---|
1319 | << " relocs=" << count |
---|
1320 | << " rela=" << (char*) (sec_rela[s] ? "yes" : "no") |
---|
1321 | << std::endl; |
---|
1322 | |
---|
1323 | header = count; |
---|
1324 | header |= sec_rela[s] ? RAP_RELOC_RELA : 0; |
---|
1325 | |
---|
1326 | comp << header; |
---|
1327 | |
---|
1328 | for (objects::iterator oi = objs.begin (); |
---|
1329 | oi != objs.end (); |
---|
1330 | ++oi) |
---|
1331 | { |
---|
1332 | object& obj = *oi; |
---|
1333 | section& sec = obj.secs[s]; |
---|
1334 | relocations& relocs = sec.relocs; |
---|
1335 | uint32_t rc = 0; |
---|
1336 | |
---|
1337 | if (rld::verbose () >= RLD_VERBOSE_TRACE) |
---|
1338 | std::cout << " relocs=" << sec.relocs.size () |
---|
1339 | << " sec.offset=" << sec.offset |
---|
1340 | << " sec.size=" << sec.size () |
---|
1341 | << " sec.align=" << sec.alignment () |
---|
1342 | << " " << obj.obj.name ().full () << std::endl; |
---|
1343 | |
---|
1344 | for (relocations::const_iterator ri = relocs.begin (); |
---|
1345 | ri != relocs.end (); |
---|
1346 | ++ri, ++sr, ++rc) |
---|
1347 | { |
---|
1348 | const relocation& reloc = *ri; |
---|
1349 | uint32_t info = GELF_R_TYPE (reloc.info); |
---|
1350 | uint32_t offset; |
---|
1351 | uint32_t addend = reloc.addend; |
---|
1352 | bool write_addend = sec.rela; |
---|
1353 | bool write_symname = false; |
---|
1354 | |
---|
1355 | offset = sec.offset + reloc.offset; |
---|
1356 | |
---|
1357 | if ((reloc.symtype == STT_SECTION) || (reloc.symbinding == STB_LOCAL)) |
---|
1358 | { |
---|
1359 | int rap_symsect = obj.find (reloc.symsect); |
---|
1360 | |
---|
1361 | /* |
---|
1362 | * Bit 31 clear, bits 30:8 RAP section index. |
---|
1363 | */ |
---|
1364 | info |= rap_symsect << 8; |
---|
1365 | |
---|
1366 | addend += (obj.secs[rap_symsect].offset + |
---|
1367 | obj.secs[rap_symsect].osecs[reloc.symsect].offset + |
---|
1368 | reloc.symvalue); |
---|
1369 | |
---|
1370 | write_addend = true; |
---|
1371 | |
---|
1372 | if (rld::verbose () >= RLD_VERBOSE_TRACE) |
---|
1373 | std::cout << " " << std::setw (2) << sr |
---|
1374 | << '/' << std::setw (2) << rc |
---|
1375 | <<": rsym: sect=" << section_names[rap_symsect] |
---|
1376 | << " rap_symsect=" << rap_symsect |
---|
1377 | << " sec.offset=" << obj.secs[rap_symsect].offset |
---|
1378 | << " sec.osecs=" << obj.secs[rap_symsect].osecs[reloc.symsect].offset |
---|
1379 | << " (" << obj.obj.get_section (reloc.symsect).name << ')' |
---|
1380 | << " reloc.symsect=" << reloc.symsect |
---|
1381 | << " reloc.symvalue=" << reloc.symvalue |
---|
1382 | << " reloc.addend=" << reloc.addend |
---|
1383 | << " addend=" << addend |
---|
1384 | << std::endl; |
---|
1385 | } |
---|
1386 | else |
---|
1387 | { |
---|
1388 | /* |
---|
1389 | * Bit 31 must be set. Bit 30 determines the type of string and |
---|
1390 | * bits 29:8 the strtab offset or the size of the appended |
---|
1391 | * string. |
---|
1392 | */ |
---|
1393 | |
---|
1394 | info |= RAP_RELOC_STRING; |
---|
1395 | |
---|
1396 | std::size_t size = find_in_strtab (reloc.symname); |
---|
1397 | |
---|
1398 | if (size == std::string::npos) |
---|
1399 | { |
---|
1400 | /* |
---|
1401 | * Bit 30 clear, the size of the symbol name. |
---|
1402 | */ |
---|
1403 | info |= reloc.symname.size () << 8; |
---|
1404 | write_symname = true; |
---|
1405 | } |
---|
1406 | else |
---|
1407 | { |
---|
1408 | /* |
---|
1409 | * Bit 30 set, the offset in the strtab. |
---|
1410 | */ |
---|
1411 | info |= RAP_RELOC_STRING_EMBED | (size << 8); |
---|
1412 | } |
---|
1413 | } |
---|
1414 | |
---|
1415 | if (rld::verbose () >= RLD_VERBOSE_TRACE) |
---|
1416 | { |
---|
1417 | std::cout << " " << std::setw (2) << sr << '/' |
---|
1418 | << std::setw (2) << rc |
---|
1419 | << std::hex << ": reloc: info=0x" << info << std::dec |
---|
1420 | << " offset=" << offset; |
---|
1421 | if (write_addend) |
---|
1422 | std::cout << " addend=" << addend; |
---|
1423 | if ((info & RAP_RELOC_STRING) != 0) |
---|
1424 | { |
---|
1425 | std::cout << " symname=" << reloc.symname; |
---|
1426 | if (write_symname) |
---|
1427 | std::cout << " (appended)"; |
---|
1428 | } |
---|
1429 | std::cout << std::hex |
---|
1430 | << " reloc.info=0x" << reloc.info << std::dec |
---|
1431 | << " reloc.offset=" << reloc.offset |
---|
1432 | << " reloc.symtype=" << reloc.symtype |
---|
1433 | << std::endl; |
---|
1434 | } |
---|
1435 | |
---|
1436 | comp << info << offset; |
---|
1437 | |
---|
1438 | if (write_addend) |
---|
1439 | comp << addend; |
---|
1440 | |
---|
1441 | if (write_symname) |
---|
1442 | comp << reloc.symname; |
---|
1443 | } |
---|
1444 | } |
---|
1445 | } |
---|
1446 | } |
---|
1447 | |
---|
1448 | void image::write_details (compress::compressor& comp) |
---|
1449 | { |
---|
1450 | |
---|
1451 | std::string strtable; |
---|
1452 | uint32_t pos = 0; |
---|
1453 | |
---|
1454 | section_details s_details; |
---|
1455 | |
---|
1456 | |
---|
1457 | if (rld::verbose () >= RLD_VERBOSE_TRACE) |
---|
1458 | { |
---|
1459 | std::cout << "rap:file details" << std::endl |
---|
1460 | << " total " << objs.size () <<" files" << std::endl; |
---|
1461 | } |
---|
1462 | |
---|
1463 | comp << (uint32_t)(objs.size ()); |
---|
1464 | |
---|
1465 | /* rpath for rap file */ |
---|
1466 | if (rld::verbose () >= RLD_VERBOSE_TRACE) |
---|
1467 | { |
---|
1468 | std::cout << "rap:file rpath=" << rld::rap::rpath << std::endl; |
---|
1469 | } |
---|
1470 | |
---|
1471 | comp << (uint32_t)rld::rap::rpath.length (); |
---|
1472 | |
---|
1473 | if (rld::rap::rpath.length () > 0) |
---|
1474 | { |
---|
1475 | strtable += rld::rap::rpath; |
---|
1476 | } |
---|
1477 | |
---|
1478 | for (objects::iterator oi = objs.begin (); |
---|
1479 | oi != objs.end (); |
---|
1480 | ++oi) |
---|
1481 | { |
---|
1482 | object& obj = *oi; |
---|
1483 | |
---|
1484 | /* obj full name */ |
---|
1485 | strtable += obj.obj.name ().full (); |
---|
1486 | strtable += '\0'; |
---|
1487 | } |
---|
1488 | |
---|
1489 | pos = strtable.length (); |
---|
1490 | |
---|
1491 | uint32_t sec_num = 0; |
---|
1492 | for (objects::iterator oi = objs.begin (); |
---|
1493 | oi != objs.end (); |
---|
1494 | ++oi) |
---|
1495 | { |
---|
1496 | object& obj = *oi; |
---|
1497 | |
---|
1498 | if (rld::verbose () >= RLD_VERBOSE_TRACE) |
---|
1499 | std::cout << "file:" << obj.obj.name ().full () << std::endl; |
---|
1500 | |
---|
1501 | for (int s = 0; s < rap_secs; ++s) |
---|
1502 | { |
---|
1503 | section& sec = obj.secs[s]; |
---|
1504 | |
---|
1505 | if (rld::verbose () >= RLD_VERBOSE_TRACE) |
---|
1506 | { |
---|
1507 | std::cout << "rap:section: " << sec.name << " " |
---|
1508 | "offset= " << sec.offset << std::endl; |
---|
1509 | } |
---|
1510 | |
---|
1511 | for (size_t si = 0; si < sec.osindexes.size (); ++si) |
---|
1512 | { |
---|
1513 | const osection& osec = sec.get_osection (sec.osindexes[si]); |
---|
1514 | |
---|
1515 | strtable += osec.name; |
---|
1516 | strtable += '\0'; |
---|
1517 | |
---|
1518 | /* sec.offset + osec.offset is the offset in the rap section */ |
---|
1519 | s_details.push_back (section_detail (pos, |
---|
1520 | sec.offset + osec.offset, |
---|
1521 | s, |
---|
1522 | osec.size)); |
---|
1523 | |
---|
1524 | pos = strtable.length (); |
---|
1525 | |
---|
1526 | if (rld::verbose () >= RLD_VERBOSE_TRACE) |
---|
1527 | { |
---|
1528 | std::cout << "osec.name=" << osec.name << " " |
---|
1529 | << "osec.offset=" << osec.offset << " " |
---|
1530 | << "osec.size=" << osec.size << std::endl; |
---|
1531 | } |
---|
1532 | } |
---|
1533 | } |
---|
1534 | |
---|
1535 | /* Output section numbers*/ |
---|
1536 | comp << (uint32_t)((s_details.size () - sec_num)); |
---|
1537 | if (rld::verbose () >= RLD_VERBOSE_TRACE) |
---|
1538 | std::cout << "sec_num:" << s_details.size () - sec_num << std::endl; |
---|
1539 | sec_num = s_details.size (); |
---|
1540 | } |
---|
1541 | |
---|
1542 | comp << (uint32_t)(strtable.size ()); |
---|
1543 | if (rld::verbose () >= RLD_VERBOSE_TRACE) |
---|
1544 | std::cout << "total detail size:" << strtable.size () << std::endl; |
---|
1545 | |
---|
1546 | comp << strtable; |
---|
1547 | |
---|
1548 | for (section_details::const_iterator si = s_details.begin (); |
---|
1549 | si != s_details.end (); |
---|
1550 | ++si) |
---|
1551 | { |
---|
1552 | const section_detail& sec_detail = *si; |
---|
1553 | comp << (uint32_t)(sec_detail.name); |
---|
1554 | |
---|
1555 | if (sec_detail.id > 0xf) |
---|
1556 | std::cout << "Out max rap section id 15\n" << std::endl; |
---|
1557 | |
---|
1558 | comp << (uint32_t)((sec_detail.id << 28) | sec_detail.offset); |
---|
1559 | comp << (uint32_t)(sec_detail.size); |
---|
1560 | } |
---|
1561 | } |
---|
1562 | |
---|
1563 | uint32_t |
---|
1564 | image::get_relocations (int sec) const |
---|
1565 | { |
---|
1566 | if ((sec < 0) || (sec >= rap_secs)) |
---|
1567 | throw rld::error ("Invalid section index '" + rld::to_string (sec), |
---|
1568 | "rap::image::relocations"); |
---|
1569 | |
---|
1570 | uint32_t relocs = 0; |
---|
1571 | |
---|
1572 | for (objects::const_iterator oi = objs.begin (); |
---|
1573 | oi != objs.end (); |
---|
1574 | ++oi) |
---|
1575 | { |
---|
1576 | const object& obj = *oi; |
---|
1577 | relocs += obj.get_relocations (sec); |
---|
1578 | } |
---|
1579 | |
---|
1580 | return relocs; |
---|
1581 | } |
---|
1582 | |
---|
1583 | void |
---|
1584 | image::clear () |
---|
1585 | { |
---|
1586 | for (int s = 0; s < rap_secs; ++s) |
---|
1587 | { |
---|
1588 | sec_size[s] = 0; |
---|
1589 | sec_align[s] = 0; |
---|
1590 | sec_rela[s] = false; |
---|
1591 | } |
---|
1592 | symtab_size = 0; |
---|
1593 | strtab.clear (); |
---|
1594 | relocs_size = 0; |
---|
1595 | init_off = 0; |
---|
1596 | fini_off = 0; |
---|
1597 | } |
---|
1598 | |
---|
1599 | uint32_t |
---|
1600 | image::section_size (sections sec) const |
---|
1601 | { |
---|
1602 | if ((sec < 0) || (sec >= rap_secs)) |
---|
1603 | throw rld::error ("Invalid section index '" + rld::to_string (sec), |
---|
1604 | "rap::image::section_size"); |
---|
1605 | return sec_size[sec]; |
---|
1606 | } |
---|
1607 | |
---|
1608 | std::size_t |
---|
1609 | image::find_in_strtab (const std::string& symname) |
---|
1610 | { |
---|
1611 | std::size_t pos = 0; |
---|
1612 | while (pos < strtab.size ()) |
---|
1613 | { |
---|
1614 | std::size_t off = strtab.find (symname, pos); |
---|
1615 | if (off == std::string::npos) |
---|
1616 | break; |
---|
1617 | if (::strlen (strtab.c_str () + off) == symname.size ()) |
---|
1618 | return off; |
---|
1619 | pos = off + 1; |
---|
1620 | } |
---|
1621 | return std::string::npos; |
---|
1622 | } |
---|
1623 | |
---|
1624 | void |
---|
1625 | write (files::image& app, |
---|
1626 | const std::string& init, |
---|
1627 | const std::string& fini, |
---|
1628 | const files::object_list& app_objects, |
---|
1629 | const symbols::table& /* symbols */) /* Add back for incremental |
---|
1630 | * linking */ |
---|
1631 | { |
---|
1632 | std::string header; |
---|
1633 | |
---|
1634 | header = "RAP,00000000,0002,LZ77,00000000\n"; |
---|
1635 | app.write (header.c_str (), header.size ()); |
---|
1636 | |
---|
1637 | compress::compressor compressor (app, 2 * 1024); |
---|
1638 | image rap; |
---|
1639 | |
---|
1640 | rap.layout (app_objects, init, fini); |
---|
1641 | rap.write (compressor); |
---|
1642 | |
---|
1643 | compressor.flush (); |
---|
1644 | |
---|
1645 | std::ostringstream length; |
---|
1646 | |
---|
1647 | length << std::setfill ('0') << std::setw (8) |
---|
1648 | << header.size () + compressor.compressed (); |
---|
1649 | |
---|
1650 | header.replace (4, 8, length.str ()); |
---|
1651 | |
---|
1652 | app.seek (0); |
---|
1653 | app.write (header.c_str (), header.size ()); |
---|
1654 | |
---|
1655 | if (rld::verbose () >= RLD_VERBOSE_INFO) |
---|
1656 | { |
---|
1657 | int pcent = (compressor.compressed () * 100) / compressor.transferred (); |
---|
1658 | int premand = (((compressor.compressed () * 1000) + 500) / |
---|
1659 | compressor.transferred ()) % 10; |
---|
1660 | std::cout << "rap: objects: " << app_objects.size () |
---|
1661 | << ", size: " << compressor.compressed () |
---|
1662 | << ", compression: " << pcent << '.' << premand << '%' |
---|
1663 | << std::endl; |
---|
1664 | } |
---|
1665 | } |
---|
1666 | |
---|
1667 | } |
---|
1668 | } |
---|