--- map_object.c.orig 2009-03-08 12:28:36.000000000 +1100 +++ map_object.c 2009-03-08 15:59:28.000000000 +1100 @@ -85,6 +85,7 @@ caddr_t data_addr; caddr_t gap_addr; size_t gap_size; + u_long file_offset = 0; #ifdef RTLD_LOADER Elf_Addr clear_vaddr; caddr_t clear_addr; @@ -111,6 +112,54 @@ _rtld_error("%s: read error: %s", path, xstrerror(errno)); goto bad; } + +#ifndef NO_SUPPORT_FAT + { + struct fat_header { + uint32_t magic; + uint32_t nfat_arch; + } *fat = (void *)ehdr;; + struct arch { + uint32_t cputype; + uint32_t cpusubtype; + uint32_t offset; + uint32_t size; + uint32_t align; + } *arch = NULL; + int i; + uint32_t *sc = NULL; + + if (be32toh(fat->magic) == 0xcafebabe) { + for (i = 0; i < be32toh(fat->nfat_arch); i++) { + static uint32_t supported_cpus[] = { 7, 0 }; + arch = (struct arch *)((char *)fat + sizeof(*fat) + sizeof(*arch) * i); + for (sc = supported_cpus; *sc; sc++) + if (*sc == be32toh(arch->cputype)) + break; + if (*sc != 0) + break; + } + if (arch == NULL || sc == NULL || *sc == 0) { + _rtld_error("unrecognised fat binary"); + goto bad; + } + + file_offset = be32toh(arch->offset); + + munmap(ehdr, _rtld_pagesz); + + ehdr = mmap(NULL, _rtld_pagesz, PROT_READ, + MAP_FILE | MAP_SHARED, fd, (off_t)file_offset); + if (ehdr == MAP_FAILED) { + _rtld_error("%s: read error: %s", + path, xstrerror(errno)); + goto bad; + } + } + } +#endif /* Make sure the file is valid */ if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0 || ehdr->e_ident[EI_CLASS] != ELFCLASS) { @@ -241,7 +290,7 @@ #endif mapsize = base_vlimit - base_vaddr; mapbase = mmap(base_addr, mapsize, text_flags, - mapflags | MAP_FILE | MAP_PRIVATE, fd, base_offset); + mapflags | MAP_FILE | MAP_PRIVATE, fd, file_offset + base_offset); if (mapbase == MAP_FAILED) { _rtld_error("mmap of entire address space failed: %s", xstrerror(errno)); @@ -251,7 +300,7 @@ /* Overlay the data segment onto the proper region. */ data_addr = mapbase + (data_vaddr - base_vaddr); if (mmap(data_addr, data_vlimit - data_vaddr, data_flags, - MAP_FILE | MAP_PRIVATE | MAP_FIXED, fd, data_offset) == + MAP_FILE | MAP_PRIVATE | MAP_FIXED, fd, file_offset + data_offset) == MAP_FAILED) { _rtld_error("mmap of data failed: %s", xstrerror(errno)); goto bad;