2015-06-07 13 views
4

Я загружаю простой статически связанный двоичный файл ELF в MIPS (32-разрядный). После картирования загружаемых сегментов, это то, как настроить стек перед прыжком в моем целевые _start функции эльфа ЭЛТ:Загрузка ELF на MIPS, проблема malloc

__asm__("                \ 
     addi  $2,   %[envN],  0       ;\ 
    .env_loop:              \ 
     addi  $2,   $2,   -4       ;\ 
     lw   $3,   0($2)         ;\ 
     addi  $sp,  $sp,   -4       ;\ 
     sw   $3,   0($sp)         ;\ 
     bne  $2,   %[env0],  .env_loop     ;\ 
     addi  $2,   %[argN],  0       ;\ 
    .arg_loop:              \ 
     addi  $2,   $2,   -4       ;\ 
     lw   $3,   0($2)         ;\ 
     addi  $sp,  $sp,   -4       ;\ 
     sw   $3,   0($sp)         ;\ 
     bne  $2,   %[arg0],  .arg_loop     ;\ 
     addi  $2,   %[argc],  0       ;\ 
     addi  $sp,  $sp,   -4       ;\ 
     sw   $2,   0($sp)         ;\ 
     addi  $2,   %[func],  0       ;\ 
     jr   $2             ;" 
    : 
    : [envN] "r" (envp + envc + 1), 
     [env0] "r" (envp), 
     [argN] "r" (argv + argc + 1), 
     [arg0] "r" (argv), 
     [argc] "r" ((int32_t)argc), 
     [func] "r" (entry_point) 
    : "$2", "$3", "cc", "memory" 
); 

Так что я толкающий переменные окружения, аргументы командной строки, argc в стеке , и, наконец, выпрыгивая в точку входа целевой ELF. Это работает правильно, и я попал в основную функцию моей загруженной программы с помощью правильных аргументов командной строки и всего, кроме одного: malloc не работает! Любой вызов ему возвращает null и устанавливает errno в ENOMEM.

Эмулятор MIPS, который я использую (qemu-system-mips), имеет много свободного места, и если я просто запускаю программу без использования моего загрузчика, она отлично работает, поэтому она должна поступать с загрузчика. Но я понятия не имею, почему; Я использовал ту же самую технику загрузки с x86, x86_64 и arm, и все они отлично работают, но по какой-то причине malloc работает неправильно с версией MIPS загрузчика.

Что-то я пропустил здесь? Что-то, что действительно нужно сделать до перехода в загруженный исполняемый файл, что может иметь значение для MIPS, но не для других архитектур, которые я успешно пробовал? Я решил, что попрошу здесь посмотреть, не встретил ли кто-нибудь это раньше, потому что я действительно не могу представить, что здесь происходит.

Я запускаю это под Linux и использую musl как libc. После некоторой отладки я обнаружил, что разница в функции musl's expand_heap, но у меня нет источника информации о сборке, так что непонятно, что это за ошибка (musl использует один и тот же код malloc для других архитектур, и они отлично работают).

Бинарный файл связан статически (включая libc; он не имеет динамических зависимостей), а все остальное (printf, fopen и т. Д.) Отлично работает в загруженном двоичном файле с видимым единственным исключением malloc (и, конечно же, realloc/calloc, и я полагаю, что это бесплатно). Так что это действительно озадачивает.

+0

Вы статически связывали 'libc'? – user35443

+0

@ user35443 Да, двоичный файл статически связан и имеет также статически связанную библиотеку libc (у загрузчика также есть своя собственная копия libc, так как она требуется для работы mprotect/mmap, но две копии находятся в разных адресных пространствах) – Thomas

ответ

3

Это было некоторое время, так как я пытался сделать MIPS вещь, но я думаю, что ваш вспомогательный вектор должен выглядеть следующим образом:

// main()'s pseudo arguments. 
#define AT_PAGESZ 6 
argv: 
     .word name 
     .word 0      // End of argv. 
     .word 0      // End of envp. 
     // Auxv 
     .word AT_PAGESZ 
     .word 4096     // Page size. 
     .word 0 

Как я помню, запись размер страницы auxv была уникальной для MIPS для MUSL.

+0

Он отлично работает! Это именно тот ответ и опыт, на который я надеялся, когда задал этот вопрос, спасибо много. Вы спасли мой день. :) – Thomas

+0

@Thomas Я работаю над использованием clang и musl в безбожной среде. Сейчас я работаю над ARM, но я надеюсь скоро вернуться к Mips. –

+0

Это довольно круто; мы используем musl с gcc до сих пор, musl + clang, казалось бы, была бы идеальной комбинацией (gcc скорее раздувается imho), но мы еще не нашли времени, чтобы установить это, документации недостаточно (в то время как ' musl-cross' поставляется с установщиком и готовыми кросс-компиляторами gcc ..). – Thomas

1

Я не говорю о сборке MIPS, но похоже, что вы настраиваете «вспомогательный вектор», указанный на странице 3-30 MIPS ABI, расположенный здесь: http://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf - это может быть причиной проблемы?

+0

Я добавил «вспомогательный вектор» в стек, но, к сожалению, он, похоже, не имеет значения :( – Thomas