loadfile_elf.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /* $NetBSD: loadfile.c,v 1.10 2000/12/03 02:53:04 tsutsui Exp $ */
  2. /* $OpenBSD: loadfile_elf.c,v 1.11 2015/05/19 20:39:12 miod Exp $ */
  3. /*-
  4. * Copyright (c) 1997 The NetBSD Foundation, Inc.
  5. * All rights reserved.
  6. *
  7. * This code is derived from software contributed to The NetBSD Foundation
  8. * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
  9. * NASA Ames Research Center and by Christos Zoulas.
  10. *
  11. * Redistribution and use in source and binary forms, with or without
  12. * modification, are permitted provided that the following conditions
  13. * are met:
  14. * 1. Redistributions of source code must retain the above copyright
  15. * notice, this list of conditions and the following disclaimer.
  16. * 2. Redistributions in binary form must reproduce the above copyright
  17. * notice, this list of conditions and the following disclaimer in the
  18. * documentation and/or other materials provided with the distribution.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  21. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  22. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  23. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
  24. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  25. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  26. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  27. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  29. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  30. * POSSIBILITY OF SUCH DAMAGE.
  31. */
  32. /*
  33. * Copyright (c) 1992, 1993
  34. * The Regents of the University of California. All rights reserved.
  35. *
  36. * This code is derived from software contributed to Berkeley by
  37. * Ralph Campbell.
  38. *
  39. * Redistribution and use in source and binary forms, with or without
  40. * modification, are permitted provided that the following conditions
  41. * are met:
  42. * 1. Redistributions of source code must retain the above copyright
  43. * notice, this list of conditions and the following disclaimer.
  44. * 2. Redistributions in binary form must reproduce the above copyright
  45. * notice, this list of conditions and the following disclaimer in the
  46. * documentation and/or other materials provided with the distribution.
  47. * 3. Neither the name of the University nor the names of its contributors
  48. * may be used to endorse or promote products derived from this software
  49. * without specific prior written permission.
  50. *
  51. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  52. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  53. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  54. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  55. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  56. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  57. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  58. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  59. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  60. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  61. * SUCH DAMAGE.
  62. *
  63. * @(#)boot.c 8.1 (Berkeley) 6/10/93
  64. */
  65. int ELFNAME(exec)(int, Elf_Ehdr *, u_long *, int);
  66. int
  67. ELFNAME(exec)(int fd, Elf_Ehdr *elf, u_long *marks, int flags)
  68. {
  69. Elf_Shdr *shp;
  70. Elf_Phdr *phdr;
  71. Elf_Off off;
  72. int i;
  73. size_t sz;
  74. int first;
  75. int havesyms, havelines;
  76. paddr_t minp = ~0, maxp = 0, pos = 0;
  77. paddr_t offset = marks[MARK_START], shpp, elfp;
  78. sz = elf->e_phnum * sizeof(Elf_Phdr);
  79. phdr = ALLOC(sz);
  80. if (lseek(fd, (off_t)elf->e_phoff, SEEK_SET) == -1) {
  81. WARN(("lseek phdr"));
  82. FREE(phdr, sz);
  83. return 1;
  84. }
  85. if (read(fd, phdr, sz) != sz) {
  86. WARN(("read program headers"));
  87. FREE(phdr, sz);
  88. return 1;
  89. }
  90. for (first = 1, i = 0; i < elf->e_phnum; i++) {
  91. if (phdr[i].p_type == PT_OPENBSD_RANDOMIZE) {
  92. int m;
  93. /* Fill segment if asked for. */
  94. if (flags & LOAD_RANDOM) {
  95. for (pos = 0; pos < phdr[i].p_filesz;
  96. pos += m) {
  97. m = MIN(phdr[i].p_filesz - pos,
  98. sizeof(rnddata));
  99. BCOPY(rnddata, phdr[i].p_paddr + pos,
  100. m);
  101. }
  102. }
  103. if (flags & (LOAD_RANDOM | COUNT_RANDOM)) {
  104. marks[MARK_RANDOM] = LOADADDR(phdr[i].p_paddr);
  105. marks[MARK_ERANDOM] =
  106. marks[MARK_RANDOM] + phdr[i].p_filesz;
  107. }
  108. continue;
  109. }
  110. if (phdr[i].p_type != PT_LOAD ||
  111. (phdr[i].p_flags & (PF_W|PF_R|PF_X)) == 0)
  112. continue;
  113. #ifdef CHECK_PHDR
  114. if (CHECK_PHDR(ELFSIZE, &phdr[i])) {
  115. FREE(phdr, sz);
  116. return 1;
  117. }
  118. #endif
  119. #define IS_TEXT(p) (p.p_flags & PF_X)
  120. #define IS_DATA(p) ((p.p_flags & PF_X) == 0)
  121. #define IS_BSS(p) (p.p_filesz < p.p_memsz)
  122. /*
  123. * XXX: Assume first address is lowest
  124. */
  125. if ((IS_TEXT(phdr[i]) && (flags & LOAD_TEXT)) ||
  126. (IS_DATA(phdr[i]) && (flags & LOAD_DATA))) {
  127. /* Read in segment. */
  128. PROGRESS(("%s%lu", first ? "" : "+",
  129. (u_long)phdr[i].p_filesz));
  130. if (lseek(fd, (off_t)phdr[i].p_offset, SEEK_SET) == -1) {
  131. WARN(("lseek text"));
  132. FREE(phdr, sz);
  133. return 1;
  134. }
  135. if (READ(fd, phdr[i].p_paddr, phdr[i].p_filesz) !=
  136. phdr[i].p_filesz) {
  137. WARN(("read text"));
  138. FREE(phdr, sz);
  139. return 1;
  140. }
  141. first = 0;
  142. }
  143. if ((IS_TEXT(phdr[i]) && (flags & (LOAD_TEXT | COUNT_TEXT))) ||
  144. (IS_DATA(phdr[i]) && (flags & (LOAD_DATA | COUNT_TEXT)))) {
  145. pos = phdr[i].p_paddr;
  146. if (minp > pos)
  147. minp = pos;
  148. pos += phdr[i].p_filesz;
  149. if (maxp < pos)
  150. maxp = pos;
  151. }
  152. /* Zero out BSS. */
  153. if (IS_BSS(phdr[i]) && (flags & LOAD_BSS)) {
  154. PROGRESS(("+%lu",
  155. (u_long)(phdr[i].p_memsz - phdr[i].p_filesz)));
  156. BZERO((phdr[i].p_paddr + phdr[i].p_filesz),
  157. phdr[i].p_memsz - phdr[i].p_filesz);
  158. }
  159. if (IS_BSS(phdr[i]) && (flags & (LOAD_BSS|COUNT_BSS))) {
  160. pos += phdr[i].p_memsz - phdr[i].p_filesz;
  161. if (maxp < pos)
  162. maxp = pos;
  163. }
  164. }
  165. FREE(phdr, sz);
  166. /*
  167. * Copy the ELF and section headers.
  168. */
  169. elfp = maxp = roundup(maxp, sizeof(Elf_Addr));
  170. if (flags & (LOAD_HDR | COUNT_HDR))
  171. maxp += sizeof(Elf_Ehdr);
  172. if (flags & (LOAD_SYM | COUNT_SYM)) {
  173. if (lseek(fd, (off_t)elf->e_shoff, SEEK_SET) == -1) {
  174. WARN(("lseek section headers"));
  175. return 1;
  176. }
  177. sz = elf->e_shnum * sizeof(Elf_Shdr);
  178. shp = ALLOC(sz);
  179. if (read(fd, shp, sz) != sz) {
  180. WARN(("read section headers"));
  181. FREE(shp, sz);
  182. return 1;
  183. }
  184. shpp = maxp;
  185. maxp += roundup(sz, sizeof(Elf_Addr));
  186. size_t shstrsz = shp[elf->e_shstrndx].sh_size;
  187. char *shstr = ALLOC(shstrsz);
  188. if (lseek(fd, (off_t)shp[elf->e_shstrndx].sh_offset, SEEK_SET) == -1) {
  189. WARN(("lseek section header string table"));
  190. FREE(shstr, shstrsz);
  191. FREE(shp, sz);
  192. return 1;
  193. }
  194. if (read(fd, shstr, shstrsz) != shstrsz) {
  195. WARN(("read section header string table"));
  196. FREE(shstr, shstrsz);
  197. FREE(shp, sz);
  198. return 1;
  199. }
  200. /*
  201. * Now load the symbol sections themselves. Make sure the
  202. * sections are aligned. Don't bother with string tables if
  203. * there are no symbol sections.
  204. */
  205. off = roundup((sizeof(Elf_Ehdr) + sz), sizeof(Elf_Addr));
  206. for (havesyms = havelines = i = 0; i < elf->e_shnum; i++)
  207. if (shp[i].sh_type == SHT_SYMTAB)
  208. havesyms = 1;
  209. for (first = 1, i = 0; i < elf->e_shnum; i++) {
  210. if (shp[i].sh_type == SHT_SYMTAB ||
  211. shp[i].sh_type == SHT_STRTAB ||
  212. !strcmp(shstr + shp[i].sh_name, ".debug_line")) {
  213. if (havesyms && (flags & LOAD_SYM)) {
  214. PROGRESS(("%s%ld", first ? " [" : "+",
  215. (u_long)shp[i].sh_size));
  216. if (lseek(fd, (off_t)shp[i].sh_offset,
  217. SEEK_SET) == -1) {
  218. WARN(("lseek symbols"));
  219. FREE(shstr, shstrsz);
  220. FREE(shp, sz);
  221. return 1;
  222. }
  223. if (READ(fd, maxp, shp[i].sh_size) !=
  224. shp[i].sh_size) {
  225. WARN(("read symbols"));
  226. FREE(shstr, shstrsz);
  227. FREE(shp, sz);
  228. return 1;
  229. }
  230. }
  231. maxp += roundup(shp[i].sh_size,
  232. sizeof(Elf_Addr));
  233. shp[i].sh_offset = off;
  234. shp[i].sh_flags |= SHF_ALLOC;
  235. off += roundup(shp[i].sh_size, sizeof(Elf_Addr));
  236. first = 0;
  237. }
  238. }
  239. if (flags & LOAD_SYM) {
  240. BCOPY(shp, shpp, sz);
  241. if (havesyms && first == 0)
  242. PROGRESS(("]"));
  243. }
  244. FREE(shstr, shstrsz);
  245. FREE(shp, sz);
  246. }
  247. /*
  248. * Frob the copied ELF header to give information relative
  249. * to elfp.
  250. */
  251. if (flags & LOAD_HDR) {
  252. elf->e_phoff = 0;
  253. elf->e_shoff = sizeof(Elf_Ehdr);
  254. elf->e_phentsize = 0;
  255. elf->e_phnum = 0;
  256. BCOPY(elf, elfp, sizeof(*elf));
  257. }
  258. marks[MARK_START] = LOADADDR(minp);
  259. marks[MARK_ENTRY] = LOADADDR(elf->e_entry);
  260. marks[MARK_NSYM] = 1; /* XXX: Kernel needs >= 0 */
  261. marks[MARK_SYM] = LOADADDR(elfp);
  262. marks[MARK_END] = LOADADDR(maxp);
  263. return 0;
  264. }