1*159fb790SPhilippe Mathieu-Daudéstatic void glue(bswap_ehdr, SZ)(struct elfhdr *ehdr) 2*159fb790SPhilippe Mathieu-Daudé{ 3*159fb790SPhilippe Mathieu-Daudé bswap16s(&ehdr->e_type); /* Object file type */ 4*159fb790SPhilippe Mathieu-Daudé bswap16s(&ehdr->e_machine); /* Architecture */ 5*159fb790SPhilippe Mathieu-Daudé bswap32s(&ehdr->e_version); /* Object file version */ 6*159fb790SPhilippe Mathieu-Daudé bswapSZs(&ehdr->e_entry); /* Entry point virtual address */ 7*159fb790SPhilippe Mathieu-Daudé bswapSZs(&ehdr->e_phoff); /* Program header table file offset */ 8*159fb790SPhilippe Mathieu-Daudé bswapSZs(&ehdr->e_shoff); /* Section header table file offset */ 9*159fb790SPhilippe Mathieu-Daudé bswap32s(&ehdr->e_flags); /* Processor-specific flags */ 10*159fb790SPhilippe Mathieu-Daudé bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */ 11*159fb790SPhilippe Mathieu-Daudé bswap16s(&ehdr->e_phentsize); /* Program header table entry size */ 12*159fb790SPhilippe Mathieu-Daudé bswap16s(&ehdr->e_phnum); /* Program header table entry count */ 13*159fb790SPhilippe Mathieu-Daudé bswap16s(&ehdr->e_shentsize); /* Section header table entry size */ 14*159fb790SPhilippe Mathieu-Daudé bswap16s(&ehdr->e_shnum); /* Section header table entry count */ 15*159fb790SPhilippe Mathieu-Daudé bswap16s(&ehdr->e_shstrndx); /* Section header string table index */ 16*159fb790SPhilippe Mathieu-Daudé} 17*159fb790SPhilippe Mathieu-Daudé 18*159fb790SPhilippe Mathieu-Daudéstatic void glue(bswap_phdr, SZ)(struct elf_phdr *phdr) 19*159fb790SPhilippe Mathieu-Daudé{ 20*159fb790SPhilippe Mathieu-Daudé bswap32s(&phdr->p_type); /* Segment type */ 21*159fb790SPhilippe Mathieu-Daudé bswapSZs(&phdr->p_offset); /* Segment file offset */ 22*159fb790SPhilippe Mathieu-Daudé bswapSZs(&phdr->p_vaddr); /* Segment virtual address */ 23*159fb790SPhilippe Mathieu-Daudé bswapSZs(&phdr->p_paddr); /* Segment physical address */ 24*159fb790SPhilippe Mathieu-Daudé bswapSZs(&phdr->p_filesz); /* Segment size in file */ 25*159fb790SPhilippe Mathieu-Daudé bswapSZs(&phdr->p_memsz); /* Segment size in memory */ 26*159fb790SPhilippe Mathieu-Daudé bswap32s(&phdr->p_flags); /* Segment flags */ 27*159fb790SPhilippe Mathieu-Daudé bswapSZs(&phdr->p_align); /* Segment alignment */ 28*159fb790SPhilippe Mathieu-Daudé} 29*159fb790SPhilippe Mathieu-Daudé 30*159fb790SPhilippe Mathieu-Daudéstatic void glue(bswap_shdr, SZ)(struct elf_shdr *shdr) 31*159fb790SPhilippe Mathieu-Daudé{ 32*159fb790SPhilippe Mathieu-Daudé bswap32s(&shdr->sh_name); 33*159fb790SPhilippe Mathieu-Daudé bswap32s(&shdr->sh_type); 34*159fb790SPhilippe Mathieu-Daudé bswapSZs(&shdr->sh_flags); 35*159fb790SPhilippe Mathieu-Daudé bswapSZs(&shdr->sh_addr); 36*159fb790SPhilippe Mathieu-Daudé bswapSZs(&shdr->sh_offset); 37*159fb790SPhilippe Mathieu-Daudé bswapSZs(&shdr->sh_size); 38*159fb790SPhilippe Mathieu-Daudé bswap32s(&shdr->sh_link); 39*159fb790SPhilippe Mathieu-Daudé bswap32s(&shdr->sh_info); 40*159fb790SPhilippe Mathieu-Daudé bswapSZs(&shdr->sh_addralign); 41*159fb790SPhilippe Mathieu-Daudé bswapSZs(&shdr->sh_entsize); 42*159fb790SPhilippe Mathieu-Daudé} 43*159fb790SPhilippe Mathieu-Daudé 44*159fb790SPhilippe Mathieu-Daudéstatic void glue(bswap_sym, SZ)(struct elf_sym *sym) 45*159fb790SPhilippe Mathieu-Daudé{ 46*159fb790SPhilippe Mathieu-Daudé bswap32s(&sym->st_name); 47*159fb790SPhilippe Mathieu-Daudé bswapSZs(&sym->st_value); 48*159fb790SPhilippe Mathieu-Daudé bswapSZs(&sym->st_size); 49*159fb790SPhilippe Mathieu-Daudé bswap16s(&sym->st_shndx); 50*159fb790SPhilippe Mathieu-Daudé} 51*159fb790SPhilippe Mathieu-Daudé 52*159fb790SPhilippe Mathieu-Daudéstatic void glue(bswap_rela, SZ)(struct elf_rela *rela) 53*159fb790SPhilippe Mathieu-Daudé{ 54*159fb790SPhilippe Mathieu-Daudé bswapSZs(&rela->r_offset); 55*159fb790SPhilippe Mathieu-Daudé bswapSZs(&rela->r_info); 56*159fb790SPhilippe Mathieu-Daudé bswapSZs((elf_word *)&rela->r_addend); 57*159fb790SPhilippe Mathieu-Daudé} 58*159fb790SPhilippe Mathieu-Daudé 59*159fb790SPhilippe Mathieu-Daudéstatic struct elf_shdr *glue(find_section, SZ)(struct elf_shdr *shdr_table, 60*159fb790SPhilippe Mathieu-Daudé int n, int type) 61*159fb790SPhilippe Mathieu-Daudé{ 62*159fb790SPhilippe Mathieu-Daudé int i; 63*159fb790SPhilippe Mathieu-Daudé for(i=0;i<n;i++) { 64*159fb790SPhilippe Mathieu-Daudé if (shdr_table[i].sh_type == type) 65*159fb790SPhilippe Mathieu-Daudé return shdr_table + i; 66*159fb790SPhilippe Mathieu-Daudé } 67*159fb790SPhilippe Mathieu-Daudé return NULL; 68*159fb790SPhilippe Mathieu-Daudé} 69*159fb790SPhilippe Mathieu-Daudé 70*159fb790SPhilippe Mathieu-Daudéstatic int glue(symfind, SZ)(const void *s0, const void *s1) 71*159fb790SPhilippe Mathieu-Daudé{ 72*159fb790SPhilippe Mathieu-Daudé hwaddr addr = *(hwaddr *)s0; 73*159fb790SPhilippe Mathieu-Daudé struct elf_sym *sym = (struct elf_sym *)s1; 74*159fb790SPhilippe Mathieu-Daudé int result = 0; 75*159fb790SPhilippe Mathieu-Daudé if (addr < sym->st_value) { 76*159fb790SPhilippe Mathieu-Daudé result = -1; 77*159fb790SPhilippe Mathieu-Daudé } else if (addr >= sym->st_value + sym->st_size) { 78*159fb790SPhilippe Mathieu-Daudé result = 1; 79*159fb790SPhilippe Mathieu-Daudé } 80*159fb790SPhilippe Mathieu-Daudé return result; 81*159fb790SPhilippe Mathieu-Daudé} 82*159fb790SPhilippe Mathieu-Daudé 83*159fb790SPhilippe Mathieu-Daudéstatic const char *glue(lookup_symbol, SZ)(struct syminfo *s, 84*159fb790SPhilippe Mathieu-Daudé hwaddr orig_addr) 85*159fb790SPhilippe Mathieu-Daudé{ 86*159fb790SPhilippe Mathieu-Daudé struct elf_sym *syms = glue(s->disas_symtab.elf, SZ); 87*159fb790SPhilippe Mathieu-Daudé struct elf_sym *sym; 88*159fb790SPhilippe Mathieu-Daudé 89*159fb790SPhilippe Mathieu-Daudé sym = bsearch(&orig_addr, syms, s->disas_num_syms, sizeof(*syms), 90*159fb790SPhilippe Mathieu-Daudé glue(symfind, SZ)); 91*159fb790SPhilippe Mathieu-Daudé if (sym != NULL) { 92*159fb790SPhilippe Mathieu-Daudé return s->disas_strtab + sym->st_name; 93*159fb790SPhilippe Mathieu-Daudé } 94*159fb790SPhilippe Mathieu-Daudé 95*159fb790SPhilippe Mathieu-Daudé return ""; 96*159fb790SPhilippe Mathieu-Daudé} 97*159fb790SPhilippe Mathieu-Daudé 98*159fb790SPhilippe Mathieu-Daudéstatic int glue(symcmp, SZ)(const void *s0, const void *s1) 99*159fb790SPhilippe Mathieu-Daudé{ 100*159fb790SPhilippe Mathieu-Daudé struct elf_sym *sym0 = (struct elf_sym *)s0; 101*159fb790SPhilippe Mathieu-Daudé struct elf_sym *sym1 = (struct elf_sym *)s1; 102*159fb790SPhilippe Mathieu-Daudé return (sym0->st_value < sym1->st_value) 103*159fb790SPhilippe Mathieu-Daudé ? -1 104*159fb790SPhilippe Mathieu-Daudé : ((sym0->st_value > sym1->st_value) ? 1 : 0); 105*159fb790SPhilippe Mathieu-Daudé} 106*159fb790SPhilippe Mathieu-Daudé 107*159fb790SPhilippe Mathieu-Daudéstatic void glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab, 108*159fb790SPhilippe Mathieu-Daudé int clear_lsb, symbol_fn_t sym_cb) 109*159fb790SPhilippe Mathieu-Daudé{ 110*159fb790SPhilippe Mathieu-Daudé struct elf_shdr *symtab, *strtab; 111*159fb790SPhilippe Mathieu-Daudé g_autofree struct elf_shdr *shdr_table = NULL; 112*159fb790SPhilippe Mathieu-Daudé g_autofree struct elf_sym *syms = NULL; 113*159fb790SPhilippe Mathieu-Daudé g_autofree char *str = NULL; 114*159fb790SPhilippe Mathieu-Daudé struct syminfo *s; 115*159fb790SPhilippe Mathieu-Daudé int nsyms, i; 116*159fb790SPhilippe Mathieu-Daudé 117*159fb790SPhilippe Mathieu-Daudé shdr_table = load_at(fd, ehdr->e_shoff, 118*159fb790SPhilippe Mathieu-Daudé sizeof(struct elf_shdr) * ehdr->e_shnum); 119*159fb790SPhilippe Mathieu-Daudé if (!shdr_table) { 120*159fb790SPhilippe Mathieu-Daudé return; 121*159fb790SPhilippe Mathieu-Daudé } 122*159fb790SPhilippe Mathieu-Daudé 123*159fb790SPhilippe Mathieu-Daudé if (must_swab) { 124*159fb790SPhilippe Mathieu-Daudé for (i = 0; i < ehdr->e_shnum; i++) { 125*159fb790SPhilippe Mathieu-Daudé glue(bswap_shdr, SZ)(shdr_table + i); 126*159fb790SPhilippe Mathieu-Daudé } 127*159fb790SPhilippe Mathieu-Daudé } 128*159fb790SPhilippe Mathieu-Daudé 129*159fb790SPhilippe Mathieu-Daudé symtab = glue(find_section, SZ)(shdr_table, ehdr->e_shnum, SHT_SYMTAB); 130*159fb790SPhilippe Mathieu-Daudé if (!symtab) { 131*159fb790SPhilippe Mathieu-Daudé return; 132*159fb790SPhilippe Mathieu-Daudé } 133*159fb790SPhilippe Mathieu-Daudé syms = load_at(fd, symtab->sh_offset, symtab->sh_size); 134*159fb790SPhilippe Mathieu-Daudé if (!syms) { 135*159fb790SPhilippe Mathieu-Daudé return; 136*159fb790SPhilippe Mathieu-Daudé } 137*159fb790SPhilippe Mathieu-Daudé 138*159fb790SPhilippe Mathieu-Daudé nsyms = symtab->sh_size / sizeof(struct elf_sym); 139*159fb790SPhilippe Mathieu-Daudé 140*159fb790SPhilippe Mathieu-Daudé /* String table */ 141*159fb790SPhilippe Mathieu-Daudé if (symtab->sh_link >= ehdr->e_shnum) { 142*159fb790SPhilippe Mathieu-Daudé return; 143*159fb790SPhilippe Mathieu-Daudé } 144*159fb790SPhilippe Mathieu-Daudé strtab = &shdr_table[symtab->sh_link]; 145*159fb790SPhilippe Mathieu-Daudé 146*159fb790SPhilippe Mathieu-Daudé str = load_at(fd, strtab->sh_offset, strtab->sh_size); 147*159fb790SPhilippe Mathieu-Daudé if (!str) { 148*159fb790SPhilippe Mathieu-Daudé return; 149*159fb790SPhilippe Mathieu-Daudé } 150*159fb790SPhilippe Mathieu-Daudé 151*159fb790SPhilippe Mathieu-Daudé i = 0; 152*159fb790SPhilippe Mathieu-Daudé while (i < nsyms) { 153*159fb790SPhilippe Mathieu-Daudé if (must_swab) { 154*159fb790SPhilippe Mathieu-Daudé glue(bswap_sym, SZ)(&syms[i]); 155*159fb790SPhilippe Mathieu-Daudé } 156*159fb790SPhilippe Mathieu-Daudé if (sym_cb) { 157*159fb790SPhilippe Mathieu-Daudé sym_cb(str + syms[i].st_name, syms[i].st_info, 158*159fb790SPhilippe Mathieu-Daudé syms[i].st_value, syms[i].st_size); 159*159fb790SPhilippe Mathieu-Daudé } 160*159fb790SPhilippe Mathieu-Daudé /* We are only interested in function symbols. 161*159fb790SPhilippe Mathieu-Daudé Throw everything else away. */ 162*159fb790SPhilippe Mathieu-Daudé if (syms[i].st_shndx == SHN_UNDEF || 163*159fb790SPhilippe Mathieu-Daudé syms[i].st_shndx >= SHN_LORESERVE || 164*159fb790SPhilippe Mathieu-Daudé ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) { 165*159fb790SPhilippe Mathieu-Daudé nsyms--; 166*159fb790SPhilippe Mathieu-Daudé if (i < nsyms) { 167*159fb790SPhilippe Mathieu-Daudé syms[i] = syms[nsyms]; 168*159fb790SPhilippe Mathieu-Daudé } 169*159fb790SPhilippe Mathieu-Daudé continue; 170*159fb790SPhilippe Mathieu-Daudé } 171*159fb790SPhilippe Mathieu-Daudé if (clear_lsb) { 172*159fb790SPhilippe Mathieu-Daudé /* The bottom address bit marks a Thumb or MIPS16 symbol. */ 173*159fb790SPhilippe Mathieu-Daudé syms[i].st_value &= ~(glue(glue(Elf, SZ), _Addr))1; 174*159fb790SPhilippe Mathieu-Daudé } 175*159fb790SPhilippe Mathieu-Daudé i++; 176*159fb790SPhilippe Mathieu-Daudé } 177*159fb790SPhilippe Mathieu-Daudé 178*159fb790SPhilippe Mathieu-Daudé /* check we have symbols left */ 179*159fb790SPhilippe Mathieu-Daudé if (nsyms == 0) { 180*159fb790SPhilippe Mathieu-Daudé return; 181*159fb790SPhilippe Mathieu-Daudé } 182*159fb790SPhilippe Mathieu-Daudé 183*159fb790SPhilippe Mathieu-Daudé syms = g_realloc(syms, nsyms * sizeof(*syms)); 184*159fb790SPhilippe Mathieu-Daudé qsort(syms, nsyms, sizeof(*syms), glue(symcmp, SZ)); 185*159fb790SPhilippe Mathieu-Daudé for (i = 0; i < nsyms - 1; i++) { 186*159fb790SPhilippe Mathieu-Daudé if (syms[i].st_size == 0) { 187*159fb790SPhilippe Mathieu-Daudé syms[i].st_size = syms[i + 1].st_value - syms[i].st_value; 188*159fb790SPhilippe Mathieu-Daudé } 189*159fb790SPhilippe Mathieu-Daudé } 190*159fb790SPhilippe Mathieu-Daudé 191*159fb790SPhilippe Mathieu-Daudé /* Commit */ 192*159fb790SPhilippe Mathieu-Daudé s = g_malloc0(sizeof(*s)); 193*159fb790SPhilippe Mathieu-Daudé s->lookup_symbol = glue(lookup_symbol, SZ); 194*159fb790SPhilippe Mathieu-Daudé glue(s->disas_symtab.elf, SZ) = g_steal_pointer(&syms); 195*159fb790SPhilippe Mathieu-Daudé s->disas_num_syms = nsyms; 196*159fb790SPhilippe Mathieu-Daudé s->disas_strtab = g_steal_pointer(&str); 197*159fb790SPhilippe Mathieu-Daudé s->next = syminfos; 198*159fb790SPhilippe Mathieu-Daudé syminfos = s; 199*159fb790SPhilippe Mathieu-Daudé} 200*159fb790SPhilippe Mathieu-Daudé 201*159fb790SPhilippe Mathieu-Daudéstatic int glue(elf_reloc, SZ)(struct elfhdr *ehdr, int fd, int must_swab, 202*159fb790SPhilippe Mathieu-Daudé uint64_t (*translate_fn)(void *, uint64_t), 203*159fb790SPhilippe Mathieu-Daudé void *translate_opaque, uint8_t *data, 204*159fb790SPhilippe Mathieu-Daudé struct elf_phdr *ph, int elf_machine) 205*159fb790SPhilippe Mathieu-Daudé{ 206*159fb790SPhilippe Mathieu-Daudé struct elf_shdr *reltab, *shdr_table = NULL; 207*159fb790SPhilippe Mathieu-Daudé struct elf_rela *rels = NULL; 208*159fb790SPhilippe Mathieu-Daudé int nrels, i, ret = -1; 209*159fb790SPhilippe Mathieu-Daudé elf_word wordval; 210*159fb790SPhilippe Mathieu-Daudé void *addr; 211*159fb790SPhilippe Mathieu-Daudé 212*159fb790SPhilippe Mathieu-Daudé shdr_table = load_at(fd, ehdr->e_shoff, 213*159fb790SPhilippe Mathieu-Daudé sizeof(struct elf_shdr) * ehdr->e_shnum); 214*159fb790SPhilippe Mathieu-Daudé if (!shdr_table) { 215*159fb790SPhilippe Mathieu-Daudé return -1; 216*159fb790SPhilippe Mathieu-Daudé } 217*159fb790SPhilippe Mathieu-Daudé if (must_swab) { 218*159fb790SPhilippe Mathieu-Daudé for (i = 0; i < ehdr->e_shnum; i++) { 219*159fb790SPhilippe Mathieu-Daudé glue(bswap_shdr, SZ)(&shdr_table[i]); 220*159fb790SPhilippe Mathieu-Daudé } 221*159fb790SPhilippe Mathieu-Daudé } 222*159fb790SPhilippe Mathieu-Daudé 223*159fb790SPhilippe Mathieu-Daudé reltab = glue(find_section, SZ)(shdr_table, ehdr->e_shnum, SHT_RELA); 224*159fb790SPhilippe Mathieu-Daudé if (!reltab) { 225*159fb790SPhilippe Mathieu-Daudé goto fail; 226*159fb790SPhilippe Mathieu-Daudé } 227*159fb790SPhilippe Mathieu-Daudé rels = load_at(fd, reltab->sh_offset, reltab->sh_size); 228*159fb790SPhilippe Mathieu-Daudé if (!rels) { 229*159fb790SPhilippe Mathieu-Daudé goto fail; 230*159fb790SPhilippe Mathieu-Daudé } 231*159fb790SPhilippe Mathieu-Daudé nrels = reltab->sh_size / sizeof(struct elf_rela); 232*159fb790SPhilippe Mathieu-Daudé 233*159fb790SPhilippe Mathieu-Daudé for (i = 0; i < nrels; i++) { 234*159fb790SPhilippe Mathieu-Daudé if (must_swab) { 235*159fb790SPhilippe Mathieu-Daudé glue(bswap_rela, SZ)(&rels[i]); 236*159fb790SPhilippe Mathieu-Daudé } 237*159fb790SPhilippe Mathieu-Daudé if (rels[i].r_offset < ph->p_vaddr || 238*159fb790SPhilippe Mathieu-Daudé rels[i].r_offset >= ph->p_vaddr + ph->p_filesz) { 239*159fb790SPhilippe Mathieu-Daudé continue; 240*159fb790SPhilippe Mathieu-Daudé } 241*159fb790SPhilippe Mathieu-Daudé addr = &data[rels[i].r_offset - ph->p_vaddr]; 242*159fb790SPhilippe Mathieu-Daudé switch (elf_machine) { 243*159fb790SPhilippe Mathieu-Daudé case EM_S390: 244*159fb790SPhilippe Mathieu-Daudé switch (rels[i].r_info) { 245*159fb790SPhilippe Mathieu-Daudé case R_390_RELATIVE: 246*159fb790SPhilippe Mathieu-Daudé wordval = *(elf_word *)addr; 247*159fb790SPhilippe Mathieu-Daudé if (must_swab) { 248*159fb790SPhilippe Mathieu-Daudé bswapSZs(&wordval); 249*159fb790SPhilippe Mathieu-Daudé } 250*159fb790SPhilippe Mathieu-Daudé wordval = translate_fn(translate_opaque, wordval); 251*159fb790SPhilippe Mathieu-Daudé if (must_swab) { 252*159fb790SPhilippe Mathieu-Daudé bswapSZs(&wordval); 253*159fb790SPhilippe Mathieu-Daudé } 254*159fb790SPhilippe Mathieu-Daudé *(elf_word *)addr = wordval; 255*159fb790SPhilippe Mathieu-Daudé break; 256*159fb790SPhilippe Mathieu-Daudé default: 257*159fb790SPhilippe Mathieu-Daudé fprintf(stderr, "Unsupported relocation type %i!\n", 258*159fb790SPhilippe Mathieu-Daudé (int)rels[i].r_info); 259*159fb790SPhilippe Mathieu-Daudé } 260*159fb790SPhilippe Mathieu-Daudé } 261*159fb790SPhilippe Mathieu-Daudé } 262*159fb790SPhilippe Mathieu-Daudé 263*159fb790SPhilippe Mathieu-Daudé ret = 0; 264*159fb790SPhilippe Mathieu-Daudéfail: 265*159fb790SPhilippe Mathieu-Daudé g_free(rels); 266*159fb790SPhilippe Mathieu-Daudé g_free(shdr_table); 267*159fb790SPhilippe Mathieu-Daudé return ret; 268*159fb790SPhilippe Mathieu-Daudé} 269*159fb790SPhilippe Mathieu-Daudé 270*159fb790SPhilippe Mathieu-Daudé/* 271*159fb790SPhilippe Mathieu-Daudé * Given 'nhdr', a pointer to a range of ELF Notes, search through them 272*159fb790SPhilippe Mathieu-Daudé * for a note matching type 'elf_note_type' and return a pointer to 273*159fb790SPhilippe Mathieu-Daudé * the matching ELF note. 274*159fb790SPhilippe Mathieu-Daudé */ 275*159fb790SPhilippe Mathieu-Daudéstatic struct elf_note *glue(get_elf_note_type, SZ)(struct elf_note *nhdr, 276*159fb790SPhilippe Mathieu-Daudé elf_word note_size, 277*159fb790SPhilippe Mathieu-Daudé elf_word phdr_align, 278*159fb790SPhilippe Mathieu-Daudé elf_word elf_note_type) 279*159fb790SPhilippe Mathieu-Daudé{ 280*159fb790SPhilippe Mathieu-Daudé elf_word nhdr_size = sizeof(struct elf_note); 281*159fb790SPhilippe Mathieu-Daudé elf_word elf_note_entry_offset = 0; 282*159fb790SPhilippe Mathieu-Daudé elf_word note_type; 283*159fb790SPhilippe Mathieu-Daudé elf_word nhdr_namesz; 284*159fb790SPhilippe Mathieu-Daudé elf_word nhdr_descsz; 285*159fb790SPhilippe Mathieu-Daudé 286*159fb790SPhilippe Mathieu-Daudé if (nhdr == NULL) { 287*159fb790SPhilippe Mathieu-Daudé return NULL; 288*159fb790SPhilippe Mathieu-Daudé } 289*159fb790SPhilippe Mathieu-Daudé 290*159fb790SPhilippe Mathieu-Daudé note_type = nhdr->n_type; 291*159fb790SPhilippe Mathieu-Daudé while (note_type != elf_note_type) { 292*159fb790SPhilippe Mathieu-Daudé nhdr_namesz = nhdr->n_namesz; 293*159fb790SPhilippe Mathieu-Daudé nhdr_descsz = nhdr->n_descsz; 294*159fb790SPhilippe Mathieu-Daudé 295*159fb790SPhilippe Mathieu-Daudé elf_note_entry_offset = nhdr_size + 296*159fb790SPhilippe Mathieu-Daudé QEMU_ALIGN_UP(nhdr_namesz, phdr_align) + 297*159fb790SPhilippe Mathieu-Daudé QEMU_ALIGN_UP(nhdr_descsz, phdr_align); 298*159fb790SPhilippe Mathieu-Daudé 299*159fb790SPhilippe Mathieu-Daudé /* 300*159fb790SPhilippe Mathieu-Daudé * If the offset calculated in this iteration exceeds the 301*159fb790SPhilippe Mathieu-Daudé * supplied size, we are done and no matching note was found. 302*159fb790SPhilippe Mathieu-Daudé */ 303*159fb790SPhilippe Mathieu-Daudé if (elf_note_entry_offset > note_size) { 304*159fb790SPhilippe Mathieu-Daudé return NULL; 305*159fb790SPhilippe Mathieu-Daudé } 306*159fb790SPhilippe Mathieu-Daudé 307*159fb790SPhilippe Mathieu-Daudé /* skip to the next ELF Note entry */ 308*159fb790SPhilippe Mathieu-Daudé nhdr = (void *)nhdr + elf_note_entry_offset; 309*159fb790SPhilippe Mathieu-Daudé note_type = nhdr->n_type; 310*159fb790SPhilippe Mathieu-Daudé } 311*159fb790SPhilippe Mathieu-Daudé 312*159fb790SPhilippe Mathieu-Daudé return nhdr; 313*159fb790SPhilippe Mathieu-Daudé} 314*159fb790SPhilippe Mathieu-Daudé 315*159fb790SPhilippe Mathieu-Daudéstatic ssize_t glue(load_elf, SZ)(const char *name, int fd, 316*159fb790SPhilippe Mathieu-Daudé uint64_t (*elf_note_fn)(void *, void *, bool), 317*159fb790SPhilippe Mathieu-Daudé uint64_t (*translate_fn)(void *, uint64_t), 318*159fb790SPhilippe Mathieu-Daudé void *translate_opaque, 319*159fb790SPhilippe Mathieu-Daudé int must_swab, uint64_t *pentry, 320*159fb790SPhilippe Mathieu-Daudé uint64_t *lowaddr, uint64_t *highaddr, 321*159fb790SPhilippe Mathieu-Daudé uint32_t *pflags, int elf_machine, 322*159fb790SPhilippe Mathieu-Daudé int clear_lsb, int data_swab, 323*159fb790SPhilippe Mathieu-Daudé AddressSpace *as, bool load_rom, 324*159fb790SPhilippe Mathieu-Daudé symbol_fn_t sym_cb) 325*159fb790SPhilippe Mathieu-Daudé{ 326*159fb790SPhilippe Mathieu-Daudé struct elfhdr ehdr; 327*159fb790SPhilippe Mathieu-Daudé struct elf_phdr *phdr = NULL, *ph; 328*159fb790SPhilippe Mathieu-Daudé int size, i; 329*159fb790SPhilippe Mathieu-Daudé ssize_t total_size; 330*159fb790SPhilippe Mathieu-Daudé elf_word mem_size, file_size, data_offset; 331*159fb790SPhilippe Mathieu-Daudé uint64_t addr, low = (uint64_t)-1, high = 0; 332*159fb790SPhilippe Mathieu-Daudé GMappedFile *mapped_file = NULL; 333*159fb790SPhilippe Mathieu-Daudé uint8_t *data = NULL; 334*159fb790SPhilippe Mathieu-Daudé ssize_t ret = ELF_LOAD_FAILED; 335*159fb790SPhilippe Mathieu-Daudé 336*159fb790SPhilippe Mathieu-Daudé if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) 337*159fb790SPhilippe Mathieu-Daudé goto fail; 338*159fb790SPhilippe Mathieu-Daudé if (must_swab) { 339*159fb790SPhilippe Mathieu-Daudé glue(bswap_ehdr, SZ)(&ehdr); 340*159fb790SPhilippe Mathieu-Daudé } 341*159fb790SPhilippe Mathieu-Daudé 342*159fb790SPhilippe Mathieu-Daudé if (elf_machine <= EM_NONE) { 343*159fb790SPhilippe Mathieu-Daudé /* The caller didn't specify an ARCH, we can figure it out */ 344*159fb790SPhilippe Mathieu-Daudé elf_machine = ehdr.e_machine; 345*159fb790SPhilippe Mathieu-Daudé } 346*159fb790SPhilippe Mathieu-Daudé 347*159fb790SPhilippe Mathieu-Daudé switch (elf_machine) { 348*159fb790SPhilippe Mathieu-Daudé case EM_PPC64: 349*159fb790SPhilippe Mathieu-Daudé if (ehdr.e_machine != EM_PPC64) { 350*159fb790SPhilippe Mathieu-Daudé if (ehdr.e_machine != EM_PPC) { 351*159fb790SPhilippe Mathieu-Daudé ret = ELF_LOAD_WRONG_ARCH; 352*159fb790SPhilippe Mathieu-Daudé goto fail; 353*159fb790SPhilippe Mathieu-Daudé } 354*159fb790SPhilippe Mathieu-Daudé } 355*159fb790SPhilippe Mathieu-Daudé break; 356*159fb790SPhilippe Mathieu-Daudé case EM_X86_64: 357*159fb790SPhilippe Mathieu-Daudé if (ehdr.e_machine != EM_X86_64) { 358*159fb790SPhilippe Mathieu-Daudé if (ehdr.e_machine != EM_386) { 359*159fb790SPhilippe Mathieu-Daudé ret = ELF_LOAD_WRONG_ARCH; 360*159fb790SPhilippe Mathieu-Daudé goto fail; 361*159fb790SPhilippe Mathieu-Daudé } 362*159fb790SPhilippe Mathieu-Daudé } 363*159fb790SPhilippe Mathieu-Daudé break; 364*159fb790SPhilippe Mathieu-Daudé case EM_MICROBLAZE: 365*159fb790SPhilippe Mathieu-Daudé if (ehdr.e_machine != EM_MICROBLAZE) { 366*159fb790SPhilippe Mathieu-Daudé if (ehdr.e_machine != EM_MICROBLAZE_OLD) { 367*159fb790SPhilippe Mathieu-Daudé ret = ELF_LOAD_WRONG_ARCH; 368*159fb790SPhilippe Mathieu-Daudé goto fail; 369*159fb790SPhilippe Mathieu-Daudé } 370*159fb790SPhilippe Mathieu-Daudé } 371*159fb790SPhilippe Mathieu-Daudé break; 372*159fb790SPhilippe Mathieu-Daudé case EM_MIPS: 373*159fb790SPhilippe Mathieu-Daudé case EM_NANOMIPS: 374*159fb790SPhilippe Mathieu-Daudé if ((ehdr.e_machine != EM_MIPS) && 375*159fb790SPhilippe Mathieu-Daudé (ehdr.e_machine != EM_NANOMIPS)) { 376*159fb790SPhilippe Mathieu-Daudé ret = ELF_LOAD_WRONG_ARCH; 377*159fb790SPhilippe Mathieu-Daudé goto fail; 378*159fb790SPhilippe Mathieu-Daudé } 379*159fb790SPhilippe Mathieu-Daudé break; 380*159fb790SPhilippe Mathieu-Daudé default: 381*159fb790SPhilippe Mathieu-Daudé if (elf_machine != ehdr.e_machine) { 382*159fb790SPhilippe Mathieu-Daudé ret = ELF_LOAD_WRONG_ARCH; 383*159fb790SPhilippe Mathieu-Daudé goto fail; 384*159fb790SPhilippe Mathieu-Daudé } 385*159fb790SPhilippe Mathieu-Daudé } 386*159fb790SPhilippe Mathieu-Daudé 387*159fb790SPhilippe Mathieu-Daudé if (pflags) { 388*159fb790SPhilippe Mathieu-Daudé *pflags = ehdr.e_flags; 389*159fb790SPhilippe Mathieu-Daudé } 390*159fb790SPhilippe Mathieu-Daudé if (pentry) { 391*159fb790SPhilippe Mathieu-Daudé *pentry = ehdr.e_entry; 392*159fb790SPhilippe Mathieu-Daudé } 393*159fb790SPhilippe Mathieu-Daudé 394*159fb790SPhilippe Mathieu-Daudé glue(load_symbols, SZ)(&ehdr, fd, must_swab, clear_lsb, sym_cb); 395*159fb790SPhilippe Mathieu-Daudé 396*159fb790SPhilippe Mathieu-Daudé size = ehdr.e_phnum * sizeof(phdr[0]); 397*159fb790SPhilippe Mathieu-Daudé if (lseek(fd, ehdr.e_phoff, SEEK_SET) != ehdr.e_phoff) { 398*159fb790SPhilippe Mathieu-Daudé goto fail; 399*159fb790SPhilippe Mathieu-Daudé } 400*159fb790SPhilippe Mathieu-Daudé phdr = g_malloc0(size); 401*159fb790SPhilippe Mathieu-Daudé if (!phdr) 402*159fb790SPhilippe Mathieu-Daudé goto fail; 403*159fb790SPhilippe Mathieu-Daudé if (read(fd, phdr, size) != size) 404*159fb790SPhilippe Mathieu-Daudé goto fail; 405*159fb790SPhilippe Mathieu-Daudé if (must_swab) { 406*159fb790SPhilippe Mathieu-Daudé for(i = 0; i < ehdr.e_phnum; i++) { 407*159fb790SPhilippe Mathieu-Daudé ph = &phdr[i]; 408*159fb790SPhilippe Mathieu-Daudé glue(bswap_phdr, SZ)(ph); 409*159fb790SPhilippe Mathieu-Daudé } 410*159fb790SPhilippe Mathieu-Daudé } 411*159fb790SPhilippe Mathieu-Daudé 412*159fb790SPhilippe Mathieu-Daudé /* 413*159fb790SPhilippe Mathieu-Daudé * Since we want to be able to modify the mapped buffer, we set the 414*159fb790SPhilippe Mathieu-Daudé * 'writable' parameter to 'true'. Modifications to the buffer are not 415*159fb790SPhilippe Mathieu-Daudé * written back to the file. 416*159fb790SPhilippe Mathieu-Daudé */ 417*159fb790SPhilippe Mathieu-Daudé mapped_file = g_mapped_file_new_from_fd(fd, true, NULL); 418*159fb790SPhilippe Mathieu-Daudé if (!mapped_file) { 419*159fb790SPhilippe Mathieu-Daudé goto fail; 420*159fb790SPhilippe Mathieu-Daudé } 421*159fb790SPhilippe Mathieu-Daudé 422*159fb790SPhilippe Mathieu-Daudé total_size = 0; 423*159fb790SPhilippe Mathieu-Daudé for(i = 0; i < ehdr.e_phnum; i++) { 424*159fb790SPhilippe Mathieu-Daudé ph = &phdr[i]; 425*159fb790SPhilippe Mathieu-Daudé if (ph->p_type == PT_LOAD) { 426*159fb790SPhilippe Mathieu-Daudé mem_size = ph->p_memsz; /* Size of the ROM */ 427*159fb790SPhilippe Mathieu-Daudé file_size = ph->p_filesz; /* Size of the allocated data */ 428*159fb790SPhilippe Mathieu-Daudé data_offset = ph->p_offset; /* Offset where the data is located */ 429*159fb790SPhilippe Mathieu-Daudé 430*159fb790SPhilippe Mathieu-Daudé if (file_size > 0) { 431*159fb790SPhilippe Mathieu-Daudé if (g_mapped_file_get_length(mapped_file) < 432*159fb790SPhilippe Mathieu-Daudé file_size + data_offset) { 433*159fb790SPhilippe Mathieu-Daudé goto fail; 434*159fb790SPhilippe Mathieu-Daudé } 435*159fb790SPhilippe Mathieu-Daudé 436*159fb790SPhilippe Mathieu-Daudé data = (uint8_t *)g_mapped_file_get_contents(mapped_file); 437*159fb790SPhilippe Mathieu-Daudé data += data_offset; 438*159fb790SPhilippe Mathieu-Daudé } 439*159fb790SPhilippe Mathieu-Daudé 440*159fb790SPhilippe Mathieu-Daudé /* The ELF spec is somewhat vague about the purpose of the 441*159fb790SPhilippe Mathieu-Daudé * physical address field. One common use in the embedded world 442*159fb790SPhilippe Mathieu-Daudé * is that physical address field specifies the load address 443*159fb790SPhilippe Mathieu-Daudé * and the virtual address field specifies the execution address. 444*159fb790SPhilippe Mathieu-Daudé * Segments are packed into ROM or flash, and the relocation 445*159fb790SPhilippe Mathieu-Daudé * and zero-initialization of data is done at runtime. This 446*159fb790SPhilippe Mathieu-Daudé * means that the memsz header represents the runtime size of the 447*159fb790SPhilippe Mathieu-Daudé * segment, but the filesz represents the loadtime size. If 448*159fb790SPhilippe Mathieu-Daudé * we try to honour the memsz value for an ELF file like this 449*159fb790SPhilippe Mathieu-Daudé * we will end up with overlapping segments (which the 450*159fb790SPhilippe Mathieu-Daudé * loader.c code will later reject). 451*159fb790SPhilippe Mathieu-Daudé * We support ELF files using this scheme by by checking whether 452*159fb790SPhilippe Mathieu-Daudé * paddr + memsz for this segment would overlap with any other 453*159fb790SPhilippe Mathieu-Daudé * segment. If so, then we assume it's using this scheme and 454*159fb790SPhilippe Mathieu-Daudé * truncate the loaded segment to the filesz size. 455*159fb790SPhilippe Mathieu-Daudé * If the segment considered as being memsz size doesn't overlap 456*159fb790SPhilippe Mathieu-Daudé * then we use memsz for the segment length, to handle ELF files 457*159fb790SPhilippe Mathieu-Daudé * which assume that the loader will do the zero-initialization. 458*159fb790SPhilippe Mathieu-Daudé */ 459*159fb790SPhilippe Mathieu-Daudé if (mem_size > file_size) { 460*159fb790SPhilippe Mathieu-Daudé /* If this segment's zero-init portion overlaps another 461*159fb790SPhilippe Mathieu-Daudé * segment's data or zero-init portion, then truncate this one. 462*159fb790SPhilippe Mathieu-Daudé * Invalid ELF files where the segments overlap even when 463*159fb790SPhilippe Mathieu-Daudé * only file_size bytes are loaded will be rejected by 464*159fb790SPhilippe Mathieu-Daudé * the ROM overlap check in loader.c, so we don't try to 465*159fb790SPhilippe Mathieu-Daudé * explicitly detect those here. 466*159fb790SPhilippe Mathieu-Daudé */ 467*159fb790SPhilippe Mathieu-Daudé int j; 468*159fb790SPhilippe Mathieu-Daudé elf_word zero_start = ph->p_paddr + file_size; 469*159fb790SPhilippe Mathieu-Daudé elf_word zero_end = ph->p_paddr + mem_size; 470*159fb790SPhilippe Mathieu-Daudé 471*159fb790SPhilippe Mathieu-Daudé for (j = 0; j < ehdr.e_phnum; j++) { 472*159fb790SPhilippe Mathieu-Daudé struct elf_phdr *jph = &phdr[j]; 473*159fb790SPhilippe Mathieu-Daudé 474*159fb790SPhilippe Mathieu-Daudé if (i != j && jph->p_type == PT_LOAD) { 475*159fb790SPhilippe Mathieu-Daudé elf_word other_start = jph->p_paddr; 476*159fb790SPhilippe Mathieu-Daudé elf_word other_end = jph->p_paddr + jph->p_memsz; 477*159fb790SPhilippe Mathieu-Daudé 478*159fb790SPhilippe Mathieu-Daudé if (!(other_start >= zero_end || 479*159fb790SPhilippe Mathieu-Daudé zero_start >= other_end)) { 480*159fb790SPhilippe Mathieu-Daudé mem_size = file_size; 481*159fb790SPhilippe Mathieu-Daudé break; 482*159fb790SPhilippe Mathieu-Daudé } 483*159fb790SPhilippe Mathieu-Daudé } 484*159fb790SPhilippe Mathieu-Daudé } 485*159fb790SPhilippe Mathieu-Daudé } 486*159fb790SPhilippe Mathieu-Daudé 487*159fb790SPhilippe Mathieu-Daudé if (mem_size > SSIZE_MAX - total_size) { 488*159fb790SPhilippe Mathieu-Daudé ret = ELF_LOAD_TOO_BIG; 489*159fb790SPhilippe Mathieu-Daudé goto fail; 490*159fb790SPhilippe Mathieu-Daudé } 491*159fb790SPhilippe Mathieu-Daudé 492*159fb790SPhilippe Mathieu-Daudé /* address_offset is hack for kernel images that are 493*159fb790SPhilippe Mathieu-Daudé linked at the wrong physical address. */ 494*159fb790SPhilippe Mathieu-Daudé if (translate_fn) { 495*159fb790SPhilippe Mathieu-Daudé addr = translate_fn(translate_opaque, ph->p_paddr); 496*159fb790SPhilippe Mathieu-Daudé glue(elf_reloc, SZ)(&ehdr, fd, must_swab, translate_fn, 497*159fb790SPhilippe Mathieu-Daudé translate_opaque, data, ph, elf_machine); 498*159fb790SPhilippe Mathieu-Daudé } else { 499*159fb790SPhilippe Mathieu-Daudé addr = ph->p_paddr; 500*159fb790SPhilippe Mathieu-Daudé } 501*159fb790SPhilippe Mathieu-Daudé 502*159fb790SPhilippe Mathieu-Daudé if (data_swab) { 503*159fb790SPhilippe Mathieu-Daudé elf_word j; 504*159fb790SPhilippe Mathieu-Daudé for (j = 0; j < file_size; j += (1 << data_swab)) { 505*159fb790SPhilippe Mathieu-Daudé uint8_t *dp = data + j; 506*159fb790SPhilippe Mathieu-Daudé switch (data_swab) { 507*159fb790SPhilippe Mathieu-Daudé case (1): 508*159fb790SPhilippe Mathieu-Daudé *(uint16_t *)dp = bswap16(*(uint16_t *)dp); 509*159fb790SPhilippe Mathieu-Daudé break; 510*159fb790SPhilippe Mathieu-Daudé case (2): 511*159fb790SPhilippe Mathieu-Daudé *(uint32_t *)dp = bswap32(*(uint32_t *)dp); 512*159fb790SPhilippe Mathieu-Daudé break; 513*159fb790SPhilippe Mathieu-Daudé case (3): 514*159fb790SPhilippe Mathieu-Daudé *(uint64_t *)dp = bswap64(*(uint64_t *)dp); 515*159fb790SPhilippe Mathieu-Daudé break; 516*159fb790SPhilippe Mathieu-Daudé default: 517*159fb790SPhilippe Mathieu-Daudé g_assert_not_reached(); 518*159fb790SPhilippe Mathieu-Daudé } 519*159fb790SPhilippe Mathieu-Daudé } 520*159fb790SPhilippe Mathieu-Daudé } 521*159fb790SPhilippe Mathieu-Daudé 522*159fb790SPhilippe Mathieu-Daudé /* the entry pointer in the ELF header is a virtual 523*159fb790SPhilippe Mathieu-Daudé * address, if the text segments paddr and vaddr differ 524*159fb790SPhilippe Mathieu-Daudé * we need to adjust the entry */ 525*159fb790SPhilippe Mathieu-Daudé if (pentry && !translate_fn && 526*159fb790SPhilippe Mathieu-Daudé ph->p_vaddr != ph->p_paddr && 527*159fb790SPhilippe Mathieu-Daudé ehdr.e_entry >= ph->p_vaddr && 528*159fb790SPhilippe Mathieu-Daudé ehdr.e_entry < ph->p_vaddr + ph->p_filesz && 529*159fb790SPhilippe Mathieu-Daudé ph->p_flags & PF_X) { 530*159fb790SPhilippe Mathieu-Daudé *pentry = ehdr.e_entry - ph->p_vaddr + ph->p_paddr; 531*159fb790SPhilippe Mathieu-Daudé } 532*159fb790SPhilippe Mathieu-Daudé 533*159fb790SPhilippe Mathieu-Daudé /* Some ELF files really do have segments of zero size; 534*159fb790SPhilippe Mathieu-Daudé * just ignore them rather than trying to create empty 535*159fb790SPhilippe Mathieu-Daudé * ROM blobs, because the zero-length blob can falsely 536*159fb790SPhilippe Mathieu-Daudé * trigger the overlapping-ROM-blobs check. 537*159fb790SPhilippe Mathieu-Daudé */ 538*159fb790SPhilippe Mathieu-Daudé if (mem_size != 0) { 539*159fb790SPhilippe Mathieu-Daudé if (load_rom) { 540*159fb790SPhilippe Mathieu-Daudé g_autofree char *label = 541*159fb790SPhilippe Mathieu-Daudé g_strdup_printf("%s ELF program header segment %d", 542*159fb790SPhilippe Mathieu-Daudé name, i); 543*159fb790SPhilippe Mathieu-Daudé 544*159fb790SPhilippe Mathieu-Daudé /* 545*159fb790SPhilippe Mathieu-Daudé * rom_add_elf_program() takes its own reference to 546*159fb790SPhilippe Mathieu-Daudé * 'mapped_file'. 547*159fb790SPhilippe Mathieu-Daudé */ 548*159fb790SPhilippe Mathieu-Daudé rom_add_elf_program(label, mapped_file, data, file_size, 549*159fb790SPhilippe Mathieu-Daudé mem_size, addr, as); 550*159fb790SPhilippe Mathieu-Daudé } else { 551*159fb790SPhilippe Mathieu-Daudé MemTxResult res; 552*159fb790SPhilippe Mathieu-Daudé 553*159fb790SPhilippe Mathieu-Daudé res = address_space_write(as ? as : &address_space_memory, 554*159fb790SPhilippe Mathieu-Daudé addr, MEMTXATTRS_UNSPECIFIED, 555*159fb790SPhilippe Mathieu-Daudé data, file_size); 556*159fb790SPhilippe Mathieu-Daudé if (res != MEMTX_OK) { 557*159fb790SPhilippe Mathieu-Daudé goto fail; 558*159fb790SPhilippe Mathieu-Daudé } 559*159fb790SPhilippe Mathieu-Daudé /* 560*159fb790SPhilippe Mathieu-Daudé * We need to zero'ify the space that is not copied 561*159fb790SPhilippe Mathieu-Daudé * from file 562*159fb790SPhilippe Mathieu-Daudé */ 563*159fb790SPhilippe Mathieu-Daudé if (file_size < mem_size) { 564*159fb790SPhilippe Mathieu-Daudé res = address_space_set(as ? as : &address_space_memory, 565*159fb790SPhilippe Mathieu-Daudé addr + file_size, 0, 566*159fb790SPhilippe Mathieu-Daudé mem_size - file_size, 567*159fb790SPhilippe Mathieu-Daudé MEMTXATTRS_UNSPECIFIED); 568*159fb790SPhilippe Mathieu-Daudé if (res != MEMTX_OK) { 569*159fb790SPhilippe Mathieu-Daudé goto fail; 570*159fb790SPhilippe Mathieu-Daudé } 571*159fb790SPhilippe Mathieu-Daudé } 572*159fb790SPhilippe Mathieu-Daudé } 573*159fb790SPhilippe Mathieu-Daudé } 574*159fb790SPhilippe Mathieu-Daudé 575*159fb790SPhilippe Mathieu-Daudé total_size += mem_size; 576*159fb790SPhilippe Mathieu-Daudé if (addr < low) 577*159fb790SPhilippe Mathieu-Daudé low = addr; 578*159fb790SPhilippe Mathieu-Daudé if ((addr + mem_size) > high) 579*159fb790SPhilippe Mathieu-Daudé high = addr + mem_size; 580*159fb790SPhilippe Mathieu-Daudé 581*159fb790SPhilippe Mathieu-Daudé data = NULL; 582*159fb790SPhilippe Mathieu-Daudé 583*159fb790SPhilippe Mathieu-Daudé } else if (ph->p_type == PT_NOTE && elf_note_fn) { 584*159fb790SPhilippe Mathieu-Daudé struct elf_note *nhdr = NULL; 585*159fb790SPhilippe Mathieu-Daudé 586*159fb790SPhilippe Mathieu-Daudé file_size = ph->p_filesz; /* Size of the range of ELF notes */ 587*159fb790SPhilippe Mathieu-Daudé data_offset = ph->p_offset; /* Offset where the notes are located */ 588*159fb790SPhilippe Mathieu-Daudé 589*159fb790SPhilippe Mathieu-Daudé if (file_size > 0) { 590*159fb790SPhilippe Mathieu-Daudé if (g_mapped_file_get_length(mapped_file) < 591*159fb790SPhilippe Mathieu-Daudé file_size + data_offset) { 592*159fb790SPhilippe Mathieu-Daudé goto fail; 593*159fb790SPhilippe Mathieu-Daudé } 594*159fb790SPhilippe Mathieu-Daudé 595*159fb790SPhilippe Mathieu-Daudé data = (uint8_t *)g_mapped_file_get_contents(mapped_file); 596*159fb790SPhilippe Mathieu-Daudé data += data_offset; 597*159fb790SPhilippe Mathieu-Daudé } 598*159fb790SPhilippe Mathieu-Daudé 599*159fb790SPhilippe Mathieu-Daudé /* 600*159fb790SPhilippe Mathieu-Daudé * Search the ELF notes to find one with a type matching the 601*159fb790SPhilippe Mathieu-Daudé * value passed in via 'translate_opaque' 602*159fb790SPhilippe Mathieu-Daudé */ 603*159fb790SPhilippe Mathieu-Daudé nhdr = (struct elf_note *)data; 604*159fb790SPhilippe Mathieu-Daudé assert(translate_opaque != NULL); 605*159fb790SPhilippe Mathieu-Daudé nhdr = glue(get_elf_note_type, SZ)(nhdr, file_size, ph->p_align, 606*159fb790SPhilippe Mathieu-Daudé *(uint64_t *)translate_opaque); 607*159fb790SPhilippe Mathieu-Daudé if (nhdr != NULL) { 608*159fb790SPhilippe Mathieu-Daudé elf_note_fn((void *)nhdr, (void *)&ph->p_align, SZ == 64); 609*159fb790SPhilippe Mathieu-Daudé } 610*159fb790SPhilippe Mathieu-Daudé data = NULL; 611*159fb790SPhilippe Mathieu-Daudé } 612*159fb790SPhilippe Mathieu-Daudé } 613*159fb790SPhilippe Mathieu-Daudé 614*159fb790SPhilippe Mathieu-Daudé if (lowaddr) { 615*159fb790SPhilippe Mathieu-Daudé *lowaddr = low; 616*159fb790SPhilippe Mathieu-Daudé } 617*159fb790SPhilippe Mathieu-Daudé if (highaddr) { 618*159fb790SPhilippe Mathieu-Daudé *highaddr = high; 619*159fb790SPhilippe Mathieu-Daudé } 620*159fb790SPhilippe Mathieu-Daudé ret = total_size; 621*159fb790SPhilippe Mathieu-Daudé fail: 622*159fb790SPhilippe Mathieu-Daudé if (mapped_file) { 623*159fb790SPhilippe Mathieu-Daudé g_mapped_file_unref(mapped_file); 624*159fb790SPhilippe Mathieu-Daudé } 625*159fb790SPhilippe Mathieu-Daudé g_free(phdr); 626*159fb790SPhilippe Mathieu-Daudé return ret; 627*159fb790SPhilippe Mathieu-Daudé} 628