/* * COPYRIGHT (c) 2012-2013, 2018 Chris Johns * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rtems.org/license/LICENSE. */ /** * @file * * @ingroup rtems_rtld * * @brief RTEMS Run-Time Link Editor * * This is the RAP format loader support.. */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include "rtl-elf.h" #include "rtl-error.h" #include #include "rtl-rap.h" #include #include /** * The offsets in the unresolved array. */ #define REL_R_OFFSET (0) #define REL_R_INFO (1) #define REL_R_ADDEND (2) /** * The ELF format signature. */ static rtems_rtl_loader_format rap_sig = { .label = "RAP", .flags = RTEMS_RTL_FMT_COMP }; /** * The section definitions found in a RAP file. */ typedef struct rtems_rtl_rap_sectdef { const char* name; /**< Name of the section. */ const uint32_t flags; /**< Section flags. */ } rtems_rtl_rap_sectdef; /** * The section indexes. These are fixed. */ #define RTEMS_RTL_RAP_TEXT_SEC (0) #define RTEMS_RTL_RAP_CONST_SEC (1) #define RTEMS_RTL_RAP_CTOR_SEC (2) #define RTEMS_RTL_RAP_DTOR_SEC (3) #define RTEMS_RTL_RAP_DATA_SEC (4) #define RTEMS_RTL_RAP_BSS_SEC (5) #define RTEMS_RTL_RAP_SECS (6) /** * The sections as loaded from a RAP file. */ static const rtems_rtl_rap_sectdef rap_sections[RTEMS_RTL_RAP_SECS] = { { ".text", RTEMS_RTL_OBJ_SECT_TEXT | RTEMS_RTL_OBJ_SECT_LOAD }, { ".const", RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD }, { ".ctor", RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_CTOR }, { ".dtor", RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_DTOR }, { ".data", RTEMS_RTL_OBJ_SECT_DATA | RTEMS_RTL_OBJ_SECT_LOAD }, { ".bss", RTEMS_RTL_OBJ_SECT_BSS | RTEMS_RTL_OBJ_SECT_ZERO } }; /** * The section definitions found in a RAP file. */ typedef struct rtems_rtl_rap_section { uint32_t size; /**< The size of the section. */ uint32_t alignment; /**< The alignment of the section. */ } rtems_rtl_rap_section; /** * The RAP loader. */ typedef struct rtems_rtl_rap { rtems_rtl_obj_cache* file; /**< The file cache for the RAP file. */ rtems_rtl_obj_comp* decomp; /**< The decompression streamer. */ uint32_t length; /**< The file length. */ uint32_t version; /**< The RAP file version. */ uint32_t compression; /**< The type of compression. */ uint32_t checksum; /**< The checksum. */ uint32_t machinetype; /**< The ELF machine type. */ uint32_t datatype; /**< The ELF data type. */ uint32_t class; /**< The ELF class. */ uint32_t init; /**< The initialisation strtab offset. */ uint32_t fini; /**< The finish strtab offset. */ rtems_rtl_rap_section secs[RTEMS_RTL_RAP_SECS]; /**< The sections. */ uint32_t symtab_size; /**< The symbol table size. */ char* strtab; /**< The string table. */ uint32_t strtab_size; /**< The string table size. */ uint32_t relocs_size; /**< The relocation table size. */ uint32_t symbols; /**< The number of symbols. */ uint32_t strtable_size;/**< The size of section names and obj names. */ uint32_t rpathlen; /**< The length of rpath. */ char* strtable; /**< The detail string which resides in obj detail. */ } rtems_rtl_rap; /** * Check the machine type. */ static bool rtems_rtl_rap_machine_check (uint32_t machinetype) { /* * This code is determined by the machine headers. */ switch (machinetype) { ELFDEFNNAME (MACHDEP_ID_CASES) default: return false; } return true; } /** * Check the data type. */ static bool rtems_rtl_rap_datatype_check (uint32_t datatype) { /* * This code is determined by the machine headers. */ if (datatype != ELFDEFNNAME (MACHDEP_ENDIANNESS)) return false; return true; } /** * Check the class of executable. */ static bool rtems_rtl_rap_class_check (uint32_t class) { /* * This code is determined by the machine headers. */ switch (class) { case ELFCLASS32: if (ARCH_ELFSIZE == 32) return true; break; case ELFCLASS64: if (ARCH_ELFSIZE == 64) return true; break; default: break; } return false; } static uint32_t rtems_rtl_rap_get_uint32 (const uint8_t* buffer) { uint32_t value = 0; int b; for (b = 0; b < sizeof (uint32_t); ++b) { value <<= 8; value |= buffer[b]; } return value; } static bool rtems_rtl_rap_read_uint32 (rtems_rtl_obj_comp* comp, uint32_t* value) { uint8_t buffer[sizeof (uint32_t)]; if (!rtems_rtl_obj_comp_read (comp, buffer, sizeof (uint32_t))) return false; *value = rtems_rtl_rap_get_uint32 (buffer); return true; } static bool rtems_rtl_rap_loader (rtems_rtl_obj* obj, int fd, rtems_rtl_obj_sect* sect, void* data) { rtems_rtl_rap* rap = (rtems_rtl_rap*) data; if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD)) printf ("rtl: rap: input %s=%" PRIu32 "\n", sect->name, rtems_rtl_obj_comp_input (rap->decomp)); return rtems_rtl_obj_comp_read (rap->decomp, sect->base, sect->size); } static bool rtems_rtl_rap_relocate (rtems_rtl_rap* rap, rtems_rtl_obj* obj) { #define SYMNAME_BUFFER_SIZE (1024) char* symname_buffer = NULL; int section; if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) printf ("rtl: relocation\n"); symname_buffer = malloc (SYMNAME_BUFFER_SIZE); if (!symname_buffer) { rtems_rtl_set_error (ENOMEM, "no memory for local symbol name buffer"); return false; } for (section = 0; section < RTEMS_RTL_RAP_SECS; ++section) { rtems_rtl_obj_sect* targetsect; uint32_t header = 0; int relocs; bool is_rela; int r; targetsect = rtems_rtl_obj_find_section (obj, rap_sections[section].name); if (!targetsect) continue; if (!rtems_rtl_rap_read_uint32 (rap->decomp, &header)) { free (symname_buffer); return false; } /* * Bit 31 of the header indicates if the relocations for this section * have a valid addend field. */ is_rela = (header & (1 << 31)) != 0 ? true : false; relocs = header & ~(1 << 31); if (relocs && rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) printf ("rtl: relocation: %s: header: %08" PRIx32 " relocs: %d %s\n", rap_sections[section].name, header, relocs, is_rela ? "rela" : "rel"); for (r = 0; r < relocs; ++r) { uint32_t info = 0; uint32_t offset = 0; uint32_t addend = 0; Elf_Word type; const char* symname = NULL; uint32_t symname_size; Elf_Word symtype = 0; Elf_Word symvalue = 0; if (!rtems_rtl_rap_read_uint32 (rap->decomp, &info)) { free (symname_buffer); return false; } if (!rtems_rtl_rap_read_uint32 (rap->decomp, &offset)) { free (symname_buffer); return false; } /* * The types are: * * 0 Section symbol offset in addend. * 1 Symbol appended to the relocation record. * 2 Symbol is in the strtabl. * * If type 2 bits 30:8 is the offset in the strtab. If type 1 the bits * are the size of the string. The lower 8 bits of the info field if the * ELF relocation type field. */ if (((info & (1 << 31)) == 0) || is_rela) { if (!rtems_rtl_rap_read_uint32 (rap->decomp, &addend)) { free (symname_buffer); return false; } } if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) printf (" %2d: info=%08" PRIx32 " offset=%" PRIu32 " addend=%" PRIu32 "\n", r, info, offset, addend); type = info & 0xff; if ((info & (1 << 31)) == 0) { rtems_rtl_obj_sect* symsect; symsect = rtems_rtl_obj_find_section_by_index (obj, info >> 8); if (!symsect) { free (symname_buffer); return false; } symvalue = (Elf_Addr) symsect->base + addend; } else if (rtems_rtl_elf_rel_resolve_sym (type)) { rtems_rtl_obj_sym* symbol; symname_size = (info & ~(3 << 30)) >> 8; if ((info & (1 << 30)) != 0) { symname = rap->strtab + symname_size; } else { if (symname_size > (SYMNAME_BUFFER_SIZE - 1)) { free (symname_buffer); rtems_rtl_set_error (EINVAL, "reloc symbol too big"); return false; } if (!rtems_rtl_obj_comp_read (rap->decomp, symname_buffer, symname_size)) { free (symname_buffer); return false; } symname_buffer[symname_size] = '\0'; symname = symname_buffer; } symbol = rtems_rtl_symbol_obj_find (obj, symname); if (!symbol) { rtems_rtl_set_error (EINVAL, "global symbol not found: %s", symname); free (symname_buffer); return false; } symvalue = (Elf_Addr) symbol->value; } if (is_rela) { Elf_Rela rela; rela.r_offset = offset; rela.r_info = type; if ((info & (1 << 31)) == 0) rela.r_addend = 0; else rela.r_addend = addend; if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) printf (" %2d: rela: type:%-2d off:%" PRIu32 " addend:%d" " symname=%s symtype=%ju symvalue=0x%08jx\n", r, (int) type, offset, (int) addend, symname, (uintmax_t) symtype, (uintmax_t) symvalue); if (!rtems_rtl_elf_relocate_rela (obj, &rela, targetsect, symname, symtype, symvalue)) { free (symname_buffer); return false; } } else { Elf_Rel rel; rel.r_offset = offset; rel.r_info = type; if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) printf (" %2d: rel: type:%-2d off:%" PRIu32 " symname=%s symtype=%ju symvalue=0x%08jx\n", r, (int) type, offset, symname, (uintmax_t) symtype, (uintmax_t) symvalue); if (!rtems_rtl_elf_relocate_rel (obj, &rel, targetsect, symname, symtype, symvalue)) { free (symname_buffer); return false; } } } } free (symname_buffer); return true; } /** * The structure of obj->linkmap is: * * |object_detail(0..obj_num)|section_detail(0..sec_num[0..obj_num])| * obj_name(0..obj_num)|section_name(0..sec_num[0..obj_num]) * */ static bool rtems_rtl_rap_load_linkmap (rtems_rtl_rap* rap, rtems_rtl_obj* obj) { void* detail; struct link_map* tmp1; section_detail* tmp2; uint32_t obj_detail_size; uint32_t pos = 0; int i; int j; obj_detail_size = sizeof (struct link_map) * obj->obj_num; for (i = 0; i < obj->obj_num; ++i) { obj_detail_size += (obj->sec_num[i] * sizeof (section_detail)); } detail = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, obj_detail_size + rap->strtable_size, true); if (!detail) { rap->strtable_size = 0; rtems_rtl_set_error (ENOMEM, "no memory for obj global syms"); return false; } rap->strtable = detail + obj_detail_size; /* * Read the obj names and section names */ if (!rtems_rtl_obj_comp_read (rap->decomp, rap->strtable, rap->strtable_size)) { rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, detail); return false; } obj->linkmap = (struct link_map*) detail; if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL)) { if (rap->rpathlen > 0) printf ("File rpath:\n"); } while (pos < rap->rpathlen) { if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL)) { printf (" %s\n", rap->strtable + pos); } pos = pos + strlen (rap->strtable + pos) + 1; } if (rap->rpathlen > 0) pos = rap->rpathlen; for (i = 0; i < obj->obj_num; ++i) { tmp1 = obj->linkmap + i; tmp1->name = rap->strtable + pos; tmp1->sec_num = obj->sec_num[i]; tmp1->rpathlen = rap->rpathlen; tmp1->rpath = (char*) rap->strtable; pos += strlen (tmp1->name) + 1; if (!i) { tmp1->l_next = NULL; tmp1->l_prev = NULL; } else { (tmp1 - 1)->l_next = tmp1; tmp1->l_prev = tmp1 - 1; tmp1->l_next = NULL; } } tmp2 = (section_detail*) (obj->linkmap + obj->obj_num); for (i = 0; i < obj->obj_num; ++i) { if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL)) { printf ("File %d: %s\n", i, (obj->linkmap + i)->name); printf ("Section: %d sections\n", (unsigned int) obj->sec_num[i]); } obj->linkmap[i].sec_detail = tmp2; for (j = 0; j < obj->sec_num[i]; ++j) { uint32_t name; uint32_t rap_id; uint32_t offset; uint32_t size; if (!rtems_rtl_rap_read_uint32 (rap->decomp, &name) || !rtems_rtl_rap_read_uint32 (rap->decomp, &offset) || !rtems_rtl_rap_read_uint32 (rap->decomp, &size)) { rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->linkmap); obj->linkmap = NULL; return false; } rap_id = offset >> 28; offset = offset & 0xfffffff; tmp2->name = rap->strtable + name; tmp2->offset = offset; tmp2->rap_id = rap_id; tmp2->size = size; pos += strlen (tmp2->name) + 1; if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL)) { printf ("name:%16s offset:0x%08x rap_id:%d size:0x%x\n", tmp2->name, (unsigned int) tmp2->offset, (unsigned int) tmp2->rap_id, (unsigned int) tmp2->size); } tmp2 += 1; } } return true; } static bool rtems_rtl_rap_load_symbols (rtems_rtl_rap* rap, rtems_rtl_obj* obj) { rtems_rtl_obj_sym* gsym; int sym; obj->global_size = rap->symbols * sizeof (rtems_rtl_obj_sym) + rap->strtab_size; obj->global_table = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL, obj->global_size, true); if (!obj->global_table) { obj->global_size = 0; rtems_rtl_set_error (ENOMEM, "no memory for obj global syms"); return false; } obj->global_syms = rap->symbols; rap->strtab = (((char*) obj->global_table) + (rap->symbols * sizeof (rtems_rtl_obj_sym))); if (!rtems_rtl_obj_comp_read (rap->decomp, rap->strtab, rap->strtab_size)) { rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table); return false; } for (sym = 0, gsym = obj->global_table; sym < rap->symbols; ++sym) { rtems_rtl_obj_sect* symsect; uint32_t data; uint32_t name; uint32_t value; if (!rtems_rtl_rap_read_uint32 (rap->decomp, &data) || !rtems_rtl_rap_read_uint32 (rap->decomp, &name) || !rtems_rtl_rap_read_uint32 (rap->decomp, &value)) { rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table); obj->global_table = NULL; obj->global_syms = 0; obj->global_size = 0; return false; } if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL)) printf ("rtl: sym:load: data=0x%08" PRIx32 " name=0x%08" PRIx32 " value=0x%08" PRIx32 "\n", data, name, value); /* * If there is a globally exported symbol already present and this * symbol is not weak raise an error. If the symbol is weak and present * globally ignore this symbol and use the global one and if it is not * present take this symbol global or weak. We accept the first weak * symbol we find and make it globally exported. */ if (rtems_rtl_symbol_global_find (rap->strtab + name) && (ELF_ST_BIND (data & 0xffff) != STB_WEAK)) { rtems_rtl_set_error (EINVAL, "duplicate global symbol: %s", rap->strtab + name); rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table); obj->global_table = NULL; obj->global_syms = 0; obj->global_size = 0; return false; } symsect = rtems_rtl_obj_find_section_by_index (obj, data >> 16); if (!symsect) { rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table); obj->global_table = NULL; obj->global_syms = 0; obj->global_size = 0; rtems_rtl_set_error (EINVAL, "section index not found: %" PRIu32, data >> 16); return false; } rtems_chain_set_off_chain (&gsym->node); gsym->name = rap->strtab + name; gsym->value = (uint8_t*) (value + symsect->base); gsym->data = data & 0xffff; if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL)) printf ("rtl: sym:add:%-2d name:%-20s bind:%-2d type:%-2d val:%8p sect:%d\n", sym, gsym->name, (int) ELF_ST_BIND (data & 0xffff), (int) ELF_ST_TYPE (data & 0xffff), gsym->value, (int) (data >> 16)); ++gsym; } if (obj->global_syms) rtems_rtl_symbol_obj_add (obj); return true; } static bool rtems_rtl_rap_parse_header (uint8_t* rhdr, size_t* rhdr_len, uint32_t* length, uint32_t* version, uint32_t* compression, uint32_t* checksum) { char* sptr = (char*) rhdr; char* eptr; *rhdr_len = 0; /* * "RAP," = 4 bytes, total 4 */ if ((rhdr[0] != 'R') || (rhdr[1] != 'A') || (rhdr[2] != 'P') || (rhdr[3] != ',')) return false; sptr = sptr + 4; /* * "00000000," = 9 bytes, total 13 */ *length = strtoul (sptr, &eptr, 10); if (*eptr != ',') return false; sptr = eptr + 1; /* * "0000," = 5 bytes, total 18 */ *version = strtoul (sptr, &eptr, 10); if (*eptr != ',') return false; sptr = eptr + 1; /* * "NONE," and "LZ77," = 5 bytes, total 23 */ if ((sptr[0] == 'N') && (sptr[1] == 'O') && (sptr[2] == 'N') && (sptr[3] == 'E')) { *compression = RTEMS_RTL_COMP_NONE; eptr = sptr + 4; } else if ((sptr[0] == 'L') && (sptr[1] == 'Z') && (sptr[2] == '7') && (sptr[3] == '7')) { *compression = RTEMS_RTL_COMP_LZ77; eptr = sptr + 4; } else return false; if (*eptr != ',') return false; sptr = eptr + 1; /* * "00000000," = 9 bytes, total 32 */ *checksum = strtoul (sptr, &eptr, 16); /* * "\n" = 1 byte, total 33 */ if (*eptr != '\n') return false; *rhdr_len = ((uint8_t*) eptr) - rhdr + 1; return true; } bool rtems_rtl_rap_file_check (rtems_rtl_obj* obj, int fd) { rtems_rtl_obj_cache* header; uint8_t* rhdr = NULL; size_t rlen = 64; uint32_t length = 0; uint32_t version = 0; uint32_t compression = 0; uint32_t checksum = 0; rtems_rtl_obj_caches (&header, NULL, NULL); if (!rtems_rtl_obj_cache_read (header, fd, obj->ooffset, (void**) &rhdr, &rlen)) return false; if (!rtems_rtl_rap_parse_header (rhdr, &rlen, &length, &version, &compression, &checksum)) return false; return true; } bool rtems_rtl_rap_file_load (rtems_rtl_obj* obj, int fd) { rtems_rtl_rap rap = { 0 }; uint8_t* rhdr = NULL; size_t rlen = 64; int section; rtems_rtl_obj_caches (&rap.file, NULL, NULL); if (!rtems_rtl_obj_cache_read (rap.file, fd, obj->ooffset, (void**) &rhdr, &rlen)) return false; if (!rtems_rtl_rap_parse_header (rhdr, &rlen, &rap.length, &rap.version, &rap.compression, &rap.checksum)) { rtems_rtl_set_error (EINVAL, "invalid RAP file format"); return false; } /* * Set up the decompressor. */ rtems_rtl_obj_decompress (&rap.decomp, rap.file, fd, rap.compression, rlen + obj->ooffset); /* * uint32_t: machinetype * uint32_t: datatype * uint32_t: class */ if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD)) printf ("rtl: rap: input machine=%" PRIu32 "\n", rtems_rtl_obj_comp_input (rap.decomp)); if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.machinetype)) return false; if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD)) printf ("rtl: rap: machinetype=%" PRIu32 "\n", rap.machinetype); if (!rtems_rtl_rap_machine_check (rap.machinetype)) { rtems_rtl_set_error (EINVAL, "invalid machinetype"); return false; } if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.datatype)) return false; if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD)) printf ("rtl: rap: datatype=%" PRIu32 "\n", rap.datatype); if (!rtems_rtl_rap_datatype_check (rap.datatype)) { rtems_rtl_set_error (EINVAL, "invalid datatype"); return false; } if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.class)) return false; if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD)) printf ("rtl: rap: class=%" PRIu32 "\n", rap.class); if (!rtems_rtl_rap_class_check (rap.class)) { rtems_rtl_set_error (EINVAL, "invalid class"); return false; } /* * uint32_t: init * uint32_t: fini * uint32_t: symtab_size * uint32_t: strtab_size * uint32_t: relocs_size */ if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD)) printf ("rtl: rap: input header=%" PRIu32 "\n", rtems_rtl_obj_comp_input (rap.decomp)); if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.init)) return false; if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.fini)) return false; if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.symtab_size)) return false; if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.strtab_size)) return false; if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.relocs_size)) return false; rap.symbols = rap.symtab_size / (3 * sizeof (uint32_t)); if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD)) printf ("rtl: rap: load: symtab=%" PRIu32 " (%" PRIu32 ") strtab=%" PRIu32 " relocs=%" PRIu32 "\n", rap.symtab_size, rap.symbols, rap.strtab_size, rap.relocs_size); /* * Load the details */ if (!rtems_rtl_rap_read_uint32 (rap.decomp, &obj->obj_num)) return false; if (obj->obj_num > 0) { obj->sec_num = (uint32_t*) malloc (sizeof (uint32_t) * obj->obj_num); if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.rpathlen)) return false; uint32_t i; for (i = 0; i < obj->obj_num; ++i) { if (!rtems_rtl_rap_read_uint32 (rap.decomp, &(obj->sec_num[i]))) return false; } if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.strtable_size)) return false; if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL)) printf ("rtl: rap: details: obj_num=%" PRIu32 "\n", obj->obj_num); if (!rtems_rtl_rap_load_linkmap (&rap, obj)) return false; } /* * uint32_t: text_size * uint32_t: text_alignment * uint32_t: const_size * uint32_t: const_alignment * uint32_t: ctor_size * uint32_t: ctor_alignment * uint32_t: dtor_size * uint32_t: dtor_alignment * uint32_t: data_size * uint32_t: data_alignment * uint32_t: bss_size * uint32_t: bss_alignment */ for (section = 0; section < RTEMS_RTL_RAP_SECS; ++section) { if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.secs[section].size)) return false; if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.secs[section].alignment)) return false; if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT)) printf ("rtl: rap: %s: size=%" PRIu32 " align=%" PRIu32 "\n", rap_sections[section].name, rap.secs[section].size, rap.secs[section].alignment); if (!rtems_rtl_obj_add_section (obj, section, rap_sections[section].name, rap.secs[section].size, 0, rap.secs[section].alignment, 0, 0, rap_sections[section].flags)) return false; } /** obj->entry = (void*)(uintptr_t) ehdr.e_entry; */ if (!rtems_rtl_obj_load_sections (obj, fd, rtems_rtl_rap_loader, &rap)) return false; if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD)) printf ("rtl: rap: input symbols=%" PRIu32 "\n", rtems_rtl_obj_comp_input (rap.decomp)); if (!rtems_rtl_rap_load_symbols (&rap, obj)) return false; if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD)) printf ("rtl: rap: input relocs=%" PRIu32 "\n", rtems_rtl_obj_comp_input (rap.decomp)); if (!rtems_rtl_rap_relocate (&rap, obj)) return false; rtems_rtl_obj_synchronize_cache (obj); return true; } bool rtems_rtl_rap_file_unload (rtems_rtl_obj* obj) { (void) obj; return true; } rtems_rtl_loader_format* rtems_rtl_rap_file_sig (void) { return &rap_sig; }