Uma vez li um artigo sobre a escolha de sistemas de arquivos "para que funcione em qualquer lugar, em qualquer lugar". Mais uma vez, vi reclamações de que o Ext4 é um sistema de arquivos maravilhoso, mas no Windows há apenas as curvas drivers proprietários imprecisos. Mas nós rebobinamos a fita há alguns anos: em Habré (e naqueles dias - Giktayms) as notícias sobre o LibOS chegaram - uma tentativa de transformar o kernel do Linux em uma biblioteca comum no modo de usuário. A ênfase estava na remoção da pilha de rede no espaço do usuário. Uma vez, decidi examinar se o projeto estava vivo e, no blog deles, vi um link para um tipo de concorrente - o projeto Linux Kernel Library (LKL) . De fato, esta é a porta do kernel, por assim dizer, para a arquitetura de hardware "POSIX / Win32 user-mode library".
O que é interessante LKL? Primeiro, pelo fato de que ela vive e vive, embora não na base de código principal do kernel. Em segundo lugar, é um suporte mais ou menos honesto para a "arquitetura", que automaticamente disponibiliza a maior parte do kernel. Além disso, exemplos de utilitários estão no kit: cptofs
/ cpfromfs
, fs2tar
, lklfuse
. Neste artigo, testaremos o LKL no host Linux, examinaremos o arquivo com a imagem Ext4 (Btrfs, XFS ...) sem máquinas raiz e virtuais e discutiremos brevemente como ele pode ser tentado no Windows.
AVISO LEGAL 1: Deseja experimentar - faça backups. Se você quiser fazer isso com uma seção com dados importantes - por seu próprio risco e risco. No entanto, aqui pelo menos os drivers serão realmente nativos.
AVISO LEGAL 2: Respeite as licenças. A ligação LKL provavelmente cria o seu programa GPL.
Conhecimento primário
O repositório LKL ( lkl / linux no GitHub) é uma bifurcação do kernel normal do Linux, que adiciona suporte a outra arquitetura, veremos isso principalmente nos arch/lkl
e tools/lkl
. Vamos fazer um clone do repositório e tentar montar de acordo com as instruções. Para experimentos, usarei um clone superficial, que não contém todo o histórico do repositório, mas apenas o número especificado de confirmações recentes:
$ git clone https://github.com/lkl/linux.git lkl-linux --depth 10 $ cd lkl-linux $ patch -p 1 <<EOF diff --git a/tools/lkl/lib/hijack/xlate.cb/tools/lkl/lib/hijack/xlate.c index 03ccc6294..75368dcc2 100644 --- a/tools/lkl/lib/hijack/xlate.c +++ b/tools/lkl/lib/hijack/xlate.c @@ -3,6 +3,7 @@ #include <fcntl.h> #include <sys/ioctl.h> #include <sys/socket.h> +#include <linux/sockios.h> #undef st_atime #undef st_mtime #undef st_ctime EOF $ make -C tools/lkl -j4
Eu tive que corrigir um pouco a fonte, mas no final consegui a tools/lkl/lib/liblkl.so
(e também as tools/lkl/liblkl.a
estáticas tools/lkl/liblkl.a
):
nm -D tools / lkl / lib / liblkl.so U __assert_fail U bind U calloc U clock_gettime U close w __cxa_finalize 0000000000063b30 T dbg_entrance 0000000000063f30 T dbg_handler U __errno_location U fcntl U fdatasync 0000000000639580 D fd_net_ops U fgets U __fprintf_chk U free U fwrite U getc U getenv w __gmon_start__ U if_nametoindex U inet_pton U ioctl U __isoc99_scanf w _ITM_deregisterTMCloneTable w _ITM_registerTMCloneTable 0000000000061750 T jmp_buf_longjmp 0000000000061720 T jmp_buf_set 0000000000065470 T jsmn_init 0000000000065060 T jsmn_parse 0000000000065490 T jsmn_strerror 00000000000614c0 T lkl_add_gateway 0000000000061290 T lkl_add_neighbor 00000000000621a0 T lkl_bug 000000000005f070 T lkl_closedir 0000000000639520 D lkl_dev_blk_ops 000000000005fa10 T lkl_dirfd 0000000000062640 T lkl_disk_add 0000000000062780 T lkl_disk_remove 000000000005ec50 T lkl_encode_dev_from_sysfs 000000000005f9f0 T lkl_errdir 000000000005ef80 T lkl_fdopendir 0000000000067f10 T lkl_get_free_irq 000000000005f2c0 T lkl_get_virtio_blkdev 00000000006395c0 D lkl_host_ops 00000000000614b0 T lkl_if_add_gateway 00000000000613e0 T lkl_if_add_ip 00000000000614a0 T lkl_if_add_linklocal 0000000000061520 T lkl_if_add_rule_from_saddr 0000000000061480 T lkl_if_del_ip 0000000000060d70 T lkl_if_down 0000000000060b10 T lkl_ifname_to_ifindex 0000000000061400 T lkl_if_set_ipv4 0000000000061530 T lkl_if_set_ipv4_gateway 0000000000061430 T lkl_if_set_ipv6 00000000000615b0 T lkl_if_set_ipv6_gateway 0000000000060ef0 T lkl_if_set_mtu 0000000000060bf0 T lkl_if_up 0000000000061160 T lkl_if_wait_ipv6_dad 000000000005fba0 T lkl_iomem_access 000000000005fb50 T lkl_ioremap 0000000000067730 T lkl_is_running 0000000000066150 T lkl_load_config_env 0000000000065950 T lkl_load_config_json 0000000000066880 T lkl_load_config_post 0000000000066510 T lkl_load_config_pre 000000000005f470 T lkl_mount_dev 000000000005eae0 T lkl_mount_fs 00000000000642a0 T lkl_netdev_add 00000000000645c0 T lkl_netdev_free 0000000000061030 T lkl_netdev_get_ifindex 0000000000064e70 T lkl_netdev_macvtap_create 0000000000064ed0 T lkl_netdev_pipe_create 0000000000064ce0 T lkl_netdev_raw_create 00000000000644c0 T lkl_netdev_remove 0000000000064c60 T lkl_netdev_tap_create 0000000000064a10 T lkl_netdev_tap_init 000000000005eea0 T lkl_opendir 0000000000062170 T lkl_perror 00000000000620b0 T lkl_printf 0000000000067f90 T lkl_put_irq 0000000000061620 T lkl_qdisc_add 0000000000061630 T lkl_qdisc_parse_add 000000000005f0f0 T lkl_readdir 0000000000063f80 T lkl_register_dbg_handler 0000000000064930 T lkl_register_netdev_fd 000000000005efe0 T lkl_rewinddir 000000000005fa20 T lkl_set_fd_limit 00000000000614e0 T lkl_set_ipv4_gateway 0000000000061500 T lkl_set_ipv6_gateway 0000000000065f60 T lkl_show_config 00000000004f51ad T lkl_start_kernel 0000000000062080 T lkl_strerror 00000000000685f0 T lkl_syscall 0000000000062270 T lkl_sysctl 0000000000062410 T lkl_sysctl_parse_write 0000000000067770 T lkl_sys_halt 00000000000680e0 T lkl_trigger_irq 000000000005f870 T lkl_umount_dev 000000000005edc0 T lkl_umount_timeout 0000000000066ed0 T lkl_unload_config 00000000008186a0 B lkl_virtio_devs U __longjmp_chk U lseek64 U malloc U memchr U memcpy U memset U open U perror U pipe U poll 0000000000064070 T poll_thread U pread64 U __printf_chk U pthread_create U pthread_detach U pthread_exit U pthread_getspecific U pthread_join U pthread_key_create U pthread_key_delete U pthread_mutexattr_init U pthread_mutexattr_settype U pthread_mutex_destroy U pthread_mutex_init U pthread_mutex_lock U pthread_mutex_unlock U pthread_self U pthread_setspecific U puts U pwrite64 U read U readv 00000000008196a0 B registered_devs 000000000005fa90 T register_iomem U sem_destroy U sem_init U sem_post U sem_wait U _setjmp U setsockopt U sigaction U sigemptyset U __snprintf_chk U socket U __stack_chk_fail U stderr U stdin U stpcpy U strchr U strcpy U __strcpy_chk U strdup U strerror U strlen U strncat U __strncat_chk U strncmp U strncpy U strrchr U strtok U strtok_r U strtol U strtoul U syscall U timer_create U timer_delete U timer_settime 000000000005fb00 T unregister_iomem U usleep 0000000000063110 T virtio_dev_cleanup 0000000000062ee0 T virtio_dev_setup 0000000000063100 T virtio_get_num_bootdevs 0000000000062c10 T virtio_process_queue 0000000000062af0 T virtio_req_complete 0000000000062ec0 T virtio_set_queue_max_merge_len U __vsnprintf_chk U write U writev
E onde estão as chamadas do sistema, você pergunta. Sem pânico, eles ficam ocultos atrás do ponto de entrada comum lkl_syscall
. Este é um análogo da função syscall
para LKL. Em uma situação real, na maioria dos casos, você usará os wrappers digitados lkl_sys_<name>
. Também vemos todos os tipos de funções para configurar o "kernel", adicionando dispositivos virtuais a ele, bem como wrappers sobre chamadas de sistema "complexas", fornecidas pelo sistema libc em um sistema regular. Por exemplo, existe um sistema chamado getdents
, mas ... "Não é nessas interfaces que você está interessado." - a página de manual nos diz a partir do limite. Em casos comuns, é suposto usar a função de biblioteca padrão readdir (3)
, mas não a confunda com readdir (2)
, uma chamada de sistema antiga que nem foi implementada no x86_64. No caso de trabalhar com LKL, você precisará dos lkl_opendir
/ lkl_readdir
/ lkl_closedir
.
Vamos tentar escrever algo
Lembre-se de respeitar as licenças. O próprio kernel do Linux é distribuído sob a GPL2, se o programa que puxa para as interfaces LKL relativamente públicas será considerado um trabalho derivado - eu não sei.
Bem, vamos tentar vincular à biblioteca. Supõe-se que a variável $LKL
atribuída ao caminho do repositório com LKL compilado.
#include <stdio.h> #include "lkl_host.h" #include "lkl.h" int main() { // lkl_host_ops // "-" : `printk`, `panic`, ... // , -- lkl_start_kernel(&lkl_host_ops, "mem=128M"); return 0; }
Compilar:
$ gcc test.c -o test -I$LKL/tools/lkl/include -L$LKL/tools/lkl/lib -llkl
E funciona!
$ ./test ./test: error while loading shared libraries: liblkl.so: cannot open shared object file: No such file or directory $ LD_LIBRARY_PATH=$LKL/tools/lkl/lib ./test [ 0.000000] Linux version 5.3.0+ (trosinenko@trosinenko-pc) (gcc version 9.2.1 20191008 (Ubuntu 9.2.1-9ubuntu2)) #1 Tue Dec 3 14:37:02 MSK 2019 [ 0.000000] memblock address range: 0x7fba8c000000 - 0x7fba93fff000 [ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 32319 [ 0.000000] Kernel command line: mem=128M [ 0.000000] Dentry cache hash table entries: 16384 (order: 5, 131072 bytes, linear) [ 0.000000] Inode-cache hash table entries: 8192 (order: 4, 65536 bytes, linear) [ 0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off [ 0.000000] Memory available: 129044k/131068k RAM [ 0.000000] SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1 [ 0.000000] NR_IRQS: 4096 [ 0.000000] lkl: irqs initialized [ 0.000000] clocksource: lkl: mask: 0xffffffffffffffff max_cycles: 0x1cd42e4dffb, max_idle_ns: 881590591483 ns [ 0.000000] lkl: time and timers initialized (irq1) [ 0.000003] pid_max: default: 4096 minimum: 301 [ 0.000019] Mount-cache hash table entries: 512 (order: 0, 4096 bytes, linear) [ 0.000022] Mountpoint-cache hash table entries: 512 (order: 0, 4096 bytes, linear) [ 0.003622] random: get_random_bytes called from _etext+0xbcdb/0x14b05 with crng_init=0 [ 0.003692] printk: console [lkl_console0] enabled [ 0.003707] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns [ 0.003714] xor: automatically using best checksumming function 8regs [ 0.003783] NET: Registered protocol family 16 [ 0.171647] raid6: int64x8 gen() 4489 MB/s [ 0.343119] raid6: int64x8 xor() 3165 MB/s [ 0.514836] raid6: int64x4 gen() 4668 MB/s [ 0.689529] raid6: int64x4 xor() 3256 MB/s [ 0.861155] raid6: int64x2 gen() 6283 MB/s [ 1.032668] raid6: int64x2 xor() 3793 MB/s [ 1.206752] raid6: int64x1 gen() 5185 MB/s [ 1.378219] raid6: int64x1 xor() 2901 MB/s [ 1.378225] raid6: using algorithm int64x2 gen() 6283 MB/s [ 1.378227] raid6: .... xor() 3793 MB/s, rmw enabled [ 1.378229] raid6: using intx1 recovery algorithm [ 1.378333] clocksource: Switched to clocksource lkl [ 1.378427] NET: Registered protocol family 2 [ 1.378516] tcp_listen_portaddr_hash hash table entries: 256 (order: 0, 4096 bytes, linear) [ 1.378521] TCP established hash table entries: 1024 (order: 1, 8192 bytes, linear) [ 1.378527] TCP bind hash table entries: 1024 (order: 1, 8192 bytes, linear) [ 1.378532] TCP: Hash tables configured (established 1024 bind 1024) [ 1.378596] UDP hash table entries: 128 (order: 0, 4096 bytes, linear) [ 1.378618] UDP-Lite hash table entries: 128 (order: 0, 4096 bytes, linear) [ 1.379286] workingset: timestamp_bits=62 max_order=16 bucket_order=0 [ 1.380271] SGI XFS with ACLs, security attributes, no debug enabled [ 1.380864] io scheduler mq-deadline registered [ 1.380872] io scheduler kyber registered [ 1.383396] NET: Registered protocol family 10 [ 1.383763] Segment Routing with IPv6 [ 1.383779] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver [ 1.384091] Btrfs loaded, crc32c=crc32c-generic [ 1.384223] Warning: unable to open an initial console. [ 1.384237] This architecture does not have kernel memory protection. [ 1.384239] Run /init as init process
Você pode ver nos registros de data e hora que o kernel não "cuspiu" esse texto no console, mas foi carregado gradualmente. como real .
Nós complicamos o experimento
Vamos agora tentar de alguma forma realmente usar esta biblioteca - afinal, todo o núcleo do sistema operacional! Vamos tentar ler o arquivo da seção Ext4 corretamente no espaço do usuário. E o driver "nativo"! Tomamos as tools/lkl/cptofs.c
e implementamos apenas o mais necessário (para maior clareza):
#undef NDEBUG #include <stdio.h> #include <stdint.h> #include <string.h> #include <assert.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> #include "lkl_host.h" #include "lkl.h" // , // -- :) int main(int argc, const char *argv[]) { const char * const fsimage = argv[1]; const char * const fstype = argv[2]; const char * const file_to_dump = argv[3]; struct lkl_disk disk; int disk_id, ret; char mpoint[128]; // memset(&disk, 0, sizeof(disk)); disk.fd = open(fsimage, O_RDONLY); assert(disk.fd >= 0); // disk_id = lkl_disk_add(&disk); assert(disk_id >= 0); // lkl_start_kernel(&lkl_host_ops, "mem=128M"); // ret = lkl_mount_dev(disk_id, 0 /* part */, fstype, LKL_MS_RDONLY, NULL, mpoint, sizeof(mpoint)); if (ret < 0) { fprintf(stderr, "lkl_mount_dev failed: %s\n", lkl_strerror(ret)); close(disk.fd); exit(1); } // , ... // ( -libc ) struct lkl_dir *dir = lkl_opendir(mpoint, &ret); struct lkl_linux_dirent64 *dent; while ((dent = lkl_readdir(dir)) != NULL) { fprintf(stderr, "Directory entry: %s\n", dent->d_name); } // : NULL -- ... lkl_closedir(dir); // - // char tmp[256]; uint8_t buffer[65536]; snprintf(tmp, sizeof(tmp), "%s/%s", mpoint, file_to_dump); int fd = lkl_sys_open(tmp, LKL_O_RDONLY, 0); fprintf(stderr, "fd = %d\n", fd); assert(fd >= 0); int count = lkl_sys_read(fd, buffer, sizeof(buffer)); /* */ write(STDERR_FILENO, buffer, count); lkl_sys_close(fd); return 0; }
Preste atenção às definições renomeadas com prefixos LKL_ (por exemplo, LKL_O_RDONLY
): em um host Linux, eles provavelmente coincidem com aqueles sem prefixos, mas em outros sistemas isso não é um fato.
$ mke2fs ext4.img -t ext4 32M $ sudo mount ext4.img /mnt $ echo -e "Hello world\!\nTEST" | sudo tee /mnt/test.txt $ sudo umount /mnt $ LD_LIBRARY_PATH=$LKL/tools/lkl/lib ./read-file ext4.img ext4 test.txt [ 0.000000] Linux version 5.3.0+ (trosinenko@trosinenko-pc) (gcc version 9.2.1 20191008 (Ubuntu 9.2.1-9ubuntu2)) #1 Tue Dec 3 14:37:02 MSK 2019 // ... // [ 1.378960] Warning: unable to open an initial console. [ 1.378975] This architecture does not have kernel memory protection. [ 1.378977] Run /init as init process [ 1.379852] EXT4-fs (vda): mounted filesystem with ordered data mode. Opts: Directory entry: test.txt Directory entry: .. Directory entry: lost+found Directory entry: . fd = 0 Hello world\! TEST
Uau, funciona! Existe algo mais exótico?
$ mksquashfs test.c read-file.c squashfs.img $ LD_LIBRARY_PATH=$LKL/tools/lkl/lib ./read-file squashfs.img squashfs test.c [ 0.000000] Linux version 5.3.0+ (trosinenko@trosinenko-pc) (gcc version 9.2.1 20191008 (Ubuntu 9.2.1-9ubuntu2)) #1 Tue Dec 3 14:37:02 MSK 2019 // ... // [ 1.378472] This architecture does not have kernel memory protection. [ 1.378474] Run /init as init process lkl_mount_dev failed: No such device
Ai! Embora, espere, provavelmente não incluímos o suporte ao SquashFS em nossa biblioteca principal!
Configurar opções de compilação LKL
Para mim, desenvolvi uma sequência de comandos que funciona para o LKL - talvez possa ser reduzida ao make defconfig
tradicional make defconfig
, make menuconfig
, make
.
$ make defconfig ARCH=lkl $ make menuconfig ARCH=lkl //// SquashFS $ cp .config arch/lkl/configs/defconfig $ make mrproper $ make -C tools/lkl -j4 #
E pronto!
$ gcc read-file.c -o read-file -I$LKL/tools/lkl/include -L$LKL/tools/lkl/lib -llkl $ LD_LIBRARY_PATH=$LKL/tools/lkl/lib ./read-file squashfs.img squashfs test.c [ 0.000000] Linux version 5.3.0+ (trosinenko@trosinenko-pc) (gcc version 9.2.1 20191008 (Ubuntu 9.2.1-9ubuntu2)) #1 Wed Dec 4 12:07:50 MSK 2019 // ... // [ 1.378346] This architecture does not have kernel memory protection. [ 1.378348] Run /init as init process Directory entry: . Directory entry: .. Directory entry: read-file.c Directory entry: test.c fd = 0 #include <stdio.h> #include "lkl_host.h" #include "lkl.h" int main() { lkl_start_kernel(&lkl_host_ops, "mem=128M"); return 0; }
Nesse caso, no entanto, dificilmente era necessário recompilar o read-file.c
- a biblioteca é dinâmica.
Com licença, onde estão os programas prontos prometidos?
De fato, o tools/lkl
contém cptofs.c
, fs2tar.c
e muito mais, mas não vai! Depois de vasculhar o Makefiles, descobri que existe um certo Makefile.autoconf
que está procurando os arquivos de cabeçalho necessários e o Makefile.conf
, onde tudo isso está escrito.
Então, alguém quer libarchive
, alguém quer libarchive
- bem, vamos colocar libarchive-dev
, libfuse-dev
(no caso do Ubuntu) e reconstruir. Mesmo assim, não funciona ... E se você remover o Makefile.conf
... Opa, ele se juntou!
Então, o que temos agora? Agora, no tools/lkl
, temos cptofs
, fs2tar
e lklfuse
.
Primeiro, copie cptofs
como cpfromfs
:
$ $LKL/tools/lkl/cptofs --help Usage: cptofs [OPTION...] -t fstype -i fsimage path... fs_path Copy files to a filesystem image -i, --filesystem-image=string path to the filesystem image - mandatory -p, --enable-printk show Linux printks -P, --partition=int partition number -s, --selinux=string selinux attributes for destination -t, --filesystem-type=string select filesystem type - mandatory -?, --help Give this help list --usage Give a short usage message Mandatory or optional arguments to long options are also mandatory or optional for any corresponding short options. $ cp $LKL/tools/lkl/cp{to,from}fs $ $LKL/tools/lkl/cpfromfs --help Usage: cpfromfs [OPTION...] -t fstype -i fsimage fs_path... path Copy files from a filesystem image -i, --filesystem-image=string path to the filesystem image - mandatory -p, --enable-printk show Linux printks -P, --partition=int partition number -s, --selinux=string selinux attributes for destination -t, --filesystem-type=string select filesystem type - mandatory -?, --help Give this help list --usage Give a short usage message Mandatory or optional arguments to long options are also mandatory or optional for any corresponding short options.
Como diz o ditado, "Como você chama um iate ...". Começamos ...
$ $LKL/tools/lkl/cpfromfs -t ext4 -i ext4.img test.txt . error processing entry /mnt/0000fe00/test.txt, aborting
Hmm ... temos que ver ... No entanto, para uso interativo, ainda é inconveniente, porque cada vez que você precisa esperar cerca de um segundo até que o kernel seja inicializado. Mas o fs2tar
funciona sem problemas:
$ $LKL/tools/lkl/fs2tar -t ext4 ext4.img ext4.tar $ tar -tf ext4.tar tar: `/' /test.txt /lost+found/
Mas o programa mais interessante aqui na minha opinião é o lklfuse
:
$ mkdir mountpoint $ $LKL/tools/lkl/lklfuse -o type=ext4 ext4.img mountpoint/ $ ls mountpoint/ lost+found test.txt $ mount sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime) proc on /proc type proc (rw,nosuid,nodev,noexec,relatime) ... , /dev/fuse on /run/user/1000/doc type fuse (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000) lklfuse on /path/to/mountpoint type fuse.lklfuse (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000) $ echo ABC > mountpoint/ABC.XYZ $ umount mountpoint $ sudo mount ext4.img /mnt $ ls /mnt $ cat /mnt/ABC.XYZ ABC
Na minha opinião, é impressionante: você pode montar o sistema de arquivos através do FUSE sem root (mas depende das configurações do sistema), trabalhar com ele, desmontá-lo e conectá-lo ao kernel host (já com root) e continuar como se nada tivesse acontecido.
Além disso, o lklfuse
permite que um usuário comum monte uma partição usando um driver de kernel comum. O núcleo do host não precisa ser construído com suporte para esse FS. Mas o que há aí? Não ficarei surpreso se tudo começar da mesma maneira no OS X.
Mas e o acesso ao Linux FS a partir de outros sistemas operacionais? No OS X, acho que será mais simples: afinal, é um UNIX completo, e o suporte ao FUSE parece estar lá. Portanto, há esperança de que ele comece em movimento. Caso contrário, eu procuraria verificar se as constantes com prefixos LKL_
são passadas em todos os lugares para as chamadas do sistema LKL, e não as contrapartes do host.
O Windows é um pouco mais complicado: primeiro, pode não haver algumas bibliotecas comuns conhecidas no mundo UNIX (por exemplo, para analisar argumentos de linha de comando). Em segundo lugar, você precisa entender como montar na árvore do sistema de arquivos host. O mais simples seria - também através do FUSE. Eles dizem que, uma vez que havia um certo Dokan, agora também há algo, mas você precisa pesquisar no Google. O principal é que o próprio LKL é construído no Windows, você só precisa considerar que ele precisa de um tipo de 64 bits para funcionar no modo de 64 bits, para que nem todo compilador funcione (pelo menos, como diz o leia-me atual do projeto).