File indexing completed on 2025-05-11 08:24:16
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 #ifdef HAVE_CONFIG_H
0039 #include "config.h"
0040 #endif
0041
0042 #include <errno.h>
0043 #include <fcntl.h>
0044 #include <inttypes.h>
0045 #include <stdlib.h>
0046 #include <string.h>
0047 #include <stdio.h>
0048 #include <unistd.h>
0049
0050 #include <rtems/rtl/rtl.h>
0051 #include "rtl-elf.h"
0052 #include "rtl-error.h"
0053 #include <rtems/rtl/rtl-trace.h>
0054 #include "rtl-trampoline.h"
0055 #include "rtl-unwind.h"
0056 #include <rtems/rtl/rtl-unresolved.h>
0057
0058
0059
0060
0061 #define REL_R_OFFSET (0)
0062 #define REL_R_INFO (1)
0063 #define REL_R_ADDEND (2)
0064
0065
0066
0067
0068 static rtems_rtl_loader_format elf_sig =
0069 {
0070 .label = "ELF",
0071 .flags = RTEMS_RTL_FMT_ELF
0072 };
0073
0074 static const char*
0075 rtems_rtl_elf_sym_type_label (Elf_Byte st_info)
0076 {
0077 const char* label;
0078 switch (ELF_ST_TYPE (st_info))
0079 {
0080 case STT_NOTYPE:
0081 label = "STT_NOTYPE";
0082 break;
0083 case STT_OBJECT:
0084 label = "STT_OBJECT";
0085 break;
0086 case STT_FUNC:
0087 label = "STT_FUNC";
0088 break;
0089 case STT_SECTION:
0090 label = "STT_SECTION";
0091 break;
0092 case STT_FILE:
0093 label = "STT_FILE";
0094 break;
0095 case STT_COMMON:
0096 label = "STT_COMMON";
0097 break;
0098 case STT_TLS:
0099 label = "STT_TLS";
0100 break;
0101 default:
0102 label = "unknown";
0103 break;
0104 }
0105 return label;
0106 }
0107
0108 static const char*
0109 rtems_rtl_elf_sym_bind_label (Elf_Byte st_info)
0110 {
0111 const char* label;
0112 switch (ELF_ST_BIND (st_info))
0113 {
0114 case STB_LOCAL:
0115 label = "STB_LOCAL";
0116 break;
0117 case STB_GLOBAL:
0118 label = "STB_GLOBAL";
0119 break;
0120 case STB_WEAK:
0121 label = "STB_WEAK";
0122 break;
0123 default:
0124 label = "unknown";
0125 break;
0126 }
0127 return label;
0128 }
0129
0130 static bool
0131 rtems_rtl_elf_machine_check (Elf_Ehdr* ehdr)
0132 {
0133
0134
0135
0136 switch (ehdr->e_machine)
0137 {
0138 ELFDEFNNAME (MACHDEP_ID_CASES)
0139 default:
0140 return false;
0141 }
0142 return true;
0143 }
0144
0145 static const char*
0146 rtems_rtl_elf_separated_section (const char* name)
0147 {
0148 struct {
0149 const char* label;
0150 size_t len;
0151 } prefix[] = {
0152 #define SEPARATED_PREFIX(_p) { _p, sizeof (_p) - 1 }
0153 SEPARATED_PREFIX (".text."),
0154 SEPARATED_PREFIX (".rel.text."),
0155 SEPARATED_PREFIX (".data."),
0156 SEPARATED_PREFIX (".rel.data."),
0157 SEPARATED_PREFIX (".rodata."),
0158 SEPARATED_PREFIX (".rel.rodata.")
0159 };
0160 const size_t prefixes = sizeof (prefix) / sizeof (prefix[0]);
0161 size_t p;
0162 for (p = 0; p < prefixes; ++p)
0163 {
0164 if (strncmp (name, prefix[p].label, prefix[p].len) == 0)
0165 return name + prefix[p].len;
0166 }
0167 return NULL;
0168 }
0169
0170 static bool
0171 rtems_rtl_elf_find_symbol (rtems_rtl_obj* obj,
0172 const Elf_Sym* sym,
0173 const char* symname,
0174 rtems_rtl_obj_sym** symbol,
0175 Elf_Word* value)
0176 {
0177 rtems_rtl_obj_sect* sect;
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191 if (ELF_ST_BIND (sym->st_info) == STB_GLOBAL ||
0192 sym->st_shndx == SHN_COMMON ||
0193 ELF_ST_TYPE (sym->st_info) == STT_TLS)
0194 {
0195
0196
0197
0198 *symbol = rtems_rtl_symbol_obj_find (obj, symname);
0199 if (!*symbol)
0200 return false;
0201
0202 *value = (Elf_Addr)(uintptr_t) (*symbol)->value;
0203 return true;
0204 }
0205
0206 *symbol = NULL;
0207
0208 sect = rtems_rtl_obj_find_section_by_index (obj, sym->st_shndx);
0209 if (!sect)
0210 return false;
0211
0212 *value = sym->st_value + (Elf_Addr)(uintptr_t) sect->base;
0213
0214 return true;
0215 }
0216
0217
0218
0219
0220 typedef bool (*rtems_rtl_elf_reloc_handler)(rtems_rtl_obj* obj,
0221 bool is_rela,
0222 void* relbuf,
0223 rtems_rtl_obj_sect* targetsect,
0224 rtems_rtl_obj_sym* symbol,
0225 Elf_Sym* sym,
0226 const char* symname,
0227 Elf_Word symvalue,
0228 bool resolved,
0229 void* data);
0230
0231
0232
0233
0234 typedef struct
0235 {
0236 size_t dependents;
0237 size_t unresolved;
0238 } rtems_rtl_elf_reloc_data;
0239
0240 static bool
0241 rtems_rtl_elf_reloc_parser (rtems_rtl_obj* obj,
0242 bool is_rela,
0243 void* relbuf,
0244 rtems_rtl_obj_sect* targetsect,
0245 rtems_rtl_obj_sym* symbol,
0246 Elf_Sym* sym,
0247 const char* symname,
0248 Elf_Word symvalue,
0249 bool resolved,
0250 void* data)
0251 {
0252 rtems_rtl_elf_reloc_data* rd = (rtems_rtl_elf_reloc_data*) data;
0253 rtems_rtl_word rel_words[3];
0254 rtems_rtl_elf_rel_status rs;
0255
0256
0257
0258
0259 if (ELF_ST_TYPE (sym->st_info) == STT_TLS) {
0260 return true;
0261 }
0262
0263
0264
0265
0266 if (is_rela)
0267 {
0268 const Elf_Rela* rela = (const Elf_Rela*) relbuf;
0269 if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0270 printf ("rtl: rela tramp: sym: %c:%s(%d)=%08jx type:%d off:%08jx addend:%d\n",
0271 ELF_ST_BIND (sym->st_info) == STB_GLOBAL ||
0272 ELF_ST_BIND (sym->st_info) == STB_WEAK ? 'G' : 'L',
0273 symname, (int) ELF_R_SYM (rela->r_info),
0274 (uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info),
0275 (uintmax_t) rela->r_offset, (int) rela->r_addend);
0276 rs = rtems_rtl_elf_relocate_rela_tramp (obj, rela, targetsect,
0277 symname, sym->st_info, symvalue);
0278 rel_words[REL_R_OFFSET] = rela->r_offset;
0279 rel_words[REL_R_INFO] = rela->r_info;
0280 rel_words[REL_R_ADDEND] = rela->r_addend;
0281 }
0282 else
0283 {
0284 const Elf_Rel* rel = (const Elf_Rel*) relbuf;
0285 if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0286 printf ("rtl: rel tramp: sym: %c:%s(%d)=%08jx type:%d off:%08jx\n",
0287 ELF_ST_BIND (sym->st_info) == STB_GLOBAL ||
0288 ELF_ST_BIND (sym->st_info) == STB_WEAK ? 'G' : 'L',
0289 symname, (int) ELF_R_SYM (rel->r_info),
0290 (uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info),
0291 (uintmax_t) rel->r_offset);
0292 rs = rtems_rtl_elf_relocate_rel_tramp (obj, rel, targetsect,
0293 symname, sym->st_info, symvalue);
0294 rel_words[REL_R_OFFSET] = rel->r_offset;
0295 rel_words[REL_R_INFO] = rel->r_info;
0296 rel_words[REL_R_ADDEND] = 0;
0297 }
0298
0299 if (rs == rtems_rtl_elf_rel_failure)
0300 return false;
0301
0302 if (rs == rtems_rtl_elf_rel_tramp_cache || rs == rtems_rtl_elf_rel_tramp_add)
0303 {
0304 uint32_t flags = (is_rela ? 1 : 0) | (resolved ? 0 : 1 << 1) | (sym->st_info << 8);
0305 if (!rtems_rtl_trampoline_add (obj, flags,
0306 targetsect->section, symvalue, rel_words))
0307 return false;
0308 }
0309
0310
0311
0312
0313 if (symname != NULL)
0314 {
0315
0316
0317
0318
0319 rtems_rtl_obj* sobj = rtems_rtl_find_obj_with_symbol (symbol);
0320 if (sobj != NULL)
0321 {
0322
0323
0324
0325
0326 if (sobj != rtems_rtl_baseimage () && obj != sobj &&
0327 (sobj->flags & RTEMS_RTL_OBJ_RELOC_TAG) == 0)
0328 {
0329 sobj->flags |= RTEMS_RTL_OBJ_RELOC_TAG;
0330 ++rd->dependents;
0331 }
0332 }
0333 }
0334
0335 return true;
0336 }
0337
0338 static bool
0339 rtems_rtl_elf_reloc_relocator (rtems_rtl_obj* obj,
0340 bool is_rela,
0341 void* relbuf,
0342 rtems_rtl_obj_sect* targetsect,
0343 rtems_rtl_obj_sym* symbol,
0344 Elf_Sym* sym,
0345 const char* symname,
0346 Elf_Word symvalue,
0347 bool resolved,
0348 void* data)
0349 {
0350 const Elf_Rela* rela = (const Elf_Rela*) relbuf;
0351 const Elf_Rel* rel = (const Elf_Rel*) relbuf;
0352
0353 if (!resolved)
0354 {
0355 uint16_t flags = 0;
0356 rtems_rtl_word rel_words[3];
0357
0358 if (is_rela)
0359 {
0360 flags = 1;
0361 rel_words[REL_R_OFFSET] = rela->r_offset;
0362 rel_words[REL_R_INFO] = rela->r_info;
0363 rel_words[REL_R_ADDEND] = rela->r_addend;
0364 }
0365 else
0366 {
0367 rel_words[REL_R_OFFSET] = rel->r_offset;
0368 rel_words[REL_R_INFO] = rel->r_info;
0369 rel_words[REL_R_ADDEND] = 0;
0370 }
0371
0372 if (!rtems_rtl_unresolved_add (obj,
0373 flags,
0374 symname,
0375 targetsect->section,
0376 rel_words))
0377 return false;
0378
0379 ++obj->unresolved;
0380 }
0381 else
0382 {
0383 rtems_rtl_obj* sobj;
0384 rtems_rtl_elf_rel_status rs;
0385
0386 if (is_rela)
0387 {
0388 if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0389 printf ("rtl: rela: sym:%s(%d)=%08jx type:%d off:%08jx addend:%d\n",
0390 symname, (int) ELF_R_SYM (rela->r_info),
0391 (uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info),
0392 (uintmax_t) rela->r_offset, (int) rela->r_addend);
0393 rs = rtems_rtl_elf_relocate_rela (obj, rela, targetsect,
0394 symname, sym->st_info, symvalue);
0395 if (rs != rtems_rtl_elf_rel_no_error)
0396 return false;
0397 }
0398 else
0399 {
0400 if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0401 printf ("rtl: rel: sym:%s(%d)=%08jx type:%d off:%08jx\n",
0402 symname, (int) ELF_R_SYM (rel->r_info),
0403 (uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info),
0404 (uintmax_t) rel->r_offset);
0405 rs = rtems_rtl_elf_relocate_rel (obj, rel, targetsect,
0406 symname, sym->st_info, symvalue);
0407 if (rs != rtems_rtl_elf_rel_no_error)
0408 return false;
0409 }
0410
0411 sobj = rtems_rtl_find_obj_with_symbol (symbol);
0412
0413 if (rtems_rtl_trace (RTEMS_RTL_TRACE_DEPENDENCY))
0414 printf ("rtl: depend: %s -> %s:%s\n",
0415 obj->oname,
0416 sobj == NULL ? "not-found" : sobj->oname,
0417 symname);
0418
0419 if (sobj != NULL)
0420 {
0421 if (rtems_rtl_obj_add_dependent (obj, sobj))
0422 rtems_rtl_obj_inc_reference (sobj);
0423 }
0424 }
0425
0426 return true;
0427 }
0428
0429 static bool
0430 rtems_rtl_elf_relocate_worker (rtems_rtl_obj* obj,
0431 int fd,
0432 rtems_rtl_obj_sect* sect,
0433 rtems_rtl_elf_reloc_handler handler,
0434 void* data)
0435 {
0436 rtems_rtl_obj_cache* symbols;
0437 rtems_rtl_obj_cache* strings;
0438 rtems_rtl_obj_cache* relocs;
0439 rtems_rtl_obj_sect* targetsect;
0440 rtems_rtl_obj_sect* symsect;
0441 rtems_rtl_obj_sect* strtab;
0442 bool is_rela;
0443 size_t reloc_size;
0444 int reloc;
0445
0446
0447
0448
0449
0450 targetsect = rtems_rtl_obj_find_section_by_index (obj, sect->info);
0451 if (!targetsect)
0452 return true;
0453
0454
0455
0456
0457
0458 if ((targetsect->flags & RTEMS_RTL_OBJ_SECT_LOAD) == 0)
0459 return true;
0460
0461
0462 rtems_rtl_obj_caches (&symbols, &strings, &relocs);
0463
0464 if (!symbols || !strings || !relocs)
0465 return false;
0466
0467 symsect = rtems_rtl_obj_find_section (obj, ".symtab");
0468 if (!symsect)
0469 {
0470 rtems_rtl_set_error (EINVAL, "no .symtab section");
0471 return false;
0472 }
0473
0474 strtab = rtems_rtl_obj_find_section (obj, ".strtab");
0475 if (!strtab)
0476 {
0477 rtems_rtl_set_error (EINVAL, "no .strtab section");
0478 return false;
0479 }
0480
0481 if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0482 printf ("rtl: relocation: %s, syms:%s\n", sect->name, symsect->name);
0483
0484
0485
0486
0487 is_rela = ((sect->flags & RTEMS_RTL_OBJ_SECT_RELA) ==
0488 RTEMS_RTL_OBJ_SECT_RELA) ? true : false;
0489 reloc_size = is_rela ? sizeof (Elf_Rela) : sizeof (Elf_Rel);
0490
0491 for (reloc = 0; reloc < (sect->size / reloc_size); ++reloc)
0492 {
0493 uint8_t relbuf[reloc_size];
0494 const Elf_Rela* rela = (const Elf_Rela*) relbuf;
0495 const Elf_Rel* rel = (const Elf_Rel*) relbuf;
0496 rtems_rtl_obj_sym* symbol = NULL;
0497 Elf_Sym sym;
0498 const char* symname = NULL;
0499 off_t off;
0500 Elf_Word rel_type;
0501 Elf_Word symvalue = 0;
0502 bool resolved;
0503
0504 off = obj->ooffset + sect->offset + (reloc * reloc_size);
0505
0506 if (!rtems_rtl_obj_cache_read_byval (relocs, fd, off,
0507 &relbuf[0], reloc_size))
0508 return false;
0509
0510
0511
0512
0513 if (is_rela)
0514 off = (obj->ooffset + symsect->offset +
0515 (ELF_R_SYM (rela->r_info) * sizeof (sym)));
0516 else
0517 off = (obj->ooffset + symsect->offset +
0518 (ELF_R_SYM (rel->r_info) * sizeof (sym)));
0519
0520 if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off,
0521 &sym, sizeof (sym)))
0522 return false;
0523
0524
0525
0526
0527 if (ELF_ST_TYPE (sym.st_info) == STT_OBJECT ||
0528 ELF_ST_TYPE (sym.st_info) == STT_COMMON ||
0529 ELF_ST_TYPE (sym.st_info) == STT_FUNC ||
0530 ELF_ST_TYPE (sym.st_info) == STT_NOTYPE ||
0531 ELF_ST_TYPE (sym.st_info) == STT_TLS ||
0532 sym.st_shndx == SHN_COMMON)
0533 {
0534 size_t len;
0535 off = obj->ooffset + strtab->offset + sym.st_name;
0536 len = RTEMS_RTL_ELF_STRING_MAX;
0537
0538 if (!rtems_rtl_obj_cache_read (strings, fd, off,
0539 (void**) &symname, &len))
0540 return false;
0541 }
0542
0543
0544
0545
0546
0547
0548
0549 if (is_rela)
0550 rel_type = ELF_R_TYPE(rela->r_info);
0551 else
0552 rel_type = ELF_R_TYPE(rel->r_info);
0553
0554 resolved = true;
0555
0556 if (rtems_rtl_elf_rel_resolve_sym (rel_type))
0557 resolved = rtems_rtl_elf_find_symbol (obj,
0558 &sym, symname,
0559 &symbol, &symvalue);
0560
0561 if (!handler (obj,
0562 is_rela, relbuf, targetsect,
0563 symbol, &sym, symname, symvalue, resolved,
0564 data))
0565 return false;
0566 }
0567
0568
0569
0570
0571 if (obj->unresolved)
0572 obj->flags |= RTEMS_RTL_OBJ_UNRESOLVED;
0573
0574 return true;
0575 }
0576
0577 static bool
0578 rtems_rtl_elf_relocs_parser (rtems_rtl_obj* obj,
0579 int fd,
0580 rtems_rtl_obj_sect* sect,
0581 void* data)
0582 {
0583 bool r = rtems_rtl_elf_relocate_worker (obj, fd, sect,
0584 rtems_rtl_elf_reloc_parser, data);
0585 return r;
0586 }
0587
0588 static bool
0589 rtems_rtl_elf_relocs_locator (rtems_rtl_obj* obj,
0590 int fd,
0591 rtems_rtl_obj_sect* sect,
0592 void* data)
0593 {
0594 return rtems_rtl_elf_relocate_worker (obj, fd, sect,
0595 rtems_rtl_elf_reloc_relocator, data);
0596 }
0597
0598 bool
0599 rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc* reloc,
0600 rtems_rtl_obj_sym* sym)
0601 {
0602 rtems_rtl_obj_sect* sect;
0603 bool is_rela;
0604 Elf_Word symvalue;
0605 rtems_rtl_obj* sobj;
0606 rtems_rtl_elf_rel_status rs;
0607
0608 is_rela = reloc->flags & 1;
0609
0610 sect = rtems_rtl_obj_find_section_by_index (reloc->obj, reloc->sect);
0611 if (!sect)
0612 {
0613 rtems_rtl_set_error (ENOEXEC, "unresolved sect not found");
0614 return false;
0615 }
0616
0617 symvalue = (Elf_Word) (intptr_t) sym->value;
0618 if (is_rela)
0619 {
0620 Elf_Rela rela;
0621 rela.r_offset = reloc->rel[REL_R_OFFSET];
0622 rela.r_info = reloc->rel[REL_R_INFO];
0623 rela.r_addend = reloc->rel[REL_R_ADDEND];
0624 if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0625 printf ("rtl: rela: sym:%d type:%d off:%08jx addend:%d\n",
0626 (int) ELF_R_SYM (rela.r_info), (int) ELF_R_TYPE (rela.r_info),
0627 (uintmax_t) rela.r_offset, (int) rela.r_addend);
0628 rs = rtems_rtl_elf_relocate_rela (reloc->obj, &rela, sect,
0629 sym->name, sym->data, symvalue);
0630 if (rs != rtems_rtl_elf_rel_no_error)
0631 return false;
0632 }
0633 else
0634 {
0635 Elf_Rel rel;
0636 rel.r_offset = reloc->rel[REL_R_OFFSET];
0637 rel.r_info = reloc->rel[REL_R_INFO];
0638 if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0639 printf ("rtl: rel: sym:%d type:%d off:%08jx\n",
0640 (int) ELF_R_SYM (rel.r_info), (int) ELF_R_TYPE (rel.r_info),
0641 (uintmax_t) rel.r_offset);
0642 rs = rtems_rtl_elf_relocate_rel (reloc->obj, &rel, sect,
0643 sym->name, sym->data, symvalue);
0644 if (rs != rtems_rtl_elf_rel_no_error)
0645 return false;
0646 }
0647
0648 if (reloc->obj->unresolved > 0)
0649 {
0650 --reloc->obj->unresolved;
0651 if (reloc->obj->unresolved == 0)
0652 reloc->obj->flags &= ~RTEMS_RTL_OBJ_UNRESOLVED;
0653 }
0654
0655 sobj = rtems_rtl_find_obj_with_symbol (sym);
0656
0657 if (rtems_rtl_trace (RTEMS_RTL_TRACE_DEPENDENCY))
0658 printf ("rtl: depend: %s -> %s:%s\n",
0659 reloc->obj->oname,
0660 sobj == NULL ? "not-found" : sobj->oname,
0661 sym->name);
0662
0663 if (sobj != NULL)
0664 {
0665 if (rtems_rtl_obj_add_dependent (reloc->obj, sobj))
0666 rtems_rtl_obj_inc_reference (sobj);
0667 }
0668
0669 return true;
0670 }
0671
0672
0673
0674
0675 typedef struct
0676 {
0677 size_t size;
0678 uint32_t alignment;
0679 } rtems_rtl_elf_common_data;
0680
0681 static bool
0682 rtems_rtl_elf_common (rtems_rtl_obj* obj,
0683 int fd,
0684 rtems_rtl_obj_sect* sect,
0685 void* data)
0686 {
0687 rtems_rtl_elf_common_data* common = (rtems_rtl_elf_common_data*) data;
0688 rtems_rtl_obj_cache* symbols;
0689 int sym;
0690
0691 rtems_rtl_obj_caches (&symbols, NULL, NULL);
0692
0693 if (!symbols)
0694 return false;
0695
0696
0697
0698
0699
0700 for (sym = 0; sym < (sect->size / sizeof (Elf_Sym)); ++sym)
0701 {
0702 Elf_Sym symbol;
0703 off_t off;
0704
0705 off = obj->ooffset + sect->offset + (sym * sizeof (symbol));
0706
0707 if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off,
0708 &symbol, sizeof (symbol)))
0709 return false;
0710
0711 if ((symbol.st_shndx == SHN_COMMON) &&
0712 ((ELF_ST_TYPE (symbol.st_info) == STT_OBJECT) ||
0713 (ELF_ST_TYPE (symbol.st_info) == STT_COMMON)))
0714 {
0715 if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
0716 printf ("rtl: com:elf:%-2d bind:%-2d type:%-2d size:%d value:%d name:%d\n",
0717 sym, (int) ELF_ST_BIND (symbol.st_info),
0718 (int) ELF_ST_TYPE (symbol.st_info),
0719 (int) symbol.st_size, (int) symbol.st_value,
0720 (int) symbol.st_name);
0721
0722
0723
0724
0725 if (common->size == 0)
0726 common->alignment = symbol.st_value;
0727 common->size +=
0728 rtems_rtl_obj_align (common->size, symbol.st_value) + symbol.st_size;
0729 }
0730 }
0731
0732 return true;
0733 }
0734
0735
0736
0737
0738 typedef struct rtems_rtl_tramp_data
0739 {
0740 bool failure;
0741 rtems_rtl_obj* obj;
0742 size_t count;
0743 size_t total;
0744 } rtems_rtl_tramp_data;
0745
0746 static bool
0747 rtems_rtl_elf_tramp_resolve_reloc (rtems_rtl_unresolv_rec* rec,
0748 void* data)
0749 {
0750 rtems_rtl_tramp_data* td = (rtems_rtl_tramp_data*) data;
0751 if (rec->type == rtems_rtl_trampoline_reloc)
0752 {
0753 const rtems_rtl_tramp_reloc* tramp = &rec->rec.tramp;
0754
0755 ++td->total;
0756
0757 if (tramp->obj == td->obj)
0758 {
0759 const rtems_rtl_obj_sect* targetsect;
0760 Elf_Byte st_info;
0761 Elf_Word symvalue;
0762 rtems_rtl_elf_rel_status rs;
0763 bool* failure = (bool*) data;
0764 const bool is_rela = (tramp->flags & 1) == 1;
0765 const bool unresolved = (tramp->flags & (1 << 1)) != 0;
0766
0767 ++td->count;
0768
0769 targetsect = rtems_rtl_obj_find_section_by_index (tramp->obj, tramp->sect);
0770 st_info = tramp->flags >> 8;
0771 symvalue = tramp->symvalue;
0772
0773 if (is_rela)
0774 {
0775 Elf_Rela rela = {
0776 .r_offset = tramp->rel[REL_R_OFFSET],
0777 .r_info = tramp->rel[REL_R_INFO],
0778 .r_addend = tramp->rel[REL_R_ADDEND]
0779 };
0780 if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0781 printf ("rtl: rela tramp: check: %c(%d)=%08jx type:%d off:%08jx addend:%d\n",
0782 ELF_ST_BIND (st_info) == STB_GLOBAL ||
0783 ELF_ST_BIND (st_info) == STB_WEAK ? 'G' : 'L',
0784 (int) ELF_R_SYM (rela.r_info),
0785 (uintmax_t) symvalue, (int) ELF_R_TYPE (rela.r_info),
0786 (uintmax_t) rela.r_offset, (int) rela.r_addend);
0787 rs = rtems_rtl_elf_relocate_rela_tramp (tramp->obj, &rela, targetsect,
0788 NULL, st_info, symvalue);
0789 }
0790 else
0791 {
0792 Elf_Rel rel = {
0793 .r_offset = tramp->rel[REL_R_OFFSET],
0794 .r_info = tramp->rel[REL_R_INFO],
0795 };
0796 if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0797 printf ("rtl: rel tramp: check: %c(%d)=%08jx type:%d off:%08jx\n",
0798 ELF_ST_BIND (st_info) == STB_GLOBAL ||
0799 ELF_ST_BIND (st_info) == STB_WEAK ? 'G' : 'L',
0800 (int) ELF_R_SYM (rel.r_info),
0801 (uintmax_t) symvalue, (int) ELF_R_TYPE (rel.r_info),
0802 (uintmax_t) rel.r_offset);
0803 rs = rtems_rtl_elf_relocate_rel_tramp (tramp->obj, &rel, targetsect,
0804 NULL, st_info, symvalue);
0805 }
0806
0807 if (unresolved || rs == rtems_rtl_elf_rel_tramp_add)
0808 ++tramp->obj->tramp_slots;
0809 if (rs == rtems_rtl_elf_rel_failure)
0810 {
0811 *failure = true;
0812 return true;
0813 }
0814 }
0815 }
0816
0817 return false;
0818 }
0819
0820 static bool
0821 rtems_rtl_elf_find_trampolines (rtems_rtl_obj* obj, size_t unresolved)
0822 {
0823 rtems_rtl_tramp_data td = { 0 };
0824 td.obj = obj;
0825
0826
0827
0828 rtems_rtl_unresolved_iterate (rtems_rtl_elf_tramp_resolve_reloc, &td);
0829 if (td.failure)
0830 return false;
0831 rtems_rtl_trampoline_remove (obj);
0832 obj->tramp_relocs = obj->tramp_slots;
0833 if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0834 printf ("rtl: tramp:elf: tramps: slots:%zu count:%zu total:%zu\n",
0835 obj->tramp_relocs, td.count, td.total);
0836
0837
0838
0839
0840
0841 obj->tramp_slots += unresolved;
0842 if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0843 printf ("rtl: tramp:elf: slots:%zu (%zu)\n",
0844 obj->tramp_slots, obj->tramp_slots * obj->tramp_slot_size);
0845 return true;
0846 }
0847
0848 static bool
0849 rtems_rtl_elf_dependents (rtems_rtl_obj* obj, rtems_rtl_elf_reloc_data* reloc)
0850 {
0851
0852
0853
0854
0855
0856
0857
0858 if (reloc->dependents > 0 && reloc->unresolved == 0)
0859 {
0860 if (!rtems_rtl_obj_alloc_dependents (obj, reloc->dependents))
0861 return false;
0862 }
0863 return true;
0864 }
0865
0866 static bool
0867 rtems_rtl_elf_symbols_load (rtems_rtl_obj* obj,
0868 int fd,
0869 rtems_rtl_obj_sect* sect,
0870 void* data)
0871 {
0872 rtems_rtl_obj_cache* symbols;
0873 rtems_rtl_obj_cache* strings;
0874 rtems_rtl_obj_sect* strtab;
0875 int locals;
0876 int local_string_space;
0877 rtems_rtl_obj_sym* lsym;
0878 char* lstring;
0879 int globals;
0880 int global_string_space;
0881 rtems_rtl_obj_sym* gsym;
0882 char* gstring;
0883 size_t common_offset;
0884 int sym;
0885
0886 strtab = rtems_rtl_obj_find_section (obj, ".strtab");
0887 if (!strtab)
0888 {
0889 rtems_rtl_set_error (EINVAL, "no .strtab section");
0890 return false;
0891 }
0892
0893 rtems_rtl_obj_caches (&symbols, &strings, NULL);
0894
0895 if (!symbols || !strings)
0896 return false;
0897
0898
0899
0900
0901
0902
0903 globals = 0;
0904 global_string_space = 0;
0905 locals = 0;
0906 local_string_space = 0;
0907
0908 for (sym = 0; sym < (sect->size / sizeof (Elf_Sym)); ++sym)
0909 {
0910 Elf_Sym symbol;
0911 off_t off;
0912 const char* name;
0913 size_t len;
0914
0915 off = obj->ooffset + sect->offset + (sym * sizeof (symbol));
0916
0917 if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off,
0918 &symbol, sizeof (symbol)))
0919 return false;
0920
0921 off = obj->ooffset + strtab->offset + symbol.st_name;
0922 len = RTEMS_RTL_ELF_STRING_MAX;
0923
0924 if (!rtems_rtl_obj_cache_read (strings, fd, off, (void**) &name, &len))
0925 return false;
0926
0927
0928
0929
0930
0931
0932
0933 if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
0934 printf ("rtl: sym:elf:%-4d name:%-4d: %-20s: bind:%-2d:%-12s " \
0935 "type:%-2d:%-10s sect:%-5d size:%-5d value:%d\n",
0936 sym, (int) symbol.st_name, name,
0937 (int) ELF_ST_BIND (symbol.st_info),
0938 rtems_rtl_elf_sym_bind_label (symbol.st_info),
0939 (int) ELF_ST_TYPE (symbol.st_info),
0940 rtems_rtl_elf_sym_type_label (symbol.st_info),
0941 symbol.st_shndx,
0942 (int) symbol.st_size,
0943 (int) symbol.st_value);
0944
0945
0946
0947
0948 if (rtems_rtl_symbol_global_find (name))
0949 continue;
0950
0951 if ((symbol.st_shndx != 0) &&
0952 ((ELF_ST_TYPE (symbol.st_info) == STT_OBJECT) ||
0953 (ELF_ST_TYPE (symbol.st_info) == STT_COMMON) ||
0954 (ELF_ST_TYPE (symbol.st_info) == STT_FUNC) ||
0955 (ELF_ST_TYPE (symbol.st_info) == STT_NOTYPE)))
0956 {
0957
0958
0959
0960 rtems_rtl_obj_sect* symsect;
0961
0962 symsect = rtems_rtl_obj_find_section_by_index (obj, symbol.st_shndx);
0963 if (symsect != NULL)
0964 {
0965 if ((ELF_ST_BIND (symbol.st_info) == STB_GLOBAL) ||
0966 (ELF_ST_BIND (symbol.st_info) == STB_WEAK))
0967 {
0968
0969
0970
0971
0972
0973
0974
0975
0976
0977
0978
0979
0980 if (rtems_rtl_symbol_global_find (name) &&
0981 (ELF_ST_BIND (symbol.st_info) != STB_WEAK))
0982 {
0983 if (!rtems_rtl_obj_aname_valid (obj))
0984 {
0985 rtems_rtl_set_error (ENOMEM, "duplicate global symbol: %s", name);
0986 return false;
0987 }
0988 }
0989 else
0990 {
0991 if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
0992 printf ("rtl: sym:elf:%-4d name:%-4d: %-20s: global\n",
0993 sym, (int) symbol.st_name, name);
0994 ++globals;
0995 global_string_space += strlen (name) + 1;
0996 }
0997 }
0998 else if (ELF_ST_BIND (symbol.st_info) == STB_LOCAL)
0999 {
1000 if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
1001 printf ("rtl: sym:elf:%-4d name:%-4d: %-20s: local\n",
1002 sym, (int) symbol.st_name, name);
1003 ++locals;
1004 local_string_space += strlen (name) + 1;
1005 }
1006 }
1007 }
1008 }
1009
1010 if (locals)
1011 {
1012 obj->local_size = locals * sizeof (rtems_rtl_obj_sym) + local_string_space;
1013 obj->local_table = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL,
1014 obj->local_size, true);
1015 if (!obj->local_table)
1016 {
1017 obj->local_size = 0;
1018 rtems_rtl_set_error (ENOMEM, "no memory for obj local syms");
1019 return false;
1020 }
1021
1022 obj->local_syms = locals;
1023 }
1024
1025 if (globals)
1026 {
1027 obj->global_size = globals * sizeof (rtems_rtl_obj_sym) + global_string_space;
1028 obj->global_table = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL,
1029 obj->global_size, true);
1030 if (!obj->global_table)
1031 {
1032 if (locals)
1033 {
1034 rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->local_table);
1035 obj->local_size = 0;
1036 obj->local_syms = 0;
1037 }
1038 obj->global_size = 0;
1039 rtems_rtl_set_error (ENOMEM, "no memory for obj global syms");
1040 return false;
1041 }
1042
1043 obj->global_syms = globals;
1044 }
1045
1046 lsym = obj->local_table;
1047 lstring =
1048 (((char*) obj->local_table) + (locals * sizeof (rtems_rtl_obj_sym)));
1049 gsym = obj->global_table;
1050 gstring =
1051 (((char*) obj->global_table) + (globals * sizeof (rtems_rtl_obj_sym)));
1052
1053 common_offset = 0;
1054
1055 for (sym = 0; sym < (sect->size / sizeof (Elf_Sym)); ++sym)
1056 {
1057 Elf_Sym symbol;
1058 off_t off;
1059 size_t len;
1060
1061 off = obj->ooffset + sect->offset + (sym * sizeof (symbol));
1062
1063 if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off,
1064 &symbol, sizeof (symbol)))
1065 {
1066 if (obj->local_syms)
1067 {
1068 rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->local_table);
1069 obj->local_table = NULL;
1070 obj->local_size = 0;
1071 obj->local_syms = 0;
1072 }
1073 if (obj->global_syms)
1074 {
1075 rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table);
1076 obj->global_table = NULL;
1077 obj->global_syms = 0;
1078 obj->global_size = 0;
1079 }
1080 return false;
1081 }
1082
1083 if ((symbol.st_shndx != 0) &&
1084 ((ELF_ST_TYPE (symbol.st_info) == STT_OBJECT) ||
1085 (ELF_ST_TYPE (symbol.st_info) == STT_COMMON) ||
1086 (ELF_ST_TYPE (symbol.st_info) == STT_FUNC) ||
1087 (ELF_ST_TYPE (symbol.st_info) == STT_NOTYPE)) &&
1088 ((ELF_ST_BIND (symbol.st_info) == STB_GLOBAL) ||
1089 (ELF_ST_BIND (symbol.st_info) == STB_WEAK) ||
1090 (ELF_ST_BIND (symbol.st_info) == STB_LOCAL)))
1091 {
1092 rtems_rtl_obj_sect* symsect;
1093
1094
1095
1096
1097 symsect = rtems_rtl_obj_find_section_by_index (obj, symbol.st_shndx);
1098
1099 if (symsect != NULL)
1100 {
1101 rtems_rtl_obj_sym* osym;
1102 char* string;
1103 Elf_Word value;
1104 const char* name;
1105
1106 off = obj->ooffset + strtab->offset + symbol.st_name;
1107 len = RTEMS_RTL_ELF_STRING_MAX;
1108
1109 if (!rtems_rtl_obj_cache_read (strings, fd, off, (void**) &name, &len))
1110 return false;
1111
1112
1113
1114
1115 if (rtems_rtl_symbol_global_find (name))
1116 continue;
1117
1118 if ((ELF_ST_BIND (symbol.st_info) == STB_GLOBAL) ||
1119 (ELF_ST_BIND (symbol.st_info) == STB_WEAK))
1120 {
1121 size_t slen = strlen (name) + 1;
1122 if ((gstring + slen) > (char*) obj->global_table + obj->global_size)
1123 string = NULL;
1124 else
1125 {
1126 osym = gsym;
1127 string = gstring;
1128 gstring += slen;
1129 ++gsym;
1130 }
1131 }
1132 else
1133 {
1134 size_t slen = strlen (name) + 1;
1135 if ((lstring + slen) > (char*) obj->local_table + obj->local_size)
1136 string = NULL;
1137 else
1138 {
1139 osym = lsym;
1140 string = lstring;
1141 lstring += slen;
1142 ++lsym;
1143 }
1144 }
1145
1146
1147
1148
1149 if (string == NULL)
1150 {
1151 if (obj->local_syms)
1152 {
1153 rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->local_table);
1154 obj->local_table = NULL;
1155 obj->local_size = 0;
1156 obj->local_syms = 0;
1157 }
1158 if (obj->global_syms)
1159 {
1160 rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table);
1161 obj->global_table = NULL;
1162 obj->global_syms = 0;
1163 obj->global_size = 0;
1164 }
1165 rtems_rtl_set_error (ENOMEM, "syms overlow, parsing/loading size mismatch");
1166 return false;
1167 }
1168
1169
1170
1171
1172 if (symbol.st_shndx == SHN_COMMON)
1173 {
1174 size_t value_off = rtems_rtl_obj_align (common_offset,
1175 symbol.st_value);
1176 common_offset = value_off + symbol.st_size;
1177 value = value_off;
1178 }
1179 else
1180 {
1181 value = symbol.st_value;
1182 }
1183
1184 rtems_chain_set_off_chain (&osym->node);
1185 memcpy (string, name, strlen (name) + 1);
1186 osym->name = string;
1187 osym->value = (void*) (intptr_t) value;
1188 osym->data = symbol.st_shndx;
1189
1190 if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
1191 printf ("rtl: sym:add:%-4d name:%-4d: %-20s: bind:%-2d " \
1192 "type:%-2d val:%-8p sect:%-3d size:%d\n",
1193 sym, (int) symbol.st_name, osym->name,
1194 (int) ELF_ST_BIND (symbol.st_info),
1195 (int) ELF_ST_TYPE (symbol.st_info),
1196 osym->value, symbol.st_shndx,
1197 (int) symbol.st_size);
1198 }
1199 }
1200 }
1201
1202 return true;
1203 }
1204
1205 static bool
1206 rtems_rtl_elf_symbols_locate (rtems_rtl_obj* obj,
1207 int fd,
1208 rtems_rtl_obj_sect* sect,
1209 void* data)
1210 {
1211 int sym;
1212
1213 for (sym = 0; sym < obj->local_syms; ++sym)
1214 {
1215 rtems_rtl_obj_sym* osym = &obj->local_table[sym];
1216 rtems_rtl_obj_sect* symsect;
1217 symsect = rtems_rtl_obj_find_section_by_index (obj, osym->data);
1218 if (symsect)
1219 {
1220 osym->value += (intptr_t) symsect->base;
1221 if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
1222 printf ("rtl: sym:locate:local :%-4d name: %-20s val:%-8p sect:%-3d (%s, %p)\n",
1223 sym, osym->name, osym->value, osym->data,
1224 symsect->name, symsect->base);
1225 }
1226 }
1227
1228 for (sym = 0; sym < obj->global_syms; ++sym)
1229 {
1230 rtems_rtl_obj_sym* osym = &obj->global_table[sym];
1231 rtems_rtl_obj_sect* symsect;
1232 symsect = rtems_rtl_obj_find_section_by_index (obj, osym->data);
1233 if (symsect)
1234 {
1235 osym->value += (intptr_t) symsect->base;
1236 if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
1237 printf ("rtl: sym:locate:global:%-4d name: %-20s val:%-8p sect:%-3d (%s, %p)\n",
1238 sym, osym->name, osym->value, osym->data,
1239 symsect->name, symsect->base);
1240 }
1241 }
1242
1243 if (obj->global_size)
1244 rtems_rtl_symbol_obj_add (obj);
1245
1246 return true;
1247 }
1248
1249 static bool
1250 rtems_rtl_elf_arch_alloc (rtems_rtl_obj* obj,
1251 int fd,
1252 rtems_rtl_obj_sect* sect,
1253 void* data)
1254 {
1255 if (rtems_rtl_obj_sect_is_arch_alloc (sect))
1256 return rtems_rtl_elf_arch_section_alloc (obj, sect);
1257 return true;
1258 }
1259
1260 static bool
1261 rtems_rtl_elf_arch_free (rtems_rtl_obj* obj)
1262 {
1263 int index = -1;
1264 while (true)
1265 {
1266 rtems_rtl_obj_sect* sect;
1267 sect = rtems_rtl_obj_find_section_by_mask (obj,
1268 index,
1269 RTEMS_RTL_OBJ_SECT_ARCH_ALLOC);
1270 if (sect == NULL)
1271 break;
1272 if (!rtems_rtl_elf_arch_section_free (obj, sect))
1273 return false;
1274 index = sect->section;
1275 }
1276 return true;
1277 }
1278
1279 static bool
1280 rtems_rtl_elf_loader (rtems_rtl_obj* obj,
1281 int fd,
1282 rtems_rtl_obj_sect* sect,
1283 void* data)
1284 {
1285 uint8_t* base_offset;
1286 size_t len;
1287
1288 if (lseek (fd, obj->ooffset + sect->offset, SEEK_SET) < 0)
1289 {
1290 rtems_rtl_set_error (errno, "section load seek failed");
1291 return false;
1292 }
1293
1294 base_offset = sect->base;
1295 len = sect->size;
1296
1297 while (len)
1298 {
1299 ssize_t r = read (fd, base_offset, len);
1300 if (r <= 0)
1301 {
1302 rtems_rtl_set_error (errno, "section load read failed");
1303 return false;
1304 }
1305 base_offset += r;
1306 len -= r;
1307 }
1308
1309 return true;
1310 }
1311
1312 static bool
1313 rtems_rtl_elf_parse_sections (rtems_rtl_obj* obj, int fd, Elf_Ehdr* ehdr)
1314 {
1315 rtems_rtl_obj_cache* sects;
1316 rtems_rtl_obj_cache* strings;
1317 int section;
1318 off_t sectstroff;
1319 off_t off;
1320 Elf_Shdr shdr;
1321
1322 rtems_rtl_obj_caches (§s, &strings, NULL);
1323
1324 if (!sects || !strings)
1325 return false;
1326
1327
1328
1329
1330 off = obj->ooffset + ehdr->e_shoff + (ehdr->e_shstrndx * ehdr->e_shentsize);
1331
1332 if (!rtems_rtl_obj_cache_read_byval (sects, fd, off, &shdr, sizeof (shdr)))
1333 return false;
1334
1335 if (shdr.sh_type != SHT_STRTAB)
1336 {
1337 rtems_rtl_set_error (EINVAL, "bad .sectstr section type");
1338 return false;
1339 }
1340
1341 sectstroff = obj->ooffset + shdr.sh_offset;
1342
1343 for (section = 0; section < ehdr->e_shnum; ++section)
1344 {
1345 char* name;
1346 size_t len;
1347 uint32_t flags;
1348
1349
1350
1351
1352 off = obj->ooffset + ehdr->e_shoff + (((uint32_t) section) * ehdr->e_shentsize);
1353
1354 if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
1355 printf ("rtl: section header: %2d: offset=%d\n", section, (int) off);
1356
1357 if (!rtems_rtl_obj_cache_read_byval (sects, fd, off, &shdr, sizeof (shdr)))
1358 return false;
1359
1360 len = RTEMS_RTL_ELF_STRING_MAX;
1361 if (!rtems_rtl_obj_cache_read (strings, fd,
1362 sectstroff + shdr.sh_name,
1363 (void**) &name, &len))
1364 return false;
1365
1366 if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
1367 printf ("rtl: section: %2d: name=%s type=%d flags=%08x link=%d info=%d\n",
1368 section, name, (int) shdr.sh_type, (unsigned int) shdr.sh_flags,
1369 (int) shdr.sh_link, (int) shdr.sh_info);
1370
1371 flags = 0;
1372
1373 switch (shdr.sh_type)
1374 {
1375 case SHT_NULL:
1376
1377
1378
1379 break;
1380
1381 case SHT_PROGBITS:
1382
1383
1384
1385
1386
1387 if ((shdr.sh_flags & SHF_ALLOC) == SHF_ALLOC)
1388 {
1389 if ((shdr.sh_flags & SHF_EXECINSTR) == SHF_EXECINSTR)
1390 flags = RTEMS_RTL_OBJ_SECT_TEXT | RTEMS_RTL_OBJ_SECT_LOAD;
1391 else if ((shdr.sh_flags & SHF_WRITE) == SHF_WRITE)
1392 flags = RTEMS_RTL_OBJ_SECT_DATA | RTEMS_RTL_OBJ_SECT_LOAD;
1393 else
1394 flags = RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD;
1395 }
1396 break;
1397
1398 case SHT_NOBITS:
1399
1400
1401
1402
1403 if ((shdr.sh_flags & (SHF_ALLOC | SHF_WRITE)) == (SHF_ALLOC | SHF_WRITE))
1404 flags = RTEMS_RTL_OBJ_SECT_BSS | RTEMS_RTL_OBJ_SECT_ZERO;
1405 break;
1406
1407 case SHT_RELA:
1408 flags = RTEMS_RTL_OBJ_SECT_RELA | RTEMS_RTL_OBJ_SECT_LOAD;
1409 break;
1410
1411 case SHT_REL:
1412
1413
1414
1415
1416 flags = RTEMS_RTL_OBJ_SECT_REL | RTEMS_RTL_OBJ_SECT_LOAD;
1417 break;
1418
1419 case SHT_SYMTAB:
1420 flags = RTEMS_RTL_OBJ_SECT_SYM;
1421 break;
1422
1423 case SHT_STRTAB:
1424 flags = RTEMS_RTL_OBJ_SECT_STR;
1425 break;
1426
1427 case SHT_INIT_ARRAY:
1428
1429
1430
1431 flags = (RTEMS_RTL_OBJ_SECT_CTOR |
1432 RTEMS_RTL_OBJ_SECT_TEXT |
1433 RTEMS_RTL_OBJ_SECT_LOAD);
1434 break;
1435
1436 case SHT_FINI_ARRAY:
1437
1438
1439
1440 flags = (RTEMS_RTL_OBJ_SECT_DTOR |
1441 RTEMS_RTL_OBJ_SECT_TEXT |
1442 RTEMS_RTL_OBJ_SECT_LOAD);
1443 break;
1444
1445 default:
1446
1447
1448
1449 flags = rtems_rtl_elf_section_flags (obj, &shdr);
1450 if (flags == 0)
1451 {
1452 if (rtems_rtl_trace (RTEMS_RTL_TRACE_WARNING))
1453 printf ("rtl: unsupported section: %2d: type=%02d flags=%02x\n",
1454 section, (int) shdr.sh_type, (int) shdr.sh_flags);
1455 }
1456 break;
1457 }
1458
1459 if (flags != 0)
1460 {
1461
1462
1463
1464
1465
1466
1467 if (rtems_rtl_obj_aname_valid (obj))
1468 {
1469 const char* symname = rtems_rtl_elf_separated_section (name);
1470 if (symname != NULL && rtems_rtl_symbol_global_find (symname))
1471 flags &= ~RTEMS_RTL_OBJ_SECT_LOAD;
1472 }
1473
1474
1475
1476
1477
1478 if ((shdr.sh_flags & SHF_LINK_ORDER) != 0)
1479 flags |= RTEMS_RTL_OBJ_SECT_LINK;
1480
1481
1482
1483
1484 if (strcmp (".ctors", name) == 0)
1485 flags |= RTEMS_RTL_OBJ_SECT_CTOR;
1486 if (strcmp (".dtors", name) == 0)
1487 flags |= RTEMS_RTL_OBJ_SECT_DTOR;
1488
1489 if (rtems_rtl_elf_unwind_parse (obj, name, flags))
1490 {
1491 flags &= ~(RTEMS_RTL_OBJ_SECT_TEXT | RTEMS_RTL_OBJ_SECT_CONST);
1492 flags |= RTEMS_RTL_OBJ_SECT_EH;
1493 }
1494
1495
1496
1497
1498 flags = rtems_rtl_elf_arch_parse_section (obj, section, name, &shdr, flags);
1499 if (flags == 0)
1500 {
1501 if (rtems_rtl_trace (RTEMS_RTL_TRACE_WARNING))
1502 printf ("rtl: unsupported section: %2d: type=%02d flags=%02x\n",
1503 section, (int) shdr.sh_type, (int) shdr.sh_flags);
1504 rtems_rtl_set_error (ENOMEM, "invalid architecture section: %s", name);
1505 return false;
1506 }
1507
1508
1509
1510
1511 if (!rtems_rtl_obj_add_section (obj, section, name,
1512 shdr.sh_size, shdr.sh_offset,
1513 shdr.sh_addralign, shdr.sh_link,
1514 shdr.sh_info, flags))
1515 return false;
1516 }
1517 }
1518
1519 return true;
1520 }
1521
1522 static bool
1523 rtems_rtl_elf_add_common (rtems_rtl_obj* obj, size_t size, uint32_t alignment)
1524 {
1525 if (size > 0)
1526 {
1527 if (!rtems_rtl_obj_add_section (obj, SHN_COMMON, ".common.rtems.rtl",
1528 size, 0, alignment, 0, 0,
1529 RTEMS_RTL_OBJ_SECT_BSS | RTEMS_RTL_OBJ_SECT_ZERO))
1530 return false;
1531 }
1532 return true;
1533 }
1534
1535 bool
1536 rtems_rtl_elf_file_check (rtems_rtl_obj* obj, int fd)
1537 {
1538 rtems_rtl_obj_cache* header;
1539 Elf_Ehdr ehdr;
1540
1541 rtems_rtl_obj_caches (&header, NULL, NULL);
1542
1543 if (!rtems_rtl_obj_cache_read_byval (header, fd, obj->ooffset,
1544 &ehdr, sizeof (ehdr)))
1545 return false;
1546
1547
1548
1549
1550 if ((memcmp (ELFMAG, ehdr.e_ident, SELFMAG) != 0)
1551 || ehdr.e_ident[EI_CLASS] != ELFCLASS)
1552 {
1553 return false;
1554 }
1555
1556 if ((ehdr.e_ident[EI_VERSION] != EV_CURRENT)
1557 || (ehdr.e_version != EV_CURRENT)
1558 || (ehdr.e_ident[EI_DATA] != ELFDEFNNAME (MACHDEP_ENDIANNESS)))
1559 {
1560 return false;
1561 }
1562
1563 return true;
1564 }
1565
1566 static bool
1567 rtems_rtl_elf_load_linkmap (rtems_rtl_obj* obj)
1568 {
1569 rtems_chain_control* sections = NULL;
1570 rtems_chain_node* node = NULL;
1571 int sec_num = 0;
1572 section_detail* sd;
1573 int i = 0;
1574 size_t m;
1575
1576
1577
1578
1579 const uint32_t sect_mask[] = {
1580 RTEMS_RTL_OBJ_SECT_TEXT | RTEMS_RTL_OBJ_SECT_LOAD,
1581 RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD,
1582 RTEMS_RTL_OBJ_SECT_DATA | RTEMS_RTL_OBJ_SECT_LOAD,
1583 RTEMS_RTL_OBJ_SECT_BSS
1584 };
1585 const size_t sect_masks = sizeof (sect_mask) / sizeof (sect_mask[0]);
1586
1587
1588
1589
1590 for (m = 0; m < sect_masks; ++m)
1591 {
1592 sections = &obj->sections;
1593 node = rtems_chain_first (sections);
1594 while (!rtems_chain_is_tail (sections, node))
1595 {
1596 rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
1597 const uint32_t mask = sect_mask[m];
1598 if ((sect->size != 0) && ((sect->flags & mask) == mask))
1599 {
1600 ++sec_num;
1601 }
1602 node = rtems_chain_next (node);
1603 }
1604 }
1605
1606 obj->obj_num = 1;
1607 obj->linkmap = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
1608 sizeof(struct link_map) +
1609 sec_num * sizeof (section_detail), true);
1610 if (!obj->linkmap)
1611 {
1612 rtems_rtl_set_error (ENOMEM, "no memory for obj linkmap");
1613 return false;
1614 }
1615
1616 obj->linkmap->name = obj->oname;
1617 obj->linkmap->sec_num = sec_num;
1618 obj->linkmap->sec_detail = (section_detail*) (obj->linkmap + 1);
1619 obj->linkmap->rpathlen = 0;
1620 obj->linkmap->rpath = NULL;
1621 obj->linkmap->l_next = NULL;
1622 obj->linkmap->l_prev = NULL;
1623 obj->linkmap->sec_addr[rap_text] = obj->text_base;
1624 obj->linkmap->sec_addr[rap_const] = obj->const_base;
1625 obj->linkmap->sec_addr[rap_data] = obj->data_base;
1626 obj->linkmap->sec_addr[rap_bss] = obj->bss_base;
1627
1628 sd = obj->linkmap->sec_detail;
1629
1630 for (m = 0; m < sect_masks; ++m)
1631 {
1632 sections = &obj->sections;
1633 node = rtems_chain_first (sections);
1634 while (!rtems_chain_is_tail (sections, node))
1635 {
1636 rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
1637 const uint32_t mask = sect_mask[m];
1638
1639 if ((sect->size != 0) && ((sect->flags & mask) == mask))
1640 {
1641 sd[i].name = sect->name;
1642 sd[i].size = sect->size;
1643 if ((mask & RTEMS_RTL_OBJ_SECT_TEXT) != 0)
1644 {
1645 sd[i].rap_id = rap_text;
1646 sd[i].offset = sect->base - obj->text_base;
1647 }
1648 if ((mask & RTEMS_RTL_OBJ_SECT_CONST) != 0)
1649 {
1650 sd[i].rap_id = rap_const;
1651 sd[i].offset = sect->base - obj->const_base;
1652 }
1653 if ((mask & RTEMS_RTL_OBJ_SECT_DATA) != 0)
1654 {
1655 sd[i].rap_id = rap_data;
1656 sd[i].offset = sect->base - obj->data_base;
1657 }
1658 if ((mask & RTEMS_RTL_OBJ_SECT_BSS) != 0)
1659 {
1660 sd[i].rap_id = rap_bss;
1661 sd[i].offset = sect->base - obj->bss_base;
1662 }
1663
1664 ++i;
1665 }
1666 node = rtems_chain_next (node);
1667 }
1668 }
1669
1670 return true;
1671 }
1672
1673 bool
1674 rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd)
1675 {
1676 rtems_rtl_obj_cache* header;
1677 Elf_Ehdr ehdr;
1678 rtems_rtl_elf_reloc_data relocs = { 0 };
1679 rtems_rtl_elf_common_data common = { 0 };
1680
1681 rtems_rtl_obj_caches (&header, NULL, NULL);
1682
1683 if (!rtems_rtl_obj_cache_read_byval (header, fd, obj->ooffset,
1684 &ehdr, sizeof (ehdr)))
1685 return false;
1686
1687
1688
1689
1690 if ((memcmp (ELFMAG, ehdr.e_ident, SELFMAG) != 0)
1691 || ehdr.e_ident[EI_CLASS] != ELFCLASS)
1692 {
1693 rtems_rtl_set_error (EINVAL, "invalid ELF file format");
1694 return false;
1695 }
1696
1697 if ((ehdr.e_ident[EI_VERSION] != EV_CURRENT)
1698 || (ehdr.e_version != EV_CURRENT)
1699 || (ehdr.e_ident[EI_DATA] != ELFDEFNNAME (MACHDEP_ENDIANNESS)))
1700 {
1701 rtems_rtl_set_error (EINVAL, "unsupported ELF file version");
1702 return false;
1703 }
1704
1705 if (!rtems_rtl_elf_machine_check (&ehdr))
1706 {
1707 rtems_rtl_set_error (EINVAL, "unsupported machine type");
1708 return false;
1709 }
1710
1711 if (ehdr.e_type == ET_DYN)
1712 {
1713 rtems_rtl_set_error (EINVAL, "unsupported ELF file type");
1714 return false;
1715 }
1716
1717 if (ehdr.e_phentsize != 0)
1718 {
1719 rtems_rtl_set_error (EINVAL, "ELF file contains program headers");
1720 return false;
1721 }
1722
1723 if (ehdr.e_shentsize != sizeof (Elf_Shdr))
1724 {
1725 rtems_rtl_set_error (EINVAL, "invalid ELF section header size");
1726 return false;
1727 }
1728
1729
1730
1731
1732 obj->tramp_slot_size = rtems_rtl_elf_relocate_tramp_max_size ();
1733
1734
1735
1736
1737
1738
1739 if (!rtems_rtl_elf_parse_sections (obj, fd, &ehdr))
1740 return false;
1741
1742
1743
1744
1745 obj->entry = (void*)(uintptr_t) ehdr.e_entry;
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755 if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_common, &common))
1756 return false;
1757 if (!rtems_rtl_elf_add_common (obj, common.size, common.alignment))
1758 return false;
1759 if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols_load, &ehdr))
1760 return false;
1761
1762
1763
1764
1765
1766 if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_parser, &relocs))
1767 return false;
1768
1769
1770
1771
1772
1773 rtems_rtl_alloc_lock ();
1774
1775
1776
1777
1778 if (!rtems_rtl_obj_alloc_sections (obj, fd, rtems_rtl_elf_arch_alloc, &ehdr))
1779 return false;
1780
1781 if (!rtems_rtl_elf_dependents (obj, &relocs))
1782 return false;
1783
1784 if (!rtems_rtl_elf_find_trampolines (obj, relocs.unresolved))
1785 return false;
1786
1787
1788
1789
1790
1791 if (rtems_rtl_obj_has_trampolines (obj))
1792 {
1793 if (!rtems_rtl_obj_resize_sections (obj))
1794 return false;
1795 }
1796
1797 if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols_locate, &ehdr))
1798 return false;
1799
1800
1801
1802
1803 rtems_rtl_alloc_unlock ();
1804
1805
1806
1807
1808 if (!rtems_rtl_obj_load_sections (obj, fd, rtems_rtl_elf_loader, &ehdr))
1809 return false;
1810
1811
1812
1813
1814 if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_locator, &ehdr))
1815 return false;
1816
1817 rtems_rtl_symbol_obj_erase_local (obj);
1818
1819 if (!rtems_rtl_elf_load_linkmap (obj))
1820 {
1821 return false;
1822 }
1823
1824 if (!rtems_rtl_elf_unwind_register (obj))
1825 {
1826 return false;
1827 }
1828
1829 return true;
1830 }
1831
1832 bool
1833 rtems_rtl_elf_file_unload (rtems_rtl_obj* obj)
1834 {
1835 rtems_rtl_elf_arch_free (obj);
1836 rtems_rtl_elf_unwind_deregister (obj);
1837 return true;
1838 }
1839
1840 rtems_rtl_loader_format*
1841 rtems_rtl_elf_file_sig (void)
1842 {
1843 return &elf_sig;
1844 }