elf_ops.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. static void glue(bswap_ehdr, SZ)(struct elfhdr *ehdr)
  2. {
  3. bswap16s(&ehdr->e_type); /* Object file type */
  4. bswap16s(&ehdr->e_machine); /* Architecture */
  5. bswap32s(&ehdr->e_version); /* Object file version */
  6. bswapSZs(&ehdr->e_entry); /* Entry point virtual address */
  7. bswapSZs(&ehdr->e_phoff); /* Program header table file offset */
  8. bswapSZs(&ehdr->e_shoff); /* Section header table file offset */
  9. bswap32s(&ehdr->e_flags); /* Processor-specific flags */
  10. bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
  11. bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
  12. bswap16s(&ehdr->e_phnum); /* Program header table entry count */
  13. bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
  14. bswap16s(&ehdr->e_shnum); /* Section header table entry count */
  15. bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
  16. }
  17. static void glue(bswap_phdr, SZ)(struct elf_phdr *phdr)
  18. {
  19. bswap32s(&phdr->p_type); /* Segment type */
  20. bswapSZs(&phdr->p_offset); /* Segment file offset */
  21. bswapSZs(&phdr->p_vaddr); /* Segment virtual address */
  22. bswapSZs(&phdr->p_paddr); /* Segment physical address */
  23. bswapSZs(&phdr->p_filesz); /* Segment size in file */
  24. bswapSZs(&phdr->p_memsz); /* Segment size in memory */
  25. bswap32s(&phdr->p_flags); /* Segment flags */
  26. bswapSZs(&phdr->p_align); /* Segment alignment */
  27. }
  28. static void glue(bswap_shdr, SZ)(struct elf_shdr *shdr)
  29. {
  30. bswap32s(&shdr->sh_name);
  31. bswap32s(&shdr->sh_type);
  32. bswapSZs(&shdr->sh_flags);
  33. bswapSZs(&shdr->sh_addr);
  34. bswapSZs(&shdr->sh_offset);
  35. bswapSZs(&shdr->sh_size);
  36. bswap32s(&shdr->sh_link);
  37. bswap32s(&shdr->sh_info);
  38. bswapSZs(&shdr->sh_addralign);
  39. bswapSZs(&shdr->sh_entsize);
  40. }
  41. static void glue(bswap_sym, SZ)(struct elf_sym *sym)
  42. {
  43. bswap32s(&sym->st_name);
  44. bswapSZs(&sym->st_value);
  45. bswapSZs(&sym->st_size);
  46. bswap16s(&sym->st_shndx);
  47. }
  48. static struct elf_shdr *glue(find_section, SZ)(struct elf_shdr *shdr_table,
  49. int n, int type)
  50. {
  51. int i;
  52. for(i=0;i<n;i++) {
  53. if (shdr_table[i].sh_type == type)
  54. return shdr_table + i;
  55. }
  56. return NULL;
  57. }
  58. static int glue(symfind, SZ)(const void *s0, const void *s1)
  59. {
  60. struct elf_sym *key = (struct elf_sym *)s0;
  61. struct elf_sym *sym = (struct elf_sym *)s1;
  62. int result = 0;
  63. if (key->st_value < sym->st_value) {
  64. result = -1;
  65. } else if (key->st_value > sym->st_value + sym->st_size) {
  66. result = 1;
  67. }
  68. return result;
  69. }
  70. static const char *glue(lookup_symbol, SZ)(struct syminfo *s, target_ulong orig_addr)
  71. {
  72. struct elf_sym *syms = glue(s->disas_symtab.elf, SZ);
  73. struct elf_sym key;
  74. struct elf_sym *sym;
  75. key.st_value = orig_addr;
  76. sym = bsearch(&key, syms, s->disas_num_syms, sizeof(*syms), glue(symfind, SZ));
  77. if (sym != 0) {
  78. return s->disas_strtab + sym->st_name;
  79. }
  80. return "";
  81. }
  82. static int glue(symcmp, SZ)(const void *s0, const void *s1)
  83. {
  84. struct elf_sym *sym0 = (struct elf_sym *)s0;
  85. struct elf_sym *sym1 = (struct elf_sym *)s1;
  86. return (sym0->st_value < sym1->st_value)
  87. ? -1
  88. : ((sym0->st_value > sym1->st_value) ? 1 : 0);
  89. }
  90. static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab)
  91. {
  92. struct elf_shdr *symtab, *strtab, *shdr_table = NULL;
  93. struct elf_sym *syms = NULL;
  94. struct syminfo *s;
  95. int nsyms, i;
  96. char *str = NULL;
  97. shdr_table = load_at(fd, ehdr->e_shoff,
  98. sizeof(struct elf_shdr) * ehdr->e_shnum);
  99. if (!shdr_table)
  100. return -1;
  101. if (must_swab) {
  102. for (i = 0; i < ehdr->e_shnum; i++) {
  103. glue(bswap_shdr, SZ)(shdr_table + i);
  104. }
  105. }
  106. symtab = glue(find_section, SZ)(shdr_table, ehdr->e_shnum, SHT_SYMTAB);
  107. if (!symtab)
  108. goto fail;
  109. syms = load_at(fd, symtab->sh_offset, symtab->sh_size);
  110. if (!syms)
  111. goto fail;
  112. nsyms = symtab->sh_size / sizeof(struct elf_sym);
  113. i = 0;
  114. while (i < nsyms) {
  115. if (must_swab)
  116. glue(bswap_sym, SZ)(&syms[i]);
  117. /* We are only interested in function symbols.
  118. Throw everything else away. */
  119. if (syms[i].st_shndx == SHN_UNDEF ||
  120. syms[i].st_shndx >= SHN_LORESERVE ||
  121. ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
  122. nsyms--;
  123. if (i < nsyms) {
  124. syms[i] = syms[nsyms];
  125. }
  126. continue;
  127. }
  128. #if defined(TARGET_ARM) || defined (TARGET_MIPS)
  129. /* The bottom address bit marks a Thumb or MIPS16 symbol. */
  130. syms[i].st_value &= ~(target_ulong)1;
  131. #endif
  132. i++;
  133. }
  134. syms = qemu_realloc(syms, nsyms * sizeof(*syms));
  135. qsort(syms, nsyms, sizeof(*syms), glue(symcmp, SZ));
  136. /* String table */
  137. if (symtab->sh_link >= ehdr->e_shnum)
  138. goto fail;
  139. strtab = &shdr_table[symtab->sh_link];
  140. str = load_at(fd, strtab->sh_offset, strtab->sh_size);
  141. if (!str)
  142. goto fail;
  143. /* Commit */
  144. s = qemu_mallocz(sizeof(*s));
  145. s->lookup_symbol = glue(lookup_symbol, SZ);
  146. glue(s->disas_symtab.elf, SZ) = syms;
  147. s->disas_num_syms = nsyms;
  148. s->disas_strtab = str;
  149. s->next = syminfos;
  150. syminfos = s;
  151. qemu_free(shdr_table);
  152. return 0;
  153. fail:
  154. qemu_free(syms);
  155. qemu_free(str);
  156. qemu_free(shdr_table);
  157. return -1;
  158. }
  159. static int glue(load_elf, SZ)(int fd, int64_t address_offset,
  160. int must_swab, uint64_t *pentry,
  161. uint64_t *lowaddr, uint64_t *highaddr)
  162. {
  163. struct elfhdr ehdr;
  164. struct elf_phdr *phdr = NULL, *ph;
  165. int size, i, total_size;
  166. elf_word mem_size;
  167. uint64_t addr, low = 0, high = 0;
  168. uint8_t *data = NULL;
  169. if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
  170. goto fail;
  171. if (must_swab) {
  172. glue(bswap_ehdr, SZ)(&ehdr);
  173. }
  174. if (ELF_MACHINE != ehdr.e_machine)
  175. goto fail;
  176. if (pentry)
  177. *pentry = (uint64_t)(elf_sword)ehdr.e_entry;
  178. glue(load_symbols, SZ)(&ehdr, fd, must_swab);
  179. size = ehdr.e_phnum * sizeof(phdr[0]);
  180. lseek(fd, ehdr.e_phoff, SEEK_SET);
  181. phdr = qemu_mallocz(size);
  182. if (!phdr)
  183. goto fail;
  184. if (read(fd, phdr, size) != size)
  185. goto fail;
  186. if (must_swab) {
  187. for(i = 0; i < ehdr.e_phnum; i++) {
  188. ph = &phdr[i];
  189. glue(bswap_phdr, SZ)(ph);
  190. }
  191. }
  192. total_size = 0;
  193. for(i = 0; i < ehdr.e_phnum; i++) {
  194. ph = &phdr[i];
  195. if (ph->p_type == PT_LOAD) {
  196. mem_size = ph->p_memsz;
  197. /* XXX: avoid allocating */
  198. data = qemu_mallocz(mem_size);
  199. if (ph->p_filesz > 0) {
  200. if (lseek(fd, ph->p_offset, SEEK_SET) < 0)
  201. goto fail;
  202. if (read(fd, data, ph->p_filesz) != ph->p_filesz)
  203. goto fail;
  204. }
  205. /* address_offset is hack for kernel images that are
  206. linked at the wrong physical address. */
  207. addr = ph->p_paddr + address_offset;
  208. cpu_physical_memory_write_rom(addr, data, mem_size);
  209. total_size += mem_size;
  210. if (!low || addr < low)
  211. low = addr;
  212. if (!high || (addr + mem_size) > high)
  213. high = addr + mem_size;
  214. qemu_free(data);
  215. data = NULL;
  216. }
  217. }
  218. qemu_free(phdr);
  219. if (lowaddr)
  220. *lowaddr = (uint64_t)(elf_sword)low;
  221. if (highaddr)
  222. *highaddr = (uint64_t)(elf_sword)high;
  223. return total_size;
  224. fail:
  225. qemu_free(data);
  226. qemu_free(phdr);
  227. return -1;
  228. }