1 /****************************************************************************/ 2 /* 3 * QEMU bFLT binary loader. Based on linux/fs/binfmt_flat.c 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, see <http://www.gnu.org/licenses/>. 17 * 18 * Copyright (C) 2006 CodeSourcery. 19 * Copyright (C) 2000-2003 David McCullough <davidm@snapgear.com> 20 * Copyright (C) 2002 Greg Ungerer <gerg@snapgear.com> 21 * Copyright (C) 2002 SnapGear, by Paul Dale <pauli@snapgear.com> 22 * Copyright (C) 2000, 2001 Lineo, by David McCullough <davidm@lineo.com> 23 * based heavily on: 24 * 25 * linux/fs/binfmt_aout.c: 26 * Copyright (C) 1991, 1992, 1996 Linus Torvalds 27 * linux/fs/binfmt_flat.c for 2.0 kernel 28 * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com> 29 * JAN/99 -- coded full program relocation (gerg@snapgear.com) 30 */ 31 32 /****************************************************************************/ 33 34 #include "qemu/osdep.h" 35 36 #include "qemu.h" 37 #include "exec/page-protection.h" 38 #include "user-internals.h" 39 #include "loader.h" 40 #include "user-mmap.h" 41 #include "flat.h" 42 #include "target_flat.h" 43 44 //#define DEBUG 45 46 #ifdef DEBUG 47 #define DBG_FLT(...) printf(__VA_ARGS__) 48 #else 49 #define DBG_FLT(...) 50 #endif 51 52 #define RELOC_FAILED 0xff00ff01 /* Relocation incorrect somewhere */ 53 #define UNLOADED_LIB 0x7ff000ff /* Placeholder for unused library */ 54 55 struct lib_info { 56 abi_ulong start_code; /* Start of text segment */ 57 abi_ulong start_data; /* Start of data segment */ 58 abi_ulong end_data; /* Start of bss section */ 59 abi_ulong start_brk; /* End of data segment */ 60 abi_ulong text_len; /* Length of text segment */ 61 abi_ulong entry; /* Start address for this module */ 62 abi_ulong build_date; /* When this one was compiled */ 63 short loaded; /* Has this library been loaded? */ 64 }; 65 66 struct linux_binprm; 67 68 /****************************************************************************/ 69 /* 70 * create_flat_tables() parses the env- and arg-strings in new user 71 * memory and creates the pointer tables from them, and puts their 72 * addresses on the "stack", returning the new stack pointer value. 73 */ 74 75 /* Push a block of strings onto the guest stack. */ 76 static abi_ulong copy_strings(abi_ulong p, int n, char **s) 77 { 78 int len; 79 80 while (n-- > 0) { 81 len = strlen(s[n]) + 1; 82 p -= len; 83 memcpy_to_target(p, s[n], len); 84 } 85 86 return p; 87 } 88 89 static int target_pread(int fd, abi_ulong ptr, abi_ulong len, 90 abi_ulong offset) 91 { 92 void *buf; 93 int ret; 94 95 buf = lock_user(VERIFY_WRITE, ptr, len, 0); 96 if (!buf) { 97 return -EFAULT; 98 } 99 ret = pread(fd, buf, len, offset); 100 if (ret < 0) { 101 ret = -errno; 102 } 103 unlock_user(buf, ptr, len); 104 return ret; 105 } 106 107 /****************************************************************************/ 108 109 static abi_ulong 110 calc_reloc(abi_ulong r, struct lib_info *p, int curid, int internalp) 111 { 112 abi_ulong addr; 113 int id; 114 abi_ulong start_brk; 115 abi_ulong start_data; 116 abi_ulong text_len; 117 abi_ulong start_code; 118 119 id = 0; 120 121 start_brk = p[id].start_brk; 122 start_data = p[id].start_data; 123 start_code = p[id].start_code; 124 text_len = p[id].text_len; 125 126 if (!flat_reloc_valid(r, start_brk - start_data + text_len)) { 127 fprintf(stderr, "BINFMT_FLAT: reloc outside program 0x%x " 128 "(0 - 0x%x/0x%x)\n", 129 (int) r,(int)(start_brk-start_code),(int)text_len); 130 goto failed; 131 } 132 133 if (r < text_len) /* In text segment */ 134 addr = r + start_code; 135 else /* In data segment */ 136 addr = r - text_len + start_data; 137 138 /* Range checked already above so doing the range tests is redundant...*/ 139 return(addr); 140 141 failed: 142 abort(); 143 return RELOC_FAILED; 144 } 145 146 /****************************************************************************/ 147 148 /* ??? This does not handle endianness correctly. */ 149 static void old_reloc(struct lib_info *libinfo, uint32_t rl) 150 { 151 #ifdef DEBUG 152 const char *segment[] = { "TEXT", "DATA", "BSS", "*UNKNOWN*" }; 153 #endif 154 uint32_t *ptr; 155 uint32_t offset; 156 int reloc_type; 157 158 offset = rl & 0x3fffffff; 159 reloc_type = rl >> 30; 160 /* ??? How to handle this? */ 161 #if defined(CONFIG_COLDFIRE) 162 ptr = (uint32_t *) ((unsigned long) libinfo->start_code + offset); 163 #else 164 ptr = (uint32_t *) ((unsigned long) libinfo->start_data + offset); 165 #endif 166 167 #ifdef DEBUG 168 fprintf(stderr, "Relocation of variable at DATASEG+%x " 169 "(address %p, currently %x) into segment %s\n", 170 offset, ptr, (int)*ptr, segment[reloc_type]); 171 #endif 172 173 switch (reloc_type) { 174 case OLD_FLAT_RELOC_TYPE_TEXT: 175 *ptr += libinfo->start_code; 176 break; 177 case OLD_FLAT_RELOC_TYPE_DATA: 178 *ptr += libinfo->start_data; 179 break; 180 case OLD_FLAT_RELOC_TYPE_BSS: 181 *ptr += libinfo->end_data; 182 break; 183 default: 184 fprintf(stderr, "BINFMT_FLAT: Unknown relocation type=%x\n", 185 reloc_type); 186 break; 187 } 188 DBG_FLT("Relocation became %x\n", (int)*ptr); 189 } 190 191 /****************************************************************************/ 192 193 static int load_flat_file(struct linux_binprm * bprm, 194 struct lib_info *libinfo, int id, abi_ulong *extra_stack) 195 { 196 struct flat_hdr * hdr; 197 abi_ulong textpos = 0, datapos = 0; 198 abi_long result; 199 abi_ulong realdatastart = 0; 200 abi_ulong text_len, data_len, bss_len, stack_len, flags; 201 abi_ulong extra; 202 abi_ulong reloc = 0, rp; 203 int i, rev, relocs = 0; 204 abi_ulong fpos; 205 abi_ulong start_code; 206 abi_ulong indx_len; 207 208 hdr = ((struct flat_hdr *) bprm->buf); /* exec-header */ 209 210 text_len = ntohl(hdr->data_start); 211 data_len = ntohl(hdr->data_end) - ntohl(hdr->data_start); 212 bss_len = ntohl(hdr->bss_end) - ntohl(hdr->data_end); 213 stack_len = ntohl(hdr->stack_size); 214 if (extra_stack) { 215 stack_len += *extra_stack; 216 *extra_stack = stack_len; 217 } 218 relocs = ntohl(hdr->reloc_count); 219 flags = ntohl(hdr->flags); 220 rev = ntohl(hdr->rev); 221 222 DBG_FLT("BINFMT_FLAT: Loading file: %s\n", bprm->filename); 223 224 if (rev != FLAT_VERSION && rev != OLD_FLAT_VERSION) { 225 fprintf(stderr, "BINFMT_FLAT: bad magic/rev (0x%x, need 0x%x)\n", 226 rev, (int) FLAT_VERSION); 227 return -ENOEXEC; 228 } 229 230 /* Don't allow old format executables to use shared libraries */ 231 if (rev == OLD_FLAT_VERSION && id != 0) { 232 fprintf(stderr, "BINFMT_FLAT: shared libraries are not available\n"); 233 return -ENOEXEC; 234 } 235 236 /* 237 * fix up the flags for the older format, there were all kinds 238 * of endian hacks, this only works for the simple cases 239 */ 240 if (rev == OLD_FLAT_VERSION && flat_old_ram_flag(flags)) 241 flags = FLAT_FLAG_RAM; 242 243 if (flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) { 244 fprintf(stderr, "ZFLAT executables are not supported\n"); 245 return -ENOEXEC; 246 } 247 248 /* 249 * calculate the extra space we need to map in 250 */ 251 extra = relocs * sizeof(abi_ulong); 252 if (extra < bss_len + stack_len) 253 extra = bss_len + stack_len; 254 255 /* Add space for library base pointers. Make sure this does not 256 misalign the doesn't misalign the data segment. */ 257 indx_len = MAX_SHARED_LIBS * sizeof(abi_ulong); 258 indx_len = (indx_len + 15) & ~(abi_ulong)15; 259 260 /* 261 * Allocate the address space. 262 */ 263 probe_guest_base(bprm->filename, 0, 264 text_len + data_len + extra + indx_len - 1); 265 266 /* 267 * there are a couple of cases here, the separate code/data 268 * case, and then the fully copied to RAM case which lumps 269 * it all together. 270 */ 271 if ((flags & (FLAT_FLAG_RAM|FLAT_FLAG_GZIP)) == 0) { 272 /* 273 * this should give us a ROM ptr, but if it doesn't we don't 274 * really care 275 */ 276 DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n"); 277 278 textpos = target_mmap(0, text_len, PROT_READ|PROT_EXEC, 279 MAP_PRIVATE, bprm->src.fd, 0); 280 if (textpos == -1) { 281 fprintf(stderr, "Unable to mmap process text\n"); 282 return -1; 283 } 284 285 realdatastart = target_mmap(0, data_len + extra + indx_len, 286 PROT_READ|PROT_WRITE|PROT_EXEC, 287 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 288 289 if (realdatastart == -1) { 290 fprintf(stderr, "Unable to allocate RAM for process data\n"); 291 return realdatastart; 292 } 293 datapos = realdatastart + indx_len; 294 295 DBG_FLT("BINFMT_FLAT: Allocated data+bss+stack (%d bytes): %x\n", 296 (int)(data_len + bss_len + stack_len), (int)datapos); 297 298 fpos = ntohl(hdr->data_start); 299 result = target_pread(bprm->src.fd, datapos, 300 data_len + (relocs * sizeof(abi_ulong)), 301 fpos); 302 if (result < 0) { 303 fprintf(stderr, "Unable to read data+bss\n"); 304 return result; 305 } 306 307 reloc = datapos + (ntohl(hdr->reloc_start) - text_len); 308 309 } else { 310 311 textpos = target_mmap(0, text_len + data_len + extra + indx_len, 312 PROT_READ | PROT_EXEC | PROT_WRITE, 313 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 314 if (textpos == -1 ) { 315 fprintf(stderr, "Unable to allocate RAM for process text/data\n"); 316 return -1; 317 } 318 319 realdatastart = textpos + ntohl(hdr->data_start); 320 datapos = realdatastart + indx_len; 321 reloc = (textpos + ntohl(hdr->reloc_start) + indx_len); 322 323 result = target_pread(bprm->src.fd, textpos, 324 text_len, 0); 325 if (result >= 0) { 326 result = target_pread(bprm->src.fd, datapos, 327 data_len + (relocs * sizeof(abi_ulong)), 328 ntohl(hdr->data_start)); 329 } 330 if (result < 0) { 331 fprintf(stderr, "Unable to read code+data+bss\n"); 332 return result; 333 } 334 } 335 336 DBG_FLT("Mapping is 0x%x, Entry point is 0x%x, data_start is 0x%x\n", 337 (int)textpos, 0x00ffffff&ntohl(hdr->entry), 338 ntohl(hdr->data_start)); 339 340 /* The main program needs a little extra setup in the task structure */ 341 start_code = textpos + sizeof (struct flat_hdr); 342 343 DBG_FLT("%s %s: TEXT=%x-%x DATA=%x-%x BSS=%x-%x\n", 344 id ? "Lib" : "Load", bprm->filename, 345 (int) start_code, (int) (textpos + text_len), 346 (int) datapos, 347 (int) (datapos + data_len), 348 (int) (datapos + data_len), 349 (int) (((datapos + data_len + bss_len) + 3) & ~3)); 350 351 text_len -= sizeof(struct flat_hdr); /* the real code len */ 352 353 /* Store the current module values into the global library structure */ 354 libinfo[id].start_code = start_code; 355 libinfo[id].start_data = datapos; 356 libinfo[id].end_data = datapos + data_len; 357 libinfo[id].start_brk = datapos + data_len + bss_len; 358 libinfo[id].text_len = text_len; 359 libinfo[id].loaded = 1; 360 libinfo[id].entry = (0x00ffffff & ntohl(hdr->entry)) + textpos; 361 libinfo[id].build_date = ntohl(hdr->build_date); 362 363 /* 364 * We just load the allocations into some temporary memory to 365 * help simplify all this mumbo jumbo 366 * 367 * We've got two different sections of relocation entries. 368 * The first is the GOT which resides at the beginning of the data segment 369 * and is terminated with a -1. This one can be relocated in place. 370 * The second is the extra relocation entries tacked after the image's 371 * data segment. These require a little more processing as the entry is 372 * really an offset into the image which contains an offset into the 373 * image. 374 */ 375 if (flags & FLAT_FLAG_GOTPIC) { 376 rp = datapos; 377 while (1) { 378 abi_ulong addr; 379 if (get_user_ual(addr, rp)) 380 return -EFAULT; 381 if (addr == -1) 382 break; 383 if (addr) { 384 addr = calc_reloc(addr, libinfo, id, 0); 385 if (addr == RELOC_FAILED) 386 return -ENOEXEC; 387 if (put_user_ual(addr, rp)) 388 return -EFAULT; 389 } 390 rp += sizeof(abi_ulong); 391 } 392 } 393 394 /* 395 * Now run through the relocation entries. 396 * We've got to be careful here as C++ produces relocatable zero 397 * entries in the constructor and destructor tables which are then 398 * tested for being not zero (which will always occur unless we're 399 * based from address zero). This causes an endless loop as __start 400 * is at zero. The solution used is to not relocate zero addresses. 401 * This has the negative side effect of not allowing a global data 402 * reference to be statically initialised to _stext (I've moved 403 * __start to address 4 so that is okay). 404 */ 405 if (rev > OLD_FLAT_VERSION) { 406 abi_ulong persistent = 0; 407 for (i = 0; i < relocs; i++) { 408 abi_ulong addr, relval; 409 410 /* Get the address of the pointer to be 411 relocated (of course, the address has to be 412 relocated first). */ 413 if (get_user_ual(relval, reloc + i * sizeof(abi_ulong))) 414 return -EFAULT; 415 relval = ntohl(relval); 416 if (flat_set_persistent(relval, &persistent)) 417 continue; 418 addr = flat_get_relocate_addr(relval); 419 rp = calc_reloc(addr, libinfo, id, 1); 420 if (rp == RELOC_FAILED) 421 return -ENOEXEC; 422 423 /* Get the pointer's value. */ 424 if (get_user_ual(addr, rp)) 425 return -EFAULT; 426 addr = flat_get_addr_from_rp(addr, relval, flags, &persistent); 427 if (addr != 0) { 428 /* 429 * Do the relocation. PIC relocs in the data section are 430 * already in target order 431 */ 432 if ((flags & FLAT_FLAG_GOTPIC) == 0) 433 addr = ntohl(addr); 434 addr = calc_reloc(addr, libinfo, id, 0); 435 if (addr == RELOC_FAILED) 436 return -ENOEXEC; 437 438 /* Write back the relocated pointer. */ 439 if (flat_put_addr_at_rp(rp, addr, relval)) 440 return -EFAULT; 441 } 442 } 443 } else { 444 for (i = 0; i < relocs; i++) { 445 abi_ulong relval; 446 if (get_user_ual(relval, reloc + i * sizeof(abi_ulong))) 447 return -EFAULT; 448 old_reloc(&libinfo[0], relval); 449 } 450 } 451 452 /* zero the BSS. */ 453 memset(g2h_untagged(datapos + data_len), 0, bss_len); 454 455 return 0; 456 } 457 458 459 /****************************************************************************/ 460 int load_flt_binary(struct linux_binprm *bprm, struct image_info *info) 461 { 462 struct lib_info libinfo[MAX_SHARED_LIBS]; 463 abi_ulong p; 464 abi_ulong stack_len; 465 abi_ulong start_addr; 466 abi_ulong sp; 467 int res; 468 int i, j; 469 470 memset(libinfo, 0, sizeof(libinfo)); 471 /* 472 * We have to add the size of our arguments to our stack size 473 * otherwise it's too easy for users to create stack overflows 474 * by passing in a huge argument list. And yes, we have to be 475 * pedantic and include space for the argv/envp array as it may have 476 * a lot of entries. 477 */ 478 stack_len = 0; 479 for (i = 0; i < bprm->argc; ++i) { 480 /* the argv strings */ 481 stack_len += strlen(bprm->argv[i]); 482 } 483 for (i = 0; i < bprm->envc; ++i) { 484 /* the envp strings */ 485 stack_len += strlen(bprm->envp[i]); 486 } 487 stack_len += (bprm->argc + 1) * 4; /* the argv array */ 488 stack_len += (bprm->envc + 1) * 4; /* the envp array */ 489 490 491 mmap_lock(); 492 res = load_flat_file(bprm, libinfo, 0, &stack_len); 493 mmap_unlock(); 494 495 if (is_error(res)) { 496 return res; 497 } 498 499 /* Update data segment pointers for all libraries */ 500 for (i=0; i<MAX_SHARED_LIBS; i++) { 501 if (libinfo[i].loaded) { 502 abi_ulong seg; 503 seg = libinfo[i].start_data; 504 for (j=0; j<MAX_SHARED_LIBS; j++) { 505 seg -= 4; 506 /* FIXME - handle put_user() failures */ 507 if (put_user_ual(libinfo[j].loaded 508 ? libinfo[j].start_data 509 : UNLOADED_LIB, 510 seg)) 511 return -EFAULT; 512 } 513 } 514 } 515 516 p = ((libinfo[0].start_brk + stack_len + 3) & ~3) - 4; 517 DBG_FLT("p=%x\n", (int)p); 518 519 /* Copy argv/envp. */ 520 p = copy_strings(p, bprm->envc, bprm->envp); 521 p = copy_strings(p, bprm->argc, bprm->argv); 522 /* Align stack. */ 523 sp = p & ~(abi_ulong)(sizeof(abi_ulong) - 1); 524 /* Enforce final stack alignment of 16 bytes. This is sufficient 525 for all current targets, and excess alignment is harmless. */ 526 stack_len = bprm->envc + bprm->argc + 2; 527 stack_len += flat_argvp_envp_on_stack() ? 2 : 0; /* argv, argp */ 528 stack_len += 1; /* argc */ 529 stack_len *= sizeof(abi_ulong); 530 sp -= (sp - stack_len) & 15; 531 sp = loader_build_argptr(bprm->envc, bprm->argc, sp, p, 532 flat_argvp_envp_on_stack()); 533 534 /* Fake some return addresses to ensure the call chain will 535 * initialise library in order for us. We are required to call 536 * lib 1 first, then 2, ... and finally the main program (id 0). 537 */ 538 start_addr = libinfo[0].entry; 539 540 /* Stash our initial stack pointer into the mm structure */ 541 info->start_code = libinfo[0].start_code; 542 info->end_code = libinfo[0].start_code + libinfo[0].text_len; 543 info->start_data = libinfo[0].start_data; 544 info->end_data = libinfo[0].end_data; 545 info->brk = libinfo[0].start_brk; 546 info->start_stack = sp; 547 info->stack_limit = libinfo[0].start_brk; 548 info->entry = start_addr; 549 info->code_offset = info->start_code; 550 info->data_offset = info->start_data - libinfo[0].text_len; 551 552 DBG_FLT("start_thread(entry=0x%x, start_stack=0x%x)\n", 553 (int)info->entry, (int)info->start_stack); 554 555 return 0; 556 } 557