Очень короткий ответ
Прочитайте гораздо более длинный ответ.
Короткий ответ
Если вы намереваетесь предоставить пользовательский libc, который использует некоторые функции вашего эмулятора, чтобы хост-ОС выполняла ваши системные вызовы, вы должны реализовать их все.
Намного более длинный ответ
Отойдите на минутку и посмотрите, как все обычно наслоено в реальной (не эмулированной) системе:
- Периферийные устройства имеют некоторый интерфейс ввода / вывода (например, пронумерованные порты или отображение памяти), который ЦП может щекотать, чтобы заставить их делать то, что они делают.
- CPU запускает программное обеспечение, которое понимает, как манипулировать оборудованием. Это может быть специализированная программа или операционная система, которая запускает другие программы. Поскольку на рисунке изображен libc, давайте предположим, что есть ОС, и это что-то Unix-y.
- Программы в пользовательском пространстве, запускаемые ОС, используют определенный интерфейс между собой и ОС, чтобы запрашивать выполнение определенных «системных» функций.
То, что вы пытаетесь выполнить, происходит между уровнями 3 и 2, где функция в libc или пользовательском коде делает то, что ОС определяет как запуск системного вызова. Это открывает многочисленные банки червей:
То, что ОС определяет как запуск системного вызова, отличается от ОС к ОС и (редко) между версиями одной и той же ОС. Эта проблема смягчается в «реальных» системах, предоставляя динамически подключаемый libc, который заботится о сокрытии этих деталей. Кроме того, если у вас есть двоичный файл MIPS32, который вы хотите запустить, использует ли он соглашение о системных вызовах, поддерживаемое вашим эмулятором?
Вам нужно будет предоставить пользовательский libc, который делает то, что ваш эмулятор может распознать как выполняющий определенный системный вызов, и выполнять его. Любая программа, которую вы хотите запустить, должна быть кросс-скомпилирована в MIPS32 и статически связана с ней, как и любые другие библиотеки, необходимые программе (на ум приходит libm). С другой стороны, ваш пакет эмулятора должен будет обеспечить имитацию динамического компоновщика плюс динамически связываемые копии всех необходимых библиотек, потому что открытие их на хосте не будет работать. Если у вас достаточно исходного кода для перекомпиляции программы с нуля, перенос может быть лучше, чем эмуляция.
Любой код, который делает предположения о путях к файлам в конкретной системе или другие предположения о том, что они найдут на определенных устройствах (которые сами являются файлами), не будет работать правильно.
Если вы предоставляете уровень 2, вы регистрируетесь, чтобы обеспечить полное и правильное моделирование поведения одной конкретной версии всей операционной системы. С некоторыми вызовами, такими как read()
и write()
, будет легко иметь дело; другие, такие как fork()
, uselib()
и ioctl()
, будут намного сложнее Также не обязательно однозначное сопоставление вызовов и поведения, которое ваша программа использует с теми, которые предоставляет ваша хост-ОС. Все это предполагает, что хост Unix и целевая программа тоже. Если цель скомпилирована для какой-либо другой среды, все ставки выключены.
Этот последний момент заключается в том, что большинство эмуляторов предоставляют только процессор и аппаратное поведение некоторой целевой системы (т. Е. Все на уровне 1). Имея их, вы можете запускать загрузочный диск оригинальной системы, ОС и пользовательские программы без изменений. Существует ряд существующих эмуляторов MIPS32 , которые делают именно это и могут запускать неизмененные версии операционных систем, работающих на оборудовании, которое они эмулируют.
HTH и удачи в вашем проекте.