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